com.googlecode.gwt.test.internal.GwtFactory Maven / Gradle / Ivy
package com.googlecode.gwt.test.internal;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.CompilerContext;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.javac.CompilationState;
import com.google.gwt.dev.shell.JsValueGlue;
import com.googlecode.gwt.test.GwtTreeLogger;
import com.googlecode.gwt.test.exceptions.GwtTestException;
import com.googlecode.gwt.test.internal.rewrite.OverlayTypesRewriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.regex.Pattern;
/**
* An unique place for internal singleton which are ClassLoader independent and can eventually be
* reset. For internal use only.
*
* @author Gael Lazzari
*/
public class GwtFactory {
private static GwtFactory instance;
private static final Pattern SUREFIRE_BOOTER_JAR_PATTERN = Pattern.compile("^.*surefire.*\\.jar$");
public static GwtFactory get() {
return instance;
}
public static boolean initializeIfNeeded() {
URL currentSurefireBooterJarUrl = findSureFireBooterJarUrl();
if (instance == null) {
// first return
instance = new GwtFactory(currentSurefireBooterJarUrl);
return true;
}
if (instance.surefireBooterJarUrl != null
&& !instance.surefireBooterJarUrl.equals(currentSurefireBooterJarUrl)
|| instance.surefireBooterJarUrl == null && currentSurefireBooterJarUrl != null) {
// surefire booter jar has changed : this should never happen since
// surefire-plugin runs each sub-module tests in an isolated
// classloader
// but just in case it would happen in the future, recompute everything
// :-o
instance = new GwtFactory(currentSurefireBooterJarUrl);
return true;
}
return false;
}
private static URL findSureFireBooterJarUrl() {
ClassLoader parent = Thread.currentThread().getContextClassLoader();
if (parent instanceof URLClassLoader) {
URL[] parentUrls = ((URLClassLoader) parent).getURLs();
if (parentUrls.length == 1
&& SUREFIRE_BOOTER_JAR_PATTERN.matcher(parentUrls[0].getPath()).matches()) {
return parentUrls[0];
}
}
return null;
}
private final CompilationState compilationState;
private final CompilerContext compilerContext;
private final CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder();
private final ConfigurationLoader configurationLoader;
private final GwtClassLoader gwtClassLoader;
private final ModuleDef moduleDef;
private final OverlayTypesRewriter overlayRewriter;
private final URL surefireBooterJarUrl;
private GwtFactory(URL surefireBooterJarUrl) {
configurationLoader = new ConfigurationLoader(surefireBooterJarUrl);
this.surefireBooterJarUrl = surefireBooterJarUrl;
// create a the temporary classloader used to build the CompilationState object which needs
// access to the project's resources (.java file)
ClassLoader defaultClassLoader = Thread.currentThread().getContextClassLoader();
CompilationStateClassLoader tempCl = new CompilationStateClassLoader(defaultClassLoader,
configurationLoader);
// ClassLoader classLoaderForResources =
// createTemporaryClassLoaderForResourceLoading(surefireBooterJarUrl);
Thread.currentThread().setContextClassLoader(tempCl);
try {
// create every gwt stuff, searching for resources in the setup
// 'src-directories' entries in
// META-INF/gwt-test-utils.properties files
CompilerContext tempContext = compilerContextBuilder.build();
moduleDef = createModuleDef(configurationLoader, tempContext);
compilerContext = compilerContextBuilder.module(moduleDef).build();
compilationState = createCompilationState(moduleDef, compilerContext);
overlayRewriter = createOverlayRewriter(compilationState);
gwtClassLoader = GwtClassLoader.createClassLoader(configurationLoader, compilationState,
overlayRewriter);
} catch (UnableToCompleteException e) {
// log related errors
GwtTreeLogger.get().onUnableToCompleteError();
throw new GwtTestException("Error while generating gwt-test-utils prerequisites", e);
} finally {
// reset the default classloader
Thread.currentThread().setContextClassLoader(defaultClassLoader);
}
}
public GwtClassLoader getClassLoader() {
return gwtClassLoader;
}
public CompilationState getCompilationState() {
return compilationState;
}
public ConfigurationLoader getConfigurationLoader() {
return configurationLoader;
}
public ModuleDef getModuleDef() {
return moduleDef;
}
public OverlayTypesRewriter getOverlayRewriter() {
return overlayRewriter;
}
private CompilationState createCompilationState(ModuleDef moduleDef,
CompilerContext compilerContext) throws UnableToCompleteException {
TreeLogger treeLogger = GwtTreeLogger.get();
return moduleDef.getCompilationState(treeLogger, compilerContext);
}
private ModuleDef createModuleDef(ConfigurationLoader configurationLoader,
CompilerContext compilerContext) throws UnableToCompleteException {
List gwtModules = configurationLoader.getGwtModules();
String[] inherits = gwtModules.toArray(new String[gwtModules.size()]);
return ModuleDefLoader.createSyntheticModule(GwtTreeLogger.get(),
"com.googlecode.gwt.test.Aggregator", inherits, false);
}
private OverlayTypesRewriter createOverlayRewriter(CompilationState compilationState) {
TypeOracle typeOracle = compilationState.getTypeOracle();
JClassType jsoType = typeOracle.findType(JsValueGlue.JSO_CLASS);
// If we couldn't find the JSO class, we don't need to do any rewrites.
return jsoType != null ? new OverlayTypesRewriter(compilationState, jsoType) : null;
}
}