Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java2
-rw-r--r--org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java14
-rw-r--r--org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java12
-rw-r--r--org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java14
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MultiReleaseJarTests.java220
-rw-r--r--org.eclipse.jdt.core.tests.compiler/workspace/multi.jarbin0 -> 6523 bytes
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java99
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java2
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathMultiReleaseJar.java172
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java17
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java18
-rw-r--r--org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java33
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java4
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java45
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java6
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java5
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java25
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java25
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java186
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java12
-rw-r--r--org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java33
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java9
-rw-r--r--org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java9
23 files changed, 850 insertions, 112 deletions
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java
index 3c36c6d1ca..3706f40651 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java8ElementsTests.java
@@ -320,7 +320,7 @@ public class Java8ElementsTests extends TestCase {
internalTest(compiler, JAVA8_ANNOTATION_PROC, "testPackageAnnotations", null, "filer8", "9");
}
// See Java8ElementProcessor.testPackageAnnotations()
- public void _testPackageAnnotationsWithJavac() throws Exception {
+ public void testPackageAnnotationsWithJavac() throws Exception {
if (!canRunJava9())
return;
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
index ec9051533e..38ce78b664 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/util/EclipseFileManager.java
@@ -87,6 +87,7 @@ public class EclipseFileManager implements StandardJavaFileManager {
File jrtHome;
JrtFileSystem jrtSystem;
public ResourceBundle bundle;
+ String releaseVersion;
public EclipseFileManager(Locale locale, Charset charset) {
this.locale = locale == null ? Locale.getDefault() : locale;
@@ -814,6 +815,13 @@ public class EclipseFileManager implements StandardJavaFileManager {
} else {
throw new IllegalArgumentException();
}
+ case "--relese": //$NON-NLS-1$
+ if (remaining.hasNext()) {
+ this.releaseVersion = remaining.next();
+ return true;
+ } else {
+ throw new IllegalArgumentException();
+ }
}
} catch (IOException e) {
// ignore
@@ -1206,7 +1214,9 @@ public class EclipseFileManager implements StandardJavaFileManager {
customEncoding,
isSourceOnly,
accessRuleSet,
- destPath, null);
+ destPath,
+ null,
+ this.releaseVersion);
if (currentClasspath != null) {
paths.add(currentClasspath);
}
@@ -1336,7 +1346,7 @@ public class EclipseFileManager implements StandardJavaFileManager {
new DefaultProblemFactory());
for (Path path : paths) {
List<Classpath> mp = ModuleFinder.findModules(path.toFile(), null,
- new Parser(problemReporter, true), null, true);
+ new Parser(problemReporter, true), null, true, this.releaseVersion);
for (Classpath cp : mp) {
Collection<String> moduleNames = cp.getModuleNames(null);
for (String string : moduleNames) {
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
index c547b22ec8..4e1f2dee80 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseCompilerImpl.java
@@ -515,7 +515,9 @@ public class EclipseCompilerImpl extends Main {
Classpath classpath = FileSystem.getClasspath(
file.getAbsolutePath(),
null,
- null, this.options);
+ null,
+ this.options,
+ this.releaseVersion);
if (classpath != null) {
fileSystemClasspaths.add(classpath);
havePlatformPaths = true;
@@ -559,7 +561,9 @@ public class EclipseCompilerImpl extends Main {
Classpath classpath = FileSystem.getClasspath(
file.getAbsolutePath(),
null,
- null, this.options);
+ null,
+ this.options,
+ this.releaseVersion);
if (classpath != null) {
fileSystemClasspaths.add(classpath);
}
@@ -571,7 +575,9 @@ public class EclipseCompilerImpl extends Main {
Classpath classpath = FileSystem.getClasspath(
file.getAbsolutePath(),
null,
- null, this.options);
+ null,
+ this.options,
+ this.releaseVersion);
if (classpath != null) {
fileSystemClasspaths.add(classpath);
haveClassPaths = true;
diff --git a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
index 4aa0201692..1a9420c4b5 100644
--- a/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
+++ b/org.eclipse.jdt.compiler.tool/src/org/eclipse/jdt/internal/compiler/tool/EclipseFileManager.java
@@ -87,6 +87,7 @@ public class EclipseFileManager implements StandardJavaFileManager {
File jrtHome;
JrtFileSystem jrtSystem;
public ResourceBundle bundle;
+ private String releaseVersion;
public EclipseFileManager(Locale locale, Charset charset) {
this.locale = locale == null ? Locale.getDefault() : locale;
@@ -814,6 +815,13 @@ public class EclipseFileManager implements StandardJavaFileManager {
} else {
throw new IllegalArgumentException();
}
+ case "--relese": //$NON-NLS-1$
+ if (remaining.hasNext()) {
+ this.releaseVersion = remaining.next();
+ return true;
+ } else {
+ throw new IllegalArgumentException();
+ }
}
} catch (IOException e) {
// ignore
@@ -1231,7 +1239,9 @@ public class EclipseFileManager implements StandardJavaFileManager {
customEncoding,
isSourceOnly,
accessRuleSet,
- destPath, null);
+ destPath,
+ null,
+ this.releaseVersion);
if (currentClasspath != null) {
paths.add(currentClasspath);
}
@@ -1362,7 +1372,7 @@ public class EclipseFileManager implements StandardJavaFileManager {
new DefaultProblemFactory());
for (Path path : paths) {
List<Classpath> mp = ModuleFinder.findModules(path.toFile(), null,
- new Parser(problemReporter, true), null, true);
+ new Parser(problemReporter, true), null, true, this.releaseVersion);
for (Classpath cp : mp) {
Collection<String> moduleNames = cp.getModuleNames(null);
for (String string : moduleNames) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MultiReleaseJarTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MultiReleaseJarTests.java
new file mode 100644
index 0000000000..fa0dbd44f1
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/MultiReleaseJarTests.java
@@ -0,0 +1,220 @@
+package org.eclipse.jdt.core.tests.compiler.regression;
+
+import java.io.File;
+
+import javax.lang.model.SourceVersion;
+
+import org.eclipse.jdt.core.tests.util.Util;
+
+import junit.framework.Test;
+
+public class MultiReleaseJarTests extends AbstractBatchCompilerTest {
+
+ static {
+// TESTS_NAMES = new String[] { "test001" };
+ // TESTS_NUMBERS = new int[] { 1 };
+ // TESTS_RANGE = new int[] { 298, -1 };
+ }
+
+ private boolean isJRE10 = false;
+ public MultiReleaseJarTests(String name) {
+ super(name);
+ try {
+ SourceVersion valueOf = SourceVersion.valueOf("RELEASE_10");
+ if (valueOf != null) this.isJRE10 = true;
+ } catch(Exception e) {
+
+ }
+ }
+
+ public static Test suite() {
+ return buildMinimalComplianceTestSuite(testClass(), F_9);
+ }
+
+ public static Class<?> testClass() {
+ return MultiReleaseJarTests.class;
+ }
+ public void test001() {
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ runNegativeTest(
+ new String[] {
+ "src/X.java",
+ "import a.b.c.MultiVersion1.Inner;\n" +
+ "import p.q.r.MultiVersion2.Inner;\n" +
+ "public class X {\n" +
+ "}\n"},
+ "\"" + OUTPUT_DIR + File.separator + "src/X.java\"" +
+ " -classpath " + path + " --release 8 ",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/X.java (at line 1)\n" +
+ " import a.b.c.MultiVersion1.Inner;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "The import a.b.c.MultiVersion1.Inner cannot be resolved\n" +
+ "----------\n" +
+ "2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/X.java (at line 2)\n" +
+ " import p.q.r.MultiVersion2.Inner;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "The import p.q.r.MultiVersion2.Inner cannot be resolved\n" +
+ "----------\n" +
+ "2 problems (2 errors)\n",
+ false
+ );
+ }
+ public void test002() {
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ runNegativeTest(
+ new String[] {
+ "src/X.java",
+ "import a.b.c.MultiVersion1.Inner;\n" +
+ "import p.q.r.MultiVersion2.Inner;\n" +
+ "public class X {\n" +
+ "}\n"},
+ "\"" + OUTPUT_DIR + File.separator + "src/X.java\"" +
+ " -classpath " + path + " --release 9 ",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/X.java (at line 1)\n" +
+ " import a.b.c.MultiVersion1.Inner;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "The type a.b.c.MultiVersion1.Inner is not visible\n" +
+ "----------\n" +
+ "1 problem (1 error)\n",
+ false
+ );
+ }
+ public void test003() {
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ runConformTest(
+ new String[] {
+ "src/X.java",
+ "import p.q.r.MultiVersion3.Inner;\n" +
+ "public class X {\n" +
+ " Inner i = null;\n" +
+ " p.q.r.MultiVersion2.Inner i2 = null;\n" +
+ "}\n"},
+ "\"" + OUTPUT_DIR + File.separator + "src/X.java\"" +
+ " -classpath " + path + " --release 9 ",
+ "",
+ "",
+ false
+ );
+ }
+ public void test004() {
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ runNegativeTest(
+ new String[] {
+ "src/X.java",
+ "import p.q.r.MultiVersion3.Inner;\n" +
+ "import p.q.r.MultiVersion2.Inner;\n" +
+ "public class X {\n" +
+ " Inner i = null;\n" +
+ "}\n"},
+ "\"" + OUTPUT_DIR + File.separator + "src/X.java\"" +
+ " -classpath " + path + " --release 9 ",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/X.java (at line 2)\n" +
+ " import p.q.r.MultiVersion2.Inner;\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "The import p.q.r.MultiVersion2.Inner collides with another import statement\n" +
+ "----------\n" +
+ "1 problem (1 error)\n",
+ false
+ );
+ }
+ public void test005() {
+ Util.flushDirectoryContent(new File(OUTPUT_DIR));
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ File directory = new File(OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" );
+ File out = new File(OUTPUT_DIR + File.separator + "out" );
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ System.out.println("Could not create " + directory.toString());
+ return;
+ }
+ }
+ if (!out.exists()) {
+ if (!out.mkdirs()) {
+ System.out.println("Could not create " + directory.toString());
+ return;
+ }
+ }
+ runNegativeTest(
+ new String[] {
+ "src/MyModule/module-info.java",
+ "module MyModule {\n" +
+ " requires Version9;\n" +
+ "}",
+ "src/MyModule/p/X.java",
+ "package p;\n" +
+ "public class X {\n" +
+ " java.sql.Connection con = null;\n" +
+ "}\n"},
+ " -d \"" + out.toString() + "\" " +
+ " --module-source-path \"" + directory.toString() + "\" " +
+ " \"" + OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" + File.separator + "module-info.java\"" +
+ " \"" + OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" + File.separator + "p" + File.separator + "X.java\" " +
+ " --module-path " + path + " --release 9 ",
+ "",
+ "----------\n" +
+ "1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/MyModule/p/X.java (at line 3)\n" +
+ " java.sql.Connection con = null;\n" +
+ " ^^^^^^^^^^^^^^^^^^^\n" +
+ "The type java.sql.Connection is not accessible\n" +
+ "----------\n" +
+ "1 problem (1 error)\n",
+ false
+ );
+ }
+ public void test006() {
+ if (!this.isJRE10) return;
+ String path = this.getCompilerTestsPluginDirectoryPath() + File.separator + "workspace" + File.separator + "multi.jar";
+ String[] libs = new String[1];
+ libs[0] = path;
+ File directory = new File(OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" );
+ File out = new File(OUTPUT_DIR + File.separator + "out" );
+ if (!directory.exists()) {
+ if (!directory.mkdirs()) {
+ System.out.println("Could not create " + directory.toString());
+ return;
+ }
+ }
+ if (!out.exists()) {
+ if (!directory.mkdirs()) {
+ System.out.println("Could not create " + directory.toString());
+ return;
+ }
+ }
+ runConformTest(
+ new String[] {
+ "src/MyModule/module-info.java",
+ "module MyModule {\n" +
+ " requires Version10;\n" +
+ "}",
+ "src/MyModule/p/X.java",
+ "package p;\n" +
+ "public class X {\n" +
+ " java.sql.Connection con = null;\n" +
+ "}\n"},
+ " -d \"" + out.toString() + "\" " +
+ " --module-source-path \"" + directory.toString() + "\" " +
+ " \"" + OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" + File.separator + "module-info.java\"" +
+ " \"" + OUTPUT_DIR + File.separator + "src" + File.separator + "MyModule" + File.separator + "p" + File.separator + "X.java\" " +
+ " --module-path " + path + " --release 10 ",
+ "",
+ "",
+ false
+ );
+ }
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/workspace/multi.jar b/org.eclipse.jdt.core.tests.compiler/workspace/multi.jar
new file mode 100644
index 0000000000..c28b088a36
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/workspace/multi.jar
Binary files differ
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
index 37bb0a0564..6e1eb3af8e 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJep247.java
@@ -15,32 +15,37 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.compiler.util.Util;
-public class ClasspathJep247 extends ClasspathLocation {
+public class ClasspathJep247 extends ClasspathJrt {
private java.nio.file.FileSystem fs = null;
private String compliance = null;
private String releaseInHex = null;
private String[] subReleases = null;
private Path releasePath = null;
- private File file = null;
private Set<String> packageCache;
+ File jdkHome;
+ String modulePath = null;
public ClasspathJep247(File jdkHome, String release, AccessRuleSet accessRuleSet) {
- super(accessRuleSet, null);
+ super(jdkHome, false, accessRuleSet, null);
this.compliance = release;
- this.file = jdkHome;
+ this.jdkHome = jdkHome;
+ this.file = new File(new File(jdkHome, "lib"), "jrt-fs.jar"); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
public List<Classpath> fetchLinkedJars(FileSystem.ClasspathSectionProblemReporter problemReporter) {
@@ -83,15 +88,6 @@ public class ClasspathJep247 extends ClasspathLocation {
}
return null;
}
- @Override
- public boolean hasAnnotationFileFor(String qualifiedTypeName) {
- return false;
- }
- @Override
- public char[][][] findTypeNames(final String qualifiedPackageName, String moduleName) {
- // TODO: Revisit
- return null;
- }
@Override
public void initialize() throws IOException {
@@ -99,7 +95,7 @@ public class ClasspathJep247 extends ClasspathLocation {
return;
}
this.releaseInHex = Integer.toHexString(Integer.parseInt(this.compliance));
- Path filePath = this.file.toPath().resolve("lib").resolve("ct.sym"); //$NON-NLS-1$ //$NON-NLS-2$
+ Path filePath = this.jdkHome.toPath().resolve("lib").resolve("ct.sym"); //$NON-NLS-1$ //$NON-NLS-2$
URI t = filePath.toUri();
if (!Files.exists(filePath)) {
return;
@@ -118,9 +114,73 @@ public class ClasspathJep247 extends ClasspathLocation {
if (!Files.exists(this.fs.getPath(this.releaseInHex))) {
throw new IllegalArgumentException("release " + this.compliance + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$
}
+ super.initialize();
+ }
+ @Override
+ public void loadModules() {
+ if (CompilerOptions.releaseToJDKLevel(this.compliance) <= ClassFileConstants.JDK1_8) {
+ return;
+ }
+ final Path modPath = this.fs.getPath(this.releaseInHex + "-modules"); //$NON-NLS-1$
+ if (!Files.exists(modPath)) {
+ throw new IllegalArgumentException("release " + this.compliance + " is not found in the system"); //$NON-NLS-1$//$NON-NLS-2$
+ }
+ this.modulePath = this.file.getPath() + "|" + modPath.toString(); //$NON-NLS-1$
+ Map<String, IModule> cache = ModulesCache.get(this.modulePath);
+ if (cache == null) {
+ try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(modPath)) {
+ for (final java.nio.file.Path subdir: stream) {
+ Files.walkFileTree(subdir, new FileVisitor<java.nio.file.Path>() {
+
+ @Override
+ public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFile(java.nio.file.Path f, BasicFileAttributes attrs) throws IOException {
+ byte[] content = null;
+ if (Files.exists(f)) {
+ content = JRTUtil.safeReadBytes(f);
+ if (content == null)
+ return FileVisitResult.CONTINUE;
+ ClasspathJep247.this.acceptModule(content);
+ ClasspathJep247.this.moduleNamesCache.add(f.getFileName().toString());
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(java.nio.file.Path f, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ this.moduleNamesCache.addAll(cache.keySet());
+ }
}
+ @Override
void acceptModule(ClassFileReader reader) {
- // Nothing to do
+ if (reader != null) {
+ IModule moduleDecl = reader.getModuleDeclaration();
+ if (moduleDecl != null) {
+ Map<String, IModule> cache = ModulesCache.get(this.modulePath);
+ if (cache == null) {
+ ModulesCache.put(this.modulePath, cache = new HashMap<String,IModule>());
+ }
+ cache.put(String.valueOf(moduleDecl.name()), moduleDecl);
+ }
+ }
}
protected void addToPackageCache(String packageName, boolean endsWithSep) {
if (this.packageCache.contains(packageName))
@@ -178,11 +238,6 @@ public class ClasspathJep247 extends ClasspathLocation {
return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName));
}
@Override
- public boolean hasCompilationUnit(String qualifiedPackageName, String moduleName) {
- // TOOD: Revisit
- return false;
- }
- @Override
public void reset() {
try {
super.reset();
@@ -224,8 +279,4 @@ public class ClasspathJep247 extends ClasspathLocation {
return BINARY;
}
- @Override
- public IModule getModule() {
- return null;
- }
}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
index d7de9a9b43..64e28bb6e6 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathJrt.java
@@ -45,7 +45,7 @@ public class ClasspathJrt extends ClasspathLocation implements IMultiModuleEntry
public File file;
protected ZipFile annotationZipFile;
protected boolean closeZipFileAtEnd;
- private static HashMap<String, Map<String,IModule>> ModulesCache = new HashMap<>();
+ protected static HashMap<String, Map<String,IModule>> ModulesCache = new HashMap<>();
public final Set<String> moduleNamesCache;
//private Set<String> packageCache;
protected List<String> annotationPaths;
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathMultiReleaseJar.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathMultiReleaseJar.java
new file mode 100644
index 0000000000..41756884ec
--- /dev/null
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ClasspathMultiReleaseJar.java
@@ -0,0 +1,172 @@
+package org.eclipse.jdt.internal.compiler.batch;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.zip.ZipEntry;
+
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+public class ClasspathMultiReleaseJar extends ClasspathJar {
+ private java.nio.file.FileSystem fs = null;
+ Path releasePath = null;
+ String compliance = null;
+
+ public ClasspathMultiReleaseJar(File file, boolean closeZipFileAtEnd,
+ AccessRuleSet accessRuleSet, String destinationPath, String compliance) {
+ super(file, closeZipFileAtEnd, accessRuleSet, destinationPath);
+ this.compliance = compliance;
+ }
+ @Override
+ public void initialize() throws IOException {
+ super.initialize();
+ URI t = this.file.toURI();
+ if (this.file.exists()) {
+ URI uri = URI.create("jar:file:" + t.getRawPath()); //$NON-NLS-1$
+ try {
+ this.fs = FileSystems.getFileSystem(uri);
+ } catch(FileSystemNotFoundException fne) {
+ // Ignore and move on
+ }
+ if (this.fs == null) {
+ HashMap<String, ?> env = new HashMap<>();
+ try {
+ this.fs = FileSystems.newFileSystem(uri, env);
+ } catch (IOException e) {
+ // return
+ }
+ }
+ this.releasePath = this.fs.getPath("/", "META-INF", "versions", this.compliance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (!Files.exists(this.releasePath)) {
+ this.releasePath = null;
+ }
+ }
+ }
+ @SuppressWarnings("rawtypes")
+ @Override
+ public synchronized char[][] getModulesDeclaringPackage(String qualifiedPackageName, String moduleName) {
+ if (this.releasePath == null) {
+ return super.getModulesDeclaringPackage(qualifiedPackageName, moduleName);
+ }
+ if (this.packageCache != null)
+ return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName));
+
+ this.packageCache = new HashSet<>(41);
+ this.packageCache.add(Util.EMPTY_STRING);
+
+ for (Enumeration e = this.zipFile.entries(); e.hasMoreElements(); ) {
+ String fileName = ((ZipEntry) e.nextElement()).getName();
+ addToPackageCache(fileName, false);
+ }
+ try {
+ if (this.releasePath != null && Files.exists(this.releasePath)) {
+ // go through the packages
+ try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
+ for (final java.nio.file.Path subdir: stream) {
+ Files.walkFileTree(subdir, new FileVisitor<java.nio.file.Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ @Override
+ public FileVisitResult visitFile(java.nio.file.Path f, BasicFileAttributes attrs)
+ throws IOException {
+ Path p = ClasspathMultiReleaseJar.this.releasePath.relativize(f);
+ addToPackageCache(p.toString(), false);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(java.nio.file.Path f, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ // move on;
+ }
+ return singletonModuleNameIf(this.packageCache.contains(qualifiedPackageName));
+ }
+ @Override
+ public NameEnvironmentAnswer findClass(char[] binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly) {
+ if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case
+ if (this.releasePath != null) {
+ try {
+ Path p = this.releasePath.resolve(qualifiedBinaryFileName);
+ byte[] content = Files.readAllBytes(p);
+ IBinaryType reader = null;
+ if (content != null) {
+ reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
+ }
+ if (reader != null) {
+ char[] modName = this.module == null ? null : this.module.name();
+ if (reader instanceof ClassFileReader) {
+ ClassFileReader classReader = (ClassFileReader) reader;
+ if (classReader.moduleName == null)
+ classReader.moduleName = modName;
+ else
+ modName = classReader.moduleName;
+ }
+ String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+ searchPaths:
+ if (this.annotationPaths != null) {
+ String qualifiedClassName = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length()-SuffixConstants.EXTENSION_CLASS.length()-1);
+ for (String annotationPath : this.annotationPaths) {
+ try {
+ if (this.annotationZipFile == null) {
+ this.annotationZipFile = ExternalAnnotationDecorator.getAnnotationZipFile(annotationPath, null);
+ }
+ reader = ExternalAnnotationDecorator.create(reader, annotationPath, qualifiedClassName, this.annotationZipFile);
+
+ if (reader.getExternalAnnotationStatus() == ExternalAnnotationStatus.TYPE_IS_ANNOTATED) {
+ break searchPaths;
+ }
+ } catch (IOException e) {
+ // don't let error on annotations fail class reading
+ }
+ }
+ // location is configured for external annotations, but no .eea found, decorate in order to answer NO_EEA_FILE:
+ reader = new ExternalAnnotationDecorator(reader, null);
+ }
+ if (this.accessRuleSet == null)
+ return new NameEnvironmentAnswer(reader, null, modName);
+ return new NameEnvironmentAnswer(reader,
+ this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()),
+ modName);
+ }
+ } catch (IOException | ClassFormatException e) {
+ // treat as if class file is missing
+ }
+ }
+ return super.findClass(binaryFileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly);
+ }
+}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index ae2c63a02a..492067b88c 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -179,7 +179,7 @@ protected FileSystem(String[] classpathNames, String[] initialFileNames, String
this.classpaths = new Classpath[classpathSize];
int counter = 0;
for (int i = 0; i < classpathSize; i++) {
- Classpath classpath = getClasspath(classpathNames[i], encoding, null, null);
+ Classpath classpath = getClasspath(classpathNames[i], encoding, null, null, null);
try {
classpath.initialize();
for (String moduleName : classpath.getModuleNames(limitModules))
@@ -244,10 +244,10 @@ protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annot
this(paths, initialFileNames, annotationsFromClasspath, null);
}
public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) {
- return getClasspath(classpathName, encoding, false, accessRuleSet, null, null);
+ return getClasspath(classpathName, encoding, false, accessRuleSet, null, null, null);
}
-public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) {
- return getClasspath(classpathName, encoding, false, accessRuleSet, null, options);
+public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options, String release) {
+ return getClasspath(classpathName, encoding, false, accessRuleSet, null, options, release);
}
public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) {
return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null);
@@ -257,7 +257,7 @@ public static Classpath getOlderSystemRelease(String jdkHome, String release, Ac
}
public static Classpath getClasspath(String classpathName, String encoding,
boolean isSourceOnly, AccessRuleSet accessRuleSet,
- String destinationPath, Map<String, String> options) {
+ String destinationPath, Map<String, String> options, String release) {
Classpath result = null;
File file = new File(convertPathSeparators(classpathName));
if (file.isDirectory()) {
@@ -298,7 +298,10 @@ public static Classpath getClasspath(String classpathName, String encoding,
JRT_CLASSPATH_CACHE.put(file, result);
}
} else {
- result = new ClasspathJar(file, true, accessRuleSet, null);
+ result =
+ (release == null) ?
+ new ClasspathJar(file, true, accessRuleSet, null) :
+ new ClasspathMultiReleaseJar(file, true, accessRuleSet, destinationPath, release);
}
}
} else if (format == Util.JMOD_FILE) {
@@ -370,7 +373,7 @@ private void initializeKnownFileNames(String[] initialFileNames) {
public void scanForModules(Parser parser) {
for (int i = 0, max = this.classpaths.length; i < max; i++) {
File file = new File(this.classpaths[i].getPath());
- IModule iModule = ModuleFinder.scanForModule(this.classpaths[i], file, parser, false);
+ IModule iModule = ModuleFinder.scanForModule(this.classpaths[i], file, parser, false, null);
if (iModule != null)
this.moduleLocations.put(String.valueOf(iModule.name()), this.classpaths[i]);
}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index d65835471d..b2b6c5e932 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -1632,7 +1632,9 @@ protected void addNewEntry(ArrayList<FileSystem.Classpath> paths, String current
customEncoding,
isSourceOnly,
accessRuleSet,
- destPath, this.options);
+ destPath,
+ this.options,
+ this.releaseVersion);
if (currentClasspath != null) {
paths.add(currentClasspath);
} else if (currentClasspathName.length() != 0) {
@@ -3531,9 +3533,9 @@ protected ArrayList<FileSystem.Classpath> handleModulepath(String arg) {
File file = new File(path);
if (file.isDirectory()) {
result.addAll(
- ModuleFinder.findModules(file, null, getNewParser(), this.options, true));
+ ModuleFinder.findModules(file, null, getNewParser(), this.options, true, this.releaseVersion));
} else {
- Classpath modulePath = ModuleFinder.findModule(file, null, getNewParser(), this.options, true);
+ Classpath modulePath = ModuleFinder.findModule(file, null, getNewParser(), this.options, true, this.releaseVersion);
if (modulePath != null)
result.add(modulePath);
}
@@ -3559,7 +3561,7 @@ protected ArrayList<FileSystem.Classpath> handleModuleSourcepath(String arg) {
// 1. Create FileSystem.Classpath for each module
// 2. Iterator each module in case of directory for source files and add to this.fileNames
- List<Classpath> modules = ModuleFinder.findModules(dir, this.destinationPath, getNewParser(), this.options, false);
+ List<Classpath> modules = ModuleFinder.findModules(dir, this.destinationPath, getNewParser(), this.options, false, this.releaseVersion);
for (Classpath classpath : modules) {
result.add(classpath);
Path modLocation = Paths.get(classpath.getPath()).toAbsolutePath();
@@ -3607,7 +3609,7 @@ protected ArrayList<FileSystem.Classpath> handleClasspath(ArrayList<String> clas
String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
if ((classProp == null) || (classProp.length() == 0)) {
addPendingErrors(this.bind("configure.noClasspath")); //$NON-NLS-1$
- final Classpath classpath = FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null, this.options);//$NON-NLS-1$
+ final Classpath classpath = FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null, this.options, this.releaseVersion);//$NON-NLS-1$
if (classpath != null) {
initial.add(classpath);
}
@@ -3617,7 +3619,7 @@ protected ArrayList<FileSystem.Classpath> handleClasspath(ArrayList<String> clas
while (tokenizer.hasMoreTokens()) {
token = tokenizer.nextToken();
FileSystem.Classpath currentClasspath = FileSystem
- .getClasspath(token, customEncoding, null, this.options);
+ .getClasspath(token, customEncoding, null, this.options, this.releaseVersion);
if (currentClasspath != null) {
initial.add(currentClasspath);
} else if (token.length() != 0) {
@@ -3697,7 +3699,7 @@ protected ArrayList<FileSystem.Classpath> handleEndorseddirs(ArrayList<String> e
FileSystem.Classpath classpath =
FileSystem.getClasspath(
current[j].getAbsolutePath(),
- null, null, this.options);
+ null, null, this.options, this.releaseVersion);
if (classpath != null) {
result.add(classpath);
}
@@ -3758,7 +3760,7 @@ protected ArrayList<FileSystem.Classpath> handleExtdirs(ArrayList<String> extdir
FileSystem.Classpath classpath =
FileSystem.getClasspath(
current[j].getAbsolutePath(),
- null, null, this.options);
+ null, null, this.options, this.releaseVersion);
if (classpath != null) {
result.add(classpath);
}
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java
index 0ef53adfc0..1d48b3d0b2 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/ModuleFinder.java
@@ -19,6 +19,7 @@ import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jdt.internal.compiler.CompilationResult;
@@ -35,45 +36,46 @@ import org.eclipse.jdt.internal.compiler.util.Util;
public class ModuleFinder {
- public static List<FileSystem.Classpath> findModules(File f, String destinationPath, Parser parser, Map<String, String> options, boolean isModulepath) {
+ public static List<FileSystem.Classpath> findModules(File f, String destinationPath, Parser parser, Map<String, String> options, boolean isModulepath, String release) {
List<FileSystem.Classpath> collector = new ArrayList<>();
- scanForModules(destinationPath, parser, options, isModulepath, false, collector, f);
+ scanForModules(destinationPath, parser, options, isModulepath, false, collector, f, release);
return collector;
}
protected static FileSystem.Classpath findModule(final File file, String destinationPath, Parser parser,
- Map<String, String> options, boolean isModulepath) {
+ Map<String, String> options, boolean isModulepath, String release) {
FileSystem.Classpath modulePath = FileSystem.getClasspath(file.getAbsolutePath(), null, !isModulepath, null,
- destinationPath == null ? null : (destinationPath + File.separator + file.getName()), options);
+ destinationPath == null ? null : (destinationPath + File.separator + file.getName()), options, release);
if (modulePath != null) {
- scanForModule(modulePath, file, parser, isModulepath);
+ scanForModule(modulePath, file, parser, isModulepath, release);
}
return modulePath;
}
protected static void scanForModules(String destinationPath, Parser parser, Map<String, String> options, boolean isModulepath,
- boolean thisAnAutomodule, List<FileSystem.Classpath> collector, final File file) {
+ boolean thisAnAutomodule, List<FileSystem.Classpath> collector, final File file, String release) {
FileSystem.Classpath entry = FileSystem.getClasspath(
file.getAbsolutePath(),
null,
!isModulepath,
null,
destinationPath == null ? null : (destinationPath + File.separator + file.getName()),
- options);
+ options,
+ release);
if (entry != null) {
- IModule module = scanForModule(entry, file, parser, thisAnAutomodule);
+ IModule module = scanForModule(entry, file, parser, thisAnAutomodule, release);
if (module != null) {
collector.add(entry);
} else {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) {
- scanForModules(destinationPath, parser, options, isModulepath, isModulepath, collector, f);
+ scanForModules(destinationPath, parser, options, isModulepath, isModulepath, collector, f, release);
}
}
}
}
}
- protected static IModule scanForModule(FileSystem.Classpath modulePath, final File file, Parser parser, boolean considerAutoModules) {
+ protected static IModule scanForModule(FileSystem.Classpath modulePath, final File file, Parser parser, boolean considerAutoModules, String release) {
IModule module = null;
if (file.isDirectory()) {
String[] list = file.list(new FilenameFilter() {
@@ -106,7 +108,7 @@ public class ModuleFinder {
} else {
String moduleDescPath = getModulePathForArchive(file);
if (moduleDescPath != null) {
- module = extractModuleFromArchive(file, modulePath, moduleDescPath);
+ module = extractModuleFromArchive(file, modulePath, moduleDescPath, release);
}
}
if (considerAutoModules && module == null && !(modulePath instanceof ClasspathJrt)) {
@@ -224,10 +226,17 @@ public class ModuleFinder {
}
return null;
}
- private static IModule extractModuleFromArchive(File file, Classpath pathEntry, String path) {
+ private static IModule extractModuleFromArchive(File file, Classpath pathEntry, String path, String release) {
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
+ if (release != null) {
+ String releasePath = "META-INF/versions/" + release + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$
+ ZipEntry entry = zipFile.getEntry(releasePath);
+ if (entry != null) {
+ path = releasePath;
+ }
+ }
ClassFileReader reader = ClassFileReader.read(zipFile, path);
IModule module = getModule(reader);
if (module != null) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
index b7683aad29..fd4432b075 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/util/Util.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2017 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -1242,7 +1242,7 @@ public class Util implements SuffixConstants {
}
List<FileSystem.Classpath> classpaths = new ArrayList<>();
for (String filePath : filePaths) {
- FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null);
+ FileSystem.Classpath currentClasspath = FileSystem.getClasspath(filePath, null, null, null, null);
if (currentClasspath != null) {
classpaths.add(currentClasspath);
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
index 33136eb339..561c6084a6 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java
@@ -14,6 +14,8 @@ import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
@@ -27,8 +29,10 @@ import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.core.nd.IReader;
@@ -63,6 +67,9 @@ public class JarPackageFragmentRoot extends PackageFragmentRoot {
boolean knownToBeModuleLess;
+ private boolean multiVersion;
+ public String versionPath;
+
/**
* Constructs a package fragment root which is the root of the Java package directory hierarchy
* based on a JAR file that is not contained in a <code>IJavaProject</code> and
@@ -89,6 +96,7 @@ public class JarPackageFragmentRoot extends PackageFragmentRoot {
@Override
protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException {
final HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject();
+ final Set<String> overridden = new HashSet<>();
IJavaElement[] children;
try {
// always create the default package
@@ -125,15 +133,28 @@ public class JarPackageFragmentRoot extends PackageFragmentRoot {
// contain an up-to-date entry for this .jar) then fetch it directly from the .jar
if (!usedIndex) {
Object file = JavaModel.getTarget(getPath(), true);
- long level = Util.getJdkLevel(file);
- String compliance = CompilerOptions.versionFromJdkLevel(level);
+ long classLevel = Util.getJdkLevel(file);
+ String projectCompliance = this.getJavaProject().getOption(JavaCore.COMPILER_COMPLIANCE, true);
+ long projectLevel = CompilerOptions.versionToJdkLevel(projectCompliance);
ZipFile jar = null;
try {
jar = getJar();
-
+ String version = "META-INF/versions/" + projectCompliance + "/"; //$NON-NLS-1$//$NON-NLS-2$
+ int versionPathLength = version.length();
+ if (projectLevel >= ClassFileConstants.JDK9 && jar.getEntry(version) != null) {
+ this.multiVersion = true;
+ this.versionPath = version;
+ }
for (Enumeration e= jar.entries(); e.hasMoreElements();) {
ZipEntry member= (ZipEntry) e.nextElement();
- initRawPackageInfo(rawPackageInfo, member.getName(), member.isDirectory(), compliance);
+ String name = member.getName();
+ if (this.multiVersion && name.length() > versionPathLength && name.startsWith(version)) {
+ name = name.substring(version.length());
+ if (org.eclipse.jdt.internal.compiler.util.Util.isClassFileName(name)) {
+ overridden.add(name);
+ }
+ }
+ initRawPackageInfo(rawPackageInfo, name, member.isDirectory(), CompilerOptions.versionFromJdkLevel(classLevel));
}
} finally {
JavaModelManager.getJavaModelManager().closeZipFile(jar);
@@ -162,6 +183,7 @@ public class JarPackageFragmentRoot extends PackageFragmentRoot {
info.setChildren(children);
((JarPackageFragmentRootInfo) info).rawPackageInfo = rawPackageInfo;
+ ((JarPackageFragmentRootInfo) info).overriddenClasses = overridden;
return true;
}
protected IJavaElement[] createChildren(final HashtableOfArrayToObject rawPackageInfo) {
@@ -258,6 +280,21 @@ public class JarPackageFragmentRoot extends PackageFragmentRoot {
}
@Override
+ public String getClassFilePath(String classname) {
+ if (this.multiVersion) {
+ JarPackageFragmentRootInfo elementInfo;
+ try {
+ elementInfo = (JarPackageFragmentRootInfo) getElementInfo();
+ if (elementInfo.overriddenClasses.contains(classname)) {
+ return this.versionPath == null ? classname : this.versionPath + classname;
+ }
+ } catch (JavaModelException e) {
+ // move on
+ }
+ }
+ return classname;
+ }
+ @Override
public IModuleDescription getModuleDescription() {
if (this.knownToBeModuleLess)
return null;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
index 7955b082ed..113c5bfb37 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRootInfo.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2018 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.jdt.internal.core;
+import java.util.Set;
+
import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
/**
@@ -18,4 +20,6 @@ import org.eclipse.jdt.internal.core.util.HashtableOfArrayToObject;
class JarPackageFragmentRootInfo extends PackageFragmentRootInfo {
// a map from package name (String[]) to a size-2 array of Array<String>, the first element being the .class file names, and the second element being the non-Java resource names
HashtableOfArrayToObject rawPackageInfo;
+ Set<String> overriddenClasses;
+
}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 2e2ebaf7d2..39c1ee10e0 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -136,6 +136,8 @@ boolean closeZipFileAtEnd;
private SimpleSet knownPackageNames;
AccessRuleSet accessRuleSet;
String externalAnnotationPath;
+// Meant for ClasspathMultiReleaseJar, not used in here
+String compliance;
ClasspathJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath) {
this.resource = resource;
@@ -228,6 +230,9 @@ public boolean equals(Object o) {
if (this.accessRuleSet != jar.accessRuleSet)
if (this.accessRuleSet == null || !this.accessRuleSet.equals(jar.accessRuleSet))
return false;
+ if (!Util.equalOrNull(this.compliance, jar.compliance)) {
+ return false;
+ }
return this.zipFilename.equals(jar.zipFilename)
&& lastModified() == jar.lastModified()
&& this.isOnModulePath == jar.isOnModulePath
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
index f87c28e9bc..94c0ce3462 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJrt.java
@@ -58,7 +58,7 @@ String externalAnnotationPath;
private ZipFile annotationZipFile;
String zipFilename; // keep for equals
AccessRuleSet accessRuleSet;
-String compliance = null;
+String release = null;
String releaseInHex = null;
private Path releasePath = null;
private String[] subReleases = null;
@@ -66,15 +66,15 @@ private java.nio.file.FileSystem fs = null;
static final Set<String> NO_LIMIT_MODULES = new HashSet<>();
-public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, String compliance) {
+public ClasspathJrt(String zipFilename, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, String release) {
this.zipFilename = zipFilename;
this.accessRuleSet = accessRuleSet;
if (externalAnnotationPath != null)
this.externalAnnotationPath = externalAnnotationPath.toString();
- if (compliance != null && compliance.length() == 0) {
- this.compliance = null;
+ if (release != null && release.length() == 0) {
+ this.release = null;
} else {
- this.compliance = compliance;
+ this.release = release;
}
initialize();
loadModules(this);
@@ -172,11 +172,11 @@ public static void loadModules(final ClasspathJrt jrt) {
}
}
public void initialize() {
- if (this.compliance == null) {
+ if (this.release == null) {
return;
}
- this.compliance = getReleaseOptionFromCompliance(this.compliance);
- this.releaseInHex = Integer.toHexString(Integer.parseInt(this.compliance));
+ this.release = getReleaseOptionFromCompliance(this.release);
+ this.releaseInHex = Integer.toHexString(Integer.parseInt(this.release));
Path lib = Paths.get(this.zipFilename).getParent();
Path filePath = Paths.get(lib.toString(), "ct.sym"); //$NON-NLS-1$
URI t = filePath.toUri();
@@ -194,16 +194,16 @@ public void initialize() {
try {
this.fs = FileSystems.newFileSystem(uri, env);
} catch (IOException e) {
- this.compliance = null;
+ this.release = null;
return;
}
}
this.releasePath = this.fs.getPath("/"); //$NON-NLS-1$
if (!Files.exists(this.fs.getPath(this.releaseInHex))
|| Files.exists(this.fs.getPath(this.releaseInHex, "system-modules"))) { //$NON-NLS-1$
- this.compliance = null;
+ this.release = null;
}
- if (this.compliance != null) {
+ if (this.release != null) {
List<String> sub = new ArrayList<>();
try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
for (final java.nio.file.Path subdir: stream) {
@@ -262,6 +262,7 @@ public void cleanup() {
}
this.annotationZipFile = null;
}
+ this.fs = null;
}
@Override
@@ -269,7 +270,7 @@ public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClasspathJrt)) return false;
ClasspathJrt jar = (ClasspathJrt) o;
- if (!Util.equalOrNull(this.compliance, jar.compliance)) {
+ if (!Util.equalOrNull(this.release, jar.release)) {
return false;
}
if (this.accessRuleSet != jar.accessRuleSet)
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
index f524946a9e..6f1748cc5a 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathLocation.java
@@ -16,15 +16,18 @@ import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
+import java.util.zip.ZipFile;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.util.Util;
@@ -128,15 +131,15 @@ static ClasspathLocation forLibrary(String libraryPathname,
IPath annotationsPath,
boolean autoModule,
String compliance) {
- return Util.isJrt(libraryPathname) ?
- new ClasspathJrt(libraryPathname, accessRuleSet, annotationsPath, compliance) :
- Util.archiveFormat(libraryPathname) == Util.JMOD_FILE ?
+ return Util.archiveFormat(libraryPathname) == Util.JMOD_FILE ?
new ClasspathJMod(libraryPathname, lastModified, accessRuleSet, annotationsPath) :
- new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule);
+ (compliance == null || (CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK9) ?
+ new ClasspathJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule) :
+ new ClasspathMultiReleaseJar(libraryPathname, lastModified, accessRuleSet, annotationsPath, autoModule, compliance));
}
-static ClasspathJrt forJrtSystem(String jdkHome, AccessRuleSet accessRuleSet, IPath annotationsPath, String release) {
- return new ClasspathJrt(jdkHome, accessRuleSet, annotationsPath, release);
+static ClasspathJrt forJrtSystem(String jrtPath, AccessRuleSet accessRuleSet, IPath annotationsPath, String release) {
+ return new ClasspathJrt(jrtPath, accessRuleSet, annotationsPath, release);
}
public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet accessRuleSet, IPath annotationsPath,
@@ -145,8 +148,14 @@ public static ClasspathLocation forLibrary(String libraryPathname, AccessRuleSet
}
static ClasspathLocation forLibrary(IFile library, AccessRuleSet accessRuleSet, IPath annotationsPath,
- boolean autoModule) {
- return new ClasspathJar(library, accessRuleSet, annotationsPath, autoModule);
+ boolean autoModule, String compliance) {
+ return compliance == null ? new ClasspathJar(library, accessRuleSet, annotationsPath, autoModule) :
+ new ClasspathMultiReleaseJar(library, accessRuleSet, annotationsPath, autoModule, compliance);
+}
+public static ClasspathLocation forLibrary(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
+ return (CompilerOptions.versionToJdkLevel(compliance) < ClassFileConstants.JDK9) ?
+ new ClasspathJar(zipFile, accessRuleSet, externalAnnotationPath, isOnModulePath) :
+ new ClasspathMultiReleaseJar(zipFile, accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
}
public abstract IPath getProjectRelativePath();
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java
new file mode 100644
index 0000000000..d5954151de
--- /dev/null
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathMultiReleaseJar.java
@@ -0,0 +1,186 @@
+package org.eclipse.jdt.internal.core.builder;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystemNotFoundException;
+import java.nio.file.FileSystems;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.HashMap;
+import java.util.function.Predicate;
+import java.util.zip.ZipFile;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
+import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
+import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
+import org.eclipse.jdt.internal.compiler.env.IBinaryType;
+import org.eclipse.jdt.internal.compiler.env.IModule;
+import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
+import org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.ExternalAnnotationStatus;
+import org.eclipse.jdt.internal.compiler.util.SimpleSet;
+import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
+
+public class ClasspathMultiReleaseJar extends ClasspathJar {
+ private java.nio.file.FileSystem fs = null;
+ Path releasePath = null;
+
+ ClasspathMultiReleaseJar(IFile resource, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
+ super(resource, accessRuleSet, externalAnnotationPath, isOnModulePath);
+ this.compliance = compliance;
+ initializeVersions();
+ }
+
+ ClasspathMultiReleaseJar(String zipFilename, long lastModified, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
+ super(zipFilename, lastModified, accessRuleSet, externalAnnotationPath, isOnModulePath);
+ this.compliance = compliance;
+ initializeVersions();
+ }
+
+ public ClasspathMultiReleaseJar(ZipFile zipFile, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
+ this(zipFile.getName(), accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
+ this.zipFile = zipFile;
+ this.closeZipFileAtEnd = true;
+ }
+
+ public ClasspathMultiReleaseJar(String fileName, AccessRuleSet accessRuleSet, IPath externalAnnotationPath, boolean isOnModulePath, String compliance) {
+ this(fileName, 0, accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
+ if (externalAnnotationPath != null)
+ this.externalAnnotationPath = externalAnnotationPath.toString();
+ }
+ private void initializeVersions() {
+ Path filePath = Paths.get(this.zipFilename);
+ if (Files.exists(filePath)) {
+ URI uri = URI.create("jar:" + filePath.toUri()); //$NON-NLS-1$
+ try {
+ this.fs = FileSystems.getFileSystem(uri);
+ if (this.fs == null) {
+ HashMap<String, ?> env = new HashMap<>();
+ this.fs = FileSystems.newFileSystem(uri, env);
+ }
+ } catch (FileSystemNotFoundException | ProviderNotFoundException e) {
+ // move on
+ } catch (IOException e) {
+ // move on
+ }
+ if (this.fs == null) {
+ this.releasePath = null;
+ } else {
+ this.releasePath = this.fs.getPath("/", "META-INF", "versions", this.compliance); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if (!Files.exists(this.releasePath)) {
+ this.releasePath = null;
+ try {
+ this.fs.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+ }
+ @Override
+ protected String readJarContent(final SimpleSet packageSet) {
+ String[] modInfo = new String[1];
+ modInfo[0] = super.readJarContent(packageSet);
+ try {
+ if (this.releasePath != null && Files.exists(this.releasePath)) {
+ // go through the packages
+ try (DirectoryStream<java.nio.file.Path> stream = Files.newDirectoryStream(this.releasePath)) {
+ for (final java.nio.file.Path subdir: stream) {
+ Files.walkFileTree(subdir, new FileVisitor<java.nio.file.Path>() {
+ @Override
+ public FileVisitResult preVisitDirectory(java.nio.file.Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ @Override
+ public FileVisitResult visitFile(java.nio.file.Path file, BasicFileAttributes attrs)
+ throws IOException {
+ Path p = ClasspathMultiReleaseJar.this.releasePath.relativize(file);
+ addToPackageSet(packageSet, p.toString(), false);
+ if (modInfo[0] == null) {
+ if (p.getFileName().toString().equalsIgnoreCase(IModule.MODULE_INFO_CLASS)) {
+ modInfo[0] = ClasspathMultiReleaseJar.this.releasePath.relativize(file).toString();
+ }
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(java.nio.file.Path file, IOException exc) throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+ }
+ }
+ } catch (Exception e) {
+ // move on;
+ }
+ return modInfo[0];
+ }
+ @Override
+ public NameEnvironmentAnswer findClass(String binaryFileName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly, Predicate<String> moduleNameFilter) {
+ if (!isPackage(qualifiedPackageName, moduleName)) return null; // most common case
+ if (this.releasePath != null) {
+ try {
+ Path path = this.releasePath.resolve(qualifiedPackageName).resolve(binaryFileName);
+ byte[] content = Files.readAllBytes(path);
+ IBinaryType reader = null;
+ if (content != null) {
+ reader = new ClassFileReader(content, qualifiedBinaryFileName.toCharArray());
+ }
+ if (reader != null) {
+ char[] modName = this.module == null ? null : this.module.name();
+ if (reader instanceof ClassFileReader) {
+ ClassFileReader classReader = (ClassFileReader) reader;
+ if (classReader.moduleName == null)
+ classReader.moduleName = modName;
+ else
+ modName = classReader.moduleName;
+ }
+ String fileNameWithoutExtension = qualifiedBinaryFileName.substring(0, qualifiedBinaryFileName.length() - SuffixConstants.SUFFIX_CLASS.length);
+ if (this.externalAnnotationPath != null) {
+ try {
+ if (this.annotationZipFile == null) {
+ this.annotationZipFile = ExternalAnnotationDecorator
+ .getAnnotationZipFile(this.externalAnnotationPath, null);
+ }
+
+ reader = ExternalAnnotationDecorator.create(reader, this.externalAnnotationPath,
+ fileNameWithoutExtension, this.annotationZipFile);
+ } catch (IOException e) {
+ // don't let error on annotations fail class reading
+ }
+ if (reader.getExternalAnnotationStatus() == ExternalAnnotationStatus.NOT_EEA_CONFIGURED) {
+ // ensure a reader that answers NO_EEA_FILE
+ reader = new ExternalAnnotationDecorator(reader, null);
+ }
+ }
+ if (this.accessRuleSet == null)
+ return new NameEnvironmentAnswer(reader, null, modName);
+ return new NameEnvironmentAnswer(reader,
+ this.accessRuleSet.getViolatedRestriction(fileNameWithoutExtension.toCharArray()),
+ modName);
+ }
+ } catch (IOException | ClassFormatException e) {
+ // treat as if class file is missing
+ }
+ }
+ return super.findClass(binaryFileName, qualifiedPackageName, moduleName, qualifiedBinaryFileName, asBinaryOnly, moduleNameFilter);
+ }
+}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
index d0137019b3..7111f9401c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java
@@ -268,7 +268,7 @@ private void computeClasspathLocations(
&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
? null
: entry.getAccessRuleSet();
- bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath, isOnModulePath);
+ bLocation = ClasspathLocation.forLibrary((IFile) resource, accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
} else if (resource instanceof IContainer) {
AccessRuleSet accessRuleSet =
(JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_FORBIDDEN_REFERENCE, true))
@@ -302,10 +302,14 @@ private void computeClasspathLocations(
&& JavaCore.IGNORE.equals(javaProject.getOption(JavaCore.COMPILER_PB_DISCOURAGED_REFERENCE, true)))
? null
: entry.getAccessRuleSet();
- if (JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.COMPILER_RELEASE, true))) {
- compliance = null;
+ String release = JavaCore.DISABLED.equals(javaProject.getOption(JavaCore.COMPILER_RELEASE, true)) ? null : compliance;
+ ClasspathLocation bLocation = null;
+ String libPath = path.toOSString();
+ if (Util.isJrt(libPath)) {
+ bLocation = ClasspathLocation.forJrtSystem(path.toOSString(), accessRuleSet, externalAnnotationPath, release);
+ } else {
+ bLocation = ClasspathLocation.forLibrary(path.toOSString(), accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
}
- ClasspathLocation bLocation = ClasspathLocation.forLibrary(path.toOSString(), accessRuleSet, externalAnnotationPath, isOnModulePath, compliance);
bLocations.add(bLocation);
if (moduleEntries != null) {
Set<String> libraryLimitModules = (limitModules == null && projectModule != null) ? ClasspathJrt.NO_LIMIT_MODULES : limitModules;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
index ab7d9c5b08..959aa62932 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/State.java
@@ -54,7 +54,7 @@ private long previousStructuralBuildTime;
private StringSet structurallyChangedTypes;
public static int MaxStructurallyChangedTypes = 100; // keep track of ? structurally changed types, otherwise consider all to be changed
-public static final byte VERSION = 0x0020;
+public static final byte VERSION = 0x0021;
static final byte SOURCE_FOLDER = 1;
static final byte BINARY_FOLDER = 2;
@@ -282,13 +282,16 @@ static State read(IProject project, DataInputStream in) throws IOException {
break;
case EXTERNAL_JAR :
String jarPath = in.readUTF();
- boolean jrt = Util.isJrt(jarPath);
- newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
- readRestriction(in), new Path(in.readUTF()), jrt ? false : in.readBoolean(), jrt ? in.readUTF() : ""); //$NON-NLS-1$
+ if (Util.isJrt(jarPath)) {
+ newState.binaryLocations[i] = ClasspathLocation.forJrtSystem(jarPath, readRestriction(in), new Path(in.readUTF()), in.readUTF());
+ } else {
+ newState.binaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
+ readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
+ }
break;
case INTERNAL_JAR :
newState.binaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
- readRestriction(in), new Path(in.readUTF()), in.readBoolean());
+ readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
break;
}
ClasspathLocation loc = newState.binaryLocations[i];
@@ -356,13 +359,16 @@ static State read(IProject project, DataInputStream in) throws IOException {
break;
case EXTERNAL_JAR :
String jarPath = in.readUTF();
- boolean jrt = Util.isJrt(jarPath);
- newState.testBinaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
- readRestriction(in), new Path(in.readUTF()), jrt ? false : in.readBoolean(), jrt ? in.readUTF() : ""); //$NON-NLS-1$
+ if (Util.isJrt(jarPath)) {
+ newState.testBinaryLocations[i] = ClasspathLocation.forJrtSystem(jarPath, readRestriction(in), new Path(in.readUTF()), in.readUTF());
+ } else {
+ newState.testBinaryLocations[i] = ClasspathLocation.forLibrary(jarPath, in.readLong(),
+ readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
+ }
break;
case INTERNAL_JAR :
newState.testBinaryLocations[i] = ClasspathLocation.forLibrary(root.getFile(new Path(in.readUTF())),
- readRestriction(in), new Path(in.readUTF()), in.readBoolean());
+ readRestriction(in), new Path(in.readUTF()), in.readBoolean(), in.readUTF());
break;
}
}
@@ -558,14 +564,15 @@ void write(DataOutputStream out) throws IOException {
writeRestriction(jar.accessRuleSet, out);
out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$
out.writeBoolean(jar.isOnModulePath);
+ out.writeUTF(jar.compliance == null ? "" : jar.compliance); //$NON-NLS-1$
+
} else {
ClasspathJrt jrt = (ClasspathJrt) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
- out.writeLong(-1);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
- out.writeUTF(jrt.compliance != null ? jrt.compliance : ""); //$NON-NLS-1$
+ out.writeUTF(jrt.release != null ? jrt.release : ""); //$NON-NLS-1$
}
char[] patchName = c.patchModuleName == null ? CharOperation.NO_CHAR : c.patchModuleName.toCharArray();
writeName(patchName, out);
@@ -670,14 +677,14 @@ void write(DataOutputStream out) throws IOException {
writeRestriction(jar.accessRuleSet, out);
out.writeUTF(jar.externalAnnotationPath != null ? jar.externalAnnotationPath : ""); //$NON-NLS-1$
out.writeBoolean(jar.isOnModulePath);
+ out.writeUTF(jar.compliance != null ? jar.compliance : ""); //$NON-NLS-1$
} else {
ClasspathJrt jrt = (ClasspathJrt) c;
out.writeByte(EXTERNAL_JAR);
out.writeUTF(jrt.zipFilename);
- out.writeLong(-1);
writeRestriction(jrt.accessRuleSet, out);
out.writeUTF(jrt.externalAnnotationPath != null ? jrt.externalAnnotationPath : ""); //$NON-NLS-1$
- out.writeUTF(jrt.compliance != null ? jrt.compliance : ""); //$NON-NLS-1$
+ out.writeUTF(jrt.release != null ? jrt.release : ""); //$NON-NLS-1$
}
}
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
index 46f5035e8b..d5e26b9bda 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/nd/java/model/BinaryTypeFactory.java
@@ -64,21 +64,24 @@ public class BinaryTypeFactory {
* a location on the filesystem.
*/
private static BinaryTypeDescriptor createDescriptor(PackageFragment pkg, ClassFile classFile) {
- String name = classFile.getName();
PackageFragmentRoot root = (PackageFragmentRoot) pkg.getParent();
IPath location = JavaIndex.getLocationForElement(root);
if (location == null) {
return null;
}
- name = root.getClassFilePath(Util.concatWith(pkg.names, name, '/'));
String entryName = Util.concatWith(pkg.names, classFile.getElementName(), '/');
+ String name = Util.concatWith(pkg.names, classFile.getName(), '/');
+ String overridePath = root.getClassFilePath(entryName);
+ if (overridePath != entryName) {
+ entryName = overridePath;
+ name = ((JarPackageFragmentRoot) root).versionPath + name;
+ }
char[] fieldDescriptor = CharArrayUtils.concat(new char[] { 'L' },
name.toCharArray(), new char[] { ';' });
IPath workspacePath = root.getPath();
String indexPath;
if (root instanceof JarPackageFragmentRoot) {
- entryName = ((JarPackageFragmentRoot) root).getClassFilePath(entryName);
// The old version returned this, but it doesn't conform to the spec on IBinaryType.getFileName():
indexPath = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName;
// Version that conforms to the JavaDoc spec on IBinaryType.getFileName() -- note that this breaks
diff --git a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
index 480bb6e640..dd2bd66985 100644
--- a/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
+++ b/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java
@@ -46,7 +46,6 @@ import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.JrtPackageFragmentRoot;
import org.eclipse.jdt.internal.core.NameLookup;
import org.eclipse.jdt.internal.core.PackageFragmentRoot;
-import org.eclipse.jdt.internal.core.builder.ClasspathJar;
import org.eclipse.jdt.internal.core.builder.ClasspathJrt;
import org.eclipse.jdt.internal.core.builder.ClasspathLocation;
import org.eclipse.jdt.internal.core.util.Util;
@@ -162,10 +161,10 @@ private ClasspathLocation mapToClassPathLocation(JavaModelManager manager, Packa
cp = (root instanceof JrtPackageFragmentRoot) ?
new ClasspathJrt(path.toOSString(), rawClasspathEntry.getAccessRuleSet(),
ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry, project.getProject(), true), compliance) :
- new ClasspathJar(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(),
- ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry,
- ((IJavaProject) root.getParent()).getProject(), true),
- rawClasspathEntry.isModular());
+ ClasspathLocation.forLibrary(manager.getZipFile(path), rawClasspathEntry.getAccessRuleSet(),
+ ClasspathEntry.getExternalAnnotationPath(rawClasspathEntry,
+ ((IJavaProject) root.getParent()).getProject(), true),
+ rawClasspathEntry.isModular(), compliance) ;
} else {
Object target = JavaModel.getTarget(path, true);
if (target != null) {

Back to the top