Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -98,51 +98,30 @@ public static String categoryName(String id, Map<String, String> id2DisplayName)

//copied from BootClassPathUtil:
public static ClassPath createDefaultBootClassPath() {
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);
}
if (modules.isEmpty()) {
throw new IllegalStateException("No modules!");
try {
Class.forName("org.netbeans.ProxyURLStreamHandlerFactory").getMethod("register")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nasty.

Why?

Why this is needed? To provide special support for protocols like nbfs? Or to override support for standard protocols like jar?

Fix

Shalln't we (finally) have a way to register the factory in a more standard way, not using reflection like this?

If it was, then this code could be replaced by for (var p : ServiceLoader.load(URLStreamHandlerProvider.class)) { } - e.g. just by iterating over public classes the support could be enabled.

Or am I over simplifying the problem?

.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()));
}
return ClassPathSupport.createClassPath(modules);
} catch (MalformedURLException e) {
throw new IllegalStateException(e);
}
if (modules.isEmpty()) {
throw new IllegalStateException("No modules!");
}
return ClassPathSupport.createClassPath(modules);
}

private static final String PROTOCOL = "nbjrt"; //NOI18N
Expand Down
9 changes: 9 additions & 0 deletions cmdline/tool/nbproject/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@
<implementation-version/>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.java.j2seplatform</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<implementation-version/>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.java.project</code-name-base>
<build-prerequisite/>
Expand Down
136 changes: 131 additions & 5 deletions cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.lang.Runtime.Version;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -68,6 +69,7 @@
import joptsimple.OptionSet;
import org.netbeans.api.actions.Savable;
import org.netbeans.api.java.classpath.ClassPath;
import org.netbeans.api.java.classpath.JavaClassPathConstants;
import org.netbeans.api.java.source.CompilationController;
import org.netbeans.api.java.source.ModificationResult;
import org.netbeans.modules.editor.tools.storage.api.ToolPreferences;
Expand Down Expand Up @@ -97,6 +99,8 @@
import org.netbeans.modules.java.hints.spiimpl.batch.ProgressHandleWrapper.ProgressHandleAbstraction;
import org.netbeans.modules.java.hints.spiimpl.batch.Scopes;
import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
import org.netbeans.modules.java.j2seplatform.platformdefinition.Util;
import org.netbeans.modules.java.source.parsing.JavacParser;
import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
Expand All @@ -108,6 +112,7 @@
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
import org.netbeans.spi.java.hints.Hint.Kind;
import org.netbeans.spi.java.hints.HintContext;
import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation;
import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
Expand Down Expand Up @@ -408,20 +413,43 @@ private static GroupOptions setupGroupParser(OptionParser parser) {
return new GroupOptions(parser.accepts("classpath", "classpath").withRequiredArg().withValuesSeparatedBy(File.pathSeparatorChar).ofType(File.class),
parser.accepts("bootclasspath", "bootclasspath").withRequiredArg().withValuesSeparatedBy(File.pathSeparatorChar).ofType(File.class),
parser.accepts("sourcepath", "sourcepath").withRequiredArg().withValuesSeparatedBy(File.pathSeparatorChar).ofType(File.class),
parser.accepts("source", "source level").withRequiredArg().ofType(String.class).defaultsTo(SOURCE_LEVEL_DEFAULT));
parser.accepts("add-exports", "javac's addd-exports option").withRequiredArg().ofType(String.class),
parser.accepts("add-modules", "javac's add-modules option").withRequiredArg().ofType(String.class),
parser.accepts("limit-modules", "javac's limit-modules option").withRequiredArg().ofType(String.class),
parser.accepts("module-path", "module path").withRequiredArg().withValuesSeparatedBy(File.pathSeparatorChar).ofType(File.class),
parser.accepts("source", "source level").withRequiredArg().ofType(String.class).defaultsTo(SOURCE_LEVEL_DEFAULT),
parser.accepts("system", "system modules").withRequiredArg().ofType(File.class));
}

