001: // You can redistribute this software and/or modify it under the terms of
002: // the Ozone Library License version 1 published by ozone-db.org.
003: //
004: // The original code and portions created by SMB are
005: // Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
006: //
007: // $Id: ProxyGenerator.java,v 1.3 2002/06/08 00:49:39 mediumnet Exp $
008:
009: package org.ozoneDB.tools.OPP;
010:
011: import java.io.*;
012: import java.lang.reflect.*;
013: import java.util.Hashtable;
014: import java.util.TreeMap;
015: import java.util.Enumeration;
016: import java.util.ArrayList;
017: import java.util.Arrays;
018: import java.util.Iterator; //import org.apache.regexp.*;
019: import org.ozoneDB.DxLib.*;
020: import org.ozoneDB.OzoneCompatible;
021: import org.ozoneDB.OzoneObject;
022: import org.ozoneDB.OzoneRemote;
023: import org.ozoneDB.core.ObjectID;
024: import org.ozoneDB.core.ObjectContainer;
025:
026: /**
027: *
028: * I'd like to support static inner classes as OzoneObjects, but where should the proxy classes defined?
029: * Within the the proxy class of the enclosing class? If so, what if the enclosing class is not OzoneCompatible?
030: *
031: * @author <a href="http://www.softwarebuero.de/">SMB</a>
032: * @author <a href="http://www.medium.net/">Medium.net</a>
033: * @version $Revision: 1.3 $Date: 2002/06/08 00:49:39 $
034: */
035: class ProxyGenerator {
036:
037: protected PrintWriter out;
038:
039: protected Class cl;
040:
041: protected Method[] methods;
042:
043: protected String outputDir;
044:
045: protected String proxyFileName;
046:
047: protected String proxyClassName;
048:
049: protected boolean quiet;
050:
051: protected boolean cache;
052:
053: protected Object re;
054:
055: /**
056: * Names of update methods as Strings.
057: */
058: protected DxHashMap updateMethodsIf = new DxHashMap();
059:
060: /**
061: * Complete signatur of methods already proceeded .
062: */
063: protected TreeMap doneMethodsIf = new TreeMap();
064:
065: public ProxyGenerator(Class _cl, String _methodPattern,
066: String _outputDir, boolean _quiet, boolean _cache)
067: throws Exception {
068: cl = _cl;
069: methods = OPPHelper.methodsOfClass(cl);
070: outputDir = _outputDir;
071: quiet = _quiet;
072: cache = _cache;
073: re = OPPHelper.newRE(_methodPattern, false);
074: proxyFileName = outputDir + OPPHelper.classFileBasename(cl)
075: + ObjectContainer.PROXYNAME_POSTFIX + ".java";
076: proxyClassName = cl.getName()
077: + ObjectContainer.PROXYNAME_POSTFIX;
078:
079: if (!quiet) {
080: System.out.println(" creating " + proxyFileName + " ...");
081: System.out.println(" update methods:");
082: }
083:
084: if (!(cl instanceof Serializable)) {
085: System.out.println(cl.getName()
086: + " does not implement Serializable.");
087: System.exit(1);
088: }
089:
090: if (!OzoneRemote.class.isAssignableFrom(cl)) {
091: OPPHelper.error(cl, " does not implement OzoneRemote.");
092: }
093: }
094:
095: public void compileSource() throws Exception {
096: String[] args = new String[4];
097:
098: OPPHelper.progressMsg(" compiling " + proxyFileName + " ...",
099: quiet);
100:
101: String compilerCommand = System.getProperty("ozone.javac",
102: "javac");
103: if (!quiet) {
104: OPPHelper
105: .progressMsg("compiler: " + compilerCommand, quiet);
106: }
107:
108: // get the classpath of this virtual machine
109: String jvmClassPath = System.getProperty("java.class.path", "");
110:
111: // build the new argument array
112: args[0] = compilerCommand;
113: args[1] = "-classpath";
114: args[2] = jvmClassPath;
115: args[3] = proxyFileName;
116: Process process = Runtime.getRuntime().exec(args);
117:
118: // Eating compiler output is required to avoid pipe stalls, but this code requires Medium.net classes which are not GPL. That's why this is commented out.
119: // com.mn.io.stream.StreamConnector.synchronizedProcessConnect(process.getInputStream(),process.getErrorStream(),System.out,1024,process);
120:
121: process.waitFor();
122: if (process.exitValue() != 0) {
123: OPPHelper.warnMsg(proxyFileName, 0,
124: "Unable to compile the generated source code!");
125: OPPHelper.warnMsg(proxyFileName, 0, " command line: '"
126: + args[0] + " " + args[1] + " " + args[2] + " "
127: + args[3] + "'");
128: }
129: }
130:
131: public void generateClassSource(Class cl) throws Exception {
132: makeLocalHeader();
133: makeCtors();
134: makeCreateMethods();
135: makeMethods();
136: checkMethodLists();
137:
138: out.print(" }\n");
139: }
140:
141: public void generateSource(boolean searchInterfaceSource) {
142: try {
143: searchUpdateMethods(searchInterfaceSource);
144:
145: File proxyFile = new File(proxyFileName);
146: File parentFile = proxyFile.getParentFile();
147: if (parentFile != null)
148: parentFile.mkdirs();
149: out = new PrintWriter(new FileOutputStream(proxyFileName));
150: makeGlobalHeader();
151: generateClassSource(cl);
152: } catch (Exception e) {
153: System.out.println(OPPHelper.classFileBasename(cl)
154: + ".java:0: " + e.getMessage());
155: e.printStackTrace();
156: System.exit(1);
157: } finally {
158: out.close();
159: }
160: }
161:
162: public void deleteSource() throws Exception {
163: File file = new File(proxyFileName);
164: if (!file.delete()) {
165: System.out.println("Unable to delete the source file.");
166: }
167: }
168:
169: public void makeGlobalHeader() throws Exception {
170: out
171: .print("// Proxy class generated by ozone's OPP ($Revision: 1.3 $).\n");
172: out.print("// DO NOT EDIT!\n");
173: out.print("\n");
174: if (!OPPHelper.packageName(cl).equals("")) {
175: out.print("package " + OPPHelper.packageName(cl) + ";\n");
176: out.print("\n");
177: }
178: out.print("import org.ozoneDB.*;\n");
179: out.print("import org.ozoneDB.core.ObjectID;\n");
180: out.print("import org.ozoneDB.core.Lock;\n");
181: out.print("import org.ozoneDB.core.ResultConverter;\n");
182: }
183:
184: public void makeLocalHeader() throws Exception {
185:
186: out.print("\n");
187: out.print("/**\n");
188: out
189: .print(" * This class was automatically generated by ozone's OPP.\n");
190: out
191: .print(" * Do not instantiate or use this class directly.\n");
192: out.print(" */\n");
193: out.print("public final class "
194: + OPPHelper.simpleClassName(proxyClassName) + " \n");
195: out.print(" extends OzoneProxy\n");
196:
197: Class[] ifs = cl.getInterfaces();
198: for (int i = 0, c = 0; i < ifs.length; i++) {
199: // filter methods that are not inherited from a OzoneRemote
200: // interface
201: if (OzoneRemote.class.isAssignableFrom(ifs[i])) {
202: if (c++ == 0) {
203: out.print(" implements ");
204: } else {
205: out.print(", ");
206: }
207:
208: out.print(ifs[i].getName());
209: }
210: }
211: out.print(" {\n");
212:
213: out.print("\n static final long serialVersionUID = 1L;\n");
214: }
215:
216: /**
217: * Employ IfHelper and CDHelper to find the methods that need to
218: * acquire WRITE lock.
219: */
220: public void searchUpdateMethods(boolean searchInterfaceSource)
221: throws Exception {
222: IfHelper ifHelper = new IfHelper(cl, outputDir, quiet);
223: ifHelper.searchUpdateMethods(updateMethodsIf);
224:
225: CDHelper cdHelper = new CDHelper(cl, outputDir, quiet);
226: cdHelper.searchUpdateMethods(updateMethodsIf);
227: }
228:
229: public void makeCtors() throws Exception {
230: out.print("\n");
231: out.print(" public "
232: + OPPHelper.simpleClassName(proxyClassName) + "() {\n");
233: out.print(" super();\n");
234: // out.print (" System.out.println (\"Ctor...\");\n");
235: // out.print (" new Exception().fillInStackTrace().printStackTrace();\n");
236: out.print(" }\n");
237: out.print("\n\n");
238:
239: // create default ctor that is responsible to create a pure proxy
240: // without interacting with any database
241: out.print(" public "
242: + OPPHelper.simpleClassName(proxyClassName)
243: + " (ObjectID oid, OzoneInterface link) {\n");
244: out.print(" super (oid, link);\n");
245: out.print(" }\n");
246:
247: if (false) {
248: java.lang.reflect.Constructor[] ctors = cl
249: .getDeclaredConstructors();
250: for (int i = 0; i < ctors.length; i++) {
251: makeCtor(ctors[i]);
252: }
253: }
254: }
255:
256: public void makeCtor(Constructor ctor) throws Exception {
257: // string buffer to build the signatur of this method
258: StringBuffer signaturBuf = new StringBuffer("");
259:
260: signaturBuf.append(" public "
261: + OPPHelper.simpleClassName(proxyClassName) + " (");
262:
263: // argumente in declaration schreiben
264: Class[] args = ctor.getParameterTypes();
265:
266: // skip default ctor
267: if (args.length == 0) {
268: return;
269: }
270:
271: for (int i = 0; i < args.length; i++) {
272: if (i != 0) {
273: signaturBuf.append(", ");
274: }
275: signaturBuf.append(typecodeForClass(args[i]) + " arg" + i);
276: }
277: signaturBuf.append(")");
278:
279: out.print("\n\n");
280: out.print(signaturBuf.toString());
281:
282: //exceptions in declaration schreiben
283: Class[] excs = ctor.getExceptionTypes();
284: for (int i = 0; i < excs.length; i++) {
285: out.print(i == 0 ? " throws " : ", ");
286: out.print(excs[i].getName());
287: }
288: out.print(" {\n");
289:
290: // the actual code of the method
291: out.print(" try {\n");
292: out
293: .print(" link = ExternalDatabase.forThread (Thread.currentThread());\n");
294: out.print(" if (link == null)\n");
295: out
296: .print(" throw new TransactionExc (\"Thread has not yet joined a transaction.\");\n");
297: out.print(" \n");
298:
299: //array of arguments
300: out.print(" Object[] args = {");
301: for (int i = 0; i < args.length; i++) {
302: out.print(i > 0 ? ", " : "");
303: if (args[i].isPrimitive()) {
304: out.print("new "
305: + OPPHelper.wrappercodeForPrimitive(args[i])
306: + "(arg" + i + ")");
307: } else {
308: out.print("arg" + i);
309: }
310: }
311: out.print("};\n");
312:
313: String sig = OPPHelper.signature(ctor.getParameterTypes());
314: out.print(" OzoneProxy proxy = link.createObject (\""
315: + cl.getName()
316: + "_Impl\", OzoneInterface.Public, null, " + sig
317: + ", args);\n");
318: out.print(" remoteID = proxy.remoteID();\n");
319: out.print(" }\n");
320:
321: //exceptions
322: boolean alreadyCatched = false;
323: for (int i = 0; i < excs.length; i++) {
324: out.print(" catch (" + excs[i].getName() + " e) {\n");
325: out.print(" e.fillInStackTrace();\n");
326: out.print(" throw e; }\n");
327: // out.print (" throw (" + excs[i].getName() + ")e.fillInStackTrace(); }\n");
328: if (excs[i].getName().equals("java.lang.Exception")) {
329: alreadyCatched = true;
330: }
331: }
332: if (!alreadyCatched) {
333: out.print(" catch (Exception e) {\n");
334: if (OPP.printStackTrace) {
335: out.print(" e.printStackTrace (System.out);\n");
336: }
337: out.print(" e.fillInStackTrace();\n");
338: out
339: .print(" throw new UnexpectedException (e.toString()); }\n");
340: }
341: out.print(" }\n");
342: }
343:
344: protected String determineProxyInterface() {
345: Class[] ifs = cl.getInterfaces();
346:
347: for (int i = 0, c = 0; i < ifs.length; i++) {
348: // filter methods that are not inherited from a OzoneRemote
349: // interface
350: // System.out.println("determineProxyInterface(): checking "+ifs[i]+".");
351:
352: if (OzoneRemote.class.isAssignableFrom(ifs[i])) {
353:
354: return ifs[i].getName();
355: }
356: }
357:
358: return determineProxyInterfaceDeep(cl);
359: }
360:
361: protected String determineProxyInterfaceDeep(Class of) {
362: Class[] ifs = of.getInterfaces();
363: ArrayList list = new ArrayList(Arrays.asList(ifs));
364:
365: if (false) {
366: Class super class = of.getSuperclass();
367:
368: if (super class != null) {
369: list.add(super class);
370: }
371: }
372:
373: for (Iterator i = list.iterator(); i.hasNext();) {
374: Class testClass = (Class) i.next();
375:
376: // filter methods that are not inherited from a OzoneRemote
377: // interface
378: // System.out.println("determineProxyInterface(): checking "+testClass+".");
379:
380: if (OzoneRemote.class.isAssignableFrom(testClass)) {
381:
382: return testClass.getName();
383: } else {
384: String interfaceName = determineProxyInterfaceDeep(testClass);
385:
386: if (interfaceName != null) {
387: return interfaceName;
388: }
389: }
390: }
391:
392: return null;
393: }
394:
395: public void makeCreateMethods() throws Exception {
396:
397: java.lang.reflect.Constructor[] ctors = cl
398: .getDeclaredConstructors();
399: for (int i = 0; i < ctors.length; i++) {
400: makeCreateMethod(ctors[i]);
401: }
402: }
403:
404: protected void makeCreateMethod(Constructor ctor) throws Exception {
405: // string buffer to build the signatur of this method
406: StringBuffer signaturBuf = new StringBuffer("");
407:
408: signaturBuf.append(" public static ");
409:
410: String proxyInterface = determineProxyInterface();
411:
412: signaturBuf.append(proxyInterface);
413: signaturBuf.append(" createObject(");
414:
415: // argumente in declaration schreiben
416: Class[] args = ctor.getParameterTypes();
417:
418: for (int i = 0; i < args.length; i++) {
419: if (i != 0) {
420: signaturBuf.append(", ");
421: }
422: signaturBuf.append(typecodeForClass(args[i]) + " arg" + i);
423: }
424:
425: if (args.length != 0) {
426: signaturBuf.append(",");
427: }
428:
429: signaturBuf.append("OzoneInterface link)");
430:
431: out.print("\n\n");
432: out.print(signaturBuf.toString());
433:
434: //exceptions in declaration schreiben
435: Class[] excs = ctor.getExceptionTypes();
436: for (int i = 0; i < excs.length; i++) {
437: out.print(i == 0 ? " throws " : ", ");
438: out.print(excs[i].getName());
439: }
440: out.print(" {\n");
441:
442: // the actual code of the method
443: out.print(" try {\n");
444: out.print(" /*\n");
445: out.print(" if (link == null)\n");
446: out
447: .print(" throw new TransactionExc (\"Thread has not yet joined a transaction.\");\n");
448: out.print(" */\n");
449: out.print(" \n");
450:
451: //array of arguments
452: out.print(" Object[] args = {");
453: for (int i = 0; i < args.length; i++) {
454: out.print(i > 0 ? ", " : "");
455: if (args[i].isPrimitive()) {
456: out.print("new "
457: + OPPHelper.wrappercodeForPrimitive(args[i])
458: + "(arg" + i + ")");
459: } else {
460: out.print("arg" + i);
461: }
462: }
463: out.print("};\n");
464:
465: String sig = OPPHelper.signature(ctor.getParameterTypes());
466: out.print(" OzoneProxy proxy = link.createObject (\""
467: + cl.getName() + "\", OzoneInterface.Public, null, "
468: + sig + ", args);\n");
469: out.print(" \n");
470: out.print(" return (" + proxyInterface + ") proxy;\n");
471:
472: //exceptions
473: boolean alreadyCatched = false;
474: if (false) {
475: for (int i = 0; i < excs.length; i++) {
476: out.print(" } catch (" + excs[i].getName()
477: + " e) {\n");
478: out.print(" e.fillInStackTrace();\n");
479: out.print(" throw e;\n");
480: // out.print (" throw (" + excs[i].getName() + ")e.fillInStackTrace(); }\n");
481: if (excs[i].getName().equals(
482: "java.lang.RuntimeException")) {
483: alreadyCatched = true;
484: }
485: }
486: } else {
487: if (true || excs.length > 0) {
488: out
489: .print(" } catch (ExceptionInOzoneObjectException e) {\n");
490: out.print(" Throwable ee = e.getCause();\n");
491: out.print(" \n");
492: for (int i = 0; i < excs.length; i++) {
493: out.print(" if (ee instanceof "
494: + excs[i].getName() + ") {\n");
495: out.print(" throw ("
496: + excs[i].getName() + ") ee;\n");
497: out.print(" }\n");
498: out.print(" \n");
499: }
500:
501: out
502: .print(" // Hope that the compiler is not so smart and detect these statements as unreachable if these exceptions are already matched above\n");
503: out
504: .print(" if (ee instanceof RuntimeException) {\n");
505: out
506: .print(" throw (RuntimeException) ee;\n");
507: out.print(" }\n");
508: out.print(" \n");
509: out.print(" if (ee instanceof Error) {\n");
510: out.print(" throw (Error) ee;\n");
511: out.print(" }\n");
512: out.print(" \n");
513: out
514: .print(" throw e; // Unhandled exception.\n");
515: }
516: }
517: if (!alreadyCatched) {
518: out.print(" } catch (RuntimeException e) {\n");
519: if (OPP.printStackTrace) {
520: out.print(" e.printStackTrace(System.out);\n");
521: }
522: out.print(" e.fillInStackTrace();\n");
523: out
524: .print(" throw new UnexpectedException(e.toString());\n");
525: }
526: out.print(" }\n");
527: out.print(" }\n");
528: }
529:
530: public void makeMethods() throws Exception {
531: Class[] ifs = cl.getInterfaces();
532: for (int i = 0; i < ifs.length; i++) {
533: // filter interfaces that are not inherited from a OzoneRemote
534: // interface
535: if (OzoneRemote.class.isAssignableFrom(ifs[i])) {
536: java.lang.reflect.Method[] methods = ifs[i]
537: .getMethods();
538: for (int j = 0; j < methods.length; j++) {
539: makeMethod(methods[j]);
540: }
541: }
542: }
543: }
544:
545: /**
546: * Checks if all method names in the update lists
547: * are processed.
548: */
549: public void checkMethodLists() throws Exception {
550: for (Enumeration e = updateMethodsIf.internalHashtable().keys(); e
551: .hasMoreElements();) {
552: Object o = e.nextElement();
553: if (doneMethodsIf.get(o) != null) {
554: OPPHelper
555: .warnMsg(
556: OPPHelper.simpleClassName(cl),
557: 0,
558: " method with name: '"
559: + o.toString()
560: + "' could not be processed, but is marked as 'update' or 'WRITE'-LOCK");
561: }
562: }
563: }
564:
565: public void makeMethod(Method m) throws Exception {
566:
567: // string buffer to build the signatur of this method
568: StringBuffer signaturBuf = new StringBuffer("");
569:
570: signaturBuf.append(" public "
571: + typecodeForClass(m.getReturnType()) + " "
572: + m.getName() + "(");
573:
574: //argumente in declaration schreiben
575: Class[] args = m.getParameterTypes();
576: for (int i = 0; i < args.length; i++) {
577: if (i != 0) {
578: signaturBuf.append(", ");
579: }
580: signaturBuf.append(typecodeForClass(args[i]) + " arg" + i);
581: }
582: signaturBuf.append(")");
583:
584: String signaturStr = signaturBuf.toString();
585: //The getMethods() method returns methods twice, if they are
586: //declared in different interfaces. So we have to check if this
587: //signatur was already proceeded.
588: if (doneMethodsIf.get(signaturStr) != null) {
589: return;
590: }
591:
592: out.print("\n\n");
593: out.print(signaturStr);
594:
595: //exceptions in declaration schreiben
596: Class[] excs = m.getExceptionTypes();
597: for (int i = 0; i < excs.length; i++) {
598: out.print(i == 0 ? " throws " : ", ");
599: out.print(excs[i].getName());
600: }
601: out.print(" {\n");
602:
603: //implementation
604: out.print(" try {\n");
605:
606: boolean update = OPPHelper.reMatch(re, m.getName())
607: || updateMethodsIf.contains(m.getName());
608: String sig = OPPHelper.signature(m.getParameterTypes());
609: if (update && !quiet) {
610: System.out.println(" "
611: + m.getDeclaringClass().getName() + "."
612: + m.getName() + " (" + sig + ")");
613: }
614:
615: // code to directly invoke the target method
616: if (cache) {
617: out.print(" Object target = link.fetch (this, "
618: + (update ? "Lock.LEVEL_WRITE" : "Lock.LEVEL_READ")
619: + ");\n");
620: out.print("\n");
621: out.print(" if (target!=null) {\n");
622:
623: // convert arguments if needed
624: for (int i = 0; i < args.length; i++) {
625: if (!args[i].isPrimitive()) {
626: out
627: .print(" arg"
628: + i
629: + " = ("
630: + typecodeForClass(args[i])
631: + ") ResultConverter.substituteOzoneCompatibles(arg"
632: + i + ");\n");
633: }
634: }
635:
636: if (!m.getReturnType().getName().equals("void")) {
637: if (!m.getReturnType().isPrimitive()) {
638: out
639: .print(" return ("
640: + typecodeForClass(m
641: .getReturnType())
642: + ") ResultConverter.substituteOzoneCompatibles((("
643: + cl.getName() + ") target)."
644: + m.getName() + "(");
645: } else {
646: out.print(" return ((" + cl.getName()
647: + ") target)." + m.getName() + "(");
648: }
649: } else {
650: out.print(" ((" + cl.getName()
651: + ") target)." + m.getName() + "(");
652: }
653:
654: for (int i = 0; i < args.length; i++) {
655: out.print(i > 0 ? ", " : "");
656: out.print("arg" + i);
657: }
658: if (!m.getReturnType().getName().equals("void")) {
659: if (!m.getReturnType().isPrimitive()) {
660: out.print(")");
661: }
662: }
663: out.print(");\n");
664: out.print(" } else {\n");
665: }
666:
667: //array of arguments
668: out.print(" Object[] args = {");
669: for (int i = 0; i < args.length; i++) {
670: out.print(i > 0 ? ", " : "");
671: if (args[i].isPrimitive()) {
672: out.print("new "
673: + OPPHelper.wrappercodeForPrimitive(args[i])
674: + "(arg" + i + ")");
675: } else {
676: out.print("arg" + i);
677: }
678: }
679: out.print("};\n");
680:
681: out.print(" Object result = link.invoke(this, "
682: + OPPHelper.methodArrayIndex(methods, m) + ", args, "
683: + (update ? "Lock.LEVEL_WRITE" : "Lock.LEVEL_READ")
684: + ");\n");
685: // out.print (" result = link.invoke (this, \"" + m.getName() + "\", " + sig + ", args, " + (update ? "Lock.LEVEL_WRITE" : "Lock.LEVEL_READ") + ");\n");
686:
687: // return value
688: if (!m.getReturnType().getName().equals("void")) {
689: if (m.getReturnType().isPrimitive()) {
690: out.print(" return "
691: + OPPHelper.returncodeForPrimitive(m
692: .getReturnType(), "result") + ";\n");
693: } else {
694: out.print(" return ("
695: + typecodeForClass(m.getReturnType())
696: + ") result;\n");
697: }
698: }
699:
700: if (cache) {
701: out.print(" }\n");
702: }
703:
704: // user defined exceptions
705: boolean excAlreadyCatched = false;
706: boolean rtAlreadyCatched = false;
707:
708: if (false) {
709: for (int i = 0; i < excs.length; i++) {
710: out.print(" catch (" + excs[i].getName()
711: + " e) {\n");
712: if (OPP.printStackTrace) {
713: out
714: .print(" e.printStackTrace(System.out);\n");
715: }
716: out.print(" e.fillInStackTrace();\n");
717: out.print(" throw e;\n");
718: out.print(" }\n");
719: // out.print (" throw (" + excs[i].getName() + ")e.fillInStackTrace(); }\n");
720:
721: if (excs[i].getName().equals("java.lang.Exception")) {
722: excAlreadyCatched = true;
723: }
724: if (excs[i].getName().equals(
725: "java.lang.RuntimeException")) {
726: rtAlreadyCatched = true;
727: }
728: }
729: } else {
730: if (true || excs.length > 0) {
731: out
732: .print(" } catch (ExceptionInOzoneObjectException e) {\n");
733: out.print(" Throwable ee = e.getCause();\n");
734: out.print(" \n");
735:
736: for (int i = 0; i < excs.length; i++) {
737: out.print(" if (ee instanceof "
738: + excs[i].getName() + ") {\n");
739: out.print(" throw ("
740: + excs[i].getName() + ") ee;\n");
741: out.print(" }\n");
742: out.print(" \n");
743: }
744:
745: out
746: .print(" // Hope that the compiler is not so smart and detect these statements as unreachable if these exceptions are already matched above\n");
747: out
748: .print(" if (ee instanceof RuntimeException) {\n");
749: out
750: .print(" throw (RuntimeException) ee;\n");
751: out.print(" }\n");
752: out.print(" \n");
753: out.print(" if (ee instanceof Error) {\n");
754: out.print(" throw (Error) ee;\n");
755: out.print(" }\n");
756: out.print(" \n");
757: out
758: .print(" throw e; // Unhandled exception.\n");
759: }
760: }
761:
762: // runtime exceptions
763: if (!rtAlreadyCatched && !excAlreadyCatched) {
764: out.print(" } catch (RuntimeException e) {\n");
765: if (OPP.printStackTrace) {
766: out.print(" e.printStackTrace(System.out);\n");
767: }
768: out.print(" e.fillInStackTrace();\n");
769: out.print(" throw e;\n");
770: }
771:
772: // all exceptions left
773: if (!excAlreadyCatched) {
774: out.print(" } catch (Exception e) {\n");
775: if (OPP.printStackTrace) {
776: out.print(" e.printStackTrace(System.out);\n");
777: }
778: out.print(" e.fillInStackTrace();\n");
779: out
780: .print(" throw new UnexpectedException (e.toString());\n");
781: }
782:
783: out.print(" }\n");
784: out.print(" }\n");
785:
786: // save proceeded methods
787: doneMethodsIf.put(signaturStr, m.getName());
788: }
789:
790: /**
791: * Gives the Java source code for the type of the specified class.
792: */
793: protected String typecodeForClass(Class cl) throws Exception {
794:
795: String ret;
796:
797: // // primitive type
798: // if (name.length() == 1) {
799: // // throw new Exception ("Primitive types are not allowed as argument or return type!");
800: // ret = typecodeForPrimitive (name.charAt(0));
801: // }
802: //
803: // // array of references
804: // else if (name.startsWith("[L"))
805: // ret = name.substring (2, name.length() - 1) + "[]";
806: //
807: // // array of primitive types
808: // else if (name.startsWith("["))
809: // ret = typecodeForPrimitive(name.charAt(1)) + "[]";
810:
811: // array
812: if (cl.isArray()) {
813: StringBuffer b = new StringBuffer();
814:
815: while (cl.isArray()) {
816: b.append("[]");
817: cl = cl.getComponentType();
818: }
819: b.insert(0, getSourcecodeClassName(cl));
820: ret = b.toString();
821: } else {
822:
823: // norgetSourcecodeClassName(cl)reference and primitive types
824: ret = getSourcecodeClassName(cl);
825: }
826: return ret;
827: }
828:
829: /**
830: Returns the name of the class in the way it is used within source code.
831: This is similar to the internal class name with the exception that names of inner
832: classes separate between class levels not by '$' but by '.'.
833: */
834: protected static String getSourcecodeClassName(Class cl) {
835: return cl.getName().replace('$', '.');
836: }
837: }
|