Merge
This commit is contained in:
commit
4548261e7b
@ -100,8 +100,7 @@ else
|
||||
# Allow override by ALT_JVMCFG_SRC if it exists
|
||||
JVMCFG_SRC := $(if $(wildcard $(ALT_JVMCFG_SRC)),$(ALT_JVMCFG_SRC),$(JVMCFG_SRC))
|
||||
endif
|
||||
JVMCFG_DIR := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)
|
||||
JVMCFG := $(JVMCFG_DIR)/jvm.cfg
|
||||
JVMCFG := $(LIB_DST_DIR)/jvm.cfg
|
||||
|
||||
# To do: should this also support -zeroshark?
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -64,7 +64,7 @@ ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype)
|
||||
else
|
||||
FREETYPE_TARGET_LIB := $(LIB_DST_DIR)$(OPENJDK_TARGET_CPU_LIBDIR)/$(call SHARED_LIBRARY,freetype).6
|
||||
FREETYPE_TARGET_LIB := $(LIB_DST_DIR)/$(call SHARED_LIBRARY,freetype).6
|
||||
endif
|
||||
|
||||
# We can't use $(install-file) in this rule because it preserves symbolic links and
|
||||
|
@ -74,7 +74,7 @@ $(eval $(call SetupBuildLauncher, keytool, \
|
||||
BUILD_JEXEC :=
|
||||
BUILD_JEXEC_SRC :=
|
||||
BUILD_JEXEC_INC :=
|
||||
BUILD_JEXEC_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)
|
||||
BUILD_JEXEC_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base
|
||||
|
||||
#
|
||||
# UNHANDLED:
|
||||
@ -138,7 +138,7 @@ endif
|
||||
BUILD_JSPAWNHELPER :=
|
||||
BUILD_JSPAWNHELPER_SRC := $(JDK_TOPDIR)/src/java.base/unix/native/jspawnhelper
|
||||
JSPAWNHELPER_CFLAGS := -I$(JDK_TOPDIR)/src/java.base/unix/native/libjava
|
||||
BUILD_JSPAWNHELPER_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)
|
||||
BUILD_JSPAWNHELPER_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base
|
||||
LINK_JSPAWNHELPER_OBJECTS := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjava/childproc.o
|
||||
BUILD_JSPAWNHELPER_LDFLAGS :=
|
||||
|
||||
|
37
jdk/make/launcher/Launcher-jdk.aot.gmk
Normal file
37
jdk/make/launcher/Launcher-jdk.aot.gmk
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation. 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.
|
||||
#
|
||||
|
||||
include LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, jaotc, \
|
||||
MAIN_CLASS := jdk.tools.jaotc.Main, \
|
||||
JAVA_ARGS := -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI \
|
||||
-XX:+UseAOT \
|
||||
-Djvmci.UseProfilingInformation=false \
|
||||
-Dgraal.UseExceptionProbability=false \
|
||||
-Djvmci.Compiler=graal \
|
||||
--add-modules ALL-DEFAULT \
|
||||
, \
|
||||
))
|
@ -32,13 +32,13 @@ else
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
DISABLE_MAPFILES := true
|
||||
endif
|
||||
ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli)
|
||||
ORIGIN_ARG := $(call SET_EXECUTABLE_ORIGIN,/../lib/jli)
|
||||
|
||||
# Applications expect to be able to link against libjawt without invoking
|
||||
# System.loadLibrary("jawt") first. This was the behaviour described in the
|
||||
# devloper documentation of JAWT and what worked with OpenJDK6.
|
||||
ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
|
||||
ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib$(OPENJDK_TARGET_CPU_LIBDIR))
|
||||
ORIGIN_ARG += $(call SET_EXECUTABLE_ORIGIN,/../lib)
|
||||
endif
|
||||
endif
|
||||
|
||||
@ -190,9 +190,9 @@ define SetupBuildLauncherBody
|
||||
$$(ORIGIN_ARG) \
|
||||
$$($1_LDFLAGS), \
|
||||
LDFLAGS_linux := \
|
||||
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
|
||||
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli, \
|
||||
LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
|
||||
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
|
||||
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base/jli, \
|
||||
MAPFILE := $$($1_MAPFILE), \
|
||||
LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
|
||||
LIBS_unix := $$($1_LIBS_unix), \
|
||||
|
@ -418,6 +418,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBLCMS, \
|
||||
DISABLED_WARNINGS_gcc := format-nonliteral type-limits misleading-indentation, \
|
||||
DISABLED_WARNINGS_clang := tautological-compare, \
|
||||
DISABLED_WARNINGS_solstudio := E_STATEMENT_NOT_REACHED, \
|
||||
DISABLED_WARNINGS_microsoft := 4819, \
|
||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/liblcms/mapfile-vers, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
@ -681,7 +682,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBFONTMANAGER, \
|
||||
DISABLED_WARNINGS_CXX_solstudio := \
|
||||
truncwarn wvarhidenmem wvarhidemem wbadlkginit identexpected \
|
||||
hidevf w_novirtualdescr arrowrtn2, \
|
||||
DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334, \
|
||||
DISABLED_WARNINGS_microsoft := 4267 4244 4018 4090 4996 4146 4334 4819, \
|
||||
MAPFILE := $(BUILD_LIBFONTMANAGER_MAPFILE), \
|
||||
LDFLAGS := $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
|
@ -340,9 +340,6 @@ endif
|
||||
|
||||
LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
|
||||
|
||||
# Append defines depending on target platform
|
||||
LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
|
||||
|
||||
ifneq ($(USE_EXTERNAL_LIBZ), true)
|
||||
LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
|
||||
LIBJLI_EXTRA_FILES += \
|
||||
|
@ -150,7 +150,6 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_StrictMath_atan;
|
||||
Java_java_lang_StrictMath_atan2;
|
||||
Java_java_lang_StrictMath_cos;
|
||||
Java_java_lang_StrictMath_exp;
|
||||
Java_java_lang_StrictMath_log;
|
||||
Java_java_lang_StrictMath_log10;
|
||||
Java_java_lang_StrictMath_sin;
|
||||
|
@ -26,6 +26,7 @@
|
||||
package build.tools.jigsaw;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
@ -44,7 +45,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.*;
|
||||
import static java.lang.module.ModuleDescriptor.Requires.Modifier.TRANSITIVE;
|
||||
|
||||
/**
|
||||
@ -69,42 +71,25 @@ public class GenGraphs {
|
||||
.map(ModuleReference::descriptor)
|
||||
.filter(m -> (m.name().startsWith("java.") &&
|
||||
!m.name().equals("java.smartcardio")))
|
||||
.collect(Collectors.toSet()));
|
||||
.collect(toSet()));
|
||||
Set<ModuleDescriptor> jdkModules
|
||||
= new TreeSet<>(finder.findAll().stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.filter(m -> !javaSEModules.contains(m))
|
||||
.collect(Collectors.toSet()));
|
||||
.collect(toSet()));
|
||||
|
||||
GenGraphs genGraphs = new GenGraphs(javaSEModules, jdkModules);
|
||||
GenGraphs genGraphs = new GenGraphs(dir, javaSEModules, jdkModules);
|
||||
Set<String> mods = new HashSet<>();
|
||||
for (ModuleReference mref: finder.findAll()) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
String name = descriptor.name();
|
||||
mods.add(name);
|
||||
Configuration cf = Configuration.empty()
|
||||
.resolveRequires(finder,
|
||||
ModuleFinder.of(),
|
||||
Set.of(name));
|
||||
genGraphs.genDotFile(dir, name, cf);
|
||||
mods.add(mref.descriptor().name());
|
||||
genGraphs.genDotFile(mref);
|
||||
}
|
||||
|
||||
Configuration cf = Configuration.empty()
|
||||
.resolveRequires(finder,
|
||||
ModuleFinder.of(),
|
||||
mods);
|
||||
genGraphs.genDotFile(dir, "jdk", cf);
|
||||
// all modules
|
||||
genGraphs.genDotFile("jdk", mods);
|
||||
|
||||
}
|
||||
|
||||
private final Set<ModuleDescriptor> javaGroup;
|
||||
private final Set<ModuleDescriptor> jdkGroup;
|
||||
|
||||
GenGraphs(Set<ModuleDescriptor> javaGroup, Set<ModuleDescriptor> jdkGroup) {
|
||||
this.javaGroup = Collections.unmodifiableSet(javaGroup);
|
||||
this.jdkGroup = Collections.unmodifiableSet(jdkGroup);
|
||||
}
|
||||
|
||||
private static final String ORANGE = "#e76f00";
|
||||
private static final String BLUE = "#437291";
|
||||
private static final String GRAY = "#dddddd";
|
||||
@ -145,23 +130,70 @@ public class GenGraphs {
|
||||
|
||||
}
|
||||
|
||||
private void genDotFile(Path dir, String name, Configuration cf) throws IOException {
|
||||
try (PrintStream out
|
||||
= new PrintStream(Files.newOutputStream(dir.resolve(name + ".dot")))) {
|
||||
private final Path dir;
|
||||
private final Set<ModuleDescriptor> javaGroup;
|
||||
private final Set<ModuleDescriptor> jdkGroup;
|
||||
|
||||
Map<String, ModuleDescriptor> nameToModule;
|
||||
if (name.equals("java.se.ee")) {
|
||||
nameToModule = cf.modules().stream()
|
||||
.map(ResolvedModule::reference)
|
||||
.map(ModuleReference::descriptor)
|
||||
.filter(md -> !md.name().startsWith("jdk."))
|
||||
.collect(Collectors.toMap(ModuleDescriptor::name, Function.identity()));
|
||||
} else {
|
||||
nameToModule = cf.modules().stream()
|
||||
.map(ResolvedModule::reference)
|
||||
.map(ModuleReference::descriptor)
|
||||
.collect(Collectors.toMap(ModuleDescriptor::name, Function.identity()));
|
||||
GenGraphs(Path dir, Set<ModuleDescriptor> javaGroup, Set<ModuleDescriptor> jdkGroup) {
|
||||
this.dir = dir;
|
||||
this.javaGroup = Collections.unmodifiableSet(javaGroup);
|
||||
this.jdkGroup = Collections.unmodifiableSet(jdkGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a dot file for the given module reference as the root.
|
||||
*/
|
||||
void genDotFile(ModuleReference mref) throws IOException {
|
||||
String name = mref.descriptor().name();
|
||||
genDotFile(name, Set.of(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a dot file for the given set of root modules.
|
||||
*/
|
||||
void genDotFile(String name, Set<String> roots) throws IOException {
|
||||
Configuration cf =
|
||||
Configuration.empty().resolveRequires(ModuleFinder.ofSystem(),
|
||||
ModuleFinder.of(),
|
||||
roots);
|
||||
|
||||
Set<ModuleDescriptor> mds = cf.modules().stream()
|
||||
.map(ResolvedModule::reference)
|
||||
.map(ModuleReference::descriptor)
|
||||
.collect(toSet());
|
||||
|
||||
// generate a dot file for the resolved graph
|
||||
try (OutputStream os = Files.newOutputStream(dir.resolve(name + ".dot"));
|
||||
PrintStream out = new PrintStream(os)) {
|
||||
printGraph(out, name, gengraph(cf),
|
||||
mds.stream()
|
||||
.collect(toMap(ModuleDescriptor::name, Function.identity()))
|
||||
);
|
||||
}
|
||||
|
||||
if (name.equals("java.se") || name.equals("java.se.ee")) {
|
||||
// generate a dot file for Java SE module graph
|
||||
try (OutputStream os = Files.newOutputStream(dir.resolve(name + "-spec.dot"));
|
||||
PrintStream out = new PrintStream(os)) {
|
||||
// transitive reduction on the graph of `requires transitive` edges
|
||||
// filter out jdk.* modules which are implementation dependences
|
||||
Graph<String> graph = requiresTransitiveGraph(cf, true);
|
||||
printGraph(out, name, graph,
|
||||
mds.stream()
|
||||
.filter(md -> !md.name().startsWith("jdk.") &&
|
||||
graph.nodes().contains(md.name()))
|
||||
.collect(toMap(ModuleDescriptor::name, Function.identity()))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void printGraph(PrintStream out,
|
||||
String name,
|
||||
Graph<String> graph,
|
||||
Map<String, ModuleDescriptor> nameToModule)
|
||||
throws IOException
|
||||
{
|
||||
Set<ModuleDescriptor> descriptors = new TreeSet<>(nameToModule.values());
|
||||
|
||||
out.format("digraph \"%s\" {%n", name);
|
||||
@ -182,13 +214,13 @@ public class GenGraphs {
|
||||
|
||||
// same ranks
|
||||
ranks.stream()
|
||||
.forEach(group -> out.format("{rank=same %s}%n",
|
||||
descriptors.stream()
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(group::contains)
|
||||
.map(mn -> "\"" + mn + "\"")
|
||||
.collect(Collectors.joining(","))
|
||||
));
|
||||
.map(group -> descriptors.stream()
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(group::contains)
|
||||
.map(mn -> "\"" + mn + "\"")
|
||||
.collect(joining(",")))
|
||||
.filter(group -> group.length() > 0)
|
||||
.forEach(group -> out.format("{rank=same %s}%n", group));
|
||||
|
||||
descriptors.stream()
|
||||
.filter(jdkGroup::contains)
|
||||
@ -196,30 +228,28 @@ public class GenGraphs {
|
||||
.forEach(mn -> out.format(" \"%s\" [fontcolor=\"%s\", group=%s];%n",
|
||||
mn, BLUE, "jdk"));
|
||||
|
||||
// transitive reduction
|
||||
Graph<String> graph = gengraph(cf);
|
||||
descriptors.forEach(md -> {
|
||||
String mn = md.name();
|
||||
Set<String> requiresTransitive = md.requires().stream()
|
||||
.filter(d -> d.modifiers().contains(TRANSITIVE))
|
||||
.map(d -> d.name())
|
||||
.collect(Collectors.toSet());
|
||||
descriptors.stream()
|
||||
.forEach(md -> {
|
||||
String mn = md.name();
|
||||
Set<String> requiresTransitive = md.requires().stream()
|
||||
.filter(d -> d.modifiers().contains(TRANSITIVE))
|
||||
.map(d -> d.name())
|
||||
.collect(toSet());
|
||||
|
||||
graph.adjacentNodes(mn)
|
||||
.stream()
|
||||
.filter(nameToModule::containsKey)
|
||||
.forEach(dn -> {
|
||||
String attr = dn.equals("java.base") ? REQUIRES_BASE
|
||||
: (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
|
||||
int w = weightOf(mn, dn);
|
||||
if (w > 1)
|
||||
attr += "weight=" + w;
|
||||
out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
|
||||
});
|
||||
});
|
||||
graph.adjacentNodes(mn)
|
||||
.stream()
|
||||
.filter(nameToModule::containsKey)
|
||||
.forEach(dn -> {
|
||||
String attr = dn.equals("java.base") ? REQUIRES_BASE
|
||||
: (requiresTransitive.contains(dn) ? REEXPORTS : REQUIRES);
|
||||
int w = weightOf(mn, dn);
|
||||
if (w > 1)
|
||||
attr += "weight=" + w;
|
||||
out.format(" \"%s\" -> \"%s\" [%s];%n", mn, dn, attr);
|
||||
});
|
||||
});
|
||||
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -239,7 +269,7 @@ public class GenGraphs {
|
||||
.map(ResolvedModule::name)
|
||||
.forEach(target -> builder.addEdge(mn, target));
|
||||
}
|
||||
Graph<String> rpg = requiresTransitiveGraph(cf);
|
||||
Graph<String> rpg = requiresTransitiveGraph(cf, false);
|
||||
return builder.build().reduce(rpg);
|
||||
}
|
||||
|
||||
@ -247,13 +277,14 @@ public class GenGraphs {
|
||||
* Returns a Graph containing only requires transitive edges
|
||||
* with transitive reduction.
|
||||
*/
|
||||
private Graph<String> requiresTransitiveGraph(Configuration cf) {
|
||||
private Graph<String> requiresTransitiveGraph(Configuration cf, boolean includeBase) {
|
||||
Graph.Builder<String> builder = new Graph.Builder<>();
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
|
||||
String mn = descriptor.name();
|
||||
descriptor.requires().stream()
|
||||
.filter(d -> d.modifiers().contains(TRANSITIVE))
|
||||
.filter(d -> d.modifiers().contains(TRANSITIVE)
|
||||
|| (includeBase && d.name().equals("java.base")))
|
||||
.map(d -> d.name())
|
||||
.forEach(d -> builder.addEdge(mn, d));
|
||||
}
|
||||
|
@ -171,8 +171,6 @@ struct NSAppArgs {
|
||||
* Main
|
||||
*/
|
||||
|
||||
#define GetArch() GetArchPath(CURRENT_DATA_MODEL)
|
||||
|
||||
/* Store the name of the executable once computed */
|
||||
static char *execname = NULL;
|
||||
|
||||
@ -184,16 +182,6 @@ GetExecName() {
|
||||
return execname;
|
||||
}
|
||||
|
||||
const char *
|
||||
GetArchPath(int nbits)
|
||||
{
|
||||
switch(nbits) {
|
||||
default:
|
||||
return LIBARCHNAME;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Exports the JNI interface from libjli
|
||||
*
|
||||
@ -211,7 +199,7 @@ static InvocationFunctions *GetExportedJNIFunctions() {
|
||||
if (sExportedJNIFunctions != NULL) return sExportedJNIFunctions;
|
||||
|
||||
char jrePath[PATH_MAX];
|
||||
jboolean gotJREPath = GetJREPath(jrePath, sizeof(jrePath), GetArch(), JNI_FALSE);
|
||||
jboolean gotJREPath = GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE);
|
||||
if (!gotJREPath) {
|
||||
JLI_ReportErrorMessage("Failed to GetJREPath()");
|
||||
return NULL;
|
||||
@ -229,7 +217,7 @@ static InvocationFunctions *GetExportedJNIFunctions() {
|
||||
}
|
||||
|
||||
char jvmPath[PATH_MAX];
|
||||
jboolean gotJVMPath = GetJVMPath(jrePath, preferredJVM, jvmPath, sizeof(jvmPath), GetArch(), CURRENT_DATA_MODEL);
|
||||
jboolean gotJVMPath = GetJVMPath(jrePath, preferredJVM, jvmPath, sizeof(jvmPath), CURRENT_DATA_MODEL);
|
||||
if (!gotJVMPath) {
|
||||
JLI_ReportErrorMessage("Failed to GetJVMPath()");
|
||||
return NULL;
|
||||
@ -390,7 +378,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
|
||||
/* Check data model flags, and exec process, if needed */
|
||||
{
|
||||
char *arch = (char *)GetArch(); /* like sparc or sparcv9 */
|
||||
char * jvmtype = NULL;
|
||||
int argc = *pargc;
|
||||
char **argv = *pargv;
|
||||
@ -462,7 +449,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
jvmpath does not exist */
|
||||
if (wanted == running) {
|
||||
/* Find out where the JRE is that we will be using. */
|
||||
if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
|
||||
if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE) ) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR1);
|
||||
exit(2);
|
||||
}
|
||||
@ -481,7 +468,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
exit(4);
|
||||
}
|
||||
|
||||
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, wanted)) {
|
||||
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, wanted)) {
|
||||
JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
|
||||
exit(4);
|
||||
}
|
||||
@ -502,7 +489,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
#if defined(DUAL_MODE)
|
||||
if (running != wanted) {
|
||||
/* Find out where the JRE is that we will be using. */
|
||||
if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) {
|
||||
if (!GetJREPath(jrepath, so_jrepath, JNI_TRUE)) {
|
||||
/* give up and let other code report error message */
|
||||
JLI_ReportErrorMessage(JRE_ERROR2, wanted);
|
||||
exit(1);
|
||||
@ -526,7 +513,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
}
|
||||
|
||||
/* exec child can do error checking on the existence of the path */
|
||||
jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted), wanted);
|
||||
jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, wanted);
|
||||
}
|
||||
#else /* ! DUAL_MODE */
|
||||
JLI_ReportErrorMessage(JRE_ERROR2, wanted);
|
||||
@ -579,7 +566,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
*/
|
||||
static jboolean
|
||||
GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
char *jvmpath, jint jvmpathsize, const char * arch, int bitsWanted)
|
||||
char *jvmpath, jint jvmpathsize, int bitsWanted)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
@ -613,7 +600,7 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
* Find path to JRE based on .exe's location or registry settings.
|
||||
*/
|
||||
static jboolean
|
||||
GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
|
||||
GetJREPath(char *path, jint pathsize, jboolean speculative)
|
||||
{
|
||||
char libjava[MAXPATHLEN];
|
||||
|
||||
@ -841,7 +828,7 @@ static void* hSplashLib = NULL;
|
||||
void* SplashProcAddress(const char* name) {
|
||||
if (!hSplashLib) {
|
||||
char jrePath[PATH_MAX];
|
||||
if (!GetJREPath(jrePath, sizeof(jrePath), GetArch(), JNI_FALSE)) {
|
||||
if (!GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE)) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR1);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -317,7 +317,7 @@ public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
this(null, je);
|
||||
}
|
||||
boolean isClassFile() {
|
||||
if (!name.endsWith(".class")) {
|
||||
if (!name.endsWith(".class") || name.endsWith("module-info.class")) {
|
||||
return false;
|
||||
}
|
||||
for (String prefix = name;;) {
|
||||
|
@ -14,15 +14,6 @@ pack.code.attribute.CharacterRangeTable = NH[PHPOHIIH]
|
||||
pack.class.attribute.SourceID = RUH
|
||||
pack.class.attribute.CompilationID = RUH
|
||||
|
||||
# Module attributes, supported by the tool and not JSR-200
|
||||
pack.class.attribute.Module = RUHFHNH[RUHFH]NH[RUHFHNH[RUH]]NH[RUHFHNH[RUH]]NH[RCH]NH[RCHNH[RCH]]
|
||||
pack.class.attribute.ModulePackages = NH[RUH]
|
||||
pack.class.attribute.ModuleVersion = RUH
|
||||
pack.class.attribute.ModuleMainClass = RCH
|
||||
pack.class.attribute.ModuleTarget = RUHRUHRUH
|
||||
pack.class.attribute.ModuleHashes = RUHNH[RUHNH[B]]
|
||||
|
||||
|
||||
# Note: Zero-length ("marker") attributes do not need to be specified here.
|
||||
# They are automatically defined to have an empty layout.
|
||||
#pack.class.attribute.Deprecated =
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -79,7 +79,8 @@ class FdLibm {
|
||||
*/
|
||||
private static double __LO(double x, int low) {
|
||||
long transX = Double.doubleToRawLongBits(x);
|
||||
return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L)|low );
|
||||
return Double.longBitsToDouble((transX & 0xFFFF_FFFF_0000_0000L) |
|
||||
(low & 0x0000_0000_FFFF_FFFFL));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +97,8 @@ class FdLibm {
|
||||
*/
|
||||
private static double __HI(double x, int high) {
|
||||
long transX = Double.doubleToRawLongBits(x);
|
||||
return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL)|( ((long)high)) << 32 );
|
||||
return Double.longBitsToDouble((transX & 0x0000_0000_FFFF_FFFFL) |
|
||||
( ((long)high)) << 32 );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -580,4 +582,152 @@ class FdLibm {
|
||||
return s * z;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exponential of x.
|
||||
*
|
||||
* Method
|
||||
* 1. Argument reduction:
|
||||
* Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658.
|
||||
* Given x, find r and integer k such that
|
||||
*
|
||||
* x = k*ln2 + r, |r| <= 0.5*ln2.
|
||||
*
|
||||
* Here r will be represented as r = hi-lo for better
|
||||
* accuracy.
|
||||
*
|
||||
* 2. Approximation of exp(r) by a special rational function on
|
||||
* the interval [0,0.34658]:
|
||||
* Write
|
||||
* R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ...
|
||||
* We use a special Reme algorithm on [0,0.34658] to generate
|
||||
* a polynomial of degree 5 to approximate R. The maximum error
|
||||
* of this polynomial approximation is bounded by 2**-59. In
|
||||
* other words,
|
||||
* R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5
|
||||
* (where z=r*r, and the values of P1 to P5 are listed below)
|
||||
* and
|
||||
* | 5 | -59
|
||||
* | 2.0+P1*z+...+P5*z - R(z) | <= 2
|
||||
* | |
|
||||
* The computation of exp(r) thus becomes
|
||||
* 2*r
|
||||
* exp(r) = 1 + -------
|
||||
* R - r
|
||||
* r*R1(r)
|
||||
* = 1 + r + ----------- (for better accuracy)
|
||||
* 2 - R1(r)
|
||||
* where
|
||||
* 2 4 10
|
||||
* R1(r) = r - (P1*r + P2*r + ... + P5*r ).
|
||||
*
|
||||
* 3. Scale back to obtain exp(x):
|
||||
* From step 1, we have
|
||||
* exp(x) = 2^k * exp(r)
|
||||
*
|
||||
* Special cases:
|
||||
* exp(INF) is INF, exp(NaN) is NaN;
|
||||
* exp(-INF) is 0, and
|
||||
* for finite argument, only exp(0)=1 is exact.
|
||||
*
|
||||
* Accuracy:
|
||||
* according to an error analysis, the error is always less than
|
||||
* 1 ulp (unit in the last place).
|
||||
*
|
||||
* Misc. info.
|
||||
* For IEEE double
|
||||
* if x > 7.09782712893383973096e+02 then exp(x) overflow
|
||||
* if x < -7.45133219101941108420e+02 then exp(x) underflow
|
||||
*
|
||||
* Constants:
|
||||
* The hexadecimal values are the intended ones for the following
|
||||
* constants. The decimal values may be used, provided that the
|
||||
* compiler will convert from decimal to binary accurately enough
|
||||
* to produce the hexadecimal values shown.
|
||||
*/
|
||||
static class Exp {
|
||||
private static final double one = 1.0;
|
||||
private static final double[] half = {0.5, -0.5,};
|
||||
private static final double huge = 1.0e+300;
|
||||
private static final double twom1000= 0x1.0p-1000; // 9.33263618503218878990e-302 = 2^-1000
|
||||
private static final double o_threshold= 0x1.62e42fefa39efp9; // 7.09782712893383973096e+02
|
||||
private static final double u_threshold= -0x1.74910d52d3051p9; // -7.45133219101941108420e+02;
|
||||
private static final double[] ln2HI ={ 0x1.62e42feep-1, // 6.93147180369123816490e-01
|
||||
-0x1.62e42feep-1}; // -6.93147180369123816490e-01
|
||||
private static final double[] ln2LO ={ 0x1.a39ef35793c76p-33, // 1.90821492927058770002e-10
|
||||
-0x1.a39ef35793c76p-33}; // -1.90821492927058770002e-10
|
||||
private static final double invln2 = 0x1.71547652b82fep0; // 1.44269504088896338700e+00
|
||||
|
||||
private static final double P1 = 0x1.555555555553ep-3; // 1.66666666666666019037e-01
|
||||
private static final double P2 = -0x1.6c16c16bebd93p-9; // -2.77777777770155933842e-03
|
||||
private static final double P3 = 0x1.1566aaf25de2cp-14; // 6.61375632143793436117e-05
|
||||
private static final double P4 = -0x1.bbd41c5d26bf1p-20; // -1.65339022054652515390e-06
|
||||
private static final double P5 = 0x1.6376972bea4d0p-25; // 4.13813679705723846039e-08
|
||||
|
||||
// should be able to forgo strictfp due to controlled over/underflow
|
||||
public static strictfp double compute(double x) {
|
||||
double y;
|
||||
double hi = 0.0;
|
||||
double lo = 0.0;
|
||||
double c;
|
||||
double t;
|
||||
int k = 0;
|
||||
int xsb;
|
||||
/*unsigned*/ int hx;
|
||||
|
||||
hx = __HI(x); /* high word of x */
|
||||
xsb = (hx >> 31) & 1; /* sign bit of x */
|
||||
hx &= 0x7fffffff; /* high word of |x| */
|
||||
|
||||
/* filter out non-finite argument */
|
||||
if (hx >= 0x40862E42) { /* if |x| >= 709.78... */
|
||||
if (hx >= 0x7ff00000) {
|
||||
if (((hx & 0xfffff) | __LO(x)) != 0)
|
||||
return x + x; /* NaN */
|
||||
else
|
||||
return (xsb == 0) ? x : 0.0; /* exp(+-inf) = {inf, 0} */
|
||||
}
|
||||
if (x > o_threshold)
|
||||
return huge * huge; /* overflow */
|
||||
if (x < u_threshold) // unsigned compare needed here?
|
||||
return twom1000 * twom1000; /* underflow */
|
||||
}
|
||||
|
||||
/* argument reduction */
|
||||
if (hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
|
||||
if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
|
||||
hi = x - ln2HI[xsb];
|
||||
lo=ln2LO[xsb];
|
||||
k = 1 - xsb - xsb;
|
||||
} else {
|
||||
k = (int)(invln2 * x + half[xsb]);
|
||||
t = k;
|
||||
hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */
|
||||
lo = t*ln2LO[0];
|
||||
}
|
||||
x = hi - lo;
|
||||
} else if (hx < 0x3e300000) { /* when |x|<2**-28 */
|
||||
if (huge + x > one)
|
||||
return one + x; /* trigger inexact */
|
||||
} else {
|
||||
k = 0;
|
||||
}
|
||||
|
||||
/* x is now in primary range */
|
||||
t = x * x;
|
||||
c = x - t*(P1 + t*(P2 + t*(P3 + t*(P4 + t*P5))));
|
||||
if (k == 0)
|
||||
return one - ((x*c)/(c - 2.0) - x);
|
||||
else
|
||||
y = one - ((lo - (x*c)/(2.0 - c)) - hi);
|
||||
|
||||
if(k >= -1021) {
|
||||
y = __HI(y, __HI(y) + (k << 20)); /* add k to y's exponent */
|
||||
return y;
|
||||
} else {
|
||||
y = __HI(y, __HI(y) + ((k + 1000) << 20)); /* add k to y's exponent */
|
||||
return y * twom1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,10 +26,13 @@
|
||||
package java.lang;
|
||||
|
||||
import jdk.internal.loader.BuiltinClassLoader;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleReferenceImpl;
|
||||
|
||||
import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Module;
|
||||
import java.util.HashSet;
|
||||
@ -477,13 +480,16 @@ public final class StackTraceElement implements java.io.Serializable {
|
||||
static Set<String> HASHED_MODULES = hashedModules();
|
||||
|
||||
static Set<String> hashedModules() {
|
||||
Module javaBase = Layer.boot().findModule("java.base").get();
|
||||
Optional<ModuleHashes> ohashes =
|
||||
SharedSecrets.getJavaLangModuleAccess()
|
||||
.hashes(javaBase.getDescriptor());
|
||||
|
||||
if (ohashes.isPresent()) {
|
||||
Set<String> names = new HashSet<>(ohashes.get().names());
|
||||
Optional<ResolvedModule> resolvedModule = Layer.boot()
|
||||
.configuration()
|
||||
.findModule("java.base");
|
||||
assert resolvedModule.isPresent();
|
||||
ModuleReference mref = resolvedModule.get().reference();
|
||||
assert mref instanceof ModuleReferenceImpl;
|
||||
ModuleHashes hashes = ((ModuleReferenceImpl)mref).recordedHashes();
|
||||
if (hashes != null) {
|
||||
Set<String> names = new HashSet<>(hashes.names());
|
||||
names.add("java.base");
|
||||
return names;
|
||||
}
|
||||
|
@ -227,7 +227,9 @@ public final class StrictMath {
|
||||
* @return the value <i>e</i><sup>{@code a}</sup>,
|
||||
* where <i>e</i> is the base of the natural logarithms.
|
||||
*/
|
||||
public static native double exp(double a);
|
||||
public static double exp(double a) {
|
||||
return FdLibm.Exp.compute(a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the natural logarithm (base <i>e</i>) of a {@code double}
|
||||
|
@ -172,6 +172,7 @@ public class MethodHandles {
|
||||
* @throws IllegalAccessException if the access check specified above fails
|
||||
* @throws SecurityException if denied by the security manager
|
||||
* @since 9
|
||||
* @see Lookup#dropLookupMode
|
||||
*/
|
||||
public static Lookup privateLookupIn(Class<?> targetClass, Lookup lookup) throws IllegalAccessException {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
@ -691,10 +692,15 @@ public class MethodHandles {
|
||||
* A lookup object on a new lookup class
|
||||
* {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object}
|
||||
* may have some mode bits set to zero.
|
||||
* Mode bits can also be
|
||||
* {@linkplain java.lang.invoke.MethodHandles.Lookup#dropLookupMode directly cleared}.
|
||||
* Once cleared, mode bits cannot be restored from the downgraded lookup object.
|
||||
* The purpose of this is to restrict access via the new lookup object,
|
||||
* so that it can access only names which can be reached by the original
|
||||
* lookup object, and also by the new lookup class.
|
||||
* @return the lookup modes, which limit the kinds of access performed by this lookup object
|
||||
* @see #in
|
||||
* @see #dropLookupMode
|
||||
*/
|
||||
public int lookupModes() {
|
||||
return allowedModes & ALL_MODES;
|
||||
@ -748,7 +754,8 @@ public class MethodHandles {
|
||||
* which may change due to this operation.
|
||||
*
|
||||
* @param requestedLookupClass the desired lookup class for the new lookup object
|
||||
* @return a lookup object which reports the desired lookup class
|
||||
* @return a lookup object which reports the desired lookup class, or the same object
|
||||
* if there is no change
|
||||
* @throws NullPointerException if the argument is null
|
||||
*/
|
||||
public Lookup in(Class<?> requestedLookupClass) {
|
||||
@ -788,6 +795,40 @@ public class MethodHandles {
|
||||
return new Lookup(requestedLookupClass, newModes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a lookup on the same lookup class which this lookup object
|
||||
* finds members, but with a lookup mode that has lost the given lookup mode.
|
||||
* The lookup mode to drop is one of {@link #PUBLIC PUBLIC}, {@link #MODULE
|
||||
* MODULE}, {@link #PACKAGE PACKAGE}, {@link #PROTECTED PROTECTED} or {@link #PRIVATE PRIVATE}.
|
||||
* {@link #PROTECTED PROTECTED} is always dropped and so the resulting lookup
|
||||
* mode will never have this access capability. When dropping {@code PACKAGE}
|
||||
* then the resulting lookup will not have {@code PACKAGE} or {@code PRIVATE}
|
||||
* access. When dropping {@code MODULE} then the resulting lookup will not
|
||||
* have {@code MODULE}, {@code PACKAGE}, or {@code PRIVATE} access. If {@code
|
||||
* PUBLIC} is dropped then the resulting lookup has no access.
|
||||
* @param modeToDrop the lookup mode to drop
|
||||
* @return a lookup object which lacks the indicated mode, or the same object if there is no change
|
||||
* @throws IllegalArgumentException if {@code modeToDrop} is not one of {@code PUBLIC},
|
||||
* {@code MODULE}, {@code PACKAGE}, {@code PROTECTED} or {@code PRIVATE}
|
||||
* @since 9
|
||||
* @see MethodHandles#privateLookupIn
|
||||
*/
|
||||
public Lookup dropLookupMode(int modeToDrop) {
|
||||
int oldModes = lookupModes();
|
||||
int newModes = oldModes & ~(modeToDrop | PROTECTED);
|
||||
switch (modeToDrop) {
|
||||
case PUBLIC: newModes &= ~(ALL_MODES); break;
|
||||
case MODULE: newModes &= ~(PACKAGE | PRIVATE); break;
|
||||
case PACKAGE: newModes &= ~(PRIVATE); break;
|
||||
case PROTECTED:
|
||||
case PRIVATE: break;
|
||||
default: throw new IllegalArgumentException(modeToDrop + " is not a valid mode to drop");
|
||||
}
|
||||
if (newModes == oldModes) return this; // return self if no change
|
||||
return new Lookup(lookupClass(), newModes);
|
||||
}
|
||||
|
||||
// Make sure outer class is initialized first.
|
||||
static { IMPL_NAMES.getClass(); }
|
||||
|
||||
|
@ -29,7 +29,6 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -38,7 +37,6 @@ import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -52,7 +50,7 @@ import static jdk.internal.module.Checks.*;
|
||||
import static java.util.Objects.*;
|
||||
|
||||
import jdk.internal.module.Checks;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleInfo;
|
||||
|
||||
|
||||
/**
|
||||
@ -123,8 +121,9 @@ public class ModuleDescriptor
|
||||
|
||||
private final Set<Modifier> mods;
|
||||
private final String name;
|
||||
private final Version compiledVersion;
|
||||
|
||||
private Requires(Set<Modifier> ms, String mn) {
|
||||
private Requires(Set<Modifier> ms, String mn, Version v) {
|
||||
if (ms.isEmpty()) {
|
||||
ms = Collections.emptySet();
|
||||
} else {
|
||||
@ -132,11 +131,13 @@ public class ModuleDescriptor
|
||||
}
|
||||
this.mods = ms;
|
||||
this.name = mn;
|
||||
this.compiledVersion = v;
|
||||
}
|
||||
|
||||
private Requires(Set<Modifier> ms, String mn, boolean unused) {
|
||||
private Requires(Set<Modifier> ms, String mn, Version v, boolean unused) {
|
||||
this.mods = ms;
|
||||
this.name = mn;
|
||||
this.compiledVersion = v;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,13 +158,27 @@ public class ModuleDescriptor
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version of the module if recorded at compile-time.
|
||||
*
|
||||
* @return The version of the module if recorded at compile-time
|
||||
*/
|
||||
public Optional<Version> compiledVersion() {
|
||||
return Optional.ofNullable(compiledVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this module dependence to another.
|
||||
*
|
||||
* <p> Two {@code Requires} objects are compared by comparing their
|
||||
* module name lexicographically. Where the module names are equal then
|
||||
* the sets of modifiers are compared based on a value computed from the
|
||||
* ordinal of each modifier. </p>
|
||||
* ordinal of each modifier. Where the module names are equal and the
|
||||
* set of modifiers are equal then the version of the modules 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>
|
||||
*
|
||||
* @return A negative integer, zero, or a positive integer if this module
|
||||
* dependence is less than, equal to, or greater than the given
|
||||
@ -174,8 +189,24 @@ public class ModuleDescriptor
|
||||
int c = this.name().compareTo(that.name());
|
||||
if (c != 0)
|
||||
return c;
|
||||
// same name, compare by modifiers
|
||||
return Long.compare(this.modsValue(), that.modsValue());
|
||||
|
||||
// modifiers
|
||||
c = Long.compare(this.modsValue(), that.modsValue());
|
||||
if (c != 0)
|
||||
return c;
|
||||
|
||||
// compiledVersion
|
||||
if (this.compiledVersion != null) {
|
||||
if (that.compiledVersion != null)
|
||||
c = this.compiledVersion.compareTo(that.compiledVersion);
|
||||
else
|
||||
c = 1;
|
||||
} else {
|
||||
if (that.compiledVersion != null)
|
||||
c = -1;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,7 +226,9 @@ public class ModuleDescriptor
|
||||
*
|
||||
* <p> If the given object is not a {@code Requires} then this method
|
||||
* returns {@code false}. Two module dependence objects are equal if
|
||||
* the module names are equal and set of modifiers are equal. </p>
|
||||
* the module names are equal, set of modifiers are equal, and the
|
||||
* compiled version of both modules is equal or not recorded for
|
||||
* both modules. </p>
|
||||
*
|
||||
* <p> This method satisfies the general contract of the {@link
|
||||
* java.lang.Object#equals(Object) Object.equals} method. </p>
|
||||
@ -211,21 +244,25 @@ public class ModuleDescriptor
|
||||
if (!(ob instanceof Requires))
|
||||
return false;
|
||||
Requires that = (Requires)ob;
|
||||
return (name.equals(that.name) && mods.equals(that.mods));
|
||||
return name.equals(that.name) && mods.equals(that.mods)
|
||||
&& Objects.equals(compiledVersion, that.compiledVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hash code for this module dependence.
|
||||
*
|
||||
* <p> The hash code is based upon the module name and modifiers. It
|
||||
* satisfies the general contract of the {@link Object#hashCode
|
||||
* Object.hashCode} method. </p>
|
||||
* <p> The hash code is based upon the module name, modifiers, and the
|
||||
* module version if recorded at compile time. It satisfies the general
|
||||
* contract of the {@link Object#hashCode Object.hashCode} method. </p>
|
||||
*
|
||||
* @return The hash-code value for this module dependence
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() * 43 + mods.hashCode();
|
||||
int hash = name.hashCode() * 43 + mods.hashCode();
|
||||
if (compiledVersion != null)
|
||||
hash = hash * 43 + compiledVersion.hashCode();
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -235,7 +272,13 @@ public class ModuleDescriptor
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return ModuleDescriptor.toString(mods, name);
|
||||
String what;
|
||||
if (compiledVersion != null) {
|
||||
what = name() + " (@" + compiledVersion + ")";
|
||||
} else {
|
||||
what = name();
|
||||
}
|
||||
return ModuleDescriptor.toString(mods, what);
|
||||
}
|
||||
}
|
||||
|
||||
@ -967,9 +1010,8 @@ public class ModuleDescriptor
|
||||
}
|
||||
|
||||
|
||||
|
||||
// From module declarations
|
||||
private final String name;
|
||||
private final Version version;
|
||||
private final boolean open;
|
||||
|
||||
// Indicates if synthesised for a JAR file found on the module path
|
||||
@ -984,17 +1026,16 @@ public class ModuleDescriptor
|
||||
private final Set<String> uses;
|
||||
private final Set<Provides> provides;
|
||||
|
||||
// "Extended" information, added post-compilation by tools
|
||||
private final Version version;
|
||||
// Added post-compilation by tools
|
||||
private final Set<String> packages;
|
||||
private final String mainClass;
|
||||
private final String osName;
|
||||
private final String osArch;
|
||||
private final String osVersion;
|
||||
private final Set<String> packages;
|
||||
private final ModuleHashes hashes;
|
||||
|
||||
|
||||
private ModuleDescriptor(String name,
|
||||
Version version,
|
||||
boolean open,
|
||||
boolean automatic,
|
||||
boolean synthetic,
|
||||
@ -1003,16 +1044,14 @@ public class ModuleDescriptor
|
||||
Set<Opens> opens,
|
||||
Set<String> uses,
|
||||
Set<Provides> provides,
|
||||
Version version,
|
||||
Set<String> packages,
|
||||
String mainClass,
|
||||
String osName,
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes)
|
||||
String osVersion)
|
||||
{
|
||||
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.open = open;
|
||||
this.automatic = automatic;
|
||||
this.synthetic = synthetic;
|
||||
@ -1020,18 +1059,16 @@ public class ModuleDescriptor
|
||||
assert (requires.stream().map(Requires::name).distinct().count()
|
||||
== requires.size());
|
||||
this.requires = emptyOrUnmodifiableSet(requires);
|
||||
|
||||
this.exports = emptyOrUnmodifiableSet(exports);
|
||||
this.opens = emptyOrUnmodifiableSet(opens);
|
||||
this.uses = emptyOrUnmodifiableSet(uses);
|
||||
this.provides = emptyOrUnmodifiableSet(provides);
|
||||
this.version = version;
|
||||
|
||||
this.packages = emptyOrUnmodifiableSet(packages);
|
||||
this.mainClass = mainClass;
|
||||
this.osName = osName;
|
||||
this.osArch = osArch;
|
||||
this.osVersion = osVersion;
|
||||
this.hashes = hashes;
|
||||
this.packages = emptyOrUnmodifiableSet(packages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1039,6 +1076,7 @@ public class ModuleDescriptor
|
||||
*/
|
||||
ModuleDescriptor(ModuleDescriptor md, Set<String> pkgs) {
|
||||
this.name = md.name;
|
||||
this.version = md.version;
|
||||
this.open = md.open;
|
||||
this.automatic = md.automatic;
|
||||
this.synthetic = md.synthetic;
|
||||
@ -1049,16 +1087,14 @@ public class ModuleDescriptor
|
||||
this.uses = md.uses;
|
||||
this.provides = md.provides;
|
||||
|
||||
this.version = md.version;
|
||||
Set<String> packages = new HashSet<>(md.packages);
|
||||
packages.addAll(pkgs);
|
||||
this.packages = emptyOrUnmodifiableSet(packages);
|
||||
|
||||
this.mainClass = md.mainClass;
|
||||
this.osName = md.osName;
|
||||
this.osArch = md.osArch;
|
||||
this.osVersion = md.osVersion;
|
||||
this.hashes = null; // need to ignore
|
||||
|
||||
Set<String> packages = new HashSet<>(md.packages);
|
||||
packages.addAll(pkgs);
|
||||
this.packages = emptyOrUnmodifiableSet(packages);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1066,6 +1102,7 @@ public class ModuleDescriptor
|
||||
* The arguments are pre-validated and sets are unmodifiable sets.
|
||||
*/
|
||||
ModuleDescriptor(String name,
|
||||
Version version,
|
||||
boolean open,
|
||||
boolean automatic,
|
||||
boolean synthetic,
|
||||
@ -1074,16 +1111,15 @@ public class ModuleDescriptor
|
||||
Set<Opens> opens,
|
||||
Set<String> uses,
|
||||
Set<Provides> provides,
|
||||
Version version,
|
||||
Set<String> packages,
|
||||
String mainClass,
|
||||
String osName,
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes,
|
||||
int hashCode,
|
||||
boolean unused) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
this.open = open;
|
||||
this.automatic = automatic;
|
||||
this.synthetic = synthetic;
|
||||
@ -1093,12 +1129,10 @@ public class ModuleDescriptor
|
||||
this.uses = uses;
|
||||
this.provides = provides;
|
||||
this.packages = packages;
|
||||
this.version = version;
|
||||
this.mainClass = mainClass;
|
||||
this.osName = osName;
|
||||
this.osArch = osArch;
|
||||
this.osVersion = osVersion;
|
||||
this.hashes = hashes;
|
||||
this.hash = hashCode;
|
||||
}
|
||||
|
||||
@ -1284,13 +1318,6 @@ public class ModuleDescriptor
|
||||
return packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object with the hashes of other modules
|
||||
*/
|
||||
Optional<ModuleHashes> hashes() {
|
||||
return Optional.ofNullable(hashes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A builder used for building {@link ModuleDescriptor} objects.
|
||||
@ -1317,15 +1344,13 @@ public class ModuleDescriptor
|
||||
public static final class Builder {
|
||||
final String name;
|
||||
final boolean strict; // true if module names are checked
|
||||
boolean open;
|
||||
final boolean open;
|
||||
final boolean synthetic;
|
||||
boolean automatic;
|
||||
boolean synthetic;
|
||||
final Map<String, Requires> requires = new HashMap<>();
|
||||
|
||||
final Map<String, Exports> exports = new HashMap<>();
|
||||
final Map<String, Opens> opens = new HashMap<>();
|
||||
final Set<String> concealedPackages = new HashSet<>();
|
||||
|
||||
final Set<String> uses = new HashSet<>();
|
||||
final Map<String, Provides> provides = new HashMap<>();
|
||||
Version version;
|
||||
@ -1333,7 +1358,6 @@ public class ModuleDescriptor
|
||||
String osArch;
|
||||
String osVersion;
|
||||
String mainClass;
|
||||
ModuleHashes hashes;
|
||||
|
||||
/**
|
||||
* Initializes a new builder with the given module name.
|
||||
@ -1341,14 +1365,11 @@ public class ModuleDescriptor
|
||||
* @param strict
|
||||
* Indicates whether module names are checked or not
|
||||
*/
|
||||
Builder(String name, boolean strict) {
|
||||
this.strict = strict;
|
||||
Builder(String name, boolean strict, boolean open, boolean synthetic) {
|
||||
this.name = (strict) ? requireModuleName(name) : name;
|
||||
}
|
||||
|
||||
/* package */ Builder open(boolean open) {
|
||||
this.strict = strict;
|
||||
this.open = open;
|
||||
return this;
|
||||
this.synthetic = synthetic;
|
||||
}
|
||||
|
||||
/* package */ Builder automatic(boolean automatic) {
|
||||
@ -1356,10 +1377,20 @@ public class ModuleDescriptor
|
||||
return this;
|
||||
}
|
||||
|
||||
/* package */ boolean isOpen() { return open; }
|
||||
/**
|
||||
* Returns the set of packages that are exported (unconditionally or
|
||||
* unconditionally).
|
||||
*/
|
||||
/* package */ Set<String> exportedPackages() {
|
||||
return exports.keySet();
|
||||
}
|
||||
|
||||
/* package */ boolean isAutomatic() {
|
||||
return automatic;
|
||||
/**
|
||||
* Returns the set of packages that are opened (unconditionally or
|
||||
* unconditionally).
|
||||
*/
|
||||
/* package */Set<String> openPackages() {
|
||||
return opens.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1387,6 +1418,36 @@ public class ModuleDescriptor
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a dependence on a module with the given (and possibly empty)
|
||||
* set of modifiers. The dependence includes the version of the
|
||||
* module that that was recorded at compile-time.
|
||||
*
|
||||
* @param ms
|
||||
* The set of modifiers
|
||||
* @param mn
|
||||
* The module name
|
||||
* @param compiledVersion
|
||||
* The version of the module recorded at compile-time
|
||||
*
|
||||
* @return This builder
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the module name is {@code null}, is not a legal Java
|
||||
* identifier, or is equal to the module name that this builder
|
||||
* was initialized to build
|
||||
* @throws IllegalStateException
|
||||
* If the dependence on the module has already been declared
|
||||
*/
|
||||
public Builder requires(Set<Requires.Modifier> ms,
|
||||
String mn,
|
||||
Version compiledVersion) {
|
||||
Objects.requireNonNull(compiledVersion);
|
||||
if (strict)
|
||||
mn = requireModuleName(mn);
|
||||
return requires(new Requires(ms, mn, compiledVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a dependence on a module with the given (and possibly empty)
|
||||
* set of modifiers.
|
||||
@ -1408,7 +1469,7 @@ public class ModuleDescriptor
|
||||
public Builder requires(Set<Requires.Modifier> ms, String mn) {
|
||||
if (strict)
|
||||
mn = requireModuleName(mn);
|
||||
return requires(new Requires(ms, mn));
|
||||
return requires(new Requires(ms, mn, null));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1705,17 +1766,6 @@ public class ModuleDescriptor
|
||||
return opens(Collections.emptySet(), pn);
|
||||
}
|
||||
|
||||
|
||||
// Used by ModuleInfo, after a packageFinder is invoked
|
||||
/* package */ Set<String> exportedAndOpenPackages() {
|
||||
if (opens.isEmpty())
|
||||
return exports.keySet();
|
||||
Set<String> result = new HashSet<>();
|
||||
result.addAll(exports.keySet());
|
||||
result.addAll(opens.keySet());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a service dependence.
|
||||
*
|
||||
@ -1789,7 +1839,6 @@ public class ModuleDescriptor
|
||||
if (providerNames.isEmpty())
|
||||
throw new IllegalArgumentException("Empty providers set");
|
||||
providerNames.forEach(Checks::requireServiceProviderName);
|
||||
|
||||
provides.put(service, p);
|
||||
return this;
|
||||
}
|
||||
@ -1914,7 +1963,7 @@ public class ModuleDescriptor
|
||||
* If {@code mainClass} is null or is not a legal Java identifier
|
||||
*/
|
||||
public Builder mainClass(String mc) {
|
||||
mainClass = requireJavaIdentifier("main class name", mc);
|
||||
mainClass = requireBinaryName("main class name", mc);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -1972,16 +2021,6 @@ public class ModuleDescriptor
|
||||
return this;
|
||||
}
|
||||
|
||||
/* package */ Builder hashes(ModuleHashes hashes) {
|
||||
this.hashes = hashes;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* package */ Builder synthetic(boolean v) {
|
||||
this.synthetic = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a {@code ModuleDescriptor} from its components.
|
||||
*
|
||||
@ -1990,7 +2029,9 @@ public class ModuleDescriptor
|
||||
public ModuleDescriptor build() {
|
||||
Set<Requires> requires = new HashSet<>(this.requires.values());
|
||||
|
||||
Set<String> packages = new HashSet<>(exportedAndOpenPackages());
|
||||
Set<String> packages = new HashSet<>();
|
||||
packages.addAll(exports.keySet());
|
||||
packages.addAll(opens.keySet());
|
||||
packages.addAll(concealedPackages);
|
||||
|
||||
Set<Exports> exports = new HashSet<>(this.exports.values());
|
||||
@ -1999,6 +2040,7 @@ public class ModuleDescriptor
|
||||
Set<Provides> provides = new HashSet<>(this.provides.values());
|
||||
|
||||
return new ModuleDescriptor(name,
|
||||
version,
|
||||
open,
|
||||
automatic,
|
||||
synthetic,
|
||||
@ -2007,13 +2049,11 @@ public class ModuleDescriptor
|
||||
opens,
|
||||
uses,
|
||||
provides,
|
||||
version,
|
||||
packages,
|
||||
mainClass,
|
||||
osName,
|
||||
osArch,
|
||||
osVersion,
|
||||
packages,
|
||||
hashes);
|
||||
osVersion);
|
||||
}
|
||||
|
||||
}
|
||||
@ -2088,8 +2128,7 @@ public class ModuleDescriptor
|
||||
&& Objects.equals(osName, that.osName)
|
||||
&& Objects.equals(osArch, that.osArch)
|
||||
&& Objects.equals(osVersion, that.osVersion)
|
||||
&& Objects.equals(packages, that.packages)
|
||||
&& Objects.equals(hashes, that.hashes));
|
||||
&& Objects.equals(packages, that.packages));
|
||||
}
|
||||
|
||||
private transient int hash; // cached hash code
|
||||
@ -2122,7 +2161,6 @@ public class ModuleDescriptor
|
||||
hc = hc * 43 + Objects.hashCode(osArch);
|
||||
hc = hc * 43 + Objects.hashCode(osVersion);
|
||||
hc = hc * 43 + Objects.hashCode(packages);
|
||||
hc = hc * 43 + Objects.hashCode(hashes);
|
||||
if (hc == 0)
|
||||
hc = -1;
|
||||
hash = hc;
|
||||
@ -2145,7 +2183,7 @@ public class ModuleDescriptor
|
||||
if (!requires.isEmpty())
|
||||
sb.append(", ").append(requires);
|
||||
if (!uses.isEmpty())
|
||||
sb.append(", ").append(uses);
|
||||
sb.append(", uses: ").append(uses);
|
||||
if (!exports.isEmpty())
|
||||
sb.append(", exports: ").append(exports);
|
||||
if (!opens.isEmpty())
|
||||
@ -2171,7 +2209,7 @@ public class ModuleDescriptor
|
||||
* identifier
|
||||
*/
|
||||
public static Builder module(String name) {
|
||||
return new Builder(name, true);
|
||||
return new Builder(name, true, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2199,7 +2237,7 @@ public class ModuleDescriptor
|
||||
* identifier
|
||||
*/
|
||||
public static Builder openModule(String name) {
|
||||
return new Builder(name, true).open(true);
|
||||
return new Builder(name, true, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2221,7 +2259,7 @@ public class ModuleDescriptor
|
||||
* @see ModuleFinder#of(Path[])
|
||||
*/
|
||||
public static Builder automaticModule(String name) {
|
||||
return new Builder(name, true).automatic(true);
|
||||
return new Builder(name, true, false, false).automatic(true);
|
||||
}
|
||||
|
||||
|
||||
@ -2263,7 +2301,7 @@ public class ModuleDescriptor
|
||||
Supplier<Set<String>> packageFinder)
|
||||
throws IOException
|
||||
{
|
||||
return ModuleInfo.read(in, requireNonNull(packageFinder));
|
||||
return ModuleInfo.read(in, requireNonNull(packageFinder)).descriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2281,7 +2319,7 @@ public class ModuleDescriptor
|
||||
* If an I/O error occurs reading from the input stream
|
||||
*/
|
||||
public static ModuleDescriptor read(InputStream in) throws IOException {
|
||||
return ModuleInfo.read(in, null);
|
||||
return ModuleInfo.read(in, null).descriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2320,7 +2358,7 @@ public class ModuleDescriptor
|
||||
public static ModuleDescriptor read(ByteBuffer bb,
|
||||
Supplier<Set<String>> packageFinder)
|
||||
{
|
||||
return ModuleInfo.read(bb, requireNonNull(packageFinder));
|
||||
return ModuleInfo.read(bb, requireNonNull(packageFinder)).descriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2336,7 +2374,7 @@ public class ModuleDescriptor
|
||||
* If an invalid module descriptor is detected
|
||||
*/
|
||||
public static ModuleDescriptor read(ByteBuffer bb) {
|
||||
return ModuleInfo.read(bb, null);
|
||||
return ModuleInfo.read(bb, null).descriptor();
|
||||
}
|
||||
|
||||
private static <K,V> Map<K,V> emptyOrUnmodifiableMap(Map<K,V> map) {
|
||||
@ -2377,18 +2415,26 @@ public class ModuleDescriptor
|
||||
jdk.internal.misc.SharedSecrets
|
||||
.setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() {
|
||||
@Override
|
||||
public Builder newModuleBuilder(String mn, boolean strict) {
|
||||
return new Builder(mn, strict);
|
||||
public Builder newModuleBuilder(String mn,
|
||||
boolean strict,
|
||||
boolean open,
|
||||
boolean synthetic) {
|
||||
return new Builder(mn, strict, open, synthetic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder newOpenModuleBuilder(String mn, boolean strict) {
|
||||
return new Builder(mn, strict).open(true);
|
||||
public Set<String> exportedPackages(ModuleDescriptor.Builder builder) {
|
||||
return builder.exportedPackages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Requires newRequires(Set<Requires.Modifier> ms, String mn) {
|
||||
return new Requires(ms, mn, true);
|
||||
public Set<String> openPackages(ModuleDescriptor.Builder builder) {
|
||||
return builder.openPackages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v) {
|
||||
return new Requires(ms, mn, v, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2433,6 +2479,7 @@ public class ModuleDescriptor
|
||||
|
||||
@Override
|
||||
public ModuleDescriptor newModuleDescriptor(String name,
|
||||
Version version,
|
||||
boolean open,
|
||||
boolean automatic,
|
||||
boolean synthetic,
|
||||
@ -2441,15 +2488,14 @@ public class ModuleDescriptor
|
||||
Set<Opens> opens,
|
||||
Set<String> uses,
|
||||
Set<Provides> provides,
|
||||
Version version,
|
||||
Set<String> packages,
|
||||
String mainClass,
|
||||
String osName,
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes,
|
||||
int hashCode) {
|
||||
return new ModuleDescriptor(name,
|
||||
version,
|
||||
open,
|
||||
automatic,
|
||||
synthetic,
|
||||
@ -2458,22 +2504,15 @@ public class ModuleDescriptor
|
||||
opens,
|
||||
uses,
|
||||
provides,
|
||||
version,
|
||||
packages,
|
||||
mainClass,
|
||||
osName,
|
||||
osArch,
|
||||
osVersion,
|
||||
packages,
|
||||
hashes,
|
||||
hashCode,
|
||||
false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
|
||||
return descriptor.hashes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration resolveRequiresAndUses(ModuleFinder finder,
|
||||
Collection<String> roots,
|
||||
@ -2482,20 +2521,6 @@ public class ModuleDescriptor
|
||||
{
|
||||
return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleReference newPatchedModule(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> s) {
|
||||
return new ModuleReference(descriptor, location, s, true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleFinder newModulePath(Runtime.Version version,
|
||||
boolean isLinkPhase,
|
||||
Path... entries) {
|
||||
return new ModulePath(version, isLinkPhase, entries);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,8 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.module.ModulePath;
|
||||
import jdk.internal.module.SystemModuleFinder;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
@ -137,7 +139,7 @@ public interface ModuleFinder {
|
||||
|
||||
/**
|
||||
* Returns a module finder that locates the <em>system modules</em>. The
|
||||
* system modules are typically linked into the Java run-time image.
|
||||
* system modules are the modules in the Java run-time image.
|
||||
* The module finder will always find {@code java.base}.
|
||||
*
|
||||
* <p> If there is a security manager set then its {@link
|
||||
@ -166,7 +168,7 @@ public interface ModuleFinder {
|
||||
|
||||
Path modules = Paths.get(home, "lib", "modules");
|
||||
if (Files.isRegularFile(modules)) {
|
||||
return new SystemModuleFinder();
|
||||
return SystemModuleFinder.getInstance();
|
||||
} else {
|
||||
Path mlib = Paths.get(home, "modules");
|
||||
if (Files.isDirectory(mlib)) {
|
||||
|
@ -26,96 +26,42 @@
|
||||
package java.lang.module;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.module.ModuleHashes.HashSupplier;
|
||||
|
||||
|
||||
/**
|
||||
* A reference to a module's content.
|
||||
*
|
||||
* <p> A module reference contains the module's descriptor and its location, if
|
||||
* known. It also has the ability to create a {@link ModuleReader} in order to
|
||||
* access the module's content, which may be inside the Java run-time system
|
||||
* itself or in an artifact such as a modular JAR file.
|
||||
* <p> A module reference is a concrete implementation of this class that
|
||||
* implements the abstract methods defined by this class. It contains the
|
||||
* module's descriptor and its location, if known. It also has the ability to
|
||||
* create a {@link ModuleReader} in order to access the module's content, which
|
||||
* may be inside the Java run-time system itself or in an artifact such as a
|
||||
* modular JAR file.
|
||||
*
|
||||
* @see ModuleFinder
|
||||
* @see ModuleReader
|
||||
* @since 9
|
||||
*/
|
||||
|
||||
public final class ModuleReference {
|
||||
public abstract class ModuleReference {
|
||||
|
||||
private final ModuleDescriptor descriptor;
|
||||
private final URI location;
|
||||
private final Supplier<ModuleReader> readerSupplier;
|
||||
|
||||
// true if this is a reference to a patched module
|
||||
private boolean patched;
|
||||
|
||||
// the function that computes the hash of this module reference
|
||||
private final HashSupplier hasher;
|
||||
|
||||
// cached hash to avoid needing to compute it many times
|
||||
private byte[] cachedHash;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class.
|
||||
*/
|
||||
ModuleReference(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier,
|
||||
boolean patched,
|
||||
HashSupplier hasher)
|
||||
|
||||
{
|
||||
this.descriptor = Objects.requireNonNull(descriptor);
|
||||
this.location = location;
|
||||
this.readerSupplier = Objects.requireNonNull(readerSupplier);
|
||||
this.patched = patched;
|
||||
this.hasher = hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class.
|
||||
*/
|
||||
ModuleReference(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier,
|
||||
HashSupplier hasher)
|
||||
|
||||
{
|
||||
this(descriptor, location, readerSupplier, false, hasher);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class.
|
||||
*
|
||||
* <p> The {@code readSupplier} parameter is the supplier of the {@link
|
||||
* ModuleReader} that may be used to read the module content. Its {@link
|
||||
* Supplier#get() get()} method throws {@link UncheckedIOException} if an
|
||||
* I/O error occurs opening the module content. The {@code get()} method
|
||||
* throws {@link SecurityException} if opening the module is denied by the
|
||||
* security manager.
|
||||
*
|
||||
* @param descriptor
|
||||
* The module descriptor
|
||||
* @param location
|
||||
* The module location or {@code null} if not known
|
||||
* @param readerSupplier
|
||||
* The {@code Supplier} of the {@code ModuleReader}
|
||||
*/
|
||||
public ModuleReference(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier)
|
||||
{
|
||||
this(descriptor, location, readerSupplier, false, null);
|
||||
protected ModuleReference(ModuleDescriptor descriptor, URI location) {
|
||||
this.descriptor = Objects.requireNonNull(descriptor);
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,11 +69,10 @@ public final class ModuleReference {
|
||||
*
|
||||
* @return The module descriptor
|
||||
*/
|
||||
public ModuleDescriptor descriptor() {
|
||||
public final ModuleDescriptor descriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the location of this module's content, if known.
|
||||
*
|
||||
@ -139,18 +84,13 @@ public final class ModuleReference {
|
||||
*
|
||||
* @return The location or an empty {@code Optional} if not known
|
||||
*/
|
||||
public Optional<URI> location() {
|
||||
public final Optional<URI> location() {
|
||||
return Optional.ofNullable(location);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Opens the module content for reading.
|
||||
*
|
||||
* <p> This method opens the module content by invoking the {@link
|
||||
* Supplier#get() get()} method of the {@code readSupplier} specified at
|
||||
* construction time. </p>
|
||||
*
|
||||
* @return A {@code ModuleReader} to read the module
|
||||
*
|
||||
* @throws IOException
|
||||
@ -158,113 +98,5 @@ public final class ModuleReference {
|
||||
* @throws SecurityException
|
||||
* If denied by the security manager
|
||||
*/
|
||||
public ModuleReader open() throws IOException {
|
||||
try {
|
||||
return readerSupplier.get();
|
||||
} catch (UncheckedIOException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this module has been patched via --patch-module.
|
||||
*/
|
||||
boolean isPatched() {
|
||||
return patched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash supplier for this module.
|
||||
*/
|
||||
HashSupplier hasher() {
|
||||
return hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hash of this module. Returns {@code null} if the hash
|
||||
* cannot be computed.
|
||||
*
|
||||
* @throws java.io.UncheckedIOException if an I/O error occurs
|
||||
*/
|
||||
byte[] computeHash(String algorithm) {
|
||||
byte[] result = cachedHash;
|
||||
if (result != null)
|
||||
return result;
|
||||
if (hasher == null)
|
||||
return null;
|
||||
cachedHash = result = hasher.generate(algorithm);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hash code for this module reference.
|
||||
*
|
||||
* <p> The hash code is based upon the components of the reference, and
|
||||
* satisfies the general contract of the {@link Object#hashCode
|
||||
* Object.hashCode} method. </p>
|
||||
*
|
||||
* @return The hash-code value for this module reference
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hc = hash;
|
||||
if (hc == 0) {
|
||||
hc = descriptor.hashCode();
|
||||
hc = 43 * hc + readerSupplier.hashCode();
|
||||
hc = 43 * hc + Objects.hashCode(location);
|
||||
hc = 43 * hc + Objects.hashCode(hasher);
|
||||
hc = 43 * hc + Boolean.hashCode(patched);
|
||||
if (hc == 0)
|
||||
hc = -1;
|
||||
hash = hc;
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
|
||||
private int hash;
|
||||
|
||||
/**
|
||||
* Tests this module reference for equality with the given object.
|
||||
*
|
||||
* <p> If the given object is not a {@code ModuleReference} then this
|
||||
* method returns {@code false}. Two module references are equal if their
|
||||
* module descriptors are equal, their locations are equal or both unknown,
|
||||
* and were created with equal supplier objects to access the module
|
||||
* content. </p>
|
||||
*
|
||||
* <p> This method satisfies the general contract of the {@link
|
||||
* java.lang.Object#equals(Object) Object.equals} method. </p>
|
||||
*
|
||||
* @param ob
|
||||
* the object to which this object is to be compared
|
||||
*
|
||||
* @return {@code true} if, and only if, the given object is a module
|
||||
* reference that is equal to this module reference
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object ob) {
|
||||
if (!(ob instanceof ModuleReference))
|
||||
return false;
|
||||
ModuleReference that = (ModuleReference)ob;
|
||||
|
||||
return Objects.equals(this.descriptor, that.descriptor)
|
||||
&& Objects.equals(this.location, that.location)
|
||||
&& Objects.equals(this.readerSupplier, that.readerSupplier)
|
||||
&& Objects.equals(this.hasher, that.hasher)
|
||||
&& this.patched == that.patched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing this module reference.
|
||||
*
|
||||
* @return A string describing this module reference
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return ("[module " + descriptor().name()
|
||||
+ ", location=" + location + "]");
|
||||
}
|
||||
|
||||
public abstract ModuleReader open() throws IOException;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleReferenceImpl;
|
||||
|
||||
/**
|
||||
* The resolver used by {@link Configuration#resolveRequires} and
|
||||
@ -438,24 +439,32 @@ final class Resolver {
|
||||
*/
|
||||
private void checkHashes() {
|
||||
for (ModuleReference mref : nameToReference.values()) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
|
||||
// get map of module hashes
|
||||
Optional<ModuleHashes> ohashes = descriptor.hashes();
|
||||
if (!ohashes.isPresent())
|
||||
// get the recorded hashes, if any
|
||||
if (!(mref instanceof ModuleReferenceImpl))
|
||||
continue;
|
||||
ModuleHashes hashes = ((ModuleReferenceImpl)mref).recordedHashes();
|
||||
if (hashes == null)
|
||||
continue;
|
||||
ModuleHashes hashes = ohashes.get();
|
||||
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
String algorithm = hashes.algorithm();
|
||||
for (String dn : hashes.names()) {
|
||||
ModuleReference other = nameToReference.get(dn);
|
||||
if (other == null) {
|
||||
ModuleReference mref2 = nameToReference.get(dn);
|
||||
if (mref2 == null) {
|
||||
ResolvedModule resolvedModule = findInParent(dn);
|
||||
if (resolvedModule != null)
|
||||
other = resolvedModule.reference();
|
||||
mref2 = resolvedModule.reference();
|
||||
}
|
||||
if (mref2 == null)
|
||||
continue;
|
||||
|
||||
if (!(mref2 instanceof ModuleReferenceImpl)) {
|
||||
fail("Unable to compute the hash of module %s", dn);
|
||||
}
|
||||
|
||||
// skip checking the hash if the module has been patched
|
||||
ModuleReferenceImpl other = (ModuleReferenceImpl)mref2;
|
||||
if (other != null && !other.isPatched()) {
|
||||
byte[] recordedHash = hashes.hashFor(dn);
|
||||
byte[] actualHash = other.computeHash(algorithm);
|
||||
|
@ -28,9 +28,11 @@ package java.lang.reflect;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.security.AccessController;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
import jdk.internal.reflect.ReflectionFactory;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* The AccessibleObject class is the base class for Field, Method and
|
||||
@ -172,8 +174,10 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
|
||||
// package is open to caller
|
||||
String pn = packageName(declaringClass);
|
||||
if (declaringModule.isOpen(pn, callerModule))
|
||||
if (declaringModule.isOpen(pn, callerModule)) {
|
||||
printStackTraceIfOpenedReflectively(declaringModule, pn, callerModule);
|
||||
return;
|
||||
}
|
||||
|
||||
// package is exported to caller and class/member is public
|
||||
boolean isExported = declaringModule.isExported(pn, callerModule);
|
||||
@ -185,8 +189,10 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
modifiers = ((Field) this).getModifiers();
|
||||
}
|
||||
boolean isMemberPublic = Modifier.isPublic(modifiers);
|
||||
if (isExported && isClassPublic && isMemberPublic)
|
||||
if (isExported && isClassPublic && isMemberPublic) {
|
||||
printStackTraceIfExportedReflectively(declaringModule, pn, callerModule);
|
||||
return;
|
||||
}
|
||||
|
||||
// not accessible
|
||||
String msg = "Unable to make ";
|
||||
@ -198,7 +204,44 @@ public class AccessibleObject implements AnnotatedElement {
|
||||
else
|
||||
msg += "opens";
|
||||
msg += " " + pn + "\" to " + callerModule;
|
||||
Reflection.throwInaccessibleObjectException(msg);
|
||||
InaccessibleObjectException e = new InaccessibleObjectException(msg);
|
||||
if (Reflection.printStackTraceWhenAccessFails()) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
private void printStackTraceIfOpenedReflectively(Module module,
|
||||
String pn,
|
||||
Module other) {
|
||||
printStackTraceIfExposedReflectively(module, pn, other, true);
|
||||
}
|
||||
|
||||
private void printStackTraceIfExportedReflectively(Module module,
|
||||
String pn,
|
||||
Module other) {
|
||||
printStackTraceIfExposedReflectively(module, pn, other, false);
|
||||
}
|
||||
|
||||
private void printStackTraceIfExposedReflectively(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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,7 +245,6 @@ public final class Layer {
|
||||
* @see Module#addOpens
|
||||
*/
|
||||
public Controller addOpens(Module source, String pn, Module target) {
|
||||
Objects.requireNonNull(source);
|
||||
Objects.requireNonNull(source);
|
||||
Objects.requireNonNull(target);
|
||||
ensureInLayer(source);
|
||||
@ -541,7 +540,7 @@ public final class Layer {
|
||||
* {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to
|
||||
* avoid deadlocks during class loading. In addition, the entity creating
|
||||
* a new layer with this method should arrange that the class loaders are
|
||||
* ready to load from these module before there are any attempts to load
|
||||
* ready to load from these modules before there are any attempts to load
|
||||
* classes or resources.
|
||||
*
|
||||
* <p> Creating a {@code Layer} can fail for the following reasons: </p>
|
||||
|
@ -559,7 +559,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.
|
||||
*/
|
||||
private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) {
|
||||
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) {
|
||||
@ -643,6 +643,12 @@ public final class Module implements AnnotatedElement {
|
||||
* <em>open</em>) to the given module. It also has no effect if
|
||||
* invoked on an {@link ModuleDescriptor#isOpen open} module. </p>
|
||||
*
|
||||
* @apiNote As specified in section 5.4.3 of the <cite>The Java™
|
||||
* Virtual Machine Specification </cite>, if an attempt to resolve a
|
||||
* symbolic reference fails because of a linkage error, then subsequent
|
||||
* attempts to resolve the reference always fail with the same error that
|
||||
* was thrown as a result of the initial resolution attempt.
|
||||
*
|
||||
* @param pn
|
||||
* The package name
|
||||
* @param other
|
||||
@ -656,6 +662,7 @@ public final class Module implements AnnotatedElement {
|
||||
* @throws IllegalStateException
|
||||
* If this is a named module and the caller is not this module
|
||||
*
|
||||
* @jvms 5.4.3 Resolution
|
||||
* @see #isExported(String,Module)
|
||||
*/
|
||||
@CallerSensitive
|
||||
@ -676,8 +683,8 @@ public final class Module implements AnnotatedElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* If the caller's module is this module then update this module to
|
||||
* <em>open</em> the given package to the given module.
|
||||
* If this module has <em>opened</em> a package to at least the caller
|
||||
* module then update this module to open the package to the given module.
|
||||
* Opening a package with this method allows all types in the package,
|
||||
* and all their members, not just public types and their public members,
|
||||
* to be reflected on by the given module when using APIs that support
|
||||
@ -699,7 +706,8 @@ public final class Module implements AnnotatedElement {
|
||||
* If {@code pn} is {@code null}, or this is a named module and the
|
||||
* package {@code pn} is not a package in this module
|
||||
* @throws IllegalStateException
|
||||
* If this is a named module and the caller is not this module
|
||||
* If this is a named module and this module has not opened the
|
||||
* package to at least the caller
|
||||
*
|
||||
* @see #isOpen(String,Module)
|
||||
* @see AccessibleObject#setAccessible(boolean)
|
||||
@ -713,9 +721,8 @@ public final class Module implements AnnotatedElement {
|
||||
|
||||
if (isNamed() && !descriptor.isOpen()) {
|
||||
Module caller = Reflection.getCallerClass().getModule();
|
||||
if (caller != this) {
|
||||
throw new IllegalStateException(caller + " != " + this);
|
||||
}
|
||||
if (caller != this && !isOpen(pn, caller))
|
||||
throw new IllegalStateException(pn + " is not open to " + caller);
|
||||
implAddExportsOrOpens(pn, other, /*open*/true, /*syncVM*/true);
|
||||
}
|
||||
|
||||
@ -1568,6 +1575,10 @@ 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,8 @@ package javax.net.ssl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
|
||||
/**
|
||||
@ -1332,4 +1334,89 @@ public abstract class SSLEngine {
|
||||
public String getHandshakeApplicationProtocol() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback function that selects an application protocol
|
||||
* value for a SSL/TLS/DTLS handshake.
|
||||
* The function overrides any values set using
|
||||
* {@link SSLParameters#setApplicationProtocols
|
||||
* SSLParameters.setApplicationProtocols} and it supports the following
|
||||
* type parameters:
|
||||
* <blockquote>
|
||||
* <dl>
|
||||
* <dt> {@code SSLEngine}
|
||||
* <dd> The function's first argument allows the current {@code SSLEngine}
|
||||
* to be inspected, including the handshake session and configuration
|
||||
* settings.
|
||||
* <dt> {@code List<String>}
|
||||
* <dd> The function's second argument lists the application protocol names
|
||||
* advertised by the TLS peer.
|
||||
* <dt> {@code String}
|
||||
* <dd> The function's result is an application protocol name, or null to
|
||||
* indicate that none of the advertised names are acceptable.
|
||||
* If the return value is null (no value chosen) or is a value that
|
||||
* was not advertised by the peer, the underlying protocol will
|
||||
* determine what action to take. (For example, ALPN will send a
|
||||
* "no_application_protocol" alert and terminate the connection.)
|
||||
* </dl>
|
||||
* </blockquote>
|
||||
*
|
||||
* For example, the following call registers a callback function that
|
||||
* examines the TLS handshake parameters and selects an application protocol
|
||||
* name:
|
||||
* <pre>{@code
|
||||
* serverEngine.setHandshakeApplicationProtocolSelector(
|
||||
* (serverEngine, clientProtocols) -> {
|
||||
* SSLSession session = serverEngine.getHandshakeSession();
|
||||
* return chooseApplicationProtocol(
|
||||
* serverEngine,
|
||||
* clientProtocols,
|
||||
* session.getProtocol(),
|
||||
* session.getCipherSuite());
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* @apiNote
|
||||
* This method should be called by TLS server applications before the TLS
|
||||
* handshake begins. Also, this {@code SSLEngine} should be configured with
|
||||
* parameters that are compatible with the application protocol selected by
|
||||
* the callback function. For example, enabling a poor choice of cipher
|
||||
* suites could result in no suitable application protocol.
|
||||
* See {@link SSLParameters}.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @param selector the callback function, or null to disable the callback
|
||||
* functionality.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the callback function that selects an application protocol
|
||||
* value during a SSL/TLS/DTLS handshake.
|
||||
* See {@link #setHandshakeApplicationProtocolSelector
|
||||
* setHandshakeApplicationProtocolSelector}
|
||||
* for the function's type parameters.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @return the callback function, or null if none has been set.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public BiFunction<SSLEngine, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,8 @@ package javax.net.ssl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* This class extends <code>Socket</code>s and provides secure
|
||||
@ -742,4 +744,89 @@ public abstract class SSLSocket extends Socket
|
||||
public String getHandshakeApplicationProtocol() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers a callback function that selects an application protocol
|
||||
* value for a SSL/TLS/DTLS handshake.
|
||||
* The function overrides any values set using
|
||||
* {@link SSLParameters#setApplicationProtocols
|
||||
* SSLParameters.setApplicationProtocols} and it supports the following
|
||||
* type parameters:
|
||||
* <blockquote>
|
||||
* <dl>
|
||||
* <dt> {@code SSLSocket}
|
||||
* <dd> The function's first argument allows the current {@code SSLSocket}
|
||||
* to be inspected, including the handshake session and configuration
|
||||
* settings.
|
||||
* <dt> {@code List<String>}
|
||||
* <dd> The function's second argument lists the application protocol names
|
||||
* advertised by the TLS peer.
|
||||
* <dt> {@code String}
|
||||
* <dd> The function's result is an application protocol name, or null to
|
||||
* indicate that none of the advertised names are acceptable.
|
||||
* If the return value is null (no value chosen) or is a value that
|
||||
* was not advertised by the peer, the underlying protocol will
|
||||
* determine what action to take. (For example, ALPN will send a
|
||||
* "no_application_protocol" alert and terminate the connection.)
|
||||
* </dl>
|
||||
* </blockquote>
|
||||
*
|
||||
* For example, the following call registers a callback function that
|
||||
* examines the TLS handshake parameters and selects an application protocol
|
||||
* name:
|
||||
* <pre>{@code
|
||||
* serverSocket.setHandshakeApplicationProtocolSelector(
|
||||
* (serverSocket, clientProtocols) -> {
|
||||
* SSLSession session = serverSocket.getHandshakeSession();
|
||||
* return chooseApplicationProtocol(
|
||||
* serverSocket,
|
||||
* clientProtocols,
|
||||
* session.getProtocol(),
|
||||
* session.getCipherSuite());
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* @apiNote
|
||||
* This method should be called by TLS server applications before the TLS
|
||||
* handshake begins. Also, this {@code SSLSocket} should be configured with
|
||||
* parameters that are compatible with the application protocol selected by
|
||||
* the callback function. For example, enabling a poor choice of cipher
|
||||
* suites could result in no suitable application protocol.
|
||||
* See {@link SSLParameters}.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @param selector the callback function, or null to de-register.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLSocket, List<String>, String> selector) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the callback function that selects an application protocol
|
||||
* value during a SSL/TLS/DTLS handshake.
|
||||
* See {@link #setHandshakeApplicationProtocolSelector
|
||||
* setHandshakeApplicationProtocolSelector}
|
||||
* for the function's type parameters.
|
||||
*
|
||||
* @implSpec
|
||||
* The implementation in this class throws
|
||||
* {@code UnsupportedOperationException} and performs no other action.
|
||||
*
|
||||
* @return the callback function, or null if none has been set.
|
||||
* @throws UnsupportedOperationException if the underlying provider
|
||||
* does not implement the operation.
|
||||
* @since 9
|
||||
*/
|
||||
public BiFunction<SSLSocket, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
@ -64,8 +64,10 @@ public class StringSharingDecompressor implements ResourceDecompressor {
|
||||
private static final int CONSTANT_MethodHandle = 15;
|
||||
private static final int CONSTANT_MethodType = 16;
|
||||
private static final int CONSTANT_InvokeDynamic = 18;
|
||||
private static final int CONSTANT_Module = 19;
|
||||
private static final int CONSTANT_Package = 20;
|
||||
|
||||
private static final int[] SIZES = new int[20];
|
||||
private static final int[] SIZES = new int[21];
|
||||
|
||||
static {
|
||||
|
||||
@ -83,6 +85,8 @@ public class StringSharingDecompressor implements ResourceDecompressor {
|
||||
SIZES[CONSTANT_MethodHandle] = 3;
|
||||
SIZES[CONSTANT_MethodType] = 2;
|
||||
SIZES[CONSTANT_InvokeDynamic] = 4;
|
||||
SIZES[CONSTANT_Module] = 2;
|
||||
SIZES[CONSTANT_Package] = 2;
|
||||
}
|
||||
|
||||
public static int[] getSizes() {
|
||||
|
@ -38,10 +38,8 @@ import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@ -59,21 +57,28 @@ public interface JavaLangModuleAccess {
|
||||
* @param strict
|
||||
* Indicates whether module names are checked or not
|
||||
*/
|
||||
ModuleDescriptor.Builder newModuleBuilder(String mn, boolean strict);
|
||||
ModuleDescriptor.Builder newModuleBuilder(String mn,
|
||||
boolean strict,
|
||||
boolean open,
|
||||
boolean synthetic);
|
||||
|
||||
/**
|
||||
* Creates a builder for building an open module with the given module name.
|
||||
*
|
||||
* @param strict
|
||||
* Indicates whether module names are checked or not
|
||||
* Returns the set of packages that are exported (unconditionally or
|
||||
* unconditionally).
|
||||
*/
|
||||
ModuleDescriptor.Builder newOpenModuleBuilder(String mn, boolean strict);
|
||||
Set<String> exportedPackages(ModuleDescriptor.Builder builder);
|
||||
|
||||
/**
|
||||
* Returns the set of packages that are opened (unconditionally or
|
||||
* unconditionally).
|
||||
*/
|
||||
Set<String> openPackages(ModuleDescriptor.Builder builder);
|
||||
|
||||
/**
|
||||
* Returns a {@code ModuleDescriptor.Requires} of the given modifiers
|
||||
* and module name.
|
||||
*/
|
||||
Requires newRequires(Set<Requires.Modifier> ms, String mn);
|
||||
Requires newRequires(Set<Requires.Modifier> ms, String mn, Version v);
|
||||
|
||||
/**
|
||||
* Returns an unqualified {@code ModuleDescriptor.Exports}
|
||||
@ -122,6 +127,7 @@ public interface JavaLangModuleAccess {
|
||||
* Returns a new {@code ModuleDescriptor} instance.
|
||||
*/
|
||||
ModuleDescriptor newModuleDescriptor(String name,
|
||||
Version version,
|
||||
boolean open,
|
||||
boolean automatic,
|
||||
boolean synthetic,
|
||||
@ -130,20 +136,13 @@ public interface JavaLangModuleAccess {
|
||||
Set<Opens> opens,
|
||||
Set<String> uses,
|
||||
Set<Provides> provides,
|
||||
Version version,
|
||||
Set<String> packages,
|
||||
String mainClass,
|
||||
String osName,
|
||||
String osArch,
|
||||
String osVersion,
|
||||
Set<String> packages,
|
||||
ModuleHashes hashes,
|
||||
int hashCode);
|
||||
|
||||
/**
|
||||
* Returns the object with the hashes of other modules
|
||||
*/
|
||||
Optional<ModuleHashes> hashes(ModuleDescriptor descriptor);
|
||||
|
||||
/**
|
||||
* Resolves a collection of root modules, with service binding
|
||||
* and the empty configuration as the parent. The post resolution
|
||||
@ -154,18 +153,4 @@ public interface JavaLangModuleAccess {
|
||||
boolean check,
|
||||
PrintStream traceOutput);
|
||||
|
||||
/**
|
||||
* Creates a ModuleReference to a "patched" module.
|
||||
*/
|
||||
ModuleReference newPatchedModule(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier);
|
||||
|
||||
/**
|
||||
* Creates a ModuleFinder for a module path.
|
||||
*/
|
||||
ModuleFinder newModulePath(Runtime.Version version,
|
||||
boolean isLinkPhase,
|
||||
Path... entries);
|
||||
|
||||
}
|
||||
|
@ -123,4 +123,12 @@ 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);
|
||||
}
|
@ -30,11 +30,8 @@ import java.lang.module.ModuleDescriptor.Opens;
|
||||
import java.lang.module.ModuleDescriptor.Provides;
|
||||
import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jdk.internal.misc.JavaLangModuleAccess;
|
||||
@ -52,7 +49,7 @@ import jdk.internal.misc.SharedSecrets;
|
||||
* SystemModules should contain modules for the boot layer.
|
||||
*/
|
||||
final class Builder {
|
||||
private static final JavaLangModuleAccess jlma =
|
||||
private static final JavaLangModuleAccess JLMA =
|
||||
SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
// Static cache of the most recently seen Version to cheaply deduplicate
|
||||
@ -60,13 +57,36 @@ final class Builder {
|
||||
static Version cachedVersion;
|
||||
|
||||
/**
|
||||
* Returns a {@link Requires} for a dependence on a module
|
||||
* with the given (and possibly empty) set of modifiers.
|
||||
* Returns a {@link Requires} for a dependence on a module with the given
|
||||
* (and possibly empty) set of modifiers, and optionally the version
|
||||
* recorded at compile time.
|
||||
*/
|
||||
public static Requires newRequires(Set<Requires.Modifier> mods,
|
||||
String mn,
|
||||
String compiledVersion)
|
||||
{
|
||||
Version version = null;
|
||||
if (compiledVersion != null) {
|
||||
// use the cached version if the same version string
|
||||
Version ver = cachedVersion;
|
||||
if (ver != null && compiledVersion.equals(ver.toString())) {
|
||||
version = ver;
|
||||
} else {
|
||||
version = Version.parse(compiledVersion);
|
||||
}
|
||||
}
|
||||
return JLMA.newRequires(mods, mn, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Requires} for a dependence on a module with the given
|
||||
* (and possibly empty) set of modifiers, and optionally the version
|
||||
* recorded at compile time.
|
||||
*/
|
||||
public static Requires newRequires(Set<Requires.Modifier> mods,
|
||||
String mn)
|
||||
{
|
||||
return jlma.newRequires(mods, mn);
|
||||
return newRequires(mods, mn, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -77,7 +97,7 @@ final class Builder {
|
||||
public static Exports newExports(Set<Exports.Modifier> ms,
|
||||
String pn,
|
||||
Set<String> targets) {
|
||||
return jlma.newExports(ms, pn, targets);
|
||||
return JLMA.newExports(ms, pn, targets);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -85,7 +105,7 @@ final class Builder {
|
||||
* modifiers.
|
||||
*/
|
||||
public static Opens newOpens(Set<Opens.Modifier> ms, String pn) {
|
||||
return jlma.newOpens(ms, pn);
|
||||
return JLMA.newOpens(ms, pn);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,7 +116,7 @@ final class Builder {
|
||||
public static Opens newOpens(Set<Opens.Modifier> ms,
|
||||
String pn,
|
||||
Set<String> targets) {
|
||||
return jlma.newOpens(ms, pn, targets);
|
||||
return JLMA.newOpens(ms, pn, targets);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,7 +124,7 @@ final class Builder {
|
||||
* of modifiers.
|
||||
*/
|
||||
public static Exports newExports(Set<Exports.Modifier> ms, String pn) {
|
||||
return jlma.newExports(ms, pn);
|
||||
return JLMA.newExports(ms, pn);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,7 +132,7 @@ final class Builder {
|
||||
* implementation classes.
|
||||
*/
|
||||
public static Provides newProvides(String st, List<String> pcs) {
|
||||
return jlma.newProvides(st, pcs);
|
||||
return JLMA.newProvides(st, pcs);
|
||||
}
|
||||
|
||||
final String name;
|
||||
@ -130,8 +150,6 @@ final class Builder {
|
||||
String osName;
|
||||
String osArch;
|
||||
String osVersion;
|
||||
String algorithm;
|
||||
Map<String, byte[]> hashes;
|
||||
|
||||
Builder(String name) {
|
||||
this.name = name;
|
||||
@ -274,35 +292,14 @@ final class Builder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the algorithm of the module hashes
|
||||
*/
|
||||
public Builder algorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the module hash for the given module name
|
||||
*/
|
||||
public Builder moduleHash(String mn, byte[] hash) {
|
||||
if (hashes == null)
|
||||
hashes = new HashMap<>();
|
||||
|
||||
hashes.put(mn, hash);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@code ModuleDescriptor} from the components.
|
||||
*/
|
||||
public ModuleDescriptor build(int hashCode) {
|
||||
assert name != null;
|
||||
|
||||
ModuleHashes moduleHashes =
|
||||
hashes != null ? new ModuleHashes(algorithm, hashes) : null;
|
||||
|
||||
return jlma.newModuleDescriptor(name,
|
||||
return JLMA.newModuleDescriptor(name,
|
||||
version,
|
||||
open,
|
||||
automatic,
|
||||
synthetic,
|
||||
@ -311,13 +308,11 @@ final class Builder {
|
||||
opens,
|
||||
uses,
|
||||
provides,
|
||||
version,
|
||||
packages,
|
||||
mainClass,
|
||||
osName,
|
||||
osArch,
|
||||
osVersion,
|
||||
packages,
|
||||
moduleHashes,
|
||||
hashCode);
|
||||
}
|
||||
}
|
||||
|
@ -25,79 +25,200 @@
|
||||
|
||||
package jdk.internal.module;
|
||||
|
||||
/**
|
||||
* Utility class for checking module name and binary names.
|
||||
*/
|
||||
|
||||
public final class Checks {
|
||||
|
||||
private Checks() { }
|
||||
|
||||
private static void fail(String what, String id, int i) {
|
||||
throw new IllegalArgumentException(id
|
||||
+ ": Invalid " + what + ": "
|
||||
+ " Illegal character"
|
||||
+ " at index " + i);
|
||||
/**
|
||||
* Checks a name to ensure that it's a legal module name.
|
||||
*
|
||||
* @throws IllegalArgumentException if name is null or not a legal
|
||||
* module name
|
||||
*/
|
||||
public static String requireModuleName(String name) {
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException("Null module name");
|
||||
int next;
|
||||
int off = 0;
|
||||
while ((next = name.indexOf('.', off)) != -1) {
|
||||
if (isJavaIdentifier(name, off, (next - off)) == -1) {
|
||||
String id = name.substring(off, next);
|
||||
throw new IllegalArgumentException(name + ": Invalid module name"
|
||||
+ ": '" + id + "' is not a Java identifier");
|
||||
}
|
||||
off = next+1;
|
||||
}
|
||||
int last = isJavaIdentifier(name, off, name.length() - off);
|
||||
if (last == -1) {
|
||||
String id = name.substring(off);
|
||||
throw new IllegalArgumentException(name + ": Invalid module name"
|
||||
+ ": '" + id + "' is not a Java identifier");
|
||||
}
|
||||
//if (!Character.isJavaIdentifierStart(last))
|
||||
// throw new IllegalArgumentException(name + ": Module name ends in digit");
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given identifier is a legal Java identifier.
|
||||
* Returns {@code true} if the given name is a legal module name.
|
||||
*/
|
||||
public static boolean isJavaIdentifier(String id) {
|
||||
int n = id.length();
|
||||
if (n == 0)
|
||||
return false;
|
||||
if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
|
||||
return false;
|
||||
int cp = id.codePointAt(0);
|
||||
int i = Character.charCount(cp);
|
||||
for (; i < n; i += Character.charCount(cp)) {
|
||||
cp = id.codePointAt(i);
|
||||
if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
|
||||
public static boolean isModuleName(String name) {
|
||||
int next;
|
||||
int off = 0;
|
||||
while ((next = name.indexOf('.', off)) != -1) {
|
||||
if (isJavaIdentifier(name, off, (next - off)) == -1)
|
||||
return false;
|
||||
off = next+1;
|
||||
}
|
||||
if (cp == '.')
|
||||
int last = isJavaIdentifier(name, off, name.length() - off);
|
||||
if (last == -1)
|
||||
return false;
|
||||
|
||||
//if (!Character.isJavaIdentifierStart(last))
|
||||
// return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given identifier is a legal Java identifier.
|
||||
* Checks a name to ensure that it's a legal package name.
|
||||
*
|
||||
* @throws IllegalArgumentException if name is null or not a legal
|
||||
* package name
|
||||
*/
|
||||
public static String requireJavaIdentifier(String what, String id) {
|
||||
if (id == null)
|
||||
throw new IllegalArgumentException("Null " + what);
|
||||
int n = id.length();
|
||||
if (n == 0)
|
||||
throw new IllegalArgumentException("Empty " + what);
|
||||
if (!Character.isJavaIdentifierStart(id.codePointAt(0)))
|
||||
fail(what, id, 0);
|
||||
int cp = id.codePointAt(0);
|
||||
int i = Character.charCount(cp);
|
||||
int last = 0;
|
||||
for (; i < n; i += Character.charCount(cp)) {
|
||||
cp = id.codePointAt(i);
|
||||
if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.')
|
||||
fail(what, id, i);
|
||||
last = i;
|
||||
public static String requirePackageName(String name) {
|
||||
return requireBinaryName("package name", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a name to ensure that it's a legal type name.
|
||||
*
|
||||
* @throws IllegalArgumentException if name is null or not a legal
|
||||
* type name
|
||||
*/
|
||||
public static String requireServiceTypeName(String name) {
|
||||
return requireBinaryName("service type name", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a name to ensure that it's a legal type name.
|
||||
*
|
||||
* @throws IllegalArgumentException if name is null or not a legal
|
||||
* type name
|
||||
*/
|
||||
public static String requireServiceProviderName(String name) {
|
||||
return requireBinaryName("service provider name", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given name is a legal binary name.
|
||||
*/
|
||||
public static boolean isJavaIdentifier(String name) {
|
||||
return isBinaryName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the given name is a legal binary name.
|
||||
*/
|
||||
public static boolean isBinaryName(String name) {
|
||||
int next;
|
||||
int off = 0;
|
||||
while ((next = name.indexOf('.', off)) != -1) {
|
||||
if (isJavaIdentifier(name, off, (next - off)) == -1)
|
||||
return false;
|
||||
off = next+1;
|
||||
}
|
||||
if (cp == '.')
|
||||
fail(what, id, last);
|
||||
|
||||
return id;
|
||||
int count = name.length() - off;
|
||||
return (isJavaIdentifier(name, off, count) != -1);
|
||||
}
|
||||
|
||||
public static String requireModuleName(String id) {
|
||||
return requireJavaIdentifier("module name", id);
|
||||
/**
|
||||
* Checks if the given name is a legal binary name.
|
||||
*
|
||||
* @throws IllegalArgumentException if name is null or not a legal
|
||||
* binary name
|
||||
*/
|
||||
public static String requireBinaryName(String what, String name) {
|
||||
if (name == null)
|
||||
throw new IllegalArgumentException("Null " + what);
|
||||
int next;
|
||||
int off = 0;
|
||||
while ((next = name.indexOf('.', off)) != -1) {
|
||||
if (isJavaIdentifier(name, off, (next - off)) == -1) {
|
||||
String id = name.substring(off, next);
|
||||
throw new IllegalArgumentException(name + ": Invalid " + what
|
||||
+ ": '" + id + "' is not a Java identifier");
|
||||
}
|
||||
off = next + 1;
|
||||
}
|
||||
if (isJavaIdentifier(name, off, name.length() - off) == -1) {
|
||||
String id = name.substring(off, name.length());
|
||||
throw new IllegalArgumentException(name + ": Invalid " + what
|
||||
+ ": '" + id + "' is not a Java identifier");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static String requirePackageName(String id) {
|
||||
return requireJavaIdentifier("package name", id);
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public static String requireServiceTypeName(String id) {
|
||||
return requireJavaIdentifier("service type name", id);
|
||||
/**
|
||||
* Returns true if the given string only contains ASCII characters.
|
||||
*/
|
||||
private static boolean isASCIIString(String s) {
|
||||
int i = 0;
|
||||
while (i < s.length()) {
|
||||
int c = s.charAt(i);
|
||||
if (c > 0x7F)
|
||||
return false;
|
||||
i++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String requireServiceProviderName(String id) {
|
||||
return requireJavaIdentifier("service provider name", id);
|
||||
}
|
||||
/**
|
||||
* Checks if a char sequence is a legal Java identifier, returning the code
|
||||
* point of the last character if legal or {@code -1} if not legal.
|
||||
*/
|
||||
private static int isJavaIdentifier(CharSequence cs, int offset, int count) {
|
||||
if (count == 0)
|
||||
return -1;
|
||||
int first = Character.codePointAt(cs, offset);
|
||||
if (!Character.isJavaIdentifierStart(first))
|
||||
return -1;
|
||||
|
||||
int cp = first;
|
||||
int i = Character.charCount(first);
|
||||
while (i < count) {
|
||||
cp = Character.codePointAt(cs, offset+i);
|
||||
if (!Character.isJavaIdentifierPart(cp))
|
||||
return -1;
|
||||
i += Character.charCount(cp);
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
@ -68,12 +68,18 @@ public final class ClassFileAttributes {
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
private ModuleDescriptor descriptor;
|
||||
private Version replacementVersion;
|
||||
|
||||
public ModuleAttribute(ModuleDescriptor descriptor) {
|
||||
super(MODULE);
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
public ModuleAttribute(Version v) {
|
||||
super(MODULE);
|
||||
this.replacementVersion = v;
|
||||
}
|
||||
|
||||
public ModuleAttribute() {
|
||||
super(MODULE);
|
||||
}
|
||||
@ -86,46 +92,70 @@ public final class ClassFileAttributes {
|
||||
int codeOff,
|
||||
Label[] labels)
|
||||
{
|
||||
ModuleAttribute attr = new ModuleAttribute();
|
||||
|
||||
// module_name
|
||||
String mn = cr.readUTF8(off, buf).replace('/', '.');
|
||||
// module_name (CONSTANT_Module_info)
|
||||
String mn = cr.readModule(off, buf);
|
||||
off += 2;
|
||||
|
||||
// module_flags
|
||||
int module_flags = cr.readUnsignedShort(off);
|
||||
boolean open = ((module_flags & ACC_OPEN) != 0);
|
||||
boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
|
||||
off += 2;
|
||||
|
||||
ModuleDescriptor.Builder builder;
|
||||
if (open) {
|
||||
builder = JLMA.newOpenModuleBuilder(mn, false);
|
||||
} else {
|
||||
builder = JLMA.newModuleBuilder(mn, false);
|
||||
ModuleDescriptor.Builder builder = JLMA.newModuleBuilder(mn,
|
||||
false,
|
||||
open,
|
||||
synthetic);
|
||||
|
||||
// module_version
|
||||
String module_version = cr.readUTF8(off, buf);
|
||||
off += 2;
|
||||
if (replacementVersion != null) {
|
||||
builder.version(replacementVersion);
|
||||
} else if (module_version != null) {
|
||||
builder.version(module_version);
|
||||
}
|
||||
|
||||
// requires_count and requires[requires_count]
|
||||
int requires_count = cr.readUnsignedShort(off);
|
||||
off += 2;
|
||||
for (int i=0; i<requires_count; i++) {
|
||||
String dn = cr.readUTF8(off, buf).replace('/', '.');
|
||||
int flags = cr.readUnsignedShort(off + 2);
|
||||
// CONSTANT_Module_info
|
||||
String dn = cr.readModule(off, buf);
|
||||
off += 2;
|
||||
|
||||
// requires_flags
|
||||
int requires_flags = cr.readUnsignedShort(off);
|
||||
off += 2;
|
||||
Set<Requires.Modifier> mods;
|
||||
if (flags == 0) {
|
||||
if (requires_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_TRANSITIVE) != 0)
|
||||
if ((requires_flags & ACC_TRANSITIVE) != 0)
|
||||
mods.add(Requires.Modifier.TRANSITIVE);
|
||||
if ((flags & ACC_STATIC_PHASE) != 0)
|
||||
if ((requires_flags & ACC_STATIC_PHASE) != 0)
|
||||
mods.add(Requires.Modifier.STATIC);
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((requires_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Requires.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((requires_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Requires.Modifier.MANDATED);
|
||||
}
|
||||
builder.requires(mods, dn);
|
||||
off += 4;
|
||||
|
||||
|
||||
// requires_version
|
||||
Version compiledVersion = null;
|
||||
String requires_version = cr.readUTF8(off, buf);
|
||||
off += 2;
|
||||
if (requires_version != null) {
|
||||
compiledVersion = Version.parse(requires_version);
|
||||
}
|
||||
|
||||
if (compiledVersion == null) {
|
||||
builder.requires(mods, dn);
|
||||
} else {
|
||||
builder.requires(mods, dn, compiledVersion);
|
||||
}
|
||||
}
|
||||
|
||||
// exports_count and exports[exports_count]
|
||||
@ -133,19 +163,20 @@ public final class ClassFileAttributes {
|
||||
off += 2;
|
||||
if (exports_count > 0) {
|
||||
for (int i=0; i<exports_count; i++) {
|
||||
String pkg = cr.readUTF8(off, buf).replace('/', '.');
|
||||
// CONSTANT_Package_info
|
||||
String pkg = cr.readPackage(off, buf).replace('/', '.');
|
||||
off += 2;
|
||||
|
||||
int flags = cr.readUnsignedShort(off);
|
||||
int exports_flags = cr.readUnsignedShort(off);
|
||||
off += 2;
|
||||
Set<Exports.Modifier> mods;
|
||||
if (flags == 0) {
|
||||
if (exports_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((exports_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Exports.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((exports_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Exports.Modifier.MANDATED);
|
||||
}
|
||||
|
||||
@ -154,7 +185,7 @@ public final class ClassFileAttributes {
|
||||
if (exports_to_count > 0) {
|
||||
Set<String> targets = new HashSet<>();
|
||||
for (int j=0; j<exports_to_count; j++) {
|
||||
String t = cr.readUTF8(off, buf).replace('/', '.');
|
||||
String t = cr.readModule(off, buf);
|
||||
off += 2;
|
||||
targets.add(t);
|
||||
}
|
||||
@ -170,19 +201,20 @@ public final class ClassFileAttributes {
|
||||
off += 2;
|
||||
if (open_count > 0) {
|
||||
for (int i=0; i<open_count; i++) {
|
||||
String pkg = cr.readUTF8(off, buf).replace('/', '.');
|
||||
// CONSTANT_Package_info
|
||||
String pkg = cr.readPackage(off, buf).replace('/', '.');
|
||||
off += 2;
|
||||
|
||||
int flags = cr.readUnsignedShort(off);
|
||||
int opens_flags = cr.readUnsignedShort(off);
|
||||
off += 2;
|
||||
Set<Opens.Modifier> mods;
|
||||
if (flags == 0) {
|
||||
if (opens_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((opens_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Opens.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((opens_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Opens.Modifier.MANDATED);
|
||||
}
|
||||
|
||||
@ -191,7 +223,7 @@ public final class ClassFileAttributes {
|
||||
if (opens_to_count > 0) {
|
||||
Set<String> targets = new HashSet<>();
|
||||
for (int j=0; j<opens_to_count; j++) {
|
||||
String t = cr.readUTF8(off, buf).replace('/', '.');
|
||||
String t = cr.readModule(off, buf);
|
||||
off += 2;
|
||||
targets.add(t);
|
||||
}
|
||||
@ -232,8 +264,7 @@ public final class ClassFileAttributes {
|
||||
}
|
||||
}
|
||||
|
||||
attr.descriptor = builder.build();
|
||||
return attr;
|
||||
return new ModuleAttribute(builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -248,7 +279,7 @@ public final class ClassFileAttributes {
|
||||
|
||||
// module_name
|
||||
String mn = descriptor.name();
|
||||
int module_name_index = cw.newUTF8(mn.replace('.', '/'));
|
||||
int module_name_index = cw.newModule(mn);
|
||||
attr.putShort(module_name_index);
|
||||
|
||||
// module_flags
|
||||
@ -259,66 +290,83 @@ public final class ClassFileAttributes {
|
||||
module_flags |= ACC_SYNTHETIC;
|
||||
attr.putShort(module_flags);
|
||||
|
||||
// module_version
|
||||
Version v = descriptor.version().orElse(null);
|
||||
if (v == null) {
|
||||
attr.putShort(0);
|
||||
} else {
|
||||
int module_version_index = cw.newUTF8(v.toString());
|
||||
attr.putShort(module_version_index);
|
||||
}
|
||||
|
||||
// requires_count
|
||||
attr.putShort(descriptor.requires().size());
|
||||
|
||||
// requires[requires_count]
|
||||
for (Requires md : descriptor.requires()) {
|
||||
String dn = md.name();
|
||||
int flags = 0;
|
||||
if (md.modifiers().contains(Requires.Modifier.TRANSITIVE))
|
||||
flags |= ACC_TRANSITIVE;
|
||||
if (md.modifiers().contains(Requires.Modifier.STATIC))
|
||||
flags |= ACC_STATIC_PHASE;
|
||||
if (md.modifiers().contains(Requires.Modifier.SYNTHETIC))
|
||||
flags |= ACC_SYNTHETIC;
|
||||
if (md.modifiers().contains(Requires.Modifier.MANDATED))
|
||||
flags |= ACC_MANDATED;
|
||||
int index = cw.newUTF8(dn.replace('.', '/'));
|
||||
attr.putShort(index);
|
||||
attr.putShort(flags);
|
||||
for (Requires r : descriptor.requires()) {
|
||||
int requires_index = cw.newModule(r.name());
|
||||
attr.putShort(requires_index);
|
||||
|
||||
int requires_flags = 0;
|
||||
if (r.modifiers().contains(Requires.Modifier.TRANSITIVE))
|
||||
requires_flags |= ACC_TRANSITIVE;
|
||||
if (r.modifiers().contains(Requires.Modifier.STATIC))
|
||||
requires_flags |= ACC_STATIC_PHASE;
|
||||
if (r.modifiers().contains(Requires.Modifier.SYNTHETIC))
|
||||
requires_flags |= ACC_SYNTHETIC;
|
||||
if (r.modifiers().contains(Requires.Modifier.MANDATED))
|
||||
requires_flags |= ACC_MANDATED;
|
||||
attr.putShort(requires_flags);
|
||||
|
||||
int requires_version_index;
|
||||
v = r.compiledVersion().orElse(null);
|
||||
if (v == null) {
|
||||
requires_version_index = 0;
|
||||
} else {
|
||||
requires_version_index = cw.newUTF8(v.toString());
|
||||
}
|
||||
attr.putShort(requires_version_index);
|
||||
}
|
||||
|
||||
// exports_count and exports[exports_count];
|
||||
attr.putShort(descriptor.exports().size());
|
||||
for (Exports e : descriptor.exports()) {
|
||||
String pkg = e.source().replace('.', '/');
|
||||
attr.putShort(cw.newUTF8(pkg));
|
||||
attr.putShort(cw.newPackage(pkg));
|
||||
|
||||
int flags = 0;
|
||||
int exports_flags = 0;
|
||||
if (e.modifiers().contains(Exports.Modifier.SYNTHETIC))
|
||||
flags |= ACC_SYNTHETIC;
|
||||
exports_flags |= ACC_SYNTHETIC;
|
||||
if (e.modifiers().contains(Exports.Modifier.MANDATED))
|
||||
flags |= ACC_MANDATED;
|
||||
attr.putShort(flags);
|
||||
exports_flags |= ACC_MANDATED;
|
||||
attr.putShort(exports_flags);
|
||||
|
||||
if (e.isQualified()) {
|
||||
Set<String> ts = e.targets();
|
||||
attr.putShort(ts.size());
|
||||
ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
|
||||
ts.forEach(target -> attr.putShort(cw.newModule(target)));
|
||||
} else {
|
||||
attr.putShort(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// opens_counts and opens[opens_counts]
|
||||
attr.putShort(descriptor.opens().size());
|
||||
for (Opens obj : descriptor.opens()) {
|
||||
String pkg = obj.source().replace('.', '/');
|
||||
attr.putShort(cw.newUTF8(pkg));
|
||||
attr.putShort(cw.newPackage(pkg));
|
||||
|
||||
int flags = 0;
|
||||
int opens_flags = 0;
|
||||
if (obj.modifiers().contains(Opens.Modifier.SYNTHETIC))
|
||||
flags |= ACC_SYNTHETIC;
|
||||
opens_flags |= ACC_SYNTHETIC;
|
||||
if (obj.modifiers().contains(Opens.Modifier.MANDATED))
|
||||
flags |= ACC_MANDATED;
|
||||
attr.putShort(flags);
|
||||
opens_flags |= ACC_MANDATED;
|
||||
attr.putShort(opens_flags);
|
||||
|
||||
if (obj.isQualified()) {
|
||||
Set<String> ts = obj.targets();
|
||||
attr.putShort(ts.size());
|
||||
ts.forEach(t -> attr.putShort(cw.newUTF8(t.replace('.', '/'))));
|
||||
ts.forEach(target -> attr.putShort(cw.newModule(target)));
|
||||
} else {
|
||||
attr.putShort(0);
|
||||
}
|
||||
@ -369,7 +417,7 @@ public final class ClassFileAttributes {
|
||||
*
|
||||
* // the number of entries in the packages table
|
||||
* u2 packages_count;
|
||||
* { // index to CONSTANT_CONSTANT_utf8_info structure with the package name
|
||||
* { // index to CONSTANT_Package_info structure with the package name
|
||||
* u2 package_index
|
||||
* } packages[package_count];
|
||||
*
|
||||
@ -402,7 +450,7 @@ public final class ClassFileAttributes {
|
||||
// packages
|
||||
Set<String> packages = new HashSet<>();
|
||||
for (int i=0; i<package_count; i++) {
|
||||
String pkg = cr.readUTF8(off, buf).replace('/', '.');
|
||||
String pkg = cr.readPackage(off, buf).replace('/', '.');
|
||||
packages.add(pkg);
|
||||
off += 2;
|
||||
}
|
||||
@ -427,68 +475,13 @@ public final class ClassFileAttributes {
|
||||
// packages
|
||||
packages.stream()
|
||||
.map(p -> p.replace('.', '/'))
|
||||
.forEach(p -> attr.putShort(cw.newUTF8(p)));
|
||||
.forEach(p -> attr.putShort(cw.newPackage(p)));
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ModuleVersion attribute.
|
||||
*
|
||||
* <pre> {@code
|
||||
*
|
||||
* ModuleVersion_attribute {
|
||||
* // index to CONSTANT_utf8_info structure in constant pool representing
|
||||
* // the string "ModuleVersion"
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
*
|
||||
* // index to CONSTANT_CONSTANT_utf8_info structure with the version
|
||||
* u2 version_index;
|
||||
* }
|
||||
*
|
||||
* } </pre>
|
||||
*/
|
||||
public static class ModuleVersionAttribute extends Attribute {
|
||||
private final Version version;
|
||||
|
||||
public ModuleVersionAttribute(Version version) {
|
||||
super(MODULE_VERSION);
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public ModuleVersionAttribute() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr,
|
||||
int off,
|
||||
int len,
|
||||
char[] buf,
|
||||
int codeOff,
|
||||
Label[] labels)
|
||||
{
|
||||
String value = cr.readUTF8(off, buf);
|
||||
return new ModuleVersionAttribute(Version.parse(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw,
|
||||
byte[] code,
|
||||
int len,
|
||||
int maxStack,
|
||||
int maxLocals)
|
||||
{
|
||||
ByteVector attr = new ByteVector();
|
||||
int index = cw.newUTF8(version.toString());
|
||||
attr.putShort(index);
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ModuleMainClass attribute.
|
||||
*
|
||||
@ -526,7 +519,7 @@ public final class ClassFileAttributes {
|
||||
int codeOff,
|
||||
Label[] labels)
|
||||
{
|
||||
String value = cr.readClass(off, buf);
|
||||
String value = cr.readClass(off, buf).replace('/', '.');
|
||||
return new ModuleMainClassAttribute(value);
|
||||
}
|
||||
|
||||
@ -538,7 +531,7 @@ public final class ClassFileAttributes {
|
||||
int maxLocals)
|
||||
{
|
||||
ByteVector attr = new ByteVector();
|
||||
int index = cw.newClass(mainClass);
|
||||
int index = cw.newClass(mainClass.replace('.', '/'));
|
||||
attr.putShort(index);
|
||||
return attr;
|
||||
}
|
||||
@ -555,11 +548,11 @@ public final class ClassFileAttributes {
|
||||
* u2 attribute_name_index;
|
||||
* u4 attribute_length;
|
||||
*
|
||||
* // index to CONSTANT_CONSTANT_utf8_info structure with the OS name
|
||||
* // index to CONSTANT_utf8_info structure with the OS name
|
||||
* u2 os_name_index;
|
||||
* // index to CONSTANT_CONSTANT_utf8_info structure with the OS arch
|
||||
* // index to CONSTANT_utf8_info structure with the OS arch
|
||||
* u2 os_arch_index
|
||||
* // index to CONSTANT_CONSTANT_utf8_info structure with the OS version
|
||||
* // index to CONSTANT_utf8_info structure with the OS version
|
||||
* u2 os_version_index;
|
||||
* }
|
||||
*
|
||||
@ -656,7 +649,7 @@ public final class ClassFileAttributes {
|
||||
*
|
||||
* // the number of entries in the hashes table
|
||||
* u2 hashes_count;
|
||||
* { u2 module_name_index
|
||||
* { u2 module_name_index (index to CONSTANT_Module_info structure)
|
||||
* u2 hash_length;
|
||||
* u1 hash[hash_length];
|
||||
* } hashes[hashes_count];
|
||||
@ -691,7 +684,7 @@ public final class ClassFileAttributes {
|
||||
|
||||
Map<String, byte[]> map = new HashMap<>();
|
||||
for (int i=0; i<hashes_count; i++) {
|
||||
String mn = cr.readUTF8(off, buf).replace('/', '.');
|
||||
String mn = cr.readModule(off, buf);
|
||||
off += 2;
|
||||
|
||||
int hash_length = cr.readUnsignedShort(off);
|
||||
@ -728,7 +721,7 @@ public final class ClassFileAttributes {
|
||||
for (String mn : names) {
|
||||
byte[] hash = hashes.hashFor(mn);
|
||||
assert hash != null;
|
||||
attr.putShort(cw.newUTF8(mn.replace('.', '/')));
|
||||
attr.putShort(cw.newModule(mn));
|
||||
|
||||
attr.putShort(hash.length);
|
||||
for (byte b: hash) {
|
||||
@ -740,4 +733,58 @@ public final class ClassFileAttributes {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ModuleResolution_attribute {
|
||||
* u2 attribute_name_index; // "ModuleResolution"
|
||||
* u4 attribute_length; // 2
|
||||
* u2 resolution_flags;
|
||||
*
|
||||
* The value of the resolution_flags item is a mask of flags used to denote
|
||||
* properties of module resolution. The flags are as follows:
|
||||
*
|
||||
* // Optional
|
||||
* 0x0001 (DO_NOT_RESOLVE_BY_DEFAULT)
|
||||
*
|
||||
* // At most one of:
|
||||
* 0x0002 (WARN_DEPRECATED)
|
||||
* 0x0004 (WARN_DEPRECATED_FOR_REMOVAL)
|
||||
* 0x0008 (WARN_INCUBATING)
|
||||
*/
|
||||
static class ModuleResolutionAttribute extends Attribute {
|
||||
private final int value;
|
||||
|
||||
ModuleResolutionAttribute() {
|
||||
super(MODULE_RESOLUTION);
|
||||
value = 0;
|
||||
}
|
||||
|
||||
ModuleResolutionAttribute(int value) {
|
||||
super(MODULE_RESOLUTION);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Attribute read(ClassReader cr,
|
||||
int off,
|
||||
int len,
|
||||
char[] buf,
|
||||
int codeOff,
|
||||
Label[] labels)
|
||||
{
|
||||
int flags = cr.readUnsignedShort(off);
|
||||
return new ModuleResolutionAttribute(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteVector write(ClassWriter cw,
|
||||
byte[] code,
|
||||
int len,
|
||||
int maxStack,
|
||||
int maxLocals)
|
||||
{
|
||||
ByteVector attr = new ByteVector();
|
||||
attr.putShort(value);
|
||||
return attr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,10 +38,10 @@ public class ClassFileConstants {
|
||||
public static final String SDE = "SourceDebugExtension";
|
||||
|
||||
public static final String MODULE_PACKAGES = "ModulePackages";
|
||||
public static final String MODULE_VERSION = "ModuleVersion";
|
||||
public static final String MODULE_MAIN_CLASS = "ModuleMainClass";
|
||||
public static final String MODULE_TARGET = "ModuleTarget";
|
||||
public static final String MODULE_HASHES = "ModuleHashes";
|
||||
public static final String MODULE_RESOLUTION = "ModuleResolution";
|
||||
|
||||
// access, requires, exports, and opens flags
|
||||
public static final int ACC_MODULE = 0x8000;
|
||||
@ -51,4 +51,10 @@ public class ClassFileConstants {
|
||||
public static final int ACC_SYNTHETIC = 0x1000;
|
||||
public static final int ACC_MANDATED = 0x8000;
|
||||
|
||||
// ModuleResolution_attribute resolution flags
|
||||
public static final int DO_NOT_RESOLVE_BY_DEFAULT = 0x0001;
|
||||
public static final int WARN_DEPRECATED = 0x0002;
|
||||
public static final int WARN_DEPRECATED_FOR_REMOVAL = 0x0004;
|
||||
public static final int WARN_INCUBATING = 0x0008;
|
||||
|
||||
}
|
||||
|
@ -195,7 +195,9 @@ public final class ModuleBootstrap {
|
||||
// module is the unnamed module of the application class loader. This
|
||||
// is implemented by resolving "java.se" and all (non-java.*) modules
|
||||
// that export an API. If "java.se" is not observable then all java.*
|
||||
// modules are resolved.
|
||||
// modules are resolved. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
|
||||
// bit set in their ModuleResolution attribute flags are excluded from
|
||||
// the default set of roots.
|
||||
if (mainModule == null || addAllDefaultModules) {
|
||||
boolean hasJava = false;
|
||||
if (systemModules.find(JAVA_SE).isPresent()) {
|
||||
@ -212,6 +214,9 @@ public final class ModuleBootstrap {
|
||||
if (hasJava && mn.startsWith("java."))
|
||||
continue;
|
||||
|
||||
if (ModuleResolution.doNotResolveByDefault(mref))
|
||||
continue;
|
||||
|
||||
// add as root if observable and exports at least one package
|
||||
if ((finder == systemModules || finder.find(mn).isPresent())) {
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
@ -231,6 +236,7 @@ public final class ModuleBootstrap {
|
||||
ModuleFinder f = finder; // observable modules
|
||||
systemModules.findAll()
|
||||
.stream()
|
||||
.filter(mref -> !ModuleResolution.doNotResolveByDefault(mref))
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.filter(mn -> f.find(mn).isPresent()) // observable
|
||||
@ -277,6 +283,8 @@ public final class ModuleBootstrap {
|
||||
// time to create configuration
|
||||
PerfCounters.resolveTime.addElapsedTimeFrom(t3);
|
||||
|
||||
// check module names and incubating status
|
||||
checkModuleNamesAndStatus(cf);
|
||||
|
||||
// mapping of modules to class loaders
|
||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
@ -508,12 +516,12 @@ public final class ModuleBootstrap {
|
||||
String key = e.getKey();
|
||||
String[] s = key.split("/");
|
||||
if (s.length != 2)
|
||||
fail("Unable to parse: " + key);
|
||||
fail("Unable to parse as <module>/<package>: " + key);
|
||||
|
||||
String mn = s[0];
|
||||
String pn = s[1];
|
||||
if (mn.isEmpty() || pn.isEmpty())
|
||||
fail("Module and package name must be specified:" + key);
|
||||
fail("Module and package name must be specified: " + key);
|
||||
|
||||
// The exporting module is in the boot layer
|
||||
Module m;
|
||||
@ -585,7 +593,7 @@ public final class ModuleBootstrap {
|
||||
|
||||
int pos = value.indexOf('=');
|
||||
if (pos == -1)
|
||||
fail("Unable to parse: " + value);
|
||||
fail("Unable to parse as <module>=<value>: " + value);
|
||||
if (pos == 0)
|
||||
fail("Missing module name in: " + value);
|
||||
|
||||
@ -594,7 +602,7 @@ public final class ModuleBootstrap {
|
||||
|
||||
String rhs = value.substring(pos+1);
|
||||
if (rhs.isEmpty())
|
||||
fail("Unable to parse: " + value);
|
||||
fail("Unable to parse as <module>=<value>: " + value);
|
||||
|
||||
// value is <module>(,<module>)* or <file>(<pathsep><file>)*
|
||||
if (!allowDuplicates && map.containsKey(key))
|
||||
@ -626,6 +634,33 @@ public final class ModuleBootstrap {
|
||||
return (String)System.getProperties().remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the names and resolution bit of each module in the configuration,
|
||||
* emitting warnings if needed.
|
||||
*/
|
||||
private static void checkModuleNamesAndStatus(Configuration cf) {
|
||||
String incubating = null;
|
||||
for (ResolvedModule rm : cf.modules()) {
|
||||
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) {
|
||||
incubating = mn;
|
||||
} else {
|
||||
incubating += ", " + mn;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (incubating != null)
|
||||
warn("Using incubator modules: " + incubating);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a RuntimeException with the given message
|
||||
*/
|
||||
|
@ -35,6 +35,7 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@ -50,7 +51,6 @@ public final class ModuleHashes {
|
||||
byte[] generate(String algorithm);
|
||||
}
|
||||
|
||||
|
||||
private final String algorithm;
|
||||
private final Map<String, byte[]> nameToHash;
|
||||
|
||||
@ -142,4 +142,37 @@ public final class ModuleHashes {
|
||||
}
|
||||
return new ModuleHashes(algorithm, nameToHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by jdk.internal.module.SystemModules class
|
||||
* generated at link time.
|
||||
*/
|
||||
public static class Builder {
|
||||
final String algorithm;
|
||||
final Map<String, byte[]> nameToHash;
|
||||
|
||||
Builder(String algorithm, int initialCapacity) {
|
||||
this.nameToHash = new HashMap<>(initialCapacity);
|
||||
this.algorithm = Objects.requireNonNull(algorithm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the module hash for the given module name
|
||||
*/
|
||||
public Builder hashForModule(String mn, byte[] hash) {
|
||||
nameToHash.put(mn, hash);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@code ModuleHashes}.
|
||||
*/
|
||||
public ModuleHashes build() {
|
||||
if (!nameToHash.isEmpty()) {
|
||||
return new ModuleHashes(algorithm, nameToHash);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.module;
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
@ -31,10 +31,13 @@ import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.InvalidModuleDescriptorException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Builder;
|
||||
import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleDescriptor.Exports;
|
||||
import java.lang.module.ModuleDescriptor.Opens;
|
||||
import java.lang.module.ModuleDescriptor.Version;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.util.ArrayList;
|
||||
@ -46,7 +49,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.misc.JavaLangModuleAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.ModuleResolution;
|
||||
|
||||
import static jdk.internal.module.ClassFileConstants.*;
|
||||
|
||||
@ -58,7 +63,10 @@ import static jdk.internal.module.ClassFileConstants.*;
|
||||
* and fine control over the throwing of InvalidModuleDescriptorException.
|
||||
*/
|
||||
|
||||
final class ModuleInfo {
|
||||
public final class ModuleInfo {
|
||||
|
||||
private static final JavaLangModuleAccess JLMA
|
||||
= SharedSecrets.getJavaLangModuleAccess();
|
||||
|
||||
// supplies the set of packages when ModulePackages attribute not present
|
||||
private final Supplier<Set<String>> packageFinder;
|
||||
@ -75,14 +83,42 @@ final class ModuleInfo {
|
||||
this(pf, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A holder class for the ModuleDescriptor that is created by reading the
|
||||
* Module and other standard class file attributes. It also holds the objects
|
||||
* that represent the non-standard class file attributes that are read from
|
||||
* the class file.
|
||||
*/
|
||||
public static final class Attributes {
|
||||
private final ModuleDescriptor descriptor;
|
||||
private final ModuleHashes recordedHashes;
|
||||
private final ModuleResolution moduleResolution;
|
||||
Attributes(ModuleDescriptor descriptor,
|
||||
ModuleHashes recordedHashes,
|
||||
ModuleResolution moduleResolution) {
|
||||
this.descriptor = descriptor;
|
||||
this.recordedHashes = recordedHashes;
|
||||
this.moduleResolution = moduleResolution;
|
||||
}
|
||||
public ModuleDescriptor descriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
public ModuleHashes recordedHashes() {
|
||||
return recordedHashes;
|
||||
}
|
||||
public ModuleResolution moduleResolution() {
|
||||
return moduleResolution;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads a {@code module-info.class} from the given input stream.
|
||||
*
|
||||
* @throws InvalidModuleDescriptorException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ModuleDescriptor read(InputStream in,
|
||||
Supplier<Set<String>> pf)
|
||||
public static Attributes read(InputStream in, Supplier<Set<String>> pf)
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
@ -100,9 +136,7 @@ final class ModuleInfo {
|
||||
* @throws InvalidModuleDescriptorException
|
||||
* @throws UncheckedIOException
|
||||
*/
|
||||
public static ModuleDescriptor read(ByteBuffer bb,
|
||||
Supplier<Set<String>> pf)
|
||||
{
|
||||
public static Attributes read(ByteBuffer bb, Supplier<Set<String>> pf) {
|
||||
try {
|
||||
return new ModuleInfo(pf).doRead(new DataInputWrapper(bb));
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
@ -121,9 +155,7 @@ final class ModuleInfo {
|
||||
* @throws InvalidModuleDescriptorException
|
||||
* @throws UncheckedIOException
|
||||
*/
|
||||
static ModuleDescriptor readIgnoringHashes(ByteBuffer bb,
|
||||
Supplier<Set<String>> pf)
|
||||
{
|
||||
public static Attributes readIgnoringHashes(ByteBuffer bb, Supplier<Set<String>> pf) {
|
||||
try {
|
||||
return new ModuleInfo(pf, false).doRead(new DataInputWrapper(bb));
|
||||
} catch (IllegalArgumentException | IllegalStateException e) {
|
||||
@ -144,7 +176,7 @@ final class ModuleInfo {
|
||||
* because an identifier is not a legal Java identifier, duplicate
|
||||
* exports, and many other reasons
|
||||
*/
|
||||
private ModuleDescriptor doRead(DataInput in) throws IOException {
|
||||
private Attributes doRead(DataInput in) throws IOException {
|
||||
|
||||
int magic = in.readInt();
|
||||
if (magic != 0xCAFEBABE)
|
||||
@ -163,8 +195,9 @@ final class ModuleInfo {
|
||||
throw invalidModuleDescriptor("access_flags should be ACC_MODULE");
|
||||
|
||||
int this_class = in.readUnsignedShort();
|
||||
if (this_class != 0)
|
||||
throw invalidModuleDescriptor("this_class must be 0");
|
||||
String mn = cpool.getClassName(this_class);
|
||||
if (!"module-info".equals(mn))
|
||||
throw invalidModuleDescriptor("this_class should be module-info");
|
||||
|
||||
int super_class = in.readUnsignedShort();
|
||||
if (super_class > 0)
|
||||
@ -189,10 +222,10 @@ final class ModuleInfo {
|
||||
|
||||
Builder builder = null;
|
||||
Set<String> packages = null;
|
||||
String version = null;
|
||||
String mainClass = null;
|
||||
String[] osValues = null;
|
||||
ModuleHashes hashes = null;
|
||||
ModuleResolution moduleResolution = null;
|
||||
|
||||
for (int i = 0; i < attributes_count ; i++) {
|
||||
int name_index = in.readUnsignedShort();
|
||||
@ -215,10 +248,6 @@ final class ModuleInfo {
|
||||
packages = readModulePackagesAttribute(in, cpool);
|
||||
break;
|
||||
|
||||
case MODULE_VERSION :
|
||||
version = readModuleVersionAttribute(in, cpool);
|
||||
break;
|
||||
|
||||
case MODULE_MAIN_CLASS :
|
||||
mainClass = readModuleMainClassAttribute(in, cpool);
|
||||
break;
|
||||
@ -235,6 +264,10 @@ final class ModuleInfo {
|
||||
}
|
||||
break;
|
||||
|
||||
case MODULE_RESOLUTION :
|
||||
moduleResolution = readModuleResolution(in, cpool);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isAttributeDisallowed(attribute_name)) {
|
||||
throw invalidModuleDescriptor(attribute_name
|
||||
@ -263,23 +296,33 @@ final class ModuleInfo {
|
||||
usedPackageFinder = true;
|
||||
}
|
||||
if (packages != null) {
|
||||
for (String pn : builder.exportedAndOpenPackages()) {
|
||||
if (!packages.contains(pn)) {
|
||||
String tail;
|
||||
if (usedPackageFinder) {
|
||||
tail = " not found by package finder";
|
||||
} else {
|
||||
tail = " missing from ModulePackages attribute";
|
||||
Set<String> exportedPackages = JLMA.exportedPackages(builder);
|
||||
Set<String> openPackages = JLMA.openPackages(builder);
|
||||
if (packages.containsAll(exportedPackages)
|
||||
&& packages.containsAll(openPackages)) {
|
||||
packages.removeAll(exportedPackages);
|
||||
packages.removeAll(openPackages);
|
||||
} else {
|
||||
// the set of packages is not complete
|
||||
Set<String> exportedAndOpenPackages = new HashSet<>();
|
||||
exportedAndOpenPackages.addAll(exportedPackages);
|
||||
exportedAndOpenPackages.addAll(openPackages);
|
||||
for (String pn : exportedAndOpenPackages) {
|
||||
if (!packages.contains(pn)) {
|
||||
String tail;
|
||||
if (usedPackageFinder) {
|
||||
tail = " not found by package finder";
|
||||
} else {
|
||||
tail = " missing from ModulePackages attribute";
|
||||
}
|
||||
throw invalidModuleDescriptor("Package " + pn + tail);
|
||||
}
|
||||
throw invalidModuleDescriptor("Package " + pn + tail);
|
||||
}
|
||||
packages.remove(pn);
|
||||
assert false; // should not get here
|
||||
}
|
||||
builder.contains(packages);
|
||||
}
|
||||
|
||||
if (version != null)
|
||||
builder.version(version);
|
||||
if (mainClass != null)
|
||||
builder.mainClass(mainClass);
|
||||
if (osValues != null) {
|
||||
@ -287,10 +330,9 @@ final class ModuleInfo {
|
||||
if (osValues[1] != null) builder.osArch(osValues[1]);
|
||||
if (osValues[2] != null) builder.osVersion(osValues[2]);
|
||||
}
|
||||
if (hashes != null)
|
||||
builder.hashes(hashes);
|
||||
|
||||
return builder.build();
|
||||
ModuleDescriptor descriptor = builder.build();
|
||||
return new Attributes(descriptor, hashes, moduleResolution);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,38 +344,55 @@ final class ModuleInfo {
|
||||
{
|
||||
// module_name
|
||||
int module_name_index = in.readUnsignedShort();
|
||||
String mn = cpool.getUtf8AsBinaryName(module_name_index);
|
||||
|
||||
Builder builder = new ModuleDescriptor.Builder(mn, /*strict*/ false);
|
||||
String mn = cpool.getModuleName(module_name_index);
|
||||
|
||||
int module_flags = in.readUnsignedShort();
|
||||
boolean open = ((module_flags & ACC_OPEN) != 0);
|
||||
if (open)
|
||||
builder.open(true);
|
||||
if ((module_flags & ACC_SYNTHETIC) != 0)
|
||||
builder.synthetic(true);
|
||||
boolean synthetic = ((module_flags & ACC_SYNTHETIC) != 0);
|
||||
|
||||
Builder builder = JLMA.newModuleBuilder(mn, false, open, synthetic);
|
||||
|
||||
int module_version_index = in.readUnsignedShort();
|
||||
if (module_version_index != 0) {
|
||||
String vs = cpool.getUtf8(module_version_index);
|
||||
builder.version(vs);
|
||||
}
|
||||
|
||||
int requires_count = in.readUnsignedShort();
|
||||
boolean requiresJavaBase = false;
|
||||
for (int i=0; i<requires_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
int flags = in.readUnsignedShort();
|
||||
String dn = cpool.getUtf8AsBinaryName(index);
|
||||
int requires_index = in.readUnsignedShort();
|
||||
String dn = cpool.getModuleName(requires_index);
|
||||
|
||||
int requires_flags = in.readUnsignedShort();
|
||||
Set<Requires.Modifier> mods;
|
||||
if (flags == 0) {
|
||||
if (requires_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_TRANSITIVE) != 0)
|
||||
if ((requires_flags & ACC_TRANSITIVE) != 0)
|
||||
mods.add(Requires.Modifier.TRANSITIVE);
|
||||
if ((flags & ACC_STATIC_PHASE) != 0)
|
||||
if ((requires_flags & ACC_STATIC_PHASE) != 0)
|
||||
mods.add(Requires.Modifier.STATIC);
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((requires_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Requires.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((requires_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Requires.Modifier.MANDATED);
|
||||
}
|
||||
builder.requires(mods, dn);
|
||||
|
||||
int requires_version_index = in.readUnsignedShort();
|
||||
Version compiledVersion = null;
|
||||
if (requires_version_index != 0) {
|
||||
String vs = cpool.getUtf8(requires_version_index);
|
||||
compiledVersion = Version.parse(vs);
|
||||
}
|
||||
|
||||
if (compiledVersion == null) {
|
||||
builder.requires(mods, dn);
|
||||
} else {
|
||||
builder.requires(mods, dn, compiledVersion);
|
||||
}
|
||||
|
||||
if (dn.equals("java.base"))
|
||||
requiresJavaBase = true;
|
||||
}
|
||||
@ -350,18 +409,18 @@ final class ModuleInfo {
|
||||
int exports_count = in.readUnsignedShort();
|
||||
if (exports_count > 0) {
|
||||
for (int i=0; i<exports_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
String pkg = cpool.getUtf8AsBinaryName(index);
|
||||
int exports_index = in.readUnsignedShort();
|
||||
String pkg = cpool.getPackageName(exports_index);
|
||||
|
||||
Set<Exports.Modifier> mods;
|
||||
int flags = in.readUnsignedShort();
|
||||
if (flags == 0) {
|
||||
int exports_flags = in.readUnsignedShort();
|
||||
if (exports_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((exports_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Exports.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((exports_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Exports.Modifier.MANDATED);
|
||||
}
|
||||
|
||||
@ -370,7 +429,7 @@ 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.getUtf8AsBinaryName(exports_to_index));
|
||||
targets.add(cpool.getModuleName(exports_to_index));
|
||||
}
|
||||
builder.exports(mods, pkg, targets);
|
||||
} else {
|
||||
@ -386,18 +445,18 @@ final class ModuleInfo {
|
||||
+ " module must be 0 length");
|
||||
}
|
||||
for (int i=0; i<opens_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
String pkg = cpool.getUtf8AsBinaryName(index);
|
||||
int opens_index = in.readUnsignedShort();
|
||||
String pkg = cpool.getPackageName(opens_index);
|
||||
|
||||
Set<Opens.Modifier> mods;
|
||||
int flags = in.readUnsignedShort();
|
||||
if (flags == 0) {
|
||||
int opens_flags = in.readUnsignedShort();
|
||||
if (opens_flags == 0) {
|
||||
mods = Collections.emptySet();
|
||||
} else {
|
||||
mods = new HashSet<>();
|
||||
if ((flags & ACC_SYNTHETIC) != 0)
|
||||
if ((opens_flags & ACC_SYNTHETIC) != 0)
|
||||
mods.add(Opens.Modifier.SYNTHETIC);
|
||||
if ((flags & ACC_MANDATED) != 0)
|
||||
if ((opens_flags & ACC_MANDATED) != 0)
|
||||
mods.add(Opens.Modifier.MANDATED);
|
||||
}
|
||||
|
||||
@ -406,7 +465,7 @@ 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.getUtf8AsBinaryName(opens_to_index));
|
||||
targets.add(cpool.getModuleName(opens_to_index));
|
||||
}
|
||||
builder.opens(mods, pkg, targets);
|
||||
} else {
|
||||
@ -419,7 +478,7 @@ final class ModuleInfo {
|
||||
if (uses_count > 0) {
|
||||
for (int i=0; i<uses_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
String sn = cpool.getClassNameAsBinaryName(index);
|
||||
String sn = cpool.getClassName(index);
|
||||
builder.uses(sn);
|
||||
}
|
||||
}
|
||||
@ -428,12 +487,12 @@ final class ModuleInfo {
|
||||
if (provides_count > 0) {
|
||||
for (int i=0; i<provides_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
String sn = cpool.getClassNameAsBinaryName(index);
|
||||
String sn = cpool.getClassName(index);
|
||||
int with_count = in.readUnsignedShort();
|
||||
List<String> providers = new ArrayList<>(with_count);
|
||||
for (int j=0; j<with_count; j++) {
|
||||
index = in.readUnsignedShort();
|
||||
String pn = cpool.getClassNameAsBinaryName(index);
|
||||
String pn = cpool.getClassName(index);
|
||||
providers.add(pn);
|
||||
}
|
||||
builder.provides(sn, providers);
|
||||
@ -453,22 +512,16 @@ final class ModuleInfo {
|
||||
Set<String> packages = new HashSet<>(package_count);
|
||||
for (int i=0; i<package_count; i++) {
|
||||
int index = in.readUnsignedShort();
|
||||
String pn = cpool.getUtf8AsBinaryName(index);
|
||||
packages.add(pn);
|
||||
String pn = cpool.getPackageName(index);
|
||||
boolean added = packages.add(pn);
|
||||
if (!added) {
|
||||
throw invalidModuleDescriptor("Package " + pn + " in ModulePackages"
|
||||
+ "attribute more than once");
|
||||
}
|
||||
}
|
||||
return packages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the ModuleVersion attribute
|
||||
*/
|
||||
private String readModuleVersionAttribute(DataInput in, ConstantPool cpool)
|
||||
throws IOException
|
||||
{
|
||||
int index = in.readUnsignedShort();
|
||||
return cpool.getUtf8(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the ModuleMainClass attribute
|
||||
*/
|
||||
@ -476,7 +529,7 @@ final class ModuleInfo {
|
||||
throws IOException
|
||||
{
|
||||
int index = in.readUnsignedShort();
|
||||
return cpool.getClassNameAsBinaryName(index);
|
||||
return cpool.getClassName(index);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -516,7 +569,7 @@ final class ModuleInfo {
|
||||
Map<String, byte[]> map = new HashMap<>(hash_count);
|
||||
for (int i=0; i<hash_count; i++) {
|
||||
int module_name_index = in.readUnsignedShort();
|
||||
String mn = cpool.getUtf8AsBinaryName(module_name_index);
|
||||
String mn = cpool.getModuleName(module_name_index);
|
||||
int hash_length = in.readUnsignedShort();
|
||||
if (hash_length == 0) {
|
||||
throw invalidModuleDescriptor("hash_length == 0");
|
||||
@ -529,6 +582,31 @@ final class ModuleInfo {
|
||||
return new ModuleHashes(algorithm, map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the ModuleResolution attribute.
|
||||
*/
|
||||
private ModuleResolution readModuleResolution(DataInput in,
|
||||
ConstantPool cpool)
|
||||
throws IOException
|
||||
{
|
||||
int flags = in.readUnsignedShort();
|
||||
|
||||
int reason = 0;
|
||||
if ((flags & WARN_DEPRECATED) != 0)
|
||||
reason = WARN_DEPRECATED;
|
||||
if ((flags & WARN_DEPRECATED_FOR_REMOVAL) != 0) {
|
||||
if (reason != 0)
|
||||
throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
|
||||
reason = WARN_DEPRECATED_FOR_REMOVAL;
|
||||
}
|
||||
if ((flags & WARN_INCUBATING) != 0) {
|
||||
if (reason != 0)
|
||||
throw invalidModuleDescriptor("Bad module resolution flags:" + flags);
|
||||
}
|
||||
|
||||
return new ModuleResolution(flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the given attribute can be present at most once
|
||||
@ -540,10 +618,10 @@ final class ModuleInfo {
|
||||
name.equals(SOURCE_FILE) ||
|
||||
name.equals(SDE) ||
|
||||
name.equals(MODULE_PACKAGES) ||
|
||||
name.equals(MODULE_VERSION) ||
|
||||
name.equals(MODULE_MAIN_CLASS) ||
|
||||
name.equals(MODULE_TARGET) ||
|
||||
name.equals(MODULE_HASHES))
|
||||
name.equals(MODULE_HASHES) ||
|
||||
name.equals(MODULE_RESOLUTION))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -604,6 +682,8 @@ final class ModuleInfo {
|
||||
static final int CONSTANT_MethodHandle = 15;
|
||||
static final int CONSTANT_MethodType = 16;
|
||||
static final int CONSTANT_InvokeDynamic = 18;
|
||||
static final int CONSTANT_Module = 19;
|
||||
static final int CONSTANT_Package = 20;
|
||||
|
||||
private static class Entry {
|
||||
protected Entry(int tag) {
|
||||
@ -653,6 +733,8 @@ final class ModuleInfo {
|
||||
break;
|
||||
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_Package:
|
||||
case CONSTANT_Module:
|
||||
case CONSTANT_String:
|
||||
int index = in.readUnsignedShort();
|
||||
pool[i] = new IndexEntry(tag, index);
|
||||
@ -715,14 +797,34 @@ final class ModuleInfo {
|
||||
throw invalidModuleDescriptor("CONSTANT_Class expected at entry: "
|
||||
+ index);
|
||||
}
|
||||
return getUtf8(((IndexEntry) e).index);
|
||||
String value = getUtf8(((IndexEntry) e).index);
|
||||
checkUnqualifiedName("CONSTANT_Class", index, value);
|
||||
return value.replace('/', '.'); // internal form -> binary name
|
||||
}
|
||||
|
||||
String getClassNameAsBinaryName(int index) {
|
||||
String value = getClassName(index);
|
||||
String getPackageName(int index) {
|
||||
checkIndex(index);
|
||||
Entry e = pool[index];
|
||||
if (e.tag != CONSTANT_Package) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Package expected at entry: "
|
||||
+ index);
|
||||
}
|
||||
String value = getUtf8(((IndexEntry) e).index);
|
||||
checkUnqualifiedName("CONSTANT_Package", index, value);
|
||||
return value.replace('/', '.'); // internal form -> binary name
|
||||
}
|
||||
|
||||
String getModuleName(int index) {
|
||||
checkIndex(index);
|
||||
Entry e = pool[index];
|
||||
if (e.tag != CONSTANT_Module) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module expected at entry: "
|
||||
+ index);
|
||||
}
|
||||
String value = getUtf8(((IndexEntry) e).index);
|
||||
return decodeModuleName(index, value);
|
||||
}
|
||||
|
||||
String getUtf8(int index) {
|
||||
checkIndex(index);
|
||||
Entry e = pool[index];
|
||||
@ -733,15 +835,103 @@ final class ModuleInfo {
|
||||
return (String) (((ValueEntry) e).value);
|
||||
}
|
||||
|
||||
String getUtf8AsBinaryName(int index) {
|
||||
String value = getUtf8(index);
|
||||
return value.replace('/', '.'); // internal -> binary name
|
||||
}
|
||||
|
||||
void checkIndex(int index) {
|
||||
if (index < 1 || index >= pool.length)
|
||||
throw invalidModuleDescriptor("Index into constant pool out of range");
|
||||
}
|
||||
|
||||
void checkUnqualifiedName(String what, int index, String value) {
|
||||
int len = value.length();
|
||||
if (len == 0) {
|
||||
throw invalidModuleDescriptor(what + " at entry " + index
|
||||
+ " has zero length");
|
||||
}
|
||||
for (int i=0; i<len; i++) {
|
||||
char c = value.charAt(i);
|
||||
if (c == '.' || c == ';' || c == '[') {
|
||||
throw invalidModuleDescriptor(what + " at entry " + index
|
||||
+ " has illegal character: '"
|
||||
+ c + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Decode" a module name that has been read from the constant pool.
|
||||
*/
|
||||
String decodeModuleName(int index, String value) {
|
||||
int len = value.length();
|
||||
if (len == 0) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module at entry "
|
||||
+ index + " is zero length");
|
||||
}
|
||||
int i = 0;
|
||||
while (i < len) {
|
||||
int cp = value.codePointAt(i);
|
||||
if (cp == ':' || cp == '@' || cp < 0x20) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module at entry "
|
||||
+ index + " has illegal character: "
|
||||
+ Character.getName(cp));
|
||||
}
|
||||
|
||||
// blackslash is the escape character
|
||||
if (cp == '\\')
|
||||
return decodeModuleName(index, i, value);
|
||||
|
||||
i += Character.charCount(cp);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Decode" a module name that has been read from the constant pool and
|
||||
* partly checked for illegal characters (up to position {@code i}).
|
||||
*/
|
||||
String decodeModuleName(int index, int i, String value) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
// copy the code points that have been checked
|
||||
int j = 0;
|
||||
while (j < i) {
|
||||
int cp = value.codePointAt(j);
|
||||
sb.appendCodePoint(cp);
|
||||
j += Character.charCount(cp);
|
||||
}
|
||||
|
||||
// decode from position {@code i} to end
|
||||
int len = value.length();
|
||||
while (i < len) {
|
||||
int cp = value.codePointAt(i);
|
||||
if (cp == ':' || cp == '@' || cp < 0x20) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module at entry "
|
||||
+ index + " has illegal character: "
|
||||
+ Character.getName(cp));
|
||||
}
|
||||
|
||||
// blackslash is the escape character
|
||||
if (cp == '\\') {
|
||||
j = i + Character.charCount(cp);
|
||||
if (j >= len) {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module at entry "
|
||||
+ index + " has illegal "
|
||||
+ "escape sequence");
|
||||
}
|
||||
int next = value.codePointAt(j);
|
||||
if (next != '\\' && next != ':' && next != '@') {
|
||||
throw invalidModuleDescriptor("CONSTANT_Module at entry "
|
||||
+ index + " has illegal "
|
||||
+ "escape sequence");
|
||||
}
|
||||
sb.appendCodePoint(next);
|
||||
i += Character.charCount(next);
|
||||
} else {
|
||||
sb.appendCodePoint(cp);
|
||||
}
|
||||
|
||||
i += Character.charCount(cp);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
@ -70,6 +70,9 @@ public final class ModuleInfoExtender {
|
||||
// the hashes for the Hashes attribute
|
||||
private ModuleHashes hashes;
|
||||
|
||||
// the value of the ModuleResolution attribute
|
||||
private ModuleResolution moduleResolution;
|
||||
|
||||
private ModuleInfoExtender(InputStream in) {
|
||||
this.in = in;
|
||||
}
|
||||
@ -120,6 +123,14 @@ public final class ModuleInfoExtender {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for the ModuleResolution attribute.
|
||||
*/
|
||||
public ModuleInfoExtender moduleResolution(ModuleResolution mres) {
|
||||
this.moduleResolution = mres;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A ClassVisitor that supports adding class file attributes. If an
|
||||
* attribute already exists then the first occurence of the attribute
|
||||
@ -183,21 +194,20 @@ public final class ModuleInfoExtender {
|
||||
|
||||
if (packages != null)
|
||||
cv.addAttribute(new ModulePackagesAttribute(packages));
|
||||
if (version != null)
|
||||
cv.addAttribute(new ModuleVersionAttribute(version));
|
||||
if (mainClass != null)
|
||||
cv.addAttribute(new ModuleMainClassAttribute(mainClass));
|
||||
if (osName != null || osArch != null || osVersion != null)
|
||||
cv.addAttribute(new ModuleTargetAttribute(osName, osArch, osVersion));
|
||||
if (hashes != null)
|
||||
cv.addAttribute(new ModuleHashesAttribute(hashes));
|
||||
if (moduleResolution != null)
|
||||
cv.addAttribute(new ModuleResolutionAttribute(moduleResolution.value()));
|
||||
|
||||
List<Attribute> attrs = new ArrayList<>();
|
||||
|
||||
// prototypes of attributes that should be parsed
|
||||
attrs.add(new ModuleAttribute());
|
||||
attrs.add(new ModuleAttribute(version));
|
||||
attrs.add(new ModulePackagesAttribute());
|
||||
attrs.add(new ModuleVersionAttribute());
|
||||
attrs.add(new ModuleMainClassAttribute());
|
||||
attrs.add(new ModuleTargetAttribute());
|
||||
attrs.add(new ModuleHashesAttribute());
|
||||
|
@ -49,13 +49,12 @@ public final class ModuleInfoWriter {
|
||||
* returning it in a byte array.
|
||||
*/
|
||||
private static byte[] toModuleInfo(ModuleDescriptor md) {
|
||||
|
||||
ClassWriter cw = new ClassWriter(0);
|
||||
cw.visit(Opcodes.V1_9, ACC_MODULE, null, null, null, null);
|
||||
cw.visit(Opcodes.V1_9, ACC_MODULE, "module-info", null, null, null);
|
||||
cw.visitAttribute(new ModuleAttribute(md));
|
||||
|
||||
// for tests: write the Packages attribute when there are packages that
|
||||
// aren't exported or open
|
||||
// for tests: write the ModulePackages attribute when there are packages
|
||||
// that aren't exported or open
|
||||
Stream<String> exported = md.exports().stream()
|
||||
.map(ModuleDescriptor.Exports::source);
|
||||
Stream<String> open = md.opens().stream()
|
||||
@ -64,10 +63,10 @@ public final class ModuleInfoWriter {
|
||||
if (md.packages().size() > exportedOrOpen)
|
||||
cw.visitAttribute(new ModulePackagesAttribute(md.packages()));
|
||||
|
||||
md.version().ifPresent(v -> cw.visitAttribute(new ModuleVersionAttribute(v)));
|
||||
// write ModuleMainClass if the module has a main class
|
||||
md.mainClass().ifPresent(mc -> cw.visitAttribute(new ModuleMainClassAttribute(mc)));
|
||||
|
||||
// write the TargetPlatform attribute if have any of OS name/arch/version
|
||||
// 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);
|
||||
@ -76,7 +75,6 @@ public final class ModuleInfoWriter {
|
||||
}
|
||||
|
||||
cw.visitEnd();
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
|
||||
|
@ -149,9 +149,22 @@ public final class ModulePatcher {
|
||||
|
||||
// return a module reference to the patched module
|
||||
URI location = mref.location().orElse(null);
|
||||
return JLMA.newPatchedModule(descriptor,
|
||||
location,
|
||||
() -> new PatchedModuleReader(paths, mref));
|
||||
|
||||
ModuleHashes recordedHashes = null;
|
||||
ModuleResolution mres = null;
|
||||
if (mref instanceof ModuleReferenceImpl) {
|
||||
ModuleReferenceImpl impl = (ModuleReferenceImpl)mref;
|
||||
recordedHashes = impl.recordedHashes();
|
||||
mres = impl.moduleResolution();
|
||||
}
|
||||
|
||||
return new ModuleReferenceImpl(descriptor,
|
||||
location,
|
||||
() -> new PatchedModuleReader(paths, mref),
|
||||
this,
|
||||
recordedHashes,
|
||||
null,
|
||||
mres);
|
||||
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.module;
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
@ -32,7 +32,12 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.FindException;
|
||||
import java.lang.module.InvalidModuleDescriptorException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
@ -59,7 +64,6 @@ import java.util.zip.ZipFile;
|
||||
|
||||
import jdk.internal.jmod.JmodFile;
|
||||
import jdk.internal.jmod.JmodFile.Section;
|
||||
import jdk.internal.module.Checks;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
import jdk.internal.util.jar.VersionedStream;
|
||||
|
||||
@ -74,7 +78,7 @@ import jdk.internal.util.jar.VersionedStream;
|
||||
* modules in JMOD files.
|
||||
*/
|
||||
|
||||
class ModulePath implements ModuleFinder {
|
||||
public class ModulePath implements ModuleFinder {
|
||||
private static final String MODULE_INFO = "module-info.class";
|
||||
|
||||
// the version to use for multi-release modular JARs
|
||||
@ -90,7 +94,7 @@ class ModulePath implements ModuleFinder {
|
||||
// map of module name to module reference map for modules already located
|
||||
private final Map<String, ModuleReference> cachedModules = new HashMap<>();
|
||||
|
||||
ModulePath(Runtime.Version version, boolean isLinkPhase, Path... entries) {
|
||||
public ModulePath(Runtime.Version version, boolean isLinkPhase, Path... entries) {
|
||||
this.releaseVersion = version;
|
||||
this.isLinkPhase = isLinkPhase;
|
||||
this.entries = entries.clone();
|
||||
@ -99,7 +103,7 @@ class ModulePath implements ModuleFinder {
|
||||
}
|
||||
}
|
||||
|
||||
ModulePath(Path... entries) {
|
||||
public ModulePath(Path... entries) {
|
||||
this(JarFile.runtimeVersion(), false, entries);
|
||||
}
|
||||
|
||||
@ -343,11 +347,11 @@ class ModulePath implements ModuleFinder {
|
||||
*/
|
||||
private ModuleReference readJMod(Path file) throws IOException {
|
||||
try (JmodFile jf = new JmodFile(file)) {
|
||||
ModuleDescriptor md;
|
||||
ModuleInfo.Attributes attrs;
|
||||
try (InputStream in = jf.getInputStream(Section.CLASSES, MODULE_INFO)) {
|
||||
md = ModuleDescriptor.read(in, () -> jmodPackages(jf));
|
||||
attrs = ModuleInfo.read(in, () -> jmodPackages(jf));
|
||||
}
|
||||
return ModuleReferences.newJModModule(md, file);
|
||||
return ModuleReferences.newJModModule(attrs, file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -557,13 +561,14 @@ class ModulePath implements ModuleFinder {
|
||||
ZipFile.OPEN_READ,
|
||||
releaseVersion))
|
||||
{
|
||||
ModuleDescriptor md;
|
||||
ModuleInfo.Attributes attrs;
|
||||
JarEntry entry = jf.getJarEntry(MODULE_INFO);
|
||||
if (entry == null) {
|
||||
|
||||
// no module-info.class so treat it as automatic module
|
||||
try {
|
||||
md = deriveModuleDescriptor(jf);
|
||||
ModuleDescriptor md = deriveModuleDescriptor(jf);
|
||||
attrs = new ModuleInfo.Attributes(md, null, null);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new FindException(
|
||||
"Unable to derive module descriptor for: "
|
||||
@ -571,11 +576,11 @@ class ModulePath implements ModuleFinder {
|
||||
}
|
||||
|
||||
} else {
|
||||
md = ModuleDescriptor.read(jf.getInputStream(entry),
|
||||
() -> jarPackages(jf));
|
||||
attrs = ModuleInfo.read(jf.getInputStream(entry),
|
||||
() -> jarPackages(jf));
|
||||
}
|
||||
|
||||
return ModuleReferences.newJarModule(md, file);
|
||||
return ModuleReferences.newJarModule(attrs, file);
|
||||
}
|
||||
}
|
||||
|
||||
@ -604,15 +609,15 @@ class ModulePath implements ModuleFinder {
|
||||
*/
|
||||
private ModuleReference readExplodedModule(Path dir) throws IOException {
|
||||
Path mi = dir.resolve(MODULE_INFO);
|
||||
ModuleDescriptor md;
|
||||
ModuleInfo.Attributes attrs;
|
||||
try (InputStream in = Files.newInputStream(mi)) {
|
||||
md = ModuleDescriptor.read(new BufferedInputStream(in),
|
||||
() -> explodedPackages(dir));
|
||||
attrs = ModuleInfo.read(new BufferedInputStream(in),
|
||||
() -> explodedPackages(dir));
|
||||
} catch (NoSuchFileException e) {
|
||||
// for now
|
||||
return null;
|
||||
}
|
||||
return ModuleReferences.newExplodedModule(md, dir);
|
||||
return ModuleReferences.newExplodedModule(attrs, dir);
|
||||
}
|
||||
|
||||
/**
|
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A ModuleReference implementation that supports referencing a module that
|
||||
* is patched and/or can be tied to other modules by means of hashes.
|
||||
*/
|
||||
|
||||
public class ModuleReferenceImpl extends ModuleReference {
|
||||
|
||||
private final Supplier<ModuleReader> readerSupplier;
|
||||
|
||||
// non-null if the module is patched
|
||||
private final ModulePatcher patcher;
|
||||
|
||||
// the hashes of other modules recorded in this module
|
||||
private final ModuleHashes recordedHashes;
|
||||
|
||||
// the function that computes the hash of this module
|
||||
private final ModuleHashes.HashSupplier hasher;
|
||||
|
||||
// ModuleResolution flags
|
||||
private final ModuleResolution moduleResolution;
|
||||
|
||||
// cached hash of this module to avoid needing to compute it many times
|
||||
private byte[] cachedHash;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class.
|
||||
*/
|
||||
ModuleReferenceImpl(ModuleDescriptor descriptor,
|
||||
URI location,
|
||||
Supplier<ModuleReader> readerSupplier,
|
||||
ModulePatcher patcher,
|
||||
ModuleHashes recordedHashes,
|
||||
ModuleHashes.HashSupplier hasher,
|
||||
ModuleResolution moduleResolution)
|
||||
{
|
||||
super(descriptor, Objects.requireNonNull(location));
|
||||
this.readerSupplier = readerSupplier;
|
||||
this.patcher = patcher;
|
||||
this.recordedHashes = recordedHashes;
|
||||
this.hasher = hasher;
|
||||
this.moduleResolution = moduleResolution;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleReader open() throws IOException {
|
||||
try {
|
||||
return readerSupplier.get();
|
||||
} catch (UncheckedIOException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this module has been patched via --patch-module.
|
||||
*/
|
||||
public boolean isPatched() {
|
||||
return (patcher != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hashes recorded in this module or {@code null} if there
|
||||
* are no hashes recorded.
|
||||
*/
|
||||
public ModuleHashes recordedHashes() {
|
||||
return recordedHashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supplier that computes the hash of this module.
|
||||
*/
|
||||
ModuleHashes.HashSupplier hasher() {
|
||||
return hasher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ModuleResolution flags.
|
||||
*/
|
||||
public ModuleResolution moduleResolution() {
|
||||
return moduleResolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the hash of this module. Returns {@code null} if the hash
|
||||
* cannot be computed.
|
||||
*
|
||||
* @throws java.io.UncheckedIOException if an I/O error occurs
|
||||
*/
|
||||
public byte[] computeHash(String algorithm) {
|
||||
byte[] result = cachedHash;
|
||||
if (result != null)
|
||||
return result;
|
||||
if (hasher == null)
|
||||
return null;
|
||||
cachedHash = result = hasher.generate(algorithm);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hc = hash;
|
||||
if (hc == 0) {
|
||||
hc = descriptor().hashCode();
|
||||
hc = 43 * hc + Objects.hashCode(location());
|
||||
hc = 43 * hc + Objects.hashCode(patcher);
|
||||
if (hc == 0)
|
||||
hc = -1;
|
||||
hash = hc;
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
|
||||
private int hash;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object ob) {
|
||||
if (!(ob instanceof ModuleReferenceImpl))
|
||||
return false;
|
||||
ModuleReferenceImpl that = (ModuleReferenceImpl)ob;
|
||||
|
||||
// assume module content, recorded hashes, etc. are the same
|
||||
// when the modules have equal module descriptors, are at the
|
||||
// same location, and are patched by the same patcher.
|
||||
return Objects.equals(this.descriptor(), that.descriptor())
|
||||
&& Objects.equals(this.location(), that.location())
|
||||
&& Objects.equals(this.patcher, that.patcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
}
|
@ -23,13 +23,15 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.module;
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOError;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
@ -51,10 +53,7 @@ import java.util.zip.ZipFile;
|
||||
import jdk.internal.jmod.JmodFile;
|
||||
import jdk.internal.misc.JavaLangAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.ModuleBootstrap;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleHashes.HashSupplier;
|
||||
import jdk.internal.module.ModulePatcher;
|
||||
import jdk.internal.util.jar.VersionedStream;
|
||||
import sun.net.www.ParseUtil;
|
||||
|
||||
@ -75,12 +74,18 @@ class ModuleReferences {
|
||||
* Creates a ModuleReference to a module or to patched module when
|
||||
* creating modules for the boot Layer and --patch-module is specified.
|
||||
*/
|
||||
private static ModuleReference newModule(ModuleDescriptor md,
|
||||
private static ModuleReference newModule(ModuleInfo.Attributes attrs,
|
||||
URI uri,
|
||||
Supplier<ModuleReader> supplier,
|
||||
HashSupplier hasher) {
|
||||
|
||||
ModuleReference mref = new ModuleReference(md, uri, supplier, hasher);
|
||||
ModuleReference mref = new ModuleReferenceImpl(attrs.descriptor(),
|
||||
uri,
|
||||
supplier,
|
||||
null,
|
||||
attrs.recordedHashes(),
|
||||
hasher,
|
||||
attrs.moduleResolution());
|
||||
if (JLA.getBootLayer() == null)
|
||||
mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
|
||||
|
||||
@ -90,29 +95,29 @@ class ModuleReferences {
|
||||
/**
|
||||
* Creates a ModuleReference to a module packaged as a modular JAR.
|
||||
*/
|
||||
static ModuleReference newJarModule(ModuleDescriptor md, Path file) {
|
||||
static ModuleReference newJarModule(ModuleInfo.Attributes attrs, Path file) {
|
||||
URI uri = file.toUri();
|
||||
Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri);
|
||||
HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
|
||||
return newModule(md, uri, supplier, hasher);
|
||||
return newModule(attrs, uri, supplier, hasher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ModuleReference to a module packaged as a JMOD.
|
||||
*/
|
||||
static ModuleReference newJModModule(ModuleDescriptor md, Path file) {
|
||||
static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) {
|
||||
URI uri = file.toUri();
|
||||
Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri);
|
||||
HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a);
|
||||
return newModule(md, file.toUri(), supplier, hasher);
|
||||
return newModule(attrs, uri, supplier, hasher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ModuleReference to an exploded module.
|
||||
*/
|
||||
static ModuleReference newExplodedModule(ModuleDescriptor md, Path dir) {
|
||||
static ModuleReference newExplodedModule(ModuleInfo.Attributes attrs, Path dir) {
|
||||
Supplier<ModuleReader> supplier = () -> new ExplodedModuleReader(dir);
|
||||
return newModule(md, dir.toUri(), supplier, null);
|
||||
return newModule(attrs, dir.toUri(), supplier, null);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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.module.ModuleReference;
|
||||
import static jdk.internal.module.ClassFileConstants.*;
|
||||
|
||||
/**
|
||||
* Represents the Module Resolution flags.
|
||||
*/
|
||||
public final class ModuleResolution {
|
||||
|
||||
final int value;
|
||||
|
||||
ModuleResolution(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public static ModuleResolution empty() {
|
||||
return new ModuleResolution(0);
|
||||
}
|
||||
|
||||
public boolean doNotResolveByDefault() {
|
||||
return (value & DO_NOT_RESOLVE_BY_DEFAULT) != 0;
|
||||
}
|
||||
|
||||
public boolean hasDeprecatedWarning() {
|
||||
return (value & WARN_DEPRECATED) != 0;
|
||||
}
|
||||
|
||||
public boolean hasDeprecatedForRemovalWarning() {
|
||||
return (value & WARN_DEPRECATED_FOR_REMOVAL) != 0;
|
||||
}
|
||||
|
||||
public boolean hasIncubatingWarning() {
|
||||
return (value & WARN_INCUBATING) != 0;
|
||||
}
|
||||
|
||||
public ModuleResolution withDoNotResolveByDefault() {
|
||||
return new ModuleResolution(value | DO_NOT_RESOLVE_BY_DEFAULT);
|
||||
}
|
||||
|
||||
public ModuleResolution withDeprecated() {
|
||||
if ((value & (WARN_DEPRECATED_FOR_REMOVAL | WARN_INCUBATING)) != 0)
|
||||
throw new InternalError("cannot add deprecated to " + value);
|
||||
return new ModuleResolution(value | WARN_DEPRECATED);
|
||||
}
|
||||
|
||||
public ModuleResolution withDeprecatedForRemoval() {
|
||||
if ((value & (WARN_DEPRECATED | WARN_INCUBATING)) != 0)
|
||||
throw new InternalError("cannot add deprecated for removal to " + value);
|
||||
return new ModuleResolution(value | WARN_DEPRECATED_FOR_REMOVAL);
|
||||
}
|
||||
public ModuleResolution withIncubating() {
|
||||
if ((value & (WARN_DEPRECATED | WARN_DEPRECATED_FOR_REMOVAL)) != 0)
|
||||
throw new InternalError("cannot add incubating to " + value);
|
||||
return new ModuleResolution(value | WARN_INCUBATING);
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static boolean doNotResolveByDefault(ModuleReference mref) {
|
||||
// get the DO_NOT_RESOLVE_BY_DEFAULT flag, if any
|
||||
if (!(mref instanceof ModuleReferenceImpl))
|
||||
return false;
|
||||
|
||||
ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
|
||||
if (mres != null)
|
||||
return mres.doNotResolveByDefault();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasIncubatingWarning(ModuleReference mref) {
|
||||
if (!(mref instanceof ModuleReferenceImpl))
|
||||
return false;
|
||||
|
||||
ModuleResolution mres = ((ModuleReferenceImpl)mref).moduleResolution();
|
||||
if (mres != null)
|
||||
return mres.hasIncubatingWarning();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "[value=" + value + "]";
|
||||
}
|
||||
}
|
@ -23,12 +23,16 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.lang.module;
|
||||
package jdk.internal.module;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReader;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -36,7 +40,6 @@ import java.util.ArrayDeque;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@ -54,11 +57,7 @@ import jdk.internal.jimage.ImageReader;
|
||||
import jdk.internal.jimage.ImageReaderFactory;
|
||||
import jdk.internal.misc.JavaNetUriAccess;
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.ModuleBootstrap;
|
||||
import jdk.internal.module.ModuleHashes;
|
||||
import jdk.internal.module.ModuleHashes.HashSupplier;
|
||||
import jdk.internal.module.SystemModules;
|
||||
import jdk.internal.module.ModulePatcher;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
|
||||
/**
|
||||
@ -69,7 +68,7 @@ import jdk.internal.perf.PerfCounter;
|
||||
* Packages attribute.
|
||||
*/
|
||||
|
||||
class SystemModuleFinder implements ModuleFinder {
|
||||
public class SystemModuleFinder implements ModuleFinder {
|
||||
|
||||
private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
|
||||
|
||||
@ -84,11 +83,12 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
// ImageReader used to access all modules in the image
|
||||
private static final ImageReader imageReader;
|
||||
|
||||
// the set of modules in the run-time image
|
||||
private static final Set<ModuleReference> modules;
|
||||
// singleton finder to find modules in the run-time images
|
||||
private static final SystemModuleFinder INSTANCE;
|
||||
|
||||
// maps module name to module reference
|
||||
private static final Map<String, ModuleReference> nameToModule;
|
||||
public static SystemModuleFinder getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* For now, the module references are created eagerly on the assumption
|
||||
@ -98,72 +98,11 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
long t0 = System.nanoTime();
|
||||
imageReader = ImageReaderFactory.getImageReader();
|
||||
|
||||
String[] names = moduleNames();
|
||||
ModuleDescriptor[] descriptors = descriptors(names);
|
||||
|
||||
int n = names.length;
|
||||
moduleCount.add(n);
|
||||
|
||||
ModuleReference[] mods = new ModuleReference[n];
|
||||
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
Entry<String, ModuleReference>[] map
|
||||
= (Entry<String, ModuleReference>[])new Entry[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
ModuleDescriptor md = descriptors[i];
|
||||
|
||||
// create the ModuleReference
|
||||
ModuleReference mref = toModuleReference(md, hashSupplier(i, names[i]));
|
||||
|
||||
mods[i] = mref;
|
||||
map[i] = Map.entry(names[i], mref);
|
||||
|
||||
// counters
|
||||
packageCount.add(md.packages().size());
|
||||
exportsCount.add(md.exports().size());
|
||||
}
|
||||
|
||||
modules = Set.of(mods);
|
||||
nameToModule = Map.ofEntries(map);
|
||||
INSTANCE = new SystemModuleFinder();
|
||||
|
||||
initTime.addElapsedTimeFrom(t0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an array of ModuleDescriptor of the given module names.
|
||||
*
|
||||
* This obtains ModuleDescriptors from SystemModules class that is generated
|
||||
* from the jlink system-modules plugin. ModuleDescriptors have already
|
||||
* been validated at link time.
|
||||
*
|
||||
* If java.base is patched, or fastpath is disabled for troubleshooting
|
||||
* purpose, it will fall back to find system modules via jrt file system.
|
||||
*/
|
||||
private static ModuleDescriptor[] descriptors(String[] names) {
|
||||
// fastpath is enabled by default.
|
||||
// It can be disabled for troubleshooting purpose.
|
||||
boolean disabled =
|
||||
System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
|
||||
|
||||
// fast loading of ModuleDescriptor of system modules
|
||||
if (isFastPathSupported() && !disabled)
|
||||
return SystemModules.modules();
|
||||
|
||||
// if fast loading of ModuleDescriptors is disabled
|
||||
// fallback to read module-info.class
|
||||
ModuleDescriptor[] descriptors = new ModuleDescriptor[names.length];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
String mn = names[i];
|
||||
ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
|
||||
descriptors[i] = ModuleDescriptor.read(imageReader.getResourceBuffer(loc));
|
||||
|
||||
// add the recorded hashes of tied modules
|
||||
Hashes.add(descriptors[i]);
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private static boolean isFastPathSupported() {
|
||||
return SystemModules.MODULE_NAMES.length > 0;
|
||||
}
|
||||
@ -178,69 +117,95 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
return imageReader.getModuleNames();
|
||||
}
|
||||
|
||||
private static ModuleReference toModuleReference(ModuleDescriptor md,
|
||||
HashSupplier hash)
|
||||
{
|
||||
String mn = md.name();
|
||||
URI uri = JNUA.create("jrt", "/".concat(mn));
|
||||
// the set of modules in the run-time image
|
||||
private final Set<ModuleReference> modules;
|
||||
|
||||
Supplier<ModuleReader> readerSupplier = new Supplier<>() {
|
||||
@Override
|
||||
public ModuleReader get() {
|
||||
return new ImageModuleReader(mn, uri);
|
||||
}
|
||||
};
|
||||
// maps module name to module reference
|
||||
private final Map<String, ModuleReference> nameToModule;
|
||||
|
||||
ModuleReference mref =
|
||||
new ModuleReference(md, uri, readerSupplier, hash);
|
||||
// module name to hashes
|
||||
private final Map<String, byte[]> hashes;
|
||||
|
||||
// may need a reference to a patched module if --patch-module specified
|
||||
mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
|
||||
private SystemModuleFinder() {
|
||||
String[] names = moduleNames();
|
||||
int n = names.length;
|
||||
moduleCount.add(n);
|
||||
|
||||
return mref;
|
||||
}
|
||||
// fastpath is enabled by default.
|
||||
// It can be disabled for troubleshooting purpose.
|
||||
boolean disabled =
|
||||
System.getProperty("jdk.system.module.finder.disabledFastPath") != null;
|
||||
|
||||
private static HashSupplier hashSupplier(int index, String name) {
|
||||
if (isFastPathSupported()) {
|
||||
return new HashSupplier() {
|
||||
@Override
|
||||
public byte[] generate(String algorithm) {
|
||||
return SystemModules.MODULES_TO_HASH[index];
|
||||
}
|
||||
};
|
||||
ModuleDescriptor[] descriptors;
|
||||
ModuleHashes[] recordedHashes;
|
||||
ModuleResolution[] moduleResolutions;
|
||||
|
||||
// fast loading of ModuleDescriptor of system modules
|
||||
if (isFastPathSupported() && !disabled) {
|
||||
descriptors = SystemModules.descriptors();
|
||||
recordedHashes = SystemModules.hashes();
|
||||
moduleResolutions = SystemModules.moduleResolutions();
|
||||
} else {
|
||||
return Hashes.hashFor(name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This helper class is only used when SystemModules is patched.
|
||||
* It will get the recorded hashes from module-info.class.
|
||||
*/
|
||||
private static class Hashes {
|
||||
static Map<String, byte[]> hashes = new HashMap<>();
|
||||
|
||||
static void add(ModuleDescriptor descriptor) {
|
||||
Optional<ModuleHashes> ohashes = descriptor.hashes();
|
||||
if (ohashes.isPresent()) {
|
||||
hashes.putAll(ohashes.get().hashes());
|
||||
// if fast loading of ModuleDescriptors is disabled
|
||||
// fallback to read module-info.class
|
||||
descriptors = new ModuleDescriptor[n];
|
||||
recordedHashes = new ModuleHashes[n];
|
||||
moduleResolutions = new ModuleResolution[n];
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
String mn = names[i];
|
||||
ImageLocation loc = imageReader.findLocation(mn, "module-info.class");
|
||||
ModuleInfo.Attributes attrs =
|
||||
ModuleInfo.read(imageReader.getResourceBuffer(loc), null);
|
||||
descriptors[i] = attrs.descriptor();
|
||||
recordedHashes[i] = attrs.recordedHashes();
|
||||
moduleResolutions[i] = attrs.moduleResolution();
|
||||
}
|
||||
}
|
||||
|
||||
static HashSupplier hashFor(String name) {
|
||||
if (!hashes.containsKey(name))
|
||||
return null;
|
||||
|
||||
return new HashSupplier() {
|
||||
@Override
|
||||
public byte[] generate(String algorithm) {
|
||||
return hashes.get(name);
|
||||
Map<String, byte[]> hashes = null;
|
||||
boolean secondSeen = false;
|
||||
// record the hashes to build HashSupplier
|
||||
for (ModuleHashes mh : recordedHashes) {
|
||||
if (mh != null) {
|
||||
// if only one module contain ModuleHashes, use it
|
||||
if (hashes == null) {
|
||||
hashes = mh.hashes();
|
||||
} else {
|
||||
if (!secondSeen) {
|
||||
hashes = new HashMap<>(hashes);
|
||||
secondSeen = true;
|
||||
}
|
||||
hashes.putAll(mh.hashes());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
this.hashes = (hashes == null) ? Map.of() : hashes;
|
||||
|
||||
SystemModuleFinder() { }
|
||||
ModuleReference[] mods = new ModuleReference[n];
|
||||
|
||||
@SuppressWarnings(value = {"rawtypes", "unchecked"})
|
||||
Entry<String, ModuleReference>[] map
|
||||
= (Entry<String, ModuleReference>[])new Entry[n];
|
||||
|
||||
for (int i = 0; i < n; i++) {
|
||||
ModuleDescriptor md = descriptors[i];
|
||||
|
||||
// create the ModuleReference
|
||||
ModuleReference mref = toModuleReference(md,
|
||||
recordedHashes[i],
|
||||
hashSupplier(names[i]),
|
||||
moduleResolutions[i]);
|
||||
mods[i] = mref;
|
||||
map[i] = Map.entry(names[i], mref);
|
||||
|
||||
// counters
|
||||
packageCount.add(md.packages().size());
|
||||
exportsCount.add(md.exports().size());
|
||||
}
|
||||
|
||||
modules = Set.of(mods);
|
||||
nameToModule = Map.ofEntries(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModuleReference> find(String name) {
|
||||
@ -253,6 +218,41 @@ class SystemModuleFinder implements ModuleFinder {
|
||||
return modules;
|
||||
}
|
||||
|
||||
private ModuleReference toModuleReference(ModuleDescriptor md,
|
||||
ModuleHashes recordedHashes,
|
||||
HashSupplier hasher,
|
||||
ModuleResolution mres) {
|
||||
String mn = md.name();
|
||||
URI uri = JNUA.create("jrt", "/".concat(mn));
|
||||
|
||||
Supplier<ModuleReader> readerSupplier = new Supplier<>() {
|
||||
@Override
|
||||
public ModuleReader get() {
|
||||
return new ImageModuleReader(mn, uri);
|
||||
}
|
||||
};
|
||||
|
||||
ModuleReference mref =
|
||||
new ModuleReferenceImpl(md, uri, readerSupplier, null,
|
||||
recordedHashes, hasher, mres);
|
||||
|
||||
// may need a reference to a patched module if --patch-module specified
|
||||
mref = ModuleBootstrap.patcher().patchIfNeeded(mref);
|
||||
|
||||
return mref;
|
||||
}
|
||||
|
||||
private HashSupplier hashSupplier(String name) {
|
||||
if (!hashes.containsKey(name))
|
||||
return null;
|
||||
|
||||
return new HashSupplier() {
|
||||
@Override
|
||||
public byte[] generate(String algorithm) {
|
||||
return hashes.get(name);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A ModuleReader for reading resources from a module linked into the
|
@ -29,14 +29,14 @@ import java.lang.module.ModuleDescriptor;
|
||||
|
||||
/*
|
||||
* SystemModules class will be generated at link time to create
|
||||
* ModuleDescriptor for the installed modules directly to improve
|
||||
* ModuleDescriptor for the system modules directly to improve
|
||||
* the module descriptor reconstitution time.
|
||||
*
|
||||
* This will skip parsing of module-info.class file and validating
|
||||
* names such as module name, package name, service and provider type names.
|
||||
* It also avoids taking a defensive copy of any collection.
|
||||
*
|
||||
* @see jdk.tools.jlink.internal.plugins.SystemModuleDescriptorPlugin
|
||||
* @see jdk.tools.jlink.internal.plugins.SystemModulesPlugin
|
||||
*/
|
||||
public final class SystemModules {
|
||||
/**
|
||||
@ -48,11 +48,6 @@ public final class SystemModules {
|
||||
*/
|
||||
public static final String[] MODULE_NAMES = new String[0];
|
||||
|
||||
/**
|
||||
* Hash of system modules.
|
||||
*/
|
||||
public static byte[][] MODULES_TO_HASH = new byte[0][];
|
||||
|
||||
/**
|
||||
* Number of packages in the boot layer from the installed modules.
|
||||
*
|
||||
@ -66,8 +61,24 @@ public final class SystemModules {
|
||||
*
|
||||
* When running an exploded image it returns an empty array.
|
||||
*/
|
||||
public static ModuleDescriptor[] modules() {
|
||||
throw new InternalError("should not reach here");
|
||||
public static ModuleDescriptor[] descriptors() {
|
||||
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.
|
||||
*
|
||||
* When running an exploded image it returns an empty array.
|
||||
*/
|
||||
public static ModuleHashes[] hashes() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a non-empty array of ModuleResolutions in the run-time image.
|
||||
*/
|
||||
public static ModuleResolution[] moduleResolutions() {
|
||||
throw new InternalError("expected to be overridden at link time");
|
||||
}
|
||||
}
|
||||
|
@ -2490,6 +2490,40 @@ public class ClassReader {
|
||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a CONSTANT_Module_info item in {@code b}. This method is intended
|
||||
* for {@link Attribute} sub classes, and is normally not needed by class
|
||||
* generators or adapters.</i>
|
||||
*
|
||||
* @param index
|
||||
* the start index of an unsigned short value in {@link #b b},
|
||||
* whose value is the index of a module constant pool item.
|
||||
* @param buf
|
||||
* buffer to be used to read the item. This buffer must be
|
||||
* sufficiently large. It is not automatically resized.
|
||||
* @return the String corresponding to the specified module item.
|
||||
*/
|
||||
public String readModule(int index, char[] buf) {
|
||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a CONSTANT_Pakcage_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>
|
||||
*
|
||||
* @param index
|
||||
* the start index of an unsigned short value in {@link #b b},
|
||||
* whose value is the index of a package constant pool item.
|
||||
* @param buf
|
||||
* buffer to be used to read the item. This buffer must be
|
||||
* sufficiently large. It is not automatically resized.
|
||||
* @return the String corresponding to the specified package item.
|
||||
*/
|
||||
public String readPackage(int index, char[] buf) {
|
||||
return readUTF8(items[readUnsignedShort(index)], buf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a numeric or string constant pool item in {@link #b b}. <i>This
|
||||
* method is intended for {@link Attribute} sub classes, and is normally not
|
||||
@ -2516,6 +2550,8 @@ public class ClassReader {
|
||||
case ClassWriter.DOUBLE:
|
||||
return Double.longBitsToDouble(readLong(index));
|
||||
case ClassWriter.CLASS:
|
||||
case ClassWriter.MODULE:
|
||||
case ClassWriter.PACKAGE:
|
||||
return Type.getObjectType(readUTF8(index, buf));
|
||||
case ClassWriter.STR:
|
||||
return readUTF8(index, buf);
|
||||
|
@ -271,6 +271,16 @@ public class ClassWriter extends ClassVisitor {
|
||||
*/
|
||||
static final int INDY = 18;
|
||||
|
||||
/**
|
||||
* The type of CONSTANT_Module constant pool items.
|
||||
*/
|
||||
static final int MODULE = 19;
|
||||
|
||||
/**
|
||||
* The type of CONSTANT_Package constant pool items.
|
||||
*/
|
||||
static final int PACKAGE = 20;
|
||||
|
||||
/**
|
||||
* The base value for all CONSTANT_MethodHandle constant pool items.
|
||||
* Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
|
||||
@ -1160,6 +1170,50 @@ public class ClassWriter extends ClassVisitor {
|
||||
return newClassItem(value).index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a module name to the constant pool.
|
||||
*
|
||||
* Does nothing if the constant pool already contains a similar item.
|
||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||
* normally not needed by class generators or adapters.</i>
|
||||
*
|
||||
* @param value
|
||||
* the module name
|
||||
* @return the index of a new or already existing module reference item.
|
||||
*/
|
||||
public int newModule(String value) {
|
||||
key2.set(MODULE, value, null, null);
|
||||
Item result = get(key2);
|
||||
if (result == null) {
|
||||
pool.put12(MODULE, newUTF8(value));
|
||||
result = new Item(index++, key2);
|
||||
put(result);
|
||||
}
|
||||
return result.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a package name to the constant pool.
|
||||
*
|
||||
* Does nothing if the constant pool already contains a similar item.
|
||||
* <i>This method is intended for {@link Attribute} sub classes, and is
|
||||
* normally not needed by class generators or adapters.</i>
|
||||
*
|
||||
* @param value
|
||||
* the internal name of the package.
|
||||
* @return the index of a new or already existing package reference item.
|
||||
*/
|
||||
public int newPackage(String value) {
|
||||
key2.set(PACKAGE, value, null, null);
|
||||
Item result = get(key2);
|
||||
if (result == null) {
|
||||
pool.put12(PACKAGE, newUTF8(value));
|
||||
result = new Item(index++, key2);
|
||||
put(result);
|
||||
}
|
||||
return result.index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a method type reference to the constant pool of the class being
|
||||
* build. Does nothing if the constant pool already contains a similar item.
|
||||
|
@ -239,6 +239,8 @@ final class Item {
|
||||
this.strVal3 = strVal3;
|
||||
switch (type) {
|
||||
case ClassWriter.CLASS:
|
||||
case ClassWriter.MODULE:
|
||||
case ClassWriter.PACKAGE:
|
||||
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
|
||||
case ClassWriter.UTF8:
|
||||
case ClassWriter.STR:
|
||||
@ -311,6 +313,8 @@ final class Item {
|
||||
case ClassWriter.UTF8:
|
||||
case ClassWriter.STR:
|
||||
case ClassWriter.CLASS:
|
||||
case ClassWriter.MODULE:
|
||||
case ClassWriter.PACKAGE:
|
||||
case ClassWriter.MTYPE:
|
||||
case ClassWriter.TYPE_NORMAL:
|
||||
return i.strVal1.equals(strVal1);
|
||||
|
@ -58,7 +58,6 @@ import java.security.PrivilegedAction;
|
||||
|
||||
public class Cleaner
|
||||
extends PhantomReference<Object>
|
||||
implements Runnable
|
||||
{
|
||||
|
||||
// Dummy reference queue, needed because the PhantomReference constructor
|
||||
@ -153,12 +152,4 @@ public class Cleaner
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void run() {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null)
|
||||
security.checkPackageAccess("jdk.internal.ref");
|
||||
this.clean();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,6 +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;
|
||||
|
||||
@ -218,8 +219,16 @@ public class Reflection {
|
||||
if (c.isPrimitive())
|
||||
return true;
|
||||
|
||||
// check that memberModule exports the package to currentModule
|
||||
return memberModule.isExported(c.getPackageName(), currentModule);
|
||||
String pkg = c.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);
|
||||
}
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -348,25 +357,43 @@ public class Reflection {
|
||||
}
|
||||
|
||||
|
||||
// true to print a stack trace when IAE is thrown
|
||||
// true to print a stack trace when access fails
|
||||
private static volatile boolean printStackWhenAccessFails;
|
||||
|
||||
// true if printStackWhenAccessFails has been initialized
|
||||
private static volatile boolean printStackWhenAccessFailsSet;
|
||||
// true to print a stack trace when access succeeds
|
||||
private static volatile boolean printStackWhenAccessSucceeds;
|
||||
|
||||
private static void printStackTraceIfNeeded(Throwable e) {
|
||||
if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) {
|
||||
// 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");
|
||||
printStackWhenAccessFails =
|
||||
(s != null && !s.equalsIgnoreCase("false"));
|
||||
printStackWhenAccessFailsSet = true;
|
||||
}
|
||||
if (printStackWhenAccessFails) {
|
||||
e.printStackTrace();
|
||||
if (s != null) {
|
||||
printStackWhenAccessFails = !s.equalsIgnoreCase("false");
|
||||
printStackWhenAccessSucceeds = s.equalsIgnoreCase("access");
|
||||
}
|
||||
printStackPropertiesSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableStackTraces() {
|
||||
printStackWhenAccessFails = true;
|
||||
printStackWhenAccessSucceeds = true;
|
||||
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
|
||||
* the access that is denied.
|
||||
@ -416,17 +443,10 @@ public class Reflection {
|
||||
throws IllegalAccessException
|
||||
{
|
||||
IllegalAccessException e = new IllegalAccessException(msg);
|
||||
printStackTraceIfNeeded(e);
|
||||
ensurePrintStackPropertiesSet();
|
||||
if (printStackWhenAccessFails) {
|
||||
e.printStackTrace(System.err);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws InaccessibleObjectException with the given exception message.
|
||||
*/
|
||||
public static void throwInaccessibleObjectException(String msg) {
|
||||
InaccessibleObjectException e = new InaccessibleObjectException(msg);
|
||||
printStackTraceIfNeeded(e);
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -180,7 +180,8 @@ module java.base {
|
||||
java.management,
|
||||
jdk.jvmstat;
|
||||
exports jdk.internal.ref to
|
||||
java.desktop;
|
||||
java.desktop,
|
||||
jdk.unsupported;
|
||||
exports jdk.internal.reflect to
|
||||
java.corba,
|
||||
java.logging,
|
||||
@ -219,7 +220,8 @@ module java.base {
|
||||
exports sun.nio.ch to
|
||||
java.management,
|
||||
jdk.crypto.token,
|
||||
jdk.sctp;
|
||||
jdk.sctp,
|
||||
jdk.unsupported;
|
||||
exports sun.nio.cs to
|
||||
java.desktop,
|
||||
jdk.charsets;
|
||||
|
@ -36,6 +36,7 @@ import java.security.AlgorithmConstraints;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.*;
|
||||
import javax.crypto.spec.*;
|
||||
@ -122,6 +123,14 @@ abstract class Handshaker {
|
||||
// Negotiated ALPN value
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Application protocol callback function (for SSLEngine)
|
||||
BiFunction<SSLEngine,List<String>,String>
|
||||
appProtocolSelectorSSLEngine = null;
|
||||
|
||||
// Application protocol callback function (for SSLSocket)
|
||||
BiFunction<SSLSocket,List<String>,String>
|
||||
appProtocolSelectorSSLSocket = null;
|
||||
|
||||
// The maximum expected network packet size for SSL/TLS/DTLS records.
|
||||
int maximumPacketSize = 0;
|
||||
|
||||
@ -500,6 +509,22 @@ abstract class Handshaker {
|
||||
return applicationProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Application Protocol selector function for SSLEngine.
|
||||
*/
|
||||
void setApplicationProtocolSelectorSSLEngine(
|
||||
BiFunction<SSLEngine,List<String>,String> selector) {
|
||||
this.appProtocolSelectorSSLEngine = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Application Protocol selector function for SSLSocket.
|
||||
*/
|
||||
void setApplicationProtocolSelectorSSLSocket(
|
||||
BiFunction<SSLSocket,List<String>,String> selector) {
|
||||
this.appProtocolSelectorSSLSocket = selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cipher suites preference.
|
||||
*/
|
||||
|
@ -27,8 +27,9 @@ package sun.security.ssl;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
|
||||
@ -206,6 +207,10 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
// The value under negotiation will be obtained from handshaker.
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Callback function that selects the application protocol value during
|
||||
// the SSL/TLS handshake.
|
||||
BiFunction<SSLEngine, List<String>, String> applicationProtocolSelector;
|
||||
|
||||
// Have we been told whether we're client or server?
|
||||
private boolean serverModeSet = false;
|
||||
private boolean roleIsServer;
|
||||
@ -442,6 +447,8 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
handshaker.setApplicationProtocols(applicationProtocols);
|
||||
handshaker.setApplicationProtocolSelectorSSLEngine(
|
||||
applicationProtocolSelector);
|
||||
|
||||
outputRecord.initHandshaker();
|
||||
}
|
||||
@ -2264,6 +2271,21 @@ public final class SSLEngineImpl extends SSLEngine {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLEngine, List<String>, String> selector) {
|
||||
applicationProtocolSelector = selector;
|
||||
if ((handshaker != null) && !handshaker.activated()) {
|
||||
handshaker.setApplicationProtocolSelectorSSLEngine(selector);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized BiFunction<SSLEngine, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
return this.applicationProtocolSelector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a printable representation of this end of the connection.
|
||||
*/
|
||||
|
@ -37,6 +37,7 @@ import java.security.AlgorithmConstraints;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.net.ssl.*;
|
||||
@ -223,6 +224,10 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
// The value under negotiation will be obtained from handshaker.
|
||||
String applicationProtocol = null;
|
||||
|
||||
// Callback function that selects the application protocol value during
|
||||
// the SSL/TLS handshake.
|
||||
BiFunction<SSLSocket, List<String>, String> applicationProtocolSelector;
|
||||
|
||||
/*
|
||||
* READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
|
||||
* IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
|
||||
@ -1370,6 +1375,8 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
handshaker.setEnabledCipherSuites(enabledCipherSuites);
|
||||
handshaker.setEnableSessionCreation(enableSessionCreation);
|
||||
handshaker.setApplicationProtocols(applicationProtocols);
|
||||
handshaker.setApplicationProtocolSelectorSSLSocket(
|
||||
applicationProtocolSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2658,6 +2665,21 @@ public final class SSLSocketImpl extends BaseSSLSocketImpl {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void setHandshakeApplicationProtocolSelector(
|
||||
BiFunction<SSLSocket, List<String>, String> selector) {
|
||||
applicationProtocolSelector = selector;
|
||||
if ((handshaker != null) && !handshaker.activated()) {
|
||||
handshaker.setApplicationProtocolSelectorSSLSocket(selector);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized BiFunction<SSLSocket, List<String>, String>
|
||||
getHandshakeApplicationProtocolSelector() {
|
||||
return this.applicationProtocolSelector;
|
||||
}
|
||||
|
||||
//
|
||||
// We allocate a separate thread to deliver handshake completion
|
||||
// events. This ensures that the notifications don't block the
|
||||
|
@ -34,6 +34,7 @@ import java.security.cert.*;
|
||||
import java.security.interfaces.*;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.math.BigInteger;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.net.ssl.*;
|
||||
@ -532,31 +533,39 @@ final class ServerHandshaker extends Handshaker {
|
||||
ALPNExtension clientHelloALPN = (ALPNExtension)
|
||||
mesg.extensions.get(ExtensionType.EXT_ALPN);
|
||||
|
||||
if ((clientHelloALPN != null) && (localApl.length > 0)) {
|
||||
// Use the application protocol callback when provided.
|
||||
// Otherwise use the local list of application protocols.
|
||||
boolean hasAPCallback =
|
||||
((engine != null && appProtocolSelectorSSLEngine != null) ||
|
||||
(conn != null && appProtocolSelectorSSLSocket != null));
|
||||
|
||||
// Intersect the requested and the locally supported,
|
||||
// and save for later.
|
||||
String negotiatedValue = null;
|
||||
List<String> protocols = clientHelloALPN.getPeerAPs();
|
||||
if (!hasAPCallback) {
|
||||
if ((clientHelloALPN != null) && (localApl.length > 0)) {
|
||||
|
||||
// Use server preference order
|
||||
for (String ap : localApl) {
|
||||
if (protocols.contains(ap)) {
|
||||
negotiatedValue = ap;
|
||||
break;
|
||||
// Intersect the requested and the locally supported,
|
||||
// and save for later.
|
||||
String negotiatedValue = null;
|
||||
List<String> protocols = clientHelloALPN.getPeerAPs();
|
||||
|
||||
// Use server preference order
|
||||
for (String ap : localApl) {
|
||||
if (protocols.contains(ap)) {
|
||||
negotiatedValue = ap;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (negotiatedValue == null) {
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
}
|
||||
applicationProtocol = negotiatedValue;
|
||||
if (negotiatedValue == null) {
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
}
|
||||
applicationProtocol = negotiatedValue;
|
||||
|
||||
} else {
|
||||
applicationProtocol = "";
|
||||
}
|
||||
} else {
|
||||
applicationProtocol = "";
|
||||
}
|
||||
} // Otherwise, applicationProtocol will be set by the callback.
|
||||
|
||||
session = null; // forget about the current session
|
||||
//
|
||||
@ -892,8 +901,36 @@ final class ServerHandshaker extends Handshaker {
|
||||
}
|
||||
|
||||
// Prepare the ALPN response
|
||||
if (applicationProtocol != null && !applicationProtocol.isEmpty()) {
|
||||
m1.extensions.add(new ALPNExtension(applicationProtocol));
|
||||
if (clientHelloALPN != null) {
|
||||
List<String> peerAPs = clientHelloALPN.getPeerAPs();
|
||||
|
||||
// check for a callback function
|
||||
if (hasAPCallback) {
|
||||
if (conn != null) {
|
||||
applicationProtocol =
|
||||
appProtocolSelectorSSLSocket.apply(conn, peerAPs);
|
||||
} else {
|
||||
applicationProtocol =
|
||||
appProtocolSelectorSSLEngine.apply(engine, peerAPs);
|
||||
}
|
||||
}
|
||||
|
||||
// check for no-match and that the selected name was also proposed
|
||||
// by the TLS peer
|
||||
if (applicationProtocol == null ||
|
||||
(!applicationProtocol.isEmpty() &&
|
||||
!peerAPs.contains(applicationProtocol))) {
|
||||
|
||||
fatalSE(Alerts.alert_no_application_protocol,
|
||||
new SSLHandshakeException(
|
||||
"No matching ALPN values"));
|
||||
|
||||
} else if (!applicationProtocol.isEmpty()) {
|
||||
m1.extensions.add(new ALPNExtension(applicationProtocol));
|
||||
}
|
||||
} else {
|
||||
// Nothing was negotiated, returned at end of the handshake
|
||||
applicationProtocol = "";
|
||||
}
|
||||
|
||||
if (debug != null && Debug.isOn("handshake")) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -64,12 +64,6 @@ Java_java_lang_StrictMath_atan(JNIEnv *env, jclass unused, jdouble d)
|
||||
return (jdouble) jatan((double)d);
|
||||
}
|
||||
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_java_lang_StrictMath_exp(JNIEnv *env, jclass unused, jdouble d)
|
||||
{
|
||||
return (jdouble) jexp((double)d);
|
||||
}
|
||||
|
||||
JNIEXPORT jdouble JNICALL
|
||||
Java_java_lang_StrictMath_log(JNIEnv *env, jclass unused, jdouble d)
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -109,13 +109,9 @@ final class ProcessImpl extends Process {
|
||||
private String helperPath(String javahome, String osArch) {
|
||||
switch (this) {
|
||||
case SOLARIS:
|
||||
if (osArch.equals("x86")) { osArch = "i386"; }
|
||||
else if (osArch.equals("x86_64")) { osArch = "amd64"; }
|
||||
// fall through...
|
||||
case LINUX:
|
||||
case AIX:
|
||||
return javahome + "/lib/" + osArch + "/jspawnhelper";
|
||||
|
||||
case BSD:
|
||||
return javahome + "/lib/jspawnhelper";
|
||||
|
||||
|
36
jdk/src/java.base/unix/classes/module-info.java.extra
Normal file
36
jdk/src/java.base/unix/classes/module-info.java.extra
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. 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.
|
||||
*/
|
||||
|
||||
// jdk.vm.compiler uses Unsafe and VM classes from jdk.internal.misc
|
||||
exports jdk.internal.misc to jdk.vm.compiler;
|
||||
opens jdk.internal.misc to jdk.vm.compiler;
|
||||
|
||||
// jdk.vm.compiler uses com.sun.crypto.provider to generate crypto intrinsics
|
||||
opens com.sun.crypto.provider to jdk.vm.compiler;
|
||||
|
||||
exports jdk.internal.module to jdk.vm.compiler;
|
||||
|
||||
// AOT uses jdk.internal.misc.Unsafe
|
||||
exports jdk.internal.misc to jdk.aot;
|
@ -54,10 +54,8 @@ char *FindExecName(char *program);
|
||||
const char *SetExecname(char **argv);
|
||||
const char *GetExecName();
|
||||
static jboolean GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
char *jvmpath, jint jvmpathsize, const char * arch,
|
||||
int bitsWanted);
|
||||
static jboolean GetJREPath(char *path, jint pathsize, const char * arch,
|
||||
jboolean speculative);
|
||||
char *jvmpath, jint jvmpathsize, int bitsWanted);
|
||||
static jboolean GetJREPath(char *path, jint pathsize, jboolean speculative);
|
||||
|
||||
#if defined(_AIX)
|
||||
#include "java_md_aix.h"
|
||||
|
@ -52,9 +52,6 @@
|
||||
#endif
|
||||
|
||||
#ifdef __solaris__
|
||||
# ifndef LIBARCHNAME
|
||||
# error "The macro LIBARCHNAME was not defined on the compile line"
|
||||
# endif
|
||||
# include <sys/systeminfo.h>
|
||||
# include <sys/elf.h>
|
||||
# include <stdio.h>
|
||||
@ -188,12 +185,13 @@ JvmExists(const char *path) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/*
|
||||
* contains a lib/$LIBARCHNAME/{server,client}/libjvm.so ?
|
||||
* contains a lib/{server,client}/libjvm.so ?
|
||||
*/
|
||||
static jboolean
|
||||
ContainsLibJVM(const char *env) {
|
||||
char clientPattern[PATH_MAX + 1];
|
||||
char serverPattern[PATH_MAX + 1];
|
||||
/* the usual suspects */
|
||||
char clientPattern[] = "lib/client";
|
||||
char serverPattern[] = "lib/server";
|
||||
char *envpath;
|
||||
char *path;
|
||||
jboolean clientPatternFound;
|
||||
@ -204,10 +202,6 @@ ContainsLibJVM(const char *env) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/* the usual suspects */
|
||||
JLI_Snprintf(clientPattern, PATH_MAX, "lib/%s/client", LIBARCHNAME);
|
||||
JLI_Snprintf(serverPattern, PATH_MAX, "lib/%s/server", LIBARCHNAME);
|
||||
|
||||
/* to optimize for time, test if any of our usual suspects are present. */
|
||||
clientPatternFound = JLI_StrStr(env, clientPattern) != NULL;
|
||||
serverPatternFound = JLI_StrStr(env, serverPattern) != NULL;
|
||||
@ -322,7 +316,6 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
|
||||
/* Check data model flags, and exec process, if needed */
|
||||
{
|
||||
char *arch = LIBARCHNAME; /* like sparc or sparcv9 */
|
||||
char * jvmtype = NULL;
|
||||
int argc = *pargc;
|
||||
char **argv = *pargv;
|
||||
@ -408,12 +401,12 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
jvmpath does not exist */
|
||||
if (wanted == running) {
|
||||
/* Find out where the JRE is that we will be using. */
|
||||
if (!GetJREPath(jrepath, so_jrepath, arch, JNI_FALSE) ) {
|
||||
if (!GetJREPath(jrepath, so_jrepath, JNI_FALSE) ) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR1);
|
||||
exit(2);
|
||||
}
|
||||
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg",
|
||||
jrepath, FILESEP, FILESEP, arch, FILESEP);
|
||||
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%sjvm.cfg",
|
||||
jrepath, FILESEP, FILESEP, FILESEP);
|
||||
/* Find the specified JVM type */
|
||||
if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) {
|
||||
JLI_ReportErrorMessage(CFG_ERROR7);
|
||||
@ -427,7 +420,7 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
exit(4);
|
||||
}
|
||||
|
||||
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch, 0 )) {
|
||||
if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, 0 )) {
|
||||
JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath);
|
||||
exit(4);
|
||||
}
|
||||
@ -457,8 +450,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
* We will set the LD_LIBRARY_PATH as follows:
|
||||
*
|
||||
* o $JVMPATH (directory portion only)
|
||||
* o $JRE/lib/$LIBARCHNAME
|
||||
* o $JRE/../lib/$LIBARCHNAME
|
||||
* o $JRE/lib
|
||||
* o $JRE/../lib
|
||||
*
|
||||
* followed by the user's previous effective LD_LIBRARY_PATH, if
|
||||
* any.
|
||||
@ -518,10 +511,10 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
{ /* New scope to declare local variable */
|
||||
char *new_jvmpath = JLI_StringDup(jvmpath);
|
||||
new_runpath_size = ((runpath != NULL) ? JLI_StrLen(runpath) : 0) +
|
||||
2 * JLI_StrLen(jrepath) + 2 * JLI_StrLen(arch) +
|
||||
2 * JLI_StrLen(jrepath) +
|
||||
#ifdef AIX
|
||||
/* On AIX we additionally need 'jli' in the path because ld doesn't support $ORIGIN. */
|
||||
JLI_StrLen(jrepath) + JLI_StrLen(arch) + JLI_StrLen("/lib//jli:") +
|
||||
JLI_StrLen(jrepath) + JLI_StrLen("/lib//jli:") +
|
||||
#endif
|
||||
JLI_StrLen(new_jvmpath) + 52;
|
||||
new_runpath = JLI_MemAlloc(new_runpath_size);
|
||||
@ -539,17 +532,17 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
|
||||
sprintf(new_runpath, LD_LIBRARY_PATH "="
|
||||
"%s:"
|
||||
"%s/lib/%s:"
|
||||
"%s/lib:"
|
||||
#ifdef AIX
|
||||
"%s/lib/%s/jli:" /* Needed on AIX because ld doesn't support $ORIGIN. */
|
||||
"%s/lib/jli:" /* Needed on AIX because ld doesn't support $ORIGIN. */
|
||||
#endif
|
||||
"%s/../lib/%s",
|
||||
"%s/../lib",
|
||||
new_jvmpath,
|
||||
jrepath, arch,
|
||||
jrepath,
|
||||
#ifdef AIX
|
||||
jrepath, arch,
|
||||
jrepath,
|
||||
#endif
|
||||
jrepath, arch
|
||||
jrepath
|
||||
);
|
||||
|
||||
JLI_MemFree(new_jvmpath);
|
||||
@ -640,14 +633,14 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
*/
|
||||
static jboolean
|
||||
GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
char *jvmpath, jint jvmpathsize, const char * arch, int bitsWanted)
|
||||
char *jvmpath, jint jvmpathsize, int bitsWanted)
|
||||
{
|
||||
struct stat s;
|
||||
|
||||
if (JLI_StrChr(jvmtype, '/')) {
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype);
|
||||
} else {
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype);
|
||||
JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/" JVM_DLL, jrepath, jvmtype);
|
||||
}
|
||||
|
||||
JLI_TraceLauncher("Does `%s' exist ... ", jvmpath);
|
||||
@ -665,14 +658,14 @@ GetJVMPath(const char *jrepath, const char *jvmtype,
|
||||
* Find path to JRE based on .exe's location or registry settings.
|
||||
*/
|
||||
static jboolean
|
||||
GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
|
||||
GetJREPath(char *path, jint pathsize, jboolean speculative)
|
||||
{
|
||||
char libjava[MAXPATHLEN];
|
||||
struct stat s;
|
||||
|
||||
if (GetApplicationHome(path, pathsize)) {
|
||||
/* Is JRE co-located with the application? */
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
|
||||
if (access(libjava, F_OK) == 0) {
|
||||
JLI_TraceLauncher("JRE path is %s\n", path);
|
||||
return JNI_TRUE;
|
||||
@ -683,7 +676,7 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
|
||||
return JNI_FALSE;
|
||||
}
|
||||
/* Does the app ship a private JRE in <apphome>/jre directory? */
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch);
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/" JAVA_DLL, path);
|
||||
if (access(libjava, F_OK) == 0) {
|
||||
JLI_StrCat(path, "/jre");
|
||||
JLI_TraceLauncher("JRE path is %s\n", path);
|
||||
@ -692,7 +685,7 @@ GetJREPath(char *path, jint pathsize, const char * arch, jboolean speculative)
|
||||
}
|
||||
|
||||
if (GetApplicationHomeFromDll(path, pathsize)) {
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch);
|
||||
JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/" JAVA_DLL, path);
|
||||
if (stat(libjava, &s) == 0) {
|
||||
JLI_TraceLauncher("JRE path is %s\n", path);
|
||||
return JNI_TRUE;
|
||||
@ -858,12 +851,12 @@ void* SplashProcAddress(const char* name) {
|
||||
char jrePath[MAXPATHLEN];
|
||||
char splashPath[MAXPATHLEN];
|
||||
|
||||
if (!GetJREPath(jrePath, sizeof(jrePath), LIBARCHNAME, JNI_FALSE)) {
|
||||
if (!GetJREPath(jrePath, sizeof(jrePath), JNI_FALSE)) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR1);
|
||||
return NULL;
|
||||
}
|
||||
ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s/%s",
|
||||
jrePath, LIBARCHNAME, SPLASHSCREEN_SO);
|
||||
ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s",
|
||||
jrePath, SPLASHSCREEN_SO);
|
||||
|
||||
if (ret >= (int) sizeof(splashPath)) {
|
||||
JLI_ReportErrorMessage(JRE_ERROR11);
|
||||
|
@ -37,273 +37,10 @@
|
||||
|
||||
#include "java_net_Inet4AddressImpl.h"
|
||||
|
||||
#if defined(__GLIBC__) || (defined(__FreeBSD__) && (__FreeBSD_version >= 601104))
|
||||
#define HAS_GLIBC_GETHOSTBY_R 1
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R)
|
||||
#if defined(MACOSX)
|
||||
extern jobjectArray lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6);
|
||||
|
||||
/* Use getaddrinfo(3), which is thread safe */
|
||||
/************************************************************************
|
||||
* Inet4AddressImpl
|
||||
*/
|
||||
|
||||
/*
|
||||
* Class: java_net_Inet4AddressImpl
|
||||
* Method: getLocalHostName
|
||||
* Signature: ()Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_net_Inet4AddressImpl_getLocalHostName(JNIEnv *env, jobject this) {
|
||||
char hostname[NI_MAXHOST+1];
|
||||
|
||||
hostname[0] = '\0';
|
||||
if (gethostname(hostname, NI_MAXHOST)) {
|
||||
/* Something went wrong, maybe networking is not setup? */
|
||||
strcpy(hostname, "localhost");
|
||||
} else {
|
||||
struct addrinfo hints, *res;
|
||||
int error;
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
if (error == 0) {
|
||||
/* host is known to name service */
|
||||
error = getnameinfo(res->ai_addr,
|
||||
res->ai_addrlen,
|
||||
hostname,
|
||||
NI_MAXHOST,
|
||||
NULL,
|
||||
0,
|
||||
NI_NAMEREQD);
|
||||
|
||||
/* if getnameinfo fails hostname is still the value
|
||||
from gethostname */
|
||||
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
return (*env)->NewStringUTF(env, hostname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find an internet address for a given hostname. Note that this
|
||||
* code only works for addresses of type INET. The translation
|
||||
* of %d.%d.%d.%d to an address (int) occurs in java now, so the
|
||||
* String "host" shouldn't *ever* be a %d.%d.%d.%d string
|
||||
*
|
||||
* Class: java_net_Inet4AddressImpl
|
||||
* Method: lookupAllHostAddr
|
||||
* Signature: (Ljava/lang/String;)[[B
|
||||
*/
|
||||
|
||||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
jstring host) {
|
||||
const char *hostname;
|
||||
jobject name;
|
||||
jobjectArray ret = 0;
|
||||
int retLen = 0;
|
||||
|
||||
int getaddrinfo_error=0;
|
||||
struct addrinfo hints, *res, *resNew = NULL;
|
||||
|
||||
initInetAddressIDs(env);
|
||||
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
|
||||
|
||||
if (IS_NULL(host)) {
|
||||
JNU_ThrowNullPointerException(env, "host is null");
|
||||
return 0;
|
||||
}
|
||||
hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
|
||||
CHECK_NULL_RETURN(hostname, NULL);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
/*
|
||||
* Workaround for Solaris bug 4160367 - if a hostname contains a
|
||||
* white space then 0.0.0.0 is returned
|
||||
*/
|
||||
if (isspace((unsigned char)hostname[0])) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException",
|
||||
(char *)hostname);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
getaddrinfo_error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
#ifdef MACOSX
|
||||
if (getaddrinfo_error) {
|
||||
// If getaddrinfo fails try getifaddrs.
|
||||
ret = lookupIfLocalhost(env, hostname, JNI_FALSE);
|
||||
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getaddrinfo_error) {
|
||||
/* report error */
|
||||
NET_ThrowUnknownHostExceptionWithGaiError(
|
||||
env, hostname, getaddrinfo_error);
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return NULL;
|
||||
} else {
|
||||
int i = 0;
|
||||
struct addrinfo *itr, *last = NULL, *iterator = res;
|
||||
while (iterator != NULL) {
|
||||
int skip = 0;
|
||||
itr = resNew;
|
||||
|
||||
while (itr != NULL) {
|
||||
struct sockaddr_in *addr1, *addr2;
|
||||
|
||||
addr1 = (struct sockaddr_in *)iterator->ai_addr;
|
||||
addr2 = (struct sockaddr_in *)itr->ai_addr;
|
||||
if (addr1->sin_addr.s_addr ==
|
||||
addr2->sin_addr.s_addr) {
|
||||
skip = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
itr = itr->ai_next;
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
struct addrinfo *next
|
||||
= (struct addrinfo*) malloc(sizeof(struct addrinfo));
|
||||
if (!next) {
|
||||
JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
memcpy(next, iterator, sizeof(struct addrinfo));
|
||||
next->ai_next = NULL;
|
||||
if (resNew == NULL) {
|
||||
resNew = next;
|
||||
} else {
|
||||
last->ai_next = next;
|
||||
}
|
||||
last = next;
|
||||
i++;
|
||||
}
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
|
||||
retLen = i;
|
||||
iterator = resNew;
|
||||
i = 0;
|
||||
|
||||
name = (*env)->NewStringUTF(env, hostname);
|
||||
if (IS_NULL(name)) {
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
|
||||
ret = (*env)->NewObjectArray(env, retLen, ia_class, NULL);
|
||||
if (IS_NULL(ret)) {
|
||||
/* we may have memory to free at the end of this */
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
|
||||
while (iterator != NULL) {
|
||||
/* We need 4 bytes to store ipv4 address; */
|
||||
int len = 4;
|
||||
|
||||
jobject iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
|
||||
if (IS_NULL(iaObj)) {
|
||||
/* we may have memory to free at the end of this */
|
||||
ret = NULL;
|
||||
goto cleanupAndReturn;
|
||||
}
|
||||
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)(iterator->ai_addr))->sin_addr.s_addr));
|
||||
setInetAddress_hostName(env, iaObj, name);
|
||||
(*env)->SetObjectArrayElement(env, ret, retLen - i -1, iaObj);
|
||||
i++;
|
||||
iterator = iterator->ai_next;
|
||||
}
|
||||
}
|
||||
|
||||
cleanupAndReturn:
|
||||
{
|
||||
struct addrinfo *iterator, *tmp;
|
||||
iterator = resNew;
|
||||
while (iterator != NULL) {
|
||||
tmp = iterator;
|
||||
iterator = iterator->ai_next;
|
||||
free(tmp);
|
||||
}
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
}
|
||||
|
||||
freeaddrinfo(res);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_Inet4AddressImpl
|
||||
* Method: getHostByAddr
|
||||
* Signature: (I)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
|
||||
jbyteArray addrArray) {
|
||||
jstring ret = NULL;
|
||||
|
||||
char host[NI_MAXHOST+1];
|
||||
jfieldID fid;
|
||||
int error = 0;
|
||||
jint family;
|
||||
struct sockaddr *him ;
|
||||
int len = 0;
|
||||
jbyte caddr[4];
|
||||
jint addr;
|
||||
|
||||
struct sockaddr_in him4;
|
||||
struct sockaddr *sa;
|
||||
|
||||
/*
|
||||
* For IPv4 addresses construct a sockaddr_in structure.
|
||||
*/
|
||||
(*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
|
||||
addr = ((caddr[0]<<24) & 0xff000000);
|
||||
addr |= ((caddr[1] <<16) & 0xff0000);
|
||||
addr |= ((caddr[2] <<8) & 0xff00);
|
||||
addr |= (caddr[3] & 0xff);
|
||||
memset((char *) &him4, 0, sizeof(him4));
|
||||
him4.sin_addr.s_addr = htonl(addr);
|
||||
him4.sin_family = AF_INET;
|
||||
sa = (struct sockaddr *) &him4;
|
||||
len = sizeof(him4);
|
||||
|
||||
error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
|
||||
|
||||
if (!error) {
|
||||
ret = (*env)->NewStringUTF(env, host);
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
#else /* defined(_ALLBSD_SOURCE) && !defined(HAS_GLIBC_GETHOSTBY_R) */
|
||||
|
||||
/* the initial size of our hostent buffers */
|
||||
#ifndef NI_MAXHOST
|
||||
#define NI_MAXHOST 1025
|
||||
@ -405,6 +142,17 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
|
||||
error = getaddrinfo(hostname, NULL, &hints, &res);
|
||||
|
||||
#ifdef MACOSX
|
||||
if (error) {
|
||||
// If getaddrinfo fails try getifaddrs, see bug 8170910.
|
||||
ret = lookupIfLocalhost(env, hostname, JNI_FALSE);
|
||||
if (ret != NULL || (*env)->ExceptionCheck(env)) {
|
||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (error) {
|
||||
/* report error */
|
||||
NET_ThrowUnknownHostExceptionWithGaiError(env, hostname, error);
|
||||
@ -475,7 +223,7 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||
}
|
||||
}
|
||||
|
||||
cleanupAndReturn:
|
||||
cleanupAndReturn:
|
||||
{
|
||||
struct addrinfo *iterator, *tmp;
|
||||
iterator = resNew;
|
||||
@ -535,8 +283,6 @@ Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* _ALLBSD_SOURCE */
|
||||
|
||||
#define SET_NONBLOCKING(fd) { \
|
||||
int flags = fcntl(fd, F_GETFL); \
|
||||
flags |= O_NONBLOCK; \
|
||||
|
@ -150,22 +150,6 @@ IsJavaw()
|
||||
return _isjavaw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the arch path, to get the current arch use the
|
||||
* macro GetArch, nbits here is ignored for now.
|
||||
*/
|
||||
const char *
|
||||
GetArchPath(int nbits)
|
||||
{
|
||||
#ifdef _M_AMD64
|
||||
return "amd64";
|
||||
#elif defined(_M_IA64)
|
||||
return "ia64";
|
||||
#else
|
||||
return "i386";
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
@ -207,8 +191,8 @@ CreateExecutionEnvironment(int *pargc, char ***pargv,
|
||||
exit(2);
|
||||
}
|
||||
|
||||
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%s%s%sjvm.cfg",
|
||||
jrepath, FILESEP, FILESEP, (char*)GetArch(), FILESEP);
|
||||
JLI_Snprintf(jvmcfg, so_jvmcfg, "%s%slib%sjvm.cfg",
|
||||
jrepath, FILESEP, FILESEP);
|
||||
|
||||
/* Find the specified JVM type */
|
||||
if (ReadKnownVMs(jvmcfg, JNI_FALSE) < 1) {
|
||||
|
@ -34,10 +34,18 @@ import javax.swing.plaf.basic.BasicMenuBarUI;
|
||||
|
||||
import sun.lwawt.macosx.LWCToolkit;
|
||||
import sun.security.action.GetBooleanAction;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
// MenuBar implementation for Mac L&F
|
||||
public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvider {
|
||||
|
||||
static {
|
||||
java.security.AccessController.doPrivileged(
|
||||
(java.security.PrivilegedAction<Void>) () -> {
|
||||
System.loadLibrary("osxui");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
// Utilities
|
||||
public void uninstallUI(final JComponent c) {
|
||||
if (fScreenMenuBar != null) {
|
||||
@ -134,7 +142,7 @@ public class AquaMenuBarUI extends BasicMenuBarUI implements ScreenMenuBarProvid
|
||||
ScreenMenuBar fScreenMenuBar;
|
||||
boolean useScreenMenuBar = getScreenMenuBarProperty();
|
||||
|
||||
static boolean getScreenMenuBarProperty() {
|
||||
public static boolean getScreenMenuBarProperty() {
|
||||
// Do not allow AWT to set the screen menu bar if it's embedded in another UI toolkit
|
||||
if (LWCToolkit.isEmbedded()) return false;
|
||||
if (AccessController.doPrivileged(
|
||||
|
@ -141,12 +141,24 @@ public final class CFontManager extends SunFontManager {
|
||||
}
|
||||
}
|
||||
|
||||
protected void registerFontsInDir(String dirName, boolean useJavaRasterizer, int fontRank, boolean defer, boolean resolveSymLinks) {
|
||||
loadNativeDirFonts(dirName);
|
||||
protected void registerFontsInDir(final String dirName, boolean useJavaRasterizer,
|
||||
int fontRank, boolean defer, boolean resolveSymLinks) {
|
||||
|
||||
String[] files = AccessController.doPrivileged((PrivilegedAction<String[]>) () -> {
|
||||
return new File(dirName).list(getTrueTypeFilter());
|
||||
});
|
||||
|
||||
if (files == null) {
|
||||
return;
|
||||
} else {
|
||||
for (String f : files) {
|
||||
loadNativeDirFonts(dirName+File.separator+f);
|
||||
}
|
||||
}
|
||||
super.registerFontsInDir(dirName, useJavaRasterizer, fontRank, defer, resolveSymLinks);
|
||||
}
|
||||
|
||||
private native void loadNativeDirFonts(String dirName);
|
||||
private native void loadNativeDirFonts(String fontPath);
|
||||
private native void loadNativeFonts();
|
||||
|
||||
void registerFont(String fontName, String fontFamilyName) {
|
||||
|
@ -33,11 +33,14 @@ import java.awt.Dialog.ModalityType;
|
||||
import java.awt.event.*;
|
||||
import java.beans.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import sun.awt.*;
|
||||
import sun.awt.AWTAccessor.ComponentAccessor;
|
||||
import sun.awt.AWTAccessor.WindowAccessor;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.opengl.CGLSurfaceData;
|
||||
import sun.lwawt.*;
|
||||
@ -1031,6 +1034,11 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return !peer.isSimpleWindow() && target.getFocusableWindowState();
|
||||
}
|
||||
|
||||
private boolean isBlocked() {
|
||||
LWWindowPeer blocker = (peer != null) ? peer.getBlocker() : null;
|
||||
return (blocker != null);
|
||||
}
|
||||
|
||||
/*
|
||||
* An utility method for the support of the auto request focus.
|
||||
* Updates the focusable state of the window under certain
|
||||
@ -1063,29 +1071,70 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
|
||||
while (window != null) {
|
||||
if (this == window) {
|
||||
return true;
|
||||
}
|
||||
window = window.owner;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private CPlatformWindow getRootOwner() {
|
||||
CPlatformWindow rootOwner = this;
|
||||
while (rootOwner.owner != null) {
|
||||
rootOwner = rootOwner.owner;
|
||||
}
|
||||
return rootOwner;
|
||||
}
|
||||
|
||||
private void orderAboveSiblings() {
|
||||
if (owner == null) {
|
||||
return;
|
||||
// Recursively pop up the windows from the very bottom, (i.e. root owner) so that
|
||||
// the windows are ordered above their nearest owner; ancestors of the window,
|
||||
// which is going to become 'main window', are placed above their siblings.
|
||||
CPlatformWindow rootOwner = getRootOwner();
|
||||
if (rootOwner.isVisible()) {
|
||||
CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
|
||||
}
|
||||
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
|
||||
orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
|
||||
}
|
||||
|
||||
// NOTE: the logic will fail if we have a hierarchy like:
|
||||
// visible root owner
|
||||
// invisible owner
|
||||
// visible dialog
|
||||
// However, this is an unlikely scenario for real life apps
|
||||
if (owner.isVisible()) {
|
||||
// Recursively pop up the windows from the very bottom so that only
|
||||
// the very top-most one becomes the main window
|
||||
owner.orderAboveSiblings();
|
||||
private void orderAboveSiblingsImpl(Window[] windows) {
|
||||
ArrayList<Window> childWindows = new ArrayList<Window>();
|
||||
|
||||
// Order the window to front of the stack of child windows
|
||||
final long nsWindowSelfPtr = getNSWindowPtr();
|
||||
final long nsWindowOwnerPtr = owner.getNSWindowPtr();
|
||||
CWrapper.NSWindow.orderFront(nsWindowOwnerPtr);
|
||||
CWrapper.NSWindow.orderWindow(nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove, nsWindowOwnerPtr);
|
||||
final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor();
|
||||
final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
|
||||
|
||||
// Go through the list of windows and perform ordering.
|
||||
for (Window w : windows) {
|
||||
final Object p = componentAccessor.getPeer(w);
|
||||
if (p instanceof LWWindowPeer) {
|
||||
CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
|
||||
if (pw != null && pw.isVisible()) {
|
||||
// If the window is one of ancestors of 'main window' or is going to become main by itself,
|
||||
// the window should be ordered above its siblings; otherwise the window is just ordered
|
||||
// above its nearest parent.
|
||||
if (pw.isOneOfOwnersOrSelf(this)) {
|
||||
CWrapper.NSWindow.orderFront(pw.getNSWindowPtr());
|
||||
} else {
|
||||
CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove,
|
||||
pw.owner.getNSWindowPtr());
|
||||
}
|
||||
pw.applyWindowLevel(w);
|
||||
}
|
||||
}
|
||||
// Retrieve the child windows for each window from the list and store them for future use.
|
||||
// Note: we collect data about child windows even for invisible owners, since they may have
|
||||
// visible children.
|
||||
childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
|
||||
}
|
||||
// If some windows, which have just been ordered, have any child windows, let's start new iteration
|
||||
// and order these child windows.
|
||||
if (!childWindows.isEmpty()) {
|
||||
orderAboveSiblingsImpl(childWindows.toArray(new Window[0]));
|
||||
}
|
||||
|
||||
applyWindowLevel(target);
|
||||
}
|
||||
|
||||
protected void applyWindowLevel(Window target) {
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import com.apple.laf.AquaMenuBarUI;
|
||||
import java.awt.peer.TaskbarPeer;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.Clipboard;
|
||||
@ -43,6 +44,7 @@ import java.security.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.net.MalformedURLException;
|
||||
import javax.swing.UIManager;
|
||||
|
||||
import sun.awt.*;
|
||||
import sun.awt.datatransfer.DataTransferer;
|
||||
@ -935,4 +937,13 @@ public final class LWCToolkit extends LWToolkit {
|
||||
protected PlatformWindow getPlatformWindowUnderMouse() {
|
||||
return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreenMenuBarUI() {
|
||||
if (AquaMenuBarUI.getScreenMenuBarProperty()) {
|
||||
UIManager.put("MenuBarUI", "com.apple.laf.AquaMenuBarUI");
|
||||
} else {
|
||||
UIManager.put("MenuBarUI", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -430,7 +430,22 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// Tests wheather the corresponding Java paltform window is visible or not
|
||||
// Tests whether window is blocked by modal dialog/window
|
||||
- (BOOL) isBlocked {
|
||||
BOOL isBlocked = NO;
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
|
||||
if (platformWindow != NULL) {
|
||||
static JNF_MEMBER_CACHE(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z");
|
||||
isBlocked = JNFCallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO;
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
|
||||
return isBlocked;
|
||||
}
|
||||
|
||||
// Tests whether the corresponding Java platform window is visible or not
|
||||
+ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
|
||||
BOOL isVisible = NO;
|
||||
|
||||
@ -454,8 +469,9 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
- (void) orderChildWindows:(BOOL)focus {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
if (self.isMinimizing) {
|
||||
if (self.isMinimizing || [self isBlocked]) {
|
||||
// Do not perform any ordering, if iconify is in progress
|
||||
// or the window is blocked by a modal window
|
||||
return;
|
||||
}
|
||||
|
||||
@ -809,18 +825,20 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event {
|
||||
if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) {
|
||||
// Move parent windows to front and make sure that a child window is displayed
|
||||
// in front of its nearest parent.
|
||||
if (self.ownerWindow != nil) {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
|
||||
if (platformWindow != NULL) {
|
||||
static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
|
||||
JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
if ([self isBlocked]) {
|
||||
// Move parent windows to front and make sure that a child window is displayed
|
||||
// in front of its nearest parent.
|
||||
if (self.ownerWindow != nil) {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
|
||||
if (platformWindow != NULL) {
|
||||
static JNF_MEMBER_CACHE(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V");
|
||||
JNFCallVoidMethod(env,platformWindow, jm_orderAboveSiblings);
|
||||
(*env)->DeleteLocalRef(env, platformWindow);
|
||||
}
|
||||
}
|
||||
[self orderChildWindows:YES];
|
||||
}
|
||||
[self orderChildWindows:YES];
|
||||
|
||||
NSPoint p = [NSEvent mouseLocation];
|
||||
NSRect frame = [self.nsWindow frame];
|
||||
|
@ -115,19 +115,18 @@
|
||||
if (keyWindow != nil) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
|
||||
static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
|
||||
|
||||
NSUInteger modifiers = [currEvent modifierFlags];
|
||||
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
|
||||
|
||||
JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
|
||||
}
|
||||
}
|
||||
|
||||
static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
|
||||
static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
|
||||
|
||||
NSUInteger modifiers = [currEvent modifierFlags];
|
||||
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
|
||||
|
||||
JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
|
||||
}
|
||||
JNF_COCOA_EXIT(env);
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (void) setJavaLabel:(NSString *)theLabel shortcut:(NSString *)theKeyEquivalent modifierMask:(jint)modifiers {
|
||||
|
@ -404,19 +404,14 @@ Java_sun_font_CFontManager_loadNativeDirFonts
|
||||
{
|
||||
JNF_COCOA_ENTER(env);
|
||||
|
||||
NSString *nsFilePath = JNFJavaToNSString(env, filename);
|
||||
|
||||
FSRef iFile;
|
||||
OSStatus status = CreateFSRef(&iFile, nsFilePath);
|
||||
|
||||
if (status == noErr) {
|
||||
ATSFontContainerRef oContainer;
|
||||
status = ATSFontActivateFromFileReference(&iFile, kATSFontContextLocal,
|
||||
kATSFontFormatUnspecified,
|
||||
NULL, kNilOptions,
|
||||
&oContainer);
|
||||
}
|
||||
|
||||
NSString *path = JNFJavaToNSString(env, filename);
|
||||
NSURL *url = [NSURL fileURLWithPath:(NSString *)path];
|
||||
bool res = CTFontManagerRegisterFontsForURL((CFURLRef)url, kCTFontManagerScopeProcess, nil);
|
||||
#ifdef DEBUG
|
||||
NSLog(@"path is : %@", (NSString*)path);
|
||||
NSLog(@"url is : %@", (NSString*)url);
|
||||
printf("res is %d\n", res);
|
||||
#endif
|
||||
JNF_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
|
@ -591,7 +591,7 @@ CGGI_CreateImageForGlyph
|
||||
static inline GlyphInfo *
|
||||
CGGI_CreateImageForUnicode
|
||||
(CGGI_GlyphCanvas *canvas, const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode, const UniChar uniChar)
|
||||
const CGGI_RenderingMode *mode, const UnicodeScalarValue uniChar)
|
||||
{
|
||||
// save the state of the world
|
||||
CGContextSaveGState(canvas->context);
|
||||
@ -668,7 +668,7 @@ CGGI_FillImagesForGlyphsWithSizedCanvas(CGGI_GlyphCanvas *canvas,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jlong glyphInfos[],
|
||||
const UniChar uniChars[],
|
||||
const UnicodeScalarValue uniChars[],
|
||||
const CGGlyph glyphs[],
|
||||
const CFIndex len)
|
||||
{
|
||||
@ -720,7 +720,7 @@ static NSString *threadLocalLCDCanvasKey =
|
||||
static inline void
|
||||
CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
const UniChar uniChars[], const CGGlyph glyphs[],
|
||||
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
|
||||
const size_t maxWidth, const size_t maxHeight,
|
||||
const CFIndex len)
|
||||
{
|
||||
@ -767,7 +767,7 @@ CGGI_FillImagesForGlyphs(jlong *glyphInfos, const AWTStrike *strike,
|
||||
static inline void
|
||||
CGGI_CreateGlyphInfos(jlong *glyphInfos, const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
const UniChar uniChars[], const CGGlyph glyphs[],
|
||||
const UnicodeScalarValue uniChars[], const CGGlyph glyphs[],
|
||||
CGSize advances[], CGRect bboxes[], const CFIndex len)
|
||||
{
|
||||
AWTFont *font = strike->fAWTFont;
|
||||
@ -817,7 +817,7 @@ CGGI_CreateGlyphsAndScanForComplexities(jlong *glyphInfos,
|
||||
const AWTStrike *strike,
|
||||
const CGGI_RenderingMode *mode,
|
||||
jint rawGlyphCodes[],
|
||||
UniChar uniChars[], CGGlyph glyphs[],
|
||||
UnicodeScalarValue uniChars[], CGGlyph glyphs[],
|
||||
CGSize advances[], CGRect bboxes[],
|
||||
const CFIndex len)
|
||||
{
|
||||
@ -860,7 +860,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
|
||||
CGRect bboxes[len];
|
||||
CGSize advances[len];
|
||||
CGGlyph glyphs[len];
|
||||
UniChar uniChars[len];
|
||||
UnicodeScalarValue uniChars[len];
|
||||
|
||||
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, uniChars, glyphs,
|
||||
@ -871,7 +871,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
|
||||
|
||||
// just do one malloc, and carve it up for all the buffers
|
||||
void *buffer = malloc(sizeof(CGRect) * sizeof(CGSize) *
|
||||
sizeof(CGGlyph) * sizeof(UniChar) * len);
|
||||
sizeof(CGGlyph) * sizeof(UnicodeScalarValue) * len);
|
||||
if (buffer == NULL) {
|
||||
[[NSException exceptionWithName:NSMallocException
|
||||
reason:@"Failed to allocate memory for the temporary glyph strike and measurement buffers." userInfo:nil] raise];
|
||||
@ -880,7 +880,7 @@ CGGlyphImages_GetGlyphImagePtrs(jlong glyphInfos[],
|
||||
CGRect *bboxes = (CGRect *)(buffer);
|
||||
CGSize *advances = (CGSize *)(bboxes + sizeof(CGRect) * len);
|
||||
CGGlyph *glyphs = (CGGlyph *)(advances + sizeof(CGGlyph) * len);
|
||||
UniChar *uniChars = (UniChar *)(glyphs + sizeof(UniChar) * len);
|
||||
UnicodeScalarValue *uniChars = (UnicodeScalarValue *)(glyphs + sizeof(UnicodeScalarValue) * len);
|
||||
|
||||
CGGI_CreateGlyphsAndScanForComplexities(glyphInfos, strike, &mode,
|
||||
rawGlyphCodes, uniChars, glyphs,
|
||||
|
@ -32,7 +32,9 @@
|
||||
#pragma mark --- CoreText Support ---
|
||||
|
||||
#define HI_SURROGATE_START 0xD800
|
||||
#define HI_SURROGATE_END 0xDBFF
|
||||
#define LO_SURROGATE_START 0xDC00
|
||||
#define LO_SURROGATE_END 0xDFFF
|
||||
|
||||
/*
|
||||
* Transform Unicode characters into glyphs.
|
||||
|
@ -103,24 +103,34 @@ void CTS_GetGlyphsAsIntsForCharacters
|
||||
|
||||
size_t i;
|
||||
for (i = 0; i < count; i++) {
|
||||
UniChar unicode = unicodes[i];
|
||||
UniChar nextUnicode = (i+1) < count ? unicodes[i+1] : 0;
|
||||
bool surrogatePair = unicode >= HI_SURROGATE_START && unicode <= HI_SURROGATE_END
|
||||
&& nextUnicode >= LO_SURROGATE_START && nextUnicode <= LO_SURROGATE_END;
|
||||
|
||||
CGGlyph glyph = glyphs[i];
|
||||
if (glyph > 0) {
|
||||
glyphsAsInts[i] = glyph;
|
||||
if (surrogatePair) i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
UniChar unicode = unicodes[i];
|
||||
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicode, 1);
|
||||
const CTFontRef fallback = JRSFontCreateFallbackFontForCharacters((CTFontRef)font->fFont, &unicodes[i],
|
||||
surrogatePair ? 2 : 1);
|
||||
if (fallback) {
|
||||
CTFontGetGlyphsForCharacters(fallback, &unicode, &glyph, 1);
|
||||
CTFontGetGlyphsForCharacters(fallback, &unicodes[i], &glyphs[i], surrogatePair ? 2 : 1);
|
||||
glyph = glyphs[i];
|
||||
CFRelease(fallback);
|
||||
}
|
||||
|
||||
if (glyph > 0) {
|
||||
glyphsAsInts[i] = -unicode; // set the glyph code to the negative unicode value
|
||||
int codePoint = surrogatePair ? (((int)(unicode - HI_SURROGATE_START)) << 10)
|
||||
+ nextUnicode - LO_SURROGATE_START + 0x10000 : unicode;
|
||||
glyphsAsInts[i] = -codePoint; // set the glyph code to the negative unicode value
|
||||
} else {
|
||||
glyphsAsInts[i] = 0; // CoreText couldn't find a glyph for this character either
|
||||
}
|
||||
if (surrogatePair) i++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,8 +168,18 @@ CTFontRef CTS_CopyCTFallbackFontAndGlyphForJavaGlyphCode
|
||||
return (CTFontRef)font->fFont;
|
||||
}
|
||||
|
||||
UTF16Char character = -glyphCode;
|
||||
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
|
||||
int codePoint = -glyphCode;
|
||||
if (codePoint >= 0x10000) {
|
||||
UTF16Char chars[2];
|
||||
CGGlyph glyphs[2];
|
||||
CTS_BreakupUnicodeIntoSurrogatePairs(codePoint, chars);
|
||||
CTFontRef result = CTS_CopyCTFallbackFontAndGlyphForUnicode(font, chars, glyphs, 2);
|
||||
*glyphRef = glyphs[0];
|
||||
return result;
|
||||
} else {
|
||||
UTF16Char character = codePoint;
|
||||
return CTS_CopyCTFallbackFontAndGlyphForUnicode(font, &character, glyphRef, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Breakup a 32 bit unicode value into the component surrogate pairs
|
||||
|
@ -541,10 +541,10 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
}
|
||||
|
||||
// Stream position initially at beginning, left at end
|
||||
// if ignoreUnknownFields is true, do not load fields for which
|
||||
// if readUnknownTags is false, do not load fields for which
|
||||
// a tag cannot be found in an allowed TagSet.
|
||||
public void initialize(ImageInputStream stream, boolean isPrimaryIFD,
|
||||
boolean ignoreUnknownFields) throws IOException {
|
||||
boolean ignoreMetadata, boolean readUnknownTags) throws IOException {
|
||||
|
||||
removeTIFFFields();
|
||||
|
||||
@ -553,10 +553,16 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
|
||||
List<TIFFTagSet> tagSetList = getTagSetList();
|
||||
|
||||
// Configure essential tag variables if this is the primary IFD and
|
||||
// either all metadata are being ignored, or metadata are not being
|
||||
// ignored but both unknown tags are being ignored and the tag set
|
||||
// list does not contain the baseline tags.
|
||||
boolean ensureEssentialTags = false;
|
||||
TIFFTagSet baselineTagSet = null;
|
||||
if (isPrimaryIFD && ignoreUnknownFields
|
||||
&& !tagSetList.contains(BaselineTIFFTagSet.getInstance())) {
|
||||
if (isPrimaryIFD &&
|
||||
(ignoreMetadata ||
|
||||
(!readUnknownTags &&
|
||||
!tagSetList.contains(BaselineTIFFTagSet.getInstance())))) {
|
||||
ensureEssentialTags = true;
|
||||
initializeEssentialTags();
|
||||
baselineTagSet = BaselineTIFFTagSet.getInstance();
|
||||
@ -590,9 +596,12 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
tag = baselineTagSet.getTag(tagNumber);
|
||||
}
|
||||
|
||||
// Ignore unknown fields, fields with unknown type, and fields
|
||||
// Ignore non-essential fields, unknown fields unless forcibly
|
||||
// being read, fields with unknown type, and fields
|
||||
// with count out of int range.
|
||||
if((tag == null && ignoreUnknownFields)
|
||||
if((ignoreMetadata &&
|
||||
(!ensureEssentialTags || !essentialTags.contains(tagNumber)))
|
||||
|| (tag == null && !readUnknownTags)
|
||||
|| (tag != null && !tag.isDataTypeOK(type))
|
||||
|| longCount > Integer.MAX_VALUE) {
|
||||
// Skip the value/offset so as to leave the stream
|
||||
@ -701,7 +710,8 @@ public class TIFFIFD extends TIFFDirectory {
|
||||
tagSets.add(tag.getTagSet());
|
||||
TIFFIFD subIFD = new TIFFIFD(tagSets);
|
||||
|
||||
subIFD.initialize(stream, false, ignoreUnknownFields);
|
||||
subIFD.initialize(stream, false, ignoreMetadata,
|
||||
readUnknownTags);
|
||||
TIFFField f = new TIFFField(tag, type, e.offset, subIFD);
|
||||
addTIFFField(f);
|
||||
} else {
|
||||
|
@ -82,12 +82,13 @@ public class TIFFImageMetadata extends IIOMetadata {
|
||||
}
|
||||
|
||||
public void initializeFromStream(ImageInputStream stream,
|
||||
boolean ignoreUnknownFields)
|
||||
boolean ignoreMetadata,
|
||||
boolean readUnknownTags)
|
||||
throws IOException {
|
||||
rootIFD.initialize(stream, true, ignoreUnknownFields);
|
||||
rootIFD.initialize(stream, true, ignoreMetadata, readUnknownTags);
|
||||
}
|
||||
|
||||
public void addShortOrLongField(int tagNumber, int value) {
|
||||
public void addShortOrLongField(int tagNumber, long value) {
|
||||
TIFFField field = new TIFFField(rootIFD.getTag(tagNumber), value);
|
||||
rootIFD.addTIFFField(field);
|
||||
}
|
||||
|
@ -305,16 +305,19 @@ public class TIFFImageReader extends ImageReader {
|
||||
try {
|
||||
// Create an object to store the image metadata
|
||||
List<TIFFTagSet> tagSets;
|
||||
boolean readUnknownTags = false;
|
||||
if (imageReadParam instanceof TIFFImageReadParam) {
|
||||
tagSets
|
||||
= ((TIFFImageReadParam) imageReadParam).getAllowedTagSets();
|
||||
TIFFImageReadParam tp = (TIFFImageReadParam)imageReadParam;
|
||||
tagSets = tp.getAllowedTagSets();
|
||||
readUnknownTags = tp.getReadUnknownTags();
|
||||
} else {
|
||||
tagSets = new ArrayList<TIFFTagSet>(1);
|
||||
tagSets.add(BaselineTIFFTagSet.getInstance());
|
||||
}
|
||||
|
||||
this.imageMetadata = new TIFFImageMetadata(tagSets);
|
||||
imageMetadata.initializeFromStream(stream, ignoreMetadata);
|
||||
imageMetadata.initializeFromStream(stream, ignoreMetadata,
|
||||
readUnknownTags);
|
||||
} catch (IIOException iioe) {
|
||||
throw iioe;
|
||||
} catch (IOException ioe) {
|
||||
|
@ -3015,7 +3015,7 @@ public class TIFFImageWriter extends ImageWriter {
|
||||
List<TIFFTagSet> tagSets = new ArrayList<TIFFTagSet>(1);
|
||||
tagSets.add(BaselineTIFFTagSet.getInstance());
|
||||
TIFFIFD rootIFD = new TIFFIFD(tagSets);
|
||||
rootIFD.initialize(stream, true, true);
|
||||
rootIFD.initialize(stream, true, false, false);
|
||||
stream.reset();
|
||||
|
||||
return rootIFD;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,17 +22,24 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt;
|
||||
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.awt.peer.CheckboxMenuItemPeer;
|
||||
import java.awt.event.*;
|
||||
import java.util.EventListener;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import javax.accessibility.*;
|
||||
import sun.awt.AWTAccessor;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleAction;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleValue;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
/**
|
||||
* This class represents a check box that can be included in a menu.
|
||||
@ -43,7 +50,8 @@ import sun.awt.AWTAccessor;
|
||||
* of {@code CheckBoxMenuItem}:
|
||||
* <p>
|
||||
* <img src="doc-files/MenuBar-1.gif"
|
||||
* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
|
||||
* alt="Menu labeled Examples, containing items Basic, Simple, Check, and More
|
||||
* Examples. The Check item is a CheckBoxMenuItem instance, in the off state."
|
||||
* style="float:center; margin: 7px 10px;">
|
||||
* <p>
|
||||
* The item labeled {@code Check} shows a check box menu item
|
||||
@ -84,9 +92,9 @@ public class CheckboxMenuItem extends MenuItem implements ItemSelectable, Access
|
||||
* @see #getState()
|
||||
* @see #setState(boolean)
|
||||
*/
|
||||
boolean state = false;
|
||||
private volatile boolean state;
|
||||
|
||||
transient ItemListener itemListener;
|
||||
private transient volatile ItemListener itemListener;
|
||||
|
||||
private static final String base = "chkmenuitem";
|
||||
private static int nameCounter = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,15 +22,20 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.peer.MenuPeer;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.awt.peer.MenuPeer;
|
||||
import java.awt.event.KeyEvent;
|
||||
import javax.accessibility.*;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
/**
|
||||
@ -78,7 +83,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
|
||||
* @serial
|
||||
* @see #countItems()
|
||||
*/
|
||||
Vector<MenuItem> items = new Vector<>();
|
||||
private final Vector<MenuItem> items = new Vector<>();
|
||||
|
||||
/**
|
||||
* This field indicates whether the menu has the
|
||||
@ -92,7 +97,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
|
||||
* @serial
|
||||
* @see #isTearOff()
|
||||
*/
|
||||
boolean tearOff;
|
||||
private final boolean tearOff;
|
||||
|
||||
/**
|
||||
* This field will be set to {@code true}
|
||||
@ -102,7 +107,7 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
boolean isHelpMenu;
|
||||
volatile boolean isHelpMenu;
|
||||
|
||||
private static final String base = "menu";
|
||||
private static int nameCounter = 0;
|
||||
@ -415,8 +420,8 @@ public class Menu extends MenuItem implements MenuContainer, Accessible {
|
||||
if (peer != null) {
|
||||
peer.delItem(index);
|
||||
mi.removeNotify();
|
||||
mi.parent = null;
|
||||
}
|
||||
mi.parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,16 +22,21 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.peer.MenuBarPeer;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import java.awt.peer.MenuBarPeer;
|
||||
import java.awt.event.KeyEvent;
|
||||
import javax.accessibility.*;
|
||||
|
||||
/**
|
||||
* The {@code MenuBar} class encapsulates the platform's
|
||||
@ -94,7 +99,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
|
||||
* @serial
|
||||
* @see #countMenus()
|
||||
*/
|
||||
Vector<Menu> menus = new Vector<>();
|
||||
private final Vector<Menu> menus = new Vector<>();
|
||||
|
||||
/**
|
||||
* This menu is a special menu dedicated to
|
||||
@ -106,7 +111,7 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
|
||||
* @see #getHelpMenu()
|
||||
* @see #setHelpMenu(Menu)
|
||||
*/
|
||||
Menu helpMenu;
|
||||
private volatile Menu helpMenu;
|
||||
|
||||
private static final String base = "menubar";
|
||||
private static int nameCounter = 0;
|
||||
@ -252,8 +257,8 @@ public class MenuBar extends MenuComponent implements MenuContainer, Accessible
|
||||
if (peer != null) {
|
||||
peer.delMenu(index);
|
||||
m.removeNotify();
|
||||
m.parent = null;
|
||||
}
|
||||
m.parent = null;
|
||||
if (helpMenu == m) {
|
||||
helpMenu = null;
|
||||
m.isHelpMenu = false;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,21 +22,28 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt;
|
||||
|
||||
import java.awt.peer.MenuComponentPeer;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.peer.MenuComponentPeer;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.ComponentFactory;
|
||||
|
||||
import javax.accessibility.*;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleComponent;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleSelection;
|
||||
import javax.accessibility.AccessibleState;
|
||||
import javax.accessibility.AccessibleStateSet;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.AppContext;
|
||||
import sun.awt.ComponentFactory;
|
||||
|
||||
/**
|
||||
* The abstract class {@code MenuComponent} is the superclass
|
||||
* of all menu-related components. In this respect, the class
|
||||
@ -60,13 +67,13 @@ public abstract class MenuComponent implements java.io.Serializable {
|
||||
}
|
||||
|
||||
transient volatile MenuComponentPeer peer;
|
||||
transient MenuContainer parent;
|
||||
transient volatile MenuContainer parent;
|
||||
|
||||
/**
|
||||
* The {@code AppContext} of the {@code MenuComponent}.
|
||||
* This is set in the constructor and never changes.
|
||||
*/
|
||||
transient AppContext appContext;
|
||||
private transient volatile AppContext appContext;
|
||||
|
||||
/**
|
||||
* The menu component's font. This value can be
|
||||
@ -77,7 +84,7 @@ public abstract class MenuComponent implements java.io.Serializable {
|
||||
* @see #setFont(Font)
|
||||
* @see #getFont()
|
||||
*/
|
||||
volatile Font font;
|
||||
private volatile Font font;
|
||||
|
||||
/**
|
||||
* The menu component's name, which defaults to {@code null}.
|
||||
@ -85,7 +92,7 @@ public abstract class MenuComponent implements java.io.Serializable {
|
||||
* @see #getName()
|
||||
* @see #setName(String)
|
||||
*/
|
||||
private String name;
|
||||
private volatile String name;
|
||||
|
||||
/**
|
||||
* A variable to indicate whether a name is explicitly set.
|
||||
@ -94,14 +101,14 @@ public abstract class MenuComponent implements java.io.Serializable {
|
||||
* @serial
|
||||
* @see #setName(String)
|
||||
*/
|
||||
private boolean nameExplicitlySet = false;
|
||||
private volatile boolean nameExplicitlySet;
|
||||
|
||||
/**
|
||||
* Defaults to {@code false}.
|
||||
* @serial
|
||||
* @see #dispatchEvent(AWTEvent)
|
||||
*/
|
||||
boolean newEventsOnly = false;
|
||||
volatile boolean newEventsOnly;
|
||||
|
||||
/*
|
||||
* The menu's AccessControlContext.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -22,15 +22,25 @@
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package java.awt;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.peer.MenuItemPeer;
|
||||
import java.awt.event.*;
|
||||
import java.util.EventListener;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.IOException;
|
||||
import javax.accessibility.*;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.util.EventListener;
|
||||
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleAction;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
import javax.accessibility.AccessibleValue;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
/**
|
||||
@ -111,7 +121,7 @@ public class MenuItem extends MenuComponent implements Accessible {
|
||||
* @see #isEnabled()
|
||||
* @see #setEnabled(boolean)
|
||||
*/
|
||||
boolean enabled = true;
|
||||
private volatile boolean enabled = true;
|
||||
|
||||
/**
|
||||
* {@code label} is the label of a menu item.
|
||||
@ -121,7 +131,7 @@ public class MenuItem extends MenuComponent implements Accessible {
|
||||
* @see #getLabel()
|
||||
* @see #setLabel(String)
|
||||
*/
|
||||
String label;
|
||||
volatile String label;
|
||||
|
||||
/**
|
||||
* This field indicates the command that has been issued
|
||||
@ -134,7 +144,7 @@ public class MenuItem extends MenuComponent implements Accessible {
|
||||
* @see #setActionCommand(String)
|
||||
* @see #getActionCommand()
|
||||
*/
|
||||
String actionCommand;
|
||||
private volatile String actionCommand;
|
||||
|
||||
/**
|
||||
* The eventMask is ONLY set by subclasses via enableEvents.
|
||||
@ -144,9 +154,9 @@ public class MenuItem extends MenuComponent implements Accessible {
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
long eventMask;
|
||||
volatile long eventMask;
|
||||
|
||||
transient ActionListener actionListener;
|
||||
private transient volatile ActionListener actionListener;
|
||||
|
||||
/**
|
||||
* A sequence of key stokes that ia associated with
|
||||
@ -160,7 +170,7 @@ public class MenuItem extends MenuComponent implements Accessible {
|
||||
* @see #setShortcut(MenuShortcut)
|
||||
* @see #deleteShortcut()
|
||||
*/
|
||||
private MenuShortcut shortcut = null;
|
||||
private volatile MenuShortcut shortcut;
|
||||
|
||||
private static final String base = "menuitem";
|
||||
private static int nameCounter = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,8 +26,9 @@
|
||||
package java.awt;
|
||||
|
||||
import java.awt.peer.PopupMenuPeer;
|
||||
import javax.accessibility.*;
|
||||
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.accessibility.AccessibleRole;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
|
||||
@ -48,7 +49,7 @@ public class PopupMenu extends Menu {
|
||||
private static final String base = "popup";
|
||||
static int nameCounter = 0;
|
||||
|
||||
transient boolean isTrayIconPopup = false;
|
||||
transient volatile boolean isTrayIconPopup;
|
||||
|
||||
static {
|
||||
AWTAccessor.setPopupMenuAccessor(
|
||||
|
@ -4122,6 +4122,10 @@ public class Window extends Container implements Accessible {
|
||||
public void setTrayIconWindow(Window w, boolean isTrayIconWindow) {
|
||||
w.isTrayIconWindow = isTrayIconWindow;
|
||||
}
|
||||
|
||||
public Window[] getOwnedWindows(Window w) {
|
||||
return w.getOwnedWindows_NoClientCode();
|
||||
}
|
||||
}); // WindowAccessor
|
||||
} // static
|
||||
|
||||
|
@ -279,7 +279,7 @@ public class DragSourceContext
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cursor for this drag operation to the specified
|
||||
* Sets the custom cursor for this drag operation to the specified
|
||||
* {@code Cursor}. If the specified {@code Cursor}
|
||||
* is {@code null}, the default drag cursor behavior is
|
||||
* activated for this drag operation, otherwise it is deactivated.
|
||||
@ -298,9 +298,11 @@ public class DragSourceContext
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current drag {@code Cursor}.
|
||||
* Returns the current custom drag {@code Cursor}.
|
||||
*
|
||||
* @return the current drag {@code Cursor}
|
||||
* @return the current custom drag {@code Cursor}, if it was set
|
||||
* otherwise returns {@code null}.
|
||||
* @see #setCursor
|
||||
*/
|
||||
|
||||
public Cursor getCursor() { return cursor; }
|
||||
|
@ -64,27 +64,71 @@ import java.awt.Image;
|
||||
public abstract class AbstractMultiResolutionImage extends java.awt.Image
|
||||
implements MultiResolutionImage {
|
||||
|
||||
/**
|
||||
* This method simply delegates to the same method on the base image and
|
||||
* it is equivalent to: {@code getBaseImage().getWidth(observer)}.
|
||||
*
|
||||
* @return the width of the base image, or -1 if the width is not yet known
|
||||
* @see #getBaseImage()
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@Override
|
||||
public int getWidth(ImageObserver observer) {
|
||||
return getBaseImage().getWidth(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simply delegates to the same method on the base image and
|
||||
* it is equivalent to: {@code getBaseImage().getHeight(observer)}.
|
||||
*
|
||||
* @return the height of the base image, or -1 if the height is not yet known
|
||||
* @see #getBaseImage()
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@Override
|
||||
public int getHeight(ImageObserver observer) {
|
||||
return getBaseImage().getHeight(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simply delegates to the same method on the base image and
|
||||
* it is equivalent to: {@code getBaseImage().getSource()}.
|
||||
*
|
||||
* @return the image producer that produces the pixels for the base image
|
||||
* @see #getBaseImage()
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@Override
|
||||
public ImageProducer getSource() {
|
||||
return getBaseImage().getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* As per the contract of the base {@code Image#getGraphics()} method,
|
||||
* this implementation will always throw {@code UnsupportedOperationException}
|
||||
* since only off-screen images can return a {@code Graphics} object.
|
||||
*
|
||||
* @return throws {@code UnsupportedOperationException}
|
||||
* @throws UnsupportedOperationException this method is not supported
|
||||
*/
|
||||
@Override
|
||||
public Graphics getGraphics() {
|
||||
throw new UnsupportedOperationException("getGraphics() not supported"
|
||||
+ " on Multi-Resolution Images");
|
||||
}
|
||||
|
||||
/**
|
||||
* This method simply delegates to the same method on the base image and
|
||||
* it is equivalent to: {@code getBaseImage().getProperty(name, observer)}.
|
||||
*
|
||||
* @return the value of the named property in the base image
|
||||
* @see #getBaseImage()
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
@Override
|
||||
public Object getProperty(String name, ImageObserver observer) {
|
||||
return getBaseImage().getProperty(name, observer);
|
||||
|
@ -216,22 +216,27 @@ second on the inferred color space.</p>
|
||||
|
||||
<h4><a name="MetadataIssuesRead"/>Metadata Issues</h4>
|
||||
|
||||
By default all fields in the TIFF image file directory (IFD) are loaded into
|
||||
the native image metadata object. In cases where the IFD includes fields which
|
||||
contain large amounts of data this could be very inefficient. Which fields
|
||||
are loaded may be controlled by setting which TIFF tags the reader is allowed
|
||||
to recognize and whether it is ignoring metadata. The reader is informed to
|
||||
disregard metadata as usual via the <code>ignoreMetadata</code> parameter of
|
||||
By default all recognized fields in the TIFF image file directory (IFD) are
|
||||
loaded into the native image metadata object. Which fields are loaded may be
|
||||
controlled by setting which TIFF tags the reader is allowed to recognize,
|
||||
whether to read fields with unrecognized tags, and whether to ignore all
|
||||
metadata. The reader is informed to disregard all metadata as usual via the
|
||||
<code>ignoreMetadata</code> parameter of
|
||||
<code>ImageReader.setInput(Object,boolean,boolean)</code>. It is
|
||||
informed of which <a href="../../plugins/tiff/TIFFTag.html">TIFFTag</a>s to
|
||||
recognize or not to recognize via
|
||||
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code>
|
||||
and
|
||||
<code>TIFFImageReadParam.addAllowedTagSet(TIFFTagSet)</code> and
|
||||
<code>TIFFImageReadParam.removeAllowedTagSet(TIFFTagSet)</code>.
|
||||
If <code>ignoreMetadata</code> is <code>true</code>, then the reader will
|
||||
load into the native image metadata object only those fields which have a
|
||||
<code>TIFFTag</code> contained in the one of the allowed
|
||||
<code>TIFFTagSet</code>s.
|
||||
If <code>ignoreMetadata</code> is <code>true</code>, then only metadata
|
||||
essential to reading the image will be loaded into the native image metadata
|
||||
object. If <code>ignoreMetadata</code> is <code>false</code>, then the reader
|
||||
will by default load into the native image metadata object only those fields
|
||||
which are either essential to reading the image or have a <code>TIFFTag</code>
|
||||
contained in the one of the allowed <code>TIFFTagSet</code>s. Reading of
|
||||
fields with tags not in the allowed <code>TIFFTagSet</code>s may be forced
|
||||
by passing in a <code>TIFFImageReadParam</code> on which
|
||||
<code>TIFFImageReadParam.setReadUnknownTags(boolean)</code> has been
|
||||
invoked with parameter <code>true</code>.
|
||||
|
||||
<p>Use of a <a href="../../plugins/tiff/TIFFDirectory.html">TIFFDirectory</a>
|
||||
object may simplify gaining access to metadata values. An instance of
|
||||
@ -534,7 +539,7 @@ Technical Note #2</a></td>
|
||||
<tr>
|
||||
<td>ZLib</td>
|
||||
<td>"Deflate/Inflate" compression (see note following this table)</td>
|
||||
<td><a href="http://partners.adobe.com/asn/developer/pdfs/tn/TIFFphotoshop.pdf">
|
||||
<td><a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf">
|
||||
Adobe Photoshop® TIFF Technical Notes</a> (PDF)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -545,9 +550,9 @@ Adobe Photoshop® TIFF Technical Notes</a> (PDF)</td>
|
||||
<tr>
|
||||
<td>Deflate</td>
|
||||
<td>"Zip-in-TIFF" compression (see note following this table)</td>
|
||||
<td><a href="http://www.isi.edu/in-notes/rfc1950.txt">
|
||||
<td><a href="https://tools.ietf.org/html/rfc1950">
|
||||
ZLIB Compressed Data Format Specification</a>,
|
||||
<a href="http://www.isi.edu/in-notes/rfc1951.txt">
|
||||
<a href="https://tools.ietf.org/html/rfc1951">
|
||||
DEFLATE Compressed Data Format Specification</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -224,7 +224,7 @@ public final class BaselineTIFFTagSet extends TIFFTagSet {
|
||||
* A value to be used with the "Compression" tag.
|
||||
*
|
||||
* @see #TAG_COMPRESSION
|
||||
* @see <a href="http://www.isi.edu/in-notes/rfc1951.txt">DEFLATE specification</a>
|
||||
* @see <a href="https://tools.ietf.org/html/rfc1951">DEFLATE specification</a>
|
||||
* @see <a href="http://partners.adobe.com/public/developer/en/tiff/TIFFphotoshop.pdf"> TIFF Specification Supplement 2</a>
|
||||
*/
|
||||
public static final int COMPRESSION_DEFLATE = 32946;
|
||||
|
@ -29,7 +29,7 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* A class representing the extra tags found in a
|
||||
* <a href="http://tools.ietf.org/html/rfc2306"> TIFF-F</a> (RFC 2036) file.
|
||||
* <a href="http://tools.ietf.org/html/rfc2306.html">TIFF-F</a> (RFC 2036) file.
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
|
@ -30,10 +30,7 @@ import java.util.List;
|
||||
/**
|
||||
* A class representing the tags found in a GeoTIFF IFD. GeoTIFF is a
|
||||
* standard for annotating georeferenced or geocoded raster imagery.
|
||||
* The GeoTIFF specification may be found at <a
|
||||
* href="http://www.remotesensing.org/geotiff/spec/geotiffhome.html">
|
||||
* {@code http://www.remotesensing.org/geotiff/spec/geotiffhome.html}
|
||||
* </a>. This class does <i>not</i> handle the <i>GeoKey</i>s referenced
|
||||
* This class does <i>not</i> handle the <i>GeoKey</i>s referenced
|
||||
* from a <i>GeoKeyDirectoryTag</i> as those are not TIFF tags per se.
|
||||
*
|
||||
* <p>The definitions of the data types referenced by the field
|
||||
|
@ -263,14 +263,16 @@ import com.sun.imageio.plugins.tiff.TIFFIFD;
|
||||
*/
|
||||
public final class TIFFField implements Cloneable {
|
||||
|
||||
private static final String[] typeNames = {
|
||||
private static final long MAX_UINT32 = 0xffffffffL;
|
||||
|
||||
private static final String[] TYPE_NAMES = {
|
||||
null,
|
||||
"Byte", "Ascii", "Short", "Long", "Rational",
|
||||
"SByte", "Undefined", "SShort", "SLong", "SRational",
|
||||
"Float", "Double", "IFDPointer"
|
||||
};
|
||||
|
||||
private static final boolean[] isIntegral = {
|
||||
private static final boolean[] IS_INTEGRAL = {
|
||||
false,
|
||||
true, false, true, true, false,
|
||||
true, true, true, true, false,
|
||||
@ -544,6 +546,9 @@ public final class TIFFField implements Cloneable {
|
||||
* @throws IllegalArgumentException if {@code data} is an instance of
|
||||
* a class incompatible with the specified type.
|
||||
* @throws IllegalArgumentException if the size of the data array is wrong.
|
||||
* @throws IllegalArgumentException if the type of the data array is
|
||||
* {@code TIFF_LONG}, {@code TIFF_RATIONAL}, or {@code TIFF_IFD_POINTER}
|
||||
* and any of the elements is negative or greater than {@code 0xffffffff}.
|
||||
*/
|
||||
public TIFFField(TIFFTag tag, int type, int count, Object data) {
|
||||
if(tag == null) {
|
||||
@ -587,15 +592,50 @@ public final class TIFFField implements Cloneable {
|
||||
case TIFFTag.TIFF_LONG:
|
||||
isDataArrayCorrect = data instanceof long[]
|
||||
&& ((long[])data).length == count;
|
||||
if (isDataArrayCorrect) {
|
||||
for (long datum : (long[])data) {
|
||||
if (datum < 0) {
|
||||
throw new IllegalArgumentException
|
||||
("Negative value supplied for TIFF_LONG");
|
||||
}
|
||||
if (datum > MAX_UINT32) {
|
||||
throw new IllegalArgumentException
|
||||
("Too large value supplied for TIFF_LONG");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIFFTag.TIFF_IFD_POINTER:
|
||||
isDataArrayCorrect = data instanceof long[]
|
||||
&& ((long[])data).length == 1;
|
||||
if (((long[])data)[0] < 0) {
|
||||
throw new IllegalArgumentException
|
||||
("Negative value supplied for TIFF_IFD_POINTER");
|
||||
}
|
||||
if (((long[])data)[0] > MAX_UINT32) {
|
||||
throw new IllegalArgumentException
|
||||
("Too large value supplied for TIFF_IFD_POINTER");
|
||||
}
|
||||
break;
|
||||
case TIFFTag.TIFF_RATIONAL:
|
||||
isDataArrayCorrect = data instanceof long[][]
|
||||
&& ((long[][])data).length == count
|
||||
&& ((long[][])data)[0].length == 2;
|
||||
&& ((long[][])data).length == count;
|
||||
if (isDataArrayCorrect) {
|
||||
for (long[] datum : (long[][])data) {
|
||||
if (datum.length != 2) {
|
||||
isDataArrayCorrect = false;
|
||||
break;
|
||||
}
|
||||
if (datum[0] < 0 || datum[1] < 0) {
|
||||
throw new IllegalArgumentException
|
||||
("Negative value supplied for TIFF_RATIONAL");
|
||||
}
|
||||
if (datum[0] > MAX_UINT32 || datum[1] > MAX_UINT32) {
|
||||
throw new IllegalArgumentException
|
||||
("Too large value supplied for TIFF_RATIONAL");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIFFTag.TIFF_SSHORT:
|
||||
isDataArrayCorrect = data instanceof short[]
|
||||
@ -607,8 +647,15 @@ public final class TIFFField implements Cloneable {
|
||||
break;
|
||||
case TIFFTag.TIFF_SRATIONAL:
|
||||
isDataArrayCorrect = data instanceof int[][]
|
||||
&& ((int[][])data).length == count
|
||||
&& ((int[][])data)[0].length == 2;
|
||||
&& ((int[][])data).length == count;
|
||||
if (isDataArrayCorrect) {
|
||||
for (int[] datum : (int[][])data) {
|
||||
if (datum.length != 2) {
|
||||
isDataArrayCorrect = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TIFFTag.TIFF_FLOAT:
|
||||
isDataArrayCorrect = data instanceof float[]
|
||||
@ -658,27 +705,32 @@ public final class TIFFField implements Cloneable {
|
||||
|
||||
/**
|
||||
* Constructs a {@code TIFFField} with a single non-negative integral
|
||||
* value.
|
||||
* The field will have type
|
||||
* {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if
|
||||
* {@code val < 65536} and type
|
||||
* {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count
|
||||
* of the field will be unity.
|
||||
* value. The field will have type {@link TIFFTag#TIFF_SHORT TIFF_SHORT}
|
||||
* if {@code value} is in {@code [0,0xffff]}, and type
|
||||
* {@link TIFFTag#TIFF_LONG TIFF_LONG} if {@code value} is in
|
||||
* {@code [0x10000,0xffffffff]}. The count of the field will be unity.
|
||||
*
|
||||
* @param tag The tag to associate with this field.
|
||||
* @param value The value to associate with this field.
|
||||
* @throws NullPointerException if {@code tag == null}.
|
||||
* @throws IllegalArgumentException if the derived type is unacceptable
|
||||
* for the supplied {@code TIFFTag}.
|
||||
* @throws IllegalArgumentException if {@code value < 0}.
|
||||
* @throws IllegalArgumentException if {@code value} is not in
|
||||
* {@code [0,0xffffffff]}.
|
||||
* @throws IllegalArgumentException if {@code value} is in
|
||||
* {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type
|
||||
* for the {@code TIFFTag}, or if {@code value} is in
|
||||
* {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable
|
||||
* type for the {@code TIFFTag}.
|
||||
*/
|
||||
public TIFFField(TIFFTag tag, int value) {
|
||||
public TIFFField(TIFFTag tag, long value) {
|
||||
if(tag == null) {
|
||||
throw new NullPointerException("tag == null!");
|
||||
}
|
||||
if (value < 0) {
|
||||
throw new IllegalArgumentException("value < 0!");
|
||||
}
|
||||
if (value > MAX_UINT32) {
|
||||
throw new IllegalArgumentException("value > 0xffffffff!");
|
||||
}
|
||||
|
||||
this.tag = tag;
|
||||
this.tagNumber = tag.getNumber();
|
||||
@ -687,7 +739,8 @@ public final class TIFFField implements Cloneable {
|
||||
if (value < 65536) {
|
||||
if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) {
|
||||
throw new IllegalArgumentException("Illegal data type "
|
||||
+ TIFFTag.TIFF_SHORT + " for " + tag.getName() + " tag");
|
||||
+ getTypeName(TIFFTag.TIFF_SHORT) + " for tag "
|
||||
+ "\"" + tag.getName() + "\"");
|
||||
}
|
||||
this.type = TIFFTag.TIFF_SHORT;
|
||||
char[] cdata = new char[1];
|
||||
@ -696,7 +749,8 @@ public final class TIFFField implements Cloneable {
|
||||
} else {
|
||||
if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) {
|
||||
throw new IllegalArgumentException("Illegal data type "
|
||||
+ TIFFTag.TIFF_LONG + " for " + tag.getName() + " tag");
|
||||
+ getTypeName(TIFFTag.TIFF_LONG) + " for tag "
|
||||
+ "\"" + tag.getName() + "\"");
|
||||
}
|
||||
this.type = TIFFTag.TIFF_LONG;
|
||||
long[] ldata = new long[1];
|
||||
@ -799,7 +853,7 @@ public final class TIFFField implements Cloneable {
|
||||
throw new IllegalArgumentException("Unknown data type "+dataType);
|
||||
}
|
||||
|
||||
return typeNames[dataType];
|
||||
return TYPE_NAMES[dataType];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -812,7 +866,7 @@ public final class TIFFField implements Cloneable {
|
||||
*/
|
||||
public static int getTypeByName(String typeName) {
|
||||
for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
|
||||
if (typeName.equals(typeNames[i])) {
|
||||
if (typeName.equals(TYPE_NAMES[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@ -887,7 +941,7 @@ public final class TIFFField implements Cloneable {
|
||||
* @return Whether the field type is integral.
|
||||
*/
|
||||
public boolean isIntegral() {
|
||||
return isIntegral[type];
|
||||
return IS_INTEGRAL[type];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,11 +46,18 @@ import javax.imageio.ImageReadParam;
|
||||
* {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet}
|
||||
* are included.
|
||||
*
|
||||
* <p> Forcing reading of fields corresponding to {@code TIFFTag}s
|
||||
* not in any of the allowed {@code TIFFTagSet}s may be effected via
|
||||
* {@link #setReadUnknownTags setReadUnknownTags}.
|
||||
*
|
||||
* @since 9
|
||||
*/
|
||||
public final class TIFFImageReadParam extends ImageReadParam {
|
||||
|
||||
private List<TIFFTagSet> allowedTagSets = new ArrayList<TIFFTagSet>(4);
|
||||
private final List<TIFFTagSet> allowedTagSets =
|
||||
new ArrayList<TIFFTagSet>(4);
|
||||
|
||||
private boolean readUnknownTags = false;
|
||||
|
||||
/**
|
||||
* Constructs a {@code TIFFImageReadParam}. Tags defined by
|
||||
@ -72,7 +79,8 @@ public final class TIFFImageReadParam extends ImageReadParam {
|
||||
|
||||
/**
|
||||
* Adds a {@code TIFFTagSet} object to the list of allowed
|
||||
* tag sets.
|
||||
* tag sets. Attempting to add a duplicate object to the list
|
||||
* has no effect.
|
||||
*
|
||||
* @param tagSet a {@code TIFFTagSet}.
|
||||
*
|
||||
@ -83,7 +91,9 @@ public final class TIFFImageReadParam extends ImageReadParam {
|
||||
if (tagSet == null) {
|
||||
throw new IllegalArgumentException("tagSet == null!");
|
||||
}
|
||||
allowedTagSets.add(tagSet);
|
||||
if (!allowedTagSets.contains(tagSet)) {
|
||||
allowedTagSets.add(tagSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -113,4 +123,27 @@ public final class TIFFImageReadParam extends ImageReadParam {
|
||||
public List<TIFFTagSet> getAllowedTagSets() {
|
||||
return allowedTagSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to read fields corresponding to {@code TIFFTag}s not in
|
||||
* the allowed {@code TIFFTagSet}s. The default setting is {@code false}.
|
||||
* If the TIFF {@code ImageReader} is ignoring metadata, then a setting
|
||||
* of {@code true} is overridden as all metadata are ignored except those
|
||||
* essential to reading the image itself.
|
||||
*
|
||||
* @param readUnknownTags Whether to read fields of unrecognized tags
|
||||
*/
|
||||
public void setReadUnknownTags(boolean readUnknownTags) {
|
||||
this.readUnknownTags = readUnknownTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the setting of whether to read fields corresponding to unknown
|
||||
* {@code TIFFTag}s.
|
||||
*
|
||||
* @return Whether to read fields of unrecognized tags
|
||||
*/
|
||||
public boolean getReadUnknownTags() {
|
||||
return readUnknownTags;
|
||||
}
|
||||
}
|
||||
|
@ -182,6 +182,8 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
|
||||
*/
|
||||
private int modelRowCount;
|
||||
|
||||
// Whether to print warning about JDK-8160087
|
||||
private static boolean warning8160087 = true;
|
||||
|
||||
/**
|
||||
* Creates an empty <code>DefaultRowSorter</code>.
|
||||
@ -489,10 +491,7 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
|
||||
*/
|
||||
public int convertRowIndexToView(int index) {
|
||||
if (modelToView == null) {
|
||||
if (index < 0 || index >= modelRowCount) {
|
||||
throw new IndexOutOfBoundsException("Invalid index");
|
||||
}
|
||||
return index;
|
||||
return convertUnsortedUnfiltered(index);
|
||||
}
|
||||
return modelToView[index];
|
||||
}
|
||||
@ -504,14 +503,30 @@ public abstract class DefaultRowSorter<M, I> extends RowSorter<M> {
|
||||
*/
|
||||
public int convertRowIndexToModel(int index) {
|
||||
if (viewToModel == null) {
|
||||
if (index < 0 || index >= modelRowCount) {
|
||||
throw new IndexOutOfBoundsException("Invalid index");
|
||||
}
|
||||
return index;
|
||||
return convertUnsortedUnfiltered(index);
|
||||
}
|
||||
return viewToModel[index].modelIndex;
|
||||
}
|
||||
|
||||
private int convertUnsortedUnfiltered(int index) {
|
||||
if (index < 0 || index >= modelRowCount) {
|
||||
if(index >= modelRowCount &&
|
||||
index < getModelWrapper().getRowCount()) {
|
||||
// 8160087
|
||||
if(warning8160087) {
|
||||
warning8160087 = false;
|
||||
System.err.println("WARNING: row index is bigger than " +
|
||||
"sorter's row count. Most likely this is a wrong " +
|
||||
"sorter usage.");
|
||||
}
|
||||
} else {
|
||||
throw new IndexOutOfBoundsException("Invalid index");
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
private boolean isUnsorted() {
|
||||
List<? extends SortKey> keys = getSortKeys();
|
||||
int keySize = keys.size();
|
||||
|
@ -27,6 +27,7 @@ package javax.swing;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.*;
|
||||
import java.beans.JavaBean;
|
||||
import java.beans.BeanProperty;
|
||||
@ -41,6 +42,8 @@ import java.io.IOException;
|
||||
import javax.swing.plaf.*;
|
||||
import javax.accessibility.*;
|
||||
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
/**
|
||||
* An implementation of a menu bar. You add <code>JMenu</code> objects to the
|
||||
* menu bar to construct a menu. When the user selects a <code>JMenu</code>
|
||||
@ -144,6 +147,10 @@ public class JMenuBar extends JComponent implements Accessible,MenuElement
|
||||
* @see JComponent#updateUI
|
||||
*/
|
||||
public void updateUI() {
|
||||
Toolkit tk = Toolkit.getDefaultToolkit();
|
||||
if (tk instanceof SunToolkit) {
|
||||
((SunToolkit)tk).updateScreenMenuBarUI();
|
||||
}
|
||||
setUI((MenuBarUI)UIManager.getUI(this));
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.swing.SwingUtilities2;
|
||||
|
||||
/**
|
||||
* The "viewport" or "porthole" through which you see the underlying
|
||||
@ -1034,9 +1035,16 @@ public class JViewport extends JComponent implements Accessible
|
||||
private boolean isBlitting() {
|
||||
Component view = getView();
|
||||
return (scrollMode == BLIT_SCROLL_MODE) &&
|
||||
(view instanceof JComponent) && view.isOpaque();
|
||||
(view instanceof JComponent) && view.isOpaque() && !isFPScale();
|
||||
}
|
||||
|
||||
private boolean isFPScale() {
|
||||
GraphicsConfiguration gc = getGraphicsConfiguration();
|
||||
if (gc != null) {
|
||||
return SwingUtilities2.isFloatingPointScale(gc.getDefaultTransform());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <code>JViewport</code>'s one child or <code>null</code>.
|
||||
|
@ -45,7 +45,11 @@ import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
import com.sun.java.swing.SwingUtilities3;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.pipe.Region;
|
||||
import sun.swing.SwingAccessor;
|
||||
import sun.swing.SwingUtilities2;
|
||||
import sun.swing.SwingUtilities2.RepaintListener;
|
||||
|
||||
/**
|
||||
@ -1517,9 +1521,12 @@ public class RepaintManager
|
||||
// standard Image buffer.
|
||||
boolean paintCompleted = false;
|
||||
Image offscreen;
|
||||
int sw = w + 1;
|
||||
int sh = h + 1;
|
||||
|
||||
if (repaintManager.useVolatileDoubleBuffer() &&
|
||||
(offscreen = getValidImage(repaintManager.
|
||||
getVolatileOffscreenBuffer(bufferComponent, w, h))) != null) {
|
||||
getVolatileOffscreenBuffer(bufferComponent, sw, sh))) != null) {
|
||||
VolatileImage vImage = (java.awt.image.VolatileImage)offscreen;
|
||||
GraphicsConfiguration gc = bufferComponent.
|
||||
getGraphicsConfiguration();
|
||||
@ -1529,7 +1536,7 @@ public class RepaintManager
|
||||
VolatileImage.IMAGE_INCOMPATIBLE) {
|
||||
repaintManager.resetVolatileDoubleBuffer(gc);
|
||||
offscreen = repaintManager.getVolatileOffscreenBuffer(
|
||||
bufferComponent,w, h);
|
||||
bufferComponent, sw, sh);
|
||||
vImage = (java.awt.image.VolatileImage)offscreen;
|
||||
}
|
||||
paintDoubleBuffered(paintingComponent, vImage, g, x, y,
|
||||
@ -1589,8 +1596,18 @@ public class RepaintManager
|
||||
* Paints a portion of a component to an offscreen buffer.
|
||||
*/
|
||||
protected void paintDoubleBuffered(JComponent c, Image image,
|
||||
Graphics g, int clipX, int clipY,
|
||||
int clipW, int clipH) {
|
||||
Graphics g, int clipX, int clipY,
|
||||
int clipW, int clipH) {
|
||||
if (image instanceof VolatileImage && isPixelsCopying(c, g)) {
|
||||
paintDoubleBufferedFPScales(c, image, g, clipX, clipY, clipW, clipH);
|
||||
} else {
|
||||
paintDoubleBufferedImpl(c, image, g, clipX, clipY, clipW, clipH);
|
||||
}
|
||||
}
|
||||
|
||||
private void paintDoubleBufferedImpl(JComponent c, Image image,
|
||||
Graphics g, int clipX, int clipY,
|
||||
int clipW, int clipH) {
|
||||
Graphics osg = image.getGraphics();
|
||||
int bw = Math.min(clipW, image.getWidth(null));
|
||||
int bh = Math.min(clipH, image.getHeight(null));
|
||||
@ -1629,6 +1646,76 @@ public class RepaintManager
|
||||
}
|
||||
}
|
||||
|
||||
private void paintDoubleBufferedFPScales(JComponent c, Image image,
|
||||
Graphics g, int clipX, int clipY,
|
||||
int clipW, int clipH) {
|
||||
Graphics osg = image.getGraphics();
|
||||
Graphics2D g2d = (Graphics2D) g;
|
||||
Graphics2D osg2d = (Graphics2D) osg;
|
||||
|
||||
AffineTransform identity = new AffineTransform();
|
||||
int bw = Math.min(clipW, image.getWidth(null));
|
||||
int bh = Math.min(clipH, image.getHeight(null));
|
||||
int x, y, maxx, maxy;
|
||||
|
||||
AffineTransform tx = g2d.getTransform();
|
||||
double scaleX = tx.getScaleX();
|
||||
double scaleY = tx.getScaleY();
|
||||
double trX = tx.getTranslateX();
|
||||
double trY = tx.getTranslateY();
|
||||
|
||||
boolean translucent = volatileBufferType != Transparency.OPAQUE;
|
||||
Composite oldComposite = g2d.getComposite();
|
||||
|
||||
try {
|
||||
for (x = clipX, maxx = clipX + clipW; x < maxx; x += bw) {
|
||||
for (y = clipY, maxy = clipY + clipH; y < maxy; y += bh) {
|
||||
|
||||
// draw x, y, bw, bh
|
||||
int pixelx1 = Region.clipRound(x * scaleX + trX);
|
||||
int pixely1 = Region.clipRound(y * scaleY + trY);
|
||||
int pixelx2 = Region.clipRound((x + bw) * scaleX + trX);
|
||||
int pixely2 = Region.clipRound((y + bh) * scaleY + trY);
|
||||
int pixelw = pixelx2 - pixelx1;
|
||||
int pixelh = pixely2 - pixely1;
|
||||
|
||||
osg2d.setTransform(identity);
|
||||
if (translucent) {
|
||||
final Color oldBg = g2d.getBackground();
|
||||
g2d.setBackground(c.getBackground());
|
||||
g2d.clearRect(pixelx1, pixely1, pixelw, pixelh);
|
||||
g2d.setBackground(oldBg);
|
||||
}
|
||||
|
||||
osg2d.setClip(0, 0, pixelw, pixelh);
|
||||
osg2d.translate(trX - pixelx1, trY - pixely1);
|
||||
osg2d.scale(scaleX, scaleY);
|
||||
c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
|
||||
|
||||
g2d.setTransform(identity);
|
||||
g2d.setClip(pixelx1, pixely1, pixelw, pixelh);
|
||||
AffineTransform stx = new AffineTransform();
|
||||
stx.translate(pixelx1, pixely1);
|
||||
stx.scale(scaleX, scaleY);
|
||||
g2d.setTransform(stx);
|
||||
|
||||
if (translucent) {
|
||||
g2d.setComposite(AlphaComposite.Src);
|
||||
}
|
||||
|
||||
g2d.drawImage(image, 0, 0, c);
|
||||
|
||||
if (translucent) {
|
||||
g2d.setComposite(oldComposite);
|
||||
}
|
||||
g2d.setTransform(tx);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
osg.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If <code>image</code> is non-null with a positive size it
|
||||
* is returned, otherwise null is returned.
|
||||
@ -1671,8 +1758,32 @@ public class RepaintManager
|
||||
*/
|
||||
protected void dispose() {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPixelsCopying(JComponent c, Graphics g) {
|
||||
|
||||
AffineTransform tx = getTransform(g);
|
||||
GraphicsConfiguration gc = c.getGraphicsConfiguration();
|
||||
|
||||
if (tx == null || gc == null
|
||||
|| !SwingUtilities2.isFloatingPointScale(tx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AffineTransform gcTx = gc.getDefaultTransform();
|
||||
|
||||
return gcTx.getScaleX() == tx.getScaleX()
|
||||
&& gcTx.getScaleY() == tx.getScaleY();
|
||||
}
|
||||
|
||||
private static AffineTransform getTransform(Graphics g) {
|
||||
if (g instanceof SunGraphics2D) {
|
||||
return ((SunGraphics2D) g).transform;
|
||||
} else if (g instanceof Graphics2D) {
|
||||
return ((Graphics2D) g).getTransform();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private class DoubleBufferInfo {
|
||||
public Image image;
|
||||
|
@ -571,7 +571,9 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
|
||||
|
||||
/**
|
||||
* Obsolete class, not used in this version.
|
||||
* @deprecated As of JDK version 9. Obsolete class.
|
||||
*/
|
||||
@Deprecated(since = "9")
|
||||
protected class SingleClickListener extends MouseAdapter {
|
||||
/**
|
||||
* Constructs an instance of {@code SingleClickListener}.
|
||||
@ -584,7 +586,9 @@ public class MetalFileChooserUI extends BasicFileChooserUI {
|
||||
|
||||
/**
|
||||
* Obsolete class, not used in this version.
|
||||
* @deprecated As of JDK version 9. Obsolete class.
|
||||
*/
|
||||
@Deprecated(since = "9")
|
||||
@SuppressWarnings("serial") // Superclass is not serializable across versions
|
||||
protected class FileRenderer extends DefaultListCellRenderer {
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package javax.swing.text;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
@ -750,7 +751,6 @@ public class WrappedPlainView extends BoxView implements TabExpander {
|
||||
* valid location in the associated document
|
||||
* @see View#modelToView
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public Shape modelToView(int pos, Shape a, Position.Bias b)
|
||||
throws BadLocationException {
|
||||
Rectangle alloc = a.getBounds();
|
||||
@ -777,9 +777,11 @@ public class WrappedPlainView extends BoxView implements TabExpander {
|
||||
if (pos > p0) {
|
||||
Segment segment = SegmentCache.getSharedSegment();
|
||||
loadText(segment, p0, pos);
|
||||
alloc.x += Utilities.getTabbedTextWidth(segment, metrics,
|
||||
alloc.x, WrappedPlainView.this, p0);
|
||||
float x = alloc.x;
|
||||
x += Utilities.getTabbedTextWidth(segment, metrics, x,
|
||||
WrappedPlainView.this, p0);
|
||||
SegmentCache.releaseSharedSegment(segment);
|
||||
return new Rectangle2D.Float(x, alloc.y, alloc.width, alloc.height);
|
||||
}
|
||||
return alloc;
|
||||
}
|
||||
|
@ -360,6 +360,12 @@ public final class AWTAccessor {
|
||||
* Marks the specified window as an utility window for TrayIcon.
|
||||
*/
|
||||
void setTrayIconWindow(Window w, boolean isTrayIconWindow);
|
||||
|
||||
/**
|
||||
* Return an array containing all the windows this
|
||||
* window currently owns.
|
||||
*/
|
||||
Window[] getOwnedWindows(Window w);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1857,6 +1857,9 @@ public abstract class SunToolkit extends Toolkit
|
||||
return time == null ? -1 : time;
|
||||
}
|
||||
|
||||
public void updateScreenMenuBarUI() {
|
||||
}
|
||||
|
||||
// Cosntant alpha
|
||||
public boolean isWindowOpacitySupported() {
|
||||
return false;
|
||||
|
@ -3101,10 +3101,10 @@ public final class SunGraphics2D
|
||||
if (scaleX == 1 && scaleY == 1) {
|
||||
return null;
|
||||
}
|
||||
sx1 = Region.clipScale(sx1, scaleX);
|
||||
sx2 = Region.clipScale(sx2, scaleX);
|
||||
sy1 = Region.clipScale(sy1, scaleY);
|
||||
sy2 = Region.clipScale(sy2, scaleY);
|
||||
sx1 = Region.clipRound(sx1 * scaleX);
|
||||
sx2 = Region.clipRound(sx2 * scaleX);
|
||||
sy1 = Region.clipRound(sy1 * scaleY);
|
||||
sy2 = Region.clipRound(sy2 * scaleY);
|
||||
|
||||
AffineTransform tx = null;
|
||||
if (xform != null) {
|
||||
|
@ -305,6 +305,12 @@ public final class JLightweightFrame extends LightweightFrame implements RootPan
|
||||
int startY = (int)Math.floor(y * scaleY);
|
||||
int width = (int)Math.ceil((x + w) * scaleX) - startX;
|
||||
int height = (int)Math.ceil((y + h) * scaleY) - startY;
|
||||
if (startX + width > linestride) {
|
||||
width = linestride - startX;
|
||||
}
|
||||
if (startY + height > bbImage.getHeight()) {
|
||||
height = bbImage.getHeight() - startY;
|
||||
}
|
||||
|
||||
for (int i = 0; i < height; i++) {
|
||||
int from = (startY + i) * linestride + startX;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user