private static final class GroupOptions {
private final ArgumentAcceptingOptionSpec<File> classpath;
private final ArgumentAcceptingOptionSpec<File> bootclasspath;
private final ArgumentAcceptingOptionSpec<File> sourcepath;
private final ArgumentAcceptingOptionSpec<String> addExports;
private final ArgumentAcceptingOptionSpec<String> addModules;
private final ArgumentAcceptingOptionSpec<String> limitModules;
private final ArgumentAcceptingOptionSpec<File> modulePath;
private final ArgumentAcceptingOptionSpec<String> source;

public GroupOptions(ArgumentAcceptingOptionSpec<File> classpath, ArgumentAcceptingOptionSpec<File> bootclasspath, ArgumentAcceptingOptionSpec<File> sourcepath, ArgumentAcceptingOptionSpec<String> source) {
private final ArgumentAcceptingOptionSpec<File> system;

public GroupOptions(ArgumentAcceptingOptionSpec<File> classpath,
ArgumentAcceptingOptionSpec<File> bootclasspath,
ArgumentAcceptingOptionSpec<File> sourcepath,
ArgumentAcceptingOptionSpec<String> addExports,
ArgumentAcceptingOptionSpec<String> addModules,
ArgumentAcceptingOptionSpec<String> limitModules,
ArgumentAcceptingOptionSpec<File> modulePath,
ArgumentAcceptingOptionSpec<String> source,
ArgumentAcceptingOptionSpec<File> system) {
this.classpath = classpath;
this.bootclasspath = bootclasspath;
this.sourcepath = sourcepath;
this.limitModules = limitModules;
this.modulePath = modulePath;
this.source = source;
this.addExports = addExports;
this.addModules = addModules;
this.system = system;
}

}
Expand Down Expand Up @@ -1008,9 +1036,14 @@ private static final class WarningsAndErrors {
private static final class RootConfiguration {
private final List<Folder> rootFolders;
private final ClassPath bootCP;
private final ClassPath systemCP;
private final ClassPath compileCP;
private final ClassPath modulePathCP;
private final ClassPath sourceCP;
private final ClassPath binaryCP;
private final List<String> addExports;
private final String addModules;
private final String limitModules;
private final String sourceLevel;

public RootConfiguration(OptionSet parsed, GroupOptions groupOptions) throws IOException {
Expand All @@ -1029,12 +1062,50 @@ public RootConfiguration(OptionSet parsed, GroupOptions groupOptions) throws IOE
}

this.bootCP = createClassPath(parsed.has(groupOptions.bootclasspath) ? parsed.valuesOf(groupOptions.bootclasspath) : null, Utils.createDefaultBootClassPath());
this.systemCP = parsed.has(groupOptions.system) ? systemPath(parsed.valueOf(groupOptions.system)) : Utils.createDefaultBootClassPath();
this.compileCP = createClassPath(parsed.has(groupOptions.classpath) ? parsed.valuesOf(groupOptions.classpath) : null, ClassPath.EMPTY);
if (parsed.has(groupOptions.modulePath)) {
this.modulePathCP = createClassPath(expandModulePathEntries(parsed.valuesOf(groupOptions.modulePath)), ClassPath.EMPTY);
} else {
this.modulePathCP = ClassPath.EMPTY;
}
this.sourceCP = createClassPath(parsed.has(groupOptions.sourcepath) ? parsed.valuesOf(groupOptions.sourcepath) : null, ClassPathSupport.createClassPath(roots.toArray(new FileObject[0])));
this.binaryCP = ClassPathSupport.createProxyClassPath(bootCP, compileCP);
this.binaryCP = ClassPathSupport.createProxyClassPath(bootCP, compileCP, systemCP, modulePathCP);
this.addExports = parsed.has(groupOptions.addExports) ? parsed.valuesOf(groupOptions.addExports) : null;
this.addModules = parsed.has(groupOptions.addModules) ? parsed.valueOf(groupOptions.addModules) : null;
this.limitModules = parsed.has(groupOptions.limitModules) ? parsed.valueOf(groupOptions.limitModules) : null;
this.sourceLevel = parsed.valueOf(groupOptions.source);
}

private ClassPath systemPath(File system) throws IOException {
try {
Method createModulePath = Util.class.getDeclaredMethod("createModulePath", Collection.class);
createModulePath.setAccessible(true);
return (ClassPath) createModulePath.invoke(null, List.of(FileUtil.toFileObject(system)));
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}

private List<File> expandModulePathEntries(Iterable<? extends File> modulePathEntries) {
List<File> expandedModulePath = new ArrayList<>();

for (File entry : modulePathEntries) {
if (entry.isFile()) {
expandedModulePath.add(entry);
} else if (new File(entry, "module-info.class").canRead()) {
expandedModulePath.add(entry);
} else if (entry.isDirectory()) {
File[] children = entry.listFiles();

if (children != null) {
expandedModulePath.addAll(List.of(children));
}
}
}

return expandedModulePath;
}
}

private static final class GlobalConfiguration {
Expand Down Expand Up @@ -1088,8 +1159,12 @@ public ClassPath findClassPath(FileObject file, String type) {
if (rootConfiguration.sourceCP.findOwnerRoot(file) != null) {
if (ClassPath.BOOT.equals(type)) {
return rootConfiguration.bootCP;
} else if (JavaClassPathConstants.MODULE_BOOT_PATH.equals(type)) {
return rootConfiguration.systemCP;
} else if (ClassPath.COMPILE.equals(type)) {
return rootConfiguration.compileCP;
} else if (JavaClassPathConstants.MODULE_COMPILE_PATH.equals(type)) {
return rootConfiguration.modulePathCP;
} else if (ClassPath.SOURCE.equals(type)) {
return rootConfiguration.sourceCP;
}
Expand All @@ -1099,6 +1174,52 @@ public ClassPath findClassPath(FileObject file, String type) {
}
}

@ServiceProvider(service=CompilerOptionsQueryImplementation.class, position=100)
public static final class CompilerOptionsQueryImpl implements CompilerOptionsQueryImplementation {
private final Result result = new Result() {
@Override
public List<? extends String> getArguments() {
RootConfiguration rootConfiguration = currentRootConfiguration.get();

if (rootConfiguration == null) {
return List.of();
}

List<String> result = new ArrayList<>();

if (rootConfiguration.addModules != null) {
result.add("--add-modules");
result.add(rootConfiguration.addModules);
}

if (rootConfiguration.limitModules != null) {
result.add("--limit-modules");
result.add(rootConfiguration.limitModules);
}

if (rootConfiguration.addExports != null) {
rootConfiguration.addExports.forEach(exp -> {
result.add("--add-exports");
result.add(exp);
});
}

return result;
}
@Override
public void addChangeListener(ChangeListener cl) {
}
@Override
public void removeChangeListener(ChangeListener cl) {
}
};

@Override
public Result getOptions(FileObject fo) {
return result;
}
}

@ServiceProvider(service=SourceLevelQueryImplementation2.class, position=100)
public static final class SourceLevelQueryImpl implements SourceLevelQueryImplementation2 {

Expand Down Expand Up @@ -1226,7 +1347,7 @@ public ClassPath findClassPath(FileObject file, String type) {
}
}

if (ClassPath.BOOT.equals(type)) {
if (ClassPath.BOOT.equals(type) || JavaClassPathConstants.MODULE_BOOT_PATH.equals(type)) {
return Utils.createDefaultBootClassPath();
}
return null;
Expand Down Expand Up @@ -1301,4 +1422,9 @@ private static void copyPreferences(Preferences from, Preferences to) throws Bac
copyPreferences(from.node(child), to.node(child));
}
}

static {
//disable the source level downgrade, to avoid falling back to --release (which breaks --add-exports on system classes):
JavacParser.DISABLE_SOURCE_LEVEL_DOWNGRADE = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
package org.netbeans.modules.jackpot30.cmdline;

import java.util.regex.Pattern;
import javax.annotation.processing.Processor;
import org.netbeans.modules.jackpot30.cmdline.Main.BCPFallBack;
import org.netbeans.modules.jackpot30.cmdline.Main.CompilerOptionsQueryImpl;
import org.netbeans.modules.jackpot30.cmdline.Main.SourceLevelQueryImpl;
import org.netbeans.modules.jackpot30.cmdline.lib.CreateStandaloneJar;
import org.netbeans.modules.jackpot30.cmdline.lib.CreateStandaloneJar.Info;
Expand All @@ -31,6 +31,7 @@
import org.netbeans.modules.java.platform.DefaultJavaPlatformProvider;
import org.netbeans.modules.project.ui.OpenProjectsTrampolineImpl;
import org.netbeans.spi.java.classpath.ClassPathProvider;
import org.netbeans.spi.java.queries.CompilerOptionsQueryImplementation;
import org.netbeans.spi.java.queries.SourceLevelQueryImplementation2;

/**
Expand All @@ -45,13 +46,14 @@ public CreateTool(String name) {

@Override
protected Info computeInfo() {
return new Info().addAdditionalRoots(Main.class.getName(), DeclarativeHintsTestBase.class.getName(), OpenProjectsTrampolineImpl.class.getName(), J2SEProject.class.getName(), DefaultJavaPlatformProvider.class.getName(), PatternConvertorImpl.class.getName(), BCPFallBack.class.getName(), "org.slf4j.impl.StaticLoggerBinder")
return new Info().addAdditionalRoots(Main.class.getName(), DeclarativeHintsTestBase.class.getName(), OpenProjectsTrampolineImpl.class.getName(), J2SEProject.class.getName(), DefaultJavaPlatformProvider.class.getName(), PatternConvertorImpl.class.getName(), BCPFallBack.class.getName(), "org.slf4j.impl.StaticLoggerBinder", CompilerOptionsQueryImpl.class.getName())
.addAdditionalResources("org/netbeans/modules/java/hints/resources/Bundle.properties", "org/netbeans/modules/java/hints/declarative/resources/Bundle.properties")
.addAdditionalLayers("org/netbeans/modules/java/hints/resources/layer.xml", "org/netbeans/modules/java/hints/declarative/resources/layer.xml")
.addMetaInfRegistrations(new MetaInfRegistration(org.netbeans.modules.project.uiapi.OpenProjectsTrampoline.class, OpenProjectsTrampolineImpl.class))
.addMetaInfRegistrations(new MetaInfRegistration(ClassPathProvider.class.getName(), BCPFallBack.class.getName(), 9999))
.addMetaInfRegistrations(new MetaInfRegistration(ClassPathProvider.class.getName(), Main.ClassPathProviderImpl.class.getName(), 100))
.addMetaInfRegistrations(new MetaInfRegistration(SourceLevelQueryImplementation2.class.getName(), SourceLevelQueryImpl.class.getName(), 100))
.addMetaInfRegistrations(new MetaInfRegistration(CompilerOptionsQueryImplementation.class.getName(), CompilerOptionsQueryImpl.class.getName(), 100))
.addMetaInfRegistrationToCopy(PatternConvertor.class.getName())
.addExcludePattern(Pattern.compile("junit\\.framework\\..*"))
.setEscapeJavaxLang();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,14 @@ protected void reallyRunCompiler(File workingDir, int exitcode, String[] output,

int actualExitCode = p.waitFor();

assertEquals(exitcode, actualExitCode);

outCopy.doJoin();
errCopy.doJoin();

assertEquals(exitcode, actualExitCode);
} catch (Throwable t) {
System.err.println(output[0]);
System.err.println(output[1]);

throw new IOException(t);
}
}
Expand Down
Loading