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);
}
}
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);
}
}
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();
}
};
}
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;
}
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;
}
Aggregations