use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class EnhancerProxyCreater method buildProxyCallbackClass.
/**
* Creates a Cglib Callback which is a subclass of DetachableBeanHolder
*
* @param cglibPackage
* Cglib Package name
* @param cp
* @return Class of the Enhancer Proxy callback
* @throws CannotCompileException
* @throws NotFoundException
*/
private Class<?> buildProxyCallbackClass(String cglibPackage, ClassPool cp) throws CannotCompileException, NotFoundException {
String proxyPackage = cglibPackage + "proxy.";
CtClass ct = cp.makeClass("HotswapSpringCallback" + getClassSuffix(cglibPackage));
ct.setSuperclass(cp.get(DetachableBeanHolder.class.getName()));
ct.addInterface(cp.get(proxyPackage + "MethodInterceptor"));
String rawBody = //
" public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args, {0}MethodProxy proxy) throws Throwable {" + //
" if(method != null && method.getName().equals(\"finalize\") && method.getParameterTypes().length == 0)" + //
" return null;" + //
" return proxy.invoke(getBean(), args);" + " }";
String body = rawBody.replaceAll("\\{0\\}", proxyPackage);
CtMethod m = CtNewMethod.make(body, ct);
ct.addMethod(m);
return ct.toClass(loader, pd);
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class ComponentScanWithWildcardsTest method copyClassFile.
public static File copyClassFile(Class<?> clazz, String newName) throws Exception {
String directoryName = clazz.getClassLoader().getResource("").getPath();
ClassPool classPool = new ClassPool();
classPool.appendClassPath(new LoaderClassPath(clazz.getClassLoader()));
CtClass ctClass = classPool.getAndRename(clazz.getName(), newName);
ctClass.writeFile(directoryName);
File file = new File(directoryName + File.separatorChar + newName.replace('.', File.separatorChar) + ".class");
assertTrue(file.exists());
return file;
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class CtClassJavaProxyGenerator method generateClassFile.
/**
* Generate a class file for the proxy class. This method drives the class file generation process.
*/
private byte[] generateClassFile() {
/*
* ============================================================ Step 1: Assemble ProxyMethod objects for all
* methods to generate proxy dispatching code for.
*/
/*
* Record that proxy methods are needed for the hashCode, equals, and toString methods of java.lang.Object. This
* is done before the methods from the proxy interfaces so that the methods from java.lang.Object take
* precedence over duplicate methods in the proxy interfaces.
*/
addProxyMethod(f.hashCodeMethod, f.oclp);
addProxyMethod(f.equalsMethod, f.oclp);
addProxyMethod(f.toStringMethod, f.oclp);
Collection<CtClass> iWithSuper = new HashSet<>();
addInterfacesWithSuperInterfaces(iWithSuper, interfaces);
/*
* Now record all of the methods from the proxy interfaces, giving earlier interfaces precedence over later ones
* with duplicate methods.
*/
for (CtClass intf : iWithSuper) {
for (CtMethod m : intf.getDeclaredMethods()) {
addProxyMethod(m, intf);
}
}
/*
* For each set of proxy methods with the same signature, verify that the methods' return types are compatible.
*/
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
checkReturnTypes(sigmethods);
}
/*
* ============================================================ Step 2: Assemble FieldInfo and MethodInfo
* structs for all of fields and methods in the class we are generating.
*/
try {
methods.add(generateConstructor());
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
// add static field for method's Method object
fields.add(new FieldInfo(pm.methodFieldName, "Ljava/lang/reflect/Method;", ACC_PRIVATE | ACC_STATIC));
}
}
fields.add(new FieldInfo(initFieldName, "Z", ACC_PRIVATE | ACC_STATIC));
for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
for (ProxyMethod pm : sigmethods) {
// generate code for proxy method and add it
methods.add(pm.generateMethod());
}
}
methods.add(generateStaticInitializer());
methods.add(generateStaticInitializerCaller());
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
if (methods.size() > 65535) {
throw new IllegalArgumentException("method limit exceeded");
}
if (fields.size() > 65535) {
throw new IllegalArgumentException("field limit exceeded");
}
/*
* ============================================================ Step 3: Write the final class file.
*/
/*
* Make sure that constant pool indexes are reserved for the following items before starting to write the final
* class file.
*/
cp.getClass(dotToSlash(className));
cp.getClass(superclassName);
for (CtClass intf : interfaces) {
cp.getClass(dotToSlash(intf.getName()));
}
/*
* Disallow new constant pool additions beyond this point, since we are about to write the final constant pool
* table.
*/
cp.setReadOnly();
ByteArrayOutputStream bout = new ByteArrayOutputStream();
DataOutputStream dout = new DataOutputStream(bout);
try {
/*
* Write all the items of the "ClassFile" structure. See JVMS section 4.1.
*/
// u4 magic;
dout.writeInt(0xCAFEBABE);
// u2 minor_version;
dout.writeShort(CLASSFILE_MINOR_VERSION);
// u2 major_version;
dout.writeShort(CLASSFILE_MAJOR_VERSION);
// (write constant pool)
cp.write(dout);
// u2 access_flags;
dout.writeShort(accessFlags);
// u2 this_class;
dout.writeShort(cp.getClass(dotToSlash(className)));
// u2 super_class;
dout.writeShort(cp.getClass(superclassName));
// u2 interfaces_count;
dout.writeShort(interfaces.length);
// u2 interfaces[interfaces_count];
for (CtClass intf : interfaces) {
dout.writeShort(cp.getClass(dotToSlash(intf.getName())));
}
// u2 fields_count;
dout.writeShort(fields.size());
// field_info fields[fields_count];
for (FieldInfo f : fields) {
f.write(dout);
}
// u2 methods_count;
dout.writeShort(methods.size());
// method_info methods[methods_count];
for (MethodInfo m : methods) {
m.write(dout);
}
// u2 attributes_count;
// (no ClassFile attributes for proxy classes)
dout.writeShort(0);
} catch (IOException e) {
throw new InternalError("unexpected I/O Exception");
}
return bout.toByteArray();
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class WebappLoaderTransformer method patchStandardRoot.
/**
* Resource lookup for Tomcat 8x.
*
* Before the resource is handled by Tomcat, try to get extraResource handled by the plugin.
*/
@OnClassLoadEvent(classNameRegexp = "org.apache.catalina.webresources.StandardRoot")
public static void patchStandardRoot(ClassPool classPool, CtClass ctClass) throws NotFoundException, CannotCompileException, ClassNotFoundException {
CtClass ctFileResource = classPool.get("org.apache.catalina.webresources.FileResource");
CtConstructor ctFileResourceConstructor = ctFileResource.getConstructors()[0];
CtClass[] constructorTypes = ctFileResourceConstructor.getParameterTypes();
String constrParams;
if (constructorTypes.length == 4)
constrParams = "this, path, file, false";
else if (constructorTypes.length == 5)
constrParams = "this, path, file, false, null";
else {
LOGGER.warning("org.apache.catalina.webresources.FileResource unknown constructor. Tomcat plugin will not work properly.");
return;
}
try {
ctClass.getDeclaredMethod("getResourceInternal", new CtClass[] { classPool.get(String.class.getName()), CtPrimitiveType.booleanType }).insertBefore("java.io.File file = " + TomcatPlugin.class.getName() + ".getExtraResourceFile(this, path);" + "if (file != null) return new org.apache.catalina.webresources.FileResource(" + constrParams + ");");
} catch (NotFoundException e) {
LOGGER.warning("org.apache.catalina.webresources.StandardRoot does not contain getResourceInternal method. Tomcat plugin will not work properly.");
return;
}
// if getResources() should contain extraClasspath, expand the original returned array and prepend extraClasspath result
try {
ctClass.getDeclaredMethod("getResources", new CtClass[] { classPool.get(String.class.getName()), CtPrimitiveType.booleanType }).insertAfter("java.io.File file = " + TomcatPlugin.class.getName() + ".getExtraResourceFile(this, path);" + "if (file != null) {" + "org.apache.catalina.WebResource[] ret = new org.apache.catalina.WebResource[$_.length + 1];" + "ret[0] = new org.apache.catalina.webresources.FileResource(" + constrParams + ");" + "java.lang.System.arraycopy($_, 0, ret, 1, $_.length);" + "return ret;" + "} else {return $_;}");
} catch (NotFoundException e) {
LOGGER.warning("org.apache.catalina.webresources.StandardRoot does not contain getResourceInternal method. Tomcat plugin will not work properly.");
return;
}
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class PluginCache method scanPlugins.
public Set<CtClass> scanPlugins(ClassLoader classLoader) throws IOException {
if (!pluginDefs.containsKey(classLoader)) {
synchronized (pluginDefs) {
if (!pluginDefs.containsKey(classLoader)) {
final Set<CtClass> plugins = new HashSet<CtClass>();
final ClassPool classPool = ClassPool.getDefault();
scanner.scan(getClass().getClassLoader(), PLUGIN_PATH, new ScannerVisitor() {
@Override
public void visit(InputStream file) throws IOException {
plugins.add(classPool.makeClass(file));
}
});
}
}
}
return pluginDefs.get(classLoader);
}
Aggregations