use of org.fakereplace.api.NewClassData in project fakereplace by fakereplace.
the class Fakereplace method redefine.
public static void redefine(ClassDefinition[] classes, AddedClass[] addedData, boolean wait) {
try {
for (AddedClass i : addedData) {
ClassFile cf = new ClassFile(new DataInputStream(new ByteArrayInputStream(i.getData())));
mainTransformer.addNewClass(new NewClassData(i.getClassName(), i.getLoader(), cf));
}
for (ClassDefinition i : classes) {
ClassDataStore.instance().markClassReplaced(i.getDefinitionClass());
BaseClassData baseClassData = ClassDataStore.instance().getBaseClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName());
if (baseClassData != null) {
ClassDataStore.instance().saveClassData(i.getDefinitionClass().getClassLoader(), i.getDefinitionClass().getName(), new ClassDataBuilder(baseClassData));
}
}
for (AddedClass c : addedData) {
ClassLookupManager.addClassInfo(c.getClassName(), c.getLoader(), c.getData());
}
inst.redefineClasses(classes);
clearJvmCaches();
if (wait) {
mainTransformer.waitForTasks();
}
} catch (Throwable e) {
try {
// dump the classes to /tmp so we can look at them
for (ClassDefinition d : classes) {
try {
ByteArrayInputStream bin = new ByteArrayInputStream(d.getDefinitionClassFile());
DataInputStream dis = new DataInputStream(bin);
final ClassFile file = new ClassFile(dis);
Transformer.getManipulator().transformClass(file, d.getDefinitionClass().getClassLoader(), true, new HashSet<>());
String dumpDir = AgentOptions.getOption(AgentOption.DUMP_DIR);
if (dumpDir != null) {
FileOutputStream s = new FileOutputStream(dumpDir + '/' + d.getDefinitionClass().getName() + "1.class");
DataOutputStream dos = new DataOutputStream(s);
file.write(dos);
dos.flush();
dos.close();
// s.write(d.getDefinitionClassFile());
s.close();
}
} catch (IOException a) {
a.printStackTrace();
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
throw (new RuntimeException(e));
}
}
use of org.fakereplace.api.NewClassData in project fakereplace by fakereplace.
the class ResteasyClassChangeAware method afterChange.
@Override
public void afterChange(final List<ChangedClass> changed, final List<NewClassData> added) {
boolean requiresRestart = false;
ClassLoader classLoader = null;
for (final ChangedClass c : changed) {
if (!c.getChangedAnnotationsByType(Path.class).isEmpty() || c.getChangedClass().isAnnotationPresent(Path.class)) {
requiresRestart = true;
classLoader = c.getChangedClass().getClassLoader();
break;
}
}
Set<String> addedResources = new HashSet<>();
for (NewClassData add : added) {
AnnotationsAttribute attribute = (AnnotationsAttribute) add.getClassFile().getAttribute(AnnotationsAttribute.visibleTag);
if (attribute == null) {
continue;
}
if (attribute.getAnnotation(Path.class.getName()) != null) {
addedResources.add(add.getClassName());
requiresRestart = true;
}
if (classLoader == null) {
classLoader = add.getClassLoader();
}
}
if (requiresRestart) {
for (final Object servlet : InstanceTracker.get(ResteasyExtension.SERVLET_DISPATCHER)) {
try {
final ResteasyServletConfig config = (ResteasyServletConfig) servlet.getClass().getField(ResteasyTransformer.FIELD_NAME).get(servlet);
if (config.getClassLoader() == classLoader) {
StringBuilder res = new StringBuilder(config.getServletContext().getInitParameter(RESOURCES));
for (String add : addedResources) {
res.append(",").append(add);
}
ResteasyServletContext sc = new ResteasyServletContext(config.getServletContext());
sc.getInitParams().put(RESOURCES, res.toString());
config.setServletContext(sc);
final Set<String> doNotClear = (Set<String>) servlet.getClass().getField(ResteasyTransformer.PARAMETER_FIELD_NAME).get(servlet);
clearContext(config.getServletContext(), doNotClear);
final ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
try {
servlet.getClass().getMethod("destroy").invoke(servlet);
servlet.getClass().getMethod("init", ServletConfig.class).invoke(servlet, config);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
} catch (Exception e) {
logger.debug("Could not restart RESTeasy", e);
}
}
for (final Object filter : InstanceTracker.get(ResteasyExtension.FILTER_DISPATCHER)) {
try {
final ResteasyFilterConfig config = (ResteasyFilterConfig) filter.getClass().getField(ResteasyTransformer.FIELD_NAME).get(filter);
if (config.getClassLoader() == classLoader) {
StringBuilder res = new StringBuilder((String) config.getServletContext().getAttribute(RESOURCES));
for (String add : addedResources) {
res.append(",").append(add);
}
ResteasyServletContext sc = new ResteasyServletContext(config.getServletContext());
sc.getInitParams().put(RESOURCES, res.toString());
config.setServletContext(sc);
final Set<String> doNotClear = (Set<String>) filter.getClass().getField(ResteasyTransformer.PARAMETER_FIELD_NAME).get(filter);
clearContext(config.getServletContext(), doNotClear);
final ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
try {
filter.getClass().getMethod("destroy").invoke(filter);
filter.getClass().getMethod("init", FilterConfig.class).invoke(filter, config);
} finally {
Thread.currentThread().setContextClassLoader(old);
}
}
} catch (Exception e) {
logger.debug("Could not restart RESTeasy", e);
}
}
}
}
Aggregations