KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > rmi > StubGenerator


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 Shigeru Chiba. All Rights Reserved.
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. Alternatively, the contents of this file may be used under
8  * the terms of the GNU Lesser General Public License Version 2.1 or later.
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  */

15
16 package javassist.rmi;
17
18 import javassist.*;
19 import java.lang.reflect.Method JavaDoc;
20 import java.util.Hashtable JavaDoc;
21 import javassist.CtMethod.ConstParameter;
22
23 /**
24  * A stub-code generator. It is used for producing a proxy class.
25  *
26  * <p>The proxy class for class A is as follows:
27  *
28  * <ul><pre>public class A implements Proxy, Serializable {
29  * private ObjectImporter importer;
30  * private int objectId;
31  * public int _getObjectId() { return objectId; }
32  * public A(ObjectImporter oi, int id) {
33  * importer = oi; objectId = id;
34  * }
35  *
36  * ... the same methods that the original class A declares ...
37  * }</pre></ul>
38  *
39  * <p>Instances of the proxy class is created by an
40  * <code>ObjectImporter</code> object.
41  */

42 public class StubGenerator implements Translator {
43     private static final String JavaDoc fieldImporter = "importer";
44     private static final String JavaDoc fieldObjectId = "objectId";
45     private static final String JavaDoc accessorObjectId = "_getObjectId";
46     private static final String JavaDoc sampleClass = "javassist.rmi.Sample";
47
48     private ClassPool classPool;
49     private Hashtable JavaDoc proxyClasses;
50     private CtMethod forwardMethod;
51     private CtMethod forwardStaticMethod;
52
53     private CtClass[] proxyConstructorParamTypes;
54     private CtClass[] interfacesForProxy;
55     private CtClass[] exceptionForProxy;
56
57     /**
58      * Constructs a stub-code generator.
59      */

60     public StubGenerator() {
61         proxyClasses = new Hashtable JavaDoc();
62     }
63
64     /**
65      * Initializes the object.
66      * This is a method declared in javassist.Translator.
67      *
68      * @see javassist.Translator#start(ClassPool)
69      */

70     public void start(ClassPool pool) throws NotFoundException {
71         classPool = pool;
72         CtClass c = pool.get(sampleClass);
73         forwardMethod = c.getDeclaredMethod("forward");
74         forwardStaticMethod = c.getDeclaredMethod("forwardStatic");
75
76         proxyConstructorParamTypes
77             = pool.get(new String JavaDoc[] { "javassist.rmi.ObjectImporter",
78                                          "int" });
79         interfacesForProxy
80             = pool.get(new String JavaDoc[] { "java.io.Serializable",
81                                          "javassist.rmi.Proxy" });
82         exceptionForProxy
83             = new CtClass[] { pool.get("javassist.rmi.RemoteException") };
84     }
85
86     /**
87      * Does nothing.
88      * This is a method declared in javassist.Translator.
89      * @see javassist.Translator#onLoad(ClassPool,String)
90      */

91     public void onLoad(ClassPool pool, String JavaDoc classname) {}
92
93     /**
94      * Returns <code>true</code> if the specified class is a proxy class
95      * recorded by <code>makeProxyClass()</code>.
96      *
97      * @param name a fully-qualified class name
98      */

99     public boolean isProxyClass(String JavaDoc name) {
100         return proxyClasses.get(name) != null;
101     }
102
103     /**
104      * Makes a proxy class. The produced class is substituted
105      * for the original class.
106      *
107      * @param clazz the class referenced
108      * through the proxy class.
109      * @return <code>false</code> if the proxy class
110      * has been already produced.
111      */

112     public synchronized boolean makeProxyClass(Class JavaDoc clazz)
113         throws CannotCompileException, NotFoundException
114     {
115         String JavaDoc classname = clazz.getName();
116         if (proxyClasses.get(classname) != null)
117             return false;
118         else {
119             CtClass ctclazz = produceProxyClass(classPool.get(classname),
120                                                 clazz);
121             proxyClasses.put(classname, ctclazz);
122             modifySuperclass(ctclazz);
123             return true;
124         }
125     }
126
127     private CtClass produceProxyClass(CtClass orgclass, Class JavaDoc orgRtClass)
128         throws CannotCompileException, NotFoundException
129     {
130         int modify = orgclass.getModifiers();
131         if (Modifier.isAbstract(modify) || Modifier.isNative(modify)
132             || !Modifier.isPublic(modify))
133             throw new CannotCompileException(orgclass.getName()
134                         + " must be public, non-native, and non-abstract.");
135
136         CtClass proxy = classPool.makeClass(orgclass.getName(),
137                                               orgclass.getSuperclass());
138
139         proxy.setInterfaces(interfacesForProxy);
140
141         CtField f
142             = new CtField(classPool.get("javassist.rmi.ObjectImporter"),
143                           fieldImporter, proxy);
144         f.setModifiers(Modifier.PRIVATE);
145         proxy.addField(f, CtField.Initializer.byParameter(0));
146
147         f = new CtField(CtClass.intType, fieldObjectId, proxy);
148         f.setModifiers(Modifier.PRIVATE);
149         proxy.addField(f, CtField.Initializer.byParameter(1));
150
151         proxy.addMethod(CtNewMethod.getter(accessorObjectId, f));
152
153         proxy.addConstructor(CtNewConstructor.defaultConstructor(proxy));
154         CtConstructor cons
155             = CtNewConstructor.skeleton(proxyConstructorParamTypes,
156                                         null, proxy);
157         proxy.addConstructor(cons);
158
159         try {
160             addMethods(proxy, orgRtClass.getMethods());
161             return proxy;
162         }
163         catch (SecurityException JavaDoc e) {
164             throw new CannotCompileException(e);
165         }
166     }
167
168     private CtClass toCtClass(Class JavaDoc rtclass) throws NotFoundException {
169         String JavaDoc name;
170         if (!rtclass.isArray())
171             name = rtclass.getName();
172         else {
173             StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
174             do {
175                 sbuf.append("[]");
176                 rtclass = rtclass.getComponentType();
177             } while(rtclass.isArray());
178             sbuf.insert(0, rtclass.getName());
179             name = sbuf.toString();
180         }
181             
182         return classPool.get(name);
183     }
184
185     private CtClass[] toCtClass(Class JavaDoc[] rtclasses) throws NotFoundException {
186         int n = rtclasses.length;
187         CtClass[] ctclasses = new CtClass[n];
188         for (int i = 0; i < n; ++i)
189             ctclasses[i] = toCtClass(rtclasses[i]);
190
191         return ctclasses;
192     }
193
194     /* ms must not be an array of CtMethod. To invoke a method ms[i]
195      * on a server, a client must send i to the server.
196      */

197     private void addMethods(CtClass proxy, Method JavaDoc[] ms)
198         throws CannotCompileException, NotFoundException
199     {
200         CtMethod wmethod;
201         for (int i = 0; i < ms.length; ++i) {
202             Method JavaDoc m = ms[i];
203             int mod = m.getModifiers();
204             if (m.getDeclaringClass() != Object JavaDoc.class
205                         && !Modifier.isFinal(mod))
206                 if (Modifier.isPublic(mod)) {
207                     CtMethod body;
208                     if (Modifier.isStatic(mod))
209                         body = forwardStaticMethod;
210                     else
211                         body = forwardMethod;
212
213                     wmethod
214                         = CtNewMethod.wrapped(toCtClass(m.getReturnType()),
215                                               m.getName(),
216                                               toCtClass(m.getParameterTypes()),
217                                               exceptionForProxy,
218                                               body,
219                                               ConstParameter.integer(i),
220                                               proxy);
221                     wmethod.setModifiers(mod);
222                     proxy.addMethod(wmethod);
223                 }
224                 else if (!Modifier.isProtected(mod)
225                          && !Modifier.isPrivate(mod))
226                     // if package method
227
throw new CannotCompileException(
228                         "the methods must be public, protected, or private.");
229         }
230     }
231
232     /**
233      * Adds a default constructor to the super classes.
234      */

235     private void modifySuperclass(CtClass orgclass)
236         throws CannotCompileException, NotFoundException
237     {
238         CtClass superclazz;
239         for (;; orgclass = superclazz) {
240             superclazz = orgclass.getSuperclass();
241             if (superclazz == null)
242                 break;
243
244             String JavaDoc name = superclazz.getName();
245             try {
246                 superclazz.getDeclaredConstructor(null);
247                 break; // the constructor with no arguments is found.
248
}
249             catch (NotFoundException e) {
250             }
251
252             superclazz.addConstructor(
253                         CtNewConstructor.defaultConstructor(superclazz));
254         }
255     }
256 }
257
Popular Tags