use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.
the class TransformNewClass method transform.
/**
* Modifies a sequence of
* NEW classname
* DUP
* ...
* INVOKESPECIAL classname:method
*/
public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws CannotCompileException {
int index;
int c = iterator.byteAt(pos);
if (c == NEW) {
index = iterator.u16bitAt(pos + 1);
if (cp.getClassInfo(index).equals(classname)) {
if (iterator.byteAt(pos + 3) != DUP)
throw new CannotCompileException("NEW followed by no DUP was found");
if (newClassIndex == 0)
newClassIndex = cp.addClassInfo(newClassName);
iterator.write16bit(newClassIndex, pos + 1);
++nested;
}
} else if (c == INVOKESPECIAL) {
index = iterator.u16bitAt(pos + 1);
int typedesc = cp.isConstructor(classname, index);
if (typedesc != 0 && nested > 0) {
int nt = cp.getMethodrefNameAndType(index);
if (newMethodNTIndex != nt) {
newMethodNTIndex = nt;
newMethodIndex = cp.addMethodrefInfo(newClassIndex, nt);
}
iterator.write16bit(newMethodIndex, pos + 1);
--nested;
}
}
return pos;
}
use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.
the class ELResolverPlugin method patchJBossEl.
/*
* JBossEL has weak reference cache. Values are stored in ThreadGroupContext cache, that must be flushed from appropriate thread.
* Therefore we must create request for cleanup cache in PURGE_CLASS_CACHE_METHOD and own cleanup is executed indirectly when
* application calls getBeanProperty(...).
*/
private static void patchJBossEl(CtClass ctClass) {
try {
ctClass.addField(new CtField(CtClass.booleanType, "$$ha$purgeRequested", ctClass), CtField.Initializer.constant(false));
ctClass.addMethod(CtNewMethod.make("public void " + PURGE_CLASS_CACHE_METHOD_NAME + "(java.lang.ClassLoader classLoader) {" + "$$ha$purgeRequested=true;" + "}", ctClass));
try {
CtMethod mGetBeanProperty = ctClass.getDeclaredMethod("getBeanProperty");
mGetBeanProperty.insertBefore("if($$ha$purgeRequested) {" + "$$ha$purgeRequested=false;" + "java.lang.reflect.Method meth = javax.el.BeanELResolver.SoftConcurrentHashMap.class.getDeclaredMethod(\"$$ha$createNewInstance\", null);" + "properties = (javax.el.BeanELResolver.SoftConcurrentHashMap) meth.invoke(properties, null);" + "}");
} catch (NotFoundException e) {
LOGGER.debug("FIXME : checkJBoss_3_0_EL() 'getBeanProperty(...)' not found in javax.el.BeanELResolver.");
}
} catch (CannotCompileException e) {
LOGGER.error("patchJBossEl() exception {}", e.getMessage());
}
}
use of org.hotswap.agent.javassist.CannotCompileException in project HotswapAgent by HotswapProjects.
the class PluginClassFileTransformer method transform.
/**
* Transformation callback as registered in initMethod:
* hotswapTransformer.registerTransformer(). Resolve method parameters to
* actual values, provide convenience parameters of javassist to streamline
* the transformation.
*/
private static byte[] transform(PluginManager pluginManager, PluginAnnotation<OnClassLoadEvent> pluginAnnotation, ClassLoader classLoader, String className, Class<?> redefiningClass, ProtectionDomain protectionDomain, byte[] bytes) {
LOGGER.trace("Transforming.... '{}' using: '{}'", className, pluginAnnotation);
// skip synthetic classes
if (pluginAnnotation.getAnnotation().skipSynthetic()) {
if (isSyntheticClass(className) || (redefiningClass != null && redefiningClass.isSynthetic())) {
return bytes;
}
}
// skip anonymous class
if (pluginAnnotation.getAnnotation().skipAnonymous()) {
if (className.matches("\\$\\d+$")) {
return bytes;
}
}
// ensure classloader initiated
if (classLoader != null) {
pluginManager.initClassLoader(classLoader, protectionDomain);
}
// default result
byte[] result = bytes;
// we may need to crate CtClass on behalf of the client and close it
// after invocation.
CtClass ctClass = null;
List<Object> args = new ArrayList<Object>();
for (Class<?> type : pluginAnnotation.getMethod().getParameterTypes()) {
if (type.isAssignableFrom(ClassLoader.class)) {
args.add(classLoader);
} else if (type.isAssignableFrom(String.class)) {
args.add(className);
} else if (type.isAssignableFrom(Class.class)) {
args.add(redefiningClass);
} else if (type.isAssignableFrom(ProtectionDomain.class)) {
args.add(protectionDomain);
} else if (type.isAssignableFrom(byte[].class)) {
args.add(bytes);
} else if (type.isAssignableFrom(ClassPool.class)) {
ClassPool classPool = new ClassPool();
classPool.appendSystemPath();
LOGGER.trace("Adding loader classpath " + classLoader);
classPool.appendClassPath(new LoaderClassPath(classLoader));
args.add(classPool);
} else if (type.isAssignableFrom(CtClass.class)) {
try {
ctClass = createCtClass(bytes, classLoader);
args.add(ctClass);
} catch (IOException e) {
LOGGER.error("Unable create CtClass for '" + className + "'.", e);
return result;
}
} else if (type.isAssignableFrom(LoadEvent.class)) {
args.add(redefiningClass == null ? LoadEvent.DEFINE : LoadEvent.REDEFINE);
} else if (type.isAssignableFrom(AppClassLoaderExecutor.class)) {
args.add(new AppClassLoaderExecutor(classLoader, protectionDomain));
} else {
LOGGER.error("Unable to call init method on plugin '" + pluginAnnotation.getPluginClass() + "'." + " Method parameter type '" + type + "' is not recognized for @Init annotation.");
return result;
}
}
try {
// call method on plugin (or if plugin null -> static method)
Object resultObject = pluginAnnotation.getMethod().invoke(pluginAnnotation.getPlugin(), args.toArray());
if (resultObject == null) {
// Ok, nothing has changed
} else if (resultObject instanceof byte[]) {
result = (byte[]) resultObject;
} else if (resultObject instanceof CtClass) {
result = ((CtClass) resultObject).toBytecode();
// instance than we created (it is closed elsewhere)
if (resultObject != ctClass) {
((CtClass) resultObject).detach();
}
} else {
LOGGER.error("Unknown result of @OnClassLoadEvent method '" + result.getClass().getName() + "'.");
}
// close CtClass if created from here
if (ctClass != null) {
// if result not set from the method, use class
if (resultObject == null) {
result = ctClass.toBytecode();
}
ctClass.detach();
}
} catch (IllegalAccessException e) {
LOGGER.error("IllegalAccessException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
} catch (InvocationTargetException e) {
LOGGER.error("InvocationTargetException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
} catch (CannotCompileException e) {
LOGGER.error("Cannot compile class after manipulation on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
} catch (IOException e) {
LOGGER.error("IOException in transform method on plugin '" + pluginAnnotation.getPluginClass() + "' class '" + className + "'.", e);
}
return result;
}
Aggregations