KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > tools > OPP > srcgen > direct > ReflectionClassDirector


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: ReflectionClassDirector.java,v 1.4 2003/11/27 13:26:03 leomekenkamp Exp $
8
package org.ozoneDB.tools.OPP.srcgen.direct;
9
10 import org.ozoneDB.tools.OPP.srcgen.MethodResolver;
11 import org.ozoneDB.tools.OPP.srcgen.ResolverException;
12 import org.ozoneDB.tools.OPP.srcgen.ClassBuilder;
13 import org.ozoneDB.tools.OPP.srcgen.BuilderException;
14 import org.ozoneDB.tools.OPP.srcgen.ClassDirector;
15 import org.ozoneDB.tools.OPP.srcgen.resolve.UpdateMethodBagMapAdapter;
16 import org.ozoneDB.tools.OPP.message.MessageWriter;
17 import org.ozoneDB.core.Lock;
18 import org.ozoneDB.OzoneRemote;
19 import org.ozoneDB.OzoneCompatible;
20
21 import java.util.Set JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Constructor JavaDoc;
27
28 /**
29  * This ClassDirector uses reflection as the foundation of directs.
30  * In order to determine the LockLevel of the different methods the Director can be paired with an UpdateMethodResolver..
31  *
32  * @author Joakim Ohlrogge
33  */

