KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > tools > OPP > srcgen > builder > ProxyBuilder


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Library License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id$
8
package org.ozoneDB.tools.OPP.srcgen.builder;
9
10 import org.ozoneDB.tools.OPP.OPPHelper;
11 import org.ozoneDB.tools.OPP.srcgen.ClassBuilder;
12 import org.ozoneDB.tools.OPP.srcgen.BuilderException;
13 import org.ozoneDB.tools.OPP.srcgen.streamfactory.OutputStreamFactory;
14 import org.ozoneDB.tools.OPP.message.MessageWriter;
15 import org.ozoneDB.OzoneRemote;
16 import org.ozoneDB.core.helper.ReflectionHelper;
17 import org.ozoneDB.core.Lock;
18
19 import java.io.*;
20 import java.util.*;
21 import java.lang.reflect.Method JavaDoc;
22
23 /**
24  * Builds an ozone Proxy. The code is lifted out of the proxy generator
25  * and adapted to the builder director pattern.
26  *
27  * A lot oof code changes has to do with the absence of reflection dependency in the implementation of the builder
28  * director pattern implementation. The proxy builder still depends heavily on reflection, something that could
29  * probably be dealt with. The changes we have now is a lot of String lookup functionality for classes.
30  *
31  * We'd like to support static inner classes as OzoneObjects, but where should the proxy classes be defined?
32  * Within the the proxy class of the enclosing class? If so, what if the enclosing class is not OzoneCompatible?
33  *
34  * @author <a HREF="http://www.softwarebuero.de/">SMB</a>
35  * @author <a HREF="http://www.medium.net/">Medium.net</a>
36  * @author Per Nyfelt
37  * @author Joakim Ohlrogge
38  */

