Search in sources :

Example 1 with Fakereplace

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;
}
Also used : Path(java.nio.file.Path) Arrays(java.util.Arrays) Files(java.nio.file.Files) URL(java.net.URL) IOException(java.io.IOException) HashMap(java.util.HashMap) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) ClassDefinition(java.lang.instrument.ClassDefinition) List(java.util.List) Fakereplace(org.fakereplace.core.Fakereplace) Paths(java.nio.file.Paths) URLConnection(java.net.URLConnection) Map(java.util.Map) ModuleClassLoader(org.jboss.modules.ModuleClassLoader) Path(java.nio.file.Path) WeakHashMap(java.util.WeakHashMap) AddedClass(org.fakereplace.replacement.AddedClass) HashMap(java.util.HashMap) WeakHashMap(java.util.WeakHashMap) ArrayList(java.util.ArrayList) AddedClass(org.fakereplace.replacement.AddedClass) ClassDefinition(java.lang.instrument.ClassDefinition) URL(java.net.URL) URLConnection(java.net.URLConnection) IOException(java.io.IOException) HashMap(java.util.HashMap) Map(java.util.Map) WeakHashMap(java.util.WeakHashMap)

Aggregations

IOException (java.io.IOException)1 ClassDefinition (java.lang.instrument.ClassDefinition)1 URL (java.net.URL)1 URLConnection (java.net.URLConnection)1 Files (java.nio.file.Files)1 Path (java.nio.file.Path)1 Paths (java.nio.file.Paths)1 ArrayList (java.util.ArrayList)1 Arrays (java.util.Arrays)1 HashMap (java.util.HashMap)1 List (java.util.List)1 Map (java.util.Map)1 WeakHashMap (java.util.WeakHashMap)1 Collectors (java.util.stream.Collectors)1 Fakereplace (org.fakereplace.core.Fakereplace)1 AddedClass (org.fakereplace.replacement.AddedClass)1 ModuleClassLoader (org.jboss.modules.ModuleClassLoader)1