All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scouter.javassist.tools.rmi.StubGenerator Maven / Gradle / Ivy

There is a newer version: 2.20.0
Show newest version
/*
 * 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 scouter.javassist.tools.rmi;

import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Map;

import scouter.javassist.CannotCompileException;
import scouter.javassist.ClassPool;
import scouter.javassist.CtClass;
import scouter.javassist.CtConstructor;
import scouter.javassist.CtField;
import scouter.javassist.CtMethod;
import scouter.javassist.CtMethod.ConstParameter;
import scouter.javassist.CtNewConstructor;
import scouter.javassist.CtNewMethod;
import scouter.javassist.Modifier;
import scouter.javassist.NotFoundException;
import scouter.javassist.Translator;

/**
 * A stub-code generator.  It is used for producing a proxy class.
 *
 * 

The proxy class for class A is as follows: * *

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 ...
 * }
* *

Instances of the proxy class is created by an * ObjectImporter 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 = "scouter.javassist.tools.rmi.Sample"; private ClassPool classPool; private Map 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 scouter.javassist.Translator. * * @see scouter.javassist.Translator#start(ClassPool) */ @Override 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[] { "scouter.javassist.tools.rmi.ObjectImporter", "int" }); interfacesForProxy = pool.get(new String[] { "java.io.Serializable", "scouter.javassist.tools.rmi.Proxy" }); exceptionForProxy = new CtClass[] { pool.get("scouter.javassist.tools.rmi.RemoteException") }; } /** * Does nothing. * This is a method declared in scouter.javassist.Translator. * @see scouter.javassist.Translator#onLoad(ClassPool,String) */ @Override public void onLoad(ClassPool pool, String classname) {} /** * Returns true if the specified class is a proxy class * recorded by makeProxyClass(). * * @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 false 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; 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("scouter.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)); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy