Skip to content

Commit

Permalink
refactor(classloader): reduces to the maximum the use of classloaders
Browse files Browse the repository at this point in the history
should simplify debug when Maven classloaders, JDT classloaders, IDE classloaders
interplay.
  • Loading branch information
monperrus committed Oct 29, 2016
1 parent f9f0dba commit 9932cde
Show file tree
Hide file tree
Showing 12 changed files with 180 additions and 195 deletions.
2 changes: 1 addition & 1 deletion src/main/java/spoon/SpoonException.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public SpoonException(String msg) {
public SpoonException(Throwable e) {
super(e);
}
public SpoonException(String msg, Exception e) {
public SpoonException(String msg, Throwable e) {
super(msg, e);
}
}
10 changes: 5 additions & 5 deletions src/main/java/spoon/SpoonTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@
*/
package spoon;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
* This class implements an Ant task for Spoon that encapsulates
* {@link spoon.Launcher}.
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/spoon/compiler/Environment.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/**
/**
* Copyright (C) 2006-2016 INRIA and contributors
* Spoon - http://spoon.gforge.inria.fr/
*
Expand Down Expand Up @@ -210,12 +210,15 @@ void report(Processor<?> processor, Level level,
int getWarningCount();

/**
* Gets the class loader used to compile/process the input source code.
* Returns the {@code ClassLoader} which is used by JDT and to resolve classes from references.
*
* By default, returns a class loader able to load classes from the
* Spoon-specific class path set with {@link #setSourceClasspath(String[])}
*/
ClassLoader getInputClassLoader();

/**
* Sets the class loader used to compile/process the input source code.
* Sets a specific classloader for JDT and reference resolution
*/
void setInputClassLoader(ClassLoader classLoader);

Expand Down Expand Up @@ -246,9 +249,9 @@ void report(Processor<?> processor, Level level,
void setSourceClasspath(String[] sourceClasspath);

/**
* Returns a {@code ClassLoader} which is able to load classes from the
* class path returned by {@link #getSourceClasspath()}
* Use {@link #getInputClassLoader()}
*/
@Deprecated
ClassLoader getClassLoader();

/**
Expand Down
21 changes: 0 additions & 21 deletions src/main/java/spoon/compiler/builder/ClasspathOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package spoon.compiler.builder;

import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

public class ClasspathOptions<T extends ClasspathOptions<T>> extends Options<T> {
public ClasspathOptions() {
Expand All @@ -41,25 +39,6 @@ public T classpath(String... classpaths) {
return classpath(join(File.pathSeparator, classpaths));
}

public T classpathFromListOrClassLoader(String... classpaths) {
return (classpaths != null && classpaths.length > 0) ? classpath(classpaths) : classpathFromCurrentClassLoader();
}

public T classpathFromCurrentClassLoader() {
ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
if (currentClassLoader instanceof URLClassLoader) {
final URL[] urls = ((URLClassLoader) currentClassLoader).getURLs();
if (urls != null && urls.length > 0) {
String classpath = ".";
for (URL url : urls) {
classpath += File.pathSeparator + url.getFile();
}
classpath(classpath);
}
}
return myself;
}

public T bootclasspath(String bootclasspath) {
if (bootclasspath == null) {
return myself;
Expand Down
78 changes: 41 additions & 37 deletions src/main/java/spoon/support/StandardEnvironment.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,9 @@
*/
package spoon.support;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.xml.sax.SAXException;

import spoon.Launcher;
import spoon.SpoonException;
import spoon.compiler.Environment;
Expand All @@ -53,6 +39,20 @@
import spoon.support.compiler.FileSystemFolder;
import spoon.support.processing.XmlProcessorProperties;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
* This class implements a simple Spoon environment that reports messages in the
* standard output stream (Java-compliant).
Expand Down Expand Up @@ -84,8 +84,6 @@ public class StandardEnvironment implements Serializable, Environment {

private String[] sourceClasspath = null;

private URLClassLoader classLoader = null;

private boolean preserveLineNumbers = false;

private boolean copyResources = true;
Expand Down Expand Up @@ -383,12 +381,35 @@ public void setTabulationSize(int tabulationSize) {
this.tabulationSize = tabulationSize;
}

private ClassLoader classloader;

@Override
public ClassLoader getClassLoader() {
if (classLoader == null) {
classLoader = new URLClassLoader(urlClasspath(), Thread.currentThread().getContextClassLoader());
public void setInputClassLoader(ClassLoader aClassLoader) {
if (aClassLoader instanceof URLClassLoader) {
final URL[] urls = ((URLClassLoader) aClassLoader).getURLs();
if (urls != null && urls.length > 0) {
List<String> classpath = new ArrayList<>();
for (URL url : urls) {
classpath.add(url.toString());
}
setSourceClasspath(classpath.toArray(new String[0]));
}
return;
}
return classLoader;
this.classloader = aClassLoader;
}

@Override
public ClassLoader getInputClassLoader() {
if (classloader != null) {
return classloader;
}
return new URLClassLoader(urlClasspath(), Thread.currentThread().getContextClassLoader());
}

@Override
public ClassLoader getClassLoader() {
return getInputClassLoader();
}

/**
Expand Down Expand Up @@ -417,7 +438,6 @@ public String[] getSourceClasspath() {
public void setSourceClasspath(String[] sourceClasspath) {
verifySourceClasspath(sourceClasspath);
this.sourceClasspath = sourceClasspath;
this.classLoader = null;
}

private void verifySourceClasspath(String[] sourceClasspath) throws InvalidClassPathException {
Expand Down Expand Up @@ -449,22 +469,6 @@ public int getWarningCount() {
return warningCount;
}

private ClassLoader inputClassLoader;

@Override
public ClassLoader getInputClassLoader() {
if (inputClassLoader == null) {
return Thread.currentThread().getContextClassLoader();
} else {
return this.inputClassLoader;
}
}

@Override
public void setInputClassLoader(ClassLoader classLoader) {
this.inputClassLoader = classLoader;
}

@Override
public boolean isPreserveLineNumbers() {
return preserveLineNumbers;
Expand Down
26 changes: 0 additions & 26 deletions src/main/java/spoon/support/compiler/jdt/CompilerClassLoader.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
import spoon.reflect.declaration.CtPackage;
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.Factory;
import spoon.reflect.visitor.AstParentConsistencyChecker;
import spoon.reflect.visitor.DefaultJavaPrettyPrinter;
import spoon.reflect.visitor.Filter;
import spoon.reflect.visitor.AstParentConsistencyChecker;
import spoon.reflect.visitor.PrettyPrinter;
import spoon.reflect.visitor.Query;
import spoon.support.QueueProcessingManager;
Expand All @@ -59,7 +59,6 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -134,7 +133,6 @@ private void checkModel() {

@Override
public boolean compile(InputType... types) {
initInputClassLoader();
factory.getEnvironment().debugMessage("compiling sources: " + factory.CompilationUnit().getMap().keySet());
long t = System.currentTimeMillis();
javaCompliance = factory.getEnvironment().getComplianceLevel();
Expand All @@ -143,7 +141,7 @@ public boolean compile(InputType... types) {


final String[] args = new JDTBuilderImpl() //
.classpathOptions(new ClasspathOptions().encoding(this.encoding).classpathFromListOrClassLoader(getSourceClasspath()).binaries(getBinaryOutputDirectory())) //
.classpathOptions(new ClasspathOptions().encoding(this.encoding).classpath(getSourceClasspath()).binaries(getBinaryOutputDirectory())) //
.complianceOptions(new ComplianceOptions().compliance(javaCompliance)) //
.annotationProcessingOptions(new AnnotationProcessingOptions().compileProcessors()) //
.advancedOptions(new AdvancedOptions().preserveUnusedVars().continueExecution().enableJavadoc()) //
Expand All @@ -161,8 +159,6 @@ public boolean compile(InputType... types) {

@Override
public void instantiateAndProcess(List<String> processors) {
initInputClassLoader();

// processing (consume all the processors)
ProcessingManager processing = new QueueProcessingManager(factory);
for (String processorName : processors) {
Expand All @@ -175,8 +171,6 @@ public void instantiateAndProcess(List<String> processors) {

@Override
public void process(Collection<Processor<? extends CtElement>> processors) {
initInputClassLoader();

// processing (consume all the processors)
ProcessingManager processing = new QueueProcessingManager(factory);
for (Processor<? extends CtElement> processorName : processors) {
Expand All @@ -194,7 +188,6 @@ public void generateProcessedSourceFiles(OutputType outputType) {

@Override
public void generateProcessedSourceFiles(OutputType outputType, Filter<CtType<?>> typeFilter) {
initInputClassLoader();
switch (outputType) {
case CLASSES:
generateProcessedSourceFilesUsingTypes(typeFilter);
Expand Down Expand Up @@ -351,12 +344,11 @@ protected boolean buildSources(JDTBuilder jdtBuilder) {
if (sources.getAllJavaFiles().isEmpty()) {
return true;
}
initInputClassLoader();
JDTBatchCompiler batchCompiler = createBatchCompiler(InputType.FILES);
String[] args;
if (jdtBuilder == null) {
args = new JDTBuilderImpl() //
.classpathOptions(new ClasspathOptions().encoding(this.encoding).classpathFromListOrClassLoader(getSourceClasspath())) //
.classpathOptions(new ClasspathOptions().encoding(this.encoding).classpath(getSourceClasspath())) //
.complianceOptions(new ComplianceOptions().compliance(javaCompliance)) //
.advancedOptions(new AdvancedOptions().preserveUnusedVars().continueExecution().enableJavadoc()) //
.sources(new SourceOptions().sources(sources.getAllJavaFiles())) //
Expand Down Expand Up @@ -653,47 +645,6 @@ protected InputStream getCompilationUnitInputStream(String path) {
return new ByteArrayInputStream(printer.getResult().toString().getBytes());
}

private CompilerClassLoader getCompilerClassLoader(ClassLoader initialClassLoader) {
while (initialClassLoader != null) {
if (initialClassLoader instanceof CompilerClassLoader) {
return (CompilerClassLoader) initialClassLoader;
}
initialClassLoader = initialClassLoader.getParent();
}
return null;
}

private boolean hasClassLoader(ClassLoader initialClassLoader, ClassLoader classLoader) {
while (initialClassLoader != null) {
if (initialClassLoader == classLoader) {
return true;
}
initialClassLoader = initialClassLoader.getParent();
}
return false;
}

protected void initInputClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (buildOnlyOutdatedFiles && getBinaryOutputDirectory() != null) {
CompilerClassLoader ccl = getCompilerClassLoader(cl);
if (ccl == null) {
try {
Launcher.LOGGER.debug("setting classloader for " + getBinaryOutputDirectory().toURI().toURL());
Thread.currentThread().setContextClassLoader(new CompilerClassLoader(new URL[] {
getBinaryOutputDirectory().toURI().toURL()
}, factory.getEnvironment().getInputClassLoader()));
} catch (Exception e) {
Launcher.LOGGER.error(e.getMessage(), e);
}
}
} else {
if (!hasClassLoader(Thread.currentThread().getContextClassLoader(), factory.getEnvironment().getInputClassLoader())) {
Thread.currentThread().setContextClassLoader(factory.getEnvironment().getInputClassLoader());
}
}
}

protected Environment getEnvironment() {
return getFactory().getEnvironment();
}
Expand Down
Loading

0 comments on commit 9932cde

Please sign in to comment.