running new JPS builder from gant scripts

This commit is contained in:
nik
2012-08-15 10:10:34 +04:00
parent 77637b9e27
commit 306c9f6bae
34 changed files with 716 additions and 331 deletions
@@ -24,18 +24,16 @@ import com.intellij.openapi.roots.AnnotationOrderRootType;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.util.containers.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.impl.JavaSdkUtil;
import javax.swing.*;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -453,88 +451,16 @@ public class JavaSdkImpl extends JavaSdk {
}
private static VirtualFile[] findClasses(File file, boolean isJre) {
FileFilter jarFileFilter = new FileFilter() {
@Override
@SuppressWarnings({"HardCodedStringLiteral"})
public boolean accept(File f) {
return !f.isDirectory() && f.getName().endsWith(".jar");
}
};
File[] jarDirs;
if (SystemInfo.isMac && !file.getName().startsWith("mockJDK")) {
final File openJdkRtJar = new File(new File(new File(file, "jre"), "lib"), "rt.jar");
if (openJdkRtJar.exists() && !openJdkRtJar.isDirectory()) {
// OpenJDK
File libFile = new File(file, "lib");
@NonNls File classesFile = openJdkRtJar.getParentFile();
@NonNls File libExtFile = new File(openJdkRtJar.getParentFile(), "ext");
@NonNls File libEndorsedFile = new File(libFile, "endorsed");
jarDirs = new File[]{libEndorsedFile, libFile, classesFile, libExtFile};
}
else {
File libFile = new File(file, "lib");
@NonNls File classesFile = new File(file, "../Classes");
@NonNls File libExtFile = new File(libFile, "ext");
@NonNls File libEndorsedFile = new File(libFile, "endorsed");
jarDirs = new File[]{libEndorsedFile, libFile, classesFile, libExtFile};
}
}
else {
@NonNls final String jre = "jre";
File jreLibFile = isJre ? new File(file, "lib") : new File(new File(file, jre), "lib");
@NonNls File jreLibExtFile = new File(jreLibFile, "ext");
@NonNls File jreLibEndorsedFile = new File(jreLibFile, "endorsed");
jarDirs = new File[]{jreLibEndorsedFile, jreLibFile, jreLibExtFile};
}
Set<File> filter = new LinkedHashSet<File>();
List<File> children = new ArrayList<File>();
for (File jarDir : jarDirs) {
if (jarDir != null && jarDir.isDirectory()) {
File[] jarFiles = jarDir.listFiles(jarFileFilter);
for (File jarFile : jarFiles) {
final String jarFileName = jarFile.getName();
if (jarFileName.equals("alt-rt.jar") || jarFileName.equals("alt-string.jar")) continue;
try {
// File.getCanonicalFile() allows us to filter out duplicate (symbolically linked) jar files,
// commonly found in osx JDK distributions
if (filter.add(jarFile.getCanonicalFile())) children.add(jarFile);
}
catch (IOException e) {
// Symbolic links may fail to resolve. Just skip those jars as we won't be able to find virtual file in this case anyway.
}
}
}
}
List<File> rootFiles = JavaSdkUtil.getJdkClassesRoots(file, isJre);
ArrayList<VirtualFile> result = new ArrayList<VirtualFile>();
for (File child : children) {
String url = JarFileSystem.PROTOCOL_PREFIX + FileUtil.toSystemIndependentName(child.getAbsolutePath()) + JarFileSystem.JAR_SEPARATOR;
for (File child : rootFiles) {
String url = VfsUtil.getUrlForLibraryRoot(child);
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
if (vFile != null) {
result.add(vFile);
}
}
File classesZip = new File(new File(file, "lib"), "classes.zip");
if (classesZip.isFile()) {
String url = JarFileSystem.PROTOCOL_PREFIX + FileUtil.toSystemIndependentName(classesZip.getAbsolutePath()) + JarFileSystem.JAR_SEPARATOR;
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
if (vFile != null) {
result.add(vFile);
}
}
File classesDir = new File(file, "classes");
if (result.isEmpty() && classesDir.isDirectory()) {
String url = LocalFileSystem.PROTOCOL_PREFIX + FileUtil.toSystemIndependentName(classesDir.getAbsolutePath());
VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
if (vFile != null) {
result.add(vFile);
}
}
return VfsUtil.toVirtualFileArray(result);
}
@@ -62,6 +62,6 @@ public abstract class JavaSdk extends SdkType implements JavaSdkType, Applicatio
@Nullable
public static String getJdkVersion(final String sdkHome) {
return SdkVersionUtil.readVersionFromProcessOutput(sdkHome, new String[] {sdkHome + File.separator + "bin" + File.separator + "java", "-version"}, "version");
return SdkVersionUtil.detectJdkVersion(sdkHome);
}
}
@@ -1,6 +1,5 @@
package org.jetbrains.jps.api;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -9,9 +8,7 @@ import java.util.concurrent.Future;
* @author Eugene Zhuravlev
* Date: 3/29/12
*/
public class SharedThreadPool implements Executor {
private static final ExecutorService ourService = Executors.newCachedThreadPool();
public class SharedBuilderThreadPool {
private static final int MAX_BUILDER_THREADS;
static {
int maxThreads = 4;
@@ -24,15 +21,10 @@ public class SharedThreadPool implements Executor {
}
private static final ExecutorService ourBuilderPool = Executors.newFixedThreadPool(Math.min(MAX_BUILDER_THREADS, Math.max(2, Runtime.getRuntime().availableProcessors())));
public static final SharedThreadPool INSTANCE = new SharedThreadPool();
public static final SharedBuilderThreadPool INSTANCE = new SharedBuilderThreadPool();
private SharedThreadPool() {
}
/** @noinspection MethodMayBeStatic*/
public Future<?> submit(final Runnable task) {
return _submit(task, ourService);
private SharedBuilderThreadPool() {
}
/** @noinspection MethodMayBeStatic*/
@@ -52,18 +44,4 @@ public class SharedThreadPool implements Executor {
}
});
}
public void execute(final Runnable task) {
ourService.execute(new Runnable() {
public void run() {
try {
task.run();
}
finally {
Thread.interrupted(); // reset interrupted status
}
}
});
}
}
@@ -15,8 +15,8 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.api.CmdlineProtoUtil;
import org.jetbrains.jps.api.CmdlineRemoteProto;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.File;
import java.net.InetSocketAddress;
@@ -41,7 +41,7 @@ public class BuildMain {
initLoggers();
ourChannelFactory = new NioClientSocketChannelFactory(SharedThreadPool.INSTANCE, SharedThreadPool.INSTANCE, 1);
ourChannelFactory = new NioClientSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
final ClientBootstrap bootstrap = new ClientBootstrap(ourChannelFactory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
@@ -99,7 +99,7 @@ public class BuildMain {
final CmdlineRemoteProto.Message.ControllerMessage.FSEvent delta = controllerMessage.hasFsEvent()? controllerMessage.getFsEvent() : null;
final BuildSession session = new BuildSession(mySessionId, channel, controllerMessage.getParamsMessage(), delta);
mySession = session;
SharedThreadPool.INSTANCE.submit(new Runnable() {
SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
public void run() {
try {
session.run();
@@ -3,15 +3,12 @@ package org.jetbrains.jps.cmdline;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ParameterizedRunnable;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.ether.dependencyView.Callbacks;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.api.BuildType;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.idea.IdeaProjectLoader;
import org.jetbrains.jps.idea.SystemOutErrorReporter;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.artifacts.JpsBuilderArtifactService;
import org.jetbrains.jps.incremental.fs.BuildFSState;
@@ -21,12 +18,9 @@ import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
import org.jetbrains.jps.incremental.storage.Timestamps;
import org.jetbrains.jps.model.JpsElementFactory;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.artifact.JpsArtifact;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
import org.jetbrains.jps.model.serialization.JpsProjectLoader;
import java.io.File;
import java.io.IOException;
@@ -36,34 +30,20 @@ import java.util.*;
* @author nik
*/
public class BuildRunner {
public static final String IDEA_PROJECT_DIRNAME = ".idea";
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.BuildRunner");
private final String myProjectPath;
// globals
private final Map<String, String> myPathVars;
private final String myGlobalEncoding;
private final String myIgnorePatterns;
// build params
private final JpsModelLoader myModelLoader;
private final Set<String> myModules;
private BuildType myBuildType;
private final List<String> myArtifacts;
private final List<String> myFilePaths;
private final Map<String, String> myBuilderParams;
private final String myGlobalOptionsPath;
private boolean myForceCleanCaches;
private ParameterizedRunnable<JpsModel> myModelInitializer;
public BuildRunner(String projectPath, String globalOptionsPath, Map<String, String> pathVars,
String globalEncoding,
String ignorePatterns,
public BuildRunner(JpsModelLoader modelLoader,
Set<String> modules,
BuildType buildType,
List<String> artifacts, List<String> filePaths, Map<String, String> builderParams) {
myProjectPath = projectPath;
myGlobalOptionsPath = globalOptionsPath;
myPathVars = pathVars;
myGlobalEncoding = globalEncoding;
myIgnorePatterns = ignorePatterns;
myModelLoader = modelLoader;
myModules = modules;
myBuildType = buildType;
myArtifacts = artifacts;
@@ -71,10 +51,6 @@ public class BuildRunner {
myBuilderParams = builderParams;
}
public void setModelInitializer(ParameterizedRunnable<JpsModel> modelInitializer) {
myModelInitializer = modelInitializer;
}
public ProjectDescriptor load(MessageHandler msgHandler, File dataStorageRoot, BuildFSState fsState) throws IOException {
if (!dataStorageRoot.exists()) {
// invoked the very first time for this project. Force full rebuild
@@ -109,58 +85,11 @@ public class BuildRunner {
msgHandler.processMessage(new CompilerMessage("build", BuildMessage.Kind.INFO, "Project rebuild forced: " + e.getMessage()));
}
final JpsModel jpsModel = loadJpsModel();
final Project project = loadProject();
final JpsModel jpsModel = myModelLoader.loadModel();
final Project project = myModelLoader.loadOldProject();
return new ProjectDescriptor(project, jpsModel, fsState, projectTimestamps, dataManager, BuildLoggingManager.DEFAULT);
}
private JpsModel loadJpsModel() {
final long start = System.currentTimeMillis();
try {
final JpsModel model = JpsElementFactory.getInstance().createModel();
try {
if (myGlobalOptionsPath != null) {
JpsGlobalLoader.loadGlobalSettings(model.getGlobal(), myPathVars, myGlobalOptionsPath);
}
JpsProjectLoader.loadProject(model.getProject(), myPathVars, myProjectPath);
if (myModelInitializer != null) {
myModelInitializer.run(model);
}
LOG.info("New JPS model: " + model.getProject().getModules().size() + " modules, " + model.getProject().getLibraryCollection().getLibraries().size() + " libraries");
}
catch (IOException e) {
LOG.info(e);
}
return model;
}
finally {
final long loadTime = System.currentTimeMillis() - start;
LOG.info("New JPS model: project " + myProjectPath + " loaded in " + loadTime + " ms");
}
}
private Project loadProject() {
final long start = System.currentTimeMillis();
try {
final Project project = new Project();
final File projectFile = new File(myProjectPath);
final String loadPath = isDirectoryBased(projectFile) ? new File(projectFile, IDEA_PROJECT_DIRNAME).getPath() : myProjectPath;
IdeaProjectLoader.loadFromPath(project, loadPath, myPathVars, null, new SystemOutErrorReporter(false));
final String globalEncoding = myGlobalEncoding;
if (!StringUtil.isEmpty(globalEncoding) && project.getProjectCharset() == null) {
project.setProjectCharset(globalEncoding);
}
project.getIgnoredFilePatterns().loadFromString(myIgnorePatterns);
return project;
}
finally {
final long loadTime = System.currentTimeMillis() - start;
LOG.info("Project " + myProjectPath + " loaded in " + loadTime + " ms");
}
}
public void runBuild(ProjectDescriptor pd, CanceledStatus cs, @Nullable Callbacks.ConstantAffectionResolver constantSearch,
MessageHandler msgHandler) throws Exception {
for (int attempt = 0; attempt < 2; attempt++) {
@@ -209,10 +138,6 @@ public class BuildRunner {
return myBuildType;
}
private static boolean isDirectoryBased(File projectFile) {
return !(projectFile.isFile() && projectFile.getName().endsWith(".ipr"));
}
private static CompileScope createCompilationScope(BuildType buildType,
ProjectDescriptor pd,
Set<String> modules,
@@ -19,6 +19,7 @@ import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.fs.RootDescriptor;
import org.jetbrains.jps.incremental.messages.*;
import org.jetbrains.jps.incremental.storage.Timestamps;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.*;
import java.util.*;
@@ -77,7 +78,8 @@ final class BuildSession implements Runnable, CanceledStatus {
builderParams.put(pair.getKey(), pair.getValue());
}
myInitialFSDelta = delta;
myBuildRunner = new BuildRunner(myProjectPath, globalOptionsPath, pathVars, globalEncoding, ignorePatterns, modules, myBuildType, artifacts, filePaths, builderParams);
JpsModelLoaderImpl loader = new JpsModelLoaderImpl(myProjectPath, globalOptionsPath, pathVars, globalEncoding, ignorePatterns, null);
myBuildRunner = new BuildRunner(loader, modules, myBuildType, artifacts, filePaths, builderParams);
}
public void run() {
@@ -428,7 +430,7 @@ final class BuildSession implements Runnable, CanceledStatus {
private final AtomicBoolean myProcessingEnabled = new AtomicBoolean(false);
EventsProcessor() {
super(SharedThreadPool.INSTANCE);
super(SharedThreadPool.getInstance());
}
public void startProcessing() {
@@ -0,0 +1,13 @@
package org.jetbrains.jps.cmdline;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.model.JpsModel;
/**
* @author nik
*/
public interface JpsModelLoader {
JpsModel loadModel();
Project loadOldProject();
}
@@ -0,0 +1,96 @@
package org.jetbrains.jps.cmdline;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ParameterizedRunnable;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.idea.IdeaProjectLoader;
import org.jetbrains.jps.idea.SystemOutErrorReporter;
import org.jetbrains.jps.model.JpsElementFactory;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.serialization.JpsGlobalLoader;
import org.jetbrains.jps.model.serialization.JpsProjectLoader;
import java.io.File;
import java.io.IOException;
import java.util.Map;
/**
* @author nik
*/
public class JpsModelLoaderImpl implements JpsModelLoader {
public static final String IDEA_PROJECT_DIRNAME = ".idea";
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.cmdline.JpsModelLoaderImpl");
private final String myProjectPath;
private final String myGlobalOptionsPath;
private final Map<String, String> myPathVars;
private final String myGlobalEncoding;
private final String myIgnorePatterns;
private final ParameterizedRunnable<JpsModel> myModelInitializer;
public JpsModelLoaderImpl(String projectPath,
String globalOptionsPath,
Map<String, String> pathVars,
String globalEncoding,
String ignorePatterns, ParameterizedRunnable<JpsModel> initializer) {
myProjectPath = projectPath;
myGlobalOptionsPath = globalOptionsPath;
myPathVars = pathVars;
myGlobalEncoding = globalEncoding;
myIgnorePatterns = ignorePatterns;
myModelInitializer = initializer;
}
@Override
public JpsModel loadModel() {
final long start = System.currentTimeMillis();
try {
final JpsModel model = JpsElementFactory.getInstance().createModel();
try {
if (myGlobalOptionsPath != null) {
JpsGlobalLoader.loadGlobalSettings(model.getGlobal(), myPathVars, myGlobalOptionsPath);
}
JpsProjectLoader.loadProject(model.getProject(), myPathVars, myProjectPath);
if (myModelInitializer != null) {
myModelInitializer.run(model);
}
LOG.info("New JPS model: " + model.getProject().getModules().size() + " modules, " + model.getProject().getLibraryCollection().getLibraries().size() + " libraries");
}
catch (IOException e) {
LOG.info(e);
}
return model;
}
finally {
final long loadTime = System.currentTimeMillis() - start;
LOG.info("New JPS model: project " + myProjectPath + " loaded in " + loadTime + " ms");
}
}
@Override
public Project loadOldProject() {
final long start = System.currentTimeMillis();
try {
final Project project = new Project();
final File projectFile = new File(myProjectPath);
final String loadPath = isDirectoryBased(projectFile) ? new File(projectFile, IDEA_PROJECT_DIRNAME).getPath() : myProjectPath;
IdeaProjectLoader.loadFromPath(project, loadPath, myPathVars, null, new SystemOutErrorReporter(false));
final String globalEncoding = myGlobalEncoding;
if (!StringUtil.isEmpty(globalEncoding) && project.getProjectCharset() == null) {
project.setProjectCharset(globalEncoding);
}
project.getIgnoredFilePatterns().loadFromString(myIgnorePatterns);
return project;
}
finally {
final long loadTime = System.currentTimeMillis() - start;
LOG.info("Project " + myProjectPath + " loaded in " + loadTime + " ms");
}
}
private static boolean isDirectoryBased(File projectFile) {
return !(projectFile.isFile() && projectFile.getName().endsWith(".ipr"));
}
}
@@ -14,7 +14,7 @@ import org.jetbrains.jps.*;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.api.GlobalOptions;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.api.SharedBuilderThreadPool;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.fs.RootDescriptor;
@@ -26,6 +26,7 @@ import org.jetbrains.jps.incremental.storage.*;
import org.jetbrains.jps.model.java.JpsJavaClasspathKind;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.BufferedWriter;
import java.io.File;
@@ -439,7 +440,7 @@ public class IncProjectBuilder {
for (final ModuleChunk chunk : groupChunks) {
final CompileContext chunkLocalContext = createContextWrapper(context);
SharedThreadPool.INSTANCE.submitBuildTask(new Runnable() {
SharedBuilderThreadPool.INSTANCE.submitBuildTask(new Runnable() {
@Override
public void run() {
try {
@@ -584,7 +585,7 @@ public class IncProjectBuilder {
if (doneSomething && GENERATE_CLASSPATH_INDEX) {
final boolean forTests = context.isCompilingTests();
final Future<?> future = SharedThreadPool.INSTANCE.submit(new Runnable() {
final Future<?> future = SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
@Override
public void run() {
createClasspathIndex(chunk, forTests);
@@ -1,9 +1,9 @@
package org.jetbrains.jps.incremental;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.incremental.java.JavaBuilder;
import org.jetbrains.jps.incremental.resources.ResourcesBuilder;
import org.jetbrains.jps.service.SharedThreadPool;
import java.util.Arrays;
import java.util.List;
@@ -15,6 +15,6 @@ public class JavaBuilderService extends BuilderService {
@NotNull
@Override
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
return Arrays.asList(new JavaBuilder(SharedThreadPool.INSTANCE), new ResourcesBuilder());
return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()), new ResourcesBuilder());
}
}
@@ -21,7 +21,7 @@ public class Utils {
public static final Key<Map<String, Collection<String>>> REMOVED_SOURCES_KEY = Key.create("_removed_sources_");
public static final Key<Boolean> PROCEED_ON_ERROR_KEY = Key.create("_proceed_on_error_");
public static final Key<Boolean> ERRORS_DETECTED_KEY = Key.create("_errors_detected_");
private static volatile File ourSystemRoot = new File(System.getProperty("user.home", ".idea-build"));
private static volatile File ourSystemRoot = new File(System.getProperty("user.home"), ".idea-build");
public static final boolean IS_TEST_MODE = Boolean.parseBoolean(System.getProperty("test.mode", "false"));
private Utils() {
@@ -12,10 +12,9 @@ import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.api.CanceledStatus;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.service.SharedThreadPool;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
import javax.tools.*;
import java.io.File;
import java.net.InetSocketAddress;
import java.util.*;
@@ -34,7 +33,7 @@ public class JavacServer {
private final ChannelPipelineFactory myPipelineFactory;
public JavacServer() {
myChannelFactory = new NioServerSocketChannelFactory(SharedThreadPool.INSTANCE, SharedThreadPool.INSTANCE, 1);
myChannelFactory = new NioServerSocketChannelFactory(SharedThreadPool.getInstance(), SharedThreadPool.getInstance(), 1);
final ChannelRegistrar channelRegistrar = new ChannelRegistrar();
final ChannelHandler compilationRequestsHandler = new CompilationRequestsHandler();
myPipelineFactory = new ChannelPipelineFactory() {
@@ -196,7 +195,7 @@ public class JavacServer {
final CancelHandler cancelHandler = new CancelHandler();
myCancelHandlers.add(cancelHandler);
SharedThreadPool.INSTANCE.submit(new Runnable() {
SharedThreadPool.getInstance().executeOnPooledThread(new Runnable() {
public void run() {
try {
final JavacRemoteProto.Message exitMsg =
@@ -3,9 +3,9 @@ package org.jetbrains.jps.javac;
import org.jboss.netty.channel.MessageEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.api.SharedThreadPool;
import org.jetbrains.jps.client.SimpleProtobufClient;
import org.jetbrains.jps.client.UUIDGetter;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.File;
import java.util.*;
@@ -17,7 +17,7 @@ import java.util.*;
public class JavacServerClient extends SimpleProtobufClient<JavacServerResponseHandler>{
public JavacServerClient() {
super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.INSTANCE, new UUIDGetter() {
super(JavacRemoteProto.Message.getDefaultInstance(), SharedThreadPool.getInstance(), new UUIDGetter() {
@NotNull
public UUID getSessionUUID(@NotNull MessageEvent e) {
final JavacRemoteProto.Message message = (JavacRemoteProto.Message)e.getMessage();
@@ -0,0 +1,30 @@
package org.jetbrains.jps.model.java;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.service.JpsServiceManager;
import java.util.concurrent.Future;
/**
* @author nik
*/
public abstract class JdkVersionDetector {
public static JdkVersionDetector getInstance() {
return JpsServiceManager.getInstance().getService(JdkVersionDetector.class);
}
@Nullable
public abstract String detectJdkVersion(String homePath);
@Nullable
public abstract String detectJdkVersion(String homePath, ActionRunner actionRunner);
@Nullable
public abstract String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
ActionRunner actionRunner);
//todo[nik] replace with a service with difference implementation for IDEA and for JPS process (need to exclude jps-builders module from IDEA classpath)
public interface ActionRunner {
Future<?> run(Runnable runnable);
}
}
@@ -2,7 +2,11 @@ package org.jetbrains.jps.model.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsGlobal;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.library.JpsTypedLibrary;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.model.module.JpsDependencyElement;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsModuleReference;
@@ -66,4 +70,7 @@ public abstract class JpsJavaExtensionService {
@Nullable
public abstract String getSourcePrefix(JpsModule module, String rootUrl);
public abstract JpsTypedLibrary<JpsSdk<JpsDummyElement>> addJavaSdk(@NotNull JpsGlobal global, @NotNull String name,
@NotNull String homePath);
}
@@ -18,6 +18,8 @@ public interface JpsLibrary extends JpsNamedElement, JpsReferenceableElement<Jps
void addRoot(@NotNull String url, @NotNull JpsOrderRootType rootType);
void addRoot(@NotNull File file, @NotNull JpsOrderRootType rootType);
void addRoot(@NotNull String url, @NotNull JpsOrderRootType rootType, @NotNull JpsLibraryRoot.InclusionOptions options);
void removeUrl(@NotNull String url, @NotNull JpsOrderRootType rootType);
@@ -0,0 +1,15 @@
package org.jetbrains.jps.service;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
/**
* @author nik
*/
public abstract class SharedThreadPool implements Executor {
public static SharedThreadPool getInstance() {
return JpsServiceManager.getInstance().getService(SharedThreadPool.class);
}
public abstract Future<?> executeOnPooledThread(Runnable action);
}
@@ -0,0 +1 @@
org.jetbrains.jps.model.java.impl.JdkVersionDetectorImpl
@@ -0,0 +1 @@
org.jetbrains.jps.service.impl.SharedThreadPoolImpl
@@ -80,4 +80,12 @@ public class JpsPathUtil {
public static String pathToUrl(String path) {
return "file://" + path;
}
public static String getLibraryRootUrl(File file) {
String path = FileUtilRt.toSystemIndependentName(file.getAbsolutePath());
if (file.isDirectory()) {
return "file://" + path;
}
return "jar://" + path + "!/";
}
}
@@ -0,0 +1,83 @@
package org.jetbrains.jps.model.java.impl;
import com.intellij.openapi.util.SystemInfo;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
/**
* @author nik
*/
public class JavaSdkUtil {
public static List<File> getJdkClassesRoots(File file, boolean isJre) {
FileFilter jarFileFilter = new FileFilter() {
@Override
@SuppressWarnings({"HardCodedStringLiteral"})
public boolean accept(File f) {
return !f.isDirectory() && f.getName().endsWith(".jar");
}
};
File[] jarDirs;
if (SystemInfo.isMac && !file.getName().startsWith("mockJDK")) {
final File openJdkRtJar = new File(new File(new File(file, "jre"), "lib"), "rt.jar");
if (openJdkRtJar.exists() && !openJdkRtJar.isDirectory()) {
// OpenJDK
File libFile = new File(file, "lib");
File classesFile = openJdkRtJar.getParentFile();
File libExtFile = new File(openJdkRtJar.getParentFile(), "ext");
File libEndorsedFile = new File(libFile, "endorsed");
jarDirs = new File[]{libEndorsedFile, libFile, classesFile, libExtFile};
}
else {
File libFile = new File(file, "lib");
File classesFile = new File(file, "../Classes");
File libExtFile = new File(libFile, "ext");
File libEndorsedFile = new File(libFile, "endorsed");
jarDirs = new File[]{libEndorsedFile, libFile, classesFile, libExtFile};
}
}
else {
File jreLibFile = isJre ? new File(file, "lib") : new File(new File(file, "jre"), "lib");
File jreLibExtFile = new File(jreLibFile, "ext");
File jreLibEndorsedFile = new File(jreLibFile, "endorsed");
jarDirs = new File[]{jreLibEndorsedFile, jreLibFile, jreLibExtFile};
}
Set<File> filter = new LinkedHashSet<File>();
List<File> rootFiles = new ArrayList<File>();
for (File jarDir : jarDirs) {
if (jarDir != null && jarDir.isDirectory()) {
File[] jarFiles = jarDir.listFiles(jarFileFilter);
for (File jarFile : jarFiles) {
final String jarFileName = jarFile.getName();
if (jarFileName.equals("alt-rt.jar") || jarFileName.equals("alt-string.jar")) continue;
try {
// File.getCanonicalFile() allows us to filter out duplicate (symbolically linked) jar files,
// commonly found in osx JDK distributions
if (filter.add(jarFile.getCanonicalFile())) rootFiles.add(jarFile);
}
catch (IOException e) {
// Symbolic links may fail to resolve. Just skip those jars as we won't be able to find virtual file in this case anyway.
}
}
}
}
File classesZip = new File(new File(file, "lib"), "classes.zip");
if (classesZip.isFile()) {
rootFiles.add(classesZip);
}
File classesDir = new File(file, "classes");
if (rootFiles.isEmpty() && classesDir.isDirectory()) {
rootFiles.add(classesDir);
}
return rootFiles;
}
}
@@ -0,0 +1,163 @@
package org.jetbrains.jps.model.java.impl;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JdkVersionDetector;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.*;
import java.util.concurrent.Future;
/**
* @author nik
*/
public class JdkVersionDetectorImpl extends JdkVersionDetector {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.SdkVersionUtil");
private static final ActionRunner ACTION_RUNNER = new ActionRunner() {
@Override
public Future<?> run(Runnable runnable) {
return SharedThreadPool.getInstance().executeOnPooledThread(runnable);
}
};
@Override
@Nullable
public String detectJdkVersion(String homePath) {
return detectJdkVersion(homePath, ACTION_RUNNER);
}
@Nullable
public String detectJdkVersion(String homePath, final ActionRunner actionRunner) {
String[] command = {homePath + File.separator + "bin" + File.separator + "java", "-version"};
return readVersionFromProcessOutput(homePath, command, "version", actionRunner);
}
public String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
ActionRunner actionRunner) {
if (homePath == null || !new File(homePath).exists()) {
return null;
}
final String[] versionString = new String[1];
try {
//noinspection HardCodedStringLiteral
Process process = Runtime.getRuntime().exec(command);
VersionParsingThread parsingThread = new VersionParsingThread(process.getErrorStream(), versionString, versionLineMarker);
final Future<?> parsingThreadFuture = actionRunner.run(parsingThread);
ReadStreamThread readThread = new ReadStreamThread(process.getInputStream());
actionRunner.run(readThread);
try {
try {
process.waitFor();
}
catch (InterruptedException e) {
LOG.info(e);
process.destroy();
}
}
finally {
try {
parsingThreadFuture.get();
}
catch (Exception e) {
LOG.info(e);
}
}
}
catch (IOException ex) {
LOG.info(ex);
}
return versionString[0];
}
public static class ReadStreamThread implements Runnable {
private final InputStream myStream;
protected ReadStreamThread(InputStream stream) {
myStream = stream;
}
public void run() {
try {
while (true) {
int b = myStream.read();
if (b == -1) break;
}
}
catch (IOException e) {
LOG.info(e);
}
}
}
public static class VersionParsingThread implements Runnable {
private Reader myReader;
private final InputStream myStream;
private boolean mySkipLF = false;
private final String[] myVersionString;
private final String myVersionLineMarker;
protected VersionParsingThread(InputStream input, String[] versionString, String versionLineMarker) {
myStream = input;
myVersionString = versionString;
myVersionLineMarker = versionLineMarker;
}
public void run() {
try {
myReader = new InputStreamReader(myStream);
while (true) {
String line = readLine();
if (line == null) return;
if (line.contains(myVersionLineMarker)) {
myVersionString[0] = line;
}
}
}
catch (IOException e) {
LOG.info(e);
}
finally {
if (myReader != null){
try {
myReader.close();
}
catch (IOException e) {
LOG.info(e);
}
}
}
}
private String readLine() throws IOException {
boolean first = true;
StringBuilder buffer = new StringBuilder();
while (true) {
int c = myReader.read();
if (c == -1) break;
first = false;
if (c == '\n') {
if (mySkipLF) {
mySkipLF = false;
continue;
}
break;
}
else if (c == '\r') {
mySkipLF = true;
break;
}
else {
mySkipLF = false;
buffer.append((char)c);
}
}
if (first) return null;
String s = buffer.toString();
//if (Diagnostic.TRACE_ENABLED){
// Diagnostic.trace(s);
//}
return s;
}
}
}
@@ -1,12 +1,19 @@
package org.jetbrains.jps.model.java.impl;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsGlobal;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.JpsSimpleElement;
import org.jetbrains.jps.model.java.*;
import org.jetbrains.jps.model.library.JpsOrderRootType;
import org.jetbrains.jps.model.library.JpsTypedLibrary;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.model.module.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -115,6 +122,18 @@ public class JpsJavaExtensionServiceImpl extends JpsJavaExtensionService {
return null;
}
@Override
public JpsTypedLibrary<JpsSdk<JpsDummyElement>> addJavaSdk(@NotNull JpsGlobal global, @NotNull String name, @NotNull String homePath) {
String version = JdkVersionDetector.getInstance().detectJdkVersion(homePath);
JpsTypedLibrary<JpsSdk<JpsDummyElement>> sdk = global.addSdk(name, homePath, version, JpsJavaSdkType.INSTANCE);
File homeDir = new File(FileUtil.toSystemDependentName(homePath));
List<File> roots = JavaSdkUtil.getJdkClassesRoots(homeDir, false);
for (File root : roots) {
sdk.addRoot(root, JpsOrderRootType.COMPILED);
}
return sdk;
}
@Override
@NotNull
public JpsProductionModuleOutputPackagingElement createProductionModuleOutput(@NotNull JpsModuleReference moduleReference) {
@@ -54,6 +54,11 @@ public class JpsLibraryImpl<P extends JpsElement> extends JpsNamedCompositeEleme
addRoot(url, rootType, JpsLibraryRoot.InclusionOptions.ROOT_ITSELF);
}
@Override
public void addRoot(@NotNull File file, @NotNull JpsOrderRootType rootType) {
addRoot(JpsPathUtil.getLibraryRootUrl(file), rootType);
}
@Override
public void addRoot(@NotNull final String url, @NotNull final JpsOrderRootType rootType,
@NotNull JpsLibraryRoot.InclusionOptions options) {
@@ -0,0 +1,34 @@
package org.jetbrains.jps.service.impl;
import org.jetbrains.jps.service.SharedThreadPool;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* @author nik
*/
public class SharedThreadPoolImpl extends SharedThreadPool {
private final ExecutorService myService = Executors.newCachedThreadPool();
@Override
public void execute(Runnable command) {
executeOnPooledThread(command);
}
@Override
public Future<?> executeOnPooledThread(final Runnable action) {
return myService.submit(new Runnable() {
@Override
public void run() {
try {
action.run();
}
finally {
Thread.interrupted(); // reset interrupted status
}
}
});
}
}
@@ -32,7 +32,7 @@ public class JpsProjectLoader extends JpsLoaderBase {
private final JpsProject myProject;
private final Map<String, String> myPathVariables;
public JpsProjectLoader(JpsProject project, Map<String, String> pathVariables, File baseDir) {
private JpsProjectLoader(JpsProject project, Map<String, String> pathVariables, File baseDir) {
super(createProjectMacroExpander(pathVariables, baseDir));
myProject = project;
myPathVariables = pathVariables;
@@ -21,6 +21,7 @@
</orderEntry>
<orderEntry type="library" name="cli-parser" level="project" />
<orderEntry type="library" name="Ant" level="project" />
<orderEntry type="module" module-name="jps-model-serialization" />
</component>
</module>
@@ -0,0 +1,72 @@
package org.jetbrains.jps.gant;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.jetbrains.jps.api.BuildType;
import org.jetbrains.jps.build.Standalone;
import org.jetbrains.jps.cmdline.JpsModelLoader;
import org.jetbrains.jps.model.JpsModel;
import java.io.File;
import java.util.Collections;
/**
* @author nik
*/
public class JpsGantProjectBuilder {
private final Project myProject;
private final JpsModel myModel;
private final org.jetbrains.jps.Project myOldProject;
private boolean myCompressJars;
private File myDataStorageRoot;
private JpsModelLoader myModelLoader;
public JpsGantProjectBuilder(Project project, JpsModel model, org.jetbrains.jps.Project oldProject) {
myProject = project;
myModel = model;
myOldProject = oldProject;
myModelLoader = new JpsModelLoader() {
@Override
public JpsModel loadModel() {
return myModel;
}
@Override
public org.jetbrains.jps.Project loadOldProject() {
return myOldProject;
}
};
}
public boolean isCompressJars() {
return myCompressJars;
}
public void setCompressJars(boolean compressJars) {
myCompressJars = compressJars;
}
public void error(String message) {
throw new BuildException(message);
}
public void warning(String message) {
myProject.log(message, Project.MSG_WARN);
}
public void info(String message) {
myProject.log(message, Project.MSG_INFO);
}
public void stage(String message) {
myProject.log(message, Project.MSG_INFO);
}
public void setDataStorageRoot(File dataStorageRoot) {
myDataStorageRoot = dataStorageRoot;
}
public void rebuildModules() {
Standalone.runBuild(myModelLoader, myDataStorageRoot, BuildType.PROJECT_REBUILD, Collections.<String>emptySet(), Collections.<String>emptyList());
}
}
@@ -0,0 +1,103 @@
package org.jetbrains.jps.gant
import org.codehaus.gant.GantBinding
import org.jetbrains.jps.Project
import org.jetbrains.jps.idea.IdeaProjectLoader
import org.jetbrains.jps.incremental.Utils
import org.jetbrains.jps.model.JpsElementFactory
import org.jetbrains.jps.model.JpsGlobal
import org.jetbrains.jps.model.JpsModel
import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.model.library.JpsOrderRootType
import org.jetbrains.jps.model.serialization.JpsProjectLoader
/**
* @author nik
*/
final class JpsGantTool {
JpsGantTool(GantBinding binding) {
JpsModel model = JpsElementFactory.getInstance().createModel();
JpsProject project = model.project
def oldProject = new Project()
binding.setVariable("project", project)
binding.setVariable("oldProject", oldProject)
binding.setVariable("global", model.global)
def builder = new JpsGantProjectBuilder(binding.ant.project, model, oldProject)
binding.setVariable("builder", builder)
binding.setVariable("loadProject", {String path ->
loadProject(path, model, oldProject, builder);
})
binding.setVariable("jdk", {Object[] args ->
if (!(args.length in [2,3])) {
builder.error("expected 2 to 3 parameters for jdk() but ${args.length} found")
}
Closure initializer = args.length > 2 ? (Closure)args[2] : {}
return createJavaSdk(model.global, (String)args[0], (String)args[1], initializer)
})
binding.setVariable("layout", {String dir, Closure body ->
def layoutInfo = new LayoutInfo()
["module", "moduleTests", "zip", "dir"].each {tag ->
binding.setVariable(tag, {Object[] args ->
if (args.length == 1) {
binding.ant."$tag"(name: args[0])
}
else if (args.length == 2) {
binding.ant."$tag"(name: args[0], args[1])
}
else {
builder.error("unexpected number of parameters for $tag")
}
if (tag == "module") {
layoutInfo.usedModules << args[0].toString()
}
})
}
binding.setVariable("jar", {Object[] args ->
if (args.length == 2) {
def param0 = args[0]
String name;
String duplicate = null;
if (param0 instanceof Map) {
name = param0.name;
duplicate = param0.duplicate;
}
else {
name = (String)param0;
}
if (duplicate == null) {
duplicate = "fail"
}
binding.ant.jar(name: name, compress: builder.compressJars, duplicate: duplicate, args[1])
}
else {
builder.error("unexpected number of parameters for 'jar' task: $args.length")
}
})
def meta = new Expando()
body.delegate = meta
binding.ant.layout(toDir: dir, body)
return layoutInfo
})
binding.ant.taskdef(name: "layout", classname: "jetbrains.antlayout.tasks.LayoutTask")
}
private void loadProject(String path, JpsModel model, Project oldProject, JpsGantProjectBuilder builder) {
IdeaProjectLoader.loadFromPath(oldProject, path, [:])
JpsProjectLoader.loadProject(model.project, [:], path)
builder.setDataStorageRoot(Utils.getDataStorageRoot(path))
}
private void createJavaSdk(JpsGlobal global, String name, String homePath, Closure initializer) {
def sdk = JpsJavaExtensionService.getInstance().addJavaSdk(global, name, homePath)
def meta = new Expando()
meta.classpath = {String path ->
sdk.addRoot(new File(path), JpsOrderRootType.COMPILED)
}
initializer.delegate = meta
initializer.call()
}
}
@@ -0,0 +1,15 @@
package org.jetbrains.jps.gant;
import java.util.HashSet;
import java.util.Set;
/**
* @author nik
*/
public class LayoutInfo {
private Set<String> myUsedModules = new HashSet<String>();
public Set<String> getUsedModules() {
return myUsedModules;
}
}
@@ -92,7 +92,7 @@ public class SimpleJavaSdkType extends SdkType implements JavaSdkType {
public final String getVersionString(final String sdkHome) {
return SdkVersionUtil.readVersionFromProcessOutput(sdkHome, new String[] {sdkHome + File.separator + "bin" + File.separator + "java", "-version"}, "version");
return SdkVersionUtil.detectJdkVersion(sdkHome);
}
}
@@ -23,145 +23,30 @@
package com.intellij.openapi.projectRoots.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JdkVersionDetector;
import java.io.*;
import java.util.concurrent.Future;
public class SdkVersionUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.SdkVersionUtil");
private static final JdkVersionDetector.ActionRunner ACTION_RUNNER = new JdkVersionDetector.ActionRunner() {
@Override
public Future<?> run(Runnable runnable) {
return ApplicationManager.getApplication().executeOnPooledThread(runnable);
}
};
private SdkVersionUtil() {
}
@Nullable
public static String readVersionFromProcessOutput(String homePath, @NonNls String[] command, @NonNls String versionLineMarker) {
if (homePath == null || !new File(homePath).exists()) {
return null;
}
final String[] versionString = new String[1];
try {
//noinspection HardCodedStringLiteral
Process process = Runtime.getRuntime().exec(command);
VersionParsingThread parsingThread = new VersionParsingThread(process.getErrorStream(), versionString, versionLineMarker);
final Future<?> parsingThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(parsingThread);
ReadStreamThread readThread = new ReadStreamThread(process.getInputStream());
ApplicationManager.getApplication().executeOnPooledThread(readThread);
try {
try {
process.waitFor();
}
catch (InterruptedException e) {
LOG.info(e);
process.destroy();
}
}
finally {
try {
parsingThreadFuture.get();
}
catch (Exception e) {
LOG.info(e);
}
}
}
catch (IOException ex) {
LOG.info(ex);
}
return versionString[0];
return JdkVersionDetector.getInstance().readVersionFromProcessOutput(homePath, command, versionLineMarker, ACTION_RUNNER);
}
public static class ReadStreamThread implements Runnable {
private final InputStream myStream;
protected ReadStreamThread(InputStream stream) {
myStream = stream;
}
public void run() {
try {
while (true) {
int b = myStream.read();
if (b == -1) break;
}
}
catch (IOException e) {
LOG.info(e);
}
}
}
public static class VersionParsingThread implements Runnable {
private Reader myReader;
private final InputStream myStream;
private boolean mySkipLF = false;
private final String[] myVersionString;
private final String myVersionLineMarker;
protected VersionParsingThread(InputStream input, String[] versionString, String versionLineMarker) {
myStream = input;
myVersionString = versionString;
myVersionLineMarker = versionLineMarker;
}
public void run() {
try {
myReader = new InputStreamReader(myStream);
while (true) {
String line = readLine();
if (line == null) return;
if (line.contains(myVersionLineMarker)) {
myVersionString[0] = line;
}
}
}
catch (IOException e) {
LOG.info(e);
}
finally {
if (myReader != null){
try {
myReader.close();
}
catch (IOException e) {
LOG.info(e);
}
}
}
}
private String readLine() throws IOException {
boolean first = true;
StringBuilder buffer = new StringBuilder();
while (true) {
int c = myReader.read();
if (c == -1) break;
first = false;
if (c == '\n') {
if (mySkipLF) {
mySkipLF = false;
continue;
}
break;
}
else if (c == '\r') {
mySkipLF = true;
break;
}
else {
mySkipLF = false;
buffer.append((char)c);
}
}
if (first) return null;
String s = buffer.toString();
//if (Diagnostic.TRACE_ENABLED){
// Diagnostic.trace(s);
//}
return s;
}
@Nullable
public static String detectJdkVersion(String homePath) {
return JdkVersionDetector.getInstance().detectJdkVersion(homePath, ACTION_RUNNER);
}
}
@@ -8,6 +8,7 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="core-api" exported="" />
<orderEntry type="module" module-name="jps-model-api" exported="" />
</component>
</module>
@@ -10,7 +10,7 @@
<orderEntry type="module" module-name="projectModel-api" exported="" />
<orderEntry type="module" module-name="core-impl" />
<orderEntry type="module" module-name="jps-model-api" />
<orderEntry type="module" module-name="jps-model-impl" />
<orderEntry type="module" module-name="jps-model-impl" exported="" />
<orderEntry type="module" module-name="jps-model-serialization" exported="" />
</component>
</module>