mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-08 01:21:42 +01:00
Merge
This commit is contained in:
@@ -602,12 +602,8 @@ public final class Layer {
|
||||
|
||||
checkGetClassLoaderPermission();
|
||||
|
||||
// For now, no two modules in the boot Layer may contain the same
|
||||
// package so we use a simple check for the boot Layer to keep
|
||||
// the overhead at startup to a minimum
|
||||
if (boot() == null) {
|
||||
checkBootModulesForDuplicatePkgs(cf);
|
||||
} else {
|
||||
// The boot layer is checked during module system initialization
|
||||
if (boot() != null) {
|
||||
checkForDuplicatePkgs(cf, clf);
|
||||
}
|
||||
|
||||
@@ -656,27 +652,6 @@ public final class Layer {
|
||||
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a configuration for the boot Layer to ensure that no two modules
|
||||
* have the same package.
|
||||
*
|
||||
* @throws LayerInstantiationException
|
||||
*/
|
||||
private static void checkBootModulesForDuplicatePkgs(Configuration cf) {
|
||||
Map<String, String> packageToModule = new HashMap<>();
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
|
||||
String name = descriptor.name();
|
||||
for (String p : descriptor.packages()) {
|
||||
String other = packageToModule.putIfAbsent(p, name);
|
||||
if (other != null) {
|
||||
throw fail("Package " + p + " in both module "
|
||||
+ name + " and module " + other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a configuration and the module-to-loader mapping to ensure that
|
||||
* no two modules mapped to the same class loader have the same package.
|
||||
|
||||
@@ -60,7 +60,6 @@ import java.security.PrivilegedExceptionAction;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.spi.ResourceBundleControlProvider;
|
||||
import java.util.spi.ResourceBundleProvider;
|
||||
|
||||
import jdk.internal.loader.BootLoader;
|
||||
@@ -232,8 +231,6 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
|
||||
* <li>{@code ResourceBundle.Control} is <em>not</em> supported in named modules.
|
||||
* If the {@code getBundle} method with a {@code ResourceBundle.Control} is called
|
||||
* in a named module, the method will throw an {@code UnsupportedOperationException}.
|
||||
* Any service providers of {@link ResourceBundleControlProvider} are ignored in
|
||||
* named modules.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
@@ -264,17 +261,6 @@ import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION;
|
||||
* {@link #getBundle(String, Locale, ClassLoader, Control) getBundle}
|
||||
* factory method for details.
|
||||
*
|
||||
* <p><a name="modify_default_behavior">For the {@code getBundle} factory</a>
|
||||
* methods that take no {@link Control} instance, their <a
|
||||
* href="#default_behavior"> default behavior</a> of resource bundle loading
|
||||
* can be modified with <em>installed</em> {@link
|
||||
* ResourceBundleControlProvider} implementations. Any installed providers are
|
||||
* detected at the {@code ResourceBundle} class loading time. If any of the
|
||||
* providers provides a {@link Control} for the given base name, that {@link
|
||||
* Control} will be used instead of the default {@link Control}. If there is
|
||||
* more than one service provider installed for supporting the same base name,
|
||||
* the first one returned from {@link ServiceLoader} will be used.
|
||||
*
|
||||
* <h3>Cache Management</h3>
|
||||
*
|
||||
* Resource bundle instances created by the <code>getBundle</code> factory
|
||||
@@ -469,21 +455,6 @@ public abstract class ResourceBundle {
|
||||
*/
|
||||
private volatile Set<String> keySet;
|
||||
|
||||
private static final List<ResourceBundleControlProvider> providers;
|
||||
|
||||
static {
|
||||
List<ResourceBundleControlProvider> list = null;
|
||||
ServiceLoader<ResourceBundleControlProvider> serviceLoaders
|
||||
= ServiceLoader.loadInstalled(ResourceBundleControlProvider.class);
|
||||
for (ResourceBundleControlProvider provider : serviceLoaders) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.add(provider);
|
||||
}
|
||||
providers = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sole constructor. (For invocation by subclass constructors, typically
|
||||
* implicit.)
|
||||
@@ -948,7 +919,7 @@ public abstract class ResourceBundle {
|
||||
{
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return getBundleImpl(baseName, Locale.getDefault(),
|
||||
caller, getDefaultControl(caller, baseName));
|
||||
caller, Control.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1022,7 +993,7 @@ public abstract class ResourceBundle {
|
||||
{
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return getBundleImpl(baseName, locale,
|
||||
caller, getDefaultControl(caller, baseName));
|
||||
caller, Control.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1163,10 +1134,7 @@ public abstract class ResourceBundle {
|
||||
*
|
||||
* <p>This method behaves the same as calling
|
||||
* {@link #getBundle(String, Locale, ClassLoader, Control)} passing a
|
||||
* default instance of {@link Control} unless another {@link Control} is
|
||||
* provided with the {@link ResourceBundleControlProvider} SPI. Refer to the
|
||||
* description of <a href="#modify_default_behavior">modifying the default
|
||||
* behavior</a>.
|
||||
* default instance of {@link Control}.
|
||||
*
|
||||
* <p><a name="default_behavior">The following describes the default
|
||||
* behavior</a>.
|
||||
@@ -1364,7 +1332,7 @@ public abstract class ResourceBundle {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
Class<?> caller = Reflection.getCallerClass();
|
||||
return getBundleImpl(baseName, locale, caller, loader, getDefaultControl(caller, baseName));
|
||||
return getBundleImpl(baseName, locale, caller, loader, Control.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1589,18 +1557,6 @@ public abstract class ResourceBundle {
|
||||
return getBundleImpl(baseName, targetLocale, caller, loader, control);
|
||||
}
|
||||
|
||||
private static Control getDefaultControl(Class<?> caller, String baseName) {
|
||||
if (providers != null && !caller.getModule().isNamed()) {
|
||||
for (ResourceBundleControlProvider provider : providers) {
|
||||
Control control = provider.getControl(baseName);
|
||||
if (control != null) {
|
||||
return control;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Control.INSTANCE;
|
||||
}
|
||||
|
||||
private static void checkNamedModule(Class<?> caller) {
|
||||
if (caller.getModule().isNamed()) {
|
||||
throw new UnsupportedOperationException(
|
||||
@@ -2573,8 +2529,7 @@ public abstract class ResourceBundle {
|
||||
* @apiNote <a name="note">{@code ResourceBundle.Control} is not supported
|
||||
* in named modules.</a> If the {@code ResourceBundle.getBundle} method with
|
||||
* a {@code ResourceBundle.Control} is called in a named module, the method
|
||||
* will throw an {@link UnsupportedOperationException}. Any service providers
|
||||
* of {@link ResourceBundleControlProvider} are ignored in named modules.
|
||||
* will throw an {@link UnsupportedOperationException}.
|
||||
*
|
||||
* @since 1.6
|
||||
* @see java.util.spi.ResourceBundleProvider
|
||||
|
||||
@@ -35,21 +35,19 @@ import java.util.ResourceBundle;
|
||||
* no {@link java.util.ResourceBundle.Control} instance can be modified with {@code
|
||||
* ResourceBundleControlProvider} implementations.
|
||||
*
|
||||
* <p>Provider implementations must be packaged using the <a
|
||||
* href="../../../../technotes/guides/extensions/index.html">Java Extension
|
||||
* Mechanism</a> as installed extensions. Refer to {@link java.util.ServiceLoader}
|
||||
* for the extension packaging. Any installed {@code
|
||||
* ResourceBundleControlProvider} implementations are loaded using {@link
|
||||
* java.util.ServiceLoader} at the {@code ResourceBundle} class loading time.
|
||||
*
|
||||
* <p>All {@code ResourceBundleControlProvider}s are ignored in named modules.
|
||||
*
|
||||
* @author Masayoshi Okutsu
|
||||
* @since 1.8
|
||||
* @see ResourceBundle#getBundle(String, java.util.Locale, ClassLoader, ResourceBundle.Control)
|
||||
* ResourceBundle.getBundle
|
||||
* @see java.util.ServiceLoader#loadInstalled(Class)
|
||||
* @deprecated There is no longer any mechanism to install a custom
|
||||
* {@code ResourceBundleControlProvider} implementation defined
|
||||
* by the platform class loader or its ancestor. The recommended
|
||||
* way to use a custom {@code Control} implementation to load resource bundle
|
||||
* is to use {@link java.util.ResourceBundle#getBundle(String, Control)}
|
||||
* or other factory methods that take custom {@link java.util.ResourceBundle.Control}.
|
||||
*/
|
||||
@Deprecated(since="9", forRemoval=true)
|
||||
public interface ResourceBundleControlProvider {
|
||||
/**
|
||||
* Returns a {@code ResourceBundle.Control} instance that is used
|
||||
|
||||
@@ -306,8 +306,32 @@ public final class ModuleBootstrap {
|
||||
fail(name + ": cannot be loaded from application module path");
|
||||
}
|
||||
}
|
||||
|
||||
// check if module specified in --patch-module is present
|
||||
for (String mn: patcher.patchedModules()) {
|
||||
if (!cf.findModule(mn).isPresent()) {
|
||||
warnUnknownModule(PATCH_MODULE, mn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if needed check that there are no split packages in the set of
|
||||
// resolved modules for the boot layer
|
||||
if (SystemModules.hasSplitPackages() || needPostResolutionChecks) {
|
||||
Map<String, String> packageToModule = new HashMap<>();
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleDescriptor descriptor =
|
||||
resolvedModule.reference().descriptor();
|
||||
String name = descriptor.name();
|
||||
for (String p : descriptor.packages()) {
|
||||
String other = packageToModule.putIfAbsent(p, name);
|
||||
if (other != null) {
|
||||
fail("Package " + p + " in both module "
|
||||
+ name + " and module " + other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long t4 = System.nanoTime();
|
||||
|
||||
@@ -464,7 +488,7 @@ public final class ModuleBootstrap {
|
||||
String mn = e.getKey();
|
||||
Optional<Module> om = bootLayer.findModule(mn);
|
||||
if (!om.isPresent()) {
|
||||
warn("Unknown module: " + mn);
|
||||
warnUnknownModule(ADD_READS, mn);
|
||||
continue;
|
||||
}
|
||||
Module m = om.get();
|
||||
@@ -478,7 +502,7 @@ public final class ModuleBootstrap {
|
||||
if (om.isPresent()) {
|
||||
Modules.addReads(m, om.get());
|
||||
} else {
|
||||
warn("Unknown module: " + name);
|
||||
warnUnknownModule(ADD_READS, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -510,24 +534,25 @@ public final class ModuleBootstrap {
|
||||
Map<String, List<String>> map,
|
||||
boolean opens)
|
||||
{
|
||||
String option = opens ? ADD_OPENS : ADD_EXPORTS;
|
||||
for (Map.Entry<String, List<String>> e : map.entrySet()) {
|
||||
|
||||
// the key is $MODULE/$PACKAGE
|
||||
String key = e.getKey();
|
||||
String[] s = key.split("/");
|
||||
if (s.length != 2)
|
||||
fail("Unable to parse as <module>/<package>: " + key);
|
||||
fail(unableToParse(option, "<module>/<package>", key));
|
||||
|
||||
String mn = s[0];
|
||||
String pn = s[1];
|
||||
if (mn.isEmpty() || pn.isEmpty())
|
||||
fail("Module and package name must be specified: " + key);
|
||||
fail(unableToParse(option, "<module>/<package>", key));
|
||||
|
||||
// The exporting module is in the boot layer
|
||||
Module m;
|
||||
Optional<Module> om = bootLayer.findModule(mn);
|
||||
if (!om.isPresent()) {
|
||||
warn("Unknown module: " + mn);
|
||||
warnUnknownModule(option, mn);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -549,7 +574,7 @@ public final class ModuleBootstrap {
|
||||
if (om.isPresent()) {
|
||||
other = om.get();
|
||||
} else {
|
||||
warn("Unknown module: " + name);
|
||||
warnUnknownModule(option, name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -593,24 +618,30 @@ public final class ModuleBootstrap {
|
||||
|
||||
int pos = value.indexOf('=');
|
||||
if (pos == -1)
|
||||
fail("Unable to parse as <module>=<value>: " + value);
|
||||
fail(unableToParse(option(prefix), "<module>=<value>", value));
|
||||
if (pos == 0)
|
||||
fail("Missing module name in: " + value);
|
||||
fail(unableToParse(option(prefix), "<module>=<value>", value));
|
||||
|
||||
// key is <module> or <module>/<package>
|
||||
String key = value.substring(0, pos);
|
||||
|
||||
String rhs = value.substring(pos+1);
|
||||
if (rhs.isEmpty())
|
||||
fail("Unable to parse as <module>=<value>: " + value);
|
||||
fail(unableToParse(option(prefix), "<module>=<value>", value));
|
||||
|
||||
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
|
||||
if (!allowDuplicates && map.containsKey(key))
|
||||
fail(key + " specified more than once");
|
||||
fail(key + " specified more than once in " + option(prefix));
|
||||
List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>());
|
||||
int ntargets = 0;
|
||||
for (String s : rhs.split(regex)) {
|
||||
if (s.length() > 0) values.add(s);
|
||||
if (s.length() > 0) {
|
||||
values.add(s);
|
||||
ntargets++;
|
||||
}
|
||||
}
|
||||
if (ntargets == 0)
|
||||
fail("Target must be specified: " + option(prefix) + " " + value);
|
||||
|
||||
index++;
|
||||
value = getAndRemoveProperty(prefix + index);
|
||||
@@ -672,6 +703,42 @@ public final class ModuleBootstrap {
|
||||
System.err.println("WARNING: " + m);
|
||||
}
|
||||
|
||||
static void warnUnknownModule(String option, String mn) {
|
||||
warn("Unknown module: " + mn + " specified in " + option);
|
||||
}
|
||||
|
||||
static String unableToParse(String option, String text, String value) {
|
||||
return "Unable to parse " + option + " " + text + ": " + value;
|
||||
}
|
||||
|
||||
private static final String ADD_MODULES = "--add-modules";
|
||||
private static final String ADD_EXPORTS = "--add-exports";
|
||||
private static final String ADD_OPENS = "--add-opens";
|
||||
private static final String ADD_READS = "--add-reads";
|
||||
private static final String PATCH_MODULE = "--patch-module";
|
||||
|
||||
|
||||
/*
|
||||
* Returns the command-line option name corresponds to the specified
|
||||
* system property prefix.
|
||||
*/
|
||||
static String option(String prefix) {
|
||||
switch (prefix) {
|
||||
case "jdk.module.addexports.":
|
||||
return ADD_EXPORTS;
|
||||
case "jdk.module.addopens.":
|
||||
return ADD_OPENS;
|
||||
case "jdk.module.addreads.":
|
||||
return ADD_READS;
|
||||
case "jdk.module.patch.":
|
||||
return PATCH_MODULE;
|
||||
case "jdk.module.addmods.":
|
||||
return ADD_MODULES;
|
||||
default:
|
||||
throw new IllegalArgumentException(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
static class PerfCounters {
|
||||
|
||||
static PerfCounter systemModulesTime
|
||||
|
||||
@@ -175,6 +175,12 @@ public final class ModulePatcher {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the names of the patched modules.
|
||||
*/
|
||||
Set<String> patchedModules() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* A ModuleReader that reads resources from a patched module.
|
||||
|
||||
@@ -56,6 +56,14 @@ public final class SystemModules {
|
||||
*/
|
||||
public static int PACKAGES_IN_BOOT_LAYER = 1024;
|
||||
|
||||
/**
|
||||
* @return {@code false} if there are no split packages in the run-time
|
||||
* image, {@code true} if there are or if it's not been checked.
|
||||
*/
|
||||
public static boolean hasSplitPackages() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleDescriptors in the run-time image.
|
||||
*
|
||||
|
||||
@@ -573,6 +573,17 @@ IsModuleOption(const char* name) {
|
||||
JLI_StrCmp(name, "--patch-module") == 0;
|
||||
}
|
||||
|
||||
static jboolean
|
||||
IsLongFormModuleOption(const char* name) {
|
||||
return JLI_StrCCmp(name, "--module-path=") == 0 ||
|
||||
JLI_StrCCmp(name, "--upgrade-module-path=") == 0 ||
|
||||
JLI_StrCCmp(name, "--add-modules=") == 0 ||
|
||||
JLI_StrCCmp(name, "--limit-modules=") == 0 ||
|
||||
JLI_StrCCmp(name, "--add-exports=") == 0 ||
|
||||
JLI_StrCCmp(name, "--add-reads=") == 0 ||
|
||||
JLI_StrCCmp(name, "--patch-module=") == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the given name has a white space option.
|
||||
*/
|
||||
@@ -1236,7 +1247,7 @@ ParseArguments(int *pargc, char ***pargv,
|
||||
char *option = NULL;
|
||||
char *value = NULL;
|
||||
int kind = GetOpt(&argc, &argv, &option, &value);
|
||||
jboolean has_arg = value != NULL;
|
||||
jboolean has_arg = value != NULL && JLI_StrLen(value) > 0;
|
||||
|
||||
/*
|
||||
* Option to set main entry point
|
||||
@@ -1285,19 +1296,13 @@ ParseArguments(int *pargc, char ***pargv,
|
||||
/*
|
||||
* Error missing argument
|
||||
*/
|
||||
} else if (!has_arg && IsWhiteSpaceOption(arg)) {
|
||||
if (JLI_StrCmp(arg, "--module-path") == 0 ||
|
||||
JLI_StrCmp(arg, "-p") == 0 ||
|
||||
JLI_StrCmp(arg, "--upgrade-module-path") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR4, arg);
|
||||
} else if (JLI_StrCmp(arg, "--add-modules") == 0 ||
|
||||
JLI_StrCmp(arg, "--limit-modules") == 0 ||
|
||||
JLI_StrCmp(arg, "--add-exports") == 0 ||
|
||||
JLI_StrCmp(arg, "--add-opens") == 0 ||
|
||||
JLI_StrCmp(arg, "--add-reads") == 0 ||
|
||||
JLI_StrCmp(arg, "--patch-module") == 0) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR6, arg);
|
||||
}
|
||||
} else if (!has_arg && (JLI_StrCmp(arg, "--module-path") == 0 ||
|
||||
JLI_StrCmp(arg, "-p") == 0 ||
|
||||
JLI_StrCmp(arg, "--upgrade-module-path") == 0)) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR4, arg);
|
||||
|
||||
} else if (!has_arg && (IsModuleOption(arg) || IsLongFormModuleOption(arg))) {
|
||||
REPORT_ERROR (has_arg, ARG_ERROR6, arg);
|
||||
/*
|
||||
* The following cases will cause the argument parsing to stop
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@@ -22,42 +21,16 @@
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# List of JVMs that can be used as an option to java, javac, etc.
|
||||
# Order is important -- first in this list is the default JVM.
|
||||
# NOTE that this both this file and its format are UNSUPPORTED and
|
||||
# WILL GO AWAY in a future release.
|
||||
#
|
||||
# Makefile for building a ResourceBundleControlProvider jar file for testing.
|
||||
# You may also select a JVM in an arbitrary location with the
|
||||
# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
|
||||
# and may not be available in a future release.
|
||||
#
|
||||
# Usage: make JDK_HOME=... all install
|
||||
#
|
||||
|
||||
DESTDIR = ..
|
||||
TMPDIR = tmp
|
||||
SERVICESDIR = $(TMPDIR)/META-INF/services
|
||||
TARGETJAR = rbcontrolprovider.jar
|
||||
BINDIR = $(JDK_HOME)/bin
|
||||
|
||||
|
||||
all: $(TARGETJAR)
|
||||
|
||||
install: all
|
||||
cp $(TARGETJAR) $(DESTDIR)
|
||||
|
||||
SERVICES = java.util.spi.ResourceBundleControlProvider
|
||||
|
||||
FILES_JAVA = UserControlProvider.java \
|
||||
UserXMLControl.java
|
||||
|
||||
RESOURCE_FILES = XmlRB.xml \
|
||||
XmlRB_ja.xml
|
||||
|
||||
$(TARGETJAR): $(SERVICES) $(FILES_JAVA) $(RESOURCE_FILES)
|
||||
rm -rf $(TMPDIR) $@
|
||||
mkdir -p $(SERVICESDIR)
|
||||
$(BINDIR)/javac -d $(TMPDIR) $(FILES_JAVA)
|
||||
cp $(SERVICES) $(SERVICESDIR)
|
||||
cp $(RESOURCE_FILES) $(TMPDIR)/com/foo
|
||||
$(BINDIR)/jar cvf $@ -C $(TMPDIR) .
|
||||
|
||||
clean:
|
||||
rm -rf $(TMPDIR) $(TARGETJAR)
|
||||
|
||||
.PHONY: all install clean
|
||||
-server KNOWN
|
||||
-client KNOWN
|
||||
-minimal KNOWN
|
||||
@@ -34,6 +34,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -342,7 +343,8 @@ public final class SystemModulesPlugin implements Plugin {
|
||||
*
|
||||
* static Map<String, ModuleDescriptor> map = new HashMap<>();
|
||||
*/
|
||||
private void clinit(int numModules, int numPackages) {
|
||||
private void clinit(int numModules, int numPackages,
|
||||
boolean hasSplitPackages) {
|
||||
cw.visit(Opcodes.V1_8, ACC_PUBLIC+ACC_FINAL+ACC_SUPER, CLASSNAME,
|
||||
null, "java/lang/Object", null);
|
||||
|
||||
@@ -379,6 +381,17 @@ public final class SystemModulesPlugin implements Plugin {
|
||||
clinit.visitInsn(RETURN);
|
||||
clinit.visitMaxs(0, 0);
|
||||
clinit.visitEnd();
|
||||
|
||||
// public static boolean hasSplitPackages();
|
||||
MethodVisitor split =
|
||||
cw.visitMethod(ACC_PUBLIC+ACC_STATIC, "hasSplitPackages",
|
||||
"()Z", null, null);
|
||||
split.visitCode();
|
||||
split.visitInsn(hasSplitPackages ? ICONST_1 : ICONST_0);
|
||||
split.visitInsn(IRETURN);
|
||||
split.visitMaxs(0, 0);
|
||||
split.visitEnd();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -416,12 +429,16 @@ public final class SystemModulesPlugin implements Plugin {
|
||||
*/
|
||||
public ClassWriter getClassWriter() {
|
||||
int numModules = moduleInfos.size();
|
||||
int numPackages = 0;
|
||||
Set<String> allPackages = new HashSet<>();
|
||||
int packageCount = 0;
|
||||
for (ModuleInfo minfo : moduleInfos) {
|
||||
numPackages += minfo.packages.size();
|
||||
allPackages.addAll(minfo.packages);
|
||||
packageCount += minfo.packages.size();
|
||||
}
|
||||
|
||||
clinit(numModules, numPackages);
|
||||
int numPackages = allPackages.size();
|
||||
boolean hasSplitPackages = (numPackages < packageCount);
|
||||
clinit(numModules, numPackages, hasSplitPackages);
|
||||
|
||||
// generate SystemModules::descriptors
|
||||
genDescriptorsMethod();
|
||||
|
||||
@@ -292,8 +292,6 @@ com/sun/jdi/sde/SourceDebugExtensionTest.java 8158066 windows-
|
||||
|
||||
# jdk_util
|
||||
|
||||
java/util/spi/ResourceBundleControlProvider/UserDefaultControlTest.java 8062512 generic-all
|
||||
|
||||
java/util/BitSet/BitSetStreamTest.java 8079538 generic-all
|
||||
|
||||
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6959653
|
||||
* @summary Test ResourceBundle.Control provided using SPI.
|
||||
* @build UserDefaultControlTest
|
||||
* @run shell UserDefaultControlTest.sh
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
public class UserDefaultControlTest {
|
||||
public static void main(String[] args) {
|
||||
ResourceBundle rb = ResourceBundle.getBundle("com.foo.XmlRB", Locale.ROOT);
|
||||
String type = rb.getString("type");
|
||||
if (!type.equals("XML")) {
|
||||
throw new RuntimeException("Root Locale: type: got " + type
|
||||
+ ", expected XML (ASCII)");
|
||||
}
|
||||
|
||||
rb = ResourceBundle.getBundle("com.foo.XmlRB", Locale.JAPAN);
|
||||
type = rb.getString("type");
|
||||
// Expect fullwidth "XML"
|
||||
if (!type.equals("\uff38\uff2d\uff2c")) {
|
||||
throw new RuntimeException("Locale.JAPAN: type: got " + type
|
||||
+ ", expected \uff38\uff2d\uff2c (fullwidth XML)");
|
||||
}
|
||||
|
||||
try {
|
||||
rb = ResourceBundle.getBundle("com.bar.XmlRB", Locale.JAPAN);
|
||||
throw new RuntimeException("com.bar.XmlRB test failed.");
|
||||
} catch (MissingResourceException e) {
|
||||
// OK
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
${TESTJAVA}/bin/java ${TESTVMOPTS} -Djava.ext.dirs=${TESTSRC} -cp ${TESTCLASSES} UserDefaultControlTest
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.foo;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import static java.util.ResourceBundle.Control.*;
|
||||
|
||||
public class UserXMLControl extends ResourceBundle.Control {
|
||||
@Override
|
||||
public List<String> getFormats(String baseName) {
|
||||
if (baseName == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return Arrays.asList("xml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceBundle newBundle(String baseName, Locale locale,
|
||||
String format,
|
||||
ClassLoader loader,
|
||||
boolean reload)
|
||||
throws IllegalAccessException,
|
||||
InstantiationException, IOException {
|
||||
if (baseName == null || locale == null
|
||||
|| format == null || loader == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ResourceBundle bundle = null;
|
||||
if (format.equals("xml")) {
|
||||
String bundleName = toBundleName(baseName, locale);
|
||||
String resourceName = toResourceName(bundleName, format);
|
||||
URL url = loader.getResource(resourceName);
|
||||
if (url != null) {
|
||||
URLConnection connection = url.openConnection();
|
||||
if (connection != null) {
|
||||
if (reload) {
|
||||
// disable caches if reloading
|
||||
connection.setUseCaches(false);
|
||||
}
|
||||
try (InputStream stream = connection.getInputStream()) {
|
||||
if (stream != null) {
|
||||
BufferedInputStream bis = new BufferedInputStream(stream);
|
||||
bundle = new XMLResourceBundle(bis);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private static class XMLResourceBundle extends ResourceBundle {
|
||||
private Properties props;
|
||||
|
||||
XMLResourceBundle(InputStream stream) throws IOException {
|
||||
props = new Properties();
|
||||
props.loadFromXML(stream);
|
||||
}
|
||||
|
||||
protected Object handleGetObject(String key) {
|
||||
if (key == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return props.get(key);
|
||||
}
|
||||
|
||||
public Enumeration<String> getKeys() {
|
||||
// Not implemented
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
|
||||
This code is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License version 2 only, as
|
||||
published by the Free Software Foundation. Oracle designates this
|
||||
particular file as subject to the "Classpath" exception as provided
|
||||
by Oracle in the LICENSE file that accompanied this code.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
version 2 for more details (a copy is included in the LICENSE file that
|
||||
accompanied this code).
|
||||
|
||||
You should have received a copy of the GNU General Public License version
|
||||
2 along with this work; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
or visit www.oracle.com if you need additional information or have any
|
||||
questions.
|
||||
-->
|
||||
<!---->
|
||||
|
||||
<!-- DTD for properties -->
|
||||
<!DOCTYPE properties [
|
||||
<!ELEMENT properties ( comment?, entry* ) >
|
||||
<!ATTLIST properties version CDATA #FIXED "1.0">
|
||||
<!ELEMENT comment (#PCDATA) >
|
||||
<!ELEMENT entry (#PCDATA) >
|
||||
<!ATTLIST entry key CDATA #REQUIRED>
|
||||
]>
|
||||
|
||||
<properties>
|
||||
<comment>Test data for UserDefaultControlTest.java</comment>
|
||||
<entry key="type">XML</entry>
|
||||
</properties>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
|
||||
This code is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License version 2 only, as
|
||||
published by the Free Software Foundation. Oracle designates this
|
||||
particular file as subject to the "Classpath" exception as provided
|
||||
by Oracle in the LICENSE file that accompanied this code.
|
||||
|
||||
This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
version 2 for more details (a copy is included in the LICENSE file that
|
||||
accompanied this code).
|
||||
|
||||
You should have received a copy of the GNU General Public License version
|
||||
2 along with this work; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
or visit www.oracle.com if you need additional information or have any
|
||||
questions.
|
||||
-->
|
||||
<!---->
|
||||
|
||||
<!-- DTD for properties -->
|
||||
<!DOCTYPE properties [
|
||||
<!ELEMENT properties ( comment?, entry* ) >
|
||||
<!ATTLIST properties version CDATA #FIXED "1.0">
|
||||
<!ELEMENT comment (#PCDATA) >
|
||||
<!ELEMENT entry (#PCDATA) >
|
||||
<!ATTLIST entry key CDATA #REQUIRED>
|
||||
]>
|
||||
|
||||
<properties>
|
||||
<comment>Test data for UserDefaultControlTest.java</comment>
|
||||
<entry key="type">XML</entry>
|
||||
</properties>
|
||||
@@ -1 +0,0 @@
|
||||
com.foo.UserControlProvider
|
||||
Binary file not shown.
127
jdk/test/lib/testlibrary/ModuleSourceBuilder.java
Normal file
127
jdk/test/lib/testlibrary/ModuleSourceBuilder.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Utility class for creating test modules.
|
||||
*/
|
||||
public class ModuleSourceBuilder {
|
||||
private static String MODULE_INFO_JAVA = "module-info.java";
|
||||
private static Pattern MODULE_PATTERN =
|
||||
Pattern.compile("module\\s+((?:\\w+\\.)*)");
|
||||
private static Pattern PACKAGE_PATTERN =
|
||||
Pattern.compile("package\\s+(((?:\\w+\\.)*)(?:\\w+))");
|
||||
private static Pattern CLASS_PATTERN =
|
||||
Pattern.compile("(?:public\\s+)?(?:class|enum|interface)\\s+(\\w+)");
|
||||
|
||||
private final Path dir;
|
||||
public ModuleSourceBuilder(Path dir) {
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create java source files of the given module
|
||||
*/
|
||||
public void writeJavaFiles(String module, String moduleInfoJava, String... contents)
|
||||
throws IOException
|
||||
{
|
||||
Path msrc = dir.resolve(module);
|
||||
new JavaSource(moduleInfoJava).write(msrc);
|
||||
for (String c : contents) {
|
||||
new JavaSource(c).write(msrc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the module to the given destination.
|
||||
*/
|
||||
public void compile(String module, Path dest, String... options)
|
||||
throws IOException
|
||||
{
|
||||
Path msrc = dir.resolve(module);
|
||||
Stream<String> args =
|
||||
Stream.concat(Arrays.stream(options),
|
||||
Stream.of("--module-source-path",
|
||||
dir.toString()));
|
||||
assertTrue(CompilerUtils.compile(msrc, dest, args.toArray(String[]::new)),
|
||||
"Fail to compile " + module);
|
||||
}
|
||||
|
||||
static class JavaSource {
|
||||
final String source;
|
||||
JavaSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the source code to a file in a specified directory.
|
||||
* @param dir the directory
|
||||
* @throws IOException if there is a problem writing the file
|
||||
*/
|
||||
public void write(Path dir) throws IOException {
|
||||
Path file = dir.resolve(getJavaFileNameFromSource(source));
|
||||
Files.createDirectories(file.getParent());
|
||||
try (BufferedWriter out = Files.newBufferedWriter(file)) {
|
||||
out.write(source.replace("\n", System.lineSeparator()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Java file name from the class declaration.
|
||||
* This method is intended for simple files and uses regular expressions,
|
||||
* so comments matching the pattern can make the method fail.
|
||||
*/
|
||||
static String getJavaFileNameFromSource(String source) {
|
||||
String packageName = null;
|
||||
|
||||
Matcher matcher = MODULE_PATTERN.matcher(source);
|
||||
if (matcher.find())
|
||||
return MODULE_INFO_JAVA;
|
||||
|
||||
matcher = PACKAGE_PATTERN.matcher(source);
|
||||
if (matcher.find())
|
||||
packageName = matcher.group(1).replace(".", "/");
|
||||
|
||||
matcher = CLASS_PATTERN.matcher(source);
|
||||
if (matcher.find()) {
|
||||
String className = matcher.group(1) + ".java";
|
||||
return (packageName == null) ? className : packageName + "/" + className;
|
||||
} else if (packageName != null) {
|
||||
return packageName + "/package-info.java";
|
||||
} else {
|
||||
throw new Error("Could not extract the java class " +
|
||||
"name from the provided source");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,8 +56,6 @@ public class CustomLauncherTest {
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
private static final String OSNAME = System.getProperty("os.name");
|
||||
private static final String ARCH;
|
||||
private static final String LIBARCH;
|
||||
|
||||
static {
|
||||
// magic with os.arch
|
||||
String osarch = System.getProperty("os.arch");
|
||||
@@ -84,7 +82,6 @@ public class CustomLauncherTest {
|
||||
ARCH = osarch;
|
||||
}
|
||||
}
|
||||
LIBARCH = ARCH.equals("i586") ? "i386" : ARCH;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
@@ -184,15 +181,12 @@ public class CustomLauncherTest {
|
||||
}
|
||||
|
||||
private static Path findLibjvm(FileSystem FS) {
|
||||
Path libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "jre", "lib", LIBARCH));
|
||||
if (libjvmPath == null) {
|
||||
libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "lib", LIBARCH));
|
||||
}
|
||||
Path libjvmPath = findLibjvm(FS.getPath(TEST_JDK, "lib"));
|
||||
return libjvmPath;
|
||||
}
|
||||
|
||||
private static Path findLibjvm(Path libPath) {
|
||||
// ARCH/libjvm.so -> ARCH/server/libjvm.so -> ARCH/client/libjvm.so
|
||||
// libjvm.so -> server/libjvm.so -> client/libjvm.so
|
||||
Path libjvmPath = libPath.resolve("libjvm.so");
|
||||
if (isFileOk(libjvmPath)) {
|
||||
return libjvmPath;
|
||||
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8047305 8075618
|
||||
* @summary Tests jarsigner tool and JarSigner API work with multi-release JAR files.
|
||||
* @library /test/lib
|
||||
* @library /lib/testlibrary
|
||||
* @run main MVJarSigningTest
|
||||
*/
|
||||
|
||||
import jdk.security.jarsigner.JarSigner;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import jdk.test.lib.JDKToolFinder;
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
|
||||
public class MVJarSigningTest {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src", ".");
|
||||
private static final String USR_DIR = System.getProperty("user.dir", ".");
|
||||
private static final String JAR_NAME = "MV.jar";
|
||||
private static final String KEYSTORE = "keystore.jks";
|
||||
private static final String ALIAS = "JavaTest";
|
||||
private static final String STOREPASS = "changeit";
|
||||
private static final String KEYPASS = "changeit";
|
||||
private static final String SIGNED_JAR = "Signed.jar";
|
||||
private static final String POLICY_FILE = "SignedJar.policy";
|
||||
private static final String VERSION_MESSAGE = "I am running on version 9";
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
// compile java files in jarContent directory
|
||||
compile("jarContent");
|
||||
|
||||
// create multi-release jar
|
||||
Path classes = Paths.get("classes");
|
||||
jar("cf", JAR_NAME, "-C", classes.resolve("base").toString(), ".",
|
||||
"--release", "9", "-C", classes.resolve("v9").toString(), ".",
|
||||
"--release", "10", "-C", classes.resolve("v10").toString(), ".")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
genKey();
|
||||
signJar(JAR_NAME)
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldMatch("signing.*META-INF/versions/9/version/Version.class")
|
||||
.shouldMatch("signing.*META-INF/versions/10/version/Version.class")
|
||||
.shouldMatch("signing.*version/Main.class")
|
||||
.shouldMatch("signing.*version/Version.class");
|
||||
verify(SIGNED_JAR);
|
||||
|
||||
// test with JarSigner API
|
||||
Files.deleteIfExists(Paths.get(SIGNED_JAR));
|
||||
signWithJarSignerAPI(JAR_NAME);
|
||||
verify(SIGNED_JAR);
|
||||
|
||||
// test Permission granted
|
||||
File keypass = new File("keypass");
|
||||
try (FileOutputStream fos = new FileOutputStream(keypass)) {
|
||||
fos.write(KEYPASS.getBytes());
|
||||
}
|
||||
String[] cmd = {
|
||||
"-classpath", SIGNED_JAR,
|
||||
"-Djava.security.manager",
|
||||
"-Djava.security.policy=" +
|
||||
TEST_SRC + File.separator + POLICY_FILE,
|
||||
"version.Main"};
|
||||
ProcessTools.executeTestJvm(cmd)
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain(VERSION_MESSAGE);
|
||||
}
|
||||
|
||||
private static void compile (String jarContent_path) throws Throwable {
|
||||
Path classes = Paths.get(USR_DIR, "classes", "base");
|
||||
Path source = Paths.get(TEST_SRC, jarContent_path, "base", "version");
|
||||
CompilerUtils.compile(source, classes);
|
||||
|
||||
classes = Paths.get(USR_DIR, "classes", "v9");
|
||||
source = Paths.get(TEST_SRC, jarContent_path , "v9", "version");
|
||||
CompilerUtils.compile(source, classes);
|
||||
|
||||
classes = Paths.get(USR_DIR, "classes", "v10");
|
||||
source = Paths.get(TEST_SRC, jarContent_path, "v10", "version");
|
||||
CompilerUtils.compile(source, classes);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer jar(String...args) throws Throwable {
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jar");
|
||||
Stream.of(args).forEach(launcher::addToolArg);
|
||||
return ProcessTools.executeCommand(launcher.getCommand());
|
||||
}
|
||||
|
||||
private static void genKey() throws Throwable {
|
||||
String keytool = JDKToolFinder.getJDKTool("keytool");
|
||||
Files.deleteIfExists(Paths.get(KEYSTORE));
|
||||
ProcessTools.executeCommand(keytool,
|
||||
"-J-Duser.language=en",
|
||||
"-J-Duser.country=US",
|
||||
"-genkey",
|
||||
"-alias", ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-keypass", KEYPASS,
|
||||
"-dname", "cn=sample",
|
||||
"-storepass", STOREPASS
|
||||
).shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer signJar(String jarName) throws Throwable {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("-verbose");
|
||||
args.add("-signedjar");
|
||||
args.add(SIGNED_JAR);
|
||||
args.add(jarName);
|
||||
args.add(ALIAS);
|
||||
|
||||
return jarsigner(args);
|
||||
}
|
||||
|
||||
private static void verify(String signedJarName) throws Throwable {
|
||||
verifyJar(signedJarName)
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain("jar verified")
|
||||
.shouldMatch("smk.*META-INF/versions/9/version/Version.class")
|
||||
.shouldMatch("smk.*META-INF/versions/10/version/Version.class")
|
||||
.shouldMatch("smk.*version/Main.class")
|
||||
.shouldMatch("smk.*version/Version.class");
|
||||
}
|
||||
|
||||
private static OutputAnalyzer verifyJar(String signedJarName) throws Throwable {
|
||||
List<String> args = new ArrayList<>();
|
||||
args.add("-verbose");
|
||||
args.add("-verify");
|
||||
args.add(signedJarName);
|
||||
|
||||
return jarsigner(args);
|
||||
}
|
||||
|
||||
private static OutputAnalyzer jarsigner(List<String> extra)
|
||||
throws Throwable {
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jarsigner")
|
||||
.addVMArg("-Duser.language=en")
|
||||
.addVMArg("-Duser.country=US")
|
||||
.addToolArg("-keystore")
|
||||
.addToolArg(KEYSTORE)
|
||||
.addToolArg("-storepass")
|
||||
.addToolArg(STOREPASS)
|
||||
.addToolArg("-keypass")
|
||||
.addToolArg(KEYPASS);
|
||||
for (String s : extra) {
|
||||
if (s.startsWith("-J")) {
|
||||
launcher.addVMArg(s.substring(2));
|
||||
} else {
|
||||
launcher.addToolArg(s);
|
||||
}
|
||||
}
|
||||
return ProcessTools.executeCommand(launcher.getCommand());
|
||||
}
|
||||
|
||||
private static void signWithJarSignerAPI(String jarName)
|
||||
throws Throwable {
|
||||
// Get JarSigner
|
||||
try (FileInputStream fis = new FileInputStream(KEYSTORE)) {
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(fis, STOREPASS.toCharArray());
|
||||
PrivateKey pk = (PrivateKey)ks.getKey(ALIAS, KEYPASS.toCharArray());
|
||||
Certificate cert = ks.getCertificate(ALIAS);
|
||||
JarSigner signer = new JarSigner.Builder(pk,
|
||||
CertificateFactory.getInstance("X.509").generateCertPath(
|
||||
Collections.singletonList(cert)))
|
||||
.build();
|
||||
// Sign jar
|
||||
try (ZipFile src = new JarFile(jarName);
|
||||
FileOutputStream out = new FileOutputStream(SIGNED_JAR)) {
|
||||
signer.sign(src,out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
keystore "file:keystore.jks";
|
||||
keystorePasswordURL "file:keypass";
|
||||
|
||||
grant signedBy "JavaTest" {
|
||||
permission java.lang.RuntimePermission "setIO";
|
||||
};
|
||||
|
||||
grant signedBy "other" {
|
||||
permission java.lang.RuntimePermission "setFactory";
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -21,23 +21,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.foo;
|
||||
package version;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.spi.ResourceBundleControlProvider;
|
||||
import java.security.Permission;
|
||||
|
||||
public class UserControlProvider implements ResourceBundleControlProvider {
|
||||
static final ResourceBundle.Control XMLCONTROL = new UserXMLControl();
|
||||
public class Main {
|
||||
|
||||
public ResourceBundle.Control getControl(String baseName) {
|
||||
System.out.println(getClass().getName()+".getControl called for " + baseName);
|
||||
|
||||
// Throws a NPE if baseName is null.
|
||||
if (baseName.startsWith("com.foo.Xml")) {
|
||||
System.out.println("\treturns " + XMLCONTROL);
|
||||
return XMLCONTROL;
|
||||
}
|
||||
System.out.println("\treturns null");
|
||||
return null;
|
||||
public static void main(String[] args) {
|
||||
Version v = new Version();
|
||||
System.out.println("I am running on version " + v.getVersion());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package version;
|
||||
|
||||
public class Version {
|
||||
|
||||
public int getVersion() {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package version;
|
||||
|
||||
public class Version {
|
||||
|
||||
public int getVersion() {
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package version;
|
||||
|
||||
import java.security.AccessControlException;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
public class Version {
|
||||
private static final Permission PERM1 = new RuntimePermission("setIO");
|
||||
private static final Permission PERM2 = new RuntimePermission("setFactory");
|
||||
|
||||
public int getVersion() {
|
||||
checkPermission(PERM1, false);
|
||||
checkPermission(PERM2, true);
|
||||
return 9;
|
||||
}
|
||||
|
||||
private void checkPermission(Permission perm, boolean expectException) {
|
||||
boolean getException = (Boolean) AccessController
|
||||
.doPrivileged((PrivilegedAction) () -> {
|
||||
try {
|
||||
AccessController.checkPermission(perm);
|
||||
return (Boolean) false;
|
||||
} catch (AccessControlException ex) {
|
||||
return (Boolean) true;
|
||||
}
|
||||
});
|
||||
|
||||
if (expectException ^ getException) {
|
||||
String message = "Check Permission :" + perm + "\n ExpectException = "
|
||||
+ expectException + "\n getException = " + getException;
|
||||
throw new RuntimeException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8168836
|
||||
* @summary Basic argument validation for --add-exports
|
||||
* @library /lib/testlibrary
|
||||
* @modules jdk.compiler
|
||||
* @build AddExportsTestWarningError CompilerUtils ModuleSourceBuilder
|
||||
* @build jdk.testlibrary.*
|
||||
* @run testng AddExportsTestWarningError
|
||||
*/
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import static jdk.testlibrary.ProcessTools.*;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
|
||||
@Test
|
||||
public class AddExportsTestWarningError {
|
||||
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
private static final Path SRC_DIR = Paths.get("src");
|
||||
private static final String M1_MAIN = "m1/p1.C1";
|
||||
private static final String M3_MAIN = "m3/p3.C3";
|
||||
|
||||
@BeforeTest
|
||||
public void setup() throws Exception {
|
||||
ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR);
|
||||
builder.writeJavaFiles("m1",
|
||||
"module m1 { }",
|
||||
"package p1; public class C1 { " +
|
||||
" public static void main(String... args) {}" +
|
||||
"}");
|
||||
|
||||
builder.writeJavaFiles("m2",
|
||||
"module m2 { requires m1; exports p2; }",
|
||||
"package p2; public class C2 { private p1.C1 c1; }");
|
||||
|
||||
builder.writeJavaFiles("m3",
|
||||
"module m3 { requires m2; }",
|
||||
"package p3; class C3 { " +
|
||||
" p1.C1 c; " +
|
||||
" public static void main(String... args) { new p2.C2(); }" +
|
||||
"}");
|
||||
|
||||
builder.compile("m1", MODS_DIR);
|
||||
builder.compile("m2", MODS_DIR, "--add-exports", "m1/p1=m2");
|
||||
builder.compile("m3", MODS_DIR, "--add-exports", "m1/p1=m3");
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "goodcases")
|
||||
public Object[][] goodCases() {
|
||||
return new Object[][]{
|
||||
|
||||
// empty items
|
||||
{ "m1/p1=,m2,m3", null },
|
||||
{ "m1/p1=m2,,m3", null },
|
||||
{ "m1/p1=m2,m3,", null },
|
||||
|
||||
// duplicates
|
||||
{ "m1/p1=m2,m2,m3,,", null },
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "goodcases")
|
||||
public void test(String value, String ignore) throws Exception {
|
||||
testNoWarning(value);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "illFormedAddExports")
|
||||
public Object[][] illFormedAddExports() {
|
||||
return new Object[][]{
|
||||
{ "m1", "Unable to parse --add-exports <module>=<value>: m1"},
|
||||
|
||||
// missing source part
|
||||
{ "=m2", "Unable to parse --add-exports <module>=<value>: =m2"},
|
||||
{ "/=m2", "Unable to parse --add-exports <module>/<package>: /" },
|
||||
{ "m1=m2", "Unable to parse --add-exports <module>/<package>: m1" },
|
||||
{ "/p1=m2", "Unable to parse --add-exports <module>/<package>: /p1" },
|
||||
{ "m1p1=m2", "Unable to parse --add-exports <module>/<package>: m1p1" },
|
||||
|
||||
// empty list, missing target
|
||||
{ "m1/p1=", "Unable to parse --add-exports <module>=<value>: m1/p1=" },
|
||||
{ "m1/p1=,,", "Target must be specified: --add-exports m1/p1=,," },
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "illFormedAddExports")
|
||||
public void testIllFormedAddExports(String value, String msg) throws Exception {
|
||||
testError(value, msg);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "unknownNames")
|
||||
public Object[][] unknownNames() {
|
||||
return new Object[][]{
|
||||
|
||||
// source not found
|
||||
{"DoesNotExist/p=m1", "WARNING: Unknown module: DoesNotExist specified in --add-exports"},
|
||||
{"m1/DoesNotExist=m2", "WARNING: package DoesNotExist not in m1"},
|
||||
|
||||
// target not found
|
||||
{"m1/p1=DoesNotExist", "WARNING: Unknown module: DoesNotExist specified in --add-exports"},
|
||||
|
||||
// bad names
|
||||
{"m*/p1=m2", "WARNING: Unknown module: m* specified in --add-exports"},
|
||||
{"m1/p!=m2", "WARNING: package p! not in m1"},
|
||||
{"m1/p1=m!", "WARNING: Unknown module: m! specified in --add-exports"},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "unknownNames")
|
||||
public void testUnknownNames(String value, String msg) throws Exception {
|
||||
testWarning(value, msg);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "missingArguments")
|
||||
public Object[][] missingArguments() {
|
||||
return new Object[][]{
|
||||
{ new String[] { "--add-exports" },
|
||||
"Error: --add-exports requires modules to be specified"},
|
||||
|
||||
{ new String[] { "--add-exports=" },
|
||||
"Error: --add-exports= requires modules to be specified" },
|
||||
|
||||
{ new String[] { "--add-exports", "" },
|
||||
"Error: --add-exports requires modules to be specified"}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "missingArguments")
|
||||
public void testMissingArguments(String[] options, String msg) throws Exception {
|
||||
String[] args = Stream.concat(Arrays.stream(options),
|
||||
Stream.of("-version"))
|
||||
.toArray(String[]::new);
|
||||
int exitValue = executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
|
||||
private void testWarning(String value, String msg) throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--add-exports", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M1_MAIN)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue == 0);
|
||||
}
|
||||
|
||||
private void testError(String value, String msg) throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--add-exports", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M1_MAIN)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
|
||||
private void testNoWarning(String value) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintStream ps = new PrintStream(new BufferedOutputStream(baos));
|
||||
OutputAnalyzer outputAnalyzer =
|
||||
executeTestJava("--add-exports", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M3_MAIN)
|
||||
.outputTo(ps)
|
||||
.errorTo(ps);
|
||||
|
||||
assertTrue(outputAnalyzer.getExitValue() == 0);
|
||||
|
||||
System.out.println(baos.toString());
|
||||
String[] output = baos.toString().split("\\R");
|
||||
assertFalse(Arrays.stream(output)
|
||||
.filter(s -> !s.matches("WARNING: Module name .* may soon be illegal"))
|
||||
.filter(s -> s.startsWith("WARNING:"))
|
||||
.findAny().isPresent());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8168836
|
||||
* @summary Basic argument validation for --add-reads
|
||||
* @library /lib/testlibrary
|
||||
* @modules jdk.compiler
|
||||
* @build AddReadsTestWarningError CompilerUtils ModuleSourceBuilder
|
||||
* @build jdk.testlibrary.*
|
||||
* @run testng AddReadsTestWarningError
|
||||
*/
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import static jdk.testlibrary.ProcessTools.*;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
|
||||
@Test
|
||||
public class AddReadsTestWarningError {
|
||||
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
private static final Path SRC_DIR = Paths.get("src");
|
||||
private static final String M1_MAIN = "m1/p1.C1";
|
||||
private static final String M4_MAIN = "m4/p4.C4";
|
||||
|
||||
@BeforeTest
|
||||
public void setup() throws Exception {
|
||||
ModuleSourceBuilder builder = new ModuleSourceBuilder(SRC_DIR);
|
||||
builder.writeJavaFiles("m1",
|
||||
"module m1 { requires m4; }",
|
||||
"package p1; public class C1 { " +
|
||||
" public static void main(String... args) {" +
|
||||
" p2.C2 c2 = new p2.C2();" +
|
||||
" p3.C3 c3 = new p3.C3();" +
|
||||
" }" +
|
||||
"}"
|
||||
);
|
||||
|
||||
builder.writeJavaFiles("m2",
|
||||
"module m2 { exports p2; }",
|
||||
"package p2; public class C2 { }"
|
||||
);
|
||||
|
||||
builder.writeJavaFiles("m3",
|
||||
"module m3 { exports p3; }",
|
||||
"package p3; public class C3 { }"
|
||||
);
|
||||
|
||||
builder.writeJavaFiles("m4",
|
||||
"module m4 { requires m2; requires m3; }",
|
||||
"package p4; public class C4 { " +
|
||||
" public static void main(String... args) {}" +
|
||||
"}"
|
||||
);
|
||||
|
||||
builder.compile("m2", MODS_DIR);
|
||||
builder.compile("m3", MODS_DIR);
|
||||
builder.compile("m4", MODS_DIR);
|
||||
builder.compile("m1", MODS_DIR, "--add-reads", "m1=m2,m3");
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "goodcases")
|
||||
public Object[][] goodCases() {
|
||||
return new Object[][]{
|
||||
// empty items
|
||||
{ "m1=,m2,m3", null },
|
||||
{ "m1=m2,,m3", null },
|
||||
{ "m1=m2,m3,", null },
|
||||
|
||||
// duplicates
|
||||
{ "m1=m2,m2,m3,,", null },
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "goodcases")
|
||||
public void test(String value, String ignore) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PrintStream ps = new PrintStream(new BufferedOutputStream(baos));
|
||||
OutputAnalyzer outputAnalyzer =
|
||||
executeTestJava("--add-reads", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M1_MAIN)
|
||||
.outputTo(ps)
|
||||
.errorTo(ps);
|
||||
|
||||
assertTrue(outputAnalyzer.getExitValue() == 0);
|
||||
|
||||
System.out.println(baos.toString());
|
||||
String[] output = baos.toString().split("\\R");
|
||||
assertFalse(Arrays.stream(output)
|
||||
.filter(s -> !s.matches("WARNING: Module name .* may soon be illegal"))
|
||||
.filter(s -> s.startsWith("WARNING:"))
|
||||
.findAny().isPresent());
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "illFormedAddReads")
|
||||
public Object[][] illFormedAddReads() {
|
||||
return new Object[][]{
|
||||
{ "m1", "Unable to parse --add-reads <module>=<value>: m1" },
|
||||
|
||||
// missing source part
|
||||
{ "=m2", "Unable to parse --add-reads <module>=<value>: =m2" },
|
||||
|
||||
// empty list, missing target
|
||||
{ "m1=", "Unable to parse --add-reads <module>=<value>: m1=" },
|
||||
|
||||
// empty list
|
||||
{ "m1=,,", "Target must be specified: --add-reads m1=,," },
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Test(dataProvider = "illFormedAddReads")
|
||||
public void testIllFormedAddReads(String value, String msg) throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--add-reads", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M4_MAIN)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "unknownNames")
|
||||
public Object[][] unknownNames() {
|
||||
return new Object[][]{
|
||||
|
||||
// source not found
|
||||
{"DoesNotExist=m2", "WARNING: Unknown module: DoesNotExist specified in --add-reads"},
|
||||
|
||||
// target not found
|
||||
{"m2=DoesNotExist", "WARNING: Unknown module: DoesNotExist specified in --add-reads"},
|
||||
|
||||
// bad names
|
||||
{"m*=m2", "WARNING: Unknown module: m* specified in --add-reads"},
|
||||
{"m2=m!", "WARNING: Unknown module: m! specified in --add-reads"},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "unknownNames")
|
||||
public void testUnknownNames(String value, String msg) throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--add-reads", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", M4_MAIN)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue == 0);
|
||||
}
|
||||
|
||||
|
||||
@DataProvider(name = "missingArguments")
|
||||
public Object[][] missingArguments() {
|
||||
return new Object[][]{
|
||||
{ new String[] {"--add-reads" },
|
||||
"Error: --add-reads requires modules to be specified"},
|
||||
|
||||
{ new String[] { "--add-reads=" },
|
||||
"Error: --add-reads= requires modules to be specified"},
|
||||
|
||||
{ new String[] { "--add-reads", "" },
|
||||
"Error: --add-reads requires modules to be specified"},
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "missingArguments")
|
||||
public void testEmptyArgument(String[] options, String msg) throws Exception {
|
||||
String[] args = Stream.concat(Arrays.stream(options), Stream.of("-version"))
|
||||
.toArray(String[]::new);
|
||||
int exitValue = executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8168836
|
||||
* @summary Basic argument validation for --patch-module
|
||||
* @library /lib/testlibrary
|
||||
* @modules jdk.compiler
|
||||
* @build PatchTestWarningError CompilerUtils JarUtils jdk.testlibrary.*
|
||||
* @run testng PatchTestWarningError
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static jdk.testlibrary.ProcessTools.*;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
* This test
|
||||
* See PatchTestWarningError for test description.
|
||||
*/
|
||||
|
||||
@Test
|
||||
public class PatchTestWarningError {
|
||||
|
||||
// top-level source directory
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
|
||||
// source/destination tree for the test module
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path MODS_DIR = Paths.get("mods");
|
||||
|
||||
// source/destination tree for patch tree 1
|
||||
private static final Path SRC1_DIR = Paths.get(TEST_SRC, "src1");
|
||||
private static final Path PATCHES1_DIR = Paths.get("patches1");
|
||||
|
||||
// source/destination tree for patch tree 2
|
||||
private static final Path SRC2_DIR = Paths.get(TEST_SRC, "src2");
|
||||
private static final Path PATCHES2_DIR = Paths.get("patches2");
|
||||
|
||||
// patch path for java.base
|
||||
private static final String PATCHES_PATH =
|
||||
PATCHES1_DIR.resolve("java.base") + File.pathSeparator +
|
||||
PATCHES2_DIR.resolve("java.base");
|
||||
|
||||
// the classes overridden or added with --patch-module
|
||||
private static final String[] CLASSES = {
|
||||
|
||||
// java.base = boot loader
|
||||
"java.base/java.text.Annotation", // override class
|
||||
"java.base/java.text.AnnotationBuddy", // add class to package
|
||||
"java.base/java.lang2.Object", // new package
|
||||
|
||||
};
|
||||
|
||||
|
||||
@BeforeTest
|
||||
public void setup() throws Exception {
|
||||
|
||||
// javac -d mods/test src/test/**
|
||||
boolean compiled= CompilerUtils.compile(SRC_DIR.resolve("test"),
|
||||
MODS_DIR.resolve("test"));
|
||||
assertTrue(compiled, "classes did not compile");
|
||||
|
||||
// javac -Xmodule:$MODULE -d patches1/$MODULE patches1/$MODULE/**
|
||||
Path src = SRC1_DIR.resolve("java.base");
|
||||
Path output = PATCHES1_DIR.resolve(src.getFileName());
|
||||
Files.createDirectories(output);
|
||||
String mn = src.getFileName().toString();
|
||||
compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
|
||||
assertTrue(compiled, "classes did not compile");
|
||||
|
||||
// javac -Xmodule:$MODULE -d patches2/$MODULE patches2/$MODULE/**
|
||||
src = SRC2_DIR.resolve("java.base");
|
||||
output = PATCHES2_DIR.resolve(src.getFileName());
|
||||
Files.createDirectories(output);
|
||||
mn = src.getFileName().toString();
|
||||
compiled = CompilerUtils.compile(src, output, "-Xmodule:" + mn);
|
||||
assertTrue(compiled, "classes did not compile");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with --patch-module options patching the same module
|
||||
*/
|
||||
public void testDuplicateModule() throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--patch-module", "java.base=" + PATCHES1_DIR.resolve("java.base"),
|
||||
"--patch-module", "java.base=" + PATCHES2_DIR.resolve("java.base"),
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
// error output by VM
|
||||
.shouldContain("Cannot specify java.base more than once to --patch-module")
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
|
||||
@DataProvider(name = "emptyItem")
|
||||
public Object[][] emptyItems() {
|
||||
String patch1 = PATCHES1_DIR.resolve("java.base").toString();
|
||||
String patch2 = PATCHES2_DIR.resolve("java.base").toString();
|
||||
String pathSep = File.pathSeparator;
|
||||
return new Object[][]{
|
||||
|
||||
{ "java.base="+ pathSep + patch1 + pathSep + patch2, null },
|
||||
{ "java.base="+ patch1 + pathSep + pathSep + patch2, null },
|
||||
{ "java.base="+ patch1 + pathSep + patch2 + pathSep + pathSep, null },
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty item in a non-empty path list
|
||||
*/
|
||||
@Test(dataProvider = "emptyItem")
|
||||
public void testEmptyItem(String value, String msg) throws Exception {
|
||||
// the argument to the test is the list of classes overridden or added
|
||||
String arg = Stream.of(CLASSES).collect(Collectors.joining(","));
|
||||
|
||||
int exitValue =
|
||||
executeTestJava("--patch-module", value,
|
||||
"--add-exports", "java.base/java.lang2=test",
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main", arg)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bad module name that should emit a warning
|
||||
*/
|
||||
public void testBadName() throws Exception {
|
||||
// the argument to the test is the list of classes overridden or added
|
||||
String arg = Stream.of(CLASSES).collect(Collectors.joining(","));
|
||||
|
||||
int exitValue =
|
||||
executeTestJava("--patch-module", "DoesNotExist=tmp",
|
||||
"--patch-module", "java.base=" + PATCHES_PATH,
|
||||
"--add-exports", "java.base/java.lang2=test",
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main", arg)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain("WARNING: Unknown module: DoesNotExist specified in --patch-module")
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue == 0);
|
||||
}
|
||||
|
||||
@DataProvider(name = "badArguments")
|
||||
public Object[][] badArguments() {
|
||||
return new Object[][]{
|
||||
|
||||
// source not found
|
||||
{ "=tmp", "Unable to parse --patch-module <module>=<value>: =tmp" },
|
||||
|
||||
// target not found: check by VM
|
||||
{ "java.base", "Missing '=' in --patch-module specification" },
|
||||
{ "foo", "Missing '=' in --patch-module specification" },
|
||||
|
||||
// target not found
|
||||
{ "java.base=", "Unable to parse --patch-module <module>=<value>: java.base=" },
|
||||
{ "java.base=" + File.pathSeparator,
|
||||
"Target must be specified: --patch-module java.base=" + File.pathSeparator }
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ill-formed argument to --patch-module
|
||||
*/
|
||||
@Test(dataProvider = "badArguments")
|
||||
public void testBadArgument(String value, String msg) throws Exception {
|
||||
int exitValue =
|
||||
executeTestJava("--patch-module", value,
|
||||
"--module-path", MODS_DIR.toString(),
|
||||
"-m", "test/jdk.test.Main")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.shouldContain(msg)
|
||||
.getExitValue();
|
||||
|
||||
assertTrue(exitValue != 0);
|
||||
}
|
||||
}
|
||||
@@ -29,4 +29,8 @@ package jdk.internal.module;
|
||||
*/
|
||||
public final class SystemModules {
|
||||
public static final String[] MODULE_NAMES = new String[0];
|
||||
|
||||
public static boolean hasSplitPackages() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user