34 public class ReflectionClassDirector implements ClassDirector {
35     private MethodResolver resolver;
36     private Class JavaDoc filterInterface;
37     private Set JavaDoc processedMethods;
38     private MessageWriter msgWriter;
39
40     public ReflectionClassDirector(MessageWriter msgListener, MethodResolver resolver) {
41         this(msgListener, resolver, OzoneRemote.class);
42     }
43
44     public ReflectionClassDirector(MessageWriter msgListener, MethodResolver resolver, Class JavaDoc filterInterface) {
45         this.msgWriter = msgListener;
46         this.resolver = resolver;
47         this.filterInterface = filterInterface;
48         this.processedMethods = new HashSet JavaDoc();
49     }
50
51     public void build(String JavaDoc fullClassName, ClassBuilder builder) throws BuilderException {
52         msgWriter.startGeneration("Processing " + fullClassName);
53         try {
54             Map JavaDoc updateMethods = new HashMap JavaDoc();
55             processedMethods.clear();
56             msgWriter.startGeneration("Resolving update methods");
57             MethodResolver.UpdateMethodBag methodBag = new UpdateMethodBagMapAdapter(updateMethods);
58             try {
59                 resolver.resolveMethods(fullClassName, methodBag);
60             } catch (ResolverException e) {
61                 throw new BuilderException(e);
62             } finally {
63                 msgWriter.endGeneration();
64             }
65             Class JavaDoc sourceClass;
66             try {
67                 sourceClass = Class.forName(fullClassName);
68                 if (sourceClass.isInterface()) {
69                     throw new BuilderException(fullClassName + " is an interface, should be a class");
70                 }
71                 if (!OzoneCompatible.class.isAssignableFrom(sourceClass)) {
72                     throw new BuilderException("The class " + fullClassName + " must extend OzoneObject or implement OzoneCompatible");
73                 }
74             } catch (ClassNotFoundException JavaDoc e) {
75                 throw new BuilderException(e);
76             }
77             Class JavaDoc clazz = sourceClass.getSuperclass();
78             String JavaDoc superClassName;
79             if (clazz == null) {
80                 throw new BuilderException("No superclass exist for " + fullClassName);
81             } else {
82                 superClassName = clazz.getName();
83                 //msgWriter.info("superclass for " + fullClassName + " is " + superClassName);
84
}
85
86             String JavaDoc interfaces[] = getClassNames(sourceClass.getInterfaces());
87
88             // init builder
89
builder.init(msgWriter);
90
91             // Start of class
92
builder.beginClass(sourceClass.getModifiers(), fullClassName, superClassName, interfaces);
93
94             // Make constructors
95
Constructor JavaDoc constructors[] = sourceClass.getConstructors();
96             for (int i = 0; i < constructors.length; ++i) {
97                 Constructor JavaDoc constructor = constructors[i];
98                 ClassBuilder.Parameter parameters[] = getParameters(constructor.getParameterTypes());
99                 String JavaDoc exceptions[] = getClassNames(constructor.getExceptionTypes());
100                 builder.makeConstructor(constructor.getModifiers(), parameters, exceptions);
101             }
102             Class JavaDoc itfs[] = sourceClass.getInterfaces();
103             for (int i = 0; i < itfs.length; i++) {
104                 Class JavaDoc itf = itfs[i];
105                 // filter out all interfaces that are not assignable from the filter interface
106
if (!filterInterface.isAssignableFrom(itf))
107                     continue;
108                 buildMethodsDeep(itf, builder, updateMethods);
109             }
110
111
112             // end of class
113
builder.endClass();
114         } finally {
115             msgWriter.endGeneration();
116         }
117     }
118
119     private void buildMethodsDeep(Class JavaDoc itf, ClassBuilder builder, Map JavaDoc updateMethods) throws BuilderException {
120         // Make methods
121
Method JavaDoc methods[] = itf.getMethods();
122         for (int j = 0; j < methods.length; ++j) {
123             Method JavaDoc method = methods[j];
124             // Don't process a method that has already been processed
125
// Mark methods as processed that aren't already marked.
126
if (isProcessedAndMarkMethod(method))
127                 continue;
128             ClassBuilder.Parameter parameters[] = getParameters(method.getParameterTypes());
129             String JavaDoc exceptions[] = getClassNames(method.getExceptionTypes());
130             Integer JavaDoc lockLevel = updateMethods.keySet().contains(method.getName()) ? (Integer JavaDoc) updateMethods.get(method.getName()) : new Integer JavaDoc(Lock.LEVEL_READ);
131             int iLevel = lockLevel.intValue();
132             if (iLevel > Lock.LEVEL_READ)
133                 msgWriter.info("update method [" + lockLevel + "]: " + method.getName());
134
135             String JavaDoc retType = typecodeForClass(method.getReturnType());
136             if (retType.equals("void"))
137                 retType = null;
138             builder.makeMethod(method.getModifiers(), method.getName(), parameters, retType
139                     , exceptions, lockLevel.intValue());
140         }
141     }
142
143     private boolean isProcessedAndMarkMethod(Method JavaDoc method) {
144         StringBuffer JavaDoc signatureBuf = new StringBuffer JavaDoc();
145         signatureBuf.append(" public " + typecodeForClass(method.getReturnType()) + " " + method.getName() + "(");
146         Class JavaDoc[] args = method.getParameterTypes();
147         for (int i = 0; i < args.length; i++) {
148             if (i != 0) {
149                 signatureBuf.append(", ");
150             }
151             signatureBuf.append(typecodeForClass(args[i]) + " arg" + i);
152         }
153         signatureBuf.append(")");
154         String JavaDoc signatureStr = signatureBuf.toString();
155         if (!processedMethods.contains(signatureStr)) {
156             msgWriter.debug("Processing method: " + signatureStr);
157             processedMethods.add(signatureStr);
158             return false;
159         } else {
160             return true;
161         }
162     }
163
164     /**
165      Returns the name of the class in the way it is used within resolver code.
166      This is similar to the internal class name with the exception that names of inner
167      classes separate between class levels not by '$' but by '.'.
168      */

169     private String JavaDoc getSourcecodeClassName(String JavaDoc cl) {
170         return cl.replace('$', '.');
171     }
172
173     private String JavaDoc[] getClassNames(Class JavaDoc types[]) {
174         String JavaDoc classNames[] = new String JavaDoc[types.length];
175         for (int i = 0; i < types.length; ++i) {
176             classNames[i] = getSourcecodeClassName(types[i].getName());
177         }
178         return classNames;
179     }
180
181     protected String JavaDoc typecodeForClass(Class JavaDoc cl) {
182         String JavaDoc ret;
183         // array
184

185         if (cl.isArray()) {
186             StringBuffer JavaDoc b = new StringBuffer JavaDoc();
187             while (cl.isArray()) {
188                 b.append("[]");
189                 cl = cl.getComponentType();
190             }
191             b.insert(0, getSourcecodeClassName(cl.getName()));
192             ret = b.toString();
193         } else {
194             // norgetSourcecodeClassName(implementationClass)reference and primitive types
195

196             ret = getSourcecodeClassName(cl.getName());
197         }
198         return ret;
199     }
200
201     private ClassBuilder.Parameter[] getParameters(Class JavaDoc parameterTypes[]) {
202         ClassBuilder.Parameter parameters[] = new ClassBuilder.Parameter[parameterTypes.length];
203         for (int j = 0; j < parameters.length; ++j) {
204             parameters[j] = new ClassBuilder.Parameter(typecodeForClass(parameterTypes[j]), "arg" + j, parameterTypes[j].getName(), 0);
205         }
206         return parameters;
207     }
208 }
209
Popular Tags