use of org.fakereplace.core.Fakereplace in project fakereplace by fakereplace.
the class WildflyAutoUpdate method runUpdate.
public static synchronized Result runUpdate(ModuleClassLoader classLoader) {
String moduleName = classLoader.getModule().getIdentifier().getName();
if (moduleName.startsWith(DEPLOYMENT)) {
moduleName = moduleName.substring(DEPLOYMENT.length());
}
String sourcePaths = System.getProperty(FAKEREPLACE_SOURCE_PATHS + moduleName);
if (sourcePaths == null) {
return Result.NO_CHANGE;
}
List<Path> paths = Arrays.stream(sourcePaths.split(",")).map((s) -> Paths.get(s)).collect(Collectors.toList());
try {
for (Path base : paths) {
final Map<String, Long> timestamps = new HashMap<>();
scan(base, base, timestamps);
List<String> toUpdate = new ArrayList<>();
List<String> added = new ArrayList<>();
List<String> replace = new ArrayList<>();
for (Map.Entry<String, Long> entry : timestamps.entrySet()) {
String name = entry.getKey();
if (name.endsWith(".java")) {
String baseName = name.substring(0, name.length() - 5);
Long last = replacedTimestamps.get(baseName);
if (last != null) {
if (last < entry.getValue()) {
toUpdate.add(baseName);
replacedTimestamps.put(baseName, entry.getValue());
replace.add(baseName);
}
} else {
URL res = classLoader.getResource(baseName + ".class");
if (res != null) {
URLConnection con = res.openConnection();
long lm = con.getLastModified();
if (lm < entry.getValue()) {
toUpdate.add(baseName);
replacedTimestamps.put(baseName, entry.getValue());
replace.add(baseName);
}
} else {
toUpdate.add(baseName);
replacedTimestamps.put(baseName, entry.getValue());
added.add(baseName);
}
}
}
}
if (!toUpdate.isEmpty()) {
System.out.println("Fakereplace detected the following source files have been changed: " + toUpdate);
ClassLoaderCompiler compiler = new ClassLoaderCompiler(classLoader, base, toUpdate);
compiler.compile();
Map<String, byte[]> byteMap = REPLACED_CLASSES.computeIfAbsent(classLoader, k -> new HashMap<>());
AddedClass[] addedClass = new AddedClass[added.size()];
for (int i = 0; i < added.size(); ++i) {
String className = added.get(i);
addedClass[i] = new AddedClass(className, compiler.getOutput().get(className).toByteArray(), classLoader);
byteMap.put(className, compiler.getOutput().get(className).toByteArray());
}
ClassDefinition[] classDefinition = new ClassDefinition[replace.size()];
for (int i = 0; i < replace.size(); ++i) {
String className = replace.get(i);
classDefinition[i] = new ClassDefinition(classLoader.loadClass(className.replace("/", ".")), compiler.getOutput().get(className).toByteArray());
byteMap.put(className, compiler.getOutput().get(className).toByteArray());
}
try {
Fakereplace.redefine(classDefinition, addedClass);
} catch (Exception e) {
System.err.println("Hot replace failed, redeploy required" + e.getMessage());
return Result.REDEPLOY_REQUIRED;
}
return Result.RELOAD;
}
}
return Result.NO_CHANGE;
} catch (Exception e) {
System.err.println("Check for updated classes failed");
e.printStackTrace();
} finally {
// something in the compiler clears the TCCL, fix it up
Thread.currentThread().setContextClassLoader(classLoader);
}
return Result.NO_CHANGE;
}
Aggregations