IDEA-114130: class loader that loads annotation processors should have access to classes from tools.jar, but not to libraries used by jps build itself

This commit is contained in:
Eugene Zhuravlev
2013-09-30 20:56:38 +02:00
parent 5c158b78da
commit 07ec5a917d
9 changed files with 120 additions and 18 deletions
+7
View File
@@ -139,6 +139,8 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
}
jar("bootstrap.jar") { module("bootstrap") }
jar("jps-launcher.jar") { module("jps-launcher") }
jar("resources.jar") {
module("colorSchemes")
@@ -658,6 +660,11 @@ def layoutCommunityJps(String home, String target) {
module("util-rt")
module("util")
}
jar("jps-launcher.jar") {
module("jps-launcher")
}
jar("jps-model.jar") {
module("jps-model-api")
module("jps-model-impl")
+1
View File
@@ -23,6 +23,7 @@
<orderEntry type="module" module-name="jsp-openapi" />
<orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="jps-builders" />
<orderEntry type="module" module-name="jps-launcher" />
<orderEntry type="library" name="Netty" level="project" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="module" module-name="jps-model-impl" />
@@ -100,7 +100,8 @@ import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
import javax.tools.*;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -882,15 +883,25 @@ public class
cmdLine.addParameters(args);
}
final List<String> cp = ClasspathBootstrap.getBuildProcessApplicationClasspath();
cp.add(compilerPath);
@SuppressWarnings("UnnecessaryFullyQualifiedName")
final Class<?> launcherClass = org.jetbrains.jps.cmdline.Launcher.class;
final List<String> launcherCp = new ArrayList<String>();
launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass));
launcherCp.add(compilerPath);
ClasspathBootstrap.appendJavaCompilerClasspath(launcherCp);
cmdLine.addParameter("-classpath");
cmdLine.addParameter(classpathToString(launcherCp));
cmdLine.addParameter(launcherClass.getName());
final List<String> cp = ClasspathBootstrap.getBuildProcessApplicationClasspath(true);
cp.addAll(myClasspathManager.getBuildProcessPluginsClasspath(project));
if (isProfilingMode) {
cp.add(new File(workDirectory, "yjp-controller-api-redist.jar").getPath());
cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild");
}
cmdLine.addParameter("-classpath");
cmdLine.addParameter(classpathToString(cp));
cmdLine.addParameter(BuildMain.class.getName());
@@ -58,15 +58,20 @@ public class BuildMain {
LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildMain");
}
private static final int HOST_ARG = 0;
private static final int PORT_ARG = HOST_ARG + 1;
private static final int SESSION_ID_ARG = PORT_ARG + 1;
private static final int SYSTEM_DIR_ARG = SESSION_ID_ARG + 1;
private static NioEventLoopGroup ourEventLoopGroup;
public static void main(String[] args){
System.out.println("Build process started. Classpath: " + System.getProperty("java.class.path"));
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final UUID sessionId = UUID.fromString(args[2]);
final String host = args[HOST_ARG];
final int port = Integer.parseInt(args[PORT_ARG]);
final UUID sessionId = UUID.fromString(args[SESSION_ID_ARG]);
@SuppressWarnings("ConstantConditions")
final File systemDir = new File(FileUtil.toCanonicalPath(args[3]));
final File systemDir = new File(FileUtil.toCanonicalPath(args[SYSTEM_DIR_ARG]));
Utils.setSystemRoot(systemDir);
ourEventLoopGroup = new NioEventLoopGroup(1, SharedThreadPool.getInstance());
@@ -37,7 +37,9 @@ import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.impl.JpsModelImpl;
import org.jetbrains.jps.model.serialization.JpsProjectLoader;
import javax.tools.*;
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.util.*;
@@ -89,7 +91,7 @@ public class ClasspathBootstrap {
private ClasspathBootstrap() {
}
public static List<String> getBuildProcessApplicationClasspath() {
public static List<String> getBuildProcessApplicationClasspath(boolean isLauncherUsed) {
final Set<String> cp = ContainerUtil.newHashSet();
cp.add(getResourcePath(BuildMain.class));
@@ -108,9 +110,8 @@ public class ClasspathBootstrap {
cp.add(getResourcePath(NotNullVerifyingInstrumenter.class)); // not-null
cp.add(getResourcePath(IXMLBuilder.class)); // nano-xml
final Class<StandardJavaFileManager> optimizedFileManagerClass = getOptimizedFileManagerClass();
if (optimizedFileManagerClass != null) {
cp.add(getResourcePath(optimizedFileManagerClass)); // optimizedFileManager
if (!isLauncherUsed) {
appendJavaCompilerClasspath(cp);
}
try {
@@ -120,6 +121,15 @@ public class ClasspathBootstrap {
catch (Throwable ignored) {
}
return ContainerUtil.newArrayList(cp);
}
public static void appendJavaCompilerClasspath(Collection<String> cp) {
final Class<StandardJavaFileManager> optimizedFileManagerClass = getOptimizedFileManagerClass();
if (optimizedFileManagerClass != null) {
cp.add(getResourcePath(optimizedFileManagerClass)); // optimizedFileManager
}
for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { // Eclipse compiler
final String compilerResource = getResourcePath(javaCompiler.getClass());
final String name = PathUtilRt.getFileName(compilerResource);
@@ -127,8 +137,6 @@ public class ClasspathBootstrap {
cp.add(compilerResource);
}
}
return ContainerUtil.newArrayList(cp);
}
public static List<File> getJavacServerClasspath(String sdkHome, boolean useEclipseCompiler) {
@@ -213,7 +213,7 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
}
}
// ensure processor's loader will not resolve against JPS classes and libraries used in JPS
return new URLClassLoader(urls.toArray(new URL[urls.size()]), null);
return new URLClassLoader(urls.toArray(new URL[urls.size()]), myContext.getStandardFileManager().getClass().getClassLoader());
}
private File getSingleOutputDirectory(final Location loc, final JavaFileObject sourceFile) {
@@ -26,6 +26,7 @@ import org.jetbrains.jps.incremental.LineOutputWriter;
import javax.tools.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
@@ -334,7 +335,11 @@ public class JavacMain {
final Class<StandardJavaFileManager> optimizedManagerClass = ClasspathBootstrap.getOptimizedFileManagerClass();
if (optimizedManagerClass != null) {
try {
stdManager = optimizedManagerClass.newInstance();
final Constructor<StandardJavaFileManager> constructor = optimizedManagerClass.getConstructor();
// if optimizedManagerClass is loaded by another classloader, cls.newInstance() will not work
// that's why we need to call setAccessible() to ensure access
constructor.setAccessible(true);
stdManager = constructor.newInstance();
}
catch (Throwable e) {
if (SystemInfo.isWindows) {
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$/jps-launcher">
<sourceFolder url="file://$MODULE_DIR$/jps-launcher/src" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -0,0 +1,53 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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 org.jetbrains.jps.cmdline;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* @author Eugene Zhuravlev
* Date: 9/27/13
*/
public class Launcher {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
final String jpsClasspath = args[0];
final String mainClassName = args[1];
final String[] jpsArgs = new String[args.length - 2];
System.arraycopy(args, 2, jpsArgs, 0, jpsArgs.length);
final StringTokenizer tokenizer = new StringTokenizer(jpsClasspath, File.pathSeparator, false);
final List<URL> urls = new ArrayList<URL>();
while (tokenizer.hasMoreTokens()) {
final String path = tokenizer.nextToken();
urls.add(new File(path).toURI().toURL());
}
final URLClassLoader jpsLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), Launcher.class.getClassLoader());
final Class<?> mainClass = jpsLoader.loadClass(mainClassName);
final Method mainMethod = mainClass.getMethod("main", String[].class);
Thread.currentThread().setContextClassLoader(jpsLoader);
mainMethod.invoke(null, new Object[] {jpsArgs});
}
}