Search in sources :

Example 1 with VirtualFile

use of org.webpieces.util.file.VirtualFile in project webpieces by deanhiller.

the class RouteLoader method loadImpl.

private WebAppMeta loadImpl(ClassForName loader, Consumer<Injector> startupFunction) throws IOException {
    log.info("loading the master " + WebAppMeta.class.getSimpleName() + " class file");
    VirtualFile fileWithMetaClassName = config.getMetaFile();
    String moduleName;
    Charset fileEncoding = config.getFileEncoding();
    String contents = fileWithMetaClassName.contentAsString(fileEncoding);
    moduleName = contents.trim();
    log.info(WebAppMeta.class.getSimpleName() + " class to load=" + moduleName);
    Class<?> clazz = loader.clazzForName(moduleName);
    //In development mode, the ClassLoader here will be the CompilingClassLoader so stuff it into the thread context
    //just in case plugins will need it(most won't, hibernate will).  In production, this is really a no-op and does
    //nothing.  I don't like dev code existing in production :( so perhaps we should abstract this out at some 
    //point perhaps with a lambda of a lambda function
    ClassLoader original = Thread.currentThread().getContextClassLoader();
    try {
        Thread.currentThread().setContextClassLoader(clazz.getClassLoader());
        Object obj = newInstance(clazz);
        if (!(obj instanceof WebAppMeta))
            throw new IllegalArgumentException("name=" + moduleName + " does not implement " + WebAppMeta.class.getSimpleName());
        log.info(WebAppMeta.class.getSimpleName() + " loaded.  initializing next");
        WebAppMeta routerModule = (WebAppMeta) obj;
        routerModule.initialize(config.getWebAppMetaProperties());
        log.info(WebAppMeta.class.getSimpleName() + " initialized.");
        Injector injector = createInjector(routerModule);
        pluginSetup.wireInPluginPoints(injector, startupFunction);
        loadAllRoutes(routerModule, injector);
        return routerModule;
    } finally {
        Thread.currentThread().setContextClassLoader(original);
    }
}
Also used : VirtualFile(org.webpieces.util.file.VirtualFile) Injector(com.google.inject.Injector) WebAppMeta(org.webpieces.router.api.routing.WebAppMeta) Charset(java.nio.charset.Charset)

Example 2 with VirtualFile

use of org.webpieces.util.file.VirtualFile in project webpieces by deanhiller.

the class BytecodeCache method getBytecode.

/**
     * Retrieve the bytecode if source has not changed
     * @param name The cache name
     * @param source The source code
     * @return The bytecode
     */
