001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * TieGenerator.java
020: *
021: * This class is responsible for generating the tie classes for the RMI
022: * interfaces. These Tie classes will act as container boundary for validation
023: * purposes much like the home interface.
024: */
025:
026: // package path
027: package com.rift.coad.lib.deployment.rmi;
028:
029: // java imports
030: import java.io.File;
031: import java.io.FileWriter;
032: import java.lang.reflect.Method;
033: import java.lang.reflect.Type;
034: import java.net.URLClassLoader;
035: import java.net.URL;
036: import java.util.StringTokenizer;
037: import java.util.Vector;
038: import java.util.Iterator;
039: import java.util.regex.Matcher;
040: import java.util.regex.Pattern;
041:
042: // logging import
043: import org.apache.log4j.Logger;
044:
045: // coadunation imports
046: import com.rift.coad.lib.bean.BeanPattern;
047: import com.rift.coad.lib.common.ClassUtil;
048: import com.rift.coad.lib.common.FileUtil;
049: import com.rift.coad.lib.common.RandomGuid;
050: import com.rift.coad.lib.common.ResourceReader;
051: import com.rift.coad.lib.deployment.BeanInfo;
052:
053: /**
054: * This class is responsible for generating the tie classes for the RMI
055: * interfaces. These Tie classes will act as container boundary for validation
056: * purposes much like the home interface.
057: *
058: * @author Brett Chaldecott
059: */
060: public class TieGenerator {
061:
062: // the class constants
063: private final static String TIE_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/TieTemplate.txt";
064: private final static String METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/BasicMethodTemplate.txt";
065: private final static String VOID_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
066: + "VoidMethodTemplate.txt";
067: private final static String CACHE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/CacheMethodTemplate.txt";
068: private final static String KEY_CACHE_ADD_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
069: + "KeyCacheAddMethodTemplate.txt";
070: private final static String KEY_CACHE_FIND_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
071: + "KeyCacheFindMethodTemplate.txt";
072: private final static String KEY_CACHE_REMOVE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
073: + "KeyCacheRemoveMethodTemplate.txt";
074: private final static String VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
075: + "VoidKeyCacheRemoveMethodTemplate.txt";
076: private final static String TRANSACTION_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
077: + "TransactionBasicMethodTemplate.txt";
078: private final static String TRANSACTION_VOID_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
079: + "TransactionVoidMethodTemplate.txt";
080: private final static String TRANSACTION_CACHE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
081: + "TransactionCacheMethodTemplate.txt";
082: private final static String TRANSACTION_KEY_CACHE_ADD_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
083: + "TransactionKeyCacheAddMethodTemplate.txt";
084: private final static String TRANSACTION_KEY_CACHE_FIND_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
085: + "TransactionKeyCacheFindMethodTemplate.txt";
086: private final static String TRANSACTION_KEY_CACHE_REMOVE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
087: + "TransactionKeyCacheRemoveMethodTemplate.txt";
088: private final static String TRANSACTION_VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
089: + "TransactionVoidKeyCacheRemoveMethodTemplate.txt";
090: private final static String CATCH_EXCEPTION_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
091: + "CatchException.txt";
092: private final static String CATCH_RUNTIME_EXCEPTION_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
093: + "CatchRuntimeException.txt";
094: private final static String CATCH_REMOTE_EXCEPTION_TEMPLATE = "com/rift/coad/lib/deployment/rmi/resources/"
095: + "CatchRemoteException.txt";
096: private final static String METHOD_PARAMETER = "%s%s p%d";
097: private final static String PARAMETER = "%s p%d";
098: private final static String TIE_CLASS_NAME = "%s_CoadTie";
099:
100: // the class log variable
101: protected Logger log = Logger.getLogger(TieGenerator.class
102: .getName());
103:
104: // private member variables
105: private File dir = null;
106: private File targetDir = null;
107: private BeanInfo beanInfo = null;
108: private ClassLoader classLoader = null;
109:
110: // templates
111: private String tieTemplate = null;
112: private String basicMethodTemplate = null;
113: private String voidMethodTemplate = null;
114: private String cacheMethodTemplate = null;
115: private String keyCacheAddMethodTemplate = null;
116: private String keyCacheFindMethodTemplate = null;
117: private String keyCacheRemoveMethodTemplate = null;
118: private String voidKeyCacheRemoveMethodTemplate = null;
119: private String transactionBasicMethodTemplate = null;
120: private String transactionVoidMethodTemplate = null;
121: private String transactionCacheMethodTemplate = null;
122: private String transactionKeyCacheAddMethodTemplate = null;
123: private String transactionKeyCacheFindMethodTemplate = null;
124: private String transactionKeyCacheRemoveMethodTemplate = null;
125: private String transactionVoidKeyCacheRemoveMethodTemplate = null;
126: private String catchTemplate = null;
127: private String runtimeCatchTemplate = null;
128: private String remoteCatchTemplate = null;
129:
130: /**
131: * Creates a new instance of TieGenerator
132: *
133: * @param dir The directory containing all the jars.
134: * @param targetDir The target directory for the tie class.
135: * @param classes The class to generate the ties for.
136: * @exception RMIException
137: */
138: public TieGenerator(File dir, File targetDir, BeanInfo beanInfo)
139: throws RMIException {
140: this .dir = dir;
141: this .targetDir = targetDir;
142: this .beanInfo = beanInfo;
143: initClassLoader();
144:
145: try {
146: tieTemplate = new ResourceReader(TIE_TEMPLATE)
147: .getDocument();
148: basicMethodTemplate = new ResourceReader(METHOD_TEMPLATE)
149: .getDocument();
150: voidMethodTemplate = new ResourceReader(
151: VOID_METHOD_TEMPLATE).getDocument();
152: cacheMethodTemplate = new ResourceReader(
153: CACHE_METHOD_TEMPLATE).getDocument();
154: keyCacheAddMethodTemplate = new ResourceReader(
155: KEY_CACHE_ADD_METHOD_TEMPLATE).getDocument();
156: keyCacheFindMethodTemplate = new ResourceReader(
157: KEY_CACHE_FIND_METHOD_TEMPLATE).getDocument();
158: keyCacheRemoveMethodTemplate = new ResourceReader(
159: KEY_CACHE_REMOVE_METHOD_TEMPLATE).getDocument();
160: voidKeyCacheRemoveMethodTemplate = new ResourceReader(
161: VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE)
162: .getDocument();
163: transactionBasicMethodTemplate = new ResourceReader(
164: TRANSACTION_METHOD_TEMPLATE).getDocument();
165: transactionVoidMethodTemplate = new ResourceReader(
166: TRANSACTION_VOID_METHOD_TEMPLATE).getDocument();
167: transactionCacheMethodTemplate = new ResourceReader(
168: TRANSACTION_CACHE_METHOD_TEMPLATE).getDocument();
169: transactionKeyCacheAddMethodTemplate = new ResourceReader(
170: TRANSACTION_KEY_CACHE_ADD_METHOD_TEMPLATE)
171: .getDocument();
172: transactionKeyCacheFindMethodTemplate = new ResourceReader(
173: TRANSACTION_KEY_CACHE_FIND_METHOD_TEMPLATE)
174: .getDocument();
175: transactionKeyCacheRemoveMethodTemplate = new ResourceReader(
176: TRANSACTION_KEY_CACHE_REMOVE_METHOD_TEMPLATE)
177: .getDocument();
178: transactionVoidKeyCacheRemoveMethodTemplate = new ResourceReader(
179: TRANSACTION_VOID_KEY_CACHE_REMOVE_METHOD_TEMPLATE)
180: .getDocument();
181: catchTemplate = new ResourceReader(CATCH_EXCEPTION_TEMPLATE)
182: .getDocument();
183: remoteCatchTemplate = new ResourceReader(
184: CATCH_REMOTE_EXCEPTION_TEMPLATE).getDocument();
185: runtimeCatchTemplate = new ResourceReader(
186: CATCH_RUNTIME_EXCEPTION_TEMPLATE).getDocument();
187: } catch (Exception ex) {
188: log.error("Failed retrieve the resource : "
189: + ex.getMessage(), ex);
190: throw new RMIException("Failed retrieve the resource : "
191: + ex.getMessage(), ex);
192: }
193: }
194:
195: /**
196: * This method generates the Tie classes.
197: *
198: * @exception RMIException
199: */
200: public void generate() throws RMIException {
201: Class ref = getClass(beanInfo.getClassName());
202: createTie(targetDir, ref);
203:
204: // misc classes
205: Vector classes = beanInfo.getClasses();
206: for (int index = 0; index < classes.size(); index++) {
207: ref = getClass((String) classes.get(index));
208: createTie(targetDir, ref);
209: }
210: }
211:
212: /**
213: * This method inits the class loader.
214: *
215: * @exception RMIException
216: */
217: private void initClassLoader() throws RMIException {
218: try {
219: File[] jars = FileUtil.filter(dir.listFiles(), "jar");
220: URL[] urls = new URL[jars.length + 1];
221: urls[0] = dir.toURL();
222: for (int index = 0; index < jars.length; index++) {
223: urls[index + 1] = jars[index].toURL();
224: }
225:
226: classLoader = new URLClassLoader(urls, this .getClass()
227: .getClassLoader());
228: } catch (Exception ex) {
229: log.error("Failed to init the class loader : "
230: + ex.getMessage(), ex);
231: throw new RMIException("Failed to init the class loader : "
232: + ex.getMessage(), ex);
233: }
234: }
235:
236: /**
237: * This method returns a reference to the class using the class name.
238: *
239: * @return The reference to the class to retrieve.
240: * @param className The name of the class to retrieve.
241: * @exception RMIException
242: */
243: private Class getClass(String className) throws RMIException {
244: try {
245: return classLoader.loadClass(className);
246: } catch (Exception ex) {
247: log.error("Failed to retrieve the class: "
248: + ex.getMessage(), ex);
249: throw new RMIException("Failed to retrieve the class : "
250: + ex.getMessage(), ex);
251: }
252: }
253:
254: /**
255: * This method creates the package directory.
256: *
257: * @return The package directory
258: * @param ref The reference to the class to retrieve.
259: * @exception RMIException
260: */
261: private File createPackageDir(File tmpDir, Class ref)
262: throws RMIException {
263: try {
264: String className = ref.getCanonicalName();
265: StringTokenizer tokenizer = new StringTokenizer(className,
266: ".");
267: File base = tmpDir;
268: int numElements = tokenizer.countTokens() - 1;
269: String seperator = "";
270: for (int count = 0; count < numElements; count++) {
271: File newDir = new File(base, tokenizer.nextToken());
272: newDir.mkdir();
273: base = newDir;
274: }
275: return base;
276: } catch (Exception ex) {
277: log.error("Failed to create the package: "
278: + ex.getMessage(), ex);
279: throw new RMIException(
280: "Failed to create the package dir : "
281: + ex.getMessage(), ex);
282: }
283: }
284:
285: /**
286: * This method creates the tie file.
287: *
288: * @param ref The reference to the class.
289: * @param packageDir The package directory.
290: * @exception RMIException
291: */
292: private void createTie(File tmpDir, Class ref) throws RMIException {
293: try {
294: if (!ClassUtil.testForParent(ref, java.rmi.Remote.class)) {
295: // ignore as it has not remote interface
296: return;
297: }
298: File packageDir = createPackageDir(tmpDir, ref);
299: Vector interfaces = getInterfaces(ref);
300: String methods = "";
301: Iterator iter = interfaces.iterator();
302: String interfaceList = getImplements(ref);
303: while (iter.hasNext()) {
304: Class interfaceRef = (Class) iter.next();
305: Method[] methodList = interfaceRef.getDeclaredMethods();
306: for (int index = 0; index < methodList.length; index++) {
307: methods += generateCodeForMethod(methodList[index],
308: ref);
309: }
310: }
311:
312: // parse the tie class template
313: String tieClassName = String.format(TIE_CLASS_NAME, ref
314: .getSimpleName());
315: String tieClass = new String(tieTemplate);
316: tieClass = tieClass.replaceAll("%package%", "package "
317: + ref.getPackage().getName() + ";");
318: tieClass = tieClass.replaceAll("%tieClassName%",
319: tieClassName);
320: tieClass = tieClass.replaceAll("%implements%",
321: interfaceList);
322: tieClass = tieClass.replaceAll("%target%", ref.getName());
323: tieClass = tieClass.replaceAll("%methods%", methods);
324:
325: // write out the tie class
326: File tieClassFile = new File(packageDir, tieClassName
327: + ".java");
328: FileWriter fileWriter = new FileWriter(tieClassFile);
329: fileWriter.write(tieClass);
330: fileWriter.close();
331: } catch (Exception ex) {
332: log.error("Failed to create the tie : " + ex.getMessage(),
333: ex);
334: throw new RMIException("Failed to create the tie : "
335: + ex.getMessage(), ex);
336: }
337: }
338:
339: /**
340: * This recursive method retrieve a lit of interfaces that inherit from
341: * Remote.
342: *
343: * @return The list of interfaces that inherit from remote.
344: * @param ref The reference to the class to retrieve the list for.
345: * @exception RMIException
346: */
347: private Vector getInterfaces(Class ref) throws RMIException {
348: if (ref == null) {
349: return new Vector();
350: } else if (ref.getName().equals(
351: java.lang.Object.class.getName())) {
352: return new Vector();
353: }
354: Vector results = new Vector();
355: Class[] interfaces = ref.getInterfaces();
356: for (int index = 0; index < interfaces.length; index++) {
357: if (ClassUtil.testForParent(interfaces[index],
358: "java.rmi.Remote")) {
359: results.add(interfaces[index]);
360: results.addAll(getInterfaces(interfaces[index]));
361: }
362: }
363: results.addAll(getInterfaces(ref.getSuperclass()));
364: return results;
365: }
366:
367: /**
368: * This method returns the list of RMI implemented interfaces.
369: *
370: * @return The list of implemented interfaces.
371: * @param ref The reference.
372: * @exception RMIException
373: */
374: public String getImplements(Class ref) throws RMIException {
375: String interfaceList = "";
376: Class[] interfaces = ref.getInterfaces();
377: for (int index = 0; index < interfaces.length; index++) {
378: if (ClassUtil.testForParent(interfaces[index],
379: "java.rmi.Remote")) {
380: interfaceList += "," + interfaces[index].getName();
381: }
382: }
383: return interfaceList;
384: }
385:
386: /**
387: * This method generates the code for a given method.
388: *
389: * @return The string containing the code for the tie method.
390: * @param method The method that the code is getting generated for.
391: * @exception RMIException
392: */
393: private String generateCodeForMethod(Method method, Class ref)
394: throws RMIException {
395: try {
396: String methodName = method.getName();
397: String returnType = classTypeToString(method
398: .getReturnType());
399: Class[] parametersTypes = method.getParameterTypes();
400: Method targetMethod = ref.getMethod(methodName, method
401: .getParameterTypes());
402: String fullParameters = "";
403: String parameters = "";
404: String seperator = "";
405: for (int index = 0; index < parametersTypes.length; index++) {
406: fullParameters += String.format(METHOD_PARAMETER,
407: seperator,
408: classTypeToString(parametersTypes[index]),
409: index + 1);
410: parameters += String.format(PARAMETER, seperator,
411: index + 1);
412: seperator = ",";
413: }
414:
415: // validate exceptions on interface
416: Class[] exceptionList = method.getExceptionTypes();
417: if (!findException(exceptionList,
418: java.rmi.RemoteException.class)) {
419: throw new RMIException("Interface method ["
420: + method.getName()
421: + "] must throw a java.rmi.RemoteException");
422: }
423:
424: // process the exceptions
425: String exceptions = "";
426: seperator = "";
427: String catchBlock = "";
428: Class[] targetExceptionList = targetMethod
429: .getExceptionTypes();
430: for (int index = 0; index < exceptionList.length; index++) {
431: exceptions += seperator
432: + exceptionList[index].getName();
433: seperator = ",";
434:
435: if (findException(targetExceptionList,
436: exceptionList[index])) {
437: if (exceptionList[index] == com.rift.coad.lib.security.SecurityException.class) {
438: // ignore the security exception as these get wrapped
439: // specially.
440: continue;
441: } else if (exceptionList[index] == java.rmi.RemoteException.class) {
442: catchBlock += remoteCatchTemplate.replaceAll(
443: "%exception%", exceptionList[index]
444: .getName());
445: } else {
446: catchBlock += catchTemplate.replaceAll(
447: "%exception%", exceptionList[index]
448: .getName());
449: }
450: }
451: }
452: catchBlock += runtimeCatchTemplate;
453: catchBlock = catchBlock.replace("%methodName%", methodName);
454:
455: // retrieve a copy of the template to parse
456: String template = new String(getTemplate(method));
457: template = template.replaceAll("%methodName%", methodName);
458: template = template.replaceAll("%returnType%", returnType);
459: template = template.replaceAll("%fullParameters%",
460: fullParameters);
461: template = template.replaceAll("%parameters%", parameters);
462: template = template.replaceAll("%catchs%", catchBlock);
463: template = template.replaceAll("%exceptions%", exceptions);
464: return template;
465: } catch (RMIException ex) {
466: throw ex;
467: } catch (Exception ex) {
468: throw new RMIException(
469: "Failed to generate the exception list : "
470: + ex.getMessage(), ex);
471: }
472: }
473:
474: /**
475: * This method converts the class type to a string.
476: *
477: * @return The string definition of the object.
478: * @param The type of object.
479: */
480: private String classTypeToString(Class type) {
481: // deal with a basic type
482: if (type.isArray()) {
483: return type.getComponentType().getName() + "[]";
484: }
485: return type.getName();
486: }
487:
488: /**
489: * This method returns the template for the given class.
490: *
491: * @return The string containing the template.
492: * @param method The method to retrieve the template for.
493: * @exception RMIException
494: */
495: private String getTemplate(Method method) throws RMIException {
496:
497: // retrieve the method and parameter list and check for a remove cache
498: // method.
499: String methodName = method.getName();
500: Pattern removePattern = Pattern
501: .compile(BeanPattern.REMOVE_PATTERN);
502: Class[] parametersTypes = method.getParameterTypes();
503: Class returnType = method.getReturnType();
504: if (beanInfo.getCacheResults()
505: && !beanInfo.getTransaction()
506: && (parametersTypes.length == 1)
507: && (ClassUtil.testForParent(parametersTypes[0],
508: java.io.Serializable.class))
509: && removePattern.matcher(methodName).find()
510: && returnType.getName().equals("void")) {
511: return voidKeyCacheRemoveMethodTemplate;
512: } else if (beanInfo.getCacheResults()
513: && beanInfo.getTransaction()
514: && (parametersTypes.length == 1)
515: && (ClassUtil.testForParent(parametersTypes[0],
516: java.io.Serializable.class))
517: && removePattern.matcher(methodName).find()
518: && returnType.getName().equals("void")) {
519: return transactionVoidKeyCacheRemoveMethodTemplate;
520: } else if (beanInfo.getCacheResults()
521: && !beanInfo.getTransaction()
522: && (parametersTypes.length == 1)
523: && (ClassUtil.testForParent(parametersTypes[0],
524: java.io.Serializable.class))
525: && removePattern.matcher(methodName).find()) {
526: return keyCacheRemoveMethodTemplate;
527: } else if (beanInfo.getCacheResults()
528: && beanInfo.getTransaction()
529: && (parametersTypes.length == 1)
530: && (ClassUtil.testForParent(parametersTypes[0],
531: java.io.Serializable.class))
532: && removePattern.matcher(methodName).find()) {
533: return transactionKeyCacheRemoveMethodTemplate;
534: } else if (beanInfo.getCacheResults()
535: && removePattern.matcher(methodName).find()) {
536: throw new RMIException(
537: "The bean cache result flag is set but "
538: + "there is no way identifying this entry in cache. Must "
539: + "supply the index key as a serializable object to a remove "
540: + "method.");
541: } else if (returnType.getName().equals("void")
542: && !beanInfo.getTransaction()) {
543: return voidMethodTemplate;
544: } else if (returnType.getName().equals("void")
545: && beanInfo.getTransaction()) {
546: return transactionVoidMethodTemplate;
547: }
548:
549: // check for a basic return type
550: if (!ClassUtil.testForParent(returnType, java.rmi.Remote.class)
551: && !beanInfo.getTransaction()) {
552: return basicMethodTemplate;
553: } else if (!ClassUtil.testForParent(returnType,
554: java.rmi.Remote.class)
555: && beanInfo.getTransaction()) {
556: return transactionBasicMethodTemplate;
557: }
558:
559: // check for a caching return type
560: Pattern findPattern = Pattern.compile(BeanPattern.FIND_PATTERN);
561: Pattern addPattern = Pattern.compile(BeanPattern.ADD_PATTERN);
562: if (beanInfo.getCacheResults() && !beanInfo.getTransaction()
563: && addPattern.matcher(methodName).find()) {
564: return keyCacheAddMethodTemplate;
565: } else if (beanInfo.getCacheResults()
566: && beanInfo.getTransaction()
567: && addPattern.matcher(methodName).find()) {
568: return transactionKeyCacheAddMethodTemplate;
569: } else if (beanInfo.getCacheResults()
570: && !beanInfo.getTransaction()
571: && findPattern.matcher(methodName).find()
572: && (parametersTypes.length == 1)
573: && (ClassUtil.testForParent(parametersTypes[0],
574: java.io.Serializable.class))) {
575: return keyCacheFindMethodTemplate;
576: } else if (beanInfo.getCacheResults()
577: && beanInfo.getTransaction()
578: && findPattern.matcher(methodName).find()
579: && (parametersTypes.length == 1)
580: && (ClassUtil.testForParent(parametersTypes[0],
581: java.io.Serializable.class))) {
582: return transactionKeyCacheFindMethodTemplate;
583: } else if (beanInfo.getCacheResults()
584: && findPattern.matcher(methodName).find()
585: && (parametersTypes.length != 1)) {
586: throw new RMIException(
587: "The bean cache result flag is set but "
588: + "there is no way identifying this entry in cache. Must "
589: + "supply the index key as a serializable object to a find "
590: + "method.");
591: }
592:
593: // return a none caching method
594: if (beanInfo.getTransaction()) {
595: return transactionCacheMethodTemplate;
596: } else {
597: return cacheMethodTemplate;
598: }
599: }
600:
601: /**
602: * This method will return true if the exception is found in the list of
603: * exceptions.
604: *
605: * @return TRUE if the exception is found.
606: * @param list The list of exceptions to check.
607: * @param exception The exception to perform the comparison for.
608: */
609: private boolean findException(Class[] list, Class exception) {
610: for (int index = 0; index < list.length; index++) {
611: if (list[index].getName().equals(exception.getName())) {
612: return true;
613: }
614: }
615: return false;
616: }
617: }
|