123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- /*
- * Javassist, a Java-bytecode translator toolkit.
- * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. Alternatively, the contents of this file may be used under
- * the terms of the GNU Lesser General Public License Version 2.1 or later,
- * or the Apache License Version 2.0.
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- */
-
- package javassist.tools.rmi;
-
- import javassist.*;
- import java.lang.reflect.Method;
- import java.util.Hashtable;
- import javassist.CtMethod.ConstParameter;
-
- /**
- * A stub-code generator. It is used for producing a proxy class.
- *
- * <p>The proxy class for class A is as follows:
- *
- * <pre>public class A implements Proxy, Serializable {
- * private ObjectImporter importer;
- * private int objectId;
- * public int _getObjectId() { return objectId; }
- * public A(ObjectImporter oi, int id) {
- * importer = oi; objectId = id;
- * }
- *
- * ... the same methods that the original class A declares ...
- * }</pre>
- *
- * <p>Instances of the proxy class is created by an
- * <code>ObjectImporter</code> object.
- */
- public class StubGenerator implements Translator {
- private static final String fieldImporter = "importer";
- private static final String fieldObjectId = "objectId";
- private static final String accessorObjectId = "_getObjectId";
- private static final String sampleClass = "javassist.tools.rmi.Sample";
-
- private ClassPool classPool;
- private Hashtable proxyClasses;
- private CtMethod forwardMethod;
- private CtMethod forwardStaticMethod;
-
- private CtClass[] proxyConstructorParamTypes;
- private CtClass[] interfacesForProxy;
- private CtClass[] exceptionForProxy;
-
- /**
- * Constructs a stub-code generator.
- */
- public StubGenerator() {
- proxyClasses = new Hashtable();
- }
-
- /**
- * Initializes the object.
- * This is a method declared in javassist.Translator.
- *
- * @see javassist.Translator#start(ClassPool)
- */
- public void start(ClassPool pool) throws NotFoundException {
- classPool = pool;
- CtClass c = pool.get(sampleClass);
- forwardMethod = c.getDeclaredMethod("forward");
- forwardStaticMethod = c.getDeclaredMethod("forwardStatic");
-
- proxyConstructorParamTypes
- = pool.get(new String[] { "javassist.tools.rmi.ObjectImporter",
- "int" });
- interfacesForProxy
- = pool.get(new String[] { "java.io.Serializable",
- "javassist.tools.rmi.Proxy" });
- exceptionForProxy
- = new CtClass[] { pool.get("javassist.tools.rmi.RemoteException") };
- }
-
- /**
- * Does nothing.
- * This is a method declared in javassist.Translator.
- * @see javassist.Translator#onLoad(ClassPool,String)
- */
- public void onLoad(ClassPool pool, String classname) {}
-
- /**
- * Returns <code>true</code> if the specified class is a proxy class
- * recorded by <code>makeProxyClass()</code>.
- *
- * @param name a fully-qualified class name
- */
- public boolean isProxyClass(String name) {
- return proxyClasses.get(name) != null;
- }
-
- /**
- * Makes a proxy class. The produced class is substituted
- * for the original class.
- *
- * @param clazz the class referenced
- * through the proxy class.
- * @return <code>false</code> if the proxy class
- * has been already produced.
- */
- public synchronized boolean makeProxyClass(Class clazz)
- throws CannotCompileException, NotFoundException
- {
- String classname = clazz.getName();
- if (proxyClasses.get(classname) != null)
- return false;
- else {
- CtClass ctclazz = produceProxyClass(classPool.get(classname),
- clazz);
- proxyClasses.put(classname, ctclazz);
- modifySuperclass(ctclazz);
- return true;
- }
- }
-
- private CtClass produceProxyClass(CtClass orgclass, Class orgRtClass)
- throws CannotCompileException, NotFoundException
- {
- int modify = orgclass.getModifiers();
- if (Modifier.isAbstract(modify) || Modifier.isNative(modify)
- || !Modifier.isPublic(modify))
- throw new CannotCompileException(orgclass.getName()
- + " must be public, non-native, and non-abstract.");
-
- CtClass proxy = classPool.makeClass(orgclass.getName(),
- orgclass.getSuperclass());
-
- proxy.setInterfaces(interfacesForProxy);
-
- CtField f
- = new CtField(classPool.get("javassist.tools.rmi.ObjectImporter"),
- fieldImporter, proxy);
- f.setModifiers(Modifier.PRIVATE);
- proxy.addField(f, CtField.Initializer.byParameter(0));
-
- f = new CtField(CtClass.intType, fieldObjectId, proxy);
- f.setModifiers(Modifier.PRIVATE);
- proxy.addField(f, CtField.Initializer.byParameter(1));
-
- proxy.addMethod(CtNewMethod.getter(accessorObjectId, f));
-
- proxy.addConstructor(CtNewConstructor.defaultConstructor(proxy));
- CtConstructor cons
- = CtNewConstructor.skeleton(proxyConstructorParamTypes,
- null, proxy);
- proxy.addConstructor(cons);
-
- try {
- addMethods(proxy, orgRtClass.getMethods());
- return proxy;
- }
- catch (SecurityException e) {
- throw new CannotCompileException(e);
- }
- }
-
- private CtClass toCtClass(Class rtclass) throws NotFoundException {
- String name;
- if (!rtclass.isArray())
- name = rtclass.getName();
- else {
- StringBuffer sbuf = new StringBuffer();
- do {
- sbuf.append("[]");
- rtclass = rtclass.getComponentType();
- } while(rtclass.isArray());
- sbuf.insert(0, rtclass.getName());
- name = sbuf.toString();
- }
-
- return classPool.get(name);
- }
-
- private CtClass[] toCtClass(Class[] rtclasses) throws NotFoundException {
- int n = rtclasses.length;
- CtClass[] ctclasses = new CtClass[n];
- for (int i = 0; i < n; ++i)
- ctclasses[i] = toCtClass(rtclasses[i]);
-
- return ctclasses;
- }
-
- /* ms must not be an array of CtMethod. To invoke a method ms[i]
- * on a server, a client must send i to the server.
- */
- private void addMethods(CtClass proxy, Method[] ms)
- throws CannotCompileException, NotFoundException
- {
- CtMethod wmethod;
- for (int i = 0; i < ms.length; ++i) {
- Method m = ms[i];
- int mod = m.getModifiers();
- if (m.getDeclaringClass() != Object.class
- && !Modifier.isFinal(mod))
- if (Modifier.isPublic(mod)) {
- CtMethod body;
- if (Modifier.isStatic(mod))
- body = forwardStaticMethod;
- else
- body = forwardMethod;
-
- wmethod
- = CtNewMethod.wrapped(toCtClass(m.getReturnType()),
- m.getName(),
- toCtClass(m.getParameterTypes()),
- exceptionForProxy,
- body,
- ConstParameter.integer(i),
- proxy);
- wmethod.setModifiers(mod);
- proxy.addMethod(wmethod);
- }
- else if (!Modifier.isProtected(mod)
- && !Modifier.isPrivate(mod))
- // if package method
- throw new CannotCompileException(
- "the methods must be public, protected, or private.");
- }
- }
-
- /**
- * Adds a default constructor to the super classes.
- */
- private void modifySuperclass(CtClass orgclass)
- throws CannotCompileException, NotFoundException
- {
- CtClass superclazz;
- for (;; orgclass = superclazz) {
- superclazz = orgclass.getSuperclass();
- if (superclazz == null)
- break;
-
- try {
- superclazz.getDeclaredConstructor(null);
- break; // the constructor with no arguments is found.
- }
- catch (NotFoundException e) {
- }
-
- superclazz.addConstructor(
- CtNewConstructor.defaultConstructor(superclazz));
- }
- }
- }
|