diff --git a/.idea/modules.xml b/.idea/modules.xml
index 8fedac9d8313..1e07d739f243 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -114,6 +114,7 @@
+
@@ -262,11 +263,11 @@
-
+
diff --git a/java/compiler/instrumentation-util-8/instrumentation-util-8.iml b/java/compiler/instrumentation-util-8/instrumentation-util-8.iml
new file mode 100644
index 000000000000..c00964488054
--- /dev/null
+++ b/java/compiler/instrumentation-util-8/instrumentation-util-8.iml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java/compiler/instrumentation-util-8/src/com/intellij/compiler/instrumentation/JrtLoader.java b/java/compiler/instrumentation-util-8/src/com/intellij/compiler/instrumentation/JrtLoader.java
new file mode 100644
index 000000000000..1185754304ae
--- /dev/null
+++ b/java/compiler/instrumentation-util-8/src/com/intellij/compiler/instrumentation/JrtLoader.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2000-2016 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 com.intellij.compiler.instrumentation;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
+
+/**
+ * Invoked via reflection from InstrumentationClassFinder
+ */
+public class JrtLoader extends InstrumentationClassFinder.ClassFinderClasspath.Loader{
+ private static final URI ROOT_URI = URI.create("jrt:/");
+ private static final InstrumentationClassFinder.Resource NULL_RESOURCE = ()-> null;
+ private List myRoots;
+ private final Map myCache = new HashMap<>();
+
+ public JrtLoader(URL url, int index) {
+ super(url, index);
+ }
+
+ @Override
+ public InstrumentationClassFinder.Resource getResource(String name) {
+ final InstrumentationClassFinder.Resource cached = myCache.get(name);
+ if (cached != null) {
+ return cached != NULL_RESOURCE ? cached : null;
+ }
+ try {
+ for (Path root : getRoots()) {
+ final Path path = root.resolve(name);
+ if (Files.exists(path)) {
+ final InstrumentationClassFinder.Resource res = () -> Files.newInputStream(path, StandardOpenOption.READ);
+ myCache.put(name, res);
+ return res;
+ }
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ myCache.put(name, NULL_RESOURCE);
+ return null;
+ }
+
+ @Override
+ public synchronized void releaseResources() {
+ myCache.clear();
+ final List roots = myRoots;
+ if (roots != null) {
+ try {
+ if (!roots.isEmpty()) {
+ roots.iterator().next().getFileSystem().close();
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ finally {
+ roots.clear();
+ myRoots = null;
+ }
+ }
+ }
+
+ private synchronized List getRoots() throws IOException {
+ final List cached = myRoots;
+ if (cached != null) {
+ return cached;
+ }
+ final FileSystem fs = FileSystems.newFileSystem(ROOT_URI, Collections.singletonMap("java.home", getBaseURL().getPath()));
+ final List roots = new ArrayList<>();
+ final Path modulesDir = fs.getPath("modules");
+ Files.walkFileTree(modulesDir, new SimpleFileVisitor() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ if (!modulesDir.equals(dir)) {
+ roots.add(dir);
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ myRoots = roots;
+ return roots;
+ }
+}
diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
index 02f4ffcd5f37..e34e7acfa517 100644
--- a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
+++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java
@@ -4,9 +4,9 @@ import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
-import sun.misc.Resource;
import java.io.*;
+import java.lang.reflect.Constructor;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
@@ -152,9 +152,9 @@ public class InstrumentationClassFinder {
InputStream is = null;
// first look into platformCp
final String resourceName = internalName + CLASS_RESOURCE_EXTENSION;
- Resource resource = myPlatformClasspath.getResource(resourceName, false);
+ Resource resource = myPlatformClasspath.getResource(resourceName);
if (resource != null) {
- is = new ByteArrayInputStream(resource.getBytes());
+ is = resource.getInputStream();
}
// second look into memory and classspath
if (is == null) {
@@ -162,9 +162,9 @@ public class InstrumentationClassFinder {
}
if (is == null) {
- resource = myClasspath.getResource(resourceName, false);
+ resource = myClasspath.getResource(resourceName);
if (resource != null) {
- is = new ByteArrayInputStream(resource.getBytes());
+ is = resource.getInputStream();
}
}
@@ -177,15 +177,15 @@ public class InstrumentationClassFinder {
public InputStream getResourceAsStream(String resourceName) throws IOException {
InputStream is = null;
- Resource resource = myPlatformClasspath.getResource(resourceName, false);
+ Resource resource = myPlatformClasspath.getResource(resourceName);
if (resource != null) {
- is = new ByteArrayInputStream(resource.getBytes());
+ is = resource.getInputStream();
}
if (is == null) {
- resource = myClasspath.getResource(resourceName, false);
+ resource = myClasspath.getResource(resourceName);
if (resource != null) {
- is = new ByteArrayInputStream(resource.getBytes());
+ is = resource.getInputStream();
}
}
@@ -433,8 +433,11 @@ public class InstrumentationClassFinder {
}
}
+ public interface Resource {
+ InputStream getInputStream() throws IOException;
+ }
+
static class ClassFinderClasspath {
- private static final String FILE_PROTOCOL = "file";
private final Stack myUrls = new Stack();
private final List myLoaders = new ArrayList();
@@ -448,10 +451,10 @@ public class InstrumentationClassFinder {
}
}
- public Resource getResource(String s, boolean flag) {
+ public Resource getResource(String s) {
int i = 0;
for (Loader loader; (loader = getLoader(i)) != null; i++) {
- Resource resource = loader.getResource(s, flag);
+ Resource resource = loader.getResource(s);
if (resource != null) {
return resource;
}
@@ -500,7 +503,7 @@ public class InstrumentationClassFinder {
return myLoaders.get(i);
}
- private Loader getLoader(final URL url, int index) throws IOException {
+ private static Loader getLoader(final URL url, int index) throws IOException {
String s;
try {
s = url.toURI().getSchemeSpecificPart();
@@ -510,23 +513,28 @@ public class InstrumentationClassFinder {
s = url.getFile();
}
- Loader loader = null;
- if (s != null && new File(s).isDirectory()) {
- if (FILE_PROTOCOL.equals(url.getProtocol())) {
- loader = new FileLoader(url, index);
+ if (s != null && s.length() > 0) {
+ final String protocol = url.getProtocol();
+ if (Loader.JRT_PROTOCOL.equals(protocol)) {
+ final Loader jrtLoader = JrtClassHolder.create(url, index);
+ if (jrtLoader != null) {
+ return jrtLoader;
+ }
+ }
+ if (new File(s).isDirectory()) {
+ return Loader.FILE_PROTOCOL.equals(protocol) ? new FileLoader(url, index) : null;
}
}
- else {
- loader = new JarLoader(url, index);
- }
- return loader;
+ // by default treat the url as a jar archive
+ return new JarLoader(url, index);
}
- private abstract static class Loader {
+ abstract static class Loader {
protected static final String JAR_PROTOCOL = "jar";
protected static final String FILE_PROTOCOL = "file";
+ protected static final String JRT_PROTOCOL = "jrt";
private final URL myURL;
private final int myIndex;
@@ -541,7 +549,7 @@ public class InstrumentationClassFinder {
return myURL;
}
- public abstract Resource getResource(final String name, boolean flag);
+ public abstract Resource getResource(final String name);
public abstract void releaseResources();
@@ -568,76 +576,38 @@ public class InstrumentationClassFinder {
public void releaseResources() {
}
- public Resource getResource(final String name, boolean check) {
- URL url = null;
- File file = null;
-
+ public Resource getResource(final String name) {
try {
- url = new URL(getBaseURL(), name);
+ final URL url = new URL(getBaseURL(), name);
if (!url.getFile().startsWith(getBaseURL().getFile())) {
return null;
}
- file = new File(myRootDir, name.replace('/', File.separatorChar));
- if (!check || file.exists()) { // check means we load or process resource so we check its existence via old way
- return new FileResource(name, url, file, !check);
+ final File file = new File(myRootDir, name.replace('/', File.separatorChar));
+ if (file.exists()) {
+ return new Resource() {
+ @Override
+ public InputStream getInputStream() throws IOException {
+ return new BufferedInputStream(new FileInputStream(file));
+ }
+
+ public String toString() {
+ return file.getAbsolutePath();
+ }
+ };
}
}
- catch (Exception exception) {
- if (!check && file != null && file.exists()) {
- try { // we can not open the file if it is directory, Resource still can be created
- return new FileResource(name, url, file, false);
- }
- catch (IOException ex) {
- }
- }
+ catch (Exception ignored) {
}
return null;
}
- private class FileResource extends Resource {
- private final String myName;
- private final URL myUrl;
- private final File myFile;
-
- public FileResource(String name, URL url, File file, boolean willLoadBytes) throws IOException {
- myName = name;
- myUrl = url;
- myFile = file;
- if (willLoadBytes) getByteBuffer(); // check for existence by creating cached file input stream
- }
-
- public String getName() {
- return myName;
- }
-
- public URL getURL() {
- return myUrl;
- }
-
- public URL getCodeSourceURL() {
- return getBaseURL();
- }
-
- public InputStream getInputStream() throws IOException {
- return new BufferedInputStream(new FileInputStream(myFile));
- }
-
- public int getContentLength() throws IOException {
- return -1;
- }
-
- public String toString() {
- return myFile.getAbsolutePath();
- }
- }
-
public String toString() {
return "FileLoader [" + myRootDir + "]";
}
}
- private class JarLoader extends Loader {
+ private static class JarLoader extends Loader {
private final URL myURL;
private ZipFile myZipFile;
@@ -674,21 +644,40 @@ public class InstrumentationClassFinder {
if (!new File(s).exists()) {
throw new FileNotFoundException(s);
}
- else {
- return new ZipFile(s);
- }
+ return new ZipFile(s);
}
return null;
}
- public Resource getResource(String name, boolean flag) {
+ public Resource getResource(String name) {
try {
final ZipFile file = acquireZipFile();
if (file != null) {
final ZipEntry entry = file.getEntry(name);
if (entry != null) {
- return new JarResource(entry, new URL(getBaseURL(), name));
+ return new Resource() {
+ @Override
+ public InputStream getInputStream() throws IOException {
+ try {
+ final ZipFile file = acquireZipFile();
+ if (file != null) {
+ final InputStream inputStream = file.getInputStream(entry);
+ if (inputStream != null) {
+ return new FilterInputStream(inputStream) {};
+ }
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public String toString() {
+ return "JarLoader [" + myURL + "!/" + entry.getName() + "]";
+ }
+ };
}
}
}
@@ -698,54 +687,6 @@ public class InstrumentationClassFinder {
return null;
}
- private class JarResource extends Resource {
- private final ZipEntry myEntry;
- private final URL myUrl;
-
- public JarResource(ZipEntry name, URL url) {
- myEntry = name;
- myUrl = url;
- }
-
- public String getName() {
- return myEntry.getName();
- }
-
- public URL getURL() {
- return myUrl;
- }
-
- public URL getCodeSourceURL() {
- return myURL;
- }
-
- public InputStream getInputStream() throws IOException {
- try {
- final ZipFile file = acquireZipFile();
- if (file == null) {
- return null;
- }
-
- final InputStream inputStream = file.getInputStream(myEntry);
- if (inputStream == null) {
- return null; // if entry was not found
- }
- return new FilterInputStream(inputStream) {};
- }
- catch (IOException e) {
- e.printStackTrace();
- return null;
- }
- }
-
- public int getContentLength() {
- return (int)myEntry.getSize();
- }
- }
-
- public String toString() {
- return "JarLoader [" + myURL + "]";
- }
}
}
@@ -828,4 +769,34 @@ public class InstrumentationClassFinder {
return result.toByteArray();
}
+ private static final class JrtClassHolder {
+ public static final Class extends ClassFinderClasspath.Loader> ourClass;
+ public static final Constructor extends ClassFinderClasspath.Loader> ourConstructor;
+
+ static {
+ Class extends ClassFinderClasspath.Loader> aClass = null;
+ Constructor extends ClassFinderClasspath.Loader> constructor = null;
+ try {
+ aClass = (Class extends ClassFinderClasspath.Loader>)Class.forName("com.intellij.compiler.instrumentation.JrtLoader");
+ constructor = aClass.getDeclaredConstructor(URL.class, int.class);
+ constructor.setAccessible(true);
+ }
+ catch (Throwable ignored) {
+ }
+ ourClass = aClass;
+ ourConstructor = constructor;
+ }
+
+ public static ClassFinderClasspath.Loader create(URL url, int index) {
+ if (ourConstructor != null) {
+ try {
+ return ourConstructor.newInstance(url, index);
+ }
+ catch (Throwable ignored) {
+ }
+ }
+ return null;
+ }
+ }
+
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
index bc353aa4b144..fa458f0d6976 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -18,13 +18,18 @@ package org.jetbrains.jps.incremental.instrumentation;
import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.ProjectPaths;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
+import org.jetbrains.jps.model.JpsDummyElement;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.ClassWriter;
@@ -85,8 +90,8 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
final Collection classpath = new ArrayList();
classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false));
classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());
-
- finder = createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
+ final JpsSdk sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE);
+ finder = createInstrumentationClassFinder(sdk, platformCp, classpath, outputConsumer);
CLASS_FINDER.set(context, finder);
}
@@ -109,10 +114,21 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
// utility methods
- public static InstrumentationClassFinder createInstrumentationClassFinder(Collection platformCp, Collection cp, final OutputConsumer outputConsumer) throws
+ public static InstrumentationClassFinder createInstrumentationClassFinder(@Nullable JpsSdk> sdk,
+ Collection platformCp,
+ Collection cp,
+ final OutputConsumer outputConsumer) throws
MalformedURLException {
- final URL[] platformUrls = new URL[platformCp.size()];
+ final URL[] platformUrls;
int index = 0;
+ if (sdk != null && JpsJavaSdkType.getJavaVersion(sdk) >= 9) {
+ platformUrls = new URL[1 + platformCp.size()];
+ platformUrls[index++] = new URL("jrt", null, FileUtil.toSystemIndependentName(sdk.getHomePath()));
+ }
+ else {
+ platformUrls = new URL[platformCp.size()];
+ }
+
for (File file : platformCp) {
platformUrls[index++] = file.toURI().toURL();
}
diff --git a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
index 0a4ead6ef9b1..244463148b89 100644
--- a/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
+++ b/plugins/ui-designer/jps-plugin/src/org/jetbrains/jps/uiDesigner/compiler/FormsInstrumenter.java
@@ -40,7 +40,10 @@ import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import org.jetbrains.jps.incremental.storage.OneToManyPathsMapping;
+import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.java.JpsJavaSdkType;
+import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.uiDesigner.model.JpsUiDesignerConfiguration;
import org.jetbrains.jps.uiDesigner.model.JpsUiDesignerExtensionService;
import org.jetbrains.org.objectweb.asm.ClassReader;
@@ -94,8 +97,8 @@ public class FormsInstrumenter extends FormsBuilder {
classpath.add(getResourcePath(GridConstraints.class)); // forms_rt.jar
final Map chunkSourcePath = ProjectPaths.getSourceRootsWithDependents(chunk);
classpath.addAll(chunkSourcePath.keySet()); // sourcepath for loading forms resources
-
- final InstrumentationClassFinder finder = ClassProcessingBuilder.createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
+ final JpsSdk sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE);
+ final InstrumentationClassFinder finder = ClassProcessingBuilder.createInstrumentationClassFinder(sdk, platformCp, classpath, outputConsumer);
try {
final Map> processed = instrumentForms(context, chunk, chunkSourcePath, finder, formsToCompile, outputConsumer);