public byte[] getBytecode(String name, String source) {
    try {
        VirtualFile f = cacheFile(name.replace("/", "_").replace("{", "_").replace("}", "_").replace(":", "_"));
        if (f.exists()) {
            try (InputStream fis = f.openInputStream()) {
                // Read hash
                int offset = 0;
                int read = -1;
                StringBuilder hash = new StringBuilder();
                // look for null byte, or end-of file
                while ((read = fis.read()) > 0) {
                    hash.append((char) read);
                    offset++;
                }
                if (!hash(source).equals(hash.toString())) {
                    log.trace(() -> "Bytecode too old (" + hash + " != " + hash(source) + ") for name=" + name);
                    return null;
                }
                byte[] byteCode = new byte[(int) f.length() - (offset + 1)];
                fis.read(byteCode);
                return byteCode;
            }
        }
        log.trace(() -> "Cache MISS for " + name);
        return null;
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : VirtualFile(org.webpieces.util.file.VirtualFile) InputStream(java.io.InputStream)

Example 3 with VirtualFile

use of org.webpieces.util.file.VirtualFile in project webpieces by deanhiller.

the class CompilingClassloader method getResources.

/**
     * You know ...
     */
@Override
public Enumeration<URL> getResources(String name) throws IOException {
    List<URL> urls = new ArrayList<URL>();
    for (VirtualFile vf : config.getJavaPath()) {
        VirtualFile res = vf.child(name);
        if (res != null && res.exists()) {
            urls.add(res.toURL());
        }
    }
    Enumeration<URL> parent = super.getResources(name);
    while (parent.hasMoreElements()) {
        URL next = parent.nextElement();
        if (!urls.contains(next)) {
            urls.add(next);
        }
    }
    final Iterator<URL> it = urls.iterator();
    return new Enumeration<URL>() {

        @Override
        public boolean hasMoreElements() {
            return it.hasNext();
        }

        @Override
        public URL nextElement() {
            return it.next();
        }
    };
}
Also used : VirtualFile(org.webpieces.util.file.VirtualFile) Enumeration(java.util.Enumeration) ArrayList(java.util.ArrayList) URL(java.net.URL)

Example 4 with VirtualFile

use of org.webpieces.util.file.VirtualFile in project webpieces by deanhiller.

the class CompilingClassloader method loadApplicationClassImpl.

public Class<?> loadApplicationClassImpl(String name) {
    Class<?> maybeAlreadyLoaded = super.findLoadedClass(name);
    if (maybeAlreadyLoaded != null) {
        return maybeAlreadyLoaded;
    }
    long start = System.currentTimeMillis();
    CompileClassMeta applicationClass = appClassMgr.getApplicationClass(name);
    //For anonymous classes...
    if (applicationClass == null) {
        VirtualFile file = fileLookup.getJava(name);
        applicationClass = appClassMgr.getOrCreateApplicationClass(name, file);
    }
    //if still null...
    if (applicationClass == null) {
        //the parent classloader is responsible for this class as it is not on our compile path
        return null;
    }
    if (applicationClass.isDefinable()) {
        return applicationClass.javaClass;
    }
    byte[] bc = byteCodeCache.getBytecode(name, applicationClass.javaSource);
    log.trace(() -> "Loading class for " + name);
    if (bc != null) {
        applicationClass.javaByteCode = bc;
        applicationClass.javaClass = defineClass(applicationClass.name, applicationClass.javaByteCode, 0, applicationClass.javaByteCode.length, protectionDomain);
        resolveClass(applicationClass.javaClass);
        if (log.isDebugEnabled()) {
            long time = System.currentTimeMillis() - start;
            log.trace(() -> time + "ms to load class " + name + " from cache");
        }
        return applicationClass.javaClass;
    }
    byte[] byteCode = applicationClass.javaByteCode;
    if (byteCode == null)
        byteCode = applicationClass.compile(compiler, this);
    if (byteCode == null) {
        throw new IllegalStateException("Bug, should not get here.  we could not compile and no exception thrown(should have had upstream fail fast exception");
    //previously removed class and returned
    //            	appClassMgr.classes.remove(name);
    //            	return;
    }
    applicationClass.javaClass = defineClass(applicationClass.name, applicationClass.javaByteCode, 0, applicationClass.javaByteCode.length, protectionDomain);
    byteCodeCache.cacheBytecode(applicationClass.javaByteCode, name, applicationClass.javaSource);
    resolveClass(applicationClass.javaClass);
    if (log.isTraceEnabled()) {
        long time = System.currentTimeMillis() - start;
        log.trace(() -> time + "ms to load class " + name);
    }
    return applicationClass.javaClass;
}
Also used : VirtualFile(org.webpieces.util.file.VirtualFile)

Example 5 with VirtualFile

use of org.webpieces.util.file.VirtualFile in project webpieces by deanhiller.

the class CompilingClassloader method isNeedToReloadJavaFiles.

/**
     * Detect Java changes
     */
public boolean isNeedToReloadJavaFiles() {
    // Now check for file modification
    List<CompileClassMeta> modifieds = new ArrayList<CompileClassMeta>();
    for (CompileClassMeta applicationClass : appClassMgr.all()) {
        if (applicationClass.javaFile.lastModified() > applicationClass.timestamp) {
            applicationClass.refresh();
            modifieds.add(applicationClass);
        }
    }
    Set<CompileClassMeta> modifiedWithDependencies = new HashSet<CompileClassMeta>();
    modifiedWithDependencies.addAll(modifieds);
    List<ClassDefinition> newDefinitions = new ArrayList<ClassDefinition>();
    for (CompileClassMeta applicationClass : modifiedWithDependencies) {
        if (applicationClass.compile(compiler, this) == null) {
            appClassMgr.classes.remove(applicationClass.name);
            throw new IllegalStateException("In what case can this ever happen in?");
        } else {
            byteCodeCache.cacheBytecode(applicationClass.javaByteCode, applicationClass.name, applicationClass.javaSource);
            //in rare case where outerclass is outside scope of compiling, but inner static class can be recompiled
            if (applicationClass.javaClass == null) {
                loadApplicationClass(applicationClass.name);
            }
            newDefinitions.add(new ClassDefinition(applicationClass.javaClass, applicationClass.javaByteCode));
        }
    }
    if (newDefinitions.size() > 0) {
        //Cache.clear();
        if (HotswapAgent.enabled) {
            try {
                HotswapAgent.reload(newDefinitions.toArray(new ClassDefinition[newDefinitions.size()]));
            } catch (Throwable e) {
                return true;
            }
        } else {
            return true;
        }
    }
    // Now check if there is new classes or removed classes
    int hash = classStateHashCreator.computePathHash(config.getJavaPath());
    if (hash != this.pathHash) {
        // Remove class for deleted files !!
        for (CompileClassMeta applicationClass : appClassMgr.all()) {
            if (!applicationClass.javaFile.exists()) {
                appClassMgr.classes.remove(applicationClass.name);
            }
            if (applicationClass.name.contains("$")) {
                appClassMgr.classes.remove(applicationClass.name);
                // Ok we have to remove all classes from the same file ...
                VirtualFile vf = applicationClass.javaFile;
                for (CompileClassMeta ac : appClassMgr.all()) {
                    if (ac.javaFile.equals(vf)) {
                        appClassMgr.classes.remove(ac.name);
                    }
                }
            }
        }
        return true;
    }
    return false;
}
Also used : VirtualFile(org.webpieces.util.file.VirtualFile) ArrayList(java.util.ArrayList) ClassDefinition(java.lang.instrument.ClassDefinition) HashSet(java.util.HashSet)

Aggregations

VirtualFile (org.webpieces.util.file.VirtualFile)15 ArrayList (java.util.ArrayList)5 VirtualFileImpl (org.webpieces.util.file.VirtualFileImpl)5 CompileConfig (org.webpieces.compiler.api.CompileConfig)4 File (java.io.File)3 RouterService (org.webpieces.router.api.RouterService)3 VirtualFileInputStream (org.webpieces.router.api.mocks.VirtualFileInputStream)3 Module (com.google.inject.Module)2 InputStream (java.io.InputStream)2 Before (org.junit.Before)2 RouterConfig (org.webpieces.router.api.RouterConfig)2 TemplateCompileConfig (org.webpieces.templatingdev.api.TemplateCompileConfig)2 WebserverForTest (org.webpieces.webserver.WebserverForTest)2 PlatformOverridesForTest (org.webpieces.webserver.test.PlatformOverridesForTest)2 Injector (com.google.inject.Injector)1 FileNotFoundException (java.io.FileNotFoundException)1 OutputStream (java.io.OutputStream)1 ClassDefinition (java.lang.instrument.ClassDefinition)1 URL (java.net.URL)1 Charset (java.nio.charset.Charset)1