This commit is contained in:
Lana Steuck 2017-03-23 22:57:12 +00:00
commit 57f2b95e2f
184 changed files with 4928 additions and 1989 deletions

View File

@ -128,7 +128,6 @@ SUNWprivate_1.1 {
Java_java_lang_Class_isInstance;
Java_java_lang_Class_registerNatives;
Java_java_lang_ClassLoader_findBootstrapClass;
Java_java_lang_ClassLoader_defineClass0;
Java_java_lang_ClassLoader_defineClass1;
Java_java_lang_ClassLoader_defineClass2;
Java_java_lang_ClassLoader_findBuiltinLib;

View File

@ -28,6 +28,7 @@ package build.tools.taglet;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import jdk.javadoc.doclet.Taglet;
import static jdk.javadoc.doclet.Taglet.Location.*;
@ -59,7 +60,7 @@ public class Incubating implements Taglet {
+ " Will be removed in a future release.</b>";
@Override
public String toString(List<? extends DocTree> tags) {
public String toString(List<? extends DocTree> tags, Element elem) {
return MESSAGE;
}
}

View File

@ -64,9 +64,9 @@ import java.util.StringJoiner;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.module.Resources;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.ConstantPool;
import jdk.internal.reflect.Reflection;
@ -2563,11 +2563,11 @@ public final class Class<T> implements java.io.Serializable,
Module module = getModule();
if (module.isNamed()) {
if (!ResourceHelper.isSimpleResource(name)) {
if (Resources.canEncapsulate(name)) {
Module caller = Reflection.getCallerClass().getModule();
if (caller != module) {
Set<String> packages = module.getDescriptor().packages();
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
if (packages.contains(pn) && !module.isOpen(pn, caller)) {
// resource is in package not open to caller
return null;
@ -2665,11 +2665,11 @@ public final class Class<T> implements java.io.Serializable,
Module module = getModule();
if (module.isNamed()) {
if (!ResourceHelper.isSimpleResource(name)) {
if (Resources.canEncapsulate(name)) {
Module caller = Reflection.getCallerClass().getModule();
if (caller != module) {
Set<String> packages = module.getDescriptor().packages();
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
if (packages.contains(pn) && !module.isOpen(pn, caller)) {
// resource is in package not open to caller
return null;
@ -2771,7 +2771,7 @@ public final class Class<T> implements java.io.Serializable,
* In all other cases, it requires RuntimePermission("accessDeclaredMembers")
* permission.
*/
final ClassLoader ccl = caller.getClassLoader0();
final ClassLoader ccl = ClassLoader.getClassLoader(caller);
if (which != Member.PUBLIC) {
final ClassLoader cl = getClassLoader0();
if (ccl != cl) {

View File

@ -983,7 +983,7 @@ public abstract class ClassLoader {
{
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass1(name, b, off, len, protectionDomain, source);
Class<?> c = defineClass1(this, name, b, off, len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
@ -1075,17 +1075,17 @@ public abstract class ClassLoader {
protectionDomain = preDefineClass(name, protectionDomain);
String source = defineClassSourceLocation(protectionDomain);
Class<?> c = defineClass2(name, b, b.position(), len, protectionDomain, source);
Class<?> c = defineClass2(this, name, b, b.position(), len, protectionDomain, source);
postDefineClass(c, protectionDomain);
return c;
}
private native Class<?> defineClass1(String name, byte[] b, int off, int len,
ProtectionDomain pd, String source);
static native Class<?> defineClass1(ClassLoader loader, String name, byte[] b, int off, int len,
ProtectionDomain pd, String source);
private native Class<?> defineClass2(String name, java.nio.ByteBuffer b,
int off, int len, ProtectionDomain pd,
String source);
static native Class<?> defineClass2(ClassLoader loader, String name, java.nio.ByteBuffer b,
int off, int len, ProtectionDomain pd,
String source);
// true if the name is null or has the potential to be a valid binary name
private boolean checkName(String name) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -26,9 +26,7 @@
package java.lang;
import java.security.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.lang.module.ModuleFinder;
/**
* This class is for runtime permissions. A {@code RuntimePermission}
@ -265,6 +263,16 @@ import java.util.StringTokenizer;
* </tr>
*
* <tr>
* <td>defineClass</td>
* <td>Define a class with
* {@link java.lang.invoke.MethodHandles.Lookup#defineClass(byte[])
* Lookup.defineClass}.</td>
* <td>This grants code with a suitably privileged {@code Lookup} object
* permission to define classes in the same package as the {@code Lookup}'s
* lookup class. </td>
* </tr>
*
* <tr>
* <td>accessDeclaredMembers</td>
* <td>Access to the declared members of a class</td>
* <td>This grants code permission to query a class for its public,
@ -367,6 +375,14 @@ import java.util.StringTokenizer;
* <td>See {@link java.lang.System.LoggerFinder java.lang.System.LoggerFinder}
* for more information.</td>
* </tr>
*
* <tr>
* <td>accessSystemModules</td>
* <td>Access system modules in the runtime image.</td>
* <td>This grants the permission to access resources in the
* {@linkplain ModuleFinder#ofSystem system modules} in the runtime image.</td>
* </tr>
*
* </table>
*
* @implNote

View File

@ -982,13 +982,6 @@ final class StackStreamFactory {
}
private static boolean isReflectionFrame(Class<?> c) {
if (c.getName().startsWith("jdk.internal.reflect") &&
!MethodAccessor.class.isAssignableFrom(c) &&
!ConstructorAccessor.class.isAssignableFrom(c)) {
throw new InternalError("Not jdk.internal.reflect.MethodAccessor"
+ " or jdk.internal.reflect.ConstructorAccessor: "
+ c.toString());
}
// ## should filter all @Hidden frames?
return c == Method.class ||
c == Constructor.class ||

View File

@ -43,6 +43,7 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.Module;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.util.Properties;
import java.util.PropertyPermission;
import java.util.Map;
@ -1844,6 +1845,39 @@ public final class System {
return new PrintStream(new BufferedOutputStream(fos, 128), true);
}
/**
* Logs an exception/error at initialization time to stdout or stderr.
*
* @param printToStderr to print to stderr rather than stdout
* @param printStackTrace to print the stack trace
* @param msg the message to print before the exception, can be {@code null}
* @param e the exception or error
*/
private static void logInitException(boolean printToStderr,
boolean printStackTrace,
String msg,
Throwable e) {
if (VM.initLevel() < 1) {
throw new InternalError("system classes not initialized");
}
PrintStream log = (printToStderr) ? err : out;
if (msg != null) {
log.println(msg);
}
if (printStackTrace) {
e.printStackTrace(log);
} else {
log.println(e);
for (Throwable suppressed : e.getSuppressed()) {
log.println("Suppressed: " + suppressed);
}
Throwable cause = e.getCause();
if (cause != null) {
log.println("Caused by: " + cause);
}
}
}
/**
* Initialize the system class. Called after thread initialization.
*/
@ -1922,13 +1956,25 @@ public final class System {
/*
* Invoked by VM. Phase 2 module system initialization.
* Only classes in java.base can be loaded in this phase.
*
* @param printToStderr print exceptions to stderr rather than stdout
* @param printStackTrace print stack trace when exception occurs
*
* @return JNI_OK for success, JNI_ERR for failure
*/
private static void initPhase2() {
// initialize the module system
System.bootLayer = ModuleBootstrap.boot();
private static int initPhase2(boolean printToStderr, boolean printStackTrace) {
try {
bootLayer = ModuleBootstrap.boot();
} catch (Exception | Error e) {
logInitException(printToStderr, printStackTrace,
"Error occurred during initialization of boot layer", e);
return -1; // JNI_ERR
}
// module system initialized
VM.initLevel(2);
return 0; // JNI_OK
}
/*
@ -2034,6 +2080,9 @@ public final class System {
public ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl) {
return cl.createOrGetClassLoaderValueMap();
}
public Class<?> defineClass(ClassLoader loader, String name, byte[] b, ProtectionDomain pd, String source) {
return ClassLoader.defineClass1(loader, name, b, 0, b.length, pd, source);
}
public Class<?> findBootstrapClassOrNull(ClassLoader cl, String name) {
return cl.findBootstrapClassOrNull(name);
}

View File

@ -25,6 +25,9 @@
package java.lang.invoke;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.vm.annotation.ForceInline;
@ -43,6 +46,9 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.Module;
import java.lang.reflect.ReflectPermission;
import java.nio.ByteOrder;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
@ -191,6 +197,12 @@ public class MethodHandles {
}
if ((lookup.lookupModes() & Lookup.MODULE) == 0)
throw new IllegalAccessException("lookup does not have MODULE lookup mode");
if (!callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
logger.logIfOpenedByBackdoor(lookup, targetClass);
}
}
return new Lookup(targetClass);
}
@ -855,6 +867,112 @@ public class MethodHandles {
return new Lookup(lookupClass(), newModes);
}
/**
* Defines a class to the same class loader and in the same runtime package and
* {@linkplain java.security.ProtectionDomain protection domain} as this lookup's
* {@linkplain #lookupClass() lookup class}.
*
* <p> The {@linkplain #lookupModes() lookup modes} for this lookup must include
* {@link #PACKAGE PACKAGE} access as default (package) members will be
* accessible to the class. The {@code PACKAGE} lookup mode serves to authenticate
* that the lookup object was created by a caller in the runtime package (or derived
* from a lookup originally created by suitably privileged code to a target class in
* the runtime package). The lookup modes cannot include {@link #PRIVATE PRIVATE}
* access. A lookup with {@code PRIVATE} access can be downgraded to drop this lookup
* mode with the {@linkplain #dropLookupMode(int) dropLookupMode} method. </p>
*
* <p> The {@code bytes} parameter is the class bytes of a valid class file (as defined
* by the <em>The Java Virtual Machine Specification</em>) with a class name in the
* same package as the lookup class. </p>
*
* <p> This method does not run the class initializer. The class initializer may
* run at a later time, as detailed in section 12.4 of the <em>The Java Language
* Specification</em>. </p>
*
* <p> If there is a security manager, its {@code checkPermission} method is first called
* to check {@code RuntimePermission("defineClass")}. </p>
*
* @param bytes the class bytes
* @return the {@code Class} object for the class
* @throws IllegalArgumentException the bytes are for a class in a different package
* to the lookup class
* @throws IllegalAccessException if this lookup does not have {@code PACKAGE} access
* @throws UnsupportedOperationException if the lookup class has {@code PRIVATE} access
* @throws LinkageError if the class is malformed ({@code ClassFormatError}), cannot be
* verified ({@code VerifyError}), is already defined, or another linkage error occurs
* @throws SecurityException if denied by the security manager
* @throws NullPointerException if {@code bytes} is {@code null}
* @since 9
* @spec JPMS
* @see Lookup#privateLookupIn
* @see Lookup#dropLookupMode
* @see ClassLoader#defineClass(String,byte[],int,int,ProtectionDomain)
*/
public Class<?> defineClass(byte[] bytes) throws IllegalAccessException {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(new RuntimePermission("defineClass"));
if (hasPrivateAccess())
throw new UnsupportedOperationException("PRIVATE access not supported");
if ((lookupModes() & PACKAGE) == 0)
throw new IllegalAccessException("Lookup does not have PACKAGE access");
assert (lookupModes() & (MODULE|PUBLIC)) != 0;
// parse class bytes to get class name (in internal form)
bytes = bytes.clone();
String name;
try {
ClassReader reader = new ClassReader(bytes);
name = reader.getClassName();
} catch (RuntimeException e) {
// ASM exceptions are poorly specified
ClassFormatError cfe = new ClassFormatError();
cfe.initCause(e);
throw cfe;
}
// get package and class name in binary form
String cn, pn;
int index = name.lastIndexOf('/');
if (index == -1) {
cn = name;
pn = "";
} else {
cn = name.replace('/', '.');
pn = cn.substring(0, index);
}
if (!pn.equals(lookupClass.getPackageName())) {
throw new IllegalArgumentException("Class not in same package as lookup class");
}
// invoke the class loader's defineClass method
ClassLoader loader = lookupClass.getClassLoader();
ProtectionDomain pd = (loader != null) ? lookupClassProtectionDomain() : null;
String source = "__Lookup_defineClass__";
Class<?> clazz = SharedSecrets.getJavaLangAccess().defineClass(loader, cn, bytes, pd, source);
assert clazz.getClassLoader() == lookupClass.getClassLoader()
&& clazz.getPackageName().equals(lookupClass.getPackageName())
&& protectionDomain(clazz) == lookupClassProtectionDomain();
return clazz;
}
private ProtectionDomain lookupClassProtectionDomain() {
ProtectionDomain pd = cachedProtectionDomain;
if (pd == null) {
cachedProtectionDomain = pd = protectionDomain(lookupClass);
}
return pd;
}
private ProtectionDomain protectionDomain(Class<?> clazz) {
PrivilegedAction<ProtectionDomain> pa = clazz::getProtectionDomain;
return AccessController.doPrivileged(pa);
}
// cached protection domain
private volatile ProtectionDomain cachedProtectionDomain;
// Make sure outer class is initialized first.
static { IMPL_NAMES.getClass(); }
@ -1948,7 +2066,7 @@ return mh1;
/**
* Returns {@code true} if this lookup has {@code PRIVATE} access.
* @return {@code true} if this lookup has {@code PRIVATE} acesss.
* @return {@code true} if this lookup has {@code PRIVATE} access.
* @since 9
*/
public boolean hasPrivateAccess() {

View File

@ -112,11 +112,9 @@ public final class Configuration {
// module constraints on target
private final String osName;
private final String osArch;
private final String osVersion;
String osName() { return osName; }
String osArch() { return osArch; }
String osVersion() { return osVersion; }
private Configuration() {
this.parents = Collections.emptyList();
@ -125,7 +123,6 @@ public final class Configuration {
this.nameToModule = Collections.emptyMap();
this.osName = null;
this.osArch = null;
this.osVersion = null;
}
private Configuration(List<Configuration> parents,
@ -152,7 +149,6 @@ public final class Configuration {
this.osName = resolver.osName();
this.osArch = resolver.osArch();
this.osVersion = resolver.osVersion();
}
/**
@ -281,6 +277,7 @@ public final class Configuration {
* <em>observability-related</em> reasons: </p>
*
* <ul>
*
* <li><p> A root module, or a direct or transitive dependency, is not
* found. </p></li>
*
@ -289,13 +286,6 @@ public final class Configuration {
* descriptor ({@code module-info.class}) or two versions of the same
* module are found in the same directory. </p></li>
*
* <li><p> A module with the required name is found but the module
* requires a different {@link ModuleDescriptor#osName() operating
* system}, {@link ModuleDescriptor#osArch() architecture}, or {@link
* ModuleDescriptor#osVersion() version} to other modules that have
* been resolved for the new configuration or modules in the parent
* configurations. </p></li>
*
* </ul>
*
* <p> Post-resolution consistency checks may fail with {@code
@ -306,6 +296,10 @@ public final class Configuration {
* <li><p> A cycle is detected, say where module {@code m1} requires
* module {@code m2} and {@code m2} requires {@code m1}. </p></li>
*
* <li><p> A module reads two or more modules with the same name. This
* includes the case where a module reads another with the same name as
* itself. </p></li>
*
* <li><p> Two or more modules in the configuration export the same
* package to a module that reads both. This includes the case where a
* module {@code M} containing package {@code p} reads another module
@ -319,8 +313,9 @@ public final class Configuration {
* </ul>
*
* @implNote In the implementation then observability of modules may depend
* on referential integrity checks that ensure different builds of tightly
* coupled modules are not combined in the same configuration.
* on referential integrity or other checks that ensure different builds of
* tightly coupled modules or modules for specific operating systems or
* architectures are not combined in the same configuration.
*
* @param before
* The <em>before</em> module finder to find modules

View File

@ -179,8 +179,10 @@ public class ModuleDescriptor
private final Set<Modifier> mods;
private final String name;
private final Version compiledVersion;
private final String rawCompiledVersion;
private Requires(Set<Modifier> ms, String mn, Version v) {
private Requires(Set<Modifier> ms, String mn, Version v, String vs) {
assert v == null || vs == null;
if (ms.isEmpty()) {
ms = Collections.emptySet();
} else {
@ -189,12 +191,14 @@ public class ModuleDescriptor
this.mods = ms;
this.name = mn;
this.compiledVersion = v;
this.rawCompiledVersion = vs;
}
private Requires(Set<Modifier> ms, String mn, Version v, boolean unused) {
this.mods = ms;
this.name = mn;
this.compiledVersion = v;
this.rawCompiledVersion = null;
}
/**
@ -218,12 +222,33 @@ public class ModuleDescriptor
/**
* Returns the version of the module if recorded at compile-time.
*
* @return The version of the module if recorded at compile-time
* @return The version of the module if recorded at compile-time,
* or an empty {@code Optional} if no version was recorded or
* the version string recorded is {@linkplain Version#parse(String)
* unparseable}
*/
public Optional<Version> compiledVersion() {
return Optional.ofNullable(compiledVersion);
}
/**
* Returns the string with the possibly-unparseable version of the module
* if recorded at compile-time.
*
* @return The string containing the version of the module if recorded
* at compile-time, or an empty {@code Optional} if no version
* was recorded
*
* @see #compiledVersion()
*/
public Optional<String> rawCompiledVersion() {
if (compiledVersion != null) {
return Optional.of(compiledVersion.toString());
} else {
return Optional.ofNullable(rawCompiledVersion);
}
}
/**
* Compares this module dependence to another.
*
@ -236,7 +261,10 @@ public class ModuleDescriptor
* recorded at compile-time are compared. When comparing the versions
* recorded at compile-time then a dependence that has a recorded
* version is considered to succeed a dependence that does not have a
* recorded version. </p>
* recorded version. If both recorded versions are {@linkplain
* Version#parse(String) unparseable} then the {@linkplain
* #rawCompiledVersion() raw version strings} are compared
* lexicographically. </p>
*
* @param that
* The module dependence to compare
@ -262,6 +290,10 @@ public class ModuleDescriptor
c = compare(this.compiledVersion, that.compiledVersion);
if (c != 0) return c;
// rawCompiledVersion
c = compare(this.rawCompiledVersion, that.rawCompiledVersion);
if (c != 0) return c;
return 0;
}
@ -289,7 +321,8 @@ public class ModuleDescriptor
return false;
Requires that = (Requires)ob;
return name.equals(that.name) && mods.equals(that.mods)
&& Objects.equals(compiledVersion, that.compiledVersion);
&& Objects.equals(compiledVersion, that.compiledVersion)
&& Objects.equals(rawCompiledVersion, that.rawCompiledVersion);
}
/**
@ -306,6 +339,8 @@ public class ModuleDescriptor
int hash = name.hashCode() * 43 + mods.hashCode();
if (compiledVersion != null)
hash = hash * 43 + compiledVersion.hashCode();
if (rawCompiledVersion != null)
hash = hash * 43 + rawCompiledVersion.hashCode();
return hash;
}
@ -774,7 +809,7 @@ public class ModuleDescriptor
/**
* Returns the fully qualified class name of the service type.
*
* @return The fully qualified class name of the service type.
* @return The fully qualified class name of the service type
*/
public String service() { return service; }
@ -1199,6 +1234,7 @@ public class ModuleDescriptor
private final String name;
private final Version version;
private final String rawVersionString;
private final Set<Modifier> modifiers;
private final boolean open; // true if modifiers contains OPEN
private final boolean automatic; // true if modifiers contains AUTOMATIC
@ -1209,12 +1245,10 @@ public class ModuleDescriptor
private final Set<Provides> provides;
private final Set<String> packages;
private final String mainClass;
private final String osName;
private final String osArch;
private final String osVersion;
private ModuleDescriptor(String name,
Version version,
String rawVersionString,
Set<Modifier> modifiers,
Set<Requires> requires,
Set<Exports> exports,
@ -1222,13 +1256,12 @@ public class ModuleDescriptor
Set<String> uses,
Set<Provides> provides,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion)
String mainClass)
{
assert version == null || rawVersionString == null;
this.name = name;
this.version = version;
this.rawVersionString = rawVersionString;
this.modifiers = emptyOrUnmodifiableSet(modifiers);
this.open = modifiers.contains(Modifier.OPEN);
this.automatic = modifiers.contains(Modifier.AUTOMATIC);
@ -1242,9 +1275,6 @@ public class ModuleDescriptor
this.packages = emptyOrUnmodifiableSet(packages);
this.mainClass = mainClass;
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
}
/**
@ -1261,13 +1291,11 @@ public class ModuleDescriptor
Set<Provides> provides,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
int hashCode,
boolean unused) {
this.name = name;
this.version = version;
this.rawVersionString = null;
this.modifiers = modifiers;
this.open = modifiers.contains(Modifier.OPEN);
this.automatic = modifiers.contains(Modifier.AUTOMATIC);
@ -1278,9 +1306,6 @@ public class ModuleDescriptor
this.provides = provides;
this.packages = packages;
this.mainClass = mainClass;
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
this.hash = hashCode;
}
@ -1394,18 +1419,37 @@ public class ModuleDescriptor
/**
* <p> Returns the module version. </p>
*
* @return This module's version
* @return This module's version, or an empty {@code Optional} if the
* module does not have a version or the version is
* {@linkplain Version#parse(String) unparseable}
*/
public Optional<Version> version() {
return Optional.ofNullable(version);
}
/**
* <p> Returns the string with the possibly-unparseable version of the
* module </p>
*
* @return The string containing the version of the module or an empty
* {@code Optional} if the module does not have a version
*
* @see #version()
*/
public Optional<String> rawVersion() {
if (version != null) {
return Optional.of(version.toString());
} else {
return Optional.ofNullable(rawVersionString);
}
}
/**
* <p> Returns a string containing the module name and, if present, its
* version. </p>
*
* @return A string containing the module name and, if present, its
* version.
* version
*/
public String toNameAndVersion() {
if (version != null) {
@ -1424,42 +1468,13 @@ public class ModuleDescriptor
return Optional.ofNullable(mainClass);
}
/**
* Returns the operating system name if the module is operating system
* specific.
*
* @return The operating system name or an empty {@code Optional}
* if the module is not operating system specific
*/
public Optional<String> osName() {
return Optional.ofNullable(osName);
}
/**
* Returns the operating system architecture if the module is operating
* system architecture specific.
*
* @return The operating system architecture or an empty {@code Optional}
* if the module is not operating system architecture specific
*/
public Optional<String> osArch() {
return Optional.ofNullable(osArch);
}
/**
* Returns the operating system version if the module is operating
* system version specific.
*
* @return The operating system version or an empty {@code Optional}
* if the module is not operating system version specific
*/
public Optional<String> osVersion() {
return Optional.ofNullable(osVersion);
}
/**
* Returns the set of packages in the module.
*
* <p> The set of packages includes all exported and open packages, as well
* as the packages of any service providers, and the package for the main
* class. </p>
*
* @return A possibly-empty unmodifiable set of the packages in the module
*/
public Set<String> packages() {
@ -1518,9 +1533,7 @@ public class ModuleDescriptor
final Set<String> uses = new HashSet<>();
final Map<String, Provides> provides = new HashMap<>();
Version version;
String osName;
String osArch;
String osVersion;
String rawVersionString;
String mainClass;
/**
@ -1604,24 +1617,21 @@ public class ModuleDescriptor
Objects.requireNonNull(compiledVersion);
if (strict)
mn = requireModuleName(mn);
return requires(new Requires(ms, mn, compiledVersion));
return requires(new Requires(ms, mn, compiledVersion, null));
}
/* package */Builder requires(Set<Requires.Modifier> ms,
String mn,
String compiledVersion) {
Version v = null;
String rawCompiledVersion) {
Requires r;
try {
v = Version.parse(compiledVersion);
Version v = Version.parse(rawCompiledVersion);
r = new Requires(ms, mn, v, null);
} catch (IllegalArgumentException e) {
// for now, drop un-parsable version when non-strict
if (strict) throw e;
r = new Requires(ms, mn, null, rawCompiledVersion);
}
if (v == null) {
return requires(ms, mn);
} else {
return requires(ms, mn, v);
}
return requires(r);
}
/**
@ -1646,7 +1656,7 @@ public class ModuleDescriptor
public Builder requires(Set<Requires.Modifier> ms, String mn) {
if (strict)
mn = requireModuleName(mn);
return requires(new Requires(ms, mn, null));
return requires(new Requires(ms, mn, null, null));
}
/**
@ -1952,7 +1962,7 @@ public class ModuleDescriptor
* a class in a named package
* @throws IllegalStateException
* If a dependency on the service type has already been declared
* or this is a builder for an an automatic module
* or this is a builder for an automatic module
*/
public Builder uses(String service) {
if (automatic)
@ -2068,6 +2078,7 @@ public class ModuleDescriptor
*/
public Builder version(Version v) {
version = requireNonNull(v);
rawVersionString = null;
return this;
}
@ -2086,18 +2097,15 @@ public class ModuleDescriptor
* @see Version#parse(String)
*/
public Builder version(String vs) {
Version v;
if (strict) {
v = Version.parse(vs);
} else {
try {
v = Version.parse(vs);
} catch (IllegalArgumentException ignore) {
// for now, ignore when non-strict
return this;
}
try {
version = Version.parse(vs);
rawVersionString = null;
} catch (IllegalArgumentException e) {
if (strict) throw e;
version = null;
rawVersionString = vs;
}
return version(v);
return this;
}
/**
@ -2131,60 +2139,6 @@ public class ModuleDescriptor
return this;
}
/**
* Sets the operating system name.
*
* @param name
* The operating system name
*
* @return This builder
*
* @throws IllegalArgumentException
* If {@code name} is {@code null} or the empty String
*/
public Builder osName(String name) {
if (name == null || name.isEmpty())
throw new IllegalArgumentException("OS name is null or empty");
osName = name;
return this;
}
/**
* Sets the operating system architecture.
*
* @param arch
* The operating system architecture
*
* @return This builder
*
* @throws IllegalArgumentException
* If {@code name} is {@code null} or the empty String
*/
public Builder osArch(String arch) {
if (arch == null || arch.isEmpty())
throw new IllegalArgumentException("OS arch is null or empty");
osArch = arch;
return this;
}
/**
* Sets the operating system version.
*
* @param version
* The operating system version
*
* @return This builder
*
* @throws IllegalArgumentException
* If {@code name} is {@code null} or the empty String
*/
public Builder osVersion(String version) {
if (version == null || version.isEmpty())
throw new IllegalArgumentException("OS version is null or empty");
osVersion = version;
return this;
}
/**
* Builds and returns a {@code ModuleDescriptor} from its components.
*
@ -2208,6 +2162,7 @@ public class ModuleDescriptor
&& !this.requires.containsKey("java.base")) {
requires.add(new Requires(Set.of(Requires.Modifier.MANDATED),
"java.base",
null,
null));
}
@ -2215,6 +2170,7 @@ public class ModuleDescriptor
return new ModuleDescriptor(name,
version,
rawVersionString,
modifiers,
requires,
exports,
@ -2222,10 +2178,7 @@ public class ModuleDescriptor
uses,
provides,
packages,
mainClass,
osName,
osArch,
osVersion);
mainClass);
}
}
@ -2237,9 +2190,11 @@ public class ModuleDescriptor
* module names lexicographically. Where the module names are equal then the
* module versions are compared. When comparing the module versions then a
* module descriptor with a version is considered to succeed a module
* descriptor that does not have a version. Where the module names are equal
* and the versions are equal (or not present in both), then the set of
* modifiers are compared. Sets of modifiers are compared by comparing
* descriptor that does not have a version. If both versions are {@linkplain
* Version#parse(String) unparseable} then the {@linkplain #rawVersion()
* raw version strings} are compared lexicographically. Where the module names
* are equal and the versions are equal (or not present in both), then the
* set of modifiers are compared. Sets of modifiers are compared by comparing
* a <em>binary value</em> computed for each set. If a modifier is present
* in the set then the bit at the position of its ordinal is {@code 1}
* in the binary value, otherwise {@code 0}. If the two set of modifiers
@ -2263,6 +2218,9 @@ public class ModuleDescriptor
c = compare(this.version, that.version);
if (c != 0) return c;
c = compare(this.rawVersionString, that.rawVersionString);
if (c != 0) return c;
long v1 = modsValue(this.modifiers());
long v2 = modsValue(that.modifiers());
c = Long.compare(v1, v2);
@ -2289,15 +2247,6 @@ public class ModuleDescriptor
c = compare(this.mainClass, that.mainClass);
if (c != 0) return c;
c = compare(this.osName, that.osName);
if (c != 0) return c;
c = compare(this.osArch, that.osArch);
if (c != 0) return c;
c = compare(this.osVersion, that.osVersion);
if (c != 0) return c;
return 0;
}
@ -2333,10 +2282,8 @@ public class ModuleDescriptor
&& uses.equals(that.uses)
&& provides.equals(that.provides)
&& Objects.equals(version, that.version)
&& Objects.equals(mainClass, that.mainClass)
&& Objects.equals(osName, that.osName)
&& Objects.equals(osArch, that.osArch)
&& Objects.equals(osVersion, that.osVersion));
&& Objects.equals(rawVersionString, that.rawVersionString)
&& Objects.equals(mainClass, that.mainClass));
}
/**
@ -2361,10 +2308,8 @@ public class ModuleDescriptor
hc = hc * 43 + uses.hashCode();
hc = hc * 43 + provides.hashCode();
hc = hc * 43 + Objects.hashCode(version);
hc = hc * 43 + Objects.hashCode(rawVersionString);
hc = hc * 43 + Objects.hashCode(mainClass);
hc = hc * 43 + Objects.hashCode(osName);
hc = hc * 43 + Objects.hashCode(osArch);
hc = hc * 43 + Objects.hashCode(osVersion);
if (hc == 0)
hc = -1;
hash = hc;
@ -2713,8 +2658,8 @@ public class ModuleDescriptor
public void requires(ModuleDescriptor.Builder builder,
Set<Requires.Modifier> ms,
String mn,
String compiledVersion) {
builder.requires(ms, mn, compiledVersion);
String rawCompiledVersion) {
builder.requires(ms, mn, rawCompiledVersion);
}
@Override
@ -2762,9 +2707,6 @@ public class ModuleDescriptor
Set<Provides> provides,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
int hashCode) {
return new ModuleDescriptor(name,
version,
@ -2776,9 +2718,6 @@ public class ModuleDescriptor
provides,
packages,
mainClass,
osName,
osArch,
osVersion,
hashCode,
false);
}

View File

@ -25,8 +25,6 @@
package java.lang.module;
import java.io.File;
import java.io.FilePermission;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -43,9 +41,9 @@ import java.util.Optional;
import java.util.Set;
import jdk.internal.module.ModuleBootstrap;
import jdk.internal.module.ModulePatcher;
import jdk.internal.module.ModulePath;
import jdk.internal.module.SystemModuleFinder;
import sun.security.action.GetPropertyAction;
/**
* A finder of modules. A {@code ModuleFinder} is used to find modules during
@ -146,9 +144,9 @@ public interface ModuleFinder {
*
* <p> If there is a security manager set then its {@link
* SecurityManager#checkPermission(Permission) checkPermission} method is
* invoked to check that the caller has been granted {@link FilePermission}
* to recursively read the directory that is the value of the system
* property {@code java.home}. </p>
* invoked to check that the caller has been granted
* {@link RuntimePermission RuntimePermission("accessSystemModules")}
* to access the system modules. </p>
*
* @return A {@code ModuleFinder} that locates the system modules
*
@ -156,32 +154,55 @@ public interface ModuleFinder {
* If denied by the security manager
*/
static ModuleFinder ofSystem() {
String home;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
PrivilegedAction<String> pa = new GetPropertyAction("java.home");
home = AccessController.doPrivileged(pa);
Permission p = new FilePermission(home + File.separator + "-", "read");
sm.checkPermission(p);
sm.checkPermission(new RuntimePermission("accessSystemModules"));
PrivilegedAction<ModuleFinder> pa = ModuleFinder::privilegedOfSystem;
return AccessController.doPrivileged(pa);
} else {
home = System.getProperty("java.home");
return privilegedOfSystem();
}
}
/**
* Returns a module finder that locates the system modules. This method
* assumes it has permissions to access the runtime image.
*/
private static ModuleFinder privilegedOfSystem() {
String home = System.getProperty("java.home");
Path modules = Paths.get(home, "lib", "modules");
if (Files.isRegularFile(modules)) {
return SystemModuleFinder.getInstance();
} else {
Path mlib = Paths.get(home, "modules");
if (Files.isDirectory(mlib)) {
// exploded build may be patched
return ModulePath.of(ModuleBootstrap.patcher(), mlib);
Path dir = Paths.get(home, "modules");
if (Files.isDirectory(dir)) {
return privilegedOf(ModuleBootstrap.patcher(), dir);
} else {
throw new InternalError("Unable to detect the run-time image");
}
}
}
/**
* Returns a module finder that locates the system modules in an exploded
* image. The image may be patched.
*/
private static ModuleFinder privilegedOf(ModulePatcher patcher, Path dir) {
ModuleFinder finder = ModulePath.of(patcher, dir);
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
PrivilegedAction<Optional<ModuleReference>> pa = () -> finder.find(name);
return AccessController.doPrivileged(pa);
}
@Override
public Set<ModuleReference> findAll() {
PrivilegedAction<Set<ModuleReference>> pa = finder::findAll;
return AccessController.doPrivileged(pa);
}
};
}
/**
* Returns a module finder that locates modules on the file system by
* searching a sequence of directories and/or packaged modules.
@ -201,7 +222,7 @@ public interface ModuleFinder {
*
* <p> If an element is a path to a directory of modules then each entry in
* the directory is a packaged module or the top-level directory of an
* exploded module. It it an error if a directory contains more than one
* exploded module. It is an error if a directory contains more than one
* module with the same name. If an element is a path to a directory, and
* that directory contains a file named {@code module-info.class}, then the
* directory is treated as an exploded module rather than a directory of

View File

@ -48,7 +48,11 @@ import java.util.stream.Stream;
* <p> A resource in a module is identified by an abstract name that is a
* '{@code /}'-separated path string. For example, module {@code java.base} may
* have a resource "{@code java/lang/Object.class}" that, by convention, is the
* class file for {@code java.lang.Object}. </p>
* class file for {@code java.lang.Object}. A module reader may treat
* directories in the module content as resources (whether it does or not is
* module reader specific). Where the module content contains a directory
* that can be located as a resource then its name ends with a slash ('/'). The
* directory can also be located with a name that drops the trailing slash. </p>
*
* <p> A {@code ModuleReader} is {@linkplain ModuleReference#open open} upon
* creation and is closed by invoking the {@link #close close} method. Failure
@ -80,6 +84,9 @@ public interface ModuleReader extends Closeable {
/**
* Finds a resource, returning a URI to the resource in the module.
*
* <p> If the module reader can determine that the name locates a directory
* then the resulting URI will end with a slash ('/'). </p>
*
* @param name
* The name of the resource to open for reading
*
@ -140,7 +147,7 @@ public interface ModuleReader extends Closeable {
*
* @apiNote This method is intended for high-performance class loading. It
* is not capable (or intended) to read arbitrary large resources that
* could potentially be 2GB or larger. The rational for using this method
* could potentially be 2GB or larger. The rationale for using this method
* in conjunction with the {@code release} method is to allow module reader
* implementations manage buffers in an efficient manner.
*
@ -195,7 +202,9 @@ public interface ModuleReader extends Closeable {
/**
* Lists the contents of the module, returning a stream of elements that
* are the names of all resources in the module.
* are the names of all resources in the module. Whether the stream of
* elements includes names corresponding to directories in the module is
* module reader specific.
*
* <p> In lazy implementations then an {@code IOException} may be thrown
* when using the stream to list the module contents. If this occurs then

View File

@ -47,6 +47,7 @@ import java.util.stream.Collectors;
import jdk.internal.module.ModuleHashes;
import jdk.internal.module.ModuleReferenceImpl;
import jdk.internal.module.ModuleTarget;
/**
* The resolver used by {@link Configuration#resolve} and {@link
@ -69,11 +70,9 @@ final class Resolver {
// module constraints on target platform
private String osName;
private String osArch;
private String osVersion;
String osName() { return osName; }
String osArch() { return osArch; }
String osVersion() { return osVersion; }
/**
* @throws IllegalArgumentException if there are more than one parent and
@ -110,16 +109,6 @@ final class Resolver {
}
}
}
value = parent.osVersion();
if (value != null) {
if (osVersion == null) {
osVersion = value;
} else {
if (!value.equals(osVersion)) {
failParentConflict("OS version", osVersion, value);
}
}
}
}
}
@ -318,13 +307,15 @@ final class Resolver {
* the target platform with the constraints of other modules.
*/
private void addFoundModule(ModuleReference mref) {
ModuleDescriptor descriptor = mref.descriptor();
nameToReference.put(descriptor.name(), mref);
String mn = mref.descriptor().name();
if (descriptor.osName().isPresent()
|| descriptor.osArch().isPresent()
|| descriptor.osVersion().isPresent())
checkTargetConstraints(descriptor);
if (mref instanceof ModuleReferenceImpl) {
ModuleTarget target = ((ModuleReferenceImpl)mref).moduleTarget();
if (target != null)
checkTargetConstraints(mn, target);
}
nameToReference.put(mn, mref);
}
/**
@ -332,58 +323,44 @@ final class Resolver {
* conflict with the constraints of other modules resolved so far or
* modules in parent configurations.
*/
private void checkTargetConstraints(ModuleDescriptor descriptor) {
String value = descriptor.osName().orElse(null);
private void checkTargetConstraints(String mn, ModuleTarget target) {
String value = target.osName();
if (value != null) {
if (osName == null) {
osName = value;
} else {
if (!value.equals(osName)) {
failTargetConstraint(descriptor);
failTargetConstraint(mn, target);
}
}
}
value = descriptor.osArch().orElse(null);
value = target.osArch();
if (value != null) {
if (osArch == null) {
osArch = value;
} else {
if (!value.equals(osArch)) {
failTargetConstraint(descriptor);
}
}
}
value = descriptor.osVersion().orElse(null);
if (value != null) {
if (osVersion == null) {
osVersion = value;
} else {
if (!value.equals(osVersion)) {
failTargetConstraint(descriptor);
failTargetConstraint(mn, target);
}
}
}
}
private void failTargetConstraint(ModuleDescriptor md) {
String s1 = targetAsString(osName, osArch, osVersion);
String s2 = targetAsString(md);
findFail("Module %s has constraints on target platform that conflict" +
" with other modules: %s, %s", md.name(), s1, s2);
private void failTargetConstraint(String mn, ModuleTarget target) {
String s1 = targetAsString(osName, osArch);
String s2 = targetAsString(target.osName(), target.osArch());
findFail("Module %s has constraints on target platform (%s) that"
+ " conflict with other modules: %s", mn, s1, s2);
}
private String targetAsString(ModuleDescriptor descriptor) {
String osName = descriptor.osName().orElse(null);
String osArch = descriptor.osArch().orElse(null);
String osVersion = descriptor.osVersion().orElse(null);
return targetAsString(osName, osArch, osVersion);
private String targetAsString(ModuleTarget target) {
return targetAsString(target.osName(), target.osArch());
}
private String targetAsString(String osName, String osArch, String osVersion) {
private String targetAsString(String osName, String osArch) {
return new StringJoiner("-")
.add(Objects.toString(osName, "*"))
.add(Objects.toString(osArch, "*"))
.add(Objects.toString(osVersion, "*"))
.toString();
}
@ -712,16 +689,30 @@ final class Resolver {
/**
* Checks the readability graph to ensure that no two modules export the
* same package to a module. This includes the case where module M has
* a local package P and M reads another module that exports P to M.
* Also checks the uses/provides of module M to ensure that it reads a
* module that exports the package of the service type to M.
* Checks the readability graph to ensure that
* <ol>
* <li><p> A module does not read two or more modules with the same name.
* This includes the case where a module reads another another with the
* same name as itself. </p></li>
* <li><p> Two or more modules in the configuration don't export the same
* package to a module that reads both. This includes the case where a
* module {@code M} containing package {@code p} reads another module
* that exports {@code p} to {@code M}. </p></li>
* <li><p> A module {@code M} doesn't declare that it "{@code uses p.S}"
* or "{@code provides p.S with ...}" but package {@code p} is neither
* in module {@code M} nor exported to {@code M} by any module that
* {@code M} reads. </p></li>
* </ol>
*/
private void checkExportSuppliers(Map<ResolvedModule, Set<ResolvedModule>> graph) {
for (Map.Entry<ResolvedModule, Set<ResolvedModule>> e : graph.entrySet()) {
ModuleDescriptor descriptor1 = e.getKey().descriptor();
String name1 = descriptor1.name();
// the names of the modules that are read (including self)
Set<String> names = new HashSet<>();
names.add(name1);
// the map of packages that are local or exported to descriptor1
Map<String, ModuleDescriptor> packageToExporter = new HashMap<>();
@ -737,9 +728,20 @@ final class Resolver {
for (ResolvedModule endpoint : reads) {
ModuleDescriptor descriptor2 = endpoint.descriptor();
String name2 = descriptor2.name();
if (descriptor2 != descriptor1 && !names.add(name2)) {
if (name2.equals(name1)) {
resolveFail("Module %s reads another module named %s",
name1, name1);
} else{
resolveFail("Module %s reads more than one module named %s",
name1, name2);
}
}
if (descriptor2.isAutomatic()) {
// automatic modules read self and export all packages
if (descriptor2 != descriptor1){
if (descriptor2 != descriptor1) {
for (String source : descriptor2.packages()) {
ModuleDescriptor supplier
= packageToExporter.putIfAbsent(source, descriptor2);

View File

@ -28,9 +28,12 @@ package java.lang.reflect;
import java.lang.annotation.Annotation;
import java.security.AccessController;
import jdk.internal.misc.VM;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import jdk.internal.reflect.ReflectionFactory;
import sun.security.action.GetPropertyAction;
/**
* The {@code AccessibleObject} class is the base class for {@code Field},
@ -288,27 +291,20 @@ public class AccessibleObject implements AnnotatedElement {
if (callerModule == Object.class.getModule()) return true;
if (!declaringModule.isNamed()) return true;
// package is open to caller
String pn = packageName(declaringClass);
if (declaringModule.isOpen(pn, callerModule)) {
dumpStackIfOpenedReflectively(declaringModule, pn, callerModule);
return true;
}
// package is exported to caller
boolean isExported = declaringModule.isExported(pn, callerModule);
boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
String pn = declaringClass.getPackageName();
int modifiers;
if (this instanceof Executable) {
modifiers = ((Executable) this).getModifiers();
} else {
modifiers = ((Field) this).getModifiers();
}
if (isExported && isClassPublic) {
// class is public and package is exported to caller
boolean isClassPublic = Modifier.isPublic(declaringClass.getModifiers());
if (isClassPublic && declaringModule.isExported(pn, callerModule)) {
// member is public
if (Modifier.isPublic(modifiers)) {
dumpStackIfExportedReflectively(declaringModule, pn, callerModule);
logIfExportedByBackdoor(caller, declaringClass);
return true;
}
@ -316,11 +312,17 @@ public class AccessibleObject implements AnnotatedElement {
if (Modifier.isProtected(modifiers)
&& Modifier.isStatic(modifiers)
&& isSubclassOf(caller, declaringClass)) {
dumpStackIfExportedReflectively(declaringModule, pn, callerModule);
logIfExportedByBackdoor(caller, declaringClass);
return true;
}
}
// package is open to caller
if (declaringModule.isOpen(pn, callerModule)) {
logIfOpenedByBackdoor(caller, declaringClass);
return true;
}
if (throwExceptionIfDenied) {
// not accessible
String msg = "Unable to make ";
@ -333,7 +335,7 @@ public class AccessibleObject implements AnnotatedElement {
msg += "opens";
msg += " " + pn + "\" to " + callerModule;
InaccessibleObjectException e = new InaccessibleObjectException(msg);
if (Reflection.printStackTraceWhenAccessFails()) {
if (printStackTraceWhenAccessFails()) {
e.printStackTrace(System.err);
}
throw e;
@ -351,48 +353,35 @@ public class AccessibleObject implements AnnotatedElement {
return false;
}
private void dumpStackIfOpenedReflectively(Module module,
String pn,
Module other) {
dumpStackIfExposedReflectively(module, pn, other, true);
private void logIfOpenedByBackdoor(Class<?> caller, Class<?> declaringClass) {
Module callerModule = caller.getModule();
Module targetModule = declaringClass.getModule();
// callerModule is null during early startup
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
logger.logIfOpenedByBackdoor(caller, declaringClass, this::toShortString);
}
}
}
private void dumpStackIfExportedReflectively(Module module,
String pn,
Module other) {
dumpStackIfExposedReflectively(module, pn, other, false);
}
private void dumpStackIfExposedReflectively(Module module,
String pn,
Module other,
boolean open)
{
if (Reflection.printStackTraceWhenAccessSucceeds()
&& !module.isStaticallyExportedOrOpen(pn, other, open))
{
String msg = other + " allowed to invoke setAccessible on ";
if (this instanceof Field)
msg += "field ";
msg += this;
new Exception(msg) {
private static final long serialVersionUID = 42L;
public String toString() {
return "WARNING: " + getMessage();
}
}.printStackTrace(System.err);
private void logIfExportedByBackdoor(Class<?> caller, Class<?> declaringClass) {
Module callerModule = caller.getModule();
Module targetModule = declaringClass.getModule();
// callerModule is null during early startup
if (callerModule != null && !callerModule.isNamed() && targetModule.isNamed()) {
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger != null) {
logger.logIfExportedByBackdoor(caller, declaringClass, this::toShortString);
}
}
}
/**
* Returns the package name of the given class.
* Returns a short descriptive string to describe this object in log messages.
*/
private static String packageName(Class<?> c) {
while (c.isArray()) {
c = c.getComponentType();
}
String pn = c.getPackageName();
return (pn != null) ? pn : "";
String toShortString() {
return toString();
}
/**
@ -409,6 +398,7 @@ public class AccessibleObject implements AnnotatedElement {
* it should use {@link #canAccess(Object)}.
*
* @revised 9
* @spec JPMS
*/
@Deprecated(since="9")
public boolean isAccessible() {
@ -483,10 +473,7 @@ public class AccessibleObject implements AnnotatedElement {
} else {
targetClass = Modifier.isStatic(modifiers) ? null : obj.getClass();
}
return Reflection.verifyMemberAccess(caller,
declaringClass,
targetClass,
modifiers);
return verifyAccess(caller, declaringClass, targetClass, modifiers);
}
/**
@ -527,7 +514,7 @@ public class AccessibleObject implements AnnotatedElement {
return AnnotatedElement.super.isAnnotationPresent(annotationClass);
}
/**
/**
* @throws NullPointerException {@inheritDoc}
* @since 1.8
*/
@ -597,9 +584,22 @@ public class AccessibleObject implements AnnotatedElement {
final void checkAccess(Class<?> caller, Class<?> memberClass,
Class<?> targetClass, int modifiers)
throws IllegalAccessException
{
if (!verifyAccess(caller, memberClass, targetClass, modifiers)) {
IllegalAccessException e = Reflection.newIllegalAccessException(
caller, memberClass, targetClass, modifiers);
if (printStackTraceWhenAccessFails()) {
e.printStackTrace(System.err);
}
throw e;
}
}
final boolean verifyAccess(Class<?> caller, Class<?> memberClass,
Class<?> targetClass, int modifiers)
{
if (caller == memberClass) { // quick check
return; // ACCESS IS OK
return true; // ACCESS IS OK
}
Object cache = securityCheckCache; // read volatile
if (targetClass != null // instance member or constructor
@ -610,26 +610,31 @@ public class AccessibleObject implements AnnotatedElement {
Class<?>[] cache2 = (Class<?>[]) cache;
if (cache2[1] == targetClass &&
cache2[0] == caller) {
return; // ACCESS IS OK
return true; // ACCESS IS OK
}
// (Test cache[1] first since range check for [1]
// subsumes range check for [0].)
}
} else if (cache == caller) {
// Non-protected case (or targetClass == memberClass or static member).
return; // ACCESS IS OK
return true; // ACCESS IS OK
}
// If no return, fall through to the slow path.
slowCheckMemberAccess(caller, memberClass, targetClass, modifiers);
return slowVerifyAccess(caller, memberClass, targetClass, modifiers);
}
// Keep all this slow stuff out of line:
void slowCheckMemberAccess(Class<?> caller, Class<?> memberClass,
Class<?> targetClass, int modifiers)
throws IllegalAccessException
private boolean slowVerifyAccess(Class<?> caller, Class<?> memberClass,
Class<?> targetClass, int modifiers)
{
Reflection.ensureMemberAccess(caller, memberClass, targetClass, modifiers);
if (!Reflection.verifyMemberAccess(caller, memberClass, targetClass, modifiers)) {
// access denied
return false;
}
// access okay
logIfExportedByBackdoor(caller, memberClass);
// Success: Update the cache.
Object cache = (targetClass != null
@ -643,5 +648,27 @@ public class AccessibleObject implements AnnotatedElement {
// guarantees that the initializing stores for the cache
// elements will occur before the volatile write.
securityCheckCache = cache; // write volatile
return true;
}
// true to print a stack trace when access fails
private static volatile boolean printStackWhenAccessFails;
// true if printStack* values are initialized
private static volatile boolean printStackPropertiesSet;
/**
* Returns true if a stack trace should be printed when access fails.
*/
private static boolean printStackTraceWhenAccessFails() {
if (!printStackPropertiesSet && VM.initLevel() >= 1) {
String s = GetPropertyAction.privilegedGetProperty(
"sun.reflect.debugModuleAccessChecks");
if (s != null) {
printStackWhenAccessFails = !s.equalsIgnoreCase("false");
}
printStackPropertiesSet = true;
}
return printStackWhenAccessFails;
}
}

View File

@ -38,6 +38,7 @@ import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.scope.ConstructorScope;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.util.StringJoiner;
/**
* {@code Constructor} provides information about, and access to, a single
@ -360,6 +361,20 @@ public final class Constructor<T> extends Executable {
sb.append(getDeclaringClass().getTypeName());
}
@Override
String toShortString() {
StringBuilder sb = new StringBuilder("constructor ");
sb.append(getDeclaringClass().getTypeName());
sb.append('(');
StringJoiner sj = new StringJoiner(",");
for (Class<?> parameterType : getParameterTypes()) {
sj.add(parameterType.getTypeName());
}
sb.append(sj);
sb.append(')');
return sb.toString();
}
/**
* Returns a string describing this {@code Constructor},
* including type parameters. The string is formatted as the

View File

@ -324,6 +324,11 @@ class Field extends AccessibleObject implements Member {
+ getName());
}
@Override
String toShortString() {
return "field " + getDeclaringClass().getTypeName() + "." + getName();
}
/**
* Returns a string describing this {@code Field}, including
* its generic type. The format is the access modifiers for the

View File

@ -66,9 +66,7 @@ import sun.security.util.SecurityConstants;
* ResolvedModule} in the configuration. For each resolved module that is
* {@link ResolvedModule#reads() read}, the {@code Module} {@link
* Module#canRead reads} the corresponding run-time {@code Module}, which may
* be in the same layer or a {@link #parents() parent} layer. The {@code Module}
* {@link Module#isExported(String) exports} and {@link Module#isOpen(String)
* opens} the packages described by its {@link ModuleDescriptor}. </p>
* be in the same layer or a {@link #parents() parent} layer. </p>
*
* <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
* {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
@ -91,6 +89,28 @@ import sun.security.util.SecurityConstants;
* built-in</a> into the Java virtual machine. The boot layer will often be
* the {@link #parents() parent} when creating additional layers. </p>
*
* <p> Each {@code Module} in a layer is created so that it {@link
* Module#isExported(String) exports} and {@link Module#isOpen(String) opens}
* the packages described by its {@link ModuleDescriptor}. Qualified exports
* (where a package is exported to a set of target modules rather than all
* modules) are reified when creating the layer as follows: </p>
* <ul>
* <li> If module {@code X} exports a package to {@code Y}, and if the
* runtime {@code Module} {@code X} reads {@code Module} {@code Y}, then
* the package is exported to {@code Module} {@code Y} (which may be in
* the same layer as {@code X} or a parent layer). </li>
*
* <li> If module {@code X} exports a package to {@code Y}, and if the
* runtime {@code Module} {@code X} does not read {@code Y} then target
* {@code Y} is located as if by invoking {@link #findModule(String)
* findModule} to find the module in the layer or its parent layers. If
* {@code Y} is found then the package is exported to the instance of
* {@code Y} that was found. If {@code Y} is not found then the qualified
* export is ignored. </li>
* </ul>
*
* <p> Qualified opens are handled in same way as qualified exports. </p>
*
* <p> As when creating a {@code Configuration},
* {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
* treatment when creating a layer. An automatic module is created in the
@ -193,7 +213,7 @@ public final class Layer {
}
private void ensureInLayer(Module source) {
if (!layer.modules().contains(source))
if (source.getLayer() != layer)
throw new IllegalArgumentException(source + " not in layer");
}
@ -220,9 +240,8 @@ public final class Layer {
* @see Module#addReads
*/
public Controller addReads(Module source, Module target) {
Objects.requireNonNull(source);
Objects.requireNonNull(target);
ensureInLayer(source);
Objects.requireNonNull(target);
Modules.addReads(source, target);
return this;
}
@ -248,9 +267,9 @@ public final class Layer {
* @see Module#addOpens
*/
public Controller addOpens(Module source, String pn, Module target) {
Objects.requireNonNull(source);
Objects.requireNonNull(target);
ensureInLayer(source);
Objects.requireNonNull(pn);
Objects.requireNonNull(target);
Modules.addOpens(source, pn, target);
return this;
}
@ -408,8 +427,8 @@ public final class Layer {
* </ul>
*
* <p> In addition, a layer cannot be created if the configuration contains
* a module named "{@code java.base}" or a module with a package name
* starting with "{@code java.}". </p>
* a module named "{@code java.base}", or a module contains a package named
* "{@code java}" or a package with a name starting with "{@code java.}". </p>
*
* <p> If there is a security manager then the class loader created by
* this method will load classes and resources with privileges that are
@ -418,7 +437,7 @@ public final class Layer {
* @param cf
* The configuration for the layer
* @param parentLayers
* The list parent layers in search order
* The list of parent layers in search order
* @param parentLoader
* The parent class loader for the class loader created by this
* method; may be {@code null} for the bootstrap class loader
@ -485,7 +504,7 @@ public final class Layer {
* @param cf
* The configuration for the layer
* @param parentLayers
* The list parent layers in search order
* The list of parent layers in search order
* @param parentLoader
* The parent class loader for each of the class loaders created by
* this method; may be {@code null} for the bootstrap class loader
@ -497,8 +516,10 @@ public final class Layer {
* the parent layers, including order
* @throws LayerInstantiationException
* If the layer cannot be created because the configuration contains
* a module named "{@code java.base}" or a module with a package
* name starting with "{@code java.}"
* a module named "{@code java.base}" or a module contains a package
* named "{@code java}" or a package with a name starting with
* "{@code java.}"
*
* @throws SecurityException
* If {@code RuntimePermission("createClassLoader")} or
* {@code RuntimePermission("getClassLoader")} is denied by
@ -558,10 +579,11 @@ public final class Layer {
*
* <p> In addition, a layer cannot be created if the configuration contains
* a module named "{@code java.base}", a configuration contains a module
* with a package name starting with "{@code java.}" is mapped to a class
* loader other than the {@link ClassLoader#getPlatformClassLoader()
* platform class loader}, or the function to map a module name to a class
* loader returns {@code null}. </p>
* with a package named "{@code java}" or a package name starting with
* "{@code java.}" and the module is mapped to a class loader other than
* the {@link ClassLoader#getPlatformClassLoader() platform class loader},
* or the function to map a module name to a class loader returns
* {@code null}. </p>
*
* <p> If the function to map a module name to class loader throws an error
* or runtime exception then it is propagated to the caller of this method.
@ -575,7 +597,7 @@ public final class Layer {
* @param cf
* The configuration for the layer
* @param parentLayers
* The list parent layers in search order
* The list of parent layers in search order
* @param clf
* The function to map a module name to a class loader
*
@ -754,10 +776,16 @@ public final class Layer {
* @return A possibly-empty unmodifiable set of the modules in this layer
*/
public Set<Module> modules() {
return Collections.unmodifiableSet(
nameToModule.values().stream().collect(Collectors.toSet()));
Set<Module> modules = this.modules;
if (modules == null) {
this.modules = modules =
Collections.unmodifiableSet(new HashSet<>(nameToModule.values()));
}
return modules;
}
private volatile Set<Module> modules;
/**
* Returns the module with the given name in this layer, or if not in this
@ -776,6 +804,8 @@ public final class Layer {
*/
public Optional<Module> findModule(String name) {
Objects.requireNonNull(name);
if (this == EMPTY_LAYER)
return Optional.empty();
Module m = nameToModule.get(name);
if (m != null)
return Optional.of(m);

View File

@ -42,6 +42,7 @@ import sun.reflect.annotation.AnnotationParser;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationFormatError;
import java.nio.ByteBuffer;
import java.util.StringJoiner;
/**
* A {@code Method} provides information about, and access to, a single method
@ -416,6 +417,21 @@ public final class Method extends Executable {
sb.append(getName());
}
@Override
String toShortString() {
StringBuilder sb = new StringBuilder("method ");
sb.append(getDeclaringClass().getTypeName()).append('.');
sb.append(getName());
sb.append('(');
StringJoiner sj = new StringJoiner(",");
for (Class<?> parameterType : getParameterTypes()) {
sj.add(parameterType.getTypeName());
}
sb.append(sj);
sb.append(')');
return sb.toString();
}
/**
* Returns a string describing this {@code Method}, including
* type parameters. The string is formatted as the method access

View File

@ -39,8 +39,10 @@ import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@ -51,11 +53,11 @@ import java.util.stream.Stream;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.JavaLangReflectModuleAccess;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.ServicesCatalog;
import jdk.internal.module.Resources;
import jdk.internal.org.objectweb.asm.AnnotationVisitor;
import jdk.internal.org.objectweb.asm.Attribute;
import jdk.internal.org.objectweb.asm.ClassReader;
@ -369,28 +371,19 @@ public final class Module implements AnnotatedElement {
* If {@code syncVM} is {@code true} then the VM is notified.
*/
private void implAddReads(Module other, boolean syncVM) {
Objects.requireNonNull(other);
// nothing to do
if (other == this || !this.isNamed())
return;
// check if we already read this module
Set<Module> reads = this.reads;
if (reads != null && reads.contains(other))
return;
// update VM first, just in case it fails
if (syncVM) {
if (other == ALL_UNNAMED_MODULE) {
addReads0(this, null);
} else {
addReads0(this, other);
if (!canRead(other)) {
// update VM first, just in case it fails
if (syncVM) {
if (other == ALL_UNNAMED_MODULE) {
addReads0(this, null);
} else {
addReads0(this, other);
}
}
}
// add reflective read
reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
// add reflective read
reflectivelyReads.putIfAbsent(this, other, Boolean.TRUE);
}
}
@ -553,7 +546,7 @@ public final class Module implements AnnotatedElement {
* Returns {@code true} if this module exports or opens a package to
* the given module via its module declaration.
*/
boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
// package is open to everyone or <other>
Map<String, Set<Module>> openPackages = this.openPackages;
if (openPackages != null) {
@ -909,9 +902,7 @@ public final class Module implements AnnotatedElement {
* Returns an array of the package names of the packages in this module.
*
* <p> For named modules, the returned array contains an element for each
* package in the module. It may contain elements corresponding to packages
* added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
* for example, after it was loaded.
* package in the module. </p>
*
* <p> For unnamed modules, this method is the equivalent to invoking the
* {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
@ -949,15 +940,6 @@ public final class Module implements AnnotatedElement {
}
}
/**
* Add a package to this module.
*
* @apiNote This method is for Proxy use.
*/
void addPackage(String pn) {
implAddPackage(pn, true);
}
/**
* Add a package to this module without notifying the VM.
*
@ -1080,20 +1062,28 @@ public final class Module implements AnnotatedElement {
// reads
Set<Module> reads = new HashSet<>();
// name -> source Module when in parent layer
Map<String, Module> nameToSource = Collections.emptyMap();
for (ResolvedModule other : resolvedModule.reads()) {
Module m2 = null;
if (other.configuration() == cf) {
String dn = other.reference().descriptor().name();
m2 = nameToModule.get(dn);
// this configuration
m2 = nameToModule.get(other.name());
assert m2 != null;
} else {
// parent layer
for (Layer parent: layer.parents()) {
m2 = findModule(parent, other);
if (m2 != null)
break;
}
assert m2 != null;
if (nameToSource.isEmpty())
nameToSource = new HashMap<>();
nameToSource.put(other.name(), m2);
}
assert m2 != null;
reads.add(m2);
// update VM view
@ -1107,7 +1097,7 @@ public final class Module implements AnnotatedElement {
}
// exports and opens
initExportsAndOpens(descriptor, nameToModule, m);
initExportsAndOpens(m, nameToSource, nameToModule, layer.parents());
}
// register the modules in the boot layer
@ -1159,15 +1149,17 @@ public final class Module implements AnnotatedElement {
.orElse(null);
}
/**
* Initialize the maps of exported and open packages for module m.
*/
private static void initExportsAndOpens(ModuleDescriptor descriptor,
private static void initExportsAndOpens(Module m,
Map<String, Module> nameToSource,
Map<String, Module> nameToModule,
Module m)
{
List<Layer> parents) {
// The VM doesn't special case open or automatic modules so need to
// export all packages
ModuleDescriptor descriptor = m.getDescriptor();
if (descriptor.isOpen() || descriptor.isAutomatic()) {
assert descriptor.opens().isEmpty();
for (String source : descriptor.packages()) {
@ -1187,8 +1179,7 @@ public final class Module implements AnnotatedElement {
// qualified opens
Set<Module> targets = new HashSet<>();
for (String target : opens.targets()) {
// only open to modules that are in this configuration
Module m2 = nameToModule.get(target);
Module m2 = findModule(target, nameToSource, nameToModule, parents);
if (m2 != null) {
addExports0(m, source, m2);
targets.add(m2);
@ -1217,8 +1208,7 @@ public final class Module implements AnnotatedElement {
// qualified exports
Set<Module> targets = new HashSet<>();
for (String target : exports.targets()) {
// only export to modules that are in this configuration
Module m2 = nameToModule.get(target);
Module m2 = findModule(target, nameToSource, nameToModule, parents);
if (m2 != null) {
// skip qualified export if already open to m2
if (openToTargets == null || !openToTargets.contains(m2)) {
@ -1244,6 +1234,32 @@ public final class Module implements AnnotatedElement {
m.exportedPackages = exportedPackages;
}
/**
* Find the runtime Module with the given name. The module name is the
* name of a target module in a qualified exports or opens directive.
*
* @param target The target module to find
* @param nameToSource The modules in parent layers that are read
* @param nameToModule The modules in the layer under construction
* @param parents The parent layers
*/
private static Module findModule(String target,
Map<String, Module> nameToSource,
Map<String, Module> nameToModule,
List<Layer> parents) {
Module m = nameToSource.get(target);
if (m == null) {
m = nameToModule.get(target);
if (m == null) {
for (Layer parent : parents) {
m = parent.findModule(target).orElse(null);
if (m != null) break;
}
}
}
return m;
}
// -- annotations --
@ -1428,12 +1444,12 @@ public final class Module implements AnnotatedElement {
name = name.substring(1);
}
if (isNamed() && !ResourceHelper.isSimpleResource(name)) {
if (isNamed() && Resources.canEncapsulate(name)) {
Module caller = Reflection.getCallerClass().getModule();
if (caller != this && caller != Object.class.getModule()) {
// ignore packages added for proxies via addPackage
Set<String> packages = getDescriptor().packages();
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
if (packages.contains(pn) && !isOpen(pn, caller)) {
// resource is in package not open to caller
return null;
@ -1531,24 +1547,24 @@ public final class Module implements AnnotatedElement {
m.implAddReads(Module.ALL_UNNAMED_MODULE);
}
@Override
public void addExports(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
}
@Override
public void addExports(Module m, String pn, Module other) {
m.implAddExportsOrOpens(pn, other, false, true);
}
@Override
public void addOpens(Module m, String pn, Module other) {
m.implAddExportsOrOpens(pn, other, true, true);
public void addExportsToAllUnnamed(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
}
@Override
public void addExportsToAll(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true);
}
@Override
public void addOpensToAll(Module m, String pn) {
public void addOpens(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true);
}
@Override
public void addExportsToAllUnnamed(Module m, String pn) {
m.implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true);
public void addOpens(Module m, String pn, Module other) {
m.implAddExportsOrOpens(pn, other, true, true);
}
@Override
public void addOpensToAllUnnamed(Module m, String pn) {
@ -1559,10 +1575,6 @@ public final class Module implements AnnotatedElement {
m.implAddUses(service);
}
@Override
public void addPackage(Module m, String pn) {
m.implAddPackage(pn, true);
}
@Override
public ServicesCatalog getServicesCatalog(Layer layer) {
return layer.getServicesCatalog();
}
@ -1574,10 +1586,6 @@ public final class Module implements AnnotatedElement {
public Stream<Layer> layers(ClassLoader loader) {
return Layer.layers(loader);
}
@Override
public boolean isStaticallyExported(Module module, String pn, Module other) {
return module.isStaticallyExportedOrOpen(pn, other, false);
}
});
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, 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
@ -359,10 +359,11 @@ public class Proxy implements java.io.Serializable {
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
*
* @deprecated Proxy classes generated in a named module are encapsulated and not
* accessible to code outside its module.
* {@link Constructor#newInstance(Object...) Constructor.newInstance} will throw
* {@code IllegalAccessException} when it is called on an inaccessible proxy class.
* @deprecated Proxy classes generated in a named module are encapsulated
* and not accessible to code outside its module.
* {@link Constructor#newInstance(Object...) Constructor.newInstance}
* will throw {@code IllegalAccessException} when it is called on
* an inaccessible proxy class.
* Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
* to create a proxy instance instead.
*
@ -511,17 +512,19 @@ public class Proxy implements java.io.Serializable {
"Unnamed package cannot be added to " + m);
}
// add the package to the runtime module if not exists
if (m.isNamed()) {
m.addPackage(proxyPkg);
if (!m.getDescriptor().packages().contains(proxyPkg)) {
throw new InternalError(proxyPkg + " not exist in " + m.getName());
}
}
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num
: proxyPkg + "." + proxyClassNamePrefix + num;
String proxyName = proxyPkg.isEmpty()
? proxyClassNamePrefix + num
: proxyPkg + "." + proxyClassNamePrefix + num;
ClassLoader loader = getLoader(m);
trace(proxyName, m, loader, interfaces);
@ -581,9 +584,13 @@ public class Proxy implements java.io.Serializable {
c.getModule().getName(), c.getName(), access, ld);
}
static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) {
static void trace(String cn,
Module module,
ClassLoader loader,
List<Class<?>> interfaces) {
if (isDebug()) {
System.out.format("PROXY: %s/%s defined by %s%n", module.getName(), cn, loader);
System.err.format("PROXY: %s/%s defined by %s%n",
module.getName(), cn, loader);
}
if (isDebug("debug")) {
interfaces.stream()
@ -592,7 +599,7 @@ public class Proxy implements java.io.Serializable {
}
private static final String DEBUG =
GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", "");
GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", "");
private static boolean isDebug() {
return !DEBUG.isEmpty();
@ -603,15 +610,16 @@ public class Proxy implements java.io.Serializable {
// ProxyBuilder instance members start here....
private final ClassLoader loader;
private final List<Class<?>> interfaces;
private final Module module;
ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
if (!VM.isModuleSystemInited()) {
throw new InternalError("Proxy is not supported until module system is fully initialized");
throw new InternalError("Proxy is not supported until "
+ "module system is fully initialized");
}
if (interfaces.size() > 65535) {
throw new IllegalArgumentException("interface limit exceeded: " + interfaces.size());
throw new IllegalArgumentException("interface limit exceeded: "
+ interfaces.size());
}
Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
@ -619,7 +627,6 @@ public class Proxy implements java.io.Serializable {
// IAE if violates any restrictions specified in newProxyInstance
validateProxyInterfaces(loader, interfaces, refTypes);
this.loader = loader;
this.interfaces = interfaces;
this.module = mapToModule(loader, interfaces, refTypes);
assert getLoader(module) == loader;
@ -659,8 +666,8 @@ public class Proxy implements java.io.Serializable {
* Validate the given proxy interfaces and the given referenced types
* are visible to the defining loader.
*
* @throws IllegalArgumentException if it violates the restrictions specified
* in {@link Proxy#newProxyInstance}
* @throws IllegalArgumentException if it violates the restrictions
* specified in {@link Proxy#newProxyInstance}
*/
private static void validateProxyInterfaces(ClassLoader loader,
List<Class<?>> interfaces,
@ -731,9 +738,9 @@ public class Proxy implements java.io.Serializable {
* is in the same module of the package-private interface.
*
* If all proxy interfaces are public and at least one in a non-exported
* package, then the proxy class is in a dynamic module in a non-exported
* package. Reads edge and qualified exports are added for
* dynamic module to access.
* package, then the proxy class is in a dynamic module in a
* non-exported package. Reads edge and qualified exports are added
* for dynamic module to access.
*/
private static Module mapToModule(ClassLoader loader,
List<Class<?>> interfaces,
@ -752,11 +759,12 @@ public class Proxy implements java.io.Serializable {
}
}
// all proxy interfaces are public and exported, the proxy class is in unnamed module
// Such proxy class is accessible to any unnamed module and named module that
// can read unnamed module
// all proxy interfaces are public and exported, the proxy class
// is in unnamed module. Such proxy class is accessible to
// any unnamed module and named module that can read unnamed module
if (packagePrivateTypes.isEmpty() && modulePrivateTypes.isEmpty()) {
return loader != null ? loader.getUnnamedModule() : BootLoader.getUnnamedModule();
return loader != null ? loader.getUnnamedModule()
: BootLoader.getUnnamedModule();
}
if (packagePrivateTypes.size() > 0) {
@ -778,7 +786,8 @@ public class Proxy implements java.io.Serializable {
Module target = null;
for (Module m : packagePrivateTypes.values()) {
if (getLoader(m) != loader) {
// the specified loader is not the same class loader of the non-public interface
// the specified loader is not the same class loader
// of the non-public interface
throw new IllegalArgumentException(
"non-public interface is not defined by the given loader");
}
@ -799,8 +808,9 @@ public class Proxy implements java.io.Serializable {
return target;
}
// all proxy interfaces are public and at least one in a non-exported package
// map to dynamic proxy module and add reads edge and qualified exports, if necessary
// All proxy interfaces are public and at least one in a non-exported
// package. So maps to a dynamic proxy module and add reads edge
// and qualified exports, if necessary
Module target = getDynamicModule(loader);
// set up proxy class access to proxy interfaces and types
@ -856,8 +866,8 @@ public class Proxy implements java.io.Serializable {
private static final AtomicInteger counter = new AtomicInteger();
/*
* Define a dynamic module for the generated proxy classes in a non-exported package
* named com.sun.proxy.$MODULE.
* Define a dynamic module for the generated proxy classes in
* a non-exported package named com.sun.proxy.$MODULE.
*
* Each class loader will have one dynamic module.
*/

View File

@ -1007,6 +1007,7 @@ public final class ServiceLoader<S>
{
static final String PREFIX = "META-INF/services/";
Set<String> providerNames = new HashSet<>(); // to avoid duplicates
Enumeration<URL> configs;
Iterator<String> pending;
Class<?> nextClass;
@ -1016,7 +1017,7 @@ public final class ServiceLoader<S>
/**
* Parse a single line from the given configuration file, adding the
* name on the line to the names list.
* name on the line to set of names if not already seen.
*/
private int parseLine(URL u, BufferedReader r, int lc, Set<String> names)
throws IOException
@ -1041,7 +1042,9 @@ public final class ServiceLoader<S>
if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
fail(service, u, lc, "Illegal provider-class name: " + ln);
}
names.add(ln);
if (providerNames.add(ln)) {
names.add(ln);
}
}
return lc + 1;
}
@ -1072,7 +1075,7 @@ public final class ServiceLoader<S>
return true;
}
Class<?> clazz = null;
Class<?> clazz;
do {
if (configs == null) {
try {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -59,7 +59,7 @@ public class JmodFile implements AutoCloseable {
bis.read(magic);
if (magic[0] != JMOD_MAGIC_NUMBER[0] ||
magic[1] != JMOD_MAGIC_NUMBER[1]) {
throw new IOException("Invalid jmod file: " + file.toString());
throw new IOException("Invalid JMOD file: " + file.toString());
}
if (magic[2] > JMOD_MAJOR_VERSION ||
(magic[2] == JMOD_MAJOR_VERSION && magic[3] > JMOD_MINOR_VERSION)) {
@ -130,6 +130,13 @@ public class JmodFile implements AutoCloseable {
return name;
}
/**
* Returns true if the entry is a directory in the JMOD file.
*/
public boolean isDirectory() {
return zipEntry.isDirectory();
}
/**
* Returns the size of this entry.
*/
@ -186,12 +193,12 @@ public class JmodFile implements AutoCloseable {
public Entry getEntry(Section section, String name) {
String entry = section.jmodDir() + "/" + name;
ZipEntry ze = zipfile.getEntry(entry);
return (ze == null || ze.isDirectory()) ? null : new Entry(ze);
return (ze != null) ? new Entry(ze) : null;
}
/**
* Opens an {@code InputStream} for reading the named entry of the given
* section in this jmod file.
* section in this JMOD file.
*
* @throws IOException if the named entry is not found, or I/O error
* occurs when reading it
@ -201,7 +208,7 @@ public class JmodFile implements AutoCloseable {
{
String entry = section.jmodDir() + "/" + name;
ZipEntry e = zipfile.getEntry(entry);
if (e == null || e.isDirectory()) {
if (e == null) {
throw new IOException(name + " not found: " + file);
}
return zipfile.getInputStream(e);
@ -217,11 +224,10 @@ public class JmodFile implements AutoCloseable {
}
/**
* Returns a stream of non-directory entries in this jmod file.
* Returns a stream of entries in this JMOD file.
*/
public Stream<Entry> stream() {
return zipfile.stream()
.filter(e -> !e.isDirectory())
.map(Entry::new);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2017, 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
@ -65,14 +65,12 @@ public final class JrtFileSystemProvider extends FileSystemProvider {
}
/**
* Need FilePermission ${java.home}/-", "read" to create or get jrt:/
* Need RuntimePermission "accessSystemModules" to create or get jrt:/
*/
private void checkPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
String home = SystemImage.RUNTIME_HOME;
FilePermission perm
= new FilePermission(home + File.separator + "-", "read");
RuntimePermission perm = new RuntimePermission("accessSystemModules");
sm.checkPermission(perm);
}
}

View File

@ -95,6 +95,14 @@ public class BootLoader {
return CLASS_LOADER_VALUE_MAP;
}
/**
* Returns {@code true} if there is a class path associated with the
* BootLoader.
*/
public static boolean hasClassPath() {
return ClassLoaders.bootLoader().hasClassPath();
}
/**
* Register a module with this class loader so that its classes (and
* resources) become visible via this class loader.
@ -187,14 +195,6 @@ public class BootLoader {
.map(name -> getDefinedPackage(name.replace('/', '.')));
}
/**
* Returns {@code true} if there is a class path associated with the
* BootLoader.
*/
public static boolean hasClassPath() {
return ClassLoaders.bootLoader().hasClassPath();
}
/**
* Helper class to define {@code Package} objects for packages in modules
* defined to the boot loader.

View File

@ -60,6 +60,7 @@ import java.util.stream.Stream;
import jdk.internal.misc.VM;
import jdk.internal.module.ModulePatcher.PatchedModuleReader;
import jdk.internal.module.SystemModules;
import jdk.internal.module.Resources;
/**
@ -162,6 +163,14 @@ public class BuiltinClassLoader
this.moduleToReader = new ConcurrentHashMap<>();
}
/**
* Returns {@code true} if there is a class path associated with this
* class loader.
*/
boolean hasClassPath() {
return ucp != null;
}
/**
* Register a module this this class loader. This has the effect of making
* the types in the module visible.
@ -248,18 +257,24 @@ public class BuiltinClassLoader
*/
@Override
public URL findResource(String name) {
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
LoadedModule module = packageToModule.get(pn);
if (module != null) {
// resource is in a package of a module defined to this loader
if (module.loader() == this
&& (name.endsWith(".class") || isOpen(module.mref(), pn))) {
if (module.loader() == this) {
URL url;
try {
return findResource(module.name(), name); // checks URL
url = findResource(module.name(), name); // checks URL
} catch (IOException ioe) {
return null;
}
if (url != null
&& (name.endsWith(".class")
|| url.toString().endsWith("/")
|| isOpen(module.mref(), pn))) {
return url;
}
}
} else {
@ -293,15 +308,17 @@ public class BuiltinClassLoader
public Enumeration<URL> findResources(String name) throws IOException {
List<URL> checked = new ArrayList<>(); // list of checked URLs
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
LoadedModule module = packageToModule.get(pn);
if (module != null) {
// resource is in a package of a module defined to this loader
if (module.loader() == this
&& (name.endsWith(".class") || isOpen(module.mref(), pn))) {
URL url = findResource(module.name(), name); // checks URL
if (url != null) {
if (module.loader() == this) {
URL url = findResource(module.name(), name); // checks URL
if (url != null
&& (name.endsWith(".class")
|| url.toString().endsWith("/")
|| isOpen(module.mref(), pn))) {
checked.add(url);
}
}
@ -351,11 +368,13 @@ public class BuiltinClassLoader
new PrivilegedExceptionAction<>() {
@Override
public List<URL> run() throws IOException {
List<URL> result = new ArrayList<>();
List<URL> result = null;
for (ModuleReference mref : nameToModule.values()) {
URI u = moduleReaderFor(mref).find(name).orElse(null);
if (u != null) {
try {
if (result == null)
result = new ArrayList<>();
result.add(u.toURL());
} catch (MalformedURLException |
IllegalArgumentException e) {
@ -375,7 +394,7 @@ public class BuiltinClassLoader
map = new ConcurrentHashMap<>();
this.resourceCache = new SoftReference<>(map);
}
if (urls.isEmpty())
if (urls == null)
urls = Collections.emptyList();
map.putIfAbsent(name, urls);
}
@ -869,14 +888,6 @@ public class BuiltinClassLoader
sealBase);
}
/**
* Returns {@code true} if there is a class path associated with this
* class loader.
*/
boolean hasClassPath() {
return ucp != null;
}
/**
* Returns {@code true} if the specified package name is sealed according to
* the given manifest.
@ -975,7 +986,7 @@ public class BuiltinClassLoader
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen())
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();

View File

@ -60,6 +60,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.Resources;
/**
@ -356,45 +357,52 @@ public final class Loader extends SecureClassLoader {
@Override
public URL findResource(String name) {
URL url = null;
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
LoadedModule module = localPackageToModule.get(pn);
if (module != null) {
if (name.endsWith(".class") || isOpen(module.mref(), pn)) {
try {
url = findResource(module.name(), name);
} catch (IOException ioe) {
// ignore
try {
URL url = findResource(module.name(), name);
if (url != null
&& (name.endsWith(".class")
|| url.toString().endsWith("/")
|| isOpen(module.mref(), pn))) {
return url;
}
} catch (IOException ioe) {
// ignore
}
} else {
for (ModuleReference mref : nameToModule.values()) {
try {
url = findResource(mref.descriptor().name(), name);
if (url != null)
break;
URL url = findResource(mref.descriptor().name(), name);
if (url != null) return url;
} catch (IOException ioe) {
// ignore
}
}
}
return url;
return null;
}
@Override
public Enumeration<URL> findResources(String name) throws IOException {
List<URL> urls = new ArrayList<>();
String pn = ResourceHelper.getPackageName(name);
String pn = Resources.toPackageName(name);
LoadedModule module = localPackageToModule.get(pn);
if (module != null) {
if (name.endsWith(".class") || isOpen(module.mref(), pn)) {
try {
URL url = findResource(module.name(), name);
if (url != null)
urls.add(url);
} catch (IOException ioe) {
// ignore
try {
URL url = findResource(module.name(), name);
if (url != null
&& (name.endsWith(".class")
|| url.toString().endsWith("/")
|| isOpen(module.mref(), pn))) {
urls.add(url);
}
} catch (IOException ioe) {
// ignore
}
} else {
for (ModuleReference mref : nameToModule.values()) {
@ -643,7 +651,7 @@ public final class Loader extends SecureClassLoader {
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen())
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();

View File

@ -1,125 +0,0 @@
/*
* Copyright (c) 2016, 2017, 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.
*/
package jdk.internal.loader;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import jdk.internal.module.Checks;
/**
* Helper class for Class#getResource, Module#getResourceAsStream, and other
* methods that locate a resource in a module.
*/
public final class ResourceHelper {
private ResourceHelper() { }
/**
* Returns the <em>package name</em> for a resource or the empty package if
* the resource name does not contain a slash.
*/
public static String getPackageName(String name) {
int index = name.lastIndexOf('/');
if (index != -1) {
return name.substring(0, index).replace("/", ".");
} else {
return "";
}
}
/**
* Returns true if the resource is a <em>simple resource</em>. Simple
* resources can never be encapsulated. Resources ending in "{@code .class}"
* or where the package name is not a legal package name can not be
* encapsulated.
*/
public static boolean isSimpleResource(String name) {
int len = name.length();
if (len > 6 && name.endsWith(".class")) {
return true;
}
if (!Checks.isPackageName(getPackageName(name))) {
return true;
}
return false;
}
/**
* Converts a resource name to a file path. Returns {@code null} if the
* resource name cannot be converted into a file path. Resource names
* with empty elements, or elements that are "." or ".." are rejected,
* as is a resource name that translates to a file path with a root
* component.
*/
public static Path toFilePath(String name) {
// scan the resource name to eagerly reject obviously invalid names
int next;
int off = 0;
while ((next = name.indexOf('/', off)) != -1) {
int len = next - off;
if (!mayTranslate(name, off, len)) {
return null;
}
off = next + 1;
}
int rem = name.length() - off;
if (!mayTranslate(name, off, rem)) {
return null;
}
// convert to file path
Path path;
if (File.separatorChar == '/') {
path = Paths.get(name);
} else {
// not allowed to embed file separators
if (name.contains(File.separator))
return null;
path = Paths.get(name.replace('/', File.separatorChar));
}
// file path not allowed to have root component
return (path.getRoot() == null) ? path : null;
}
/**
* Returns {@code true} if the element in a resource name is a candidate
* to translate to the element of a file path.
*/
private static boolean mayTranslate(String name, int off, int len) {
if (len <= 2) {
if (len == 0)
return false;
boolean starsWithDot = (name.charAt(off) == '.');
if (len == 1 && starsWithDot)
return false;
if (len == 2 && starsWithDot && (name.charAt(off+1) == '.'))
return false;
}
return true;
}
}

View File

@ -33,6 +33,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Module;
import java.net.URL;
import java.security.AccessControlContext;
import java.security.ProtectionDomain;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
@ -149,6 +150,11 @@ public interface JavaLangAccess {
*/
ConcurrentHashMap<?, ?> createOrGetClassLoaderValueMap(ClassLoader cl);
/**
* Defines a class with the given name to a class loader.
*/
Class<?> defineClass(ClassLoader cl, String name, byte[] b, ProtectionDomain pd, String source);
/**
* Returns a class loaded by the bootstrap class loader.
*/

View File

@ -73,7 +73,7 @@ public interface JavaLangModuleAccess {
void requires(ModuleDescriptor.Builder builder,
Set<Requires.Modifier> ms,
String mn,
String compiledVersion);
String rawCompiledVersion);
/**
* Returns a {@code ModuleDescriptor.Requires} of the given modifiers
@ -127,9 +127,6 @@ public interface JavaLangModuleAccess {
Set<Provides> provides,
Set<String> packages,
String mainClass,
String osName,
String osArch,
String osVersion,
int hashCode);
/**

View File

@ -65,6 +65,11 @@ public interface JavaLangReflectModuleAccess {
*/
void addReadsAllUnnamed(Module m);
/**
* Update module m to export a package to all modules.
*/
void addExports(Module m, String pn);
/**
* Updates module m1 to export a package to module m2. The export does
* not result in a strong reference to m2 (m2 can be GC'ed).
@ -72,25 +77,20 @@ public interface JavaLangReflectModuleAccess {
void addExports(Module m1, String pkg, Module m2);
/**
* Updates module m1 to open a package to module m2. Opening the
* package does not result in a strong reference to m2 (m2 can be GC'ed).
* Updates a module m to export a package to all unnamed modules.
*/
void addOpens(Module m1, String pkg, Module m2);
/**
* Updates a module m to export a package to all modules.
*/
void addExportsToAll(Module m, String pkg);
void addExportsToAllUnnamed(Module m, String pkg);
/**
* Updates a module m to open a package to all modules.
*/
void addOpensToAll(Module m, String pkg);
void addOpens(Module m, String pkg);
/**
* Updates a module m to export a package to all unnamed modules.
* Updates module m1 to open a package to module m2. Opening the
* package does not result in a strong reference to m2 (m2 can be GC'ed).
*/
void addExportsToAllUnnamed(Module m, String pkg);
void addOpens(Module m1, String pkg, Module m2);
/**
* Updates a module m to open a package to all unnamed modules.
@ -102,11 +102,6 @@ public interface JavaLangReflectModuleAccess {
*/
void addUses(Module m, Class<?> service);
/**
* Add a package to the given module.
*/
void addPackage(Module m, String pkg);
/**
* Returns the ServicesCatalog for the given Layer.
*/
@ -123,12 +118,4 @@ public interface JavaLangReflectModuleAccess {
* given class loader.
*/
Stream<Layer> layers(ClassLoader loader);
/**
* Tests if a module exports a package at least {@code other} via its
* module declaration.
*
* @apiNote This is a temporary method for debugging features.
*/
boolean isStaticallyExported(Module module, String pn, Module other);
}

View File

@ -145,9 +145,6 @@ final class Builder {
Set<Provides> provides;
Version version;
String mainClass;
String osName;
String osArch;
String osVersion;
Builder(String name) {
this.name = name;
@ -247,30 +244,6 @@ final class Builder {
return this;
}
/**
* Sets the OS name.
*/
public Builder osName(String name) {
this.osName = name;
return this;
}
/**
* Sets the OS arch.
*/
public Builder osArch(String arch) {
this.osArch = arch;
return this;
}
/**
* Sets the OS version.
*/
public Builder osVersion(String version) {
this.osVersion = version;
return this;
}
/**
* Returns an immutable set of the module modifiers derived from the flags.
*/
@ -305,9 +278,6 @@ final class Builder {
provides,
packages,
mainClass,
osName,
osArch,
osVersion,
hashCode);
}
}

View File

@ -180,41 +180,38 @@ public final class Checks {
}
/**
* Returns {@code true} if the last character of the given name is legal
* as the last character of a module name.
*
* @throws IllegalArgumentException if name is empty
* Returns {@code true} if a given legal module name contains an identifier
* that doesn't end with a Java letter.
*/
public static boolean hasLegalModuleNameLastCharacter(String name) {
if (name.isEmpty())
throw new IllegalArgumentException("name is empty");
int len = name.length();
if (isASCIIString(name)) {
char c = name.charAt(len-1);
return Character.isJavaIdentifierStart(c);
} else {
int i = 0;
int cp = -1;
while (i < len) {
cp = name.codePointAt(i);
i += Character.charCount(cp);
}
return Character.isJavaIdentifierStart(cp);
}
}
/**
* Returns true if the given string only contains ASCII characters.
*/
private static boolean isASCIIString(String s) {
public static boolean hasJavaIdentifierWithTrailingDigit(String name) {
// quick scan to allow names that are just ASCII without digits
boolean needToParse = false;
int i = 0;
while (i < s.length()) {
int c = s.charAt(i);
if (c > 0x7F)
return false;
while (i < name.length()) {
int c = name.charAt(i);
if (c > 0x7F || (c >= '0' && c <= '9')) {
needToParse = true;
break;
}
i++;
}
return true;
if (!needToParse)
return false;
// slow path
int next;
int off = 0;
while ((next = name.indexOf('.', off)) != -1) {
int last = isJavaIdentifier(name, off, (next - off));
if (!Character.isJavaIdentifierStart(last))
return true;
off = next+1;
}
int last = isJavaIdentifier(name, off, name.length() - off);
if (!Character.isJavaIdentifierStart(last))
return true;
return false;
}
/**

View File

@ -292,11 +292,11 @@ public final class ClassFileAttributes {
attr.putShort(module_flags);
// module_version
Version v = descriptor.version().orElse(null);
if (v == null) {
String vs = descriptor.rawVersion().orElse(null);
if (vs == null) {
attr.putShort(0);
} else {
int module_version_index = cw.newUTF8(v.toString());
int module_version_index = cw.newUTF8(vs);
attr.putShort(module_version_index);
}
@ -320,11 +320,11 @@ public final class ClassFileAttributes {
attr.putShort(requires_flags);
int requires_version_index;
v = r.compiledVersion().orElse(null);
if (v == null) {
vs = r.rawCompiledVersion().orElse(null);
if (vs == null) {
requires_version_index = 0;
} else {
requires_version_index = cw.newUTF8(v.toString());
requires_version_index = cw.newUTF8(vs);
}
attr.putShort(requires_version_index);
}
@ -553,8 +553,6 @@ public final class ClassFileAttributes {
* u2 os_name_index;
* // index to CONSTANT_utf8_info structure with the OS arch
* u2 os_arch_index
* // index to CONSTANT_utf8_info structure with the OS version
* u2 os_version_index;
* }
*
* } </pre>
@ -562,17 +560,23 @@ public final class ClassFileAttributes {
public static class ModuleTargetAttribute extends Attribute {
private final String osName;
private final String osArch;
private final String osVersion;
public ModuleTargetAttribute(String osName, String osArch, String osVersion) {
public ModuleTargetAttribute(String osName, String osArch) {
super(MODULE_TARGET);
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
}
public ModuleTargetAttribute() {
this(null, null, null);
this(null, null);
}
public String osName() {
return osName;
}
public String osArch() {
return osArch;
}
@Override
@ -586,7 +590,6 @@ public final class ClassFileAttributes {
String osName = null;
String osArch = null;
String osVersion = null;
int name_index = cr.readUnsignedShort(off);
if (name_index != 0)
@ -598,12 +601,7 @@ public final class ClassFileAttributes {
osArch = cr.readUTF8(off, buf);
off += 2;
int version_index = cr.readUnsignedShort(off);
if (version_index != 0)
osVersion = cr.readUTF8(off, buf);
off += 2;
return new ModuleTargetAttribute(osName, osArch, osVersion);
return new ModuleTargetAttribute(osName, osArch);
}
@Override
@ -625,11 +623,6 @@ public final class ClassFileAttributes {
arch_index = cw.newUTF8(osArch);
attr.putShort(arch_index);
int version_index = 0;
if (osVersion != null && osVersion.length() > 0)
version_index = cw.newUTF8(osVersion);
attr.putShort(version_index);
return attr;
}
}

View File

@ -0,0 +1,318 @@
/*
* Copyright (c) 2017, 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.
*/
package jdk.internal.module;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Module;
import java.net.URL;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* Supports logging of access to members of API packages that are exported or
* opened via backdoor mechanisms to code in unnamed modules.
*/
public final class IllegalAccessLogger {
// true to print stack trace
private static final boolean PRINT_STACK_TRACE;
static {
String s = System.getProperty("sun.reflect.debugModuleAccessChecks");
PRINT_STACK_TRACE = "access".equals(s);
}
private static final StackWalker STACK_WALKER
= StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
// the maximum number of frames to capture
private static final int MAX_STACK_FRAMES = 32;
// lock to avoid interference when printing stack traces
private static final Object OUTPUT_LOCK = new Object();
// caller -> usages
private final Map<Class<?>, Set<Usage>> callerToUsages = new WeakHashMap<>();
// module -> (package name -> CLI option)
private final Map<Module, Map<String, String>> exported;
private final Map<Module, Map<String, String>> opened;
private IllegalAccessLogger(Map<Module, Map<String, String>> exported,
Map<Module, Map<String, String>> opened) {
this.exported = deepCopy(exported);
this.opened = deepCopy(opened);
}
/**
* Returns that a Builder that is seeded with the packages known to this logger.
*/
public Builder toBuilder() {
return new Builder(exported, opened);
}
/**
* Logs access to the member of a target class by a caller class if the class
* is in a package that is exported via a backdoor mechanism.
*
* The {@code whatSupplier} supplies the message that describes the member.
*/
public void logIfExportedByBackdoor(Class<?> caller,
Class<?> target,
Supplier<String> whatSupplier) {
Map<String, String> packages = exported.get(target.getModule());
if (packages != null) {
String how = packages.get(target.getPackageName());
if (how != null) {
log(caller, whatSupplier.get(), how);
}
}
}
/**
* Logs access to the member of a target class by a caller class if the class
* is in a package that is opened via a backdoor mechanism.
*
* The {@code what} parameter supplies the message that describes the member.
*/
public void logIfOpenedByBackdoor(Class<?> caller,
Class<?> target,
Supplier<String> whatSupplier) {
Map<String, String> packages = opened.get(target.getModule());
if (packages != null) {
String how = packages.get(target.getPackageName());
if (how != null) {
log(caller, whatSupplier.get(), how);
}
}
}
/**
* Logs access by a caller class. The {@code what} parameter describes
* the member is accessed, the {@code how} parameter is the means by which
* access is allocated (CLI option for example).
*/
private void log(Class<?> caller, String what, String how) {
log(caller, what, () -> {
PrivilegedAction<ProtectionDomain> pa = caller::getProtectionDomain;
CodeSource cs = AccessController.doPrivileged(pa).getCodeSource();
URL url = (cs != null) ? cs.getLocation() : null;
String source = caller.getName();
if (url != null)
source += " (" + url + ")";
return "WARNING: Illegal access by " + source + " to " + what
+ " (permitted by " + how + ")";
});
}
/**
* Logs access to caller class if the class is in a package that is opened via
* a backdoor mechanism.
*/
public void logIfOpenedByBackdoor(MethodHandles.Lookup caller, Class<?> target) {
Map<String, String> packages = opened.get(target.getModule());
if (packages != null) {
String how = packages.get(target.getPackageName());
if (how != null) {
log(caller.lookupClass(), target.getName(), () ->
"WARNING: Illegal access using Lookup on " + caller.lookupClass()
+ " to " + target + " (permitted by " + how + ")");
}
}
}
/**
* Log access by a caller. The {@code what} parameter describes the class or
* member that is being accessed. The {@code msgSupplier} supplies the log
* message.
*
* To reduce output, this method only logs the access if it hasn't been seen
* previously. "Seen previously" is implemented as a map of caller class -> Usage,
* where a Usage is the "what" and a hash of the stack trace. The map has weak
* keys so it can be expunged when the caller is GC'ed/unloaded.
*/
private void log(Class<?> caller, String what, Supplier<String> msgSupplier) {
// stack trace without the top-most frames in java.base
List<StackWalker.StackFrame> stack = STACK_WALKER.walk(s ->
s.dropWhile(this::isJavaBase)
.limit(MAX_STACK_FRAMES)
.collect(Collectors.toList())
);
// check if the access has already been recorded
Usage u = new Usage(what, hash(stack));
boolean firstUsage;
synchronized (this) {
firstUsage = callerToUsages.computeIfAbsent(caller, k -> new HashSet<>()).add(u);
}
// log message if first usage
if (firstUsage) {
String msg = msgSupplier.get();
if (PRINT_STACK_TRACE) {
synchronized (OUTPUT_LOCK) {
System.err.println(msg);
stack.forEach(f -> System.err.println("\tat " + f));
}
} else {
System.err.println(msg);
}
}
}
private static class Usage {
private final String what;
private final int stack;
Usage(String what, int stack) {
this.what = what;
this.stack = stack;
}
@Override
public int hashCode() {
return what.hashCode() ^ stack;
}
@Override
public boolean equals(Object ob) {
if (ob instanceof Usage) {
Usage that = (Usage)ob;
return what.equals(that.what) && stack == (that.stack);
} else {
return false;
}
}
}
/**
* Returns true if the stack frame is for a class in java.base.
*/
private boolean isJavaBase(StackWalker.StackFrame frame) {
Module caller = frame.getDeclaringClass().getModule();
return "java.base".equals(caller.getName());
}
/**
* Computes a hash code for the give stack frames. The hash code is based
* on the class, method name, and BCI.
*/
private int hash(List<StackWalker.StackFrame> stack) {
int hash = 0;
for (StackWalker.StackFrame frame : stack) {
hash = (31 * hash) + Objects.hash(frame.getDeclaringClass(),
frame.getMethodName(),
frame.getByteCodeIndex());
}
return hash;
}
// system-wide IllegalAccessLogger
private static volatile IllegalAccessLogger logger;
/**
* Sets the system-wide IllegalAccessLogger
*/
public static void setIllegalAccessLogger(IllegalAccessLogger l) {
if (l.exported.isEmpty() && l.opened.isEmpty()) {
logger = null;
} else {
logger = l;
}
}
/**
* Returns the system-wide IllegalAccessLogger or {@code null} if there is
* no logger.
*/
public static IllegalAccessLogger illegalAccessLogger() {
return logger;
}
/**
* A builder for IllegalAccessLogger objects.
*/
public static class Builder {
private Map<Module, Map<String, String>> exported;
private Map<Module, Map<String, String>> opened;
public Builder() { }
public Builder(Map<Module, Map<String, String>> exported,
Map<Module, Map<String, String>> opened) {
this.exported = deepCopy(exported);
this.opened = deepCopy(opened);
}
public void logAccessToExportedPackage(Module m, String pn, String how) {
if (!m.isExported(pn)) {
if (exported == null)
exported = new HashMap<>();
exported.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
}
}
public void logAccessToOpenPackage(Module m, String pn, String how) {
// opens implies exported at run-time.
logAccessToExportedPackage(m, pn, how);
if (!m.isOpen(pn)) {
if (opened == null)
opened = new HashMap<>();
opened.computeIfAbsent(m, k -> new HashMap<>()).putIfAbsent(pn, how);
}
}
/**
* Builds the logger.
*/
public IllegalAccessLogger build() {
return new IllegalAccessLogger(exported, opened);
}
}
static Map<Module, Map<String, String>> deepCopy(Map<Module, Map<String, String>> map) {
if (map == null || map.isEmpty()) {
return new HashMap<>();
} else {
Map<Module, Map<String, String>> newMap = new HashMap<>();
for (Map.Entry<Module, Map<String, String>> e : map.entrySet()) {
newMap.put(e.getKey(), new HashMap<>(e.getValue()));
}
return newMap;
}
}
}

View File

@ -33,6 +33,7 @@ import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolvedModule;
import java.lang.reflect.Layer;
import java.lang.reflect.LayerInstantiationException;
import java.lang.reflect.Module;
import java.net.URI;
import java.nio.file.Path;
@ -46,7 +47,6 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.BuiltinClassLoader;
@ -327,8 +327,9 @@ public final class ModuleBootstrap {
for (String p : descriptor.packages()) {
String other = packageToModule.putIfAbsent(p, name);
if (other != null) {
fail("Package " + p + " in both module "
+ name + " and module " + other);
String msg = "Package " + p + " in both module "
+ name + " and module " + other;
throw new LayerInstantiationException(msg);
}
}
}
@ -359,7 +360,7 @@ public final class ModuleBootstrap {
PerfCounters.loadModulesTime.addElapsedTimeFrom(t5);
// --add-reads, -add-exports/-add-opens
// --add-reads, --add-exports/--add-opens
addExtraReads(bootLayer);
addExtraExportsAndOpens(bootLayer);
@ -514,26 +515,44 @@ public final class ModuleBootstrap {
* additional packages specified on the command-line.
*/
private static void addExtraExportsAndOpens(Layer bootLayer) {
IllegalAccessLogger.Builder builder = new IllegalAccessLogger.Builder();
// --add-exports
String prefix = "jdk.module.addexports.";
Map<String, List<String>> extraExports = decode(prefix);
if (!extraExports.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraExports, false);
addExtraExportsOrOpens(bootLayer, extraExports, false, builder);
}
// --add-opens
prefix = "jdk.module.addopens.";
Map<String, List<String>> extraOpens = decode(prefix);
if (!extraOpens.isEmpty()) {
addExtraExportsOrOpens(bootLayer, extraOpens, true);
addExtraExportsOrOpens(bootLayer, extraOpens, true, builder);
}
// --permit-illegal-access
if (getAndRemoveProperty("jdk.module.permitIllegalAccess") != null) {
warn("--permit-illegal-access will be removed in the next major release");
bootLayer.modules().stream().forEach(m -> {
m.getDescriptor()
.packages()
.stream()
.filter(pn -> !m.isOpen(pn))
.forEach(pn -> {
builder.logAccessToOpenPackage(m, pn, "--permit-illegal-access");
Modules.addOpensToAllUnnamed(m, pn);
});
});
}
IllegalAccessLogger.setIllegalAccessLogger(builder.build());
}
private static void addExtraExportsOrOpens(Layer bootLayer,
Map<String, List<String>> map,
boolean opens)
boolean opens,
IllegalAccessLogger.Builder builder)
{
String option = opens ? ADD_OPENS : ADD_EXPORTS;
for (Map.Entry<String, List<String>> e : map.entrySet()) {
@ -542,12 +561,12 @@ public final class ModuleBootstrap {
String key = e.getKey();
String[] s = key.split("/");
if (s.length != 2)
fail(unableToParse(option, "<module>/<package>", key));
fail(unableToParse(option, "<module>/<package>", key));
String mn = s[0];
String pn = s[1];
if (mn.isEmpty() || pn.isEmpty())
fail(unableToParse(option, "<module>/<package>", key));
fail(unableToParse(option, "<module>/<package>", key));
// The exporting module is in the boot layer
Module m;
@ -581,8 +600,10 @@ public final class ModuleBootstrap {
}
if (allUnnamed) {
if (opens) {
builder.logAccessToOpenPackage(m, pn, option);
Modules.addOpensToAllUnnamed(m, pn);
} else {
builder.logAccessToExportedPackage(m, pn, option);
Modules.addExportsToAllUnnamed(m, pn);
}
} else {
@ -632,7 +653,7 @@ public final class ModuleBootstrap {
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
if (!allowDuplicates && map.containsKey(key))
fail(key + " specified more than once in " + option(prefix));
fail(key + " specified more than once to " + option(prefix));
List<String> values = map.computeIfAbsent(key, k -> new ArrayList<>());
int ntargets = 0;
for (String s : rhs.split(regex)) {
@ -676,10 +697,6 @@ public final class ModuleBootstrap {
ModuleReference mref = rm.reference();
String mn = mref.descriptor().name();
// emit warning if module name ends with a non-Java letter
if (!Checks.hasLegalModuleNameLastCharacter(mn))
warn("Module name \"" + mn + "\" may soon be illegal");
// emit warning if the WARN_INCUBATING module resolution bit set
if (ModuleResolution.hasIncubatingWarning(mref)) {
if (incubating == null) {
@ -705,7 +722,7 @@ public final class ModuleBootstrap {
}
static void warnUnknownModule(String option, String mn) {
warn("Unknown module: " + mn + " specified in " + option);
warn("Unknown module: " + mn + " specified to " + option);
}
static String unableToParse(String option, String text, String value) {

View File

@ -89,18 +89,24 @@ public final class ModuleInfo {
*/
public static final class Attributes {
private final ModuleDescriptor descriptor;
private final ModuleTarget target;
private final ModuleHashes recordedHashes;
private final ModuleResolution moduleResolution;
Attributes(ModuleDescriptor descriptor,
ModuleTarget target,
ModuleHashes recordedHashes,
ModuleResolution moduleResolution) {
this.descriptor = descriptor;
this.target = target;
this.recordedHashes = recordedHashes;
this.moduleResolution = moduleResolution;
}
public ModuleDescriptor descriptor() {
return descriptor;
}
public ModuleTarget target() {
return target;
}
public ModuleHashes recordedHashes() {
return recordedHashes;
}
@ -221,8 +227,8 @@ public final class ModuleInfo {
Builder builder = null;
Set<String> allPackages = null;
String mainClass = null;
String[] osValues = null;
ModuleHashes hashes = null;
ModuleTarget moduleTarget = null;
ModuleHashes moduelHashes = null;
ModuleResolution moduleResolution = null;
for (int i = 0; i < attributes_count ; i++) {
@ -251,12 +257,12 @@ public final class ModuleInfo {
break;
case MODULE_TARGET :
osValues = readModuleTargetAttribute(in, cpool);
moduleTarget = readModuleTargetAttribute(in, cpool);
break;
case MODULE_HASHES :
if (parseHashes) {
hashes = readModuleHashesAttribute(in, cpool);
moduelHashes = readModuleHashesAttribute(in, cpool);
} else {
in.skipBytes(length);
}
@ -282,15 +288,10 @@ public final class ModuleInfo {
throw invalidModuleDescriptor(MODULE + " attribute not found");
}
// ModuleMainClass and ModuleTarget attributes
// ModuleMainClass attribute
if (mainClass != null) {
builder.mainClass(mainClass);
}
if (osValues != null) {
if (osValues[0] != null) builder.osName(osValues[0]);
if (osValues[1] != null) builder.osArch(osValues[1]);
if (osValues[2] != null) builder.osVersion(osValues[2]);
}
// If the ModulePackages attribute is not present then the packageFinder
// is used to find the set of packages
@ -323,7 +324,10 @@ public final class ModuleInfo {
}
ModuleDescriptor descriptor = builder.build();
return new Attributes(descriptor, hashes, moduleResolution);
return new Attributes(descriptor,
moduleTarget,
moduelHashes,
moduleResolution);
}
/**
@ -422,7 +426,11 @@ public final class ModuleInfo {
Set<String> targets = new HashSet<>(exports_to_count);
for (int j=0; j<exports_to_count; j++) {
int exports_to_index = in.readUnsignedShort();
targets.add(cpool.getModuleName(exports_to_index));
String target = cpool.getModuleName(exports_to_index);
if (!targets.add(target)) {
throw invalidModuleDescriptor(pkg + " exported to "
+ target + " more than once");
}
}
builder.exports(mods, pkg, targets);
} else {
@ -458,7 +466,11 @@ public final class ModuleInfo {
Set<String> targets = new HashSet<>(open_to_count);
for (int j=0; j<open_to_count; j++) {
int opens_to_index = in.readUnsignedShort();
targets.add(cpool.getModuleName(opens_to_index));
String target = cpool.getModuleName(opens_to_index);
if (!targets.add(target)) {
throw invalidModuleDescriptor(pkg + " opened to "
+ target + " more than once");
}
}
builder.opens(mods, pkg, targets);
} else {
@ -486,7 +498,10 @@ public final class ModuleInfo {
for (int j=0; j<with_count; j++) {
index = in.readUnsignedShort();
String pn = cpool.getClassName(index);
providers.add(pn);
if (!providers.add(pn)) {
throw invalidModuleDescriptor(sn + " provides " + pn
+ " more than once");
}
}
builder.provides(sn, providers);
}
@ -528,24 +543,21 @@ public final class ModuleInfo {
/**
* Reads the ModuleTarget attribute
*/
private String[] readModuleTargetAttribute(DataInput in, ConstantPool cpool)
private ModuleTarget readModuleTargetAttribute(DataInput in, ConstantPool cpool)
throws IOException
{
String[] values = new String[3];
String osName = null;
String osArch = null;
int name_index = in.readUnsignedShort();
if (name_index != 0)
values[0] = cpool.getUtf8(name_index);
osName = cpool.getUtf8(name_index);
int arch_index = in.readUnsignedShort();
if (arch_index != 0)
values[1] = cpool.getUtf8(arch_index);
osArch = cpool.getUtf8(arch_index);
int version_index = in.readUnsignedShort();
if (version_index != 0)
values[2] = cpool.getUtf8(version_index);
return values;
return new ModuleTarget(osName, osArch);
}

View File

@ -65,7 +65,6 @@ public final class ModuleInfoExtender {
// the values for the ModuleTarget attribute
private String osName;
private String osArch;
private String osVersion;
// the hashes for the ModuleHashes attribute
private ModuleHashes hashes;
@ -111,12 +110,9 @@ public final class ModuleInfoExtender {
/**
* Sets the values for the ModuleTarget attribute.
*/
public ModuleInfoExtender targetPlatform(String osName,
String osArch,
String osVersion) {
public ModuleInfoExtender targetPlatform(String osName, String osArch) {
this.osName = osName;
this.osArch = osArch;
this.osVersion = osVersion;
return this;
}
@ -203,8 +199,8 @@ public final class ModuleInfoExtender {
cv.addAttribute(new ModulePackagesAttribute(packages));
if (mainClass != null)
cv.addAttribute(new ModuleMainClassAttribute(mainClass));
if (osName != null || osArch != null || osVersion != null)
cv.addAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
if (osName != null || osArch != null)
cv.addAttribute(new ModuleTargetAttribute(osName, osArch));
if (hashes != null)
cv.addAttribute(new ModuleHashesAttribute(hashes));
if (moduleResolution != null)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, 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
@ -48,7 +48,7 @@ public final class ModuleInfoWriter {
* Writes the given module descriptor to a module-info.class file,
* returning it in a byte array.
*/
private static byte[] toModuleInfo(ModuleDescriptor md) {
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
ClassWriter cw = new ClassWriter(0);
cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null);
cw.visitAttribute(new ModuleAttribute(md));
@ -66,18 +66,29 @@ public final class ModuleInfoWriter {
// write ModuleMainClass if the module has a main class
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
// write ModuleTarget attribute if have any of OS name/arch/version
String osName = md.osName().orElse(null);
String osArch = md.osArch().orElse(null);
String osVersion = md.osVersion().orElse(null);
if (osName != null || osArch != null || osVersion != null) {
cw.visitAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
// write ModuleTarget if there is a platform OS/arch
if (target != null) {
cw.visitAttribute(new ModuleTargetAttribute(target.osName(),
target.osArch()));
}
cw.visitEnd();
return cw.toByteArray();
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
*/
public static void write(ModuleDescriptor descriptor,
ModuleTarget target,
OutputStream out)
throws IOException
{
byte[] bytes = toModuleInfo(descriptor, target);
out.write(bytes);
}
/**
* Writes a module descriptor to the given output stream as a
* module-info.class.
@ -85,8 +96,7 @@ public final class ModuleInfoWriter {
public static void write(ModuleDescriptor descriptor, OutputStream out)
throws IOException
{
byte[] bytes = toModuleInfo(descriptor);
out.write(bytes);
write(descriptor, null, out);
}
/**
@ -94,8 +104,7 @@ public final class ModuleInfoWriter {
* in module-info.class format.
*/
public static ByteBuffer toByteBuffer(ModuleDescriptor descriptor) {
byte[] bytes = toModuleInfo(descriptor);
byte[] bytes = toModuleInfo(descriptor, null);
return ByteBuffer.wrap(bytes);
}
}

View File

@ -55,7 +55,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.loader.Resource;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.JavaLangModuleAccess;
import jdk.internal.misc.SharedSecrets;
import sun.net.www.ParseUtil;
@ -165,9 +164,6 @@ public final class ModulePatcher {
descriptor.version().ifPresent(builder::version);
descriptor.mainClass().ifPresent(builder::mainClass);
descriptor.osName().ifPresent(builder::osName);
descriptor.osArch().ifPresent(builder::osArch);
descriptor.osVersion().ifPresent(builder::osVersion);
// original + new packages
builder.packages(descriptor.packages());
@ -179,10 +175,12 @@ public final class ModulePatcher {
// return a module reference to the patched module
URI location = mref.location().orElse(null);
ModuleTarget target = null;
ModuleHashes recordedHashes = null;
ModuleResolution mres = null;
if (mref instanceof ModuleReferenceImpl) {
ModuleReferenceImpl impl = (ModuleReferenceImpl)mref;
target = impl.moduleTarget();
recordedHashes = impl.recordedHashes();
mres = impl.moduleResolution();
}
@ -191,6 +189,7 @@ public final class ModulePatcher {
location,
() -> new PatchedModuleReader(paths, mref),
this,
target,
recordedHashes,
null,
mres);
@ -226,7 +225,7 @@ public final class ModulePatcher {
private volatile ModuleReader delegate;
/**
* Creates the ModuleReader to reads resources a patched module.
* Creates the ModuleReader to reads resources in a patched module.
*/
PatchedModuleReader(List<Path> patches, ModuleReference mref) {
List<ResourceFinder> finders = new ArrayList<>();
@ -291,13 +290,16 @@ public final class ModulePatcher {
}
/**
* Finds a resources in the patch locations. Returns null if not found.
* Finds a resources in the patch locations. Returns null if not found
* or the name is "module-info.class" as that cannot be overridden.
*/
private Resource findResourceInPatch(String name) throws IOException {
for (ResourceFinder finder : finders) {
Resource r = finder.find(name);
if (r != null)
return r;
if (!name.equals("module-info.class")) {
for (ResourceFinder finder : finders) {
Resource r = finder.find(name);
if (r != null)
return r;
}
}
return null;
}
@ -478,9 +480,7 @@ public final class ModulePatcher {
@Override
public Stream<String> list() throws IOException {
return jf.stream()
.filter(e -> !e.isDirectory())
.map(JarEntry::getName);
return jf.stream().map(JarEntry::getName);
}
}
@ -500,14 +500,12 @@ public final class ModulePatcher {
@Override
public Resource find(String name) throws IOException {
Path path = ResourceHelper.toFilePath(name);
if (path != null) {
Path file = dir.resolve(path);
if (Files.isRegularFile(file)) {
return newResource(name, dir, file);
}
Path file = Resources.toFilePath(dir, name);
if (file != null) {
return newResource(name, dir, file);
} else {
return null;
}
return null;
}
private Resource newResource(String name, Path top, Path file) {
@ -550,11 +548,9 @@ public final class ModulePatcher {
@Override
public Stream<String> list() throws IOException {
return Files.find(dir, Integer.MAX_VALUE,
(path, attrs) -> attrs.isRegularFile())
.map(f -> dir.relativize(f)
.toString()
.replace(File.separatorChar, '/'));
return Files.walk(dir, Integer.MAX_VALUE)
.map(f -> Resources.toResourceName(dir, f))
.filter(s -> s.length() > 0);
}
}

View File

@ -513,7 +513,7 @@ public class ModulePath implements ModuleFinder {
String pn = packageName(cn);
if (!packages.contains(pn)) {
String msg = "Provider class " + cn + " not in module";
throw new IOException(msg);
throw new InvalidModuleDescriptorException(msg);
}
providerClasses.add(cn);
}
@ -533,7 +533,7 @@ public class ModulePath implements ModuleFinder {
String pn = packageName(mainClass);
if (!packages.contains(pn)) {
String msg = "Main-Class " + mainClass + " not in module";
throw new IOException(msg);
throw new InvalidModuleDescriptorException(msg);
}
builder.mainClass(mainClass);
}
@ -609,11 +609,10 @@ public class ModulePath implements ModuleFinder {
// no module-info.class so treat it as automatic module
try {
ModuleDescriptor md = deriveModuleDescriptor(jf);
attrs = new ModuleInfo.Attributes(md, null, null);
} catch (IllegalArgumentException e) {
throw new FindException(
"Unable to derive module descriptor for: "
+ jf.getName(), e);
attrs = new ModuleInfo.Attributes(md, null, null, null);
} catch (RuntimeException e) {
throw new FindException("Unable to derive module descriptor for "
+ jf.getName(), e);
}
} else {
@ -672,18 +671,18 @@ public class ModulePath implements ModuleFinder {
/**
* Maps the name of an entry in a JAR or ZIP file to a package name.
*
* @throws IllegalArgumentException if the name is a class file in
* the top-level directory of the JAR/ZIP file (and it's
* not module-info.class)
* @throws InvalidModuleDescriptorException if the name is a class file in
* the top-level directory of the JAR/ZIP file (and it's not
* module-info.class)
*/
private Optional<String> toPackageName(String name) {
assert !name.endsWith("/");
int index = name.lastIndexOf("/");
if (index == -1) {
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
throw new IllegalArgumentException(name
+ " found in top-level directory"
+ " (unnamed package not allowed in module)");
String msg = name + " found in top-level directory"
+ " (unnamed package not allowed in module)";
throw new InvalidModuleDescriptorException(msg);
}
return Optional.empty();
}
@ -701,8 +700,8 @@ public class ModulePath implements ModuleFinder {
* Maps the relative path of an entry in an exploded module to a package
* name.
*
* @throws IllegalArgumentException if the name is a class file in
* the top-level directory (and it's not module-info.class)
* @throws InvalidModuleDescriptorException if the name is a class file in
* the top-level directory (and it's not module-info.class)
*/
private Optional<String> toPackageName(Path file) {
assert file.getRoot() == null;
@ -711,9 +710,9 @@ public class ModulePath implements ModuleFinder {
if (parent == null) {
String name = file.toString();
if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
throw new IllegalArgumentException(name
+ " found in top-level directory"
+ " (unnamed package not allowed in module)");
String msg = name + " found in top-level directory"
+ " (unnamed package not allowed in module)";
throw new InvalidModuleDescriptorException(msg);
}
return Optional.empty();
}

View File

@ -46,6 +46,9 @@ public class ModuleReferenceImpl extends ModuleReference {
// non-null if the module is patched
private final ModulePatcher patcher;
// ModuleTarget if the module is OS/architecture specific
private final ModuleTarget target;
// the hashes of other modules recorded in this module
private final ModuleHashes recordedHashes;
@ -65,6 +68,7 @@ public class ModuleReferenceImpl extends ModuleReference {
URI location,
Supplier<ModuleReader> readerSupplier,
ModulePatcher patcher,
ModuleTarget target,
ModuleHashes recordedHashes,
ModuleHashes.HashSupplier hasher,
ModuleResolution moduleResolution)
@ -72,6 +76,7 @@ public class ModuleReferenceImpl extends ModuleReference {
super(descriptor, Objects.requireNonNull(location));
this.readerSupplier = readerSupplier;
this.patcher = patcher;
this.target = target;
this.recordedHashes = recordedHashes;
this.hasher = hasher;
this.moduleResolution = moduleResolution;
@ -93,6 +98,13 @@ public class ModuleReferenceImpl extends ModuleReference {
return (patcher != null);
}
/**
* Returns the ModuleTarget or {@code null} if the no target platform.
*/
public ModuleTarget moduleTarget() {
return target;
}
/**
* Returns the hashes recorded in this module or {@code null} if there
* are no hashes recorded.

View File

@ -25,7 +25,6 @@
package jdk.internal.module;
import java.io.File;
import java.io.IOError;
import java.io.IOException;
import java.io.InputStream;
@ -50,7 +49,6 @@ import java.util.stream.Stream;
import java.util.zip.ZipFile;
import jdk.internal.jmod.JmodFile;
import jdk.internal.loader.ResourceHelper;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.module.ModuleHashes.HashSupplier;
import jdk.internal.util.jar.VersionedStream;
@ -78,6 +76,7 @@ class ModuleReferences {
uri,
supplier,
null,
attrs.target(),
attrs.recordedHashes(),
hasher,
attrs.moduleResolution());
@ -242,8 +241,7 @@ class ModuleReferences {
}
private JarEntry getEntry(String name) {
JarEntry entry = jf.getJarEntry(Objects.requireNonNull(name));
return (entry == null || entry.isDirectory()) ? null : entry;
return jf.getJarEntry(Objects.requireNonNull(name));
}
@Override
@ -252,6 +250,8 @@ class ModuleReferences {
if (je != null) {
if (jf.isMultiRelease())
name = SharedSecrets.javaUtilJarAccess().getRealName(jf, je);
if (je.isDirectory() && !name.endsWith("/"))
name += "/";
String encodedPath = ParseUtil.encodePath(name, false);
String uris = "jar:" + uri + "!/" + encodedPath;
return Optional.of(URI.create(uris));
@ -274,7 +274,6 @@ class ModuleReferences {
Stream<String> implList() throws IOException {
// take snapshot to avoid async close
List<String> names = VersionedStream.stream(jf)
.filter(e -> !e.isDirectory())
.map(JarEntry::getName)
.collect(Collectors.toList());
return names.stream();
@ -316,6 +315,8 @@ class ModuleReferences {
Optional<URI> implFind(String name) {
JmodFile.Entry je = getEntry(name);
if (je != null) {
if (je.isDirectory() && !name.endsWith("/"))
name += "/";
String encodedPath = ParseUtil.encodePath(name, false);
String uris = "jmod:" + uri + "!/" + encodedPath;
return Optional.of(URI.create(uris));
@ -376,26 +377,10 @@ class ModuleReferences {
if (closed) throw new IOException("ModuleReader is closed");
}
/**
* Returns a Path to access the given resource. Returns null if the
* resource name does not convert to a file path that locates a regular
* file in the module.
*/
private Path toFilePath(String name) {
Path path = ResourceHelper.toFilePath(name);
if (path != null) {
Path file = dir.resolve(path);
if (Files.isRegularFile(file)) {
return file;
}
}
return null;
}
@Override
public Optional<URI> find(String name) throws IOException {
ensureOpen();
Path path = toFilePath(name);
Path path = Resources.toFilePath(dir, name);
if (path != null) {
try {
return Optional.of(path.toUri());
@ -410,7 +395,7 @@ class ModuleReferences {
@Override
public Optional<InputStream> open(String name) throws IOException {
ensureOpen();
Path path = toFilePath(name);
Path path = Resources.toFilePath(dir, name);
if (path != null) {
return Optional.of(Files.newInputStream(path));
} else {
@ -421,7 +406,7 @@ class ModuleReferences {
@Override
public Optional<ByteBuffer> read(String name) throws IOException {
ensureOpen();
Path path = toFilePath(name);
Path path = Resources.toFilePath(dir, name);
if (path != null) {
return Optional.of(ByteBuffer.wrap(Files.readAllBytes(path)));
} else {
@ -432,12 +417,9 @@ class ModuleReferences {
@Override
public Stream<String> list() throws IOException {
ensureOpen();
// sym links not followed
return Files.find(dir, Integer.MAX_VALUE,
(path, attrs) -> attrs.isRegularFile())
.map(f -> dir.relativize(f)
.toString()
.replace(File.separatorChar, '/'));
return Files.walk(dir, Integer.MAX_VALUE)
.map(f -> Resources.toResourceName(dir, f))
.filter(s -> s.length() > 0);
}
@Override

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2017, 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.
*/
package jdk.internal.module;
public final class ModuleTarget {
private final String osName;
private final String osArch;
public ModuleTarget(String osName, String osArch) {
this.osName = osName;
this.osArch = osArch;
}
public String osName() {
return osName;
}
public String osArch() {
return osArch;
}
}

View File

@ -31,7 +31,6 @@ import java.lang.reflect.Module;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaders;
@ -39,10 +38,10 @@ import jdk.internal.misc.JavaLangReflectModuleAccess;
import jdk.internal.misc.SharedSecrets;
/**
* A helper class to allow JDK classes create dynamic modules and to update
* modules, exports and the readability graph. It is also invoked by the VM
* to add read edges when agents are instrumenting code that need to link
* to supporting classes.
* A helper class for creating and updating modules. This class is intended to
* support command-line options, tests, and the instrumentation API. It is also
* used by the VM to add read edges when agents are instrumenting code that
* need to link to supporting classes.
*
* The parameters that are package names in this API are the fully-qualified
* names of the packages as defined in section 6.5.3 of <cite>The Java&trade;
@ -72,25 +71,7 @@ public class Modules {
}
/**
* Define a new module to the VM. The module has the given set of
* packages and is defined to the given class loader.
*
* The resulting Module is in a larval state in that it does not not read
* any other module and does not have any exports.
*/
public static Module defineModule(ClassLoader loader,
String name,
Set<String> packages)
{
ModuleDescriptor descriptor = ModuleDescriptor.newModule(name)
.packages(packages)
.build();
return JLRMA.defineModule(loader, descriptor, null);
}
/**
* Adds a read-edge so that module {@code m1} reads module {@code m1}.
* Updates m1 to read m2.
* Same as m1.addReads(m2) but without a caller check.
*/
public static void addReads(Module m1, Module m2) {
@ -98,20 +79,45 @@ public class Modules {
}
/**
* Update module {@code m} to read all unnamed modules.
* Update module m to read all unnamed modules.
*/
public static void addReadsAllUnnamed(Module m) {
JLRMA.addReadsAllUnnamed(m);
}
/**
* Update module m to export a package to all modules.
*
* This method is for intended for use by tests only.
*/
public static void addExports(Module m, String pn) {
JLRMA.addExports(m, pn);
}
/**
* Updates module m1 to export a package to module m2.
* Same as m1.addExports(pn, m2) but without a caller check.
* Same as m1.addExports(pn, m2) but without a caller check
*/
public static void addExports(Module m1, String pn, Module m2) {
JLRMA.addExports(m1, pn, m2);
}
/**
* Updates module m to export a package to all unnamed modules.
*/
public static void addExportsToAllUnnamed(Module m, String pn) {
JLRMA.addExportsToAllUnnamed(m, pn);
}
/**
* Update module m to open a package to all modules.
*
* This method is for intended for use by tests only.
*/
public static void addOpens(Module m, String pn) {
JLRMA.addOpens(m, pn);
}
/**
* Updates module m1 to open a package to module m2.
* Same as m1.addOpens(pn, m2) but without a caller check.
@ -120,27 +126,6 @@ public class Modules {
JLRMA.addOpens(m1, pn, m2);
}
/**
* Updates a module m to export a package to all modules.
*/
public static void addExportsToAll(Module m, String pn) {
JLRMA.addExportsToAll(m, pn);
}
/**
* Updates a module m to open a package to all modules.
*/
public static void addOpensToAll(Module m, String pn) {
JLRMA.addOpensToAll(m, pn);
}
/**
* Updates module m to export a package to all unnamed modules.
*/
public static void addExportsToAllUnnamed(Module m, String pn) {
JLRMA.addExportsToAllUnnamed(m, pn);
}
/**
* Updates module m to open a package to all unnamed modules.
*/
@ -149,7 +134,8 @@ public class Modules {
}
/**
* Updates module m to use a service
* Updates module m to use a service.
* Same as m2.addUses(service) but without a caller check.
*/
public static void addUses(Module m, Class<?> service) {
JLRMA.addUses(m, service);
@ -182,16 +168,6 @@ public class Modules {
}
}
/**
* Adds a package to a module's content.
*
* This method is a no-op if the module already contains the package or the
* module is an unnamed module.
*/
public static void addPackage(Module m, String pn) {
JLRMA.addPackage(m, pn);
}
/**
* Called by the VM when code in the given Module has been transformed by
* an agent and so may have been instrumented to call into supporting

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2016, 2017, 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.
*/
package jdk.internal.module;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
/**
* A helper class to support working with resources in modules. Also provides
* support for translating resource names to file paths.
*/
public final class Resources {
private Resources() { }
/**
* Return true if a resource can be encapsulated. Resource with names
* ending in ".class" or "/" cannot be encapsulated. Resource names
* that map to a legal package name can be encapsulated.
*/
public static boolean canEncapsulate(String name) {
int len = name.length();
if (len > 6 && name.endsWith(".class")) {
return false;
} else {
return Checks.isPackageName(toPackageName(name));
}
}
/**
* Derive a <em>package name</em> for a resource. The package name
* returned by this method may not be a legal package name. This method
* returns null if the the resource name ends with a "/" (a directory)
* or the resource name does not contain a "/".
*/
public static String toPackageName(String name) {
int index = name.lastIndexOf('/');
if (index == -1 || index == name.length()-1) {
return "";
} else {
return name.substring(0, index).replace("/", ".");
}
}
/**
* Returns a resource name corresponding to the relative file path
* between {@code dir} and {@code file}. If the file is a directory
* then the name will end with a "/", except the top-level directory
* where the empty string is returned.
*/
public static String toResourceName(Path dir, Path file) {
String s = dir.relativize(file)
.toString()
.replace(File.separatorChar, '/');
if (s.length() > 0 && Files.isDirectory(file))
s += "/";
return s;
}
/**
* Returns a file path to a resource in a file tree. If the resource
* name has a trailing "/" then the file path will locate a directory.
* Returns {@code null} if the resource does not map to a file in the
* tree file.
*/
public static Path toFilePath(Path dir, String name) throws IOException {
boolean expectDirectory = name.endsWith("/");
if (expectDirectory) {
name = name.substring(0, name.length() - 1); // drop trailing "/"
}
Path path = toSafeFilePath(name);
if (path != null) {
Path file = dir.resolve(path);
try {
BasicFileAttributes attrs;
attrs = Files.readAttributes(file, BasicFileAttributes.class);
if (attrs.isDirectory()
|| (!attrs.isDirectory() && !expectDirectory))
return file;
} catch (NoSuchFileException ignore) { }
}
return null;
}
/**
* Map a resource name to a "safe" file path. Returns {@code null} if
* the resource name cannot be converted into a "safe" file path.
*
* Resource names with empty elements, or elements that are "." or ".."
* are rejected, as are resource names that translates to a file path
* with a root component.
*/
private static Path toSafeFilePath(String name) {
// scan elements of resource name
int next;
int off = 0;
while ((next = name.indexOf('/', off)) != -1) {
int len = next - off;
if (!mayTranslate(name, off, len)) {
return null;
}
off = next + 1;
}
int rem = name.length() - off;
if (!mayTranslate(name, off, rem)) {
return null;
}
// convert to file path
Path path;
if (File.separatorChar == '/') {
path = Paths.get(name);
} else {
// not allowed to embed file separators
if (name.contains(File.separator))
return null;
path = Paths.get(name.replace('/', File.separatorChar));
}
// file path not allowed to have root component
return (path.getRoot() == null) ? path : null;
}
/**
* Returns {@code true} if the element in a resource name is a candidate
* to translate to the element of a file path.
*/
private static boolean mayTranslate(String name, int off, int len) {
if (len <= 2) {
if (len == 0)
return false;
boolean starsWithDot = (name.charAt(off) == '.');
if (len == 1 && starsWithDot)
return false;
if (len == 2 && starsWithDot && (name.charAt(off+1) == '.'))
return false;
}
return true;
}
}

View File

@ -150,18 +150,21 @@ public class SystemModuleFinder implements ModuleFinder {
System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
ModuleDescriptor[] descriptors;
ModuleTarget[] targets;
ModuleHashes[] recordedHashes;
ModuleResolution[] moduleResolutions;
// fast loading of ModuleDescriptor of system modules
if (isFastPathSupported() && !disabled) {
descriptors = SystemModules.descriptors();
targets = SystemModules.targets();
recordedHashes = SystemModules.hashes();
moduleResolutions = SystemModules.moduleResolutions();
} else {
// if fast loading of ModuleDescriptors is disabled
// fallback to read module-info.class
descriptors = new ModuleDescriptor[n];
targets = new ModuleTarget[n];
recordedHashes = new ModuleHashes[n];
moduleResolutions = new ModuleResolution[n];
ImageReader imageReader = SystemImage.reader();
@ -171,6 +174,7 @@ public class SystemModuleFinder implements ModuleFinder {
ModuleInfo.Attributes attrs =
ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
descriptors[i] = attrs.descriptor();
targets[i] = attrs.target();
recordedHashes[i] = attrs.recordedHashes();
moduleResolutions[i] = attrs.moduleResolution();
}
@ -206,6 +210,7 @@ public class SystemModuleFinder implements ModuleFinder {
// create the ModuleReference
ModuleReference mref = toModuleReference(md,
targets[i],
recordedHashes[i],
hashSupplier(names[i]),
moduleResolutions[i]);
@ -233,6 +238,7 @@ public class SystemModuleFinder implements ModuleFinder {
}
private ModuleReference toModuleReference(ModuleDescriptor md,
ModuleTarget target,
ModuleHashes recordedHashes,
HashSupplier hasher,
ModuleResolution mres) {
@ -246,9 +252,14 @@ public class SystemModuleFinder implements ModuleFinder {
}
};
ModuleReference mref =
new ModuleReferenceImpl(md, uri, readerSupplier, null,
recordedHashes, hasher, mres);
ModuleReference mref = new ModuleReferenceImpl(md,
uri,
readerSupplier,
null,
target,
recordedHashes,
hasher,
mres);
// may need a reference to a patched module if --patch-module specified
mref = ModuleBootstrap.patcher().patchIfNeeded(mref);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, 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
@ -27,7 +27,7 @@ package jdk.internal.module;
import java.lang.module.ModuleDescriptor;
/*
/**
* SystemModules class will be generated at link time to create
* ModuleDescriptor for the system modules directly to improve
* the module descriptor reconstitution time.
@ -65,7 +65,7 @@ public final class SystemModules {
}
/**
* Returns a non-empty array of ModuleDescriptors in the run-time image.
* Returns a non-empty array of ModuleDescriptor objects in the run-time image.
*
* When running an exploded image it returns an empty array.
*/
@ -73,6 +73,15 @@ public final class SystemModules {
throw new InternalError("expected to be overridden at link time");
}
/**
* Returns a non-empty array of ModuleTarget objects in the run-time image.
*
* When running an exploded image it returns an empty array.
*/
public static ModuleTarget[] targets() {
throw new InternalError("expected to be overridden at link time");
}
/**
* Returns a non-empty array of ModuleHashes recorded in each module
* in the run-time image.

View File

@ -2508,7 +2508,7 @@ public class ClassReader {
}
/**
* Reads a CONSTANT_Pakcage_info item in {@code b}. This method is
* Reads a CONSTANT_Package_info item in {@code b}. This method is
* intended for {@link Attribute} sub slasses, and is normally not needed
* by class generators or adapters.</i>
*

View File

@ -31,9 +31,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import sun.security.action.GetPropertyAction;
/** Common utility routines used by both java.lang and
java.lang.reflect */
@ -104,39 +102,40 @@ public class Reflection {
int modifiers)
throws IllegalAccessException
{
if (currentClass == null || memberClass == null) {
throw new InternalError();
}
if (!verifyMemberAccess(currentClass, memberClass, targetClass, modifiers)) {
throwIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
throw newIllegalAccessException(currentClass, memberClass, targetClass, modifiers);
}
}
/**
* Verify access to a member, returning {@code false} if no access
* Verify access to a member and return {@code true} if it is granted.
*
* @param currentClass the class performing the access
* @param memberClass the declaring class of the member being accessed
* @param targetClass the class of target object if accessing instance
* field or method;
* or the declaring class if accessing constructor;
* or null if accessing static field or method
* @param modifiers the member's access modifiers
* @return {@code true} if access to member is granted
*/
public static boolean verifyMemberAccess(Class<?> currentClass,
Class<?> memberClass,
Class<?> targetClass,
int modifiers)
{
// Verify that currentClass can access a field, method, or
// constructor of memberClass, where that member's access bits are
// "modifiers".
boolean gotIsSameClassPackage = false;
boolean isSameClassPackage = false;
if (currentClass == memberClass) {
// Always succeeds
return true;
}
if (!verifyModuleAccess(currentClass, memberClass)) {
if (!verifyModuleAccess(currentClass.getModule(), memberClass)) {
return false;
}
boolean gotIsSameClassPackage = false;
boolean isSameClassPackage = false;
if (!Modifier.isPublic(getClassAccessFlags(memberClass))) {
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
gotIsSameClassPackage = true;
@ -196,31 +195,20 @@ public class Reflection {
}
/**
* Returns {@code true} if memberClass's's module exports memberClass's
* package to currentClass's module.
* Returns {@code true} if memberClass's module exports memberClass's
* package to currentModule.
*/
public static boolean verifyModuleAccess(Class<?> currentClass,
Class<?> memberClass) {
return verifyModuleAccess(currentClass.getModule(), memberClass);
}
public static boolean verifyModuleAccess(Module currentModule, Class<?> memberClass) {
Module memberModule = memberClass.getModule();
// module may be null during startup (initLevel 0)
if (currentModule == memberModule)
return true; // same module (named or unnamed)
String pkg = memberClass.getPackageName();
boolean allowed = memberModule.isExported(pkg, currentModule);
if (allowed && memberModule.isNamed() && printStackTraceWhenAccessSucceeds()) {
if (!SharedSecrets.getJavaLangReflectModuleAccess()
.isStaticallyExported(memberModule, pkg, currentModule)) {
String msg = currentModule + " allowed access to member of " + memberClass;
new Exception(msg).printStackTrace(System.err);
}
if (currentModule == memberModule) {
// same module (named or unnamed) or both null if called
// before module system is initialized, which means we are
// dealing with java.base only.
return true;
} else {
String pkg = memberClass.getPackageName();
return memberModule.isExported(pkg, currentModule);
}
return allowed;
}
/**
@ -344,46 +332,14 @@ public class Reflection {
return false;
}
// true to print a stack trace when access fails
private static volatile boolean printStackWhenAccessFails;
// true to print a stack trace when access succeeds
private static volatile boolean printStackWhenAccessSucceeds;
// true if printStack* values are initialized
private static volatile boolean printStackPropertiesSet;
private static void ensurePrintStackPropertiesSet() {
if (!printStackPropertiesSet && VM.initLevel() >= 1) {
String s = GetPropertyAction.privilegedGetProperty(
"sun.reflect.debugModuleAccessChecks");
if (s != null) {
printStackWhenAccessFails = !s.equalsIgnoreCase("false");
printStackWhenAccessSucceeds = s.equalsIgnoreCase("access");
}
printStackPropertiesSet = true;
}
}
public static boolean printStackTraceWhenAccessFails() {
ensurePrintStackPropertiesSet();
return printStackWhenAccessFails;
}
public static boolean printStackTraceWhenAccessSucceeds() {
ensurePrintStackPropertiesSet();
return printStackWhenAccessSucceeds;
}
/**
* Throws IllegalAccessException with the an exception message based on
* Returns an IllegalAccessException with an exception message based on
* the access that is denied.
*/
private static void throwIllegalAccessException(Class<?> currentClass,
Class<?> memberClass,
Object target,
int modifiers)
public static IllegalAccessException newIllegalAccessException(Class<?> currentClass,
Class<?> memberClass,
Class<?> targetClass,
int modifiers)
throws IllegalAccessException
{
String currentSuffix = "";
@ -411,20 +367,6 @@ public class Reflection {
if (m2.isNamed()) msg += " to " + m1;
}
throwIllegalAccessException(msg);
}
/**
* Throws IllegalAccessException with the given exception message.
*/
public static void throwIllegalAccessException(String msg)
throws IllegalAccessException
{
IllegalAccessException e = new IllegalAccessException(msg);
ensurePrintStackPropertiesSet();
if (printStackWhenAccessFails) {
e.printStackTrace(System.err);
}
throw e;
return new IllegalAccessException(msg);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2017, 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
@ -44,6 +44,7 @@ import java.security.PrivilegedAction;
import java.util.Objects;
import java.util.Properties;
import jdk.internal.misc.VM;
import sun.reflect.misc.ReflectUtil;
import sun.security.action.GetPropertyAction;
@ -585,17 +586,10 @@ public class ReflectionFactory {
private static void checkInitted() {
if (initted) return;
// Tests to ensure the system properties table is fully
// initialized. This is needed because reflection code is
// called very early in the initialization process (before
// command-line arguments have been parsed and therefore
// these user-settable properties installed.) We assume that
// if System.out is non-null then the System class has been
// fully initialized and that the bulk of the startup code
// has been run.
if (System.out == null) {
// java.lang.System not yet fully initialized
// Defer initialization until module system is initialized so as
// to avoid inflation and spinning bytecode in unnamed modules
// during early startup.
if (!VM.isModuleSystemInited()) {
return;
}

View File

@ -125,10 +125,9 @@ module java.base {
jdk.jlink;
exports jdk.internal.loader to
java.instrument,
java.logging,
jdk.jlink;
java.logging;
exports jdk.internal.jmod to
jdk.compiler,
jdk.compiler, // reflective dependency
jdk.jlink;
exports jdk.internal.logger to
java.logging;
@ -140,10 +139,7 @@ module java.base {
exports jdk.internal.org.objectweb.asm.tree to
jdk.jlink;
exports jdk.internal.org.objectweb.asm.util to
jdk.jlink,
jdk.scripting.nashorn;
exports jdk.internal.org.objectweb.asm.tree.analysis to
jdk.jlink;
exports jdk.internal.org.objectweb.asm.commons to
jdk.scripting.nashorn;
exports jdk.internal.org.objectweb.asm.signature to
@ -157,7 +153,6 @@ module java.base {
jdk.jlink;
exports jdk.internal.misc to
java.desktop,
jdk.incubator.httpclient,
java.logging,
java.management,
java.naming,
@ -166,8 +161,8 @@ module java.base {
java.sql,
java.xml,
jdk.charsets,
jdk.compiler,
jdk.jartool,
jdk.compiler, // reflective dependency
jdk.incubator.httpclient,
jdk.jdeps,
jdk.jlink,
jdk.jshell,
@ -210,11 +205,10 @@ module java.base {
jdk.naming.dns;
exports sun.net.util to
java.desktop,
jdk.jconsole,
jdk.naming.dns;
jdk.jconsole;
exports sun.net.www to
jdk.incubator.httpclient,
java.desktop,
jdk.incubator.httpclient,
jdk.jartool;
exports sun.net.www.protocol.http to
java.security.jgss;

View File

@ -85,6 +85,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import jdk.internal.misc.VM;
import jdk.internal.module.IllegalAccessLogger;
import jdk.internal.module.Modules;
@ -428,14 +429,20 @@ public final class LauncherHelper {
abort(null, "java.launcher.jar.error3", jarname);
}
// Add-Exports and Add-Opens to break encapsulation
// Add-Exports and Add-Opens to allow illegal access
String exports = mainAttrs.getValue(ADD_EXPORTS);
if (exports != null) {
addExportsOrOpens(exports, false);
String warn = getLocalizedMessage("java.launcher.permitaccess.warning",
jarname, ADD_EXPORTS);
System.err.println(warn);
addExportsOrOpens(exports, false, ADD_EXPORTS);
}
String opens = mainAttrs.getValue(ADD_OPENS);
if (opens != null) {
addExportsOrOpens(opens, true);
String warn = getLocalizedMessage("java.launcher.permitaccess.warning",
jarname, ADD_OPENS);
System.err.println(warn);
addExportsOrOpens(opens, true, ADD_OPENS);
}
/*
@ -460,23 +467,36 @@ public final class LauncherHelper {
* Process the Add-Exports or Add-Opens value. The value is
* {@code <module>/<package> ( <module>/<package>)*}.
*/
static void addExportsOrOpens(String value, boolean open) {
static void addExportsOrOpens(String value, boolean open, String how) {
IllegalAccessLogger.Builder builder;
IllegalAccessLogger logger = IllegalAccessLogger.illegalAccessLogger();
if (logger == null) {
builder = new IllegalAccessLogger.Builder();
} else {
builder = logger.toBuilder();
}
for (String moduleAndPackage : value.split(" ")) {
String[] s = moduleAndPackage.trim().split("/");
if (s.length == 2) {
String mn = s[0];
String pn = s[1];
Layer.boot().findModule(mn).ifPresent(m -> {
if (m.getDescriptor().packages().contains(pn)) {
if (open) {
builder.logAccessToOpenPackage(m, pn, how);
Modules.addOpensToAllUnnamed(m, pn);
} else {
builder.logAccessToExportedPackage(m, pn, how);
Modules.addExportsToAllUnnamed(m, pn);
}
}
});
}
}
IllegalAccessLogger.setIllegalAccessLogger(builder.build());
}
// From src/share/bin/java.c:

View File

@ -24,12 +24,15 @@
#
# Translators please note do not translate the options themselves
java.launcher.opt.header = Usage: {0} [options] class [args...]\n\
\ (to execute a class)\n or {0} [options] -jar jarfile [args...]\n\
java.launcher.opt.header = Usage: {0} [options] <mainclass> [args...]\n\
\ (to execute a class)\n or {0} [options] -jar <jarfile> [args...]\n\
\ (to execute a jar file)\n\
\ or {0} [options] -p <modulepath> -m <modulename>[/<mainclass>] [args...]\n\
\ or {0} [options] -m <module>[/<mainclass>] [args...]\n\
\ {0} [options] --module <module>[/<mainclass>] [args...]\n\
\ (to execute the main class in a module)\n\n\
where options include:\n\n
\ Arguments following the main class, -jar <jarfile>, -m or --module\n\
\ <module>/<mainclass> are passed as the arguments to main class.\n\n\
\ where options include:\n\n
java.launcher.opt.datamodel =\ -d{0}\t Deprecated, will be removed in a future release\n
java.launcher.opt.vmselect =\ {0}\t to select the "{1}" VM\n
@ -49,10 +52,6 @@ java.launcher.opt.footer =\ -cp <class search path of directories and zip
\ A {0} separated list of directories, each directory\n\
\ is a directory of modules that replace upgradeable\n\
\ modules in the runtime image\n\
\ -m <module>[/<mainclass>]\n\
\ --module <modulename>[/<mainclass>]\n\
\ the initial module to resolve, and the name of the main class\n\
\ to execute if not specified by the module\n\
\ --add-modules <modulename>[,<modulename>...]\n\
\ root modules to resolve in addition to the initial module.\n\
\ <modulename> can also be ALL-DEFAULT, ALL-SYSTEM,\n\
@ -129,7 +128,7 @@ java.launcher.X.usage=\n\
\ -Xms<size> set initial Java heap size\n\
\ -Xmx<size> set maximum Java heap size\n\
\ -Xnoclassgc disable class garbage collection\n\
\ -Xprof output cpu profiling data\n\
\ -Xprof output cpu profiling data (deprecated)\n\
\ -Xrs reduce use of OS signals by Java/VM (see documentation)\n\
\ -Xshare:auto use shared class data if possible (default)\n\
\ -Xshare:off do not attempt to use shared class data\n\
@ -157,6 +156,10 @@ java.launcher.X.usage=\n\
\ --add-opens <module>/<package>=<target-module>(,<target-module>)*\n\
\ updates <module> to open <package> to\n\
\ <target-module>, regardless of module declaration.\n\
\ --permit-illegal-access\n\
\ permit illegal access to members of types in named modules\n\
\ by code in unnamed modules. This compatibility option will\n\
\ be removed in the next release.\n\
\ --disable-@files disable further argument file expansion\n\
\ --patch-module <module>=<file>({0}<file>)*\n\
\ Override or augment a module with classes and resources\n\
@ -208,4 +211,6 @@ java.launcher.module.error2=\
java.launcher.module.error3=\
Error: Unable to load main class {0} from module {1}\n\
\t{2}
java.launcher.permitaccess.warning=\
WARNING: Main manifest of {0} contains {1} attribute to permit illegal access

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2017, 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
@ -26,8 +26,6 @@
package sun.net.www.protocol.jrt;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FilePermission;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
@ -44,7 +42,6 @@ import jdk.internal.loader.URLClassPath;
import jdk.internal.loader.Resource;
import sun.net.www.ParseUtil;
import sun.net.www.URLConnection;
import sun.security.action.GetPropertyAction;
/**
* URLConnection implementation that can be used to connect to resources
@ -66,9 +63,6 @@ public class JavaRuntimeURLConnection extends URLConnection {
// the Resource when connected
private volatile Resource resource;
// the permission to access resources in the runtime image, created lazily
private static volatile Permission permission;
JavaRuntimeURLConnection(URL url) throws IOException {
super(url);
String path = url.getPath();
@ -164,14 +158,8 @@ public class JavaRuntimeURLConnection extends URLConnection {
}
@Override
public Permission getPermission() throws IOException {
Permission p = permission;
if (p == null) {
String home = GetPropertyAction.privilegedGetProperty("java.home");
p = new FilePermission(home + File.separator + "-", "read");
permission = p;
}
return p;
public Permission getPermission() {
return new RuntimePermission("accessSystemModules");
}
/**

View File

@ -72,23 +72,9 @@ getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)
return utfStr;
}
// The existence or signature of this method is not guaranteed since it
// supports a private method. This method will be changed in 1.7.
JNIEXPORT jclass JNICALL
Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,
jobject loader,
jstring name,
jbyteArray data,
jint offset,
jint length,
jobject pd)
{
return Java_java_lang_ClassLoader_defineClass1(env, loader, name, data, offset,
length, pd, NULL);
}
JNIEXPORT jclass JNICALL
Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,
jclass cls,
jobject loader,
jstring name,
jbyteArray data,
@ -163,6 +149,7 @@ Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,
JNIEXPORT jclass JNICALL
Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,
jclass cls,
jobject loader,
jstring name,
jobject data,

View File

@ -73,30 +73,32 @@ Java_java_lang_reflect_Module_defineModule0(JNIEnv *env, jclass cls, jobject mod
jstring location, jobjectArray packages)
{
char** pkgs = NULL;
jsize idx;
jsize num_packages = (*env)->GetArrayLength(env, packages);
if (num_packages != 0 && (pkgs = calloc(num_packages, sizeof(char*))) == NULL) {
JNU_ThrowOutOfMemoryError(env, NULL);
return;
} else {
int valid = 1;
} else if ((*env)->EnsureLocalCapacity(env, (jint)num_packages) == 0) {
jboolean failed = JNI_FALSE;
int idx;
for (idx = 0; idx < num_packages; idx++) {
jstring pkg = (*env)->GetObjectArrayElement(env, packages, idx);
pkgs[idx] = GetInternalPackageName(env, pkg, NULL, 0);
if (pkgs[idx] == NULL) {
valid = 0;
char* name = GetInternalPackageName(env, pkg, NULL, 0);
if (name != NULL) {
pkgs[idx] = name;
} else {
failed = JNI_TRUE;
break;
}
}
if (valid != 0) {
if (!failed) {
JVM_DefineModule(env, module, is_open, version, location,
(const char* const*)pkgs, num_packages);
(const char* const*)pkgs, num_packages);
}
}
if (num_packages > 0) {
int idx;
for (idx = 0; idx < num_packages; idx++) {
if (pkgs[idx] != NULL) {
free(pkgs[idx]);

View File

@ -37,7 +37,7 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.*;
public abstract class AquaButtonBorder extends AquaBorder implements Border, UIResource {
public static final RecyclableSingleton<Dynamic> fDynamic = new RecyclableSingletonFromDefaultConstructor<Dynamic>(Dynamic.class);
private static final RecyclableSingleton<Dynamic> fDynamic = new RecyclableSingletonFromDefaultConstructor<Dynamic>(Dynamic.class);
public static AquaButtonBorder getDynamicButtonBorder() {
return fDynamic.get();
}
@ -47,12 +47,12 @@ public abstract class AquaButtonBorder extends AquaBorder implements Border, UIR
return fToggle.get();
}
public static final RecyclableSingleton<Toolbar> fToolBar = new RecyclableSingletonFromDefaultConstructor<Toolbar>(Toolbar.class);
private static final RecyclableSingleton<Toolbar> fToolBar = new RecyclableSingletonFromDefaultConstructor<Toolbar>(Toolbar.class);
public static Border getToolBarButtonBorder() {
return fToolBar.get();
}
public static final RecyclableSingleton<Named> fBevel = new RecyclableSingleton<Named>() {
private static final RecyclableSingleton<Named> fBevel = new RecyclableSingleton<Named>() {
protected Named getInstance() {
return new Named(Widget.BUTTON_BEVEL, new SizeDescriptor(new SizeVariant().alterMargins(2, 4, 2, 4)));
}

View File

@ -34,8 +34,8 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.*;
public class AquaButtonCheckBoxUI extends AquaButtonLabeledUI {
protected static final RecyclableSingleton<AquaButtonCheckBoxUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaButtonCheckBoxUI>(AquaButtonCheckBoxUI.class);
protected static final RecyclableSingleton<ImageIcon> sizingIcon = new RecyclableSingleton<ImageIcon>() {
private static final RecyclableSingleton<AquaButtonCheckBoxUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaButtonCheckBoxUI>(AquaButtonCheckBoxUI.class);
private static final RecyclableSingleton<ImageIcon> sizingIcon = new RecyclableSingleton<ImageIcon>() {
protected ImageIcon getInstance() {
return new ImageIcon(AquaNativeResources.getRadioButtonSizerImage());
}

View File

@ -138,7 +138,7 @@ public class AquaButtonExtendedTypes {
return typeDefinitions.get().get(name);
}
protected static final RecyclableSingleton<Map<String, TypeSpecifier>> typeDefinitions = new RecyclableSingleton<Map<String, TypeSpecifier>>() {
private static final RecyclableSingleton<Map<String, TypeSpecifier>> typeDefinitions = new RecyclableSingleton<Map<String, TypeSpecifier>>() {
protected Map<String, TypeSpecifier> getInstance() {
return getAllTypes();
}

View File

@ -42,9 +42,9 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.RecyclableSingleton;
public abstract class AquaButtonLabeledUI extends AquaButtonToggleUI implements Sizeable {
protected static RecyclableSizingIcon regularIcon = new RecyclableSizingIcon(18);
protected static RecyclableSizingIcon smallIcon = new RecyclableSizingIcon(16);
protected static RecyclableSizingIcon miniIcon = new RecyclableSizingIcon(14);
private static final RecyclableSizingIcon regularIcon = new RecyclableSizingIcon(18);
private static final RecyclableSizingIcon smallIcon = new RecyclableSizingIcon(16);
private static final RecyclableSizingIcon miniIcon = new RecyclableSizingIcon(14);
protected static class RecyclableSizingIcon extends RecyclableSingleton<Icon> {
final int iconSize;

View File

@ -34,8 +34,8 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.*;
public class AquaButtonRadioUI extends AquaButtonLabeledUI {
protected static final RecyclableSingleton<AquaButtonRadioUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaButtonRadioUI>(AquaButtonRadioUI.class);
protected static final RecyclableSingleton<ImageIcon> sizingIcon = new RecyclableSingleton<ImageIcon>() {
private static final RecyclableSingleton<AquaButtonRadioUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaButtonRadioUI>(AquaButtonRadioUI.class);
private static final RecyclableSingleton<ImageIcon> sizingIcon = new RecyclableSingleton<ImageIcon>() {
protected ImageIcon getInstance() {
return new ImageIcon(AquaNativeResources.getRadioButtonSizerImage());
}

View File

@ -32,7 +32,7 @@ import com.apple.laf.AquaUtils.*;
public class AquaButtonToggleUI extends AquaButtonUI {
// Create PLAF
static final RecyclableSingleton<AquaButtonToggleUI> aquaToggleButtonUI = new RecyclableSingletonFromDefaultConstructor<AquaButtonToggleUI>(AquaButtonToggleUI.class);
private static final RecyclableSingleton<AquaButtonToggleUI> aquaToggleButtonUI = new RecyclableSingletonFromDefaultConstructor<AquaButtonToggleUI>(AquaButtonToggleUI.class);
public static ComponentUI createUI(final JComponent b) {
return aquaToggleButtonUI.get();
}

View File

@ -48,7 +48,7 @@ public class AquaButtonUI extends BasicButtonUI implements Sizeable {
private static final String BUTTON_TYPE = "JButton.buttonType";
private static final String SEGMENTED_BUTTON_POSITION = "JButton.segmentPosition";
protected static final RecyclableSingleton<AquaButtonUI> buttonUI = new RecyclableSingletonFromDefaultConstructor<AquaButtonUI>(AquaButtonUI.class);
private static final RecyclableSingleton<AquaButtonUI> buttonUI = new RecyclableSingletonFromDefaultConstructor<AquaButtonUI>(AquaButtonUI.class);
public static ComponentUI createUI(final JComponent c) {
return buttonUI.get();
}
@ -462,7 +462,7 @@ public class AquaButtonUI extends BasicButtonUI implements Sizeable {
return d;
}
static final RecyclableSingleton<AquaHierarchyButtonListener> fHierListener = new RecyclableSingletonFromDefaultConstructor<AquaHierarchyButtonListener>(AquaHierarchyButtonListener.class);
private static final RecyclableSingleton<AquaHierarchyButtonListener> fHierListener = new RecyclableSingletonFromDefaultConstructor<AquaHierarchyButtonListener>(AquaHierarchyButtonListener.class);
static AquaHierarchyButtonListener getAquaHierarchyButtonListener() {
return fHierListener.get();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2017, 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
@ -25,18 +25,29 @@
package com.apple.laf;
import java.awt.*;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.*;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.Box;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicComboPopup;
import sun.lwawt.macosx.CPlatformWindow;
@SuppressWarnings("serial") // Superclass is not serializable across versions
class AquaComboBoxPopup extends BasicComboPopup {
final class AquaComboBoxPopup extends BasicComboPopup {
static final int FOCUS_RING_PAD_LEFT = 6;
static final int FOCUS_RING_PAD_RIGHT = 6;
static final int FOCUS_RING_PAD_BOTTOM = 5;
@ -201,9 +212,6 @@ class AquaComboBoxPopup extends BasicComboPopup {
//System.err.println("GetBestScreenBounds p: "+ p.x + ", " + p.y);
final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
final GraphicsDevice[] gs = ge.getScreenDevices();
//System.err.println(" gs.length = " + gs.length);
final Rectangle comboBoxBounds = comboBox.getBounds();
for (final GraphicsDevice gd : gs) {
final GraphicsConfiguration[] gc = gd.getConfigurations();
for (final GraphicsConfiguration element0 : gc) {
@ -215,15 +223,14 @@ class AquaComboBoxPopup extends BasicComboPopup {
}
// Hmm. Origin's off screen, but is any part on?
final Rectangle comboBoxBounds = comboBox.getBounds();
comboBoxBounds.setLocation(p);
for (final GraphicsDevice gd : gs) {
final GraphicsConfiguration[] gc = gd.getConfigurations();
for (final GraphicsConfiguration element0 : gc) {
final Rectangle gcBounds = element0.getBounds();
if (gcBounds.intersects(comboBoxBounds)) {
if (gcBounds.contains(p)) {
return getAvailableScreenArea(gcBounds, element0);
}
return getAvailableScreenArea(gcBounds, element0);
}
}
}
@ -234,8 +241,15 @@ class AquaComboBoxPopup extends BasicComboPopup {
private Rectangle getAvailableScreenArea(Rectangle bounds,
GraphicsConfiguration gc) {
Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
return new Rectangle(0, insets.top, bounds.width,
bounds.height - insets.top);
return new Rectangle(bounds.x + insets.left, bounds.y + insets.top,
bounds.width - insets.left - insets.right,
bounds.height - insets.top - insets.bottom);
}
private int getComboBoxEdge(int py, boolean bottom) {
int offset = bottom ? 9 : -9;
// if py is less than new y we have a clipped combo, so leave it alone.
return Math.min((py / 2) + offset, py);
}
@Override
@ -246,7 +260,7 @@ class AquaComboBoxPopup extends BasicComboPopup {
if (isPopdown && !isTableCellEditor) {
// place the popup just below the button, which is
// near the center of a large combo box
py = Math.min((py / 2) + 9, py); // if py is less than new y we have a clipped combo, so leave it alone.
py = getComboBoxEdge(py, true);
}
// px & py are relative to the combo box
@ -291,8 +305,12 @@ class AquaComboBoxPopup extends BasicComboPopup {
// Make sure it's all on the screen - shift it by the amount it's off
p.x += px;
p.y += py; // Screen location of px & py
if (p.x < scrBounds.x) px -= (p.x + scrBounds.x);
if (p.y < scrBounds.y) py -= (p.y + scrBounds.y);
if (p.x < scrBounds.x) {
px = px + (scrBounds.x - p.x);
}
if (p.y < scrBounds.y) {
py = py + (scrBounds.y - p.y);
}
final Point top = new Point(0, 0);
SwingUtilities.convertPointFromScreen(top, comboBox);
@ -324,22 +342,27 @@ class AquaComboBoxPopup extends BasicComboPopup {
}
final Rectangle r = new Rectangle(px, py, pw, ph);
if (py + ph > scrBounds.y + scrBounds.height) {
if (ph <= -scrBounds.y ) {
// popup goes above
r.y = -ph ;
} else {
// a full screen height popup
r.y = scrBounds.y + Math.max(0, (scrBounds.height - ph) / 2 );
r.height = Math.min(scrBounds.height, ph);
}
if (r.y + r.height < top.y + scrBounds.y + scrBounds.height) {
return r;
}
// Check whether it goes below the bottom of the screen, if so flip it
int newY = getComboBoxEdge(comboBoxBounds.height, false) - ph - comboBoxInsets.top;
if (newY > top.y + scrBounds.y) {
return new Rectangle(px, newY, r.width, r.height);
} else {
// There are no place at top, move popup to the center of the screen
r.y = top.y + scrBounds.y + Math.max(0, (scrBounds.height - ph) / 2 );
r.height = Math.min(scrBounds.height, ph);
}
return r;
}
// The one to use when itemCount <= maxRowCount. Size never adjusts for arrows
// We want it positioned so the selected item is right above the combo box
protected Rectangle computePopupBoundsForMenu(final int px, final int py, final int pw, final int ph, final int itemCount, final Rectangle scrBounds) {
protected Rectangle computePopupBoundsForMenu(final int px, final int py,
final int pw, final int ph,
final int itemCount,
final Rectangle scrBounds) {
//System.err.println("computePopupBoundsForMenu: " + px + "," + py + " " + pw + "," + ph);
//System.err.println("itemCount: " +itemCount +" src: "+ scrBounds);
int elementSize = 0; //kDefaultItemSize;

View File

@ -594,7 +594,7 @@ public class AquaComboBoxUI extends BasicComboBoxUI implements Sizeable {
}
@SuppressWarnings("unchecked")
static final RecyclableSingleton<ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>> APPLICATOR = new
private static final RecyclableSingleton<ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>> APPLICATOR = new
RecyclableSingleton<ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI>>() {
@Override
protected ClientPropertyApplicator<JComboBox<?>, AquaComboBoxUI> getInstance() {

View File

@ -75,7 +75,7 @@ class AquaFileView extends FileView {
private static native int getNativeLSInfo(final byte[] pathBytes, final boolean isDirectory);
private static native String getNativePathForResolvedAlias(final byte[] absolutePath, final boolean isDirectory);
static final RecyclableSingleton<String> machineName = new RecyclableSingleton<String>() {
private static final RecyclableSingleton<String> machineName = new RecyclableSingleton<String>() {
@Override
protected String getInstance() {
return getNativeMachineName();

View File

@ -35,17 +35,17 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public abstract class AquaGroupBorder extends AquaBorder {
static final RecyclableSingletonFromDefaultConstructor<? extends Border> tabbedPaneGroupBorder = new RecyclableSingletonFromDefaultConstructor<TabbedPane>(TabbedPane.class);
private static final RecyclableSingletonFromDefaultConstructor<? extends Border> tabbedPaneGroupBorder = new RecyclableSingletonFromDefaultConstructor<TabbedPane>(TabbedPane.class);
public static Border getTabbedPaneGroupBorder() {
return tabbedPaneGroupBorder.get();
}
static final RecyclableSingletonFromDefaultConstructor<? extends Border> titleBorderGroupBorder = new RecyclableSingletonFromDefaultConstructor<Titled>(Titled.class);
private static final RecyclableSingletonFromDefaultConstructor<? extends Border> titleBorderGroupBorder = new RecyclableSingletonFromDefaultConstructor<Titled>(Titled.class);
public static Border getBorderForTitledBorder() {
return titleBorderGroupBorder.get();
}
static final RecyclableSingletonFromDefaultConstructor<? extends Border> titlelessGroupBorder = new RecyclableSingletonFromDefaultConstructor<Titleless>(Titleless.class);
private static final RecyclableSingletonFromDefaultConstructor<? extends Border> titlelessGroupBorder = new RecyclableSingletonFromDefaultConstructor<Titleless>(Titleless.class);
public static Border getTitlelessBorder() {
return titlelessGroupBorder.get();
}

View File

@ -37,7 +37,7 @@ import javax.swing.text.*;
import com.apple.laf.AquaUtils.RecyclableSingleton;
public class AquaHighlighter extends DefaultHighlighter implements UIResource {
static final RecyclableSingleton<LayerPainter> instance = new RecyclableSingleton<LayerPainter>() {
private static final RecyclableSingleton<LayerPainter> instance = new RecyclableSingleton<LayerPainter>() {
protected LayerPainter getInstance() {
return new AquaHighlightPainter(null);
}

View File

@ -240,14 +240,14 @@ public class AquaImageFactory {
}
}
protected static final NamedImageSingleton northArrow = new NamedImageSingleton("NSMenuScrollUp");
protected static final IconUIResourceSingleton northArrowIcon = new IconUIResourceSingleton(northArrow);
protected static final NamedImageSingleton southArrow = new NamedImageSingleton("NSMenuScrollDown");
protected static final IconUIResourceSingleton southArrowIcon = new IconUIResourceSingleton(southArrow);
protected static final NamedImageSingleton westArrow = new NamedImageSingleton("NSMenuSubmenuLeft");
protected static final IconUIResourceSingleton westArrowIcon = new IconUIResourceSingleton(westArrow);
protected static final NamedImageSingleton eastArrow = new NamedImageSingleton("NSMenuSubmenu");
protected static final IconUIResourceSingleton eastArrowIcon = new IconUIResourceSingleton(eastArrow);
private static final NamedImageSingleton northArrow = new NamedImageSingleton("NSMenuScrollUp");
private static final IconUIResourceSingleton northArrowIcon = new IconUIResourceSingleton(northArrow);
private static final NamedImageSingleton southArrow = new NamedImageSingleton("NSMenuScrollDown");
private static final IconUIResourceSingleton southArrowIcon = new IconUIResourceSingleton(southArrow);
private static final NamedImageSingleton westArrow = new NamedImageSingleton("NSMenuSubmenuLeft");
private static final IconUIResourceSingleton westArrowIcon = new IconUIResourceSingleton(westArrow);
private static final NamedImageSingleton eastArrow = new NamedImageSingleton("NSMenuSubmenu");
private static final IconUIResourceSingleton eastArrowIcon = new IconUIResourceSingleton(eastArrow);
static Image getArrowImageForDirection(final int direction) {
switch(direction) {

View File

@ -55,7 +55,7 @@ public class AquaInternalFrameBorder implements Border, UIResource {
private static final int kContentTester = 100; // For getting region insets
static final RecyclableSingleton<AquaInternalFrameBorder> documentWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
private static final RecyclableSingleton<AquaInternalFrameBorder> documentWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
protected AquaInternalFrameBorder getInstance() {
return new AquaInternalFrameBorder(WindowType.DOCUMENT);
}
@ -64,7 +64,7 @@ public class AquaInternalFrameBorder implements Border, UIResource {
return documentWindowFrame.get();
}
static final RecyclableSingleton<AquaInternalFrameBorder> utilityWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
private static final RecyclableSingleton<AquaInternalFrameBorder> utilityWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
protected AquaInternalFrameBorder getInstance() {
return new AquaInternalFrameBorder(WindowType.UTILITY);
}
@ -73,7 +73,7 @@ public class AquaInternalFrameBorder implements Border, UIResource {
return utilityWindowFrame.get();
}
static final RecyclableSingleton<AquaInternalFrameBorder> dialogWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
private static final RecyclableSingleton<AquaInternalFrameBorder> dialogWindowFrame = new RecyclableSingleton<AquaInternalFrameBorder>() {
protected AquaInternalFrameBorder getInstance() {
return new AquaInternalFrameBorder(WindowType.DOCUMENT);
}

View File

@ -147,7 +147,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
southPane = c;
}
static final RecyclableSingleton<Icon> closeIcon = new RecyclableSingleton<Icon>() {
private static final RecyclableSingleton<Icon> closeIcon = new RecyclableSingleton<Icon>() {
@Override
protected Icon getInstance() {
return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_CLOSE_BOX);
@ -157,7 +157,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
return closeIcon.get();
}
static final RecyclableSingleton<Icon> minimizeIcon = new RecyclableSingleton<Icon>() {
private static final RecyclableSingleton<Icon> minimizeIcon = new RecyclableSingleton<Icon>() {
@Override
protected Icon getInstance() {
return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_COLLAPSE_BOX);
@ -167,7 +167,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
return minimizeIcon.get();
}
static final RecyclableSingleton<Icon> zoomIcon = new RecyclableSingleton<Icon>() {
private static final RecyclableSingleton<Icon> zoomIcon = new RecyclableSingleton<Icon>() {
@Override
protected Icon getInstance() {
return new AquaInternalFrameButtonIcon(Widget.TITLE_BAR_ZOOM_BOX);
@ -738,7 +738,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
}
} // end class PaletteListener
static final InternalFrameShadow documentWindowShadow = new InternalFrameShadow() {
private static final InternalFrameShadow documentWindowShadow = new InternalFrameShadow() {
@Override
Border getForegroundShadowBorder() {
return new AquaUtils.SlicedShadowBorder(new Painter() {
@ -778,7 +778,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
}
};
static final InternalFrameShadow paletteWindowShadow = new InternalFrameShadow() {
private static final InternalFrameShadow paletteWindowShadow = new InternalFrameShadow() {
@Override
Border getForegroundShadowBorder() {
return new AquaUtils.SlicedShadowBorder(new Painter() {
@ -834,7 +834,7 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo
}
}
static final RecyclableSingleton<Icon> RESIZE_ICON = new RecyclableSingleton<Icon>() {
private static final RecyclableSingleton<Icon> RESIZE_ICON = new RecyclableSingleton<Icon>() {
@Override
protected Icon getInstance() {
return new AquaIcon.ScalingJRSUIIcon(11, 11) {

View File

@ -37,7 +37,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaKeyBindings {
static final RecyclableSingleton<AquaKeyBindings> instance = new RecyclableSingletonFromDefaultConstructor<AquaKeyBindings>(AquaKeyBindings.class);
private static final RecyclableSingleton<AquaKeyBindings> instance = new RecyclableSingletonFromDefaultConstructor<AquaKeyBindings>(AquaKeyBindings.class);
static AquaKeyBindings instance() {
return instance.get();
}

View File

@ -37,7 +37,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaLabelUI extends BasicLabelUI {
protected static final RecyclableSingleton<AquaLabelUI> aquaLabelUI = new RecyclableSingletonFromDefaultConstructor<AquaLabelUI>(AquaLabelUI.class);
private static final RecyclableSingleton<AquaLabelUI> aquaLabelUI = new RecyclableSingletonFromDefaultConstructor<AquaLabelUI>(AquaLabelUI.class);
public static ComponentUI createUI(final JComponent c) {
return aquaLabelUI.get();

View File

@ -125,7 +125,7 @@ public class AquaMenuPainter {
return buf.toString();
}
static final RecyclableSingleton<AquaMenuPainter> sPainter = new RecyclableSingletonFromDefaultConstructor<AquaMenuPainter>(AquaMenuPainter.class);
private static final RecyclableSingleton<AquaMenuPainter> sPainter = new RecyclableSingletonFromDefaultConstructor<AquaMenuPainter>(AquaMenuPainter.class);
static AquaMenuPainter instance() {
return sPainter.get();
}
@ -139,9 +139,9 @@ public class AquaMenuPainter {
protected Border getInstance() { return UIManager.getBorder(borderName); }
}
protected final RecyclableBorder menuBarPainter = new RecyclableBorder("MenuBar.backgroundPainter");
protected final RecyclableBorder selectedMenuBarItemPainter = new RecyclableBorder("MenuBar.selectedBackgroundPainter");
protected final RecyclableBorder selectedMenuItemPainter = new RecyclableBorder("MenuItem.selectedBackgroundPainter");
private static final RecyclableBorder menuBarPainter = new RecyclableBorder("MenuBar.backgroundPainter");
private static final RecyclableBorder selectedMenuBarItemPainter = new RecyclableBorder("MenuBar.selectedBackgroundPainter");
private static final RecyclableBorder selectedMenuItemPainter = new RecyclableBorder("MenuItem.selectedBackgroundPainter");
public void paintMenuBarBackground(final Graphics g, final int width, final int height, final JComponent c) {
g.setColor(c == null ? Color.white : c.getBackground());

View File

@ -34,7 +34,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaMnemonicHandler {
static final RecyclableSingleton<AltProcessor> altProcessor = new RecyclableSingletonFromDefaultConstructor<AltProcessor>(AltProcessor.class);
private static final RecyclableSingleton<AltProcessor> altProcessor = new RecyclableSingletonFromDefaultConstructor<AltProcessor>(AltProcessor.class);
public static KeyEventPostProcessor getInstance() {
return altProcessor.get();
}

View File

@ -54,7 +54,7 @@ public class AquaNativeResources {
}
}
static final RecyclableSingleton<Color> sBackgroundColor = new RecyclableSingleton<Color>() {
private static final RecyclableSingleton<Color> sBackgroundColor = new RecyclableSingleton<Color>() {
@Override
protected Color getInstance() {
final long backgroundID = getWindowBackgroundColor();

View File

@ -35,7 +35,7 @@ import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
import java.awt.Graphics;
public class AquaPanelUI extends BasicPanelUI {
static RecyclableSingleton<AquaPanelUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaPanelUI>(AquaPanelUI.class);
private static final RecyclableSingleton<AquaPanelUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaPanelUI>(AquaPanelUI.class);
public static ComponentUI createUI(final JComponent c) {
return instance.get();

View File

@ -34,7 +34,7 @@ import javax.swing.plaf.basic.BasicSeparatorUI;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaPopupMenuSeparatorUI extends BasicSeparatorUI {
protected static RecyclableSingletonFromDefaultConstructor<AquaPopupMenuSeparatorUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaPopupMenuSeparatorUI>(AquaPopupMenuSeparatorUI.class);
private static final RecyclableSingletonFromDefaultConstructor<AquaPopupMenuSeparatorUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaPopupMenuSeparatorUI>(AquaPopupMenuSeparatorUI.class);
public static ComponentUI createUI(final JComponent c) {
return instance.get();

View File

@ -46,7 +46,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton;
public class AquaProgressBarUI extends ProgressBarUI implements ChangeListener, PropertyChangeListener, AncestorListener, Sizeable {
private static final boolean ADJUSTTIMER = true;
protected static final RecyclableSingleton<SizeDescriptor> sizeDescriptor = new RecyclableSingleton<SizeDescriptor>() {
private static final RecyclableSingleton<SizeDescriptor> sizeDescriptor = new RecyclableSingleton<SizeDescriptor>() {
@Override
protected SizeDescriptor getInstance() {
return new SizeDescriptor(new SizeVariant(146, 20)) {

View File

@ -154,7 +154,7 @@ public class AquaScrollBarUI extends ScrollBarUI {
return State.ACTIVE;
}
static final RecyclableSingleton<Map<Hit, ScrollBarPart>> hitToPressedPartMap = new RecyclableSingleton<Map<Hit,ScrollBarPart>>(){
private static final RecyclableSingleton<Map<Hit, ScrollBarPart>> hitToPressedPartMap = new RecyclableSingleton<Map<Hit,ScrollBarPart>>(){
@Override
protected Map<Hit, ScrollBarPart> getInstance() {
final Map<Hit, ScrollBarPart> map = new HashMap<Hit, ScrollBarPart>(7);

View File

@ -40,7 +40,7 @@ import com.apple.laf.AquaUtilControlSize.SizeVariant;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaScrollRegionBorder extends AquaBorder {
static final RecyclableSingletonFromDefaultConstructor<AquaScrollRegionBorder> instance = new RecyclableSingletonFromDefaultConstructor<AquaScrollRegionBorder>(AquaScrollRegionBorder.class);
private static final RecyclableSingletonFromDefaultConstructor<AquaScrollRegionBorder> instance = new RecyclableSingletonFromDefaultConstructor<AquaScrollRegionBorder>(AquaScrollRegionBorder.class);
public static AquaScrollRegionBorder getScrollRegionBorder() {
return instance.get();

View File

@ -45,7 +45,7 @@ public class AquaSliderUI extends BasicSliderUI implements Sizeable {
// static final Dimension roundThumbSize = new Dimension(21 + 4, 21 + 4); // +2px on both sides for focus fuzz
// static final Dimension pointingThumbSize = new Dimension(19 + 4, 22 + 4);
protected static final RecyclableSingleton<SizeDescriptor> roundThumbDescriptor = new RecyclableSingleton<SizeDescriptor>() {
private static final RecyclableSingleton<SizeDescriptor> roundThumbDescriptor = new RecyclableSingleton<SizeDescriptor>() {
protected SizeDescriptor getInstance() {
return new SizeDescriptor(new SizeVariant(25, 25)) {
public SizeVariant deriveSmall(final SizeVariant v) {
@ -57,7 +57,7 @@ public class AquaSliderUI extends BasicSliderUI implements Sizeable {
};
}
};
protected static final RecyclableSingleton<SizeDescriptor> pointingThumbDescriptor = new RecyclableSingleton<SizeDescriptor>() {
private static final RecyclableSingleton<SizeDescriptor> pointingThumbDescriptor = new RecyclableSingleton<SizeDescriptor>() {
protected SizeDescriptor getInstance() {
return new SizeDescriptor(new SizeVariant(23, 26)) {
public SizeVariant deriveSmall(final SizeVariant v) {

View File

@ -126,7 +126,7 @@ public class AquaTableHeaderBorder extends AbstractBorder {
return State.ACTIVE;
}
static final RecyclableSingleton<Border> alternateBorder = new RecyclableSingleton<Border>() {
private static final RecyclableSingleton<Border> alternateBorder = new RecyclableSingleton<Border>() {
@Override
protected Border getInstance() {
return BorderFactory.createRaisedBevelBorder();

View File

@ -67,7 +67,7 @@ public class AquaTableHeaderUI extends BasicTableHeaderUI {
super.uninstallDefaults();
}
static final RecyclableSingleton<ClientPropertyApplicator<JTableHeader, JTableHeader>> TABLE_HEADER_APPLICATORS = new RecyclableSingleton<ClientPropertyApplicator<JTableHeader, JTableHeader>>() {
private static final RecyclableSingleton<ClientPropertyApplicator<JTableHeader, JTableHeader>> TABLE_HEADER_APPLICATORS = new RecyclableSingleton<ClientPropertyApplicator<JTableHeader, JTableHeader>>() {
@Override
@SuppressWarnings("unchecked")
protected ClientPropertyApplicator<JTableHeader, JTableHeader> getInstance() {

View File

@ -36,7 +36,7 @@ import com.apple.laf.AquaUtilControlSize.*;
import com.apple.laf.AquaUtils.*;
public class AquaTextFieldBorder extends AquaBorder {
protected static final RecyclableSingleton<AquaTextFieldBorder> instance = new RecyclableSingletonFromDefaultConstructor<AquaTextFieldBorder>(AquaTextFieldBorder.class);
private static final RecyclableSingleton<AquaTextFieldBorder> instance = new RecyclableSingletonFromDefaultConstructor<AquaTextFieldBorder>(AquaTextFieldBorder.class);
public static AquaTextFieldBorder getTextFieldBorder() {
return instance.get();
}

View File

@ -90,7 +90,7 @@ public class AquaTextFieldSearch {
return (c.getClientProperty(FIND_POPUP_KEY) instanceof JPopupMenu);
}
protected static final RecyclableSingleton<SearchFieldBorder> instance = new RecyclableSingletonFromDefaultConstructor<SearchFieldBorder>(SearchFieldBorder.class);
private static final RecyclableSingleton<SearchFieldBorder> instance = new RecyclableSingletonFromDefaultConstructor<SearchFieldBorder>(SearchFieldBorder.class);
public static SearchFieldBorder getSearchTextFieldBorder() {
return instance.get();
}

View File

@ -38,7 +38,7 @@ import com.apple.laf.AquaUtils.RecyclableSingleton;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaTextPasswordFieldUI extends AquaTextFieldUI {
static final RecyclableSingleton<CapsLockSymbolPainter> capsLockPainter = new RecyclableSingletonFromDefaultConstructor<CapsLockSymbolPainter>(CapsLockSymbolPainter.class);
private static final RecyclableSingleton<CapsLockSymbolPainter> capsLockPainter = new RecyclableSingletonFromDefaultConstructor<CapsLockSymbolPainter>(CapsLockSymbolPainter.class);
static CapsLockSymbolPainter getCapsLockPainter() {
return capsLockPainter.get();
}

View File

@ -34,7 +34,7 @@ import javax.swing.plaf.basic.BasicToolBarSeparatorUI;
import com.apple.laf.AquaUtils.*;
public class AquaToolBarSeparatorUI extends BasicToolBarSeparatorUI {
protected static RecyclableSingleton<AquaToolBarSeparatorUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaToolBarSeparatorUI>(AquaToolBarSeparatorUI.class);
private static final RecyclableSingleton<AquaToolBarSeparatorUI> instance = new RecyclableSingletonFromDefaultConstructor<AquaToolBarSeparatorUI>(AquaToolBarSeparatorUI.class);
public static ComponentUI createUI(final JComponent c) {
return instance.get();

View File

@ -35,7 +35,7 @@ import javax.swing.plaf.basic.BasicToolBarUI;
import com.apple.laf.AquaUtils.*;
public class AquaToolBarUI extends BasicToolBarUI implements SwingConstants {
private static RecyclableSingleton<ToolBarBorder> toolBarBorder = new RecyclableSingletonFromDefaultConstructor<ToolBarBorder>(ToolBarBorder.class);
private static final RecyclableSingleton<ToolBarBorder> toolBarBorder = new RecyclableSingletonFromDefaultConstructor<ToolBarBorder>(ToolBarBorder.class);
public static Border getToolBarBorder() {
return toolBarBorder.get();
}

View File

@ -34,7 +34,7 @@ import javax.swing.plaf.basic.BasicToolTipUI;
import com.apple.laf.AquaUtils.RecyclableSingletonFromDefaultConstructor;
public class AquaToolTipUI extends BasicToolTipUI {
static final RecyclableSingletonFromDefaultConstructor<AquaToolTipUI> sharedAquaInstance = new RecyclableSingletonFromDefaultConstructor<AquaToolTipUI>(AquaToolTipUI.class);
private static final RecyclableSingletonFromDefaultConstructor<AquaToolTipUI> sharedAquaInstance = new RecyclableSingletonFromDefaultConstructor<AquaToolTipUI>(AquaToolTipUI.class);
public static ComponentUI createUI(final JComponent c) {
return sharedAquaInstance.get();

View File

@ -49,7 +49,7 @@ public class AquaUtilControlSize {
void applySizeFor(final JComponent c, final Size size);
}
protected static final RecyclableSingleton<PropertySizeListener> sizeListener
private static final RecyclableSingleton<PropertySizeListener> sizeListener
= new RecyclableSingletonFromDefaultConstructor<>(PropertySizeListener.class);
protected static PropertySizeListener getSizeListener() {
return sizeListener.get();

View File

@ -284,28 +284,21 @@ PRINT(" contextQuartzLinearGradientPath");
CGFloat components[component_size];
CGGradientRef gradient = NULL;
for (int i = 0; i < num_locations; i++) {
for (i = 0; i < num_locations; i++) {
locations[i] = gradientInfo->fractionsdata[i];
//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
}
for (i = 0; i < component_size; i++) {
components[i] = gradientInfo->colordata[i];
//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
// i, components[i], i, gradientInfo->colordata[i]);
}
CGContextSaveGState(cgRef);
gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n",
// gradientInfo->start.x, gradientInfo->start.y);
//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n",
// gradientInfo->end.x, gradientInfo->end.y);
if (qsdo->isEvenOddFill) {
CGContextEOClip(cgRef);
} else {
CGContextClip(cgRef);
}
CGContextDrawLinearGradient(cgRef, gradient, gradientInfo->start, gradientInfo->end, kCGGradientDrawsAfterEndLocation);
CGContextRestoreGState(cgRef);
CGColorSpaceRelease(colorspace);
CGGradientRelease(gradient);
@ -332,27 +325,19 @@ PRINT(" contextQuartzRadialGradientPath");
CGFloat startRadius = gradientInfo->radius;
CGFloat endRadius = gradientInfo->radius;
for (int i = 0; i < num_locations; i++) {
for (i = 0; i < num_locations; i++) {
locations[i] = gradientInfo->fractionsdata[i];
//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
}
for (i = 0; i < component_size; i++) {
components[i] = gradientInfo->colordata[i];
//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
// i, components[i], i, gradientInfo->colordata[i]);
}
CGContextSaveGState(cgRef);
gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n",
// gradientInfo->start.x, gradientInfo->start.y);
//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n",
// gradientInfo->end.x, gradientInfo->end.y);
if (qsdo->isEvenOddFill) {
CGContextEOClip(cgRef);
} else {
CGContextClip(cgRef);
}
//fprintf(stderr, "gradientInfo->startRadius %f, gradientInfo->endRadius %f\n",startRadius,endRadius);
CGContextDrawRadialGradient(cgRef, gradient, gradientInfo->start, 0, gradientInfo->end, endRadius, kCGGradientDrawsAfterEndLocation);
CGContextRestoreGState(cgRef);
@ -944,54 +929,41 @@ void setupGradient(JNIEnv *env, QuartzSDOps* qsdo, jfloat* javaFloatGraphicsStat
if (colorArray != NULL)
{
jint length = (*env)->GetArrayLength(env, colorArray);
//fprintf(stderr, "length %d\n", length);
jint* jcolorData = (jint*)(*env)->GetPrimitiveArrayCritical(env, colorArray, NULL);
CGFloat* colors= (CGFloat*)calloc(0, sizeof(CGFloat)*length);
qsdo->gradientInfo->colordata = (CGFloat*)malloc(sizeof(CGFloat)*4*length);
memset(qsdo->gradientInfo->colordata, 0, sizeof(CGFloat)*4*length);
if (jcolorData != NULL)
{
jint i;
int i;
for (i=0; i<length; i++)
{
colors[i] = (CGFloat)jcolorData[i];
qsdo->gradientInfo->colordata[i*4] = ((jcolorData[i]>>16)&0xff)*kColorConversionMultiplier;
qsdo->gradientInfo->colordata[i*4+1] = ((jcolorData[i]>>8)&0xff)*kColorConversionMultiplier;
qsdo->gradientInfo->colordata[i*4+2] = ((jcolorData[i]>>0)&0xff)*kColorConversionMultiplier;
qsdo->gradientInfo->colordata[i*4+3] = ((jcolorData[i]>>24)&0xff)*kColorConversionMultiplier;
}
}
(*env)->ReleasePrimitiveArrayCritical(env, colorArray, jcolorData, 0);
qsdo->gradientInfo->colordata = (CGFloat*)calloc(0, sizeof(CGFloat)*4*length);
for (int i = 0; i < length; i++)
{
jint c1 = colors[i];
//fprintf(stderr, "c1 %x\n", c1);
qsdo->gradientInfo->colordata[i*4] = ((c1>>16)&0xff)*kColorConversionMultiplier;
//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4, qsdo->gradientInfo->colordata[i*4]);
qsdo->gradientInfo->colordata[i*4+1] = ((c1>>8)&0xff)*kColorConversionMultiplier;
//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+1, qsdo->gradientInfo->colordata[i*4+1]);
qsdo->gradientInfo->colordata[i*4+2] = ((c1>>0)&0xff)*kColorConversionMultiplier;
//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+2, qsdo->gradientInfo->colordata[i*4+2]);
qsdo->gradientInfo->colordata[i*4+3] = ((c1>>24)&0xff)*kColorConversionMultiplier;
//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+3, qsdo->gradientInfo->colordata[i*4+3]);
}
free(colors);
}
jobject fractionsArray = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kFractionsArrayIndex));
if (fractionsArray != NULL)
{
jint length = (*env)->GetArrayLength(env, fractionsArray);
//fprintf(stderr, "fractions length %d\n", length);
qsdo->gradientInfo->fractionsLength = length;
jfloat* jfractionsData = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL);
if (jfractionsData != NULL)
{
int i;
qsdo->gradientInfo->fractionsdata = (CGFloat *)malloc(sizeof(CGFloat) *length);
jint i;
memset(qsdo->gradientInfo->fractionsdata, 0, sizeof(CGFloat)*length);
for (i=0; i<length; i++)
{
qsdo->gradientInfo->fractionsdata[i] = jfractionsData[i];
//fprintf(stderr, "jfrationsData[%d] %f, qsdo->gradientInfo->fractionsdata[%d] = %f\n", i, jfractionsData[i], i, qsdo->gradientInfo->fractionsdata[i]);
}
(*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, jfractionsData, 0);
}

View File

@ -274,6 +274,10 @@ public class Taskbar {
/**
* Requests user attention to the specified window.
*
* Has no effect if a window representation is not displayable in
* the task area. Whether it is displayable is dependent on all
* of window type, platform, and implementation.
*
* @param w window
* @throws SecurityException if a security manager exists and it denies the
* {@code RuntimePermission("canProcessApplicationEvents")} permission.
@ -375,6 +379,10 @@ public class Taskbar {
* for the specified window.
* It may be disabled by system settings.
*
* Has no effect if a window representation is not displayable in
* the task area. Whether it is displayable is dependent on all
* of window type, platform, and implementation.
*
* @param w window to update
* @param badge image to affix to the icon
* @throws SecurityException if a security manager exists and it denies the
@ -409,6 +417,11 @@ public class Taskbar {
/**
* Displays a determinate progress bar in the task area for the specified
* window.
*
* Has no effect if a window representation is not displayable in
* the task area. Whether it is displayable is dependent on all
* of window type, platform, and implementation.
*
* <br>
* The visual behavior is platform and {@link State} dependent.
* <br>
@ -437,6 +450,10 @@ public class Taskbar {
/**
* Sets a progress state for a specified window.
*
* Has no effect if a window representation is not displayable in
* the task area. Whether it is displayable is dependent on all
* of window type, platform, and implementation.
* <br>
* Each state displays a progress in a platform-dependent way.
* <br>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -36,8 +36,6 @@ import java.beans.PropertyChangeSupport;
import java.beans.PropertyChangeEvent;
import java.awt.IllegalComponentStateException;
import javax.swing.SwingContainer;
/**
* AccessibleContext represents the minimum information all accessible objects
* return. This information includes the accessible name, description, role,
@ -79,7 +77,6 @@ import javax.swing.SwingContainer;
* @author Lynn Monsanto
*/
@JavaBean(description = "Minimal information that all accessible objects return")
@SwingContainer(false)
public abstract class AccessibleContext {
/**

View File

@ -33,6 +33,8 @@ import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import sun.swing.CachedPainter;
import static sun.swing.SwingUtilities2.setAntialiasingHintForScaledGraphics;
import static sun.swing.SwingUtilities2.getAndSetAntialisingHintForScaledGraphics;
/**
* Factory object that vends <code>Icon</code>s for
@ -1247,9 +1249,15 @@ public class MetalIconFactory implements Serializable {
protected void drawCheck(Component c, Graphics g, int x, int y) {
int controlSize = getControlSize();
g.fillRect( x+3, y+5, 2, controlSize-8 );
g.drawLine( x+(controlSize-4), y+3, x+5, y+(controlSize-6) );
g.drawLine( x+(controlSize-4), y+4, x+5, y+(controlSize-5) );
int csx = controlSize - 3;
int csy1 = controlSize - 6;
int csy2 = controlSize - 4;
int csy3 = controlSize - 3;
int[] xPoints = {3, 5, 5, csx, csx, 5, 5, 3};
int[] yPoints = {5, 5, csy1, 2, 4, csy2, csy3, csy3};
g.translate(x, y);
g.fillPolygon(xPoints, yPoints, 8);
g.translate(-x, -y);
}
public int getIconWidth() {
@ -1323,8 +1331,12 @@ public class MetalIconFactory implements Serializable {
}
public void paintIcon(Component c, Graphics g, int x, int y) {
Object aaHint = getAndSetAntialisingHintForScaledGraphics(g);
if (MetalLookAndFeel.usingOcean()) {
paintOceanIcon(c, g, x, y);
setAntialiasingHintForScaledGraphics(g, aaHint);
return;
}
JRadioButton rb = (JRadioButton)c;
@ -1358,51 +1370,25 @@ public class MetalIconFactory implements Serializable {
// draw Dark Circle (start at top, go clockwise)
g.setColor(darkCircle);
g.drawLine( 4, 0, 7, 0);
g.drawLine( 8, 1, 9, 1);
g.drawLine(10, 2, 10, 3);
g.drawLine(11, 4, 11, 7);
g.drawLine(10, 8, 10, 9);
g.drawLine( 9,10, 8,10);
g.drawLine( 7,11, 4,11);
g.drawLine( 3,10, 2,10);
g.drawLine( 1, 9, 1, 8);
g.drawLine( 0, 7, 0, 4);
g.drawLine( 1, 3, 1, 2);
g.drawLine( 2, 1, 3, 1);
g.drawOval(0, 0, 11, 11);
// draw Inner Left (usually) White Arc
// start at lower left corner, go clockwise
g.setColor(whiteInnerLeftArc);
g.drawLine( 2, 9, 2, 8);
g.drawLine( 1, 7, 1, 4);
g.drawLine( 2, 2, 2, 3);
g.drawLine( 2, 2, 3, 2);
g.drawLine( 4, 1, 7, 1);
g.drawLine( 8, 2, 9, 2);
g.drawArc(1, 1, 10, 10, 60, 160);
// draw Outer Right White Arc
// start at upper right corner, go clockwise
g.setColor(whiteOuterRightArc);
g.drawLine(10, 1, 10, 1);
g.drawLine(11, 2, 11, 3);
g.drawLine(12, 4, 12, 7);
g.drawLine(11, 8, 11, 9);
g.drawLine(10,10, 10,10);
g.drawLine( 9,11, 8,11);
g.drawLine( 7,12, 4,12);
g.drawLine( 3,11, 2,11);
g.drawArc(-1, -1, 13, 13, 235, 180);
// selected dot
if ( drawDot ) {
g.setColor(dotColor);
g.fillRect( 4, 4, 4, 4);
g.drawLine( 4, 3, 7, 3);
g.drawLine( 8, 4, 8, 7);
g.drawLine( 7, 8, 4, 8);
g.drawLine( 3, 7, 3, 4);
g.fillOval(2, 2, 7, 7);
}
g.translate(-x, -y);
setAntialiasingHintForScaledGraphics(g, aaHint);
}
public int getIconWidth() {
@ -2051,16 +2037,17 @@ public class MetalIconFactory implements Serializable {
g.setColor( b.getForeground() );
}
}
if( MetalUtils.isLeftToRight(b) ) {
g.drawLine( 0, 0, 0, 7 );
g.drawLine( 1, 1, 1, 6 );
g.drawLine( 2, 2, 2, 5 );
g.drawLine( 3, 3, 3, 4 );
if (MetalUtils.isLeftToRight(b)) {
int[] xPoints = {0, 3, 3, 0};
int[] yPoints = {0, 3, 4, 7};
g.fillPolygon(xPoints, yPoints, 4);
g.drawPolygon(xPoints, yPoints, 4);
} else {
g.drawLine( 4, 0, 4, 7 );
g.drawLine( 3, 1, 3, 6 );
g.drawLine( 2, 2, 2, 5 );
g.drawLine( 1, 3, 1, 4 );
int[] xPoints = {4, 4, 1, 1};
int[] yPoints = {0, 7, 4, 3};
g.fillPolygon(xPoints, yPoints, 4);
g.drawPolygon(xPoints, yPoints, 4);
}
g.translate( -x, -y );
@ -2138,10 +2125,7 @@ public class MetalIconFactory implements Serializable {
g.setColor( MetalLookAndFeel.getMenuDisabledForeground());
}
g.drawLine( 2, 2, 2, 6 );
g.drawLine( 3, 2, 3, 6 );
g.drawLine( 4, 4, 8, 0 );
g.drawLine( 4, 5, 9, 0 );
drawCheck(g);
}
g.translate( -x, -y );
}
@ -2217,15 +2201,18 @@ public class MetalIconFactory implements Serializable {
g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
}
g.drawLine( 2, 2, 2, 6 );
g.drawLine( 3, 2, 3, 6 );
g.drawLine( 4, 4, 8, 0 );
g.drawLine( 4, 5, 9, 0 );
drawCheck(g);
}
g.translate( -x, -y );
}
private void drawCheck(Graphics g) {
int[] xPoints = {2, 3, 3, 8, 9, 3, 2};
int[] yPoints = {2, 2, 5, 0, 0, 6, 6};
g.drawPolygon(xPoints, yPoints, 7);
}
public int getIconWidth() { return menuCheckIconSize.width; }
public int getIconHeight() { return menuCheckIconSize.height; }
@ -2252,9 +2239,8 @@ public class MetalIconFactory implements Serializable {
else {
g.setColor(MetalLookAndFeel.getControlHighlight());
}
g.drawLine( 2, 9, 7, 9 );
g.drawLine( 9, 2, 9, 7 );
g.drawLine( 8, 8, 8, 8 );
g.drawArc(-1, -1, 10, 10, 245, 140);
if (isPressed || isArmed) {
g.setColor(MetalLookAndFeel.getControlInfo());
@ -2266,14 +2252,8 @@ public class MetalIconFactory implements Serializable {
else {
g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
}
g.drawLine( 2, 0, 6, 0 );
g.drawLine( 2, 8, 6, 8 );
g.drawLine( 0, 2, 0, 6 );
g.drawLine( 8, 2, 8, 6 );
g.drawLine( 1, 1, 1, 1 );
g.drawLine( 7, 1, 7, 1 );
g.drawLine( 1, 7, 1, 7 );
g.drawLine( 7, 7, 7, 7 );
g.drawOval(0, 0, 8, 8);
if (isSelected) {
if (isEnabled) {
@ -2288,11 +2268,9 @@ public class MetalIconFactory implements Serializable {
else {
g.setColor(MetalLookAndFeel.getMenuDisabledForeground());
}
g.drawLine( 3, 2, 5, 2 );
g.drawLine( 2, 3, 6, 3 );
g.drawLine( 2, 4, 6, 4 );
g.drawLine( 2, 5, 6, 5 );
g.drawLine( 3, 6, 5, 6 );
g.fillOval(2, 2, 4, 4);
g.drawOval(2, 2, 4, 4);
}
g.translate( -x, -y );
@ -2300,8 +2278,12 @@ public class MetalIconFactory implements Serializable {
public void paintIcon( Component c, Graphics g, int x, int y )
{
Object aaHint = getAndSetAntialisingHintForScaledGraphics(g);
if (MetalLookAndFeel.usingOcean()) {
paintOceanIcon(c, g, x, y);
setAntialiasingHintForScaledGraphics(g, aaHint);
return;
}
JMenuItem b = (JMenuItem) c;
@ -2319,55 +2301,24 @@ public class MetalIconFactory implements Serializable {
if ( isPressed || isArmed )
{
g.setColor( MetalLookAndFeel.getPrimaryControl() );
g.drawLine( 3, 1, 8, 1 );
g.drawLine( 2, 9, 7, 9 );
g.drawLine( 1, 3, 1, 8 );
g.drawLine( 9, 2, 9, 7 );
g.drawLine( 2, 2, 2, 2 );
g.drawLine( 8, 8, 8, 8 );
g.drawOval(1, 1, 8, 8);
g.setColor( MetalLookAndFeel.getControlInfo() );
g.drawLine( 2, 0, 6, 0 );
g.drawLine( 2, 8, 6, 8 );
g.drawLine( 0, 2, 0, 6 );
g.drawLine( 8, 2, 8, 6 );
g.drawLine( 1, 1, 1, 1 );
g.drawLine( 7, 1, 7, 1 );
g.drawLine( 1, 7, 1, 7 );
g.drawLine( 7, 7, 7, 7 );
g.drawOval(0, 0, 8, 8);
}
else
{
g.setColor( MetalLookAndFeel.getControlHighlight() );
g.drawLine( 3, 1, 8, 1 );
g.drawLine( 2, 9, 7, 9 );
g.drawLine( 1, 3, 1, 8 );
g.drawLine( 9, 2, 9, 7 );
g.drawLine( 2, 2, 2, 2 );
g.drawLine( 8, 8, 8, 8 );
g.drawOval(1, 1, 8, 8);
g.setColor( MetalLookAndFeel.getControlDarkShadow() );
g.drawLine( 2, 0, 6, 0 );
g.drawLine( 2, 8, 6, 8 );
g.drawLine( 0, 2, 0, 6 );
g.drawLine( 8, 2, 8, 6 );
g.drawLine( 1, 1, 1, 1 );
g.drawLine( 7, 1, 7, 1 );
g.drawLine( 1, 7, 1, 7 );
g.drawLine( 7, 7, 7, 7 );
g.drawOval(0, 0, 8, 8);
}
}
else
{
g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
g.drawLine( 2, 0, 6, 0 );
g.drawLine( 2, 8, 6, 8 );
g.drawLine( 0, 2, 0, 6 );
g.drawLine( 8, 2, 8, 6 );
g.drawLine( 1, 1, 1, 1 );
g.drawLine( 7, 1, 7, 1 );
g.drawLine( 1, 7, 1, 7 );
g.drawLine( 7, 7, 7, 7 );
g.drawOval(0, 0, 8, 8);
}
if ( isSelected )
@ -2388,14 +2339,12 @@ public class MetalIconFactory implements Serializable {
g.setColor( MetalLookAndFeel.getMenuDisabledForeground() );
}
g.drawLine( 3, 2, 5, 2 );
g.drawLine( 2, 3, 6, 3 );
g.drawLine( 2, 4, 6, 4 );
g.drawLine( 2, 5, 6, 5 );
g.drawLine( 3, 6, 5, 6 );
g.fillOval(2, 2, 4, 4);
g.drawOval(2, 2, 4, 4);
}
g.translate( -x, -y );
setAntialiasingHintForScaledGraphics(g, aaHint);
}
public int getIconWidth() { return menuCheckIconSize.width; }

View File

@ -39,6 +39,7 @@ import java.util.ArrayList;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Arrays;
import javax.swing.event.*;
import javax.swing.undo.AbstractUndoableEdit;
import javax.swing.undo.CannotRedoException;
@ -1263,7 +1264,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc
int offs, int len) {
attr = a;
this.type = type;
this.data = txt;
this.data = txt == null ? null : Arrays.copyOf(txt, txt.length);
this.offs = offs;
this.len = len;
this.direction = OriginateDirection;
@ -1323,7 +1324,7 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc
* @return the array
*/
public char[] getArray() {
return data;
return data == null ? null : Arrays.copyOf(data, data.length);
}

View File

@ -794,7 +794,7 @@ public class StyleContext implements Serializable, AbstractDocument.AttributeCon
* @param attributes the attributes
*/
public SmallAttributeSet(Object[] attributes) {
this.attributes = attributes;
this.attributes = Arrays.copyOf(attributes, attributes.length);
updateResolveParent();
}

View File

@ -66,7 +66,8 @@ public abstract class CustomCursor extends Cursor {
// Scale image to nearest supported size.
Dimension nativeSize = toolkit.getBestCursorSize(width, height);
if (nativeSize.width != width || nativeSize.height != height) {
if ((nativeSize.width != width || nativeSize.height != height) &&
(nativeSize.width != 0 && nativeSize.height != 0)) {
cursor = cursor.getScaledInstance(nativeSize.width,
nativeSize.height,
Image.SCALE_DEFAULT);

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2017, 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.
*/
package sun.print;
import javax.print.attribute.Attribute;
import javax.print.attribute.PrintRequestAttribute;
/*
* An implementation class used to request the dialog be set always-on-top.
* It needs to be read and honoured by the dialog code which will use
* java.awt.Window.setAlwaysOnTop(true) in cases where it is supported.
*/
public class DialogOnTop implements PrintRequestAttribute {
private static final long serialVersionUID = -1901909867156076547L;
long id;
public DialogOnTop() {
}
public DialogOnTop(long id) {
this.id = id;
}
public final Class<? extends Attribute> getCategory() {
return DialogOnTop.class;
}
public long getID() {
return id;
}
public final String getName() {
return "dialog-on-top";
}
public String toString() {
return "dialog-on-top";
}
}

View File

@ -785,7 +785,9 @@ public abstract class RasterPrinterJob extends PrinterJob {
PrintService pservice = getPrintService();
PageFormat pageFrmAttrib = attributeToPageFormat(pservice,
attributes);
setParentWindowID(attributes);
PageFormat page = pageDialog(pageFrmAttrib);
clearParentWindowID();
// If user cancels the dialog, pageDialog() will return the original
// page object and as per spec, we should return null in that case.
@ -828,6 +830,9 @@ public abstract class RasterPrinterJob extends PrinterJob {
int x = gcBounds.x+50;
int y = gcBounds.y+50;
ServiceDialog pageDialog;
if (onTop != null) {
attributes.add(onTop);
}
if (w instanceof Frame) {
pageDialog = new ServiceDialog(gc, x, y, service,
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
@ -837,6 +842,7 @@ public abstract class RasterPrinterJob extends PrinterJob {
DocFlavor.SERVICE_FORMATTED.PAGEABLE,
attributes, (Dialog)w);
}
Rectangle dlgBounds = pageDialog.getBounds();
// if portion of dialog is not within the gc boundary
@ -923,7 +929,9 @@ public abstract class RasterPrinterJob extends PrinterJob {
}
setParentWindowID(attributes);
boolean ret = printDialog();
clearParentWindowID();
this.attributes = attributes;
return ret;
@ -2539,4 +2547,26 @@ public abstract class RasterPrinterJob extends PrinterJob {
return new String(out_chars, 0, pos);
}
}
private DialogOnTop onTop = null;
private long parentWindowID = 0L;
/* Called from native code */
private long getParentWindowID() {
return parentWindowID;
}
private void clearParentWindowID() {
parentWindowID = 0L;
onTop = null;
}
private void setParentWindowID(PrintRequestAttributeSet attrs) {
parentWindowID = 0L;
onTop = (DialogOnTop)attrs.get(DialogOnTop.class);
if (onTop != null) {
parentWindowID = onTop.getID();
}
}
}

Some files were not shown because too many files have changed in this diff Show More