diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 277b4e93291d..163af945b4d6 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -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") diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index 5e6ae9d70cba..8a42f6d5b8ab 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -23,6 +23,7 @@ + diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 1db0adad0c3d..927f127119df 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -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 cp = ClasspathBootstrap.getBuildProcessApplicationClasspath(); - cp.add(compilerPath); + @SuppressWarnings("UnnecessaryFullyQualifiedName") + final Class launcherClass = org.jetbrains.jps.cmdline.Launcher.class; + + final List launcherCp = new ArrayList(); + launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass)); + launcherCp.add(compilerPath); + ClasspathBootstrap.appendJavaCompilerClasspath(launcherCp); + + cmdLine.addParameter("-classpath"); + cmdLine.addParameter(classpathToString(launcherCp)); + + cmdLine.addParameter(launcherClass.getName()); + + final List 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()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java index a1cdbf5efc89..c6b34ab97bed 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java @@ -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()); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java index ecf2ba05707a..7904f769e3cb 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java @@ -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 getBuildProcessApplicationClasspath() { + public static List getBuildProcessApplicationClasspath(boolean isLauncherUsed) { final Set 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 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 cp) { + final Class 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 getJavacServerClasspath(String sdkHome, boolean useEclipseCompiler) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java index 653d800a75fe..d2f934c40f77 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java @@ -213,7 +213,7 @@ class JavacFileManager extends ForwardingJavaFileManager optimizedManagerClass = ClasspathBootstrap.getOptimizedFileManagerClass(); if (optimizedManagerClass != null) { try { - stdManager = optimizedManagerClass.newInstance(); + final Constructor 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) { diff --git a/jps/jps-launcher.iml b/jps/jps-launcher.iml new file mode 100644 index 000000000000..8cd11475fec1 --- /dev/null +++ b/jps/jps-launcher.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java new file mode 100644 index 000000000000..8885a0e01a42 --- /dev/null +++ b/jps/jps-launcher/src/org/jetbrains/jps/cmdline/Launcher.java @@ -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 urls = new ArrayList(); + 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}); + } +}