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});
+ }
+}