use of org.hotswap.agent.javassist.CtConstructor in project HotswapAgent by HotswapProjects.
the class ClassInitPlugin method patch.
@OnClassLoadEvent(classNameRegexp = ".*", events = LoadEvent.REDEFINE)
public static void patch(final CtClass ctClass, final ClassLoader classLoader, final Class<?> originalClass) throws IOException, CannotCompileException, NotFoundException {
if (isSyntheticClass(originalClass)) {
return;
}
final String className = ctClass.getName();
try {
CtMethod origMethod = ctClass.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD);
ctClass.removeMethod(origMethod);
} catch (org.hotswap.agent.javassist.NotFoundException ex) {
// swallow
}
CtConstructor clinit = ctClass.getClassInitializer();
if (clinit != null) {
LOGGER.debug("Adding __ha_clinit to class: {}", className);
CtConstructor haClinit = new CtConstructor(clinit, ctClass, null);
haClinit.getMethodInfo().setName(HOTSWAP_AGENT_CLINIT_METHOD);
haClinit.setModifiers(Modifier.PUBLIC | Modifier.STATIC);
ctClass.addConstructor(haClinit);
final boolean[] reinitializeStatics = new boolean[] { false };
haClinit.instrument(new ExprEditor() {
public void edit(FieldAccess f) throws CannotCompileException {
try {
if (f.isStatic() && f.isWriter()) {
Field originalField = null;
try {
originalField = originalClass.getDeclaredField(f.getFieldName());
} catch (NoSuchFieldException e) {
LOGGER.debug("New field will be initialized {}", f.getFieldName());
reinitializeStatics[0] = true;
}
if (originalField != null) {
// ENUM$VALUES is last in enumeration
if (originalClass.isEnum() && "ENUM$VALUES".equals(f.getFieldName())) {
if (reinitializeStatics[0]) {
LOGGER.debug("New field will be initialized {}", f.getFieldName());
} else {
reinitializeStatics[0] = checkOldEnumValues(ctClass, originalClass);
}
} else {
LOGGER.debug("Skipping old field {}", f.getFieldName());
f.replace("{}");
}
}
}
} catch (Exception e) {
LOGGER.error("Patching __ha_clinit method failed.", e);
}
}
});
if (reinitializeStatics[0]) {
PluginManager.getInstance().getScheduler().scheduleCommand(new Command() {
@Override
public void executeCommand() {
try {
Class<?> clazz = classLoader.loadClass(className);
Method m = clazz.getDeclaredMethod(HOTSWAP_AGENT_CLINIT_METHOD, new Class[] {});
if (m != null) {
m.invoke(null, new Object[] {});
}
} catch (Exception e) {
LOGGER.error("Error initializing redefined class {}", e, className);
} finally {
reloadFlag = false;
}
}
}, // Hack : init should be done after dependant class redefinition. Since the class can
150);
// be proxied by syntetic proxy, the class init must be scheduled after proxy redefinition.
// Currently proxy redefinition (in ProxyPlugin) is scheduled with 100ms delay, therefore
// the class init must be scheduled after it.
} else {
reloadFlag = false;
}
}
}
use of org.hotswap.agent.javassist.CtConstructor in project HotswapAgent by HotswapProjects.
the class CtClassSignature method getValue.
@Override
public String getValue() throws Exception {
List<String> strings = new ArrayList<>();
if (hasElement(ClassSignatureElement.METHOD)) {
boolean usePrivateMethod = hasElement(ClassSignatureElement.METHOD_PRIVATE);
boolean useStaticMethod = hasElement(ClassSignatureElement.METHOD_STATIC);
for (CtMethod method : ctClass.getDeclaredMethods()) {
if (!usePrivateMethod && Modifier.isPrivate(method.getModifiers()))
continue;
if (!useStaticMethod && Modifier.isStatic(method.getModifiers()))
continue;
strings.add(getMethodString(method));
}
}
if (hasElement(ClassSignatureElement.CONSTRUCTOR)) {
boolean usePrivateConstructor = hasElement(ClassSignatureElement.CONSTRUCTOR_PRIVATE);
for (CtConstructor method : ctClass.getDeclaredConstructors()) {
if (!usePrivateConstructor && Modifier.isPrivate(method.getModifiers()))
continue;
strings.add(getConstructorString(method));
}
}
if (hasElement(ClassSignatureElement.CLASS_ANNOTATION)) {
strings.add(annotationToString(ctClass.getAvailableAnnotations()));
}
if (hasElement(ClassSignatureElement.INTERFACES)) {
for (CtClass iClass : ctClass.getInterfaces()) {
strings.add(iClass.getName());
}
}
if (hasElement(ClassSignatureElement.SUPER_CLASS)) {
if (ctClass.getSuperclass() != null && !ctClass.getSuperclass().getName().equals(Object.class.getName()))
strings.add(ctClass.getSuperclass().getName());
}
if (hasElement(ClassSignatureElement.FIELD)) {
boolean useStaticField = hasElement(ClassSignatureElement.FIELD_STATIC);
boolean useFieldAnnotation = hasElement(ClassSignatureElement.FIELD_ANNOTATION);
for (CtField field : ctClass.getDeclaredFields()) {
if (!useStaticField && Modifier.isStatic(field.getModifiers()))
continue;
String fieldSignature = field.getType().getName() + " " + field.getName();
if (useFieldAnnotation) {
fieldSignature += annotationToString(field.getAvailableAnnotations());
}
strings.add(fieldSignature + ";");
}
}
Collections.sort(strings);
StringBuilder strBuilder = new StringBuilder();
for (String methodString : strings) {
strBuilder.append(methodString);
}
return strBuilder.toString();
}
use of org.hotswap.agent.javassist.CtConstructor 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.CtConstructor in project HotswapAgent by HotswapProjects.
the class Javac method compileBody.
/**
* Compiles a method (or constructor) body.
*
* @param src a single statement or a block.
* If null, this method produces a body returning zero or null.
*/
public Bytecode compileBody(CtBehavior method, String src) throws CompileError {
try {
int mod = method.getModifiers();
recordParams(method.getParameterTypes(), Modifier.isStatic(mod));
CtClass rtype;
if (method instanceof CtMethod) {
gen.setThisMethod((CtMethod) method);
rtype = ((CtMethod) method).getReturnType();
} else
rtype = CtClass.voidType;
recordReturnType(rtype, false);
boolean isVoid = rtype == CtClass.voidType;
if (src == null)
makeDefaultBody(bytecode, rtype);
else {
Parser p = new Parser(new Lex(src));
SymbolTable stb = new SymbolTable(stable);
Stmnt s = p.parseStatement(stb);
if (p.hasMore())
throw new CompileError("the method/constructor body must be surrounded by {}");
boolean callSuper = false;
if (method instanceof CtConstructor)
callSuper = !((CtConstructor) method).isClassInitializer();
gen.atMethodBody(s, callSuper, isVoid);
}
return bytecode;
} catch (NotFoundException e) {
throw new CompileError(e.toString());
}
}
use of org.hotswap.agent.javassist.CtConstructor in project HotswapAgent by HotswapProjects.
the class Expr method where.
/**
* Returns the constructor or method containing the expression.
*/
public CtBehavior where() {
MethodInfo mi = thisMethod;
CtBehavior[] cb = thisClass.getDeclaredBehaviors();
for (int i = cb.length - 1; i >= 0; --i) if (cb[i].getMethodInfo2() == mi)
return cb[i];
CtConstructor init = thisClass.getClassInitializer();
if (init != null && init.getMethodInfo2() == mi)
return init;
/* getDeclaredBehaviors() returns a list of methods/constructors.
* Although the list is cached in a CtClass object, it might be
* recreated for some reason. Thus, the member name and the signature
* must be also checked.
*/
for (int i = cb.length - 1; i >= 0; --i) {
if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) {
return cb[i];
}
}
throw new RuntimeException("fatal: not found");
}
Aggregations