juzu.impl.runtime.ModuleRuntime Maven / Gradle / Ivy
/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package juzu.impl.runtime;
import juzu.impl.common.Completion;
import juzu.impl.common.LiveClassLoader;
import juzu.impl.common.ParentJarClassLoader;
import juzu.impl.common.Logger;
import juzu.impl.compiler.*;
import juzu.impl.compiler.Compiler;
import juzu.impl.fs.FileSystemScanner;
import juzu.impl.fs.Filter;
import juzu.impl.fs.Snapshot;
import juzu.impl.fs.spi.ReadFileSystem;
import juzu.impl.fs.spi.ram.RAMFileSystem;
import juzu.impl.fs.spi.url.URLFileSystem;
import juzu.processor.MainProcessor;
import java.io.IOException;
import java.net.URL;
/**
* The module life cycle.
*
* @author Julien Viet
*/
public abstract class ModuleRuntime {
/** . */
protected final Logger logger;
protected ModuleRuntime(Logger logger) {
this.logger = logger;
}
/**
* Refresh the module.
*
* @param recompile true if recompilation can occur
* @return true when the refresh operation has triggered changes
*/
public abstract Completion refresh(boolean recompile) ;
/**
* Returns the module classloader.
*
* @return the module classloader
*/
public abstract ClassLoader getClassLoader();
/**
* Returns the module classes.
*
* @return the module classes
*/
public abstract ReadFileSystem getClasses();
/**
* Returns the module dynamicity.
*
* @return the module dynamicity
*/
public abstract boolean isDynamic();
public static class Dynamic extends ModuleRuntime {
/** . */
private final ClassLoader baseClassLoader;
/** . */
private URLFileSystem classPath;
/** . */
private FileSystemScanner scanner;
/** . */
private Snapshot snapshot;
/** . */
private ClassLoader classLoader;
/** . */
private ClassLoader classPathLoader;
/** . */
private ReadFileSystem classes;
/** . */
private boolean failed;
public Dynamic(Logger logger, ClassLoader baseClassLoader, ReadFileSystem source) {
super(logger);
//
this.classLoader = null;
this.baseClassLoader = baseClassLoader;
this.classPathLoader = new ParentJarClassLoader(baseClassLoader);
this.scanner = FileSystemScanner.createHashing(source);
this.snapshot = scanner.take();
this.classPath = null;
this.failed = false;
}
@Override
public synchronized Completion refresh(boolean recompile) {
if (!recompile) {
throw new UnsupportedOperationException("Not yet implemented");
} else {
try {
return Completion.completed(refresh());
}
catch (Exception e) {
return Completion.failed(e);
}
}
}
private boolean refresh() throws Exception, CompilationException {
// Lazy initialize
if (classPath == null) {
classPath = new URLFileSystem().add(classPathLoader, ClassLoader.getSystemClassLoader().getParent());
}
Snapshot next = snapshot.scan();
//
if (!failed && !next.hasChanges()) {
logger.info("No changes detected");
return false;
}
else {
logger.info("Building application");
//
this.failed = true;
//
final ReadFileSystem sourcePath = scanner.getFileSystem();
//
final RAMFileSystem classOutput = new RAMFileSystem();
Compiler compiler = Compiler.
builder().
sourcePath(sourcePath).
sourceOutput(classOutput).
classOutput(classOutput).
addClassPath(classPath).build();
compiler.addAnnotationProcessor(new MainProcessor());
compiler.compile();
// Copy everything that is not a java source and not already present
sourcePath.copy(new Filter.Default() {
@Override
public boolean acceptFile(S file, String name) throws IOException {
Iterable names = sourcePath.getNames(file);
String[] path = classOutput.getPath(names);
return path == null && !name.endsWith(".java");
}
}, classOutput);
//
this.classLoader = new LiveClassLoader(new URL[]{classOutput.getURL()}, baseClassLoader);
this.classes = classOutput;
this.snapshot = next;
this.failed = false;
//
return true;
}
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public ReadFileSystem getClasses() {
return classes;
}
@Override
public boolean isDynamic() {
return true;
}
}
public static class Static extends ModuleRuntime
{
/** . */
private final ClassLoader classLoader;
/** . */
private final ReadFileSystem
classes;
public Static(Logger logger, ClassLoader classLoader, ReadFileSystem
classes) {
super(logger);
//
this.classLoader = classLoader;
this.classes = classes;
}
@Override
public Completion refresh(boolean recompile) {
return Completion.completed(false);
}
@Override
public ClassLoader getClassLoader() {
return classLoader;
}
@Override
public ReadFileSystem getClasses() {
return classes;
}
@Override
public boolean isDynamic() {
return false;
}
}
}