39 public class ProxyBuilder implements ClassBuilder {
40     private PrintWriter out;
41     private OutputStreamFactory osFactory;
42     private String JavaDoc postfix;
43     private Collection remoteInterfaces = new HashSet();
44     private boolean printStackTrace;
45     private boolean cache;
46     private MessageWriter msgWriter;
47     private String JavaDoc className;
48     private String JavaDoc proxyClassName;
49     private Class JavaDoc implementationClass;
50     private Method JavaDoc sortedMethods[];
51
52     private int getMethodIndex(String JavaDoc method, ClassBuilder.Parameter parameters[]) throws ClassNotFoundException JavaDoc, NoSuchMethodException JavaDoc {
53         Method JavaDoc m = implementationClass.getMethod(method, parametersToClasses(parameters));
54         return ReflectionHelper.methodArrayIndex(sortedMethods, m);
55     }
56
57     private Class JavaDoc[] parametersToClasses(ClassBuilder.Parameter parameters[]) throws ClassNotFoundException JavaDoc {
58         Class JavaDoc params[] = new Class JavaDoc[parameters.length];
59         for (int i = 0; i < parameters.length; i++) {
60             ClassBuilder.Parameter parameter = parameters[i];
61             params[i] = getClassForType(parameter.getOrigTypeName());
62         }
63         return params;
64     }
65
66     private Class JavaDoc getClassForType(String JavaDoc type) throws ClassNotFoundException JavaDoc {
67         Class JavaDoc clType = OPPHelper.classForPrimitive(type);
68         if (clType == null) {
69             Class JavaDoc cl = Class.forName(type);
70             return cl;
71         } else
72             return clType;
73     }
74
75     public ProxyBuilder(OutputStreamFactory osFactory, String JavaDoc postfix, boolean printStackTrace, boolean cache, MessageWriter listener) {
76         this.osFactory = osFactory;
77         this.postfix = postfix;
78         this.printStackTrace = printStackTrace;
79         this.cache = cache;
80         this.msgWriter = listener;
81     }
82
83     private String JavaDoc[] getTypes(ClassBuilder.Parameter parameters[]) {
84         String JavaDoc types[] = new String JavaDoc[parameters.length];
85         for (int i = 0; i < parameters.length; i++) {
86             ClassBuilder.Parameter parameter = parameters[i];
87             types[i] = parameter.getType();
88         }
89         return types;
90     }
91
92     private void makeCtrs() {
93         out.print("\n");
94         out.print(" public " + OPPHelper.simpleClassName(proxyClassName) + "() {\n");
95         out.print(" super();\n");
96
97         // out.print (" System.out.println (\"Ctor...\");\n");
98

99         // out.print (" new Exception().fillInStackTrace().printStackTrace();\n");
100

101         out.print(" }\n");
102         out.print("\n\n");
103
104
105
106         // create default ctor that is responsible to create a pure proxy
107

108         // without interacting with any database
109

110         out.print(" public " + OPPHelper.simpleClassName(proxyClassName) + " (ObjectID oid,OzoneInterface link) {\n");
111         out.print(" super(oid,link);\n");
112         out.print(" }\n");
113     }
114
115     private void makeGlobalHeader(String JavaDoc implementationClass) {
116         out.print("// Proxy class generated by ozone's OPP ($Revision$).\n");
117         out.print("// DO NOT EDIT!\n");
118         out.print("\n");
119         if (!OPPHelper.packageName(implementationClass).equals("")) {
120             out.print("package " + OPPHelper.packageName(implementationClass) + ";\n");
121             out.print("\n");
122         }
123         out.print("import org.ozoneDB.*;\n");
124         out.print("import org.ozoneDB.core.ObjectID;\n");
125         out.print("import org.ozoneDB.core.Lock;\n");
126         out.print("import org.ozoneDB.core.ResultConverter;\n");
127     }
128
129     private void makeLocalHeader(String JavaDoc proxyClassName) {
130         out.print("\n");
131         out.print("/**\n");
132         out.print(" * This class was automatically generated by ozone's OPP.\n");
133         out.print(" * Do not instantiate or use this class directly.\n");
134         out.print(" */\n");
135         out.print("public final class " + OPPHelper.simpleClassName(proxyClassName) + " extends OzoneProxy");
136         boolean first = true;
137         for (Iterator iter = remoteInterfaces.iterator(); iter.hasNext();) {
138             // filter methods that are not inherited from a OzoneRemote
139
// interface
140
if (first) {
141                 first = false;
142                 out.print(" implements ");
143             } else {
144                 out.print(", ");
145             }
146             out.print(((Class JavaDoc) iter.next()).getName());
147         }
148         out.print(" {\n");
149         out.print("\n static final long serialVersionUID = 1L;\n");
150     }
151
152     private void makeCstr(ClassBuilder.Parameter[] parameters, String JavaDoc[] exceptions) {
153         // string buffer to build the signatur of this method
154

155         StringBuffer JavaDoc signaturBuf = new StringBuffer JavaDoc("");
156         signaturBuf.append(" public " + OPPHelper.simpleClassName(proxyClassName) + " (");
157
158         // write the arguments in the declaration
159

160         // skip default ctor
161
if (parameters.length == 0) {
162             return;
163         }
164         for (int i = 0; i < parameters.length; i++) {
165             if (i != 0) {
166                 signaturBuf.append(", ");
167             }
168             signaturBuf.append(parameters[i].getType() + " " + parameters[i].getName());
169         }
170         signaturBuf.append(")");
171         out.print("\n\n");
172         out.print(signaturBuf.toString());
173
174
175
176         //Write the exceptions in the declaration
177
for (int i = 0; i < exceptions.length; i++) {
178             out.print(i == 0 ? " throws " : ", ");
179             out.print(exceptions[i]);
180         }
181         out.print(" {\n");
182
183
184
185         // the actual code of the method
186
out.print(" try {\n");
187         out.print(" link = ExternalDatabase.forThread (Thread.currentThread());\n");
188         out.print(" if (link == null)\n");
189         out.print(" throw new TransactionException (\"Thread has not yet joined a transaction.\");\n");
190         out.print(" \n");
191
192
193
194         //array of arguments
195
out.print(" Object[] args = {");
196         for (int i = 0; i < parameters.length; i++) {
197             out.print(i > 0 ? ", " : "");
198             if (OPPHelper.isPrimitive(parameters[i].getType())) {
199                 out.print("new " + OPPHelper.wrappercodeForPrimitive(parameters[i].getType()) + "(arg" + i + ")");
200             } else {
201                 out.print("arg" + i);
202             }
203         }
204         out.print("};\n");
205         String JavaDoc sig = ReflectionHelper.signature(getTypes(parameters));
206         out.print(" OzoneProxy proxy = link.createObject (\"" + className
207                 + "_Impl\", OzoneInterface.Public, null, " + sig + ", args);\n");
208         out.print(" remoteID = proxy.remoteID();\n");
209         out.print(" }\n");
210
211
212         //exceptions
213
boolean alreadyCatched = false;
214         for (int i = 0; i < exceptions.length; i++) {
215             out.print(" catch (" + exceptions[i] + " e) {\n");
216             out.print(" e.fillInStackTrace();\n");
217             out.print(" throw e; }\n");
218
219             // out.print (" throw (" + excs[i].getName() + ")e.fillInStackTrace(); }\n");
220

221             if (exceptions[i].equals("build.lang.Exception")) {
222                 alreadyCatched = true;
223             }
224         }
225         if (!alreadyCatched) {
226             out.print(" catch (Exception e) {\n");
227             if (printStackTrace) {
228                 out.print(" e.printStackTrace (System.out);\n");
229             }
230             out.print(" e.fillInStackTrace();\n");
231             out.print(" throw new UnexpectedException(e.toString()); }\n");
232         }
233         out.print(" }\n");
234     }
235
236     private void makeCreateMethod(ClassBuilder.Parameter[] parameters, String JavaDoc[] exceptions) {
237         // string buffer to build the signature of this method
238

239         StringBuffer JavaDoc signaturBuf = new StringBuffer JavaDoc("");
240         signaturBuf.append(" public static ");
241         Class JavaDoc firstItf = (Class JavaDoc) remoteInterfaces.iterator().next();
242         String JavaDoc proxyInterface = firstItf.getName();
243         signaturBuf.append(proxyInterface);
244         signaturBuf.append(" createObject(");
245
246         // argumente in declaration schreiben
247

248         for (int i = 0; i < parameters.length; i++) {
249             if (i != 0) {
250                 signaturBuf.append(", ");
251             }
252             signaturBuf.append(parameters[i].getType() + " " + parameters[i].getName());
253         }
254         if (parameters.length != 0) {
255             signaturBuf.append(",");
256         }
257         signaturBuf.append("OzoneInterface link)");
258         out.print("\n\n");
259         out.print(signaturBuf.toString());
260
261
262
263         //exceptions in declaration schreiben
264

265
266         for (int i = 0; i < exceptions.length; i++) {
267             out.print(i == 0 ? " throws " : ", ");
268             out.print(exceptions[i]);
269         }
270         out.print(" {\n");
271
272
273
274         // the actual code of the method
275

276         out.print(" try {\n");
277         out.print(" /*\n");
278         out.print(" if (link == null)\n");
279         out.print(" throw new TransactionException (\"Thread has not yet joined a transaction.\");\n");
280         out.print(" */\n");
281         out.print(" \n");
282
283
284
285         //array of arguments
286

287         out.print(" Object[] args = {");
288         for (int i = 0; i < parameters.length; i++) {
289             out.print(i > 0 ? ", " : "");
290             if (OPPHelper.isPrimitive(parameters[i].getType())) {
291                 out.print("new " + OPPHelper.wrappercodeForPrimitive(parameters[i].getType()) + "(arg" + i + ")");
292             } else {
293                 out.print("arg" + i);
294             }
295         }
296         out.print("};\n");
297         String JavaDoc sig = ReflectionHelper.signature(getTypes(parameters));
298         out.print(" OzoneProxy proxy = link.createObject (\"" + className
299                 + "\", OzoneInterface.Public, null, " + sig + ", args);\n");
300         out.print(" \n");
301         out.print(" return (" + proxyInterface + ") proxy;\n");
302
303
304
305         //exceptions
306

307         boolean catchedRuntimeException = false;
308         boolean catchedOzoneRemoteException = false;
309         if (false) {
310             for (int i = 0; i < exceptions.length; i++) {
311                 out.print(" } catch (" + exceptions[i] + " e) {\n");
312                 out.print(" e.fillInStackTrace();\n");
313                 out.print(" throw e;\n");
314
315                 // out.print (" throw (" + excs[i].getName() + ")e.fillInStackTrace(); }\n");
316

317                 if (exceptions[i].equals("build.lang.RuntimeException")) {
318                     catchedRuntimeException = true;
319                 } else if (exceptions[i].equals("org.ozoneDB.OzoneRemoteException")) {
320                     catchedOzoneRemoteException = true;
321                 }
322             }
323         } else {
324             if (true || exceptions.length > 0) {
325                 out.print(" } catch (OzoneObjectException e) {\n");
326                 out.print(" Throwable ee = e.getCause();\n");
327                 out.print(" \n");
328                 for (int i = 0; i < exceptions.length; i++) {
329                     out.print(" if (ee instanceof " + exceptions[i] + ") {\n");
330                     out.print(" throw (" + exceptions[i] + ") ee;\n");
331                     out.print(" }\n");
332                     out.print(" \n");
333                 }
334                 out.print(" // Hope that the compiler is not so smart and detect these statements as unreachable if these exceptions are already matched above\n");
335                 out.print(" if (ee instanceof RuntimeException) {\n");
336                 out.print(" throw (RuntimeException) ee;\n");
337                 out.print(" }\n");
338                 out.print(" \n");
339                 out.print(" if (ee instanceof Error) {\n");
340                 out.print(" throw (Error) ee;\n");
341                 out.print(" }\n");
342                 out.print(" \n");
343                 out.print(" throw e; // Unhandled exception.\n");
344             }
345         }
346         if (!catchedOzoneRemoteException) {
347             out.print(" } catch (OzoneRemoteException ore) {\n");
348             if (printStackTrace) {
349                 out.print(" ore.printStackTrace(System.out);\n");
350             }
351             out.print(" ore.fillInStackTrace();\n");
352             out.print(" throw new UnexpectedException(ore.toString());\n");
353         }
354         if (!catchedRuntimeException) {
355             out.print(" } catch (RuntimeException e) {\n");
356             if (printStackTrace) {
357                 out.print(" e.printStackTrace(System.out);\n");
358             }
359             out.print(" e.fillInStackTrace();\n");
360             out.print(" throw new UnexpectedException(e.toString());\n");
361         }
362         out.print(" }\n");
363         out.print(" }\n");
364     }
365
366     private Collection findRemoteInterfaces(String JavaDoc[] interfaces) throws ClassNotFoundException JavaDoc {
367         Set remoteItfs = new HashSet();
368         for (int i = interfaces.length - 1; i >= 0; i--) {
369             String JavaDoc itfName = interfaces[i];
370             Class JavaDoc itf = Class.forName(itfName);
371             if (OzoneRemote.class.isAssignableFrom(itf)) {
372                 remoteItfs.add(itf);
373             }
374         }
375         return remoteItfs;
376     }
377
378     public void init(MessageWriter msgWriter) {
379         this.msgWriter = msgWriter;
380     }
381
382     public void beginClass(int modifer, String JavaDoc fullName, String JavaDoc superClass, String JavaDoc interfaces[]) throws BuilderException {
383         msgWriter.startGeneration("Generating proxy for: " + fullName);
384         try {
385             out = new PrintWriter(osFactory.newInstance(fullName + postfix));
386         } catch (IOException e) {
387             throw new BuilderException(e);
388         }
389         className = fullName;
390         proxyClassName = fullName + postfix;
391         try {
392             implementationClass = Class.forName(fullName);
393             sortedMethods = ReflectionHelper.methodsOfClass(implementationClass);
394             remoteInterfaces = findRemoteInterfaces(interfaces);
395         } catch (ClassNotFoundException JavaDoc e) {
396             throw new BuilderException(e);
397         }
398         makeGlobalHeader(fullName);
399         makeLocalHeader(fullName + postfix);
400         makeCtrs();
401     }
402
403     public void makeConstructor(int modifier, ClassBuilder.Parameter parameters[], String JavaDoc exceptions[]) throws BuilderException {
404         makeCstr(parameters, exceptions);
405         makeCreateMethod(parameters, exceptions);
406     }
407
408     public void makeMethod(int modifier, String JavaDoc name, ClassBuilder.Parameter parameters[], String JavaDoc returnType, String JavaDoc exceptions[], int lockLevel) throws BuilderException {
409
410         // string buffer to build the signature of this method
411

412         StringBuffer JavaDoc signaturBuf = new StringBuffer JavaDoc("");
413         String JavaDoc retType = returnType == null ? "void" : returnType;
414         signaturBuf.append(" public " + retType + " " + name + "(");
415
416
417
418         //argumente in declaration schreiben
419
for (int i = 0; i < parameters.length; i++) {
420             if (i != 0) {
421                 signaturBuf.append(", ");
422             }
423             signaturBuf.append(parameters[i].getType() + " " + parameters[i].getName());
424         }
425         signaturBuf.append(")");
426         String JavaDoc signaturStr = signaturBuf.toString();
427
428
429         /*
430         I believe that this is not an issue any more
431
432         //The getMethods() method returns methods twice, if they are
433
434         //declared in different interfaces. So we have to check if this
435
436         //signatur was already proceeded.
437
438         if (doneMethodsIf.get(signaturStr) != null)
439         {
440           return;
441         } */

442
443
444         out.print("\n\n");
445         out.print(signaturStr);
446
447
448
449         //exceptions in declaration schreiben
450

451         for (int i = 0; i < exceptions.length; i++) {
452             out.print(i == 0 ? " throws " : ", ");
453             out.print(exceptions[i]);
454         }
455         out.print(" {\n");
456
457         //implementation
458
{
459             boolean update = lockLevel != (Lock.LEVEL_READ);
460
461             //System.out.println("looking at " + m.getName() + ", update is " + update + ", interface has method= " + updateMethodsIf.contains(m.getName()));
462

463             //msgWriter.info(" " + className + "." + name + " (" + sig + ")");
464

465             // code to directly invoke the target method
466
if (cache) {
467                 out.print(" Object target;\n");
468                 out.print("\n");
469                 out.print(" try {\n");
470                 out.print(" target = link.fetch(this, " + (update ? "Lock.LEVEL_WRITE" : "Lock.LEVEL_READ") + ");\n");
471                 out.print(" } catch (Exception e) {\n");
472                 if (printStackTrace) {
473                     out.print(" e.printStackTrace(System.out);\n");
474                 }
475                 out.print(" e.fillInStackTrace();\n");
476                 out.print(" throw new UnexpectedException(e.toString());\n");
477                 out.print(" }\n");
478                 out.print("\n");
479                 out.print(" if (target!=null) {\n");
480
481
482
483                 // convert arguments if needed
484

485                 for (int i = 0; i < parameters.length; i++) {
486                     if (!OPPHelper.isPrimitive(parameters[i].getType())) {
487                         out.print(" " + parameters[i].getName() + " = (" + parameters[i].getType() + ") ResultConverter.substituteOzoneCompatibles(" + parameters[i].getName() + ");\n");
488                     }
489                 }
490                 String JavaDoc ozoneInterface = ((Class JavaDoc) remoteInterfaces.iterator().next()).getName();
491                 msgWriter.debug("Interface = " + ozoneInterface);
492                 if (returnType != null) {
493                     if (!OPPHelper.isPrimitive(returnType)) {
494                         out.print(" return (" + returnType + ") ResultConverter.substituteOzoneCompatibles(((" + ozoneInterface + ") target)." + name + "(");
495                     } else {
496                         out.print(" return ((" + ozoneInterface + ") target)." + name + "(");
497                     }
498                 } else {
499                     out.print(" ((" + ozoneInterface + ") target)." + name + "(");
500                 }
501                 for (int i = 0; i < parameters.length; i++) {
502                     out.print(i > 0 ? ", " : "");
503                     out.print("arg" + i);
504                 }
505                 if (returnType != null) {
506                     if (!OPPHelper.isPrimitive(returnType)) {
507                         out.print(")");
508                     }
509                 }
510                 out.print(");\n");
511                 out.print(" } else {\n");
512             }
513
514
515
516             //array of arguments
517

518             out.print(" try {\n");
519             out.print(" Object[] args = {");
520             for (int i = 0; i < parameters.length; i++) {
521                 out.print(i > 0 ? ", " : "");
522                 if (OPPHelper.isPrimitive(parameters[i].getType())) {
523                     out.print("new " + OPPHelper.wrappercodeForPrimitive(parameters[i].getType()) + "(" + parameters[i].getName() + ")");
524                 } else {
525                     out.print("arg" + i);
526                 }
527             }
528             out.print("};\n");
529             try {
530                 out.print(" Object result = link.invoke(this, " + getMethodIndex(name, parameters) + ", args, " + (update
531                         ? "Lock.LEVEL_WRITE"
532                         : "Lock.LEVEL_READ") + ");\n");
533             } catch (ClassNotFoundException JavaDoc e) {
534                 throw new BuilderException(e);
535             } catch (NoSuchMethodException JavaDoc e) {
536                 throw new BuilderException(e);
537             }
538
539             // out.print (" result = link.invoke (this, \"" + m.getName() + "\", " + sig + ", args, " + (update ? "Lock.LEVEL_WRITE" : "Lock.LEVEL_READ") + ");\n");
540

541
542
543             // return value
544

545             if (returnType != null) {
546                 if (OPPHelper.isPrimitive(returnType)) {
547                     out.print(" return " + OPPHelper.returncodeForPrimitive(returnType,
548                             "result") + ";\n");
549                 } else {
550                     out.print(" return (" + returnType + ") result;\n");
551                 }
552             }
553
554
555
556
557
558
559
560             // user defined exceptions
561

562             boolean excAlreadyCatched = false;
563             boolean rtAlreadyCatched = false;
564             out.print(" } catch (OzoneObjectException e) {\n");
565             out.print(" Throwable ee = e.getCause();\n");
566             out.print(" \n");
567             for (int i = 0; i < exceptions.length; i++) {
568                 out.print(" if (ee instanceof " + exceptions[i] + ") {\n");
569                 out.print(" throw (" + exceptions[i] + ") ee;\n");
570                 out.print(" }\n");
571                 out.print(" \n");
572             }
573             out.print(" // Hope that the compiler is not so smart and detect these statements as unreachable if these exceptions are already matched above\n");
574             out.print(" if (ee instanceof RuntimeException) {\n");
575             out.print(" throw (RuntimeException) ee;\n");
576             out.print(" }\n");
577             out.print(" \n");
578             out.print(" if (ee instanceof Error) {\n");
579             out.print(" throw (Error) ee;\n");
580             out.print(" }\n");
581             out.print(" \n");
582             out.print(" throw e; // Unhandled exception.\n");
583
584
585
586
587
588             // runtime exceptions
589

590             if (!rtAlreadyCatched && !excAlreadyCatched) {
591                 out.print(" } catch (RuntimeException e) {\n");
592                 if (printStackTrace) {
593                     out.print(" e.printStackTrace(System.out);\n");
594                 }
595                 out.print(" e.fillInStackTrace();\n");
596                 out.print(" throw e;\n");
597             }
598
599
600
601             // all exceptions left
602

603             if (!excAlreadyCatched) {
604                 out.print(" } catch (Exception e) {\n");
605                 if (printStackTrace) {
606                     out.print(" e.printStackTrace(System.out);\n");
607                 }
608                 out.print(" e.fillInStackTrace();\n");
609                 out.print(" throw new UnexpectedException(e.toString());\n");
610             }
611             out.print(" }\n");
612             if (cache) {
613                 out.print(" }\n");
614             }
615         }
616         out.print(" }\n");
617     }
618
619     public void endClass() throws BuilderException {
620         out.println("}");
621         out.close();
622         msgWriter.endGeneration();
623     }
624 }
625
Popular Tags