This is an automated email from the ASF dual-hosted git repository. geertjan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-netbeans.git
The following commit(s) were added to refs/heads/master by this push: new 8a773b5 Adding utilities to construct boot classpath and module boot classpath on both JDK 8 and JDK 9+ (replaces TestUtil.getBootClassPath). Using it in hint tests and completion tests. (#430) 8a773b5 is described below commit 8a773b5aa86847acdb2fe3166bf568daa2676bb9 Author: Jan Lahoda <lah...@gmail.com> AuthorDate: Tue Feb 20 09:34:42 2018 +0100 Adding utilities to construct boot classpath and module boot classpath on both JDK 8 and JDK 9+ (replaces TestUtil.getBootClassPath). Using it in hint tests and completion tests. (#430) --- .../java/completion/CompletionTestBase.java | 13 +- java.hints.test/nbproject/project.properties | 2 +- java.hints.test/nbproject/project.xml | 29 +- .../modules/java/hints/test/BootClassPathUtil.java | 307 +++++++++++++++++++++ .../modules/java/hints/test/api/HintTest.java | 49 +--- .../modules/java/hints/test/api/HintTestTest.java | 18 ++ java.hints/nbproject/project.xml | 3 + .../modules/java/source/BootClassPathUtil.java | 307 +++++++++++++++++++++ .../org/netbeans/modules/java/source/TestUtil.java | 60 +--- 9 files changed, 682 insertions(+), 106 deletions(-) diff --git a/java.completion/test/unit/src/org/netbeans/modules/java/completion/CompletionTestBase.java b/java.completion/test/unit/src/org/netbeans/modules/java/completion/CompletionTestBase.java index 7e77cfe..217f8a9 100644 --- a/java.completion/test/unit/src/org/netbeans/modules/java/completion/CompletionTestBase.java +++ b/java.completion/test/unit/src/org/netbeans/modules/java/completion/CompletionTestBase.java @@ -55,6 +55,7 @@ import org.netbeans.api.lexer.Language; import org.netbeans.core.startup.Main; import org.netbeans.junit.NbTestCase; import org.netbeans.modules.java.JavaDataLoader; +import org.netbeans.modules.java.source.BootClassPathUtil; import org.netbeans.modules.java.source.TestUtil; import org.netbeans.modules.java.source.indexing.TransactionContext; import org.netbeans.modules.java.source.usages.BinaryAnalyser; @@ -118,6 +119,7 @@ public class CompletionTestBase extends NbTestCase { protected void setUp() throws Exception { ClassPathProvider cpp = new ClassPathProvider() { volatile ClassPath bootCache; + volatile ClassPath moduleBootCache; @Override public ClassPath findClassPath(FileObject file, String type) { try { @@ -127,10 +129,17 @@ public class CompletionTestBase extends NbTestCase { if (type.equals(ClassPath.COMPILE)) { return ClassPathSupport.createClassPath(new FileObject[0]); } - if (type.equals(ClassPath.BOOT) || type.equals(JavaClassPathConstants.MODULE_BOOT_PATH)) { + if (type.equals(ClassPath.BOOT)) { ClassPath cp = bootCache; if (cp == null) { - cp = TestUtil.getBootClassPath(); + bootCache = cp = BootClassPathUtil.getBootClassPath(); + } + return cp; + } + if (type.equals(JavaClassPathConstants.MODULE_BOOT_PATH)) { + ClassPath cp = moduleBootCache; + if (cp == null) { + moduleBootCache = cp = BootClassPathUtil.getModuleBootPath(); } return cp; } diff --git a/java.hints.test/nbproject/project.properties b/java.hints.test/nbproject/project.properties index 0bc79b3..f211965 100644 --- a/java.hints.test/nbproject/project.properties +++ b/java.hints.test/nbproject/project.properties @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. is.autoload=true -javac.source=1.7 +javac.source=1.8 javac.compilerargs=-Xlint -Xlint:-serial spec.version.base=1.19.0 javadoc.arch=${basedir}/arch.xml diff --git a/java.hints.test/nbproject/project.xml b/java.hints.test/nbproject/project.xml index 0a5da9d..fc7a21a 100644 --- a/java.hints.test/nbproject/project.xml +++ b/java.hints.test/nbproject/project.xml @@ -87,6 +87,13 @@ </run-dependency> </dependency> <dependency> + <code-name-base>org.netbeans.modules.java.j2seplatform</code-name-base> + <run-dependency> + <release-version>1</release-version> + <specification-version>1.42</specification-version> + </run-dependency> + </dependency> + <dependency> <code-name-base>org.netbeans.modules.java.lexer</code-name-base> <build-prerequisite/> <compile-dependency/> @@ -147,6 +154,12 @@ </run-dependency> </dependency> <dependency> + <code-name-base>org.netbeans.modules.parsing.nb</code-name-base> + <run-dependency> + <specification-version>1.4</specification-version> + </run-dependency> + </dependency> + <dependency> <code-name-base>org.netbeans.modules.projectapi</code-name-base> <build-prerequisite/> <compile-dependency/> @@ -156,6 +169,12 @@ </run-dependency> </dependency> <dependency> + <code-name-base>org.netbeans.modules.projectapi.nb</code-name-base> + <run-dependency> + <specification-version>1.4</specification-version> + </run-dependency> + </dependency> + <dependency> <code-name-base>org.netbeans.modules.projectuiapi</code-name-base> <build-prerequisite/> <compile-dependency/> @@ -231,7 +250,7 @@ </run-dependency> </dependency> <dependency> - <code-name-base>org.openide.util.ui</code-name-base> + <code-name-base>org.openide.util</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> @@ -239,19 +258,19 @@ </run-dependency> </dependency> <dependency> - <code-name-base>org.openide.util</code-name-base> + <code-name-base>org.openide.util.lookup</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>9.3</specification-version> + <specification-version>8.12</specification-version> </run-dependency> </dependency> <dependency> - <code-name-base>org.openide.util.lookup</code-name-base> + <code-name-base>org.openide.util.ui</code-name-base> <build-prerequisite/> <compile-dependency/> <run-dependency> - <specification-version>8.12</specification-version> + <specification-version>9.8</specification-version> </run-dependency> </dependency> </module-dependencies> diff --git a/java.hints.test/src/org/netbeans/modules/java/hints/test/BootClassPathUtil.java b/java.hints.test/src/org/netbeans/modules/java/hints/test/BootClassPathUtil.java new file mode 100644 index 0000000..4e44114 --- /dev/null +++ b/java.hints.test/src/org/netbeans/modules/java/hints/test/BootClassPathUtil.java @@ -0,0 +1,307 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.test; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.spi.java.classpath.PathResourceImplementation; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; +import org.openide.util.BaseUtilities; + +import static junit.framework.TestCase.assertFalse; +import org.openide.filesystems.MultiFileSystem; +import org.openide.filesystems.Repository; + +/** Note this is duplicated in: + * java.source.base/test/unit/src/org/netbeans/modules/java/source/BootClassPathUtil.java + * + * @author lahvac + */ +public class BootClassPathUtil { + + public static ClassPath getBootClassPath() { + String cp = System.getProperty("sun.boot.class.path"); + if (cp != null) { + List<URL> urls = new ArrayList<>(); + String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator"))); + for (String path : paths) { + File f = new File(path); + + if (!f.canRead()) + continue; + + FileObject fo = FileUtil.toFileObject(f); + if (FileUtil.isArchiveFile(fo)) { + fo = FileUtil.getArchiveRoot(fo); + } + if (fo != null) { + urls.add(fo.toURL()); + } + } + return ClassPathSupport.createClassPath((URL[])urls.toArray(new URL[0])); + } else { + try { + Class.forName("org.netbeans.ProxyURLStreamHandlerFactory").getMethod("register") + .invoke(null); + } catch (ClassNotFoundException | NoSuchMethodException | + SecurityException | IllegalAccessException | + IllegalArgumentException | InvocationTargetException ex) { + throw new IllegalStateException(ex); + } + final List<PathResourceImplementation> modules = new ArrayList<>(); + final File installDir = new File(System.getProperty("java.home")); + final URI imageURI = getImageURI(installDir); + try { + final FileObject jrtRoot = URLMapper.findFileObject(imageURI.toURL()); + final FileObject root = getModulesRoot(jrtRoot); + for (FileObject module : root.getChildren()) { + modules.add(ClassPathSupport.createResource(module.toURL())); + } + } catch (MalformedURLException e) { + throw new IllegalStateException(e); + } + assertFalse(modules.isEmpty()); + return ClassPathSupport.createClassPath(modules); + } + } + + public static ClassPath getModuleBootPath() { + if (System.getProperty("sun.boot.class.path") != null) { + try { + //JDK 8: + return getModuleBootOnJDK8(); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } else { + return getBootClassPath(); + } + } + + private static final String PROTOCOL = "nbjrt"; //NOI18N + + private static URI getImageURI(@NonNull final File jdkHome) { + try { + return new URI(String.format( + "%s:%s!/%s", //NOI18N + PROTOCOL, + BaseUtilities.toURI(jdkHome).toString(), + "")); + } catch (URISyntaxException e) { + throw new IllegalStateException(); + } + } + + @NonNull + private static FileObject getModulesRoot(@NonNull final FileObject jrtRoot) { + final FileObject modules = jrtRoot.getFileObject("modules"); //NOI18N + //jimage v1 - modules are located in the root + //jimage v2 - modules are located in "modules" folder + return modules == null ? + jrtRoot : + modules; + } + + //create fake "system module path" while running on JDK 8 + //java.base contains rt.jar and exports all java.* packages: + private static ClassPath moduleBootOnJDK8; + + private static ClassPath getModuleBootOnJDK8() throws Exception { + if (moduleBootOnJDK8 == null) { + List<FileSystem> roots = new ArrayList<>(); + + FileSystem output = FileUtil.createMemoryFileSystem(); + FileObject sink = output.getRoot(); + + roots.add(output); + + Set<String> packages = new HashSet<>(); + for (FileObject r : getBootClassPath().getRoots()) { + FileObject javaDir = r.getFileObject("java"); + + if (javaDir == null) + continue; + + roots.add(r.getFileSystem()); + + Enumeration<? extends FileObject> c = javaDir.getChildren(true); + + while (c.hasMoreElements()) { + FileObject current = c.nextElement(); + + if (!current.isData() || !current.hasExt("class")) continue; + + String rel = FileUtil.getRelativePath(r, current.getParent()); + + packages.add(rel.replace('/', '.')); + } + } + + FileSystem outS = new MultiFileSystem(roots.toArray(new FileSystem[0])) { + { + setSystemName("module-boot"); + } + }; + + Repository.getDefault().addFileSystem(outS); + + StringBuilder moduleInfo = new StringBuilder(); + + moduleInfo.append("module java.base {\n"); + + for (String pack : packages) { + moduleInfo.append(" exports " + pack + ";\n"); + } + + moduleInfo.append("}\n"); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + FileObject javaBase = outS.getRoot(); + + try (JavaFileManager fm = compiler.getStandardFileManager(null, null, null); + JFMImpl fmImpl = new JFMImpl(fm, javaBase, sink)) { + compiler.getTask(null, fmImpl, null, Arrays.asList("-proc:none"), null, + Arrays.asList(new SimpleJavaFileObject(new URI("mem:///module-info.java"), javax.tools.JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return moduleInfo.toString(); + } + })).call(); + } + + javaBase.refresh(); + moduleBootOnJDK8 = ClassPathSupport.createClassPath(javaBase); + } + + return moduleBootOnJDK8; + } + + private static class JFMImpl extends ForwardingJavaFileManager<JavaFileManager> { + private final FileObject output; + private final FileObject sink; + + public JFMImpl(JavaFileManager fileManager, FileObject output, FileObject sink) { + super(fileManager); + this.output = output; + this.sink = sink; + } + + @Override + public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException { + return Collections.emptyList(); + } + + @Override + public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT) { + List<JavaFileObject> result = new ArrayList<>(); + FileObject pack = output.getFileObject(packageName.replace('.', '/')); + + if (pack != null) { + Enumeration<? extends FileObject> c = pack.getChildren(recurse); + + while (c.hasMoreElements()) { + FileObject file = c.nextElement(); + if (!file.hasExt("class")) + continue; + result.add(new InferableJavaFileObject(file, JavaFileObject.Kind.CLASS)); + } + } + + return result; + } + return super.list(location, packageName, kinds, recurse); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, javax.tools.FileObject sibling) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT) { + String relPath = className.replace('.', '/') + ".class"; + try { + return new SimpleJavaFileObject(new URI("mem://" + relPath), kind) { + @Override + public OutputStream openOutputStream() throws IOException { + return new ByteArrayOutputStream() { + @Override + public void close() throws IOException { + super.close(); + FileObject target = FileUtil.createData(sink, relPath); + try (OutputStream out = target.getOutputStream()) { + out.write(toByteArray()); + } + } + }; + } + }; + } catch (URISyntaxException ex) { + throw new IOException(ex); + } + } + return super.getJavaFileForOutput(location, className, kind, sibling); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) { + if (file instanceof InferableJavaFileObject) { + return ((InferableJavaFileObject) file).className; + } + return super.inferBinaryName(location, file); + } + + private class InferableJavaFileObject extends SimpleJavaFileObject { + + private final String className; + public InferableJavaFileObject(FileObject file, Kind kind) { + super(file.toURI(), kind); + String relPath = FileUtil.getRelativePath(output, file); + className = relPath.substring(0, relPath.length() - ".class".length()).replace('/', '.'); + } + } + + } + +} diff --git a/java.hints.test/src/org/netbeans/modules/java/hints/test/api/HintTest.java b/java.hints.test/src/org/netbeans/modules/java/hints/test/api/HintTest.java index 202f548..98c80ce 100644 --- a/java.hints.test/src/org/netbeans/modules/java/hints/test/api/HintTest.java +++ b/java.hints.test/src/org/netbeans/modules/java/hints/test/api/HintTest.java @@ -56,13 +56,14 @@ import javax.swing.text.Document; import javax.tools.Diagnostic; import junit.framework.Assert; import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertFalse; import org.netbeans.api.editor.mimelookup.MimeLookup; import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.api.java.classpath.JavaClassPathConstants; import org.netbeans.api.java.lexer.JavaTokenId; import org.netbeans.api.java.queries.SourceForBinaryQuery; import org.netbeans.api.java.queries.SourceForBinaryQuery.Result; @@ -97,8 +98,10 @@ import org.netbeans.modules.java.hints.spiimpl.SyntheticFix; import org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities; import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker; import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings; +import org.netbeans.modules.java.hints.test.BootClassPathUtil; import org.netbeans.modules.java.hints.test.Utilities.TestLookup; import org.netbeans.modules.java.source.JavaSourceAccessor; +import org.netbeans.modules.java.source.parsing.JavacParser; import org.netbeans.modules.parsing.api.indexing.IndexingManager; import org.netbeans.modules.parsing.impl.indexing.CacheFolder; import org.netbeans.modules.parsing.impl.indexing.MimeTypes; @@ -261,6 +264,7 @@ public class HintTest { sourcePath = ClassPathSupport.createClassPath(sourceRoot); Main.initializeURLFactory(); + JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true; } /**Bootstraps the test framework. @@ -664,51 +668,18 @@ public class HintTest { } - private static List<URL> bootClassPath; - private static Logger log = Logger.getLogger(HintTest.class.getName()); - private static synchronized List<URL> getBootClassPath() { - if (bootClassPath == null) { - try { - String cp = System.getProperty("sun.boot.class.path"); - List<URL> urls = new ArrayList<URL>(); - String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator"))); - - for (String path : paths) { - File f = new File(path); - - if (!f.canRead()) - continue; - - FileObject fo = FileUtil.toFileObject(f); - - if (FileUtil.isArchiveFile(fo)) { - fo = FileUtil.getArchiveRoot(fo); - } - - if (fo != null) { - urls.add(fo.getURL()); - } - } - - bootClassPath = urls; - } catch (FileStateInvalidException e) { - if (log.isLoggable(Level.SEVERE)) - log.log(Level.SEVERE, e.getMessage(), e); - } - } - - return bootClassPath; - } - private class TestProxyClassPathProvider implements ClassPathProvider { public ClassPath findClassPath(FileObject file, String type) { try { if (ClassPath.BOOT == type) { - // XXX simpler to use JavaPlatformManager.getDefault().getDefaultPlatform().getBootstrapLibraries() - return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0])); + return BootClassPathUtil.getBootClassPath(); + } + + if (JavaClassPathConstants.MODULE_BOOT_PATH == type) { + return BootClassPathUtil.getModuleBootPath(); } if (ClassPath.SOURCE == type) { diff --git a/java.hints.test/test/unit/src/org/netbeans/modules/java/hints/test/api/HintTestTest.java b/java.hints.test/test/unit/src/org/netbeans/modules/java/hints/test/api/HintTestTest.java index a910d70..22a9970 100644 --- a/java.hints.test/test/unit/src/org/netbeans/modules/java/hints/test/api/HintTestTest.java +++ b/java.hints.test/test/unit/src/org/netbeans/modules/java/hints/test/api/HintTestTest.java @@ -302,4 +302,22 @@ public class HintTestTest { Assert.assertEquals("6\n7\n", doc.getText(0, doc.getLength())); } + @Test + public void testModuleBootPath() throws Exception { + HintTest.create() + .sourceLevel("9") + .input("module-info.java", + "module m1 {}\n") + .run(ModuleBootPath.class) + .assertWarnings("0:0-0:12:verifier:Test"); + } + + @Hint(displayName="testModuleBootPath", description="testModuleBootPath", category="test") + public static final class ModuleBootPath { + @TriggerTreeKind(Kind.MODULE) + public static ErrorDescription hint(HintContext ctx) { + return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Test"); + } + } + } diff --git a/java.hints/nbproject/project.xml b/java.hints/nbproject/project.xml index 04e5500..a328b25 100644 --- a/java.hints/nbproject/project.xml +++ b/java.hints/nbproject/project.xml @@ -544,6 +544,9 @@ <compile-dependency/> </test-dependency> <test-dependency> + <code-name-base>org.netbeans.modules.java.j2seplatform</code-name-base> + </test-dependency> + <test-dependency> <code-name-base>org.netbeans.modules.java.source.base</code-name-base> <compile-dependency/> <test/> diff --git a/java.source.base/test/unit/src/org/netbeans/modules/java/source/BootClassPathUtil.java b/java.source.base/test/unit/src/org/netbeans/modules/java/source/BootClassPathUtil.java new file mode 100644 index 0000000..7ea0fde --- /dev/null +++ b/java.source.base/test/unit/src/org/netbeans/modules/java/source/BootClassPathUtil.java @@ -0,0 +1,307 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.source; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; +import org.netbeans.api.annotations.common.NonNull; +import org.netbeans.api.java.classpath.ClassPath; +import org.netbeans.spi.java.classpath.PathResourceImplementation; +import org.netbeans.spi.java.classpath.support.ClassPathSupport; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileSystem; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; +import org.openide.util.BaseUtilities; + +import static junit.framework.TestCase.assertFalse; +import org.openide.filesystems.MultiFileSystem; +import org.openide.filesystems.Repository; + +/** Note this is duplicated in: + * java.hints.test/src/org/netbeans/modules/java/hints/test/BootClassPathUtil.java + * + * @author lahvac + */ +public class BootClassPathUtil { + + public static ClassPath getBootClassPath() { + String cp = System.getProperty("sun.boot.class.path"); + if (cp != null) { + List<URL> urls = new ArrayList<>(); + String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator"))); + for (String path : paths) { + File f = new File(path); + + if (!f.canRead()) + continue; + + FileObject fo = FileUtil.toFileObject(f); + if (FileUtil.isArchiveFile(fo)) { + fo = FileUtil.getArchiveRoot(fo); + } + if (fo != null) { + urls.add(fo.toURL()); + } + } + return ClassPathSupport.createClassPath((URL[])urls.toArray(new URL[0])); + } else { + try { + Class.forName("org.netbeans.ProxyURLStreamHandlerFactory").getMethod("register") + .invoke(null); + } catch (ClassNotFoundException | NoSuchMethodException | + SecurityException | IllegalAccessException | + IllegalArgumentException | InvocationTargetException ex) { + throw new IllegalStateException(ex); + } + final List<PathResourceImplementation> modules = new ArrayList<>(); + final File installDir = new File(System.getProperty("java.home")); + final URI imageURI = getImageURI(installDir); + try { + final FileObject jrtRoot = URLMapper.findFileObject(imageURI.toURL()); + final FileObject root = getModulesRoot(jrtRoot); + for (FileObject module : root.getChildren()) { + modules.add(ClassPathSupport.createResource(module.toURL())); + } + } catch (MalformedURLException e) { + throw new IllegalStateException(e); + } + assertFalse(modules.isEmpty()); + return ClassPathSupport.createClassPath(modules); + } + } + + public static ClassPath getModuleBootPath() { + if (System.getProperty("sun.boot.class.path") != null) { + try { + //JDK 8: + return getModuleBootOnJDK8(); + } catch (Exception ex) { + throw new IllegalStateException(ex); + } + } else { + return getBootClassPath(); + } + } + + private static final String PROTOCOL = "nbjrt"; //NOI18N + + private static URI getImageURI(@NonNull final File jdkHome) { + try { + return new URI(String.format( + "%s:%s!/%s", //NOI18N + PROTOCOL, + BaseUtilities.toURI(jdkHome).toString(), + "")); + } catch (URISyntaxException e) { + throw new IllegalStateException(); + } + } + + @NonNull + private static FileObject getModulesRoot(@NonNull final FileObject jrtRoot) { + final FileObject modules = jrtRoot.getFileObject("modules"); //NOI18N + //jimage v1 - modules are located in the root + //jimage v2 - modules are located in "modules" folder + return modules == null ? + jrtRoot : + modules; + } + + //create fake "system module path" while running on JDK 8 + //java.base contains rt.jar and exports all java.* packages: + private static ClassPath moduleBootOnJDK8; + + private static ClassPath getModuleBootOnJDK8() throws Exception { + if (moduleBootOnJDK8 == null) { + List<FileSystem> roots = new ArrayList<>(); + + FileSystem output = FileUtil.createMemoryFileSystem(); + FileObject sink = output.getRoot(); + + roots.add(output); + + Set<String> packages = new HashSet<>(); + for (FileObject r : getBootClassPath().getRoots()) { + FileObject javaDir = r.getFileObject("java"); + + if (javaDir == null) + continue; + + roots.add(r.getFileSystem()); + + Enumeration<? extends FileObject> c = javaDir.getChildren(true); + + while (c.hasMoreElements()) { + FileObject current = c.nextElement(); + + if (!current.isData() || !current.hasExt("class")) continue; + + String rel = FileUtil.getRelativePath(r, current.getParent()); + + packages.add(rel.replace('/', '.')); + } + } + + FileSystem outS = new MultiFileSystem(roots.toArray(new FileSystem[0])) { + { + setSystemName("module-boot"); + } + }; + + Repository.getDefault().addFileSystem(outS); + + StringBuilder moduleInfo = new StringBuilder(); + + moduleInfo.append("module java.base {\n"); + + for (String pack : packages) { + moduleInfo.append(" exports " + pack + ";\n"); + } + + moduleInfo.append("}\n"); + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + FileObject javaBase = outS.getRoot(); + + try (JavaFileManager fm = compiler.getStandardFileManager(null, null, null); + JFMImpl fmImpl = new JFMImpl(fm, javaBase, sink)) { + compiler.getTask(null, fmImpl, null, Arrays.asList("-proc:none"), null, + Arrays.asList(new SimpleJavaFileObject(new URI("mem:///module-info.java"), javax.tools.JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return moduleInfo.toString(); + } + })).call(); + } + + javaBase.refresh(); + moduleBootOnJDK8 = ClassPathSupport.createClassPath(javaBase); + } + + return moduleBootOnJDK8; + } + + private static class JFMImpl extends ForwardingJavaFileManager<JavaFileManager> { + private final FileObject output; + private final FileObject sink; + + public JFMImpl(JavaFileManager fileManager, FileObject output, FileObject sink) { + super(fileManager); + this.output = output; + this.sink = sink; + } + + @Override + public Iterable<Set<Location>> listLocationsForModules(Location location) throws IOException { + return Collections.emptyList(); + } + + @Override + public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT) { + List<JavaFileObject> result = new ArrayList<>(); + FileObject pack = output.getFileObject(packageName.replace('.', '/')); + + if (pack != null) { + Enumeration<? extends FileObject> c = pack.getChildren(recurse); + + while (c.hasMoreElements()) { + FileObject file = c.nextElement(); + if (!file.hasExt("class")) + continue; + result.add(new InferableJavaFileObject(file, JavaFileObject.Kind.CLASS)); + } + } + + return result; + } + return super.list(location, packageName, kinds, recurse); + } + + @Override + public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, javax.tools.FileObject sibling) throws IOException { + if (location == StandardLocation.CLASS_OUTPUT) { + String relPath = className.replace('.', '/') + ".class"; + try { + return new SimpleJavaFileObject(new URI("mem://" + relPath), kind) { + @Override + public OutputStream openOutputStream() throws IOException { + return new ByteArrayOutputStream() { + @Override + public void close() throws IOException { + super.close(); + FileObject target = FileUtil.createData(sink, relPath); + try (OutputStream out = target.getOutputStream()) { + out.write(toByteArray()); + } + } + }; + } + }; + } catch (URISyntaxException ex) { + throw new IOException(ex); + } + } + return super.getJavaFileForOutput(location, className, kind, sibling); + } + + @Override + public String inferBinaryName(Location location, JavaFileObject file) { + if (file instanceof InferableJavaFileObject) { + return ((InferableJavaFileObject) file).className; + } + return super.inferBinaryName(location, file); + } + + private class InferableJavaFileObject extends SimpleJavaFileObject { + + private final String className; + public InferableJavaFileObject(FileObject file, Kind kind) { + super(file.toURI(), kind); + String relPath = FileUtil.getRelativePath(output, file); + className = relPath.substring(0, relPath.length() - ".class".length()).replace('/', '.'); + } + } + + } + +} diff --git a/java.source.base/test/unit/src/org/netbeans/modules/java/source/TestUtil.java b/java.source.base/test/unit/src/org/netbeans/modules/java/source/TestUtil.java index cf658e7..8245627 100644 --- a/java.source.base/test/unit/src/org/netbeans/modules/java/source/TestUtil.java +++ b/java.source.base/test/unit/src/org/netbeans/modules/java/source/TestUtil.java @@ -405,65 +405,7 @@ public class TestUtil { } public static ClassPath getBootClassPath() { - String cp = System.getProperty("sun.boot.class.path"); - if (cp != null) { - List<URL> urls = new ArrayList<>(); - String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator"))); - for (String path : paths) { - File f = new File(path); - - if (!f.canRead()) - continue; - - FileObject fo = FileUtil.toFileObject(f); - if (FileUtil.isArchiveFile(fo)) { - fo = FileUtil.getArchiveRoot(fo); - } - if (fo != null) { - urls.add(fo.toURL()); - } - } - return ClassPathSupport.createClassPath((URL[])urls.toArray(new URL[0])); - } else { - ProxyURLStreamHandlerFactory.register(); - final List<PathResourceImplementation> modules = new ArrayList<>(); - final File installDir = new File(System.getProperty("java.home")); - final URI imageURI = getImageURI(installDir); - try { - final FileObject jrtRoot = URLMapper.findFileObject(imageURI.toURL()); - final FileObject root = getModulesRoot(jrtRoot); - for (FileObject module : root.getChildren()) { - modules.add(ClassPathSupport.createResource(module.toURL())); - } - } catch (MalformedURLException e) { - throw new IllegalStateException(e); - } - assertFalse(modules.isEmpty()); - return ClassPathSupport.createClassPath(modules); - } + return BootClassPathUtil.getBootClassPath(); } - private static final String PROTOCOL = "nbjrt"; //NOI18N - - private static URI getImageURI(@NonNull final File jdkHome) { - try { - return new URI(String.format( - "%s:%s!/%s", //NOI18N - PROTOCOL, - BaseUtilities.toURI(jdkHome).toString(), - "")); - } catch (URISyntaxException e) { - throw new IllegalStateException(); - } - } - - @NonNull - private static FileObject getModulesRoot(@NonNull final FileObject jrtRoot) { - final FileObject modules = jrtRoot.getFileObject("modules"); //NOI18N - //jimage v1 - modules are located in the root - //jimage v2 - modules are located in "modules" folder - return modules == null ? - jrtRoot : - modules; - } } -- To stop receiving notification emails like this one, please contact geert...@apache.org. --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org For additional commands, e-mail: commits-h...@netbeans.apache.org For further information about the NetBeans mailing lists, visit: https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists