use of org.hotswap.agent.annotation.handler.PluginClassFileTransformer in project HotswapAgent by HotswapProjects.
the class HotswapTransformer method transform.
/**
* Main transform method called by Java instrumentation.
* <p/>
* <p>It does not do the instrumentation itself, instead iterates registered transformers and compares
* registration class regexp - if the regexp matches, the classloader is called.
* <p/>
* <p>Note that class bytes may be send to multiple transformers, but the order is not defined.
*
* @see ClassFileTransformer#transform(ClassLoader, String, Class, java.security.ProtectionDomain, byte[])
*/
@Override
public byte[] transform(final ClassLoader classLoader, String className, Class<?> redefiningClass, final ProtectionDomain protectionDomain, byte[] bytes) throws IllegalClassFormatException {
LOGGER.trace("Transform on class '{}' @{} redefiningClass '{}'.", className, classLoader, redefiningClass);
List<ClassFileTransformer> toApply = new LinkedList<>();
List<PluginClassFileTransformer> pluginTransformers = new LinkedList<>();
try {
// call transform on all registered transformers
for (RegisteredTransformersRecord transformerRecord : new LinkedList<RegisteredTransformersRecord>(registeredTransformers.values())) {
if ((className != null && transformerRecord.pattern.matcher(className).matches()) || (redefiningClass != null && transformerRecord.pattern.matcher(redefiningClass.getName()).matches())) {
for (ClassFileTransformer transformer : new LinkedList<ClassFileTransformer>(transformerRecord.transformerList)) {
if (transformer instanceof PluginClassFileTransformer) {
PluginClassFileTransformer pcft = PluginClassFileTransformer.class.cast(transformer);
if (!pcft.isPluginDisabled(classLoader)) {
pluginTransformers.add(pcft);
}
} else {
toApply.add(transformer);
}
}
}
}
} catch (Throwable t) {
LOGGER.error("Error transforming class '" + className + "'.", t);
}
if (!pluginTransformers.isEmpty()) {
pluginTransformers = reduce(classLoader, pluginTransformers, className);
}
if (toApply.isEmpty() && pluginTransformers.isEmpty()) {
LOGGER.trace("No transformers defing for {} ", className);
return bytes;
}
// ensure classloader initialized
ensureClassLoaderInitialized(classLoader, protectionDomain);
try {
byte[] result = bytes;
for (ClassFileTransformer transformer : pluginTransformers) {
LOGGER.trace("Transforming class '" + className + "' with transformer '" + transformer + "' " + "@ClassLoader" + classLoader + ".");
result = transformer.transform(classLoader, className, redefiningClass, protectionDomain, result);
}
for (ClassFileTransformer transformer : toApply) {
LOGGER.trace("Transforming class '" + className + "' with transformer '" + transformer + "' " + "@ClassLoader" + classLoader + ".");
result = transformer.transform(classLoader, className, redefiningClass, protectionDomain, result);
}
return result;
} catch (Throwable t) {
LOGGER.error("Error transforming class '" + className + "'.", t);
}
return bytes;
}
use of org.hotswap.agent.annotation.handler.PluginClassFileTransformer in project HotswapAgent by HotswapProjects.
the class HotswapTransformer method reduce.
LinkedList<PluginClassFileTransformer> reduce(final ClassLoader classLoader, List<PluginClassFileTransformer> pluginCalls, String className) {
LinkedList<PluginClassFileTransformer> reduced = new LinkedList<>();
Map<String, PluginClassFileTransformer> fallbackMap = new HashMap<>();
for (PluginClassFileTransformer pcft : pluginCalls) {
try {
String pluginGroup = pcft.getPluginGroup();
if (pcft.versionMatches(classLoader)) {
if (pluginGroup != null) {
fallbackMap.put(pluginGroup, null);
}
reduced.add(pcft);
} else if (pcft.isFallbackPlugin()) {
if (pluginGroup != null && !fallbackMap.containsKey(pluginGroup)) {
fallbackMap.put(pluginGroup, pcft);
}
}
} catch (Exception e) {
LOGGER.warning("Error evaluating aplicability of plugin", e);
}
}
for (PluginClassFileTransformer pcft : fallbackMap.values()) {
if (pcft != null) {
reduced.add(pcft);
}
}
return reduced;
}
Aggregations