use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class OsgiEquinoxPlugin method loadClassToTargetClassLoaders.
private boolean loadClassToTargetClassLoaders(CtClass ctClass, URI uri, boolean putToReloadMap) {
List<ClassLoader> targetClassLoaders = getTargetLoaders(ctClass);
if (targetClassLoaders == null) {
LOGGER.trace("Class {} not loaded yet, no need for autoHotswap, skipped file {}", ctClass.getName());
return false;
}
LOGGER.debug("Class {} will be reloaded from URL {}", ctClass.getName(), uri);
ClassLoader classLoader = null;
try {
byte[] bytecode = ctClass.toBytecode();
for (int i = 0; i < targetClassLoaders.size(); i++) {
classLoader = targetClassLoaders.get(i);
Class clazz = classLoader.loadClass(ctClass.getName());
if (putToReloadMap) {
synchronized (reloadMap) {
reloadMap.put(clazz, bytecode);
}
}
}
} catch (ClassNotFoundException e) {
LOGGER.warning("OsgiEquinox tries to reload class {}, which is not known to Equinox classLoader {}.", ctClass.getName(), classLoader);
return false;
} catch (Exception e) {
LOGGER.warning("loadClassToTargetClassLoaders() exception : {}", e.getMessage());
return false;
}
return true;
}
use of org.hotswap.agent.javassist.CtClass 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;
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class WatchEventCommand method onWatchEvent.
/**
* Run plugin the method.
*/
public void onWatchEvent(PluginAnnotation<T> pluginAnnotation, WatchFileEvent event, ClassLoader classLoader) {
final T annot = pluginAnnotation.getAnnotation();
Object plugin = pluginAnnotation.getPlugin();
// we may need to crate CtClass on behalf of the client and close it after invocation.
CtClass ctClass = null;
// class file regexp
if (watchEventDTO.isClassFileEvent()) {
try {
// TODO creating class only to check name may slow down if lot of handlers is in use.
ctClass = createCtClass(event.getURI(), classLoader);
} catch (Exception e) {
LOGGER.error("Unable create CtClass for URI '{}'.", e, event.getURI());
return;
}
// unable to create CtClass or it's name does not match
if (ctClass == null || !ctClass.getName().matches(watchEventDTO.getClassNameRegexp()))
return;
}
LOGGER.debug("Executing resource changed method {} on class {} for event {}", pluginAnnotation.getMethod().getName(), plugin.getClass().getName(), event);
List<Object> args = new ArrayList<Object>();
for (Class<?> type : pluginAnnotation.getMethod().getParameterTypes()) {
if (type.isAssignableFrom(ClassLoader.class)) {
args.add(classLoader);
} else if (type.isAssignableFrom(URI.class)) {
args.add(event.getURI());
} else if (type.isAssignableFrom(URL.class)) {
try {
args.add(event.getURI().toURL());
} catch (MalformedURLException e) {
LOGGER.error("Unable to convert URI '{}' to URL.", e, event.getURI());
return;
}
} else if (type.isAssignableFrom(ClassPool.class)) {
args.add(ClassPool.getDefault());
} else if (type.isAssignableFrom(FileEvent.class)) {
args.add(event.getEventType());
} else if (watchEventDTO.isClassFileEvent() && type.isAssignableFrom(CtClass.class)) {
args.add(ctClass);
} else if (watchEventDTO.isClassFileEvent() && type.isAssignableFrom(String.class)) {
args.add(ctClass != null ? ctClass.getName() : null);
} else {
LOGGER.error("Unable to call method {} on plugin {}. Method parameter type {} is not recognized.", pluginAnnotation.getMethod().getName(), plugin.getClass().getName(), type);
return;
}
}
try {
pluginAnnotation.getMethod().invoke(plugin, args.toArray());
// close CtClass if created from here
if (ctClass != null) {
ctClass.detach();
}
} catch (IllegalAccessException e) {
LOGGER.error("IllegalAccessException in method {} on plugin {}", e, pluginAnnotation.getMethod().getName(), plugin.getClass().getName());
} catch (InvocationTargetException e) {
LOGGER.error("InvocationTargetException in method {} on plugin {}", e, pluginAnnotation.getMethod().getName(), plugin.getClass().getName());
}
}
use of org.hotswap.agent.javassist.CtClass in project HotswapAgent by HotswapProjects.
the class BeanDeploymentArchiveTransformer method transform.
/**
* Basic WeldBeanDeploymentArchive transformation.
*
* @param clazz
* @param classPool
* @throws NotFoundException
* @throws CannotCompileException
*/
@OnClassLoadEvent(classNameRegexp = "org.jboss.weld.environment.deployment.WeldBeanDeploymentArchive")
public static void transform(CtClass clazz, ClassPool classPool) throws NotFoundException, CannotCompileException {
CtClass[] constructorParams = new CtClass[] { classPool.get("java.lang.String"), classPool.get("java.util.Collection"), classPool.get("org.jboss.weld.bootstrap.spi.BeansXml"), classPool.get("java.util.Set") };
StringBuilder src = new StringBuilder("{");
src.append(PluginManagerInvoker.buildInitializePlugin(WeldPlugin.class));
src.append(PluginManagerInvoker.buildCallPluginMethod(WeldPlugin.class, "init"));
src.append("org.hotswap.agent.plugin.weld.command.BeanClassRefreshAgent.registerArchive(getClass().getClassLoader(), this, null);");
src.append("}");
CtConstructor declaredConstructor = clazz.getDeclaredConstructor(constructorParams);
declaredConstructor.insertAfter(src.toString());
LOGGER.debug("Class '{}' patched with BDA registration.", clazz.getName());
}
Aggregations