This commit is contained in:
J. Duke 2017-07-05 23:43:54 +02:00
commit 1edfabb9b0
272 changed files with 3720 additions and 18729 deletions

View File

@ -428,3 +428,5 @@ b94be69cbb1d2943b886bf2d458745756df146e4 jdk-10+9
2c25fc24103251f9711a1c280c31e1e41016d90f jdk-9+172
6b750cdb823a029a25ff2e560302cc2d28a86cb6 jdk-10+11
88d7fd969e7df0e07a53b201cfd29393ca33ede9 jdk-9+173
5466f409346e0446ee9a6daeb7f5d75c8fc76823 jdk-9+174
8d4ed1e06fe184c9cb08c5b708e7d6f5c066644f jdk-10+12

View File

@ -688,6 +688,7 @@ LIBFFI_LIBS
LIBFFI_CFLAGS
ALSA_LIBS
ALSA_CFLAGS
FREETYPE_LICENSE
FREETYPE_BUNDLE_LIB_PATH
FREETYPE_LIBS
FREETYPE_CFLAGS
@ -1200,6 +1201,7 @@ with_freetype_include
with_freetype_lib
with_freetype_src
enable_freetype_bundling
with_freetype_license
with_alsa
with_alsa_include
with_alsa_lib
@ -2153,6 +2155,7 @@ Optional Packages:
--with-freetype-src specify directory with freetype sources to
automatically build the library (experimental,
Windows-only)
--with-freetype-license if bundling freetype, also bundle this license file
--with-alsa specify prefix directory for the alsa package
(expecting the libraries under PATH/lib and the
headers under PATH/include)
@ -5186,7 +5189,7 @@ VS_SDK_PLATFORM_NAME_2013=
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
DATE_WHEN_GENERATED=1494858828
DATE_WHEN_GENERATED=1496926402
###############################################################################
#
@ -57906,6 +57909,12 @@ if test "${enable_freetype_bundling+set}" = set; then :
fi
# Check whether --with-freetype-license was given.
if test "${with_freetype_license+set}" = set; then :
withval=$with_freetype_license;
fi
# Need to specify explicitly since it needs to be overridden on some versions of macosx
FREETYPE_BASE_NAME=freetype
FREETYPE_CFLAGS=
@ -63852,6 +63861,153 @@ $as_echo "$BUNDLE_FREETYPE" >&6; }
fi # end freetype needed
FREETYPE_LICENSE=""
if test "x$with_freetype_license" = "xyes"; then
as_fn_error $? "--with-freetype-license must have a value" "$LINENO" 5
elif test "x$with_freetype_license" != "x"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype license" >&5
$as_echo_n "checking for freetype license... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_freetype_license" >&5
$as_echo "$with_freetype_license" >&6; }
FREETYPE_LICENSE="$with_freetype_license"
# Only process if variable expands to non-empty
if test "x$FREETYPE_LICENSE" != x; then
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
# Input might be given as Windows format, start by converting to
# unix format.
path="$FREETYPE_LICENSE"
new_path=`$CYGPATH -u "$path"`
# Cygwin tries to hide some aspects of the Windows file system, such that binaries are
# named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
# the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
# "foo.exe" is OK but "foo" is an error.
#
# This test is therefore slightly more accurate than "test -f" to check for file precense.
# It is also a way to make sure we got the proper file name for the real test later on.
test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
if test "x$test_shortpath" = x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&5
$as_echo "$as_me: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&6;}
as_fn_error $? "Cannot locate the the path of FREETYPE_LICENSE" "$LINENO" 5
fi
# Call helper function which possibly converts this using DOS-style short mode.
# If so, the updated path is stored in $new_path.
input_path="$new_path"
# Check if we need to convert this using DOS-style short mode. If the path
# contains just simple characters, use it. Otherwise (spaces, weird characters),
# take no chances and rewrite it.
# Note: m4 eats our [], so we need to use [ and ] instead.
has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
if test "x$has_forbidden_chars" != x; then
# Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
shortmode_path=`$CYGPATH -s -m -a "$input_path"`
path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
# Going to short mode and back again did indeed matter. Since short mode is
# case insensitive, let's make it lowercase to improve readability.
shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
# Now convert it back to Unix-style (cygpath)
input_path=`$CYGPATH -u "$shortmode_path"`
new_path="$input_path"
fi
fi
test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
if test "x$test_cygdrive_prefix" = x; then
# As a simple fix, exclude /usr/bin since it's not a real path.
if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
# The path is in a Cygwin special directory (e.g. /home). We need this converted to
# a path prefixed by /cygdrive for fixpath to work.
new_path="$CYGWIN_ROOT_PATH$input_path"
fi
fi
if test "x$path" != "x$new_path"; then
FREETYPE_LICENSE="$new_path"
{ $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&5
$as_echo "$as_me: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&6;}
fi
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
path="$FREETYPE_LICENSE"
has_colon=`$ECHO $path | $GREP ^.:`
new_path="$path"
if test "x$has_colon" = x; then
# Not in mixed or Windows style, start by that.
new_path=`cmd //c echo $path`
fi
input_path="$new_path"
# Check if we need to convert this using DOS-style short mode. If the path
# contains just simple characters, use it. Otherwise (spaces, weird characters),
# take no chances and rewrite it.
# Note: m4 eats our [], so we need to use [ and ] instead.
has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
if test "x$has_forbidden_chars" != x; then
# Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
fi
windows_path="$new_path"
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
unix_path=`$CYGPATH -u "$windows_path"`
new_path="$unix_path"
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
new_path="$unix_path"
fi
if test "x$path" != "x$new_path"; then
FREETYPE_LICENSE="$new_path"
{ $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&5
$as_echo "$as_me: Rewriting FREETYPE_LICENSE to \"$new_path\"" >&6;}
fi
# Save the first 10 bytes of this path to the storage, so fixpath can work.
all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
else
# We're on a unix platform. Hooray! :)
path="$FREETYPE_LICENSE"
has_space=`$ECHO "$path" | $GREP " "`
if test "x$has_space" != x; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&5
$as_echo "$as_me: The path of FREETYPE_LICENSE, which resolves as \"$path\", is invalid." >&6;}
as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
fi
# Use eval to expand a potential ~
eval path="$path"
if test ! -f "$path" && test ! -d "$path"; then
as_fn_error $? "The path of FREETYPE_LICENSE, which resolves as \"$path\", is not found." "$LINENO" 5
fi
if test -d "$path"; then
FREETYPE_LICENSE="`cd "$path"; $THEPWDCMD -L`"
else
dir="`$DIRNAME "$path"`"
base="`$BASENAME "$path"`"
FREETYPE_LICENSE="`cd "$dir"; $THEPWDCMD -L`/$base"
fi
fi
fi
if test ! -f "$FREETYPE_LICENSE"; then
as_fn_error $? "$FREETYPE_LICENSE cannot be found" "$LINENO" 5
fi
fi

View File

@ -194,6 +194,8 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
[specify directory with freetype sources to automatically build the library (experimental, Windows-only)])])
AC_ARG_ENABLE(freetype-bundling, [AS_HELP_STRING([--disable-freetype-bundling],
[disable bundling of the freetype library with the build result @<:@enabled on Windows or when using --with-freetype, disabled otherwise@:>@])])
AC_ARG_WITH(freetype-license, [AS_HELP_STRING([--with-freetype-license],
[if bundling freetype, also bundle this license file])])
# Need to specify explicitly since it needs to be overridden on some versions of macosx
FREETYPE_BASE_NAME=freetype
@ -443,7 +445,21 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
fi # end freetype needed
FREETYPE_LICENSE=""
if test "x$with_freetype_license" = "xyes"; then
AC_MSG_ERROR([--with-freetype-license must have a value])
elif test "x$with_freetype_license" != "x"; then
AC_MSG_CHECKING([for freetype license])
AC_MSG_RESULT([$with_freetype_license])
FREETYPE_LICENSE="$with_freetype_license"
BASIC_FIXUP_PATH(FREETYPE_LICENSE)
if test ! -f "$FREETYPE_LICENSE"; then
AC_MSG_ERROR([$FREETYPE_LICENSE cannot be found])
fi
fi
AC_SUBST(FREETYPE_BUNDLE_LIB_PATH)
AC_SUBST(FREETYPE_CFLAGS)
AC_SUBST(FREETYPE_LIBS)
AC_SUBST(FREETYPE_LICENSE)
])

View File

@ -312,6 +312,7 @@ DEFAULT_MAKE_TARGET:=@DEFAULT_MAKE_TARGET@
FREETYPE_LIBS:=@FREETYPE_LIBS@
FREETYPE_CFLAGS:=@FREETYPE_CFLAGS@
FREETYPE_BUNDLE_LIB_PATH=@FREETYPE_BUNDLE_LIB_PATH@
FREETYPE_LICENSE=@FREETYPE_LICENSE@
CUPS_CFLAGS:=@CUPS_CFLAGS@
ALSA_LIBS:=@ALSA_LIBS@
ALSA_CFLAGS:=@ALSA_CFLAGS@

View File

@ -893,6 +893,16 @@ var getJibProfilesProfiles = function (input, common, data) {
}
});
// The windows ri profile needs to add the freetype license file
profilesRiFreetype = {
"windows-x86-ri": {
configure_args: "--with-freetype-license="
+ input.get("freetype", "install_path")
+ "/freetype-2.7.1-v120-x86/freetype.md"
}
};
profiles = concatObjects(profiles, profilesRiFreetype);
// Generate the missing platform attributes
profiles = generatePlatformAttributes(profiles);
profiles = generateDefaultMakeTargetsConfigureArg(common, profiles);

View File

@ -428,3 +428,5 @@ c62e5964cfcf144d8f72e9ba69757897785349a9 jdk-9+171
95ed14547ca9246baed34f90ef3ca13217538a8c jdk-9+172
8ef8a0f1c4dfea17e10125e1f885920538e63085 jdk-10+11
534ba4f8cfcf12accc5b9adb943103f2ff79fe16 jdk-9+173
3615768c12904e29bb2ec1b506cd4633cd8a9ced jdk-9+174
00ae6307d78bac49883ddc85d687aa88c49f3971 jdk-10+12

View File

@ -588,3 +588,5 @@ c6cd3ec8d46b034e57c86399380ffcf7f25706e4 jdk-10+10
1ae9e84f68b359420d2d153ecfe5ee2903e33a2e jdk-9+172
7f14e550f1e8abea41c223e5fdad2261e99ba929 jdk-10+11
e64b1cb48d6e7703928a9d1da106fc27f8cb65fd jdk-9+173
944791f8160185bffa13fbb821fc09b6198f1f25 jdk-9+174
070aa7a2eb14c4645f7eb31384cba0a2ba72a4b5 jdk-10+12

View File

@ -26,6 +26,15 @@
/**
* Defines the implementation of the HotSpot Serviceability Agent.
*
* <p> This module includes the <em>{@index jhsdb jhsdb tool}</em> tool to
* attach to a running Java Virtual Machine (JVM) or launch a postmortem
* debugger to analyze the content of a core-dump from a crashed JVM.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:</dt>
* <dd> {@extLink jhsdb_tool_reference jhsdb}</dd>
* </dl>
*
* @moduleGraph
* @since 9
*/

View File

@ -251,7 +251,13 @@ public class StandardGraphBuilderPlugins {
for (JavaKind kind : new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object}) {
Class<?> javaClass = kind == JavaKind.Object ? Object.class : kind.toJavaClass();
r.register5("compareAndSwap" + kind.name(), Receiver.class, Object.class, long.class, javaClass, javaClass, new InvocationPlugin() {
String casName;
if (Java8OrEarlier) {
casName = "compareAndSwap";
} else {
casName = "compareAndSet";
}
r.register5(casName + kind.name(), Receiver.class, Object.class, long.class, javaClass, javaClass, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode expected, ValueNode x) {
// Emits a null-check for the otherwise unused receiver

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -1095,8 +1095,11 @@ inline intptr_t bitfield(intptr_t x, int start_bit_no, int field_length) {
#undef min
#endif
#define max(a,b) Do_not_use_max_use_MAX2_instead
#define min(a,b) Do_not_use_min_use_MIN2_instead
// The following defines serve the purpose of preventing use of accidentally
// included min max macros from compiling, while continuing to allow innocent
// min and max identifiers in the code to compile as intended.
#define max max
#define min min
// It is necessary to use templates here. Having normal overloaded
// functions does not work because it is necessary to provide both 32-

View File

@ -773,221 +773,221 @@ public class TestIntUnsafeCAS {
static void test_ci(int[] a) {
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -1, -123);
unsafe.compareAndSetInt(a, byte_offset(i), -1, -123);
}
}
static void test_vi(int[] a, int b, int old) {
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), old, b);
unsafe.compareAndSetInt(a, byte_offset(i), old, b);
}
}
static void test_cp(int[] a, int[] b) {
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]);
unsafe.compareAndSetInt(a, byte_offset(i), -123, b[i]);
}
}
static void test_2ci(int[] a, int[] b) {
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(i), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i), 123, -103);
}
}
static void test_2vi(int[] a, int[] b, int c, int d) {
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(i), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i), -123, c);
unsafe.compareAndSetInt(b, byte_offset(i), -103, d);
}
}
static void test_ci_neg(int[] a, int old) {
for (int i = ARRLEN-1; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), old, -123);
unsafe.compareAndSetInt(a, byte_offset(i), old, -123);
}
}
static void test_vi_neg(int[] a, int b, int old) {
for (int i = ARRLEN-1; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), old, b);
unsafe.compareAndSetInt(a, byte_offset(i), old, b);
}
}
static void test_cp_neg(int[] a, int[] b) {
for (int i = ARRLEN-1; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[i]);
unsafe.compareAndSetInt(a, byte_offset(i), -123, b[i]);
}
}
static void test_2ci_neg(int[] a, int[] b) {
for (int i = ARRLEN-1; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(i), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i), 123, -103);
}
}
static void test_2vi_neg(int[] a, int[] b, int c, int d) {
for (int i = ARRLEN-1; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(i), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i), -123, c);
unsafe.compareAndSetInt(b, byte_offset(i), -103, d);
}
}
static void test_ci_oppos(int[] a, int old) {
int limit = ARRLEN-1;
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, -123);
unsafe.compareAndSetInt(a, byte_offset(limit-i), old, -123);
}
}
static void test_vi_oppos(int[] a, int b, int old) {
int limit = ARRLEN-1;
for (int i = limit; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(limit-i), old, b);
unsafe.compareAndSetInt(a, byte_offset(limit-i), old, b);
}
}
static void test_cp_oppos(int[] a, int[] b) {
int limit = ARRLEN-1;
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, b[limit-i]);
unsafe.compareAndSetInt(a, byte_offset(i), -123, b[limit-i]);
}
}
static void test_2ci_oppos(int[] a, int[] b) {
int limit = ARRLEN-1;
for (int i = 0; i < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(limit-i), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(limit-i), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i), 123, -103);
}
}
static void test_2vi_oppos(int[] a, int[] b, int c, int d) {
int limit = ARRLEN-1;
for (int i = limit; i >= 0; i-=1) {
unsafe.compareAndSwapInt(a, byte_offset(i), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(limit-i), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i), -123, c);
unsafe.compareAndSetInt(b, byte_offset(limit-i), -103, d);
}
}
static void test_ci_off(int[] a, int old) {
for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, -123);
unsafe.compareAndSetInt(a, byte_offset(i+OFFSET), old, -123);
}
}
static void test_vi_off(int[] a, int b, int old) {
for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), old, b);
unsafe.compareAndSetInt(a, byte_offset(i+OFFSET), old, b);
}
}
static void test_cp_off(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, b[i+OFFSET]);
unsafe.compareAndSetInt(a, byte_offset(i+OFFSET), -123, b[i+OFFSET]);
}
}
static void test_2ci_off(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(i+OFFSET), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i+OFFSET), 123, -103);
}
}
static void test_2vi_off(int[] a, int[] b, int c, int d) {
for (int i = 0; i < ARRLEN-OFFSET; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+OFFSET), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(i+OFFSET), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i+OFFSET), -123, c);
unsafe.compareAndSetInt(b, byte_offset(i+OFFSET), -103, d);
}
}
static void test_ci_inv(int[] a, int k, int old) {
for (int i = 0; i < ARRLEN-k; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+k), old, -123);
unsafe.compareAndSetInt(a, byte_offset(i+k), old, -123);
}
}
static void test_vi_inv(int[] a, int b, int k, int old) {
for (int i = 0; i < ARRLEN-k; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+k), old, b);
unsafe.compareAndSetInt(a, byte_offset(i+k), old, b);
}
}
static void test_cp_inv(int[] a, int[] b, int k) {
for (int i = 0; i < ARRLEN-k; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, b[i+k]);
unsafe.compareAndSetInt(a, byte_offset(i+k), -123, b[i+k]);
}
}
static void test_2ci_inv(int[] a, int[] b, int k) {
for (int i = 0; i < ARRLEN-k; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+k), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i+k), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(i+k), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i+k), 123, -103);
}
}
static void test_2vi_inv(int[] a, int[] b, int c, int d, int k) {
for (int i = 0; i < ARRLEN-k; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+k), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(i+k), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i+k), -123, c);
unsafe.compareAndSetInt(b, byte_offset(i+k), -103, d);
}
}
static void test_ci_scl(int[] a, int old) {
for (int i = 0; i*SCALE < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, -123);
unsafe.compareAndSetInt(a, byte_offset(i*SCALE), old, -123);
}
}
static void test_vi_scl(int[] a, int b, int old) {
for (int i = 0; i*SCALE < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), old, b);
unsafe.compareAndSetInt(a, byte_offset(i*SCALE), old, b);
}
}
static void test_cp_scl(int[] a, int[] b) {
for (int i = 0; i*SCALE < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, b[i*SCALE]);
unsafe.compareAndSetInt(a, byte_offset(i*SCALE), -123, b[i*SCALE]);
}
}
static void test_2ci_scl(int[] a, int[] b) {
for (int i = 0; i*SCALE < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), 123, -123);
unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), 123, -103);
unsafe.compareAndSetInt(a, byte_offset(i*SCALE), 123, -123);
unsafe.compareAndSetInt(b, byte_offset(i*SCALE), 123, -103);
}
}
static void test_2vi_scl(int[] a, int[] b, int c, int d) {
for (int i = 0; i*SCALE < ARRLEN; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i*SCALE), -123, c);
unsafe.compareAndSwapInt(b, byte_offset(i*SCALE), -103, d);
unsafe.compareAndSetInt(a, byte_offset(i*SCALE), -123, c);
unsafe.compareAndSetInt(b, byte_offset(i*SCALE), -103, d);
}
}
static void test_cp_alndst(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, b[i]);
unsafe.compareAndSetInt(a, byte_offset(i+ALIGN_OFF), -1, b[i]);
}
}
static void test_cp_alnsrc(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
int old = unsafe.getIntVolatile(a, byte_offset(i));
unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+ALIGN_OFF]);
unsafe.compareAndSetInt(a, byte_offset(i), old, b[i+ALIGN_OFF]);
}
}
static void test_2ci_aln(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+ALIGN_OFF), -1, -123);
unsafe.compareAndSetInt(a, byte_offset(i+ALIGN_OFF), -1, -123);
int old = unsafe.getIntVolatile(b, byte_offset(i));
unsafe.compareAndSwapInt(b, byte_offset(i), old, -103);
unsafe.compareAndSetInt(b, byte_offset(i), old, -103);
}
}
static void test_2vi_aln(int[] a, int[] b, int c, int d) {
for (int i = 0; i < ARRLEN-ALIGN_OFF; i+=1) {
int old = unsafe.getIntVolatile(a, byte_offset(i));
unsafe.compareAndSwapInt(a, byte_offset(i), old, c);
unsafe.compareAndSetInt(a, byte_offset(i), old, c);
old = unsafe.getIntVolatile(b, byte_offset(i+ALIGN_OFF));
unsafe.compareAndSwapInt(b, byte_offset(i+ALIGN_OFF), old, d);
unsafe.compareAndSetInt(b, byte_offset(i+ALIGN_OFF), old, d);
}
}
static void test_cp_unalndst(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, b[i]);
unsafe.compareAndSetInt(a, byte_offset(i+UNALIGN_OFF), -1, b[i]);
}
}
static void test_cp_unalnsrc(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
int old = unsafe.getIntVolatile(a, byte_offset(i));
unsafe.compareAndSwapInt(a, byte_offset(i), old, b[i+UNALIGN_OFF]);
unsafe.compareAndSetInt(a, byte_offset(i), old, b[i+UNALIGN_OFF]);
}
}
static void test_2ci_unaln(int[] a, int[] b) {
for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
unsafe.compareAndSwapInt(a, byte_offset(i+UNALIGN_OFF), -1, -123);
unsafe.compareAndSetInt(a, byte_offset(i+UNALIGN_OFF), -1, -123);
int old = unsafe.getIntVolatile(b, byte_offset(i));
unsafe.compareAndSwapInt(b, byte_offset(i), old, -103);
unsafe.compareAndSetInt(b, byte_offset(i), old, -103);
}
}
static void test_2vi_unaln(int[] a, int[] b, int c, int d) {
for (int i = 0; i < ARRLEN-UNALIGN_OFF; i+=1) {
int old = unsafe.getIntVolatile(a, byte_offset(i));
unsafe.compareAndSwapInt(a, byte_offset(i), old, c);
unsafe.compareAndSetInt(a, byte_offset(i), old, c);
old = unsafe.getIntVolatile(b, byte_offset(i+UNALIGN_OFF));
unsafe.compareAndSwapInt(b, byte_offset(i+UNALIGN_OFF), old, d);
unsafe.compareAndSetInt(b, byte_offset(i+UNALIGN_OFF), old, d);
}
}

View File

@ -64,7 +64,7 @@ public class UnsafeAccess {
static Object helperUnsafeLoadStore(Object o, boolean isObjArray) {
if (isObjArray) {
Object o1 = U.getObject(o, off);
U.compareAndSwapObject(o, off, o1, new Object());
U.compareAndSetObject(o, off, o1, new Object());
}
return o;
}

View File

@ -428,3 +428,5 @@ bd4b2c8835f35760a51c1475b03a16cc20c62973 jdk-10+10
eedb6e54c8bd6197ecba5fc0d8568bac8ae852dd jdk-9+172
95bab8bf9201ae8bfdf28e164bf33b78e49477e7 jdk-10+11
9788347e0629d0cb3a0e55a903494ff741d4fa15 jdk-9+173
b9c0b105002272d7414c8b34af9aded151f9cad6 jdk-9+174
ff293e39e83366c40a5687dacd1ccb2305ed2c1e jdk-10+12

View File

@ -1,596 +0,0 @@
/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xerces.internal.util;
import java.io.IOException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;
import org.w3c.dom.ls.LSInput;
import org.w3c.dom.ls.LSResourceResolver;
import javax.xml.parsers.SAXParserFactory;
import com.sun.org.apache.xerces.internal.dom.DOMInputImpl;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
/**
* <p>The catalog resolver handles the resolution of external
* identifiers and URI references through XML catalogs. This
* component supports XML catalogs defined by the
* <a href="http://www.oasis-open.org/committees/entity/spec.html">
* OASIS XML Catalogs Specification</a>. It encapsulates the
* <a href="http://xml.apache.org/commons/">XML Commons</a> resolver.
* An instance of this class may be registered on the parser
* as a SAX entity resolver, as a DOM LSResourceResolver or
* as an XNI entity resolver by setting the property
* (http://apache.org/xml/properties/internal/entity-resolver).</p>
*
* <p>It is intended that this class may be used standalone to perform
* catalog resolution outside of a parsing context. It may be shared
* between several parsers and the application.</p>
*
* @deprecated This class and the JDK internal Catalog API in package
* {@code com.sun.org.apache.xml.internal.resolver}
* is encapsulated in JDK 9. The entire implementation under the package is now
* deprecated and subject to removal in a future release. Users of the API should
* migrate to the {@linkplain javax.xml.catalog new public API}.
* <p>
* The new Catalog API is supported throughout the JDK XML Processors, which allows
* the use of Catalog by simply setting a path to a Catalog file as a property.
*
* @author Michael Glavassevich, IBM
*
*/
@Deprecated(since="9", forRemoval=true)
public class XMLCatalogResolver
implements XMLEntityResolver, EntityResolver2, LSResourceResolver {
/** Internal catalog manager for Apache catalogs. **/
private CatalogManager fResolverCatalogManager = null;
/** Internal catalog structure. **/
private Catalog fCatalog = null;
/** An array of catalog URIs. **/
private String [] fCatalogsList = null;
/**
* Indicates whether the list of catalogs has
* changed since it was processed.
*/
private boolean fCatalogsChanged = true;
/** Application specified prefer public setting. **/
private boolean fPreferPublic = true;
/**
* Indicates whether the application desires that
* the parser or some other component performing catalog
* resolution should use the literal system identifier
* instead of the expanded system identifier.
*/
private boolean fUseLiteralSystemId = true;
/**
* <p>Constructs a catalog resolver with a default configuration.</p>
*/
public XMLCatalogResolver () {
this(null, true);
}
/**
* <p>Constructs a catalog resolver with the given
* list of entry files.</p>
*
* @param catalogs an ordered array list of absolute URIs
*/
public XMLCatalogResolver (String [] catalogs) {
this(catalogs, true);
}
/**
* <p>Constructs a catalog resolver with the given
* list of entry files and the preference for whether
* system or public matches are preferred.</p>
*
* @param catalogs an ordered array list of absolute URIs
* @param preferPublic the prefer public setting
*/
public XMLCatalogResolver (String [] catalogs, boolean preferPublic) {
init(catalogs, preferPublic);
}
/**
* <p>Returns the initial list of catalog entry files.</p>
*
* @return the initial list of catalog entry files
*/
public final synchronized String [] getCatalogList () {
return (fCatalogsList != null)
? (String[]) fCatalogsList.clone() : null;
}
/**
* <p>Sets the initial list of catalog entry files.
* If there were any catalog mappings cached from
* the previous list they will be replaced by catalog
* mappings from the new list the next time the catalog
* is queried.</p>
*
* @param catalogs an ordered array list of absolute URIs
*/
public final synchronized void setCatalogList (String [] catalogs) {
fCatalogsChanged = true;
fCatalogsList = (catalogs != null)
? (String[]) catalogs.clone() : null;
}
/**
* <p>Forces the cache of catalog mappings to be cleared.</p>
*/
public final synchronized void clear () {
fCatalog = null;
}
/**
* <p>Returns the preference for whether system or public
* matches are preferred. This is used in the absence
* of any occurence of the <code>prefer</code> attribute
* on the <code>catalog</code> entry of a catalog. If this
* property has not yet been explicitly set its value is
* <code>true</code>.</p>
*
* @return the prefer public setting
*/
public final boolean getPreferPublic () {
return fPreferPublic;
}
/**
* <p>Sets the preference for whether system or public
* matches are preferred. This is used in the absence
* of any occurence of the <code>prefer</code> attribute
* on the <code>catalog</code> entry of a catalog.</p>
*
* @param preferPublic the prefer public setting
*/
public final void setPreferPublic (boolean preferPublic) {
fPreferPublic = preferPublic;
fResolverCatalogManager.setPreferPublic(preferPublic);
}
/**
* <p>Returns the preference for whether the literal system
* identifier should be used when resolving system
* identifiers when both it and the expanded system
* identifier are available. If this property has not yet
* been explicitly set its value is <code>true</code>.</p>
*
* @return the preference for using literal system identifers
* for catalog resolution
*
* @see #setUseLiteralSystemId
*/
public final boolean getUseLiteralSystemId () {
return fUseLiteralSystemId;
}
/**
* <p>Sets the preference for whether the literal system
* identifier should be used when resolving system
* identifiers when both it and the expanded system
* identifier are available.</p>
*
* <p>The literal system identifier is the URI as it was
* provided before absolutization. It may be embedded within
* an entity. It may be provided externally or it may be the
* result of redirection. For example, redirection may
* have come from the protocol level through HTTP or from
* an application's entity resolver.</p>
*
* <p>The expanded system identifier is an absolute URI
* which is the result of resolving the literal system
* identifier against a base URI.</p>
*
* @param useLiteralSystemId the preference for using
* literal system identifers for catalog resolution
*/
public final void setUseLiteralSystemId (boolean useLiteralSystemId) {
fUseLiteralSystemId = useLiteralSystemId;
}
/**
* <p>Resolves an external entity. If the entity cannot be
* resolved, this method should return <code>null</code>. This
* method returns an input source if an entry was found in the
* catalog for the given external identifier. It should be
* overrided if other behaviour is required.</p>
*
* @param publicId the public identifier, or <code>null</code> if none was supplied
* @param systemId the system identifier
*
* @throws SAXException any SAX exception, possibly wrapping another exception
* @throws IOException thrown if some i/o error occurs
*/
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
String resolvedId = null;
if (publicId != null && systemId != null) {
resolvedId = resolvePublic(publicId, systemId);
}
else if (systemId != null) {
resolvedId = resolveSystem(systemId);
}
if (resolvedId != null) {
InputSource source = new InputSource(resolvedId);
source.setPublicId(publicId);
return source;
}
return null;
}
/**
* <p>Resolves an external entity. If the entity cannot be
* resolved, this method should return <code>null</code>. This
* method returns an input source if an entry was found in the
* catalog for the given external identifier. It should be
* overrided if other behaviour is required.</p>
*
* @param name the identifier of the external entity
* @param publicId the public identifier, or <code>null</code> if none was supplied
* @param baseURI the URI with respect to which relative systemIDs are interpreted.
* @param systemId the system identifier
*
* @throws SAXException any SAX exception, possibly wrapping another exception
* @throws IOException thrown if some i/o error occurs
*/
public InputSource resolveEntity(String name, String publicId,
String baseURI, String systemId) throws SAXException, IOException {
String resolvedId = null;
if (!getUseLiteralSystemId() && baseURI != null) {
// Attempt to resolve the system identifier against the base URI.
try {
URI uri = new URI(new URI(baseURI), systemId);
systemId = uri.toString();
}
// Ignore the exception. Fallback to the literal system identifier.
catch (URI.MalformedURIException ex) {}
}
if (publicId != null && systemId != null) {
resolvedId = resolvePublic(publicId, systemId);
}
else if (systemId != null) {
resolvedId = resolveSystem(systemId);
}
if (resolvedId != null) {
InputSource source = new InputSource(resolvedId);
source.setPublicId(publicId);
return source;
}
return null;
}
/**
* <p>Locates an external subset for documents which do not explicitly
* provide one. This method always returns <code>null</code>. It
* should be overrided if other behaviour is required.</p>
*
* @param name the identifier of the document root element
* @param baseURI the document's base URI
*
* @throws SAXException any SAX exception, possibly wrapping another exception
* @throws IOException thrown if some i/o error occurs
*/
public InputSource getExternalSubset(String name, String baseURI)
throws SAXException, IOException {
return null;
}
/**
* <p>Resolves a resource using the catalog. This method interprets that
* the namespace URI corresponds to uri entries in the catalog.
* Where both a namespace and an external identifier exist, the namespace
* takes precedence.</p>
*
* @param type the type of the resource being resolved
* @param namespaceURI the namespace of the resource being resolved,
* or <code>null</code> if none was supplied
* @param publicId the public identifier of the resource being resolved,
* or <code>null</code> if none was supplied
* @param systemId the system identifier of the resource being resolved,
* or <code>null</code> if none was supplied
* @param baseURI the absolute base URI of the resource being parsed,
* or <code>null</code> if there is no base URI
*/
public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
String resolvedId = null;
try {
// The namespace is useful for resolving namespace aware
// grammars such as XML schema. Let it take precedence over
// the external identifier if one exists.
if (namespaceURI != null) {
resolvedId = resolveURI(namespaceURI);
}
if (!getUseLiteralSystemId() && baseURI != null) {
// Attempt to resolve the system identifier against the base URI.
try {
URI uri = new URI(new URI(baseURI), systemId);
systemId = uri.toString();
}
// Ignore the exception. Fallback to the literal system identifier.
catch (URI.MalformedURIException ex) {}
}
// Resolve against an external identifier if one exists. This
// is useful for resolving DTD external subsets and other
// external entities. For XML schemas if there was no namespace
// mapping we might be able to resolve a system identifier
// specified as a location hint.
if (resolvedId == null) {
if (publicId != null && systemId != null) {
resolvedId = resolvePublic(publicId, systemId);
}
else if (systemId != null) {
resolvedId = resolveSystem(systemId);
}
}
}
// Ignore IOException. It cannot be thrown from this method.
catch (IOException ex) {}
if (resolvedId != null) {
return new DOMInputImpl(publicId, resolvedId, baseURI);
}
return null;
}
/**
* <p>Resolves an external entity. If the entity cannot be
* resolved, this method should return <code>null</code>. This
* method only calls <code>resolveIdentifier</code> and returns
* an input source if an entry was found in the catalog. It
* should be overrided if other behaviour is required.</p>
*
* @param resourceIdentifier location of the XML resource to resolve
*
* @throws XNIException thrown on general error
* @throws IOException thrown if some i/o error occurs
*/
public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier)
throws XNIException, IOException {
String resolvedId = resolveIdentifier(resourceIdentifier);
if (resolvedId != null) {
return new XMLInputSource(resourceIdentifier.getPublicId(),
resolvedId, resourceIdentifier.getBaseSystemId(), false);
}
return null;
}
/**
* <p>Resolves an identifier using the catalog. This method interprets that
* the namespace of the identifier corresponds to uri entries in the catalog.
* Where both a namespace and an external identifier exist, the namespace
* takes precedence.</p>
*
* @param resourceIdentifier the identifier to resolve
*
* @throws XNIException thrown on general error
* @throws IOException thrown if some i/o error occurs
*/
public String resolveIdentifier(XMLResourceIdentifier resourceIdentifier)
throws IOException, XNIException {
String resolvedId = null;
// The namespace is useful for resolving namespace aware
// grammars such as XML schema. Let it take precedence over
// the external identifier if one exists.
String namespace = resourceIdentifier.getNamespace();
if (namespace != null) {
resolvedId = resolveURI(namespace);
}
// Resolve against an external identifier if one exists. This
// is useful for resolving DTD external subsets and other
// external entities. For XML schemas if there was no namespace
// mapping we might be able to resolve a system identifier
// specified as a location hint.
if (resolvedId == null) {
String publicId = resourceIdentifier.getPublicId();
String systemId = getUseLiteralSystemId()
? resourceIdentifier.getLiteralSystemId()
: resourceIdentifier.getExpandedSystemId();
if (publicId != null && systemId != null) {
resolvedId = resolvePublic(publicId, systemId);
}
else if (systemId != null) {
resolvedId = resolveSystem(systemId);
}
}
return resolvedId;
}
/**
* <p>Returns the URI mapping in the catalog for the given
* external identifier or <code>null</code> if no mapping
* exists. If the system identifier is an URN in the
* <code>publicid</code> namespace it is converted into
* a public identifier by URN "unwrapping" as specified
* in the XML Catalogs specification.</p>
*
* @param systemId the system identifier to locate in the catalog
*
* @return the mapped URI or <code>null</code> if no mapping
* was found in the catalog
*
* @throws IOException if an i/o error occurred while reading
* the catalog
*/
public final synchronized String resolveSystem (String systemId)
throws IOException {
if (fCatalogsChanged) {
parseCatalogs();
fCatalogsChanged = false;
}
return (fCatalog != null)
? fCatalog.resolveSystem(systemId) : null;
}
/**
* <p>Returns the URI mapping in the catalog for the given
* external identifier or <code>null</code> if no mapping
* exists. Public identifiers are normalized before
* comparison.</p>
*
* @param publicId the public identifier to locate in the catalog
* @param systemId the system identifier to locate in the catalog
*
* @return the mapped URI or <code>null</code> if no mapping
* was found in the catalog
*
* @throws IOException if an i/o error occurred while reading
* the catalog
*/
public final synchronized String resolvePublic (String publicId, String systemId)
throws IOException {
if (fCatalogsChanged) {
parseCatalogs();
fCatalogsChanged = false;
}
return (fCatalog != null)
? fCatalog.resolvePublic(publicId, systemId) : null;
}
/**
* <p>Returns the URI mapping in the catalog for the given URI
* reference or <code>null</code> if no mapping exists.
* URI comparison is case sensitive. If the URI reference
* is an URN in the <code>publicid</code> namespace
* it is converted into a public identifier by URN "unwrapping"
* as specified in the XML Catalogs specification and then
* resolution is performed following the semantics of
* external identifier resolution.</p>
*
* @param uri the URI to locate in the catalog
*
* @return the mapped URI or <code>null</code> if no mapping
* was found in the catalog
*
* @throws IOException if an i/o error occurred while reading
* the catalog
*/
public final synchronized String resolveURI (String uri)
throws IOException {
if (fCatalogsChanged) {
parseCatalogs();
fCatalogsChanged = false;
}
return (fCatalog != null)
? fCatalog.resolveURI(uri) : null;
}
/**
* Initialization. Create a CatalogManager and set all
* the properties upfront. This prevents JVM wide system properties
* or a property file somewhere in the environment from affecting
* the behaviour of this catalog resolver.
*/
private void init (String [] catalogs, boolean preferPublic) {
fCatalogsList = (catalogs != null) ? (String[]) catalogs.clone() : null;
fPreferPublic = preferPublic;
fResolverCatalogManager = new CatalogManager();
fResolverCatalogManager.setAllowOasisXMLCatalogPI(false);
fResolverCatalogManager.setCatalogClassName("com.sun.org.apache.xml.internal.resolver.Catalog");
fResolverCatalogManager.setCatalogFiles("");
fResolverCatalogManager.setIgnoreMissingProperties(true);
fResolverCatalogManager.setPreferPublic(fPreferPublic);
fResolverCatalogManager.setRelativeCatalogs(false);
fResolverCatalogManager.setUseStaticCatalog(false);
fResolverCatalogManager.setVerbosity(0);
}
/**
* Instruct the <code>Catalog</code> to parse each of the
* catalogs in the list. Only the first catalog will actually be
* parsed immediately. The others will be queued and read if
* they are needed later.
*/
private void parseCatalogs () throws IOException {
if (fCatalogsList != null) {
fCatalog = new Catalog(fResolverCatalogManager);
attachReaderToCatalog(fCatalog);
for (int i = 0; i < fCatalogsList.length; ++i) {
String catalog = fCatalogsList[i];
if (catalog != null && catalog.length() > 0) {
fCatalog.parseCatalog(catalog);
}
}
}
else {
fCatalog = null;
}
}
/**
* Attaches the reader to the catalog.
*/
private void attachReaderToCatalog (Catalog catalog) {
SAXParserFactory spf = new SAXParserFactoryImpl();
spf.setNamespaceAware(true);
spf.setValidating(false);
SAXCatalogReader saxReader = new SAXCatalogReader(spf);
saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName, "catalog",
"com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader");
catalog.addReader("application/xml", saxReader);
}
}

View File

@ -1,251 +0,0 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver;
import java.util.Map;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Represents a Catalog entry.
*
* <p>Instances of this class represent individual entries
* in a Catalog.</p>
*
* <p>Each catalog entry has a unique name and is associated with
* an arbitrary number of arguments (all strings). For example, the
* TR9401 catalog entry "PUBLIC" has two arguments, a public identifier
* and a system identifier. Each entry has a unique numeric type,
* assigned automatically when the entry type is created.</p>
*
* <p>The number and type of catalog entries is maintained
* <em>statically</em>. Catalog classes, or their subclasses, can add
* new entry types, but all Catalog objects share the same global pool
* of types.</p>
*
* <p>Initially there are no valid entries.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class CatalogEntry {
/** The nextEntry is the ordinal number of the next entry type. */
static AtomicInteger nextEntry = new AtomicInteger(0);
/**
* The entryTypes vector maps catalog entry names
* (e.g., 'BASE' or 'SYSTEM') to their type (1, 2, etc.).
* Names are case sensitive.
*/
static final Map<String, Integer> entryTypes = new ConcurrentHashMap<>();
/** The entryTypes vector maps catalog entry types to the
number of arguments they're required to have. */
static final Vector entryArgs = new Vector();
/**
* Adds a new catalog entry type.
*
* @param name The name of the catalog entry type. This must be
* unique among all types and is case-sensitive. (Adding a duplicate
* name effectively replaces the old type with the new type.)
* @param numArgs The number of arguments that this entry type
* is required to have. There is no provision for variable numbers
* of arguments.
* @return The type for the new entry.
*/
static int addEntryType(String name, int numArgs) {
final int index = nextEntry.getAndIncrement();
entryTypes.put(name, index);
entryArgs.add(index, numArgs);
return index;
}
/**
* Lookup an entry type
*
* @param name The name of the catalog entry type.
* @return The type of the catalog entry with the specified name.
* @throws InvalidCatalogEntryTypeException if no entry has the
* specified name.
*/
public static int getEntryType(String name)
throws CatalogException {
if (!entryTypes.containsKey(name)) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
Integer iType = entryTypes.get(name);
if (iType == null) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
return iType;
}
/**
* Find out how many arguments an entry is required to have.
*
* @param name The name of the catalog entry type.
* @return The number of arguments that entry type is required to have.
* @throws InvalidCatalogEntryTypeException if no entry has the
* specified name.
*/
public static int getEntryArgCount(String name)
throws CatalogException {
return getEntryArgCount(getEntryType(name));
}
/**
* Find out how many arguments an entry is required to have.
*
* @param type A valid catalog entry type.
* @return The number of arguments that entry type is required to have.
* @throws InvalidCatalogEntryTypeException if the type is invalid.
*/
public static int getEntryArgCount(int type)
throws CatalogException {
try {
Integer iArgs = (Integer) entryArgs.get(type);
return iArgs.intValue();
} catch (ArrayIndexOutOfBoundsException e) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
}
/** The entry type of this entry */
protected int entryType = 0;
/** The arguments associated with this entry */
protected Vector args = null;
/**
* Null constructor; something for subclasses to call.
*/
public CatalogEntry() {}
/**
* Construct a catalog entry of the specified type.
*
* @param name The name of the entry type
* @param args A String Vector of arguments
* @throws InvalidCatalogEntryTypeException if no such entry type
* exists.
* @throws InvalidCatalogEntryException if the wrong number of arguments
* is passed.
*/
public CatalogEntry(String name, Vector args)
throws CatalogException {
Integer iType = entryTypes.get(name);
if (iType == null) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
int type = iType;
try {
Integer iArgs = (Integer) entryArgs.get(type);
if (iArgs.intValue() != args.size()) {
throw new CatalogException(CatalogException.INVALID_ENTRY);
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
entryType = type;
this.args = args;
}
/**
* Construct a catalog entry of the specified type.
*
* @param type The entry type
* @param args A String Vector of arguments
* @throws InvalidCatalogEntryTypeException if no such entry type
* exists.
* @throws InvalidCatalogEntryException if the wrong number of arguments
* is passed.
*/
public CatalogEntry(int type, Vector args)
throws CatalogException {
try {
Integer iArgs = (Integer) entryArgs.get(type);
if (iArgs.intValue() != args.size()) {
throw new CatalogException(CatalogException.INVALID_ENTRY);
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new CatalogException(CatalogException.INVALID_ENTRY_TYPE);
}
entryType = type;
this.args = args;
}
/**
* Get the entry type.
*
* @return The entry type of the CatalogEntry
*/
public int getEntryType() {
return entryType;
}
/**
* Get an entry argument.
*
* @param argNum The argument number (arguments are numbered from 0).
* @return The specified argument or null if an invalid argNum is
* provided.
*/
public String getEntryArg(int argNum) {
try {
String arg = (String) args.get(argNum);
return arg;
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
/**
* Set an entry argument.
*
* <p>Catalogs sometimes need to adjust the catlog entry parameters,
* for example to make a relative URI absolute with respect to the
* current base URI. But in general, this function should only be
* called shortly after object creation to do some sort of cleanup.
* Catalog entries should not mutate over time.</p>
*
* @param argNum The argument number (arguments are numbered from 0).
* @throws ArrayIndexOutOfBoundsException if an invalid argument
* number is provided.
*/
public void setEntryArg(int argNum, String newspec)
throws ArrayIndexOutOfBoundsException {
args.set(argNum, newspec);
}
}

View File

@ -1,165 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver;
/**
* Signal Catalog exception.
*
* <p>This exception is thrown if an error occurs loading a
* catalog file.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class CatalogException extends Exception {
private static final long serialVersionUID = 4007157171817798450L;
/** A wrapper around another exception */
public static final int WRAPPER = 1;
/** An invalid entry */
public static final int INVALID_ENTRY = 2;
/** An invalid entry type */
public static final int INVALID_ENTRY_TYPE = 3;
/** Could not instantiate an XML parser */
public static final int NO_XML_PARSER = 4;
/** Unknown XML format */
public static final int UNKNOWN_FORMAT = 5;
/** Unparseable XML catalog (not XML)*/
public static final int UNPARSEABLE = 6;
/** XML but parse failed */
public static final int PARSE_FAILED = 7;
/** Text catalog ended in mid-comment */
public static final int UNENDED_COMMENT = 8;
/**
* The embedded exception if tunnelling, or null.
*/
private final Exception exception;
private final int exceptionType;
/**
* Create a new CatalogException.
*
* @param type The exception type
* @param message The error or warning message.
*/
public CatalogException (int type, String message) {
super(message);
this.exceptionType = type;
this.exception = null;
}
/**
* Create a new CatalogException.
*
* @param type The exception type
*/
public CatalogException (int type) {
super("Catalog Exception " + type);
this.exceptionType = type;
this.exception = null;
}
/**
* Create a new CatalogException wrapping an existing exception.
*
* <p>The existing exception will be embedded in the new
* one, and its message will become the default message for
* the CatalogException.</p>
*
* @param e The exception to be wrapped in a CatalogException.
*/
public CatalogException (Exception e) {
super();
this.exceptionType = WRAPPER;
this.exception = e;
}
/**
* Create a new CatalogException from an existing exception.
*
* <p>The existing exception will be embedded in the new
* one, but the new exception will have its own message.</p>
*
* @param message The detail message.
* @param e The exception to be wrapped in a CatalogException.
*/
public CatalogException (String message, Exception e) {
super(message);
this.exceptionType = WRAPPER;
this.exception = e;
}
/**
* Return a detail message for this exception.
*
* <p>If there is an embedded exception, and if the CatalogException
* has no detail message of its own, this method will return
* the detail message from the embedded exception.</p>
*
* @return The error or warning message.
*/
public String getMessage ()
{
String message = super.getMessage();
if (message == null && exception != null) {
return exception.getMessage();
} else {
return message;
}
}
/**
* Return the embedded exception, if any.
*
* @return The embedded exception, or null if there is none.
*/
public Exception getException ()
{
return exception;
}
/**
* Return the exception type
*
* @return The exception type
*/
public int getExceptionType ()
{
return exceptionType;
}
/**
* Override toString to pick up any embedded exception.
*
* @return A string representation of this exception.
*/
public String toString ()
{
if (exception != null) {
return exception.toString();
} else {
return super.toString();
}
}
}

View File

@ -1,870 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver;
import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
import com.sun.org.apache.xml.internal.resolver.helpers.BootstrapResolver;
import com.sun.org.apache.xml.internal.resolver.helpers.Debug;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.MissingResourceException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.Vector;
import sun.reflect.misc.ReflectUtil;
/**
* CatalogManager provides an interface to the catalog properties.
*
* <p>Properties can come from two places: from system properties or
* from a <i>CatalogManager.properties</i> file. This class provides a transparent
* interface to both, with system properties preferred over property file values.</p>
*
* <p>The following table summarizes the properties:</p>
*
* <table border="1">
* <thead>
* <tr>
* <td>System Property</td>
* <td>CatalogManager.properties<br/>Property</td>
* <td>Description</td>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>xml.catalog.ignoreMissing</td>
* <td>&#160;</td>
* <td>If true, a missing <i>CatalogManager.properties</i> file or missing properties
* within that file will not generate warning messages. See also the
* <i>ignoreMissingProperties</i> method.</td>
* </tr>
*
* <tr>
* <td>xml.catalog.files</td>
* <td>catalogs</td>
* <td>The <emph>semicolon-delimited</emph> list of catalog files.</td>
* </tr>
*
* <tr>
* <td>&#160;</td>
* <td>relative-catalogs</td>
* <td>If false, relative catalog URIs are made absolute with respect to the base URI of
* the <i>CatalogManager.properties</i> file. This setting only applies to catalog
* URIs obtained from the <i>catalogs</i> property <emph>in the</emph>
* <i>CatalogManager.properties</i> file</td>
* </tr>
*
* <tr>
* <td>xml.catalog.verbosity</td>
* <td>verbosity</td>
* <td>If non-zero, the Catalog classes will print informative and debugging messages.
* The higher the number, the more messages.</td>
* </tr>
*
* <tr>
* <td>xml.catalog.prefer</td>
* <td>prefer</td>
* <td>Which identifier is preferred, "public" or "system"?</td>
* </tr>
*
* <tr>
* <td>xml.catalog.staticCatalog</td>
* <td>static-catalog</td>
* <td>Should a single catalog be constructed for all parsing, or should a different
* catalog be created for each parser?</td>
* </tr>
*
* <tr>
* <td>xml.catalog.allowPI</td>
* <td>allow-oasis-xml-catalog-pi</td>
* <td>If the source document contains "oasis-xml-catalog" processing instructions,
* should they be used?</td>
* </tr>
*
* <tr>
* <td>xml.catalog.className</td>
* <td>catalog-class-name</td>
* <td>If you're using the convenience classes
* <tt>com.sun.org.apache.xml.internal.resolver.tools.*</tt>), this setting
* allows you to specify an alternate class name to use for the underlying
* catalog.</td>
* </tr>
* </tbody>
* </table>
*
* @see Catalog
* @deprecated The JDK internal Catalog API in package
* {@code com.sun.org.apache.xml.internal.resolver}
* is encapsulated in JDK 9. The entire implementation under the package is now
* deprecated and subject to removal in a future release. Users of the API
* should migrate to the {@linkplain javax.xml.catalog new public API}.
* <p>
* The new Catalog API is supported throughout the JDK XML Processors, which allows
* the use of Catalog by simply setting a path to a Catalog file as a property.
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
@Deprecated(since="9", forRemoval=true)
public class CatalogManager {
private static final String pFiles = "xml.catalog.files";
private static final String pVerbosity = "xml.catalog.verbosity";
private static final String pPrefer = "xml.catalog.prefer";
private static final String pStatic = "xml.catalog.staticCatalog";
private static final String pAllowPI = "xml.catalog.allowPI";
private static final String pClassname = "xml.catalog.className";
private static final String pIgnoreMissing = "xml.catalog.ignoreMissing";
/** A static CatalogManager instance for sharing */
private static final CatalogManager staticManager = new CatalogManager();
/** The bootstrap resolver to use when loading XML Catalogs. */
private BootstrapResolver bResolver = new BootstrapResolver();
/** Flag to ignore missing property files and/or properties */
private boolean ignoreMissingProperties
= (SecuritySupport.getSystemProperty(pIgnoreMissing) != null
|| SecuritySupport.getSystemProperty(pFiles) != null);
/** Holds the resources after they are loaded from the file. */
private ResourceBundle resources;
/** The name of the CatalogManager properties file. */
private String propertyFile = "CatalogManager.properties";
/** The location of the propertyFile */
private URL propertyFileURI = null;
/** Default catalog files list. */
private String defaultCatalogFiles = "./xcatalog";
/** Current catalog files list. */
private String catalogFiles = null;
/** Did the catalogFiles come from the properties file? */
private boolean fromPropertiesFile = false;
/** Default verbosity level if there is no property setting for it. */
private int defaultVerbosity = 1;
/** Current verbosity level. */
private Integer verbosity = null;
/** Default preference setting. */
private boolean defaultPreferPublic = true;
/** Current preference setting. */
private Boolean preferPublic = null;
/** Default setting of the static catalog flag. */
private boolean defaultUseStaticCatalog = true;
/** Current setting of the static catalog flag. */
private Boolean useStaticCatalog = null;
/** The static catalog used by this manager. */
private static volatile Catalog staticCatalog = null;
/** Default setting of the oasisXMLCatalogPI flag. */
private boolean defaultOasisXMLCatalogPI = true;
/** Current setting of the oasisXMLCatalogPI flag. */
private Boolean oasisXMLCatalogPI = null;
/** Default setting of the relativeCatalogs flag. */
private boolean defaultRelativeCatalogs = true;
/** Current setting of the relativeCatalogs flag. */
private Boolean relativeCatalogs = null;
/** Current catalog class name. */
private String catalogClassName = null;
/**
* Indicates whether implementation parts should use
* service loader (or similar).
* Note the default value (false) is the safe option..
*/
private boolean useServicesMechanism;
/** The manager's debug object. Used for printing debugging messages.
*
* <p>This field is public so that objects that have access to this
* CatalogManager can use this debug object.</p>
*/
public Debug debug = null;
/** Constructor. */
public CatalogManager() {
init();
}
/** Constructor that specifies an explicit property file. */
public CatalogManager(String propertyFile) {
this.propertyFile = propertyFile;
init();
}
private void init() {
debug = new Debug();
// Note that we don't setDebug() here; we do that lazily. Either the
// user will set it explicitly, or we'll do it automagically if they
// read from the propertyFile for some other reason. That way, there's
// no attempt to read from the file before the caller has had a chance
// to avoid it.
if (System.getSecurityManager() == null) {
useServicesMechanism = true;
}
// Make sure verbosity is set by xml.catalog.verbosity sysprop
// setting, if defined.
queryVerbosityFromSysProp();
}
/** Set the bootstrap resolver
* @param resolver the bootstrap resolver
*/
public void setBootstrapResolver(BootstrapResolver resolver) {
bResolver = resolver;
}
/** Get the bootstrap resolver
* @return the bootstrap resolver
*/
public BootstrapResolver getBootstrapResolver() {
return bResolver;
}
/** Query system property for verbosity level. */
private void queryVerbosityFromSysProp() {
String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
if (verbStr != null) {
try {
int verb = Integer.parseInt(verbStr.trim());
verbosity = new Integer(verb);
debug.setDebug(verb);
} catch (Exception e) {
System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
}
}
}
/**
* Load the properties from the propertyFile and build the
* resources from it.
*/
private synchronized void readProperties() {
try {
propertyFileURI = CatalogManager.class.getResource("/"+propertyFile);
InputStream in =
CatalogManager.class.getResourceAsStream("/"+propertyFile);
if (in==null) {
if (!ignoreMissingProperties) {
System.err.println("Cannot find "+propertyFile);
// there's no reason to give this warning more than once
ignoreMissingProperties = true;
}
return;
}
resources = new PropertyResourceBundle(in);
} catch (MissingResourceException mre) {
if (!ignoreMissingProperties) {
System.err.println("Cannot read "+propertyFile);
}
} catch (java.io.IOException e) {
if (!ignoreMissingProperties) {
System.err.println("Failure trying to read "+propertyFile);
}
}
// This is a bit of a hack. After we've successfully read the properties,
// use them to set the default debug level, if the user hasn't already set
// the default debug level.
if (verbosity == null) {
try {
String verbStr = resources.getString("verbosity");
int verb = Integer.parseInt(verbStr.trim());
debug.setDebug(verb);
verbosity = new Integer(verb);
} catch (Exception e) {
// nop
}
}
}
/**
* Allow access to the static CatalogManager
*/
public static CatalogManager getStaticManager() {
return staticManager;
}
/**
* How are missing properties handled?
*
* <p>If true, missing or unreadable property files will
* not be reported. Otherwise, a message will be sent to System.err.
* </p>
*/
public boolean getIgnoreMissingProperties() {
return ignoreMissingProperties;
}
/**
* How should missing properties be handled?
*
* <p>If ignore is true, missing or unreadable property files will
* not be reported. Otherwise, a message will be sent to System.err.
* </p>
*/
public void setIgnoreMissingProperties(boolean ignore) {
ignoreMissingProperties = ignore;
}
/**
* How are missing properties handled?
*
* <p>If ignore is true, missing or unreadable property files will
* not be reported. Otherwise, a message will be sent to System.err.
* </p>
*
* @deprecated No longer static; use get/set methods.
*/
public void ignoreMissingProperties(boolean ignore) {
setIgnoreMissingProperties(ignore);
}
/**
* Obtain the verbosity setting from the properties.
*
* @return The verbosity level from the propertyFile or the
* defaultVerbosity.
*/
private int queryVerbosity () {
String defaultVerbStr = Integer.toString(defaultVerbosity);
String verbStr = SecuritySupport.getSystemProperty(pVerbosity);
if (verbStr == null) {
if (resources==null) readProperties();
if (resources != null) {
try {
verbStr = resources.getString("verbosity");
} catch (MissingResourceException e) {
verbStr = defaultVerbStr;
}
} else {
verbStr = defaultVerbStr;
}
}
int verb = defaultVerbosity;
try {
verb = Integer.parseInt(verbStr.trim());
} catch (Exception e) {
System.err.println("Cannot parse verbosity: \"" + verbStr + "\"");
}
// This is a bit of a hack. After we've successfully got the verbosity,
// we have to use it to set the default debug level,
// if the user hasn't already set the default debug level.
if (verbosity == null) {
debug.setDebug(verb);
verbosity = new Integer(verb);
}
return verb;
}
/**
* What is the current verbosity?
*/
public int getVerbosity() {
if (verbosity == null) {
verbosity = new Integer(queryVerbosity());
}
return verbosity.intValue();
}
/**
* Set the current verbosity.
*/
public void setVerbosity (int verbosity) {
this.verbosity = new Integer(verbosity);
debug.setDebug(verbosity);
}
/**
* What is the current verbosity?
*
* @deprecated No longer static; use get/set methods.
*/
public int verbosity () {
return getVerbosity();
}
/**
* Obtain the relativeCatalogs setting from the properties.
*
* @return The relativeCatalogs setting from the propertyFile or the
* defaultRelativeCatalogs.
*/
private boolean queryRelativeCatalogs () {
if (resources==null) readProperties();
if (resources==null) return defaultRelativeCatalogs;
try {
String allow = resources.getString("relative-catalogs");
return (allow.equalsIgnoreCase("true")
|| allow.equalsIgnoreCase("yes")
|| allow.equalsIgnoreCase("1"));
} catch (MissingResourceException e) {
return defaultRelativeCatalogs;
}
}
/**
* Get the relativeCatalogs setting.
*
* <p>This property is used when the catalogFiles property is
* interrogated. If true, then relative catalog entry file names
* are returned. If false, relative catalog entry file names are
* made absolute with respect to the properties file before returning
* them.</p>
*
* <p>This property <emph>only applies</emph> when the catalog files
* come from a properties file. If they come from a system property or
* the default list, they are never considered relative. (What would
* they be relative to?)</p>
*
* <p>In the properties, a value of 'yes', 'true', or '1' is considered
* true, anything else is false.</p>
*
* @return The relativeCatalogs setting from the propertyFile or the
* defaultRelativeCatalogs.
*/
public boolean getRelativeCatalogs () {
if (relativeCatalogs == null) {
relativeCatalogs = queryRelativeCatalogs() ? Boolean.TRUE : Boolean.FALSE;
}
return relativeCatalogs.booleanValue();
}
/**
* Set the relativeCatalogs setting.
*
* @see #getRelativeCatalogs()
*/
public void setRelativeCatalogs (boolean relative) {
relativeCatalogs = relative ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Get the relativeCatalogs setting.
*
* @deprecated No longer static; use get/set methods.
*/
public boolean relativeCatalogs () {
return getRelativeCatalogs();
}
/**
* Obtain the list of catalog files from the properties.
*
* @return A semicolon delimited list of catlog file URIs
*/
private String queryCatalogFiles () {
String catalogList = SecuritySupport.getSystemProperty(pFiles);
fromPropertiesFile = false;
if (catalogList == null) {
if (resources == null) readProperties();
if (resources != null) {
try {
catalogList = resources.getString("catalogs");
fromPropertiesFile = true;
} catch (MissingResourceException e) {
System.err.println(propertyFile + ": catalogs not found.");
catalogList = null;
}
}
}
if (catalogList == null) {
catalogList = defaultCatalogFiles;
}
return catalogList;
}
/**
* Return the current list of catalog files.
*
* @return A vector of the catalog file names or null if no catalogs
* are available in the properties.
*/
public Vector getCatalogFiles() {
if (catalogFiles == null) {
catalogFiles = queryCatalogFiles();
}
StringTokenizer files = new StringTokenizer(catalogFiles, ";");
Vector catalogs = new Vector();
while (files.hasMoreTokens()) {
String catalogFile = files.nextToken();
URL absURI = null;
if (fromPropertiesFile && !relativeCatalogs()) {
try {
absURI = new URL(propertyFileURI, catalogFile);
catalogFile = absURI.toString();
} catch (MalformedURLException mue) {
absURI = null;
}
}
catalogs.add(catalogFile);
}
return catalogs;
}
/**
* Set the list of catalog files.
*/
public void setCatalogFiles(String fileList) {
catalogFiles = fileList;
fromPropertiesFile = false;
}
/**
* Return the current list of catalog files.
*
* @return A vector of the catalog file names or null if no catalogs
* are available in the properties.
*
* @deprecated No longer static; use get/set methods.
*/
public Vector catalogFiles() {
return getCatalogFiles();
}
/**
* Obtain the preferPublic setting from the properties.
*
* <p>In the properties, a value of 'public' is true,
* anything else is false.</p>
*
* @return True if prefer is public or the
* defaultPreferSetting.
*/
private boolean queryPreferPublic () {
String prefer = SecuritySupport.getSystemProperty(pPrefer);
if (prefer == null) {
if (resources==null) readProperties();
if (resources==null) return defaultPreferPublic;
try {
prefer = resources.getString("prefer");
} catch (MissingResourceException e) {
return defaultPreferPublic;
}
}
if (prefer == null) {
return defaultPreferPublic;
}
return (prefer.equalsIgnoreCase("public"));
}
/**
* Return the current prefer public setting.
*
* @return True if public identifiers are preferred.
*/
public boolean getPreferPublic () {
if (preferPublic == null) {
preferPublic = queryPreferPublic() ? Boolean.TRUE : Boolean.FALSE;
}
return preferPublic.booleanValue();
}
/**
* Set the prefer public setting.
*/
public void setPreferPublic (boolean preferPublic) {
this.preferPublic = preferPublic ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Return the current prefer public setting.
*
* @return True if public identifiers are preferred.
*
* @deprecated No longer static; use get/set methods.
*/
public boolean preferPublic () {
return getPreferPublic();
}
/**
* Obtain the static-catalog setting from the properties.
*
* <p>In the properties, a value of 'yes', 'true', or '1' is considered
* true, anything else is false.</p>
*
* @return The static-catalog setting from the propertyFile or the
* defaultUseStaticCatalog.
*/
private boolean queryUseStaticCatalog () {
String staticCatalog = SecuritySupport.getSystemProperty(pStatic);
if (staticCatalog == null) {
if (resources==null) readProperties();
if (resources==null) return defaultUseStaticCatalog;
try {
staticCatalog = resources.getString("static-catalog");
} catch (MissingResourceException e) {
return defaultUseStaticCatalog;
}
}
if (staticCatalog == null) {
return defaultUseStaticCatalog;
}
return (staticCatalog.equalsIgnoreCase("true")
|| staticCatalog.equalsIgnoreCase("yes")
|| staticCatalog.equalsIgnoreCase("1"));
}
/**
* Get the current use static catalog setting.
*/
public boolean getUseStaticCatalog() {
if (useStaticCatalog == null) {
useStaticCatalog = queryUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
}
return useStaticCatalog.booleanValue();
}
/**
* Set the use static catalog setting.
*/
public void setUseStaticCatalog(boolean useStatic) {
useStaticCatalog = useStatic ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Get the current use static catalog setting.
*
* @deprecated No longer static; use get/set methods.
*/
public boolean staticCatalog() {
return getUseStaticCatalog();
}
/**
* Get a new catalog instance.
*
* This method always returns a new instance of the underlying catalog class.
*/
public Catalog getPrivateCatalog() {
Catalog catalog = staticCatalog;
if (useStaticCatalog == null) {
useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
}
if (catalog == null || !useStaticCatalog.booleanValue()) {
try {
String catalogClassName = getCatalogClassName();
if (catalogClassName == null) {
catalog = new Catalog();
} else {
try {
catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance();
} catch (ClassNotFoundException cnfe) {
debug.message(1,"Catalog class named '"
+ catalogClassName
+ "' could not be found. Using default.");
catalog = new Catalog();
} catch (ClassCastException cnfe) {
debug.message(1,"Class named '"
+ catalogClassName
+ "' is not a Catalog. Using default.");
catalog = new Catalog();
}
}
catalog.setCatalogManager(this);
catalog.setupReaders();
catalog.loadSystemCatalogs();
} catch (Exception ex) {
ex.printStackTrace();
}
if (useStaticCatalog.booleanValue()) {
staticCatalog = catalog;
}
}
return catalog;
}
/**
* Get a catalog instance.
*
* If this manager uses static catalogs, the same static catalog will
* always be returned. Otherwise a new catalog will be returned.
*/
public Catalog getCatalog() {
Catalog catalog = staticCatalog;
if (useStaticCatalog == null) {
useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE;
}
if (catalog == null || !useStaticCatalog.booleanValue()) {
catalog = getPrivateCatalog();
if (useStaticCatalog.booleanValue()) {
staticCatalog = catalog;
}
}
return catalog;
}
/**
* <p>Obtain the oasisXMLCatalogPI setting from the properties.</p>
*
* <p>In the properties, a value of 'yes', 'true', or '1' is considered
* true, anything else is false.</p>
*
* @return The oasisXMLCatalogPI setting from the propertyFile or the
* defaultOasisXMLCatalogPI.
*/
public boolean queryAllowOasisXMLCatalogPI () {
String allow = SecuritySupport.getSystemProperty(pAllowPI);
if (allow == null) {
if (resources==null) readProperties();
if (resources==null) return defaultOasisXMLCatalogPI;
try {
allow = resources.getString("allow-oasis-xml-catalog-pi");
} catch (MissingResourceException e) {
return defaultOasisXMLCatalogPI;
}
}
if (allow == null) {
return defaultOasisXMLCatalogPI;
}
return (allow.equalsIgnoreCase("true")
|| allow.equalsIgnoreCase("yes")
|| allow.equalsIgnoreCase("1"));
}
/**
* Get the current XML Catalog PI setting.
*/
public boolean getAllowOasisXMLCatalogPI () {
if (oasisXMLCatalogPI == null) {
oasisXMLCatalogPI = queryAllowOasisXMLCatalogPI() ? Boolean.TRUE : Boolean.FALSE;
}
return oasisXMLCatalogPI.booleanValue();
}
public boolean useServicesMechanism() {
return useServicesMechanism;
}
/**
* Set the XML Catalog PI setting
*/
public void setAllowOasisXMLCatalogPI(boolean allowPI) {
oasisXMLCatalogPI = allowPI ? Boolean.TRUE : Boolean.FALSE;
}
/**
* Get the current XML Catalog PI setting.
*
* @deprecated No longer static; use get/set methods.
*/
public boolean allowOasisXMLCatalogPI() {
return getAllowOasisXMLCatalogPI();
}
/**
* Obtain the Catalog class name setting from the properties.
*
*/
public String queryCatalogClassName () {
String className = SecuritySupport.getSystemProperty(pClassname);
if (className == null) {
if (resources==null) readProperties();
if (resources==null) return null;
try {
return resources.getString("catalog-class-name");
} catch (MissingResourceException e) {
return null;
}
}
return className;
}
/**
* Get the current Catalog class name.
*/
public String getCatalogClassName() {
if (catalogClassName == null) {
catalogClassName = queryCatalogClassName();
}
return catalogClassName;
}
/**
* Set the Catalog class name.
*/
public void setCatalogClassName(String className) {
catalogClassName = className;
}
/**
* Get the current Catalog class name.
*
* @deprecated No longer static; use get/set methods.
*/
public String catalogClassName() {
return getCatalogClassName();
}
}

View File

@ -1,697 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver;
import java.io.IOException;
import java.io.InputStream;
import java.io.FileNotFoundException;
import java.util.Enumeration;
import java.util.Vector;
import java.net.URL;
import java.net.URLConnection;
import java.net.MalformedURLException;
import javax.xml.parsers.SAXParserFactory;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader;
import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader;
import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader;
/**
* An extension to OASIS Open Catalog files, this class supports
* suffix-based matching and an external RFC2483 resolver.
*
* @see Catalog
* @deprecated The JDK internal Catalog API in package
* {@code com.sun.org.apache.xml.internal.resolver}
* is encapsulated in JDK 9. The entire implementation under the package is now
* deprecated and subject to removal in a future release. Users of the API
* should migrate to the {@linkplain javax.xml.catalog new public API}.
* <p>
* The new Catalog API is supported throughout the JDK XML Processors, which allows
* the use of Catalog by simply setting a path to a Catalog file as a property.
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
@Deprecated(since="9", forRemoval=true)
public class Resolver extends Catalog {
/**
* The URISUFFIX Catalog Entry type.
*
* <p>URI suffix entries match URIs that end in a specified suffix.</p>
*/
public static final int URISUFFIX = CatalogEntry.addEntryType("URISUFFIX", 2);
/**
* The SYSTEMSUFFIX Catalog Entry type.
*
* <p>System suffix entries match system identifiers that end in a
* specified suffix.</p>
*/
public static final int SYSTEMSUFFIX = CatalogEntry.addEntryType("SYSTEMSUFFIX", 2);
/**
* The RESOLVER Catalog Entry type.
*
* <p>A hook for providing support for web-based backup resolvers.</p>
*/
public static final int RESOLVER = CatalogEntry.addEntryType("RESOLVER", 1);
/**
* The SYSTEMREVERSE Catalog Entry type.
*
* <p>This is a bit of a hack. There's no actual SYSTEMREVERSE entry,
* but this entry type is used to indicate that a reverse lookup is
* being performed. (This allows the Resolver to implement
* RFC2483 I2N and I2NS.)
*/
public static final int SYSTEMREVERSE
= CatalogEntry.addEntryType("SYSTEMREVERSE", 1);
/**
* Setup readers.
*/
public void setupReaders() {
SAXParserFactory spf = catalogManager.useServicesMechanism() ?
SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
spf.setNamespaceAware(true);
spf.setValidating(false);
SAXCatalogReader saxReader = new SAXCatalogReader(spf);
saxReader.setCatalogParser(null, "XCatalog",
"com.sun.org.apache.xml.internal.resolver.readers.XCatalogReader");
saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName,
"catalog",
"com.sun.org.apache.xml.internal.resolver.readers.ExtendedXMLCatalogReader");
addReader("application/xml", saxReader);
TR9401CatalogReader textReader = new TR9401CatalogReader();
addReader("text/plain", textReader);
}
/**
* Cleanup and process a Catalog entry.
*
* <p>This method processes each Catalog entry, changing mapped
* relative system identifiers into absolute ones (based on the current
* base URI), and maintaining other information about the current
* catalog.</p>
*
* @param entry The CatalogEntry to process.
*/
public void addEntry(CatalogEntry entry) {
int type = entry.getEntryType();
if (type == URISUFFIX) {
String suffix = normalizeURI(entry.getEntryArg(0));
String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
entry.setEntryArg(1, fsi);
catalogManager.debug.message(4, "URISUFFIX", suffix, fsi);
} else if (type == SYSTEMSUFFIX) {
String suffix = normalizeURI(entry.getEntryArg(0));
String fsi = makeAbsolute(normalizeURI(entry.getEntryArg(1)));
entry.setEntryArg(1, fsi);
catalogManager.debug.message(4, "SYSTEMSUFFIX", suffix, fsi);
}
super.addEntry(entry);
}
/**
* Return the applicable URI.
*
* <p>If a URI entry exists in the Catalog
* for the URI specified, return the mapped value.</p>
*
* <p>In the Resolver (as opposed to the Catalog) class, if the
* URI isn't found by the usual algorithm, URISUFFIX entries are
* considered.</p>
*
* <p>URI comparison is case sensitive.</p>
*
* @param uri The URI to locate in the catalog.
*
* @return The resolved URI.
*
* @throws MalformedURLException The system identifier of a
* subordinate catalog cannot be turned into a valid URL.
* @throws IOException Error reading subordinate catalog file.
*/
public String resolveURI(String uri)
throws MalformedURLException, IOException {
String resolved = super.resolveURI(uri);
if (resolved != null) {
return resolved;
}
Enumeration en = catalogEntries.elements();
while (en.hasMoreElements()) {
CatalogEntry e = (CatalogEntry) en.nextElement();
if (e.getEntryType() == RESOLVER) {
resolved = resolveExternalSystem(uri, e.getEntryArg(0));
if (resolved != null) {
return resolved;
}
} else if (e.getEntryType() == URISUFFIX) {
String suffix = e.getEntryArg(0);
String result = e.getEntryArg(1);
if (suffix.length() <= uri.length()
&& uri.substring(uri.length()-suffix.length()).equals(suffix)) {
return result;
}
}
}
// Otherwise, look in the subordinate catalogs
return resolveSubordinateCatalogs(Catalog.URI,
null,
null,
uri);
}
/**
* Return the applicable SYSTEM system identifier, resorting
* to external RESOLVERs if necessary.
*
* <p>If a SYSTEM entry exists in the Catalog
* for the system ID specified, return the mapped value.</p>
*
* <p>In the Resolver (as opposed to the Catalog) class, if the
* URI isn't found by the usual algorithm, SYSTEMSUFFIX entries are
* considered.</p>
*
* <p>On Windows-based operating systems, the comparison between
* the system identifier provided and the SYSTEM entries in the
* Catalog is case-insensitive.</p>
*
* @param systemId The system ID to locate in the catalog.
*
* @return The system identifier to use for systemId.
*
* @throws MalformedURLException The formal system identifier of a
* subordinate catalog cannot be turned into a valid URL.
* @throws IOException Error reading subordinate catalog file.
*/
public String resolveSystem(String systemId)
throws MalformedURLException, IOException {
String resolved = super.resolveSystem(systemId);
if (resolved != null) {
return resolved;
}
Enumeration en = catalogEntries.elements();
while (en.hasMoreElements()) {
CatalogEntry e = (CatalogEntry) en.nextElement();
if (e.getEntryType() == RESOLVER) {
resolved = resolveExternalSystem(systemId, e.getEntryArg(0));
if (resolved != null) {
return resolved;
}
} else if (e.getEntryType() == SYSTEMSUFFIX) {
String suffix = e.getEntryArg(0);
String result = e.getEntryArg(1);
if (suffix.length() <= systemId.length()
&& systemId.substring(systemId.length()-suffix.length()).equals(suffix)) {
return result;
}
}
}
return resolveSubordinateCatalogs(Catalog.SYSTEM,
null,
null,
systemId);
}
/**
* Return the applicable PUBLIC or SYSTEM identifier, resorting
* to external resolvers if necessary.
*
* <p>This method searches the Catalog and returns the system
* identifier specified for the given system or
* public identifiers. If
* no appropriate PUBLIC or SYSTEM entry is found in the Catalog,
* null is returned.</p>
*
* <p>Note that a system or public identifier in the current catalog
* (or subordinate catalogs) will be used in preference to an
* external resolver. Further, if a systemId is present, the external
* resolver(s) will be queried for that before the publicId.</p>
*
* @param publicId The public identifier to locate in the catalog.
* Public identifiers are normalized before comparison.
* @param systemId The nominal system identifier for the entity
* in question (as provided in the source document).
*
* @throws MalformedURLException The formal system identifier of a
* subordinate catalog cannot be turned into a valid URL.
* @throws IOException Error reading subordinate catalog file.
*
* @return The system identifier to use.
* Note that the nominal system identifier is not returned if a
* match is not found in the catalog, instead null is returned
* to indicate that no match was found.
*/
public String resolvePublic(String publicId, String systemId)
throws MalformedURLException, IOException {
String resolved = super.resolvePublic(publicId, systemId);
if (resolved != null) {
return resolved;
}
Enumeration en = catalogEntries.elements();
while (en.hasMoreElements()) {
CatalogEntry e = (CatalogEntry) en.nextElement();
if (e.getEntryType() == RESOLVER) {
if (systemId != null) {
resolved = resolveExternalSystem(systemId,
e.getEntryArg(0));
if (resolved != null) {
return resolved;
}
}
resolved = resolveExternalPublic(publicId, e.getEntryArg(0));
if (resolved != null) {
return resolved;
}
}
}
return resolveSubordinateCatalogs(Catalog.PUBLIC,
null,
publicId,
systemId);
}
/**
* Query an external RFC2483 resolver for a system identifier.
*
* @param systemId The system ID to locate.
* @param resolver The name of the resolver to use.
*
* @return The system identifier to use for the systemId.
*/
protected String resolveExternalSystem(String systemId, String resolver)
throws MalformedURLException, IOException {
Resolver r = queryResolver(resolver, "i2l", systemId, null);
if (r != null) {
return r.resolveSystem(systemId);
} else {
return null;
}
}
/**
* Query an external RFC2483 resolver for a public identifier.
*
* @param publicId The system ID to locate.
* @param resolver The name of the resolver to use.
*
* @return The system identifier to use for the systemId.
*/
protected String resolveExternalPublic(String publicId, String resolver)
throws MalformedURLException, IOException {
Resolver r = queryResolver(resolver, "fpi2l", publicId, null);
if (r != null) {
return r.resolvePublic(publicId, null);
} else {
return null;
}
}
/**
* Query an external RFC2483 resolver.
*
* @param resolver The URL of the RFC2483 resolver.
* @param command The command to send the resolver.
* @param arg1 The first argument to the resolver.
* @param arg2 The second argument to the resolver, usually null.
*
* @return The Resolver constructed.
*/
protected Resolver queryResolver(String resolver,
String command,
String arg1,
String arg2) {
InputStream iStream = null;
String RFC2483 = resolver + "?command=" + command
+ "&format=tr9401&uri=" + arg1
+ "&uri2=" + arg2;
String line = null;
try {
URL url = new URL(RFC2483);
URLConnection urlCon = url.openConnection();
urlCon.setUseCaches(false);
Resolver r = (Resolver) newCatalog();
String cType = urlCon.getContentType();
// I don't care about the character set or subtype
if (cType.indexOf(";") > 0) {
cType = cType.substring(0, cType.indexOf(";"));
}
r.parseCatalog(cType, urlCon.getInputStream());
return r;
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.UNPARSEABLE) {
catalogManager.debug.message(1, "Unparseable catalog: " + RFC2483);
} else if (cex.getExceptionType()
== CatalogException.UNKNOWN_FORMAT) {
catalogManager.debug.message(1, "Unknown catalog format: " + RFC2483);
}
return null;
} catch (MalformedURLException mue) {
catalogManager.debug.message(1, "Malformed resolver URL: " + RFC2483);
return null;
} catch (IOException ie) {
catalogManager.debug.message(1, "I/O Exception opening resolver: " + RFC2483);
return null;
}
}
/**
* Append two vectors, returning the result.
*
* @param vec The first vector
* @param appvec The vector to be appended
* @return The vector vec, with appvec's elements appended to it
*/
private Vector appendVector(Vector vec, Vector appvec) {
if (appvec != null) {
for (int count = 0; count < appvec.size(); count++) {
vec.addElement(appvec.elementAt(count));
}
}
return vec;
}
/**
* Find the URNs for a given system identifier in all catalogs.
*
* @param systemId The system ID to locate.
*
* @return A vector of URNs that map to the systemId.
*/
public Vector resolveAllSystemReverse(String systemId)
throws MalformedURLException, IOException {
Vector resolved = new Vector();
// If there's a SYSTEM entry in this catalog, use it
if (systemId != null) {
Vector localResolved = resolveLocalSystemReverse(systemId);
resolved = appendVector(resolved, localResolved);
}
// Otherwise, look in the subordinate catalogs
Vector subResolved = resolveAllSubordinateCatalogs(SYSTEMREVERSE,
null,
null,
systemId);
return appendVector(resolved, subResolved);
}
/**
* Find the URN for a given system identifier.
*
* @param systemId The system ID to locate.
*
* @return A (single) URN that maps to the systemId.
*/
public String resolveSystemReverse(String systemId)
throws MalformedURLException, IOException {
Vector resolved = resolveAllSystemReverse(systemId);
if (resolved != null && resolved.size() > 0) {
return (String) resolved.elementAt(0);
} else {
return null;
}
}
/**
* Return the applicable SYSTEM system identifiers.
*
* <p>If one or more SYSTEM entries exists in the Catalog
* for the system ID specified, return the mapped values.</p>
*
* <p>The caller is responsible for doing any necessary
* normalization of the system identifier before calling
* this method. For example, a relative system identifier in
* a document might be converted to an absolute system identifier
* before attempting to resolve it.</p>
*
* <p>Note that this function will force all subordinate catalogs
* to be loaded.</p>
*
* <p>On Windows-based operating systems, the comparison between
* the system identifier provided and the SYSTEM entries in the
* Catalog is case-insensitive.</p>
*
* @param systemId The system ID to locate in the catalog.
*
* @return The system identifier to use for the notation.
*
* @throws MalformedURLException The formal system identifier of a
* subordinate catalog cannot be turned into a valid URL.
* @throws IOException Error reading subordinate catalog file.
*/
public Vector resolveAllSystem(String systemId)
throws MalformedURLException, IOException {
Vector resolutions = new Vector();
// If there are SYSTEM entries in this catalog, start with them
if (systemId != null) {
Vector localResolutions = resolveAllLocalSystem(systemId);
resolutions = appendVector(resolutions, localResolutions);
}
// Then look in the subordinate catalogs
Vector subResolutions = resolveAllSubordinateCatalogs(SYSTEM,
null,
null,
systemId);
resolutions = appendVector(resolutions, subResolutions);
if (resolutions.size() > 0) {
return resolutions;
} else {
return null;
}
}
/**
* Return all applicable SYSTEM system identifiers in this
* catalog.
*
* <p>If one or more SYSTEM entries exists in the catalog file
* for the system ID specified, return the mapped values.</p>
*
* @param systemId The system ID to locate in the catalog
*
* @return A vector of the mapped system identifiers or null
*/
private Vector resolveAllLocalSystem(String systemId) {
Vector map = new Vector();
String osname = SecuritySupport.getSystemProperty("os.name");
boolean windows = (osname.indexOf("Windows") >= 0);
Enumeration en = catalogEntries.elements();
while (en.hasMoreElements()) {
CatalogEntry e = (CatalogEntry) en.nextElement();
if (e.getEntryType() == SYSTEM
&& (e.getEntryArg(0).equals(systemId)
|| (windows
&& e.getEntryArg(0).equalsIgnoreCase(systemId)))) {
map.addElement(e.getEntryArg(1));
}
}
if (map.size() == 0) {
return null;
} else {
return map;
}
}
/**
* Find the URNs for a given system identifier in the current catalog.
*
* @param systemId The system ID to locate.
*
* @return A vector of URNs that map to the systemId.
*/
private Vector resolveLocalSystemReverse(String systemId) {
Vector map = new Vector();
String osname = SecuritySupport.getSystemProperty("os.name");
boolean windows = (osname.indexOf("Windows") >= 0);
Enumeration en = catalogEntries.elements();
while (en.hasMoreElements()) {
CatalogEntry e = (CatalogEntry) en.nextElement();
if (e.getEntryType() == SYSTEM
&& (e.getEntryArg(1).equals(systemId)
|| (windows
&& e.getEntryArg(1).equalsIgnoreCase(systemId)))) {
map.addElement(e.getEntryArg(0));
}
}
if (map.size() == 0) {
return null;
} else {
return map;
}
}
/**
* Search the subordinate catalogs, in order, looking for all
* match.
*
* <p>This method searches the Catalog and returns all of the system
* identifiers specified for the given entity type with the given
* name, public, and system identifiers. In some contexts, these
* may be null.</p>
*
* @param entityType The CatalogEntry type for which this query is
* being conducted. This is necessary in order to do the approprate
* query on a subordinate catalog.
* @param entityName The name of the entity being searched for, if
* appropriate.
* @param publicId The public identifier of the entity in question
* (as provided in the source document).
* @param systemId The nominal system identifier for the entity
* in question (as provided in the source document).
*
* @throws MalformedURLException The formal system identifier of a
* delegated catalog cannot be turned into a valid URL.
* @throws IOException Error reading delegated catalog file.
*
* @return The system identifier to use.
* Note that the nominal system identifier is not returned if a
* match is not found in the catalog, instead null is returned
* to indicate that no match was found.
*/
private synchronized Vector resolveAllSubordinateCatalogs(int entityType,
String entityName,
String publicId,
String systemId)
throws MalformedURLException, IOException {
Vector resolutions = new Vector();
for (int catPos = 0; catPos < catalogs.size(); catPos++) {
Resolver c = null;
try {
c = (Resolver) catalogs.elementAt(catPos);
} catch (ClassCastException e) {
String catfile = (String) catalogs.elementAt(catPos);
c = (Resolver) newCatalog();
try {
c.parseCatalog(catfile);
} catch (MalformedURLException mue) {
catalogManager.debug.message(1, "Malformed Catalog URL", catfile);
} catch (FileNotFoundException fnfe) {
catalogManager.debug.message(1, "Failed to load catalog, file not found",
catfile);
} catch (IOException ioe) {
catalogManager.debug.message(1, "Failed to load catalog, I/O error", catfile);
}
catalogs.setElementAt(c, catPos);
}
String resolved = null;
// Ok, now what are we supposed to call here?
if (entityType == DOCTYPE) {
resolved = c.resolveDoctype(entityName,
publicId,
systemId);
if (resolved != null) {
// Only find one DOCTYPE resolution
resolutions.addElement(resolved);
return resolutions;
}
} else if (entityType == DOCUMENT) {
resolved = c.resolveDocument();
if (resolved != null) {
// Only find one DOCUMENT resolution
resolutions.addElement(resolved);
return resolutions;
}
} else if (entityType == ENTITY) {
resolved = c.resolveEntity(entityName,
publicId,
systemId);
if (resolved != null) {
// Only find one ENTITY resolution
resolutions.addElement(resolved);
return resolutions;
}
} else if (entityType == NOTATION) {
resolved = c.resolveNotation(entityName,
publicId,
systemId);
if (resolved != null) {
// Only find one NOTATION resolution
resolutions.addElement(resolved);
return resolutions;
}
} else if (entityType == PUBLIC) {
resolved = c.resolvePublic(publicId, systemId);
if (resolved != null) {
// Only find one PUBLIC resolution
resolutions.addElement(resolved);
return resolutions;
}
} else if (entityType == SYSTEM) {
Vector localResolutions = c.resolveAllSystem(systemId);
resolutions = appendVector(resolutions, localResolutions);
break;
} else if (entityType == SYSTEMREVERSE) {
Vector localResolutions = c.resolveAllSystemReverse(systemId);
resolutions = appendVector(resolutions, localResolutions);
}
}
if (resolutions != null) {
return resolutions;
} else {
return null;
}
}
}

View File

@ -1,207 +0,0 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.helpers;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* A simple bootstrapping resolver.
*
* <p>This class is used as the entity resolver when reading XML Catalogs.
* It searches for the OASIS XML Catalog DTD, Relax NG Grammar and W3C XML Schema
* as resources (e.g., in the resolver jar file).</p>
*
* <p>If you have your own DTDs or schemas, you can extend this class and
* set the BootstrapResolver in your CatalogManager.</p>
*
* @see com.sun.org.apache.xml.internal.resolver.CatalogManager
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class BootstrapResolver implements EntityResolver, URIResolver {
/** URI of the W3C XML Schema for OASIS XML Catalog files. */
public static final String xmlCatalogXSD = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.xsd";
/** URI of the RELAX NG Grammar for OASIS XML Catalog files. */
public static final String xmlCatalogRNG = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.rng";
/** Public identifier for OASIS XML Catalog files. */
public static final String xmlCatalogPubId = "-//OASIS//DTD XML Catalogs V1.0//EN";
/** System identifier for OASIS XML Catalog files. */
public static final String xmlCatalogSysId = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd";
/** Public identifier for legacy Apache XCatalog files. There is no official system identifier for XCatalog files. */
public static final String xCatalogPubId = "-//DTD XCatalog//EN";
/** Private hash used for public identifiers. */
private final Map<String, String> publicMap = new HashMap<>();
/** Private hash used for system identifiers. */
private final Map<String, String> systemMap = new HashMap<>();
/** Private hash used for URIs. */
private final Map<String, String> uriMap = new HashMap<>();
/** Constructor. */
public BootstrapResolver() {
URL url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/catalog.dtd");
if (url != null) {
publicMap.put(xmlCatalogPubId, url.toString());
systemMap.put(xmlCatalogSysId, url.toString());
}
url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/catalog.rng");
if (url != null) {
uriMap.put(xmlCatalogRNG, url.toString());
}
url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/catalog.xsd");
if (url != null) {
uriMap.put(xmlCatalogXSD, url.toString());
}
url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/xcatalog.dtd");
if (url != null) {
publicMap.put(xCatalogPubId, url.toString());
}
}
/** SAX resolveEntity API. */
public InputSource resolveEntity (String publicId, String systemId) {
String resolved = null;
if (systemId != null && systemMap.containsKey(systemId)) {
resolved = systemMap.get(systemId);
} else if (publicId != null && publicMap.containsKey(publicId)) {
resolved = publicMap.get(publicId);
}
if (resolved != null) {
try {
InputSource iSource = new InputSource(resolved);
iSource.setPublicId(publicId);
// Ideally this method would not attempt to open the
// InputStream, but there is a bug (in Xerces, at least)
// that causes the parser to mistakenly open the wrong
// system identifier if the returned InputSource does
// not have a byteStream.
//
// It could be argued that we still shouldn't do this here,
// but since the purpose of calling the entityResolver is
// almost certainly to open the input stream, it seems to
// do little harm.
//
URL url = new URL(resolved);
InputStream iStream = url.openStream();
iSource.setByteStream(iStream);
return iSource;
} catch (Exception e) {
// FIXME: silently fail?
return null;
}
}
return null;
}
/** Transformer resolve API. */
public Source resolve(String href, String base)
throws TransformerException {
String uri = href;
String fragment = null;
int hashPos = href.indexOf("#");
if (hashPos >= 0) {
uri = href.substring(0, hashPos);
fragment = href.substring(hashPos+1);
}
String result = null;
if (href != null && uriMap.containsKey(href)) {
result = uriMap.get(href);
}
if (result == null) {
try {
URL url = null;
if (base==null) {
url = new URL(uri);
result = url.toString();
} else {
URL baseURL = new URL(base);
url = (href.length()==0 ? baseURL : new URL(baseURL, uri));
result = url.toString();
}
} catch (java.net.MalformedURLException mue) {
// try to make an absolute URI from the current base
String absBase = makeAbsolute(base);
if (!absBase.equals(base)) {
// don't bother if the absBase isn't different!
return resolve(href, absBase);
} else {
throw new TransformerException("Malformed URL "
+ href + "(base " + base + ")",
mue);
}
}
}
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(result));
return source;
}
/** Attempt to construct an absolute URI */
private String makeAbsolute(String uri) {
if (uri == null) {
uri = "";
}
try {
URL url = new URL(uri);
return url.toString();
} catch (MalformedURLException mue) {
try {
URL fileURL = FileURL.makeURL(uri);
return fileURL.toString();
} catch (MalformedURLException mue2) {
// bail
return uri;
}
}
}
}

View File

@ -1,105 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.helpers;
/**
* Static debugging/messaging class for Catalogs.
*
* <p>This class defines a set of static methods that can be called
* to produce debugging messages. Messages have an associated "debug
* level" and messages below the current setting are not displayed.</p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class Debug {
/** The internal debug level. */
protected int debug = 0;
/** Constructor */
public Debug() {
// nop
}
/** Set the debug level for future messages. */
public void setDebug(int newDebug) {
debug = newDebug;
}
/** Get the current debug level. */
public int getDebug() {
return debug;
}
/**
* Print debug message (if the debug level is high enough).
*
* <p>Prints "the message"</p>
*
* @param level The debug level of this message. This message
* will only be
* displayed if the current debug level is at least equal to this
* value.
* @param message The text of the message.
*/
public void message(int level, String message) {
if (debug >= level) {
System.out.println(message);
}
}
/**
* Print debug message (if the debug level is high enough).
*
* <p>Prints "the message: spec"</p>
*
* @param level The debug level of this message. This message
* will only be
* displayed if the current debug level is at least equal to this
* value.
* @param message The text of the message.
* @param spec An argument to the message.
*/
public void message(int level, String message, String spec) {
if (debug >= level) {
System.out.println(message + ": " + spec);
}
}
/**
* Print debug message (if the debug level is high enough).
*
* <p>Prints "the message: spec1" and "spec2" indented on the next line.</p>
*
* @param level The debug level of this message. This message
* will only be
* displayed if the current debug level is at least equal to this
* value.
* @param message The text of the message.
* @param spec1 An argument to the message.
* @param spec2 Another argument to the message.
*/
public void message(int level, String message,
String spec1, String spec2) {
if (debug >= level) {
System.out.println(message + ": " + spec1);
System.out.println("\t" + spec2);
}
}
}

View File

@ -1,87 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.helpers;
import java.net.URL;
import java.net.MalformedURLException;
import java.io.File;
/**
* Static method for dealing with file: URLs.
*
* <p>This class defines a static method that can be used to construct
* an appropriate file: URL from parts. It's defined here so that it
* can be reused throught the resolver.</p>
*
* <p>(Yes, I'd rather have called this class FileUR<b>I</b>, but
* given that a jave.net.URL is returned, it seemed...even more
* confusing.)</p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public abstract class FileURL {
protected FileURL() { }
/**
* Construct a file: URL for a path name.
*
* <p>URLs in the file: scheme can be constructed for paths on
* the local file system. Several possibilities need to be considered:
* </p>
*
* <ul>
* <li>If the path does not begin with a slash, then it is assumed
* to reside in the users current working directory
* (System.getProperty("user.dir")).</li>
* <li>On Windows machines, the current working directory uses
* backslashes (\\, instead of /).</li>
* <li>If the current working directory is "/", don't add an extra
* slash before the base name.</li>
* </ul>
*
* <p>This method is declared static so that other classes
* can use it directly.</p>
*
* @param pathname The path name component for which to construct a URL.
*
* @return The appropriate file: URL.
*
* @throws MalformedURLException if the pathname can't be turned into
* a proper URL.
*/
public static URL makeURL(String pathname) throws MalformedURLException {
/*if (pathname.startsWith("/")) {
return new URL("file://" + pathname);
}
String userdir = System.getProperty("user.dir");
userdir.replace('\\', '/');
if (userdir.endsWith("/")) {
return new URL("file:///" + userdir + pathname);
} else {
return new URL("file:///" + userdir + "/" + pathname);
}
*/
File file = new File(pathname);
return file.toURI().toURL();
}
}

View File

@ -1,110 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.helpers;
import org.w3c.dom.*;
/**
* Static Namespace query methods.
*
* <p>This class defines a set of static methods that can be called
* to analyze the namespace properties of DOM nodes.</p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class Namespaces {
/**
* Returns the "prefix" part of a QName or the empty string (not
* null) if the name has no prefix.
*
* @param element The QName of an element.
* @return The prefix part of the element name.
*/
public static String getPrefix(Element element) {
String name = element.getTagName();
String prefix = "";
final int indexOfColon = name.indexOf(':');
if (indexOfColon > 0) {
prefix = name.substring(0, indexOfColon);
}
return prefix;
}
/**
* Returns the "localname" part of a QName, which is the whole
* name if it has no prefix.
*
* @param element The QName of an element.
* @return The local part of a QName.
*/
public static String getLocalName(Element element) {
String name = element.getTagName();
final int indexOfColon = name.indexOf(':');
if (indexOfColon > 0) {
name = name.substring(indexOfColon + 1);
}
return name;
}
/**
* Returns the namespace URI for the specified prefix at the
* specified context node.
*
* @param node The context node.
* @param prefix The prefix.
* @return The namespace URI associated with the prefix, or
* null if no namespace declaration exists for the prefix.
*/
public static String getNamespaceURI(Node node, String prefix) {
if (node == null || node.getNodeType() != Node.ELEMENT_NODE) {
return null;
}
if (prefix.length() == 0) {
if (((Element) node).hasAttribute("xmlns")) {
return ((Element) node).getAttribute("xmlns");
}
} else {
String nsattr = "xmlns:" + prefix;
if (((Element) node).hasAttribute(nsattr)) {
return ((Element) node).getAttribute(nsattr);
}
}
return getNamespaceURI(node.getParentNode(), prefix);
}
/**
* Returns the namespace URI for the namespace to which the
* element belongs.
*
* @param element The element.
* @return The namespace URI associated with the namespace of the
* element, or null if no namespace declaration exists for it.
*/
public static String getNamespaceURI(Element element) {
String prefix = getPrefix(element);
return getNamespaceURI(element, prefix);
}
}

View File

@ -1,169 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.helpers;
/**
* Static methods for dealing with public identifiers.
*
* <p>This class defines a set of static methods that can be called
* to handle public identifiers.</p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public abstract class PublicId {
protected PublicId() {}
/**
* Normalize a public identifier.
*
* <p>Public identifiers must be normalized according to the following
* rules before comparisons between them can be made:</p>
*
* <ul>
* <li>Whitespace characters are normalized to spaces (e.g., line feeds,
* tabs, etc. become spaces).</li>
* <li>Leading and trailing whitespace is removed.</li>
* <li>Multiple internal whitespaces are normalized to a single
* space.</li>
* </ul>
*
* <p>This method is declared static so that other classes
* can use it directly.</p>
*
* @param publicId The unnormalized public identifier.
*
* @return The normalized identifier.
*/
public static String normalize(String publicId) {
String normal = publicId.replace('\t', ' ');
normal = normal.replace('\r', ' ');
normal = normal.replace('\n', ' ');
normal = normal.trim();
int pos;
while ((pos = normal.indexOf(" ")) >= 0) {
normal = normal.substring(0, pos) + normal.substring(pos+1);
}
return normal;
}
/**
* Encode a public identifier as a "publicid" URN.
*
* <p>This method is declared static so that other classes
* can use it directly.</p>
*
* @param publicId The unnormalized public identifier.
*
* @return The normalized identifier.
*/
public static String encodeURN(String publicId) {
String urn = PublicId.normalize(publicId);
urn = PublicId.stringReplace(urn, "%", "%25");
urn = PublicId.stringReplace(urn, ";", "%3B");
urn = PublicId.stringReplace(urn, "'", "%27");
urn = PublicId.stringReplace(urn, "?", "%3F");
urn = PublicId.stringReplace(urn, "#", "%23");
urn = PublicId.stringReplace(urn, "+", "%2B");
urn = PublicId.stringReplace(urn, " ", "+");
urn = PublicId.stringReplace(urn, "::", ";");
urn = PublicId.stringReplace(urn, ":", "%3A");
urn = PublicId.stringReplace(urn, "//", ":");
urn = PublicId.stringReplace(urn, "/", "%2F");
StringBuilder buffer = new StringBuilder(13 + urn.length());
buffer.append("urn:publicid:");
buffer.append(urn);
return buffer.toString();
}
/**
* Decode a "publicid" URN into a public identifier.
*
* <p>This method is declared static so that other classes
* can use it directly.</p>
*
* @param urn The urn:publicid: URN
*
* @return The normalized identifier.
*/
public static String decodeURN(String urn) {
String publicId;
if (urn.startsWith("urn:publicid:")) {
publicId = urn.substring(13);
}
else {
return urn;
}
final boolean hasEscape = (publicId.indexOf('%') >= 0);
if (hasEscape) {
publicId = PublicId.stringReplace(publicId, "%2F", "/");
}
publicId = PublicId.stringReplace(publicId, ":", "//");
if (hasEscape) {
publicId = PublicId.stringReplace(publicId, "%3A", ":");
}
publicId = PublicId.stringReplace(publicId, ";", "::");
publicId = PublicId.stringReplace(publicId, "+", " ");
if (hasEscape) {
publicId = PublicId.stringReplace(publicId, "%2B", "+");
publicId = PublicId.stringReplace(publicId, "%23", "#");
publicId = PublicId.stringReplace(publicId, "%3F", "?");
publicId = PublicId.stringReplace(publicId, "%27", "'");
publicId = PublicId.stringReplace(publicId, "%3B", ";");
publicId = PublicId.stringReplace(publicId, "%25", "%");
}
return publicId;
}
/**
* Replace one string with another.
*/
private static String stringReplace(String str,
String oldStr,
String newStr) {
int pos = str.indexOf(oldStr);
if (pos >= 0) {
final StringBuilder buffer = new StringBuilder();
final int oldStrLength = oldStr.length();
int start = 0;
do {
for (int i = start; i < pos; ++i) {
buffer.append(str.charAt(i));
}
buffer.append(newStr);
start = pos + oldStrLength;
pos = str.indexOf(oldStr, start);
}
while (pos >= 0);
final int strLength = str.length();
for (int i = start; i < strLength; ++i) {
buffer.append(str.charAt(i));
}
return buffer.toString();
}
return str;
}
}

View File

@ -1,75 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import java.io.IOException;
import java.net.MalformedURLException;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import java.io.InputStream;
import com.sun.org.apache.xml.internal.resolver.Catalog;
/**
* The CatalogReader interface.
*
* <p>The Catalog class requires that classes implement this interface
* in order to be used to read catalogs. Examples of CatalogReaders
* include the TextCatalogReader, the SAXCatalogReader, and the
* DOMCatalogReader.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public interface CatalogReader {
/**
* Read a catalog from a file.
*
* <p>This class reads a catalog from a URL.</p>
*
* @param catalog The catalog for which this reader is called.
* @param fileUrl The URL of a document to be read.
* @throws MalformedURLException if the specified URL cannot be
* turned into a URL object.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException, CatalogException;
/**
* Read a catalog from an input stream.
*
* <p>This class reads a catalog from an input stream.</p>
*
* @param catalog The catalog for which this reader is called.
* @param is The input stream that is to be read.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException;
}

View File

@ -1,47 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import org.w3c.dom.Node;
/**
* The DOMCatalogParser interface.
*
* <p>This interface must be implemented in order for a class to
* participate as a parser for the DOMCatalogReader.
*
* @see Catalog
* @see DOMCatalogReader
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public interface DOMCatalogParser {
/**
* Parse a DOM node as a catalog entry.
*
* <p>This method is expected to analyze the specified node and
* construct appropriate catalog entry(ies) from it.</p>
*
* @param catalog The catalog for which this node is being considered.
* @param node The DOM Node from the catalog.
*/
public void parseCatalogEntry(Catalog catalog, Node node);
}

View File

@ -1,240 +0,0 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import com.sun.org.apache.xml.internal.resolver.helpers.Namespaces;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import sun.reflect.misc.ReflectUtil;
/**
* A DOM-based CatalogReader.
*
* <p>This class is used to read XML Catalogs using the DOM. This reader
* has an advantage over the SAX-based reader that it can analyze the
* DOM tree rather than simply a series of SAX events. It has the disadvantage
* that it requires all of the code necessary to build and walk a DOM
* tree.</p>
*
* <p>Since the choice of CatalogReaders (in the InputStream case) can only
* be made on the basis of MIME type, the following problem occurs: only
* one CatalogReader can exist for all XML mime types. In order to get
* around this problem, the DOMCatalogReader relies on a set of external
* CatalogParsers to actually build the catalog.</p>
*
* <p>The selection of CatalogParsers is made on the basis of the QName
* of the root element of the document.</p>
*
*
* @see Catalog
* @see CatalogReader
* @see SAXCatalogReader
* @see TextCatalogReader
* @see DOMCatalogParser
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class DOMCatalogReader implements CatalogReader {
/**
* Mapping table from QNames to CatalogParser classes.
*
* <p>Each key in this hash table has the form "elementname"
* or "{namespaceuri}elementname". The former is used if the
* namespace URI is null.</p>
*/
protected Map<String, String> namespaceMap = new HashMap<>();
/**
* Add a new parser to the reader.
*
* <p>This method associates the specified parserClass with the
* namespaceURI/rootElement names specified.</p>
*
* @param namespaceURI The namespace URI. <em>Not</em> the prefix.
* @param rootElement The name of the root element.
* @param parserClass The name of the parserClass to instantiate
* for this kind of catalog.
*/
public void setCatalogParser(String namespaceURI,
String rootElement,
String parserClass) {
if (namespaceURI == null) {
namespaceMap.put(rootElement, parserClass);
} else {
namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
}
}
/**
* Get the name of the parser class for a given catalog type.
*
* <p>This method returns the parserClass associated with the
* namespaceURI/rootElement names specified.</p>
*
* @param namespaceURI The namespace URI. <em>Not</em> the prefix.
* @param rootElement The name of the root element.
* @return The parser class.
*/
public String getCatalogParser(String namespaceURI,
String rootElement) {
if (namespaceURI == null) {
return namespaceMap.get(rootElement);
} else {
return namespaceMap.get("{"+namespaceURI+"}"+rootElement);
}
}
/**
* Null constructor; something for subclasses to call.
*/
public DOMCatalogReader() { }
/**
* Read a catalog from an input stream.
*
* <p>This class reads a catalog from an input stream:</p>
*
* <ul>
* <li>Based on the QName of the root element, it determines which
* parser to instantiate for this catalog.</li>
* <li>It constructs a DOM Document from the catalog and</li>
* <li>For each child of the root node, it calls the parser's
* parseCatalogEntry method. This method is expected to make
* appropriate calls back into the catalog to add entries for the
* entries in the catalog. It is free to do this in whatever manner
* is appropriate (perhaps using just the node passed in, perhaps
* wandering arbitrarily throughout the tree).</li>
* </ul>
*
* @param catalog The catalog for which this reader is called.
* @param is The input stream that is to be read.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed or
* if the parser class cannot be instantiated.)
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException {
DocumentBuilderFactory factory = null;
DocumentBuilder builder = null;
factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
factory.setValidating(false);
try {
builder = factory.newDocumentBuilder();
} catch (ParserConfigurationException pce) {
throw new CatalogException(CatalogException.UNPARSEABLE);
}
Document doc = null;
try {
doc = builder.parse(is);
} catch (SAXException se) {
throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
}
Element root = doc.getDocumentElement();
String namespaceURI = Namespaces.getNamespaceURI(root);
String localName = Namespaces.getLocalName(root);
String domParserClass = getCatalogParser(namespaceURI,
localName);
if (domParserClass == null) {
if (namespaceURI == null) {
catalog.getCatalogManager().debug.message(1, "No Catalog parser for "
+ localName);
} else {
catalog.getCatalogManager().debug.message(1, "No Catalog parser for "
+ "{" + namespaceURI + "}"
+ localName);
}
return;
}
DOMCatalogParser domParser = null;
try {
domParser = (DOMCatalogParser) ReflectUtil.forName(domParserClass).newInstance();
} catch (ClassNotFoundException cnfe) {
catalog.getCatalogManager().debug.message(1, "Cannot load XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (InstantiationException ie) {
catalog.getCatalogManager().debug.message(1, "Cannot instantiate XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (IllegalAccessException iae) {
catalog.getCatalogManager().debug.message(1, "Cannot access XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (ClassCastException cce ) {
catalog.getCatalogManager().debug.message(1, "Cannot cast XML Catalog Parser class", domParserClass);
throw new CatalogException(CatalogException.UNPARSEABLE);
}
Node node = root.getFirstChild();
while (node != null) {
domParser.parseCatalogEntry(catalog, node);
node = node.getNextSibling();
}
}
/**
* Read the catalog behind the specified URL.
*
* @see #readCatalog(Catalog, InputStream)
*
* @param catalog The catalog for which we are reading.
* @param fileUrl The URL of the document that should be read.
*
* @throws MalformedURLException if the specified URL cannot be
* turned into a URL object.
* @throws IOException if the URL cannot be read.
* @throws UnknownCatalogFormatException if the catalog format is
* not recognized.
* @throws UnparseableCatalogException if the catalog cannot be parsed.
* (For example, if it is supposed to be XML and isn't well-formed.)
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException, CatalogException {
URL url = new URL(fileUrl);
URLConnection urlCon = url.openConnection();
readCatalog(catalog, urlCon.getInputStream());
}
}

View File

@ -1,181 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import java.util.Vector;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.Resolver;
import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import org.xml.sax.*;
import org.w3c.dom.*;
/**
* Parse Extended OASIS Entity Resolution Technical Committee
* XML Catalog files.
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class ExtendedXMLCatalogReader extends OASISXMLCatalogReader {
/** The namespace name of extended catalog elements */
public static final String extendedNamespaceName = "http://nwalsh.com/xcatalog/1.0";
/**
* The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
// Check before calling the super because super will report our
// namespace as an extension namespace, but that doesn't count
// for this element.
boolean inExtension = inExtensionNamespace();
super.startElement(namespaceURI, localName, qName, atts);
int entryType = -1;
Vector entryArgs = new Vector();
if (namespaceURI != null && extendedNamespaceName.equals(namespaceURI)
&& !inExtension) {
// This is an Extended XML Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if (localName.equals("uriSuffix")) {
if (checkAttributes(atts, "suffix", "uri")) {
entryType = Resolver.URISUFFIX;
entryArgs.add(atts.getValue("suffix"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "uriSuffix",
atts.getValue("suffix"),
atts.getValue("uri"));
}
} else if (localName.equals("systemSuffix")) {
if (checkAttributes(atts, "suffix", "uri")) {
entryType = Resolver.SYSTEMSUFFIX;
entryArgs.add(atts.getValue("suffix"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "systemSuffix",
atts.getValue("suffix"),
atts.getValue("uri"));
}
} else {
// This is equivalent to an invalid catalog entry type
debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
}
/** The SAX <code>endElement</code> method does nothing. */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
super.endElement(namespaceURI, localName, qName);
// Check after popping the stack so we don't erroneously think we
// are our own extension namespace...
boolean inExtension = inExtensionNamespace();
int entryType = -1;
Vector entryArgs = new Vector();
if (namespaceURI != null
&& (extendedNamespaceName.equals(namespaceURI))
&& !inExtension) {
String popURI = (String) baseURIStack.pop();
String baseURI = (String) baseURIStack.peek();
if (!baseURI.equals(popURI)) {
entryType = Catalog.BASE;
entryArgs.add(baseURI);
debug.message(4, "(reset) xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (rbase)", localName);
}
}
}
}
}
}

View File

@ -1,546 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
import java.util.Enumeration;
import java.util.Stack;
import java.util.Vector;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.*;
import org.xml.sax.*;
/**
* Parse OASIS Entity Resolution Technical Committee
* XML Catalog files.
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalogParser {
/** The catalog object needs to be stored by the object so that
* SAX callbacks can use it.
*/
protected Catalog catalog = null;
/** The namespace name of OASIS ERTC catalogs */
public static final String namespaceName = "urn:oasis:names:tc:entity:xmlns:xml:catalog";
/** The namespace name of OASIS ERTC TR9401 catalog extension */
public static final String tr9401NamespaceName = "urn:oasis:names:tc:entity:xmlns:tr9401:catalog";
protected Stack baseURIStack = new Stack();
protected Stack overrideStack = new Stack();
protected Stack namespaceStack = new Stack();
/** Set the current catalog. */
public void setCatalog (Catalog catalog) {
this.catalog = catalog;
debug = catalog.getCatalogManager().debug;
}
/** Get the current catalog. */
public Catalog getCatalog () {
return catalog;
}
/** Default constructor */
public OASISXMLCatalogReader() {
super();
}
/** Constructor allowing for providing custom SAX parser factory */
public OASISXMLCatalogReader(SAXParserFactory parserFactory, Catalog catalog) {
super(parserFactory);
setCatalog(catalog);
}
/**
* Are we in an extension namespace?
*
* @return true if the current stack of open namespaces includes
* an extension namespace.
*/
protected boolean inExtensionNamespace() {
boolean inExtension = false;
Enumeration elements = namespaceStack.elements();
while (!inExtension && elements.hasMoreElements()) {
String ns = (String) elements.nextElement();
if (ns == null) {
inExtension = true;
} else {
inExtension = (!ns.equals(tr9401NamespaceName)
&& !ns.equals(namespaceName));
}
}
return inExtension;
}
// ----------------------------------------------------------------------
// Implement the SAX ContentHandler interface
/** The SAX <code>setDocumentLocator</code> method does nothing. */
public void setDocumentLocator (Locator locator) {
return;
}
/** The SAX <code>startDocument</code> */
public void startDocument ()
throws SAXException {
baseURIStack.push(catalog.getCurrentBase());
overrideStack.push(catalog.getDefaultOverride());
return;
}
/** The SAX <code>endDocument</code> method does nothing. */
public void endDocument ()
throws SAXException {
return;
}
/**
* The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
namespaceStack.push(namespaceURI);
boolean inExtension = inExtensionNamespace();
if (namespaceURI != null && namespaceName.equals(namespaceURI)
&& !inExtension) {
// This is an XML Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if ((localName.equals("catalog") || localName.equals("group"))
&& atts.getValue("prefer") != null) {
String override = atts.getValue("prefer");
if (override.equals("public")) {
override = "yes";
} else if (override.equals("system")) {
override = "no";
} else {
debug.message(1,
"Invalid prefer: must be 'system' or 'public'",
localName);
override = catalog.getDefaultOverride();
}
entryType = Catalog.OVERRIDE;
entryArgs.add(override);
overrideStack.push(override);
debug.message(4, "override", override);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (override)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
overrideStack.push(overrideStack.peek());
}
if (localName.equals("delegatePublic")) {
if (checkAttributes(atts, "publicIdStartString", "catalog")) {
entryType = Catalog.DELEGATE_PUBLIC;
entryArgs.add(atts.getValue("publicIdStartString"));
entryArgs.add(atts.getValue("catalog"));
debug.message(4, "delegatePublic",
PublicId.normalize(atts.getValue("publicIdStartString")),
atts.getValue("catalog"));
}
} else if (localName.equals("delegateSystem")) {
if (checkAttributes(atts, "systemIdStartString", "catalog")) {
entryType = Catalog.DELEGATE_SYSTEM;
entryArgs.add(atts.getValue("systemIdStartString"));
entryArgs.add(atts.getValue("catalog"));
debug.message(4, "delegateSystem",
atts.getValue("systemIdStartString"),
atts.getValue("catalog"));
}
} else if (localName.equals("delegateURI")) {
if (checkAttributes(atts, "uriStartString", "catalog")) {
entryType = Catalog.DELEGATE_URI;
entryArgs.add(atts.getValue("uriStartString"));
entryArgs.add(atts.getValue("catalog"));
debug.message(4, "delegateURI",
atts.getValue("uriStartString"),
atts.getValue("catalog"));
}
} else if (localName.equals("rewriteSystem")) {
if (checkAttributes(atts, "systemIdStartString", "rewritePrefix")) {
entryType = Catalog.REWRITE_SYSTEM;
entryArgs.add(atts.getValue("systemIdStartString"));
entryArgs.add(atts.getValue("rewritePrefix"));
debug.message(4, "rewriteSystem",
atts.getValue("systemIdStartString"),
atts.getValue("rewritePrefix"));
}
} else if (localName.equals("systemSuffix")) {
if (checkAttributes(atts, "systemIdSuffix", "uri")) {
entryType = Catalog.SYSTEM_SUFFIX;
entryArgs.add(atts.getValue("systemIdSuffix"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "systemSuffix",
atts.getValue("systemIdSuffix"),
atts.getValue("uri"));
}
} else if (localName.equals("rewriteURI")) {
if (checkAttributes(atts, "uriStartString", "rewritePrefix")) {
entryType = Catalog.REWRITE_URI;
entryArgs.add(atts.getValue("uriStartString"));
entryArgs.add(atts.getValue("rewritePrefix"));
debug.message(4, "rewriteURI",
atts.getValue("uriStartString"),
atts.getValue("rewritePrefix"));
}
} else if (localName.equals("uriSuffix")) {
if (checkAttributes(atts, "uriSuffix", "uri")) {
entryType = Catalog.URI_SUFFIX;
entryArgs.add(atts.getValue("uriSuffix"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "uriSuffix",
atts.getValue("uriSuffix"),
atts.getValue("uri"));
}
} else if (localName.equals("nextCatalog")) {
if (checkAttributes(atts, "catalog")) {
entryType = Catalog.CATALOG;
entryArgs.add(atts.getValue("catalog"));
debug.message(4, "nextCatalog", atts.getValue("catalog"));
}
} else if (localName.equals("public")) {
if (checkAttributes(atts, "publicId", "uri")) {
entryType = Catalog.PUBLIC;
entryArgs.add(atts.getValue("publicId"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "public",
PublicId.normalize(atts.getValue("publicId")),
atts.getValue("uri"));
}
} else if (localName.equals("system")) {
if (checkAttributes(atts, "systemId", "uri")) {
entryType = Catalog.SYSTEM;
entryArgs.add(atts.getValue("systemId"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "system",
atts.getValue("systemId"),
atts.getValue("uri"));
}
} else if (localName.equals("uri")) {
if (checkAttributes(atts, "name", "uri")) {
entryType = Catalog.URI;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
debug.message(4, "uri",
atts.getValue("name"),
atts.getValue("uri"));
}
} else if (localName.equals("catalog")) {
// nop, start of catalog
} else if (localName.equals("group")) {
// nop, a group
} else {
// This is equivalent to an invalid catalog entry type
debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
if (namespaceURI != null && tr9401NamespaceName.equals(namespaceURI)
&& !inExtension) {
// This is a TR9401 Catalog entry
if (atts.getValue("xml:base") != null) {
String baseURI = atts.getValue("xml:base");
entryType = Catalog.BASE;
entryArgs.add(baseURI);
baseURIStack.push(baseURI);
debug.message(4, "xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (base)", localName);
}
}
entryType = -1;
entryArgs = new Vector();
} else {
baseURIStack.push(baseURIStack.peek());
}
if (localName.equals("doctype")) {
entryType = Catalog.DOCTYPE;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("document")) {
entryType = Catalog.DOCUMENT;
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("dtddecl")) {
entryType = Catalog.DTDDECL;
entryArgs.add(atts.getValue("publicId"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("entity")) {
entryType = Catalog.ENTITY;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("linktype")) {
entryType = Catalog.LINKTYPE;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("notation")) {
entryType = Catalog.NOTATION;
entryArgs.add(atts.getValue("name"));
entryArgs.add(atts.getValue("uri"));
} else if (localName.equals("sgmldecl")) {
entryType = Catalog.SGMLDECL;
entryArgs.add(atts.getValue("uri"));
} else {
// This is equivalent to an invalid catalog entry type
debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
}
public boolean checkAttributes (Attributes atts, String attName) {
if (atts.getValue(attName) == null) {
debug.message(1, "Error: required attribute " + attName + " missing.");
return false;
} else {
return true;
}
}
public boolean checkAttributes (Attributes atts,
String attName1,
String attName2) {
return checkAttributes(atts, attName1)
&& checkAttributes(atts, attName2);
}
/** The SAX <code>endElement</code> */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
boolean inExtension = inExtensionNamespace();
if (namespaceURI != null
&& !inExtension
&& (namespaceName.equals(namespaceURI)
|| tr9401NamespaceName.equals(namespaceURI))) {
String popURI = (String) baseURIStack.pop();
String baseURI = (String) baseURIStack.peek();
if (!baseURI.equals(popURI)) {
entryType = Catalog.BASE;
entryArgs.add(baseURI);
debug.message(4, "(reset) xml:base", baseURI);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (rbase)", localName);
}
}
}
}
if (namespaceURI != null && namespaceName.equals(namespaceURI)
&& !inExtension) {
if (localName.equals("catalog") || localName.equals("group")) {
String popOverride = (String) overrideStack.pop();
String override = (String) overrideStack.peek();
if (!override.equals(popOverride)) {
entryType = Catalog.OVERRIDE;
entryArgs.add(override);
overrideStack.push(override);
debug.message(4, "(reset) override", override);
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry (roverride)", localName);
}
}
}
}
}
namespaceStack.pop();
return;
}
/** The SAX <code>characters</code> method does nothing. */
public void characters (char ch[], int start, int length)
throws SAXException {
return;
}
/** The SAX <code>ignorableWhitespace</code> method does nothing. */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
return;
}
/** The SAX <code>processingInstruction</code> method does nothing. */
public void processingInstruction (String target, String data)
throws SAXException {
return;
}
/** The SAX <code>skippedEntity</code> method does nothing. */
public void skippedEntity (String name)
throws SAXException {
return;
}
/** The SAX <code>startPrefixMapping</code> method does nothing. */
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
return;
}
/** The SAX <code>endPrefixMapping</code> method does nothing. */
public void endPrefixMapping(String prefix)
throws SAXException {
return;
}
}

View File

@ -1,39 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import org.xml.sax.*;
/**
* The SAXCatalogParser interface.
*
* <p>This interface must be implemented in order for a class to
* participate as a parser for the SAXCatalogReader.
*
* @see Catalog
* @see SAXCatalogReader
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public interface SAXCatalogParser extends ContentHandler, DocumentHandler {
/** Set the Catalog for which parsing is being performed. */
public void setCatalog(Catalog catalog);
}

View File

@ -1,503 +0,0 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import com.sun.org.apache.xml.internal.resolver.helpers.Debug;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.AttributeList;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import sun.reflect.misc.ReflectUtil;
/**
* A SAX-based CatalogReader.
*
* <p>This class is used to read XML Catalogs using the SAX. This reader
* has an advantage over the DOM-based reader in that it functions on
* the stream of SAX events. It has the disadvantage
* that it cannot look around in the tree.</p>
*
* <p>Since the choice of CatalogReaders (in the InputStream case) can only
* be made on the basis of MIME type, the following problem occurs: only
* one CatalogReader can exist for all XML mime types. In order to get
* around this problem, the SAXCatalogReader relies on a set of external
* CatalogParsers to actually build the catalog.</p>
*
* <p>The selection of CatalogParsers is made on the basis of the QName
* of the root element of the document.</p>
*
* @see Catalog
* @see CatalogReader
* @see SAXCatalogReader
* @see TextCatalogReader
* @see DOMCatalogParser
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class SAXCatalogReader implements CatalogReader, ContentHandler, DocumentHandler {
/** The SAX Parser Factory */
protected SAXParserFactory parserFactory = null;
/** The SAX Parser Class */
protected String parserClass = null;
/**
* Mapping table from QNames to CatalogParser classes.
*
* <p>Each key in this hash table has the form "elementname"
* or "{namespaceuri}elementname". The former is used if the
* namespace URI is null.</p>
*/
protected Map<String, String> namespaceMap = new HashMap<>();
/** The parser in use for the current catalog. */
private SAXCatalogParser saxParser = null;
/** Set if something goes horribly wrong. It allows the class to
* ignore the rest of the events that are received.
*/
private boolean abandonHope = false;
/** The Catalog that we're working for. */
private Catalog catalog;
/** Set the XML SAX Parser Factory.
*/
public void setParserFactory(SAXParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
/** Set the XML SAX Parser Class
*/
public void setParserClass(String parserClass) {
this.parserClass = parserClass;
}
/** Get the parser factory currently in use. */
public SAXParserFactory getParserFactory() {
return parserFactory;
}
/** Get the parser class currently in use. */
public String getParserClass() {
return parserClass;
}
/** The debug class to use for this reader.
*
* This is a bit of a hack. Anyway, whenever we read for a catalog,
* we extract the debug object
* from the catalog's manager so that we can use it to print messages.
*
* In production, we don't really expect any messages so it doesn't
* really matter. But it's still a bit of a hack.
*/
protected Debug debug = CatalogManager.getStaticManager().debug;
/** The constructor */
public SAXCatalogReader() {
parserFactory = null;
parserClass = null;
}
/** The constructor */
public SAXCatalogReader(SAXParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
/** The constructor */
public SAXCatalogReader(String parserClass) {
this.parserClass = parserClass;
}
/**
* Set the SAXCatalogParser class for the given namespace/root
* element type.
*/
public void setCatalogParser(String namespaceURI,
String rootElement,
String parserClass) {
namespaceURI = namespaceURI != null ? namespaceURI.trim() : "";
namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass);
}
/**
* Get the SAXCatalogParser class for the given namespace/root
* element type.
*/
public String getCatalogParser(String namespaceURI,
String rootElement) {
namespaceURI = namespaceURI != null ? namespaceURI.trim() : "";
return namespaceMap.get("{"+namespaceURI+"}"+rootElement);
}
/**
* Parse an XML Catalog file.
*
* @param catalog The catalog to which this catalog file belongs
* @param fileUrl The URL or filename of the catalog file to process
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException,
CatalogException {
URL url = null;
try {
url = new URL(fileUrl);
} catch (MalformedURLException e) {
url = new URL("file:///" + fileUrl);
}
debug = catalog.getCatalogManager().debug;
try {
URLConnection urlCon = url.openConnection();
readCatalog(catalog, urlCon.getInputStream());
} catch (FileNotFoundException e) {
catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
url.toString());
}
}
/**
* Parse an XML Catalog stream.
*
* @param catalog The catalog to which this catalog file belongs
* @param is The input stream from which the catalog will be read
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
* @throws CatalogException A Catalog exception
*/
public void readCatalog(Catalog catalog, InputStream is)
throws IOException, CatalogException {
// Create an instance of the parser
if (parserFactory == null && parserClass == null) {
debug.message(1, "Cannot read SAX catalog without a parser");
throw new CatalogException(CatalogException.UNPARSEABLE);
}
debug = catalog.getCatalogManager().debug;
EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver();
this.catalog = catalog;
try {
if (parserFactory != null) {
SAXParser parser = parserFactory.newSAXParser();
SAXParserHandler spHandler = new SAXParserHandler();
spHandler.setContentHandler(this);
if (bResolver != null) {
spHandler.setEntityResolver(bResolver);
}
parser.parse(new InputSource(is), spHandler);
} else {
Class<?> c = ReflectUtil.forName(parserClass);
if (!Parser.class.isAssignableFrom(c)) {
throw new ClassCastException(parserClass
+ " cannot be cast to "
+ Parser.class.getName());
}
Parser parser = (Parser) c.newInstance();
parser.setDocumentHandler(this);
if (bResolver != null) {
parser.setEntityResolver(bResolver);
}
parser.parse(new InputSource(is));
}
} catch (ClassNotFoundException cnfe) {
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (IllegalAccessException iae) {
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (InstantiationException ie) {
throw new CatalogException(CatalogException.UNPARSEABLE);
} catch (ParserConfigurationException pce) {
throw new CatalogException(CatalogException.UNKNOWN_FORMAT);
} catch (SAXException se) {
Exception e = se.getException();
// FIXME: there must be a better way
UnknownHostException uhe = new UnknownHostException();
FileNotFoundException fnfe = new FileNotFoundException();
if (e != null) {
if (e.getClass() == uhe.getClass()) {
throw new CatalogException(CatalogException.PARSE_FAILED,
e.toString());
} else if (e.getClass() == fnfe.getClass()) {
throw new CatalogException(CatalogException.PARSE_FAILED,
e.toString());
}
}
throw new CatalogException(se);
}
}
// ----------------------------------------------------------------------
// Implement the SAX ContentHandler interface
/** The SAX <code>setDocumentLocator</code> method. Does nothing. */
public void setDocumentLocator (Locator locator) {
if (saxParser != null) {
saxParser.setDocumentLocator(locator);
}
}
/** The SAX <code>startDocument</code> method. Does nothing. */
public void startDocument () throws SAXException {
saxParser = null;
abandonHope = false;
return;
}
/** The SAX <code>endDocument</code> method. Does nothing. */
public void endDocument ()throws SAXException {
if (saxParser != null) {
saxParser.endDocument();
}
}
/**
* The SAX <code>startElement</code> method.
*
* <p>The catalog parser is selected based on the namespace of the
* first element encountered in the catalog.</p>
*/
public void startElement (String name,
AttributeList atts)
throws SAXException {
if (abandonHope) {
return;
}
if (saxParser == null) {
String prefix = "";
if (name.indexOf(':') > 0) {
prefix = name.substring(0, name.indexOf(':'));
}
String localName = name;
if (localName.indexOf(':') > 0) {
localName = localName.substring(localName.indexOf(':')+1);
}
String namespaceURI = null;
if (prefix.length() == 0) {
namespaceURI = atts.getValue("xmlns");
} else {
namespaceURI = atts.getValue("xmlns:" + prefix);
}
String saxParserClass = getCatalogParser(namespaceURI,
localName);
if (saxParserClass == null) {
abandonHope = true;
if (namespaceURI == null) {
debug.message(2, "No Catalog parser for " + name);
} else {
debug.message(2, "No Catalog parser for "
+ "{" + namespaceURI + "}"
+ name);
}
return;
}
try {
saxParser = (SAXCatalogParser)
ReflectUtil.forName(saxParserClass).newInstance();
saxParser.setCatalog(catalog);
saxParser.startDocument();
saxParser.startElement(name, atts);
} catch (ClassNotFoundException cnfe) {
saxParser = null;
abandonHope = true;
debug.message(2, cnfe.toString());
} catch (InstantiationException ie) {
saxParser = null;
abandonHope = true;
debug.message(2, ie.toString());
} catch (IllegalAccessException iae) {
saxParser = null;
abandonHope = true;
debug.message(2, iae.toString());
} catch (ClassCastException cce ) {
saxParser = null;
abandonHope = true;
debug.message(2, cce.toString());
}
} else {
saxParser.startElement(name, atts);
}
}
/**
* The SAX2 <code>startElement</code> method.
*
* <p>The catalog parser is selected based on the namespace of the
* first element encountered in the catalog.</p>
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
if (abandonHope) {
return;
}
if (saxParser == null) {
String saxParserClass = getCatalogParser(namespaceURI,
localName);
if (saxParserClass == null) {
abandonHope = true;
if (namespaceURI == null) {
debug.message(2, "No Catalog parser for " + localName);
} else {
debug.message(2, "No Catalog parser for "
+ "{" + namespaceURI + "}"
+ localName);
}
return;
}
try {
saxParser = (SAXCatalogParser)
ReflectUtil.forName(saxParserClass).newInstance();
saxParser.setCatalog(catalog);
saxParser.startDocument();
saxParser.startElement(namespaceURI, localName, qName, atts);
} catch (ClassNotFoundException cnfe) {
saxParser = null;
abandonHope = true;
debug.message(2, cnfe.toString());
} catch (InstantiationException ie) {
saxParser = null;
abandonHope = true;
debug.message(2, ie.toString());
} catch (IllegalAccessException iae) {
saxParser = null;
abandonHope = true;
debug.message(2, iae.toString());
} catch (ClassCastException cce ) {
saxParser = null;
abandonHope = true;
debug.message(2, cce.toString());
}
} else {
saxParser.startElement(namespaceURI, localName, qName, atts);
}
}
/** The SAX <code>endElement</code> method. Does nothing. */
public void endElement (String name) throws SAXException {
if (saxParser != null) {
saxParser.endElement(name);
}
}
/** The SAX2 <code>endElement</code> method. Does nothing. */
public void endElement (String namespaceURI,
String localName,
String qName) throws SAXException {
if (saxParser != null) {
saxParser.endElement(namespaceURI, localName, qName);
}
}
/** The SAX <code>characters</code> method. Does nothing. */
public void characters (char ch[], int start, int length)
throws SAXException {
if (saxParser != null) {
saxParser.characters(ch, start, length);
}
}
/** The SAX <code>ignorableWhitespace</code> method. Does nothing. */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
if (saxParser != null) {
saxParser.ignorableWhitespace(ch, start, length);
}
}
/** The SAX <code>processingInstruction</code> method. Does nothing. */
public void processingInstruction (String target, String data)
throws SAXException {
if (saxParser != null) {
saxParser.processingInstruction(target, data);
}
}
/** The SAX <code>startPrefixMapping</code> method. Does nothing. */
public void startPrefixMapping (String prefix, String uri)
throws SAXException {
if (saxParser != null) {
saxParser.startPrefixMapping (prefix, uri);
}
}
/** The SAX <code>endPrefixMapping</code> method. Does nothing. */
public void endPrefixMapping (String prefix)
throws SAXException {
if (saxParser != null) {
saxParser.endPrefixMapping (prefix);
}
}
/** The SAX <code>skippedentity</code> method. Does nothing. */
public void skippedEntity (String name)
throws SAXException {
if (saxParser != null) {
saxParser.skippedEntity(name);
}
}
}

View File

@ -1,144 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import java.io.IOException;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
/**
* An entity-resolving DefaultHandler.
*
* <p>This class provides a SAXParser DefaultHandler that performs
* entity resolution.
* </p>
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*/
public class SAXParserHandler extends DefaultHandler {
private EntityResolver er = null;
private ContentHandler ch = null;
public SAXParserHandler() {
super();
}
public void setEntityResolver(EntityResolver er) {
this.er = er;
}
public void setContentHandler(ContentHandler ch) {
this.ch = ch;
}
// Entity Resolver
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException {
if (er != null) {
try {
return er.resolveEntity(publicId, systemId);
} catch (IOException e) {
System.out.println("resolveEntity threw IOException!");
return null;
}
} else {
return null;
}
}
// Content Handler
public void characters(char[] ch, int start, int length)
throws SAXException {
if (this.ch != null) {
this.ch.characters(ch, start, length);
}
}
public void endDocument()
throws SAXException {
if (ch != null) {
ch.endDocument();
}
}
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (ch != null) {
ch.endElement(namespaceURI, localName, qName);
}
}
public void endPrefixMapping(String prefix)
throws SAXException {
if (ch != null) {
ch.endPrefixMapping(prefix);
}
}
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
if (this.ch != null) {
this.ch.ignorableWhitespace(ch, start, length);
}
}
public void processingInstruction(String target, String data)
throws SAXException {
if (ch != null) {
ch.processingInstruction(target, data);
}
}
public void setDocumentLocator(Locator locator) {
if (ch != null) {
ch.setDocumentLocator(locator);
}
}
public void skippedEntity(String name)
throws SAXException {
if (ch != null) {
ch.skippedEntity(name);
}
}
public void startDocument()
throws SAXException {
if (ch != null) {
ch.startDocument();
}
}
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException {
if (ch != null) {
ch.startElement(namespaceURI, localName, qName, atts);
}
}
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
if (ch != null) {
ch.startPrefixMapping(prefix, uri);
}
}
}

View File

@ -1,138 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.Locale;
import java.util.Vector;
/**
* Parses OASIS Open Catalog files.
*
* <p>This class reads OASIS Open Catalog files, returning a stream
* of tokens.</p>
*
* <p>This code interrogates the following non-standard system properties:</p>
*
* <dl>
* <dt><b>xml.catalog.debug</b></dt>
* <dd><p>Sets the debug level. A value of 0 is assumed if the
* property is not set or is not a number.</p></dd>
* </dl>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class TR9401CatalogReader extends TextCatalogReader {
/**
* Start parsing an OASIS TR9401 Open Catalog file. The file is
* actually read and parsed
* as needed by <code>nextEntry</code>.
*
* <p>In a TR9401 Catalog the 'DELEGATE' entry delegates public
* identifiers. There is no delegate entry for system identifiers
* or URIs.</p>
*
* @param catalog The Catalog to populate
* @param is The input stream from which to read the TR9401 Catalog
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
*/
public void readCatalog(Catalog catalog, InputStream is)
throws MalformedURLException, IOException {
catfile = is;
if (catfile == null) {
return;
}
Vector unknownEntry = null;
try {
while (true) {
String token = nextToken();
if (token == null) {
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
catfile.close();
catfile = null;
return;
}
String entryToken = null;
if (caseSensitive) {
entryToken = token;
} else {
entryToken = token.toUpperCase(Locale.ENGLISH);
}
if (entryToken.equals("DELEGATE")) {
entryToken = "DELEGATE_PUBLIC";
}
try {
int type = CatalogEntry.getEntryType(entryToken);
int numArgs = CatalogEntry.getEntryArgCount(type);
Vector args = new Vector();
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
for (int count = 0; count < numArgs; count++) {
args.addElement(nextToken());
}
catalog.addEntry(new CatalogEntry(entryToken, args));
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
if (unknownEntry == null) {
unknownEntry = new Vector();
}
unknownEntry.addElement(token);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", token);
unknownEntry = null;
} else if (cex.getExceptionType() == CatalogException.UNENDED_COMMENT) {
catalog.getCatalogManager().debug.message(1, cex.getMessage());
}
}
}
} catch (CatalogException cex2) {
if (cex2.getExceptionType() == CatalogException.UNENDED_COMMENT) {
catalog.getCatalogManager().debug.message(1, cex2.getMessage());
}
}
}
}

View File

@ -1,298 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;
import java.util.Stack;
import java.util.Vector;
/**
* Parses plain text Catalog files.
*
* <p>This class reads plain text Open Catalog files.</p>
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class TextCatalogReader implements CatalogReader {
/** The input stream used to read the catalog */
protected InputStream catfile = null;
/**
* Character lookahead stack. Reading a catalog sometimes requires
* up to two characters of lookahead.
*/
protected int[] stack = new int[3];
/**
* Token stack. Recognizing an unexpected catalog entry requires
* the ability to "push back" a token.
*/
protected Stack tokenStack = new Stack();
/** The current position on the lookahead stack */
protected int top = -1;
/** Are keywords in the catalog case sensitive? */
protected boolean caseSensitive = false;
/**
* Construct a CatalogReader object.
*/
public TextCatalogReader() { }
public void setCaseSensitive(boolean isCaseSensitive) {
caseSensitive = isCaseSensitive;
}
public boolean getCaseSensitive() {
return caseSensitive;
}
/**
* Start parsing a text catalog file. The file is
* actually read and parsed
* as needed by <code>nextEntry</code>.</p>
*
* @param fileUrl The URL or filename of the catalog file to process
*
* @throws MalformedURLException Improper fileUrl
* @throws IOException Error reading catalog file
*/
public void readCatalog(Catalog catalog, String fileUrl)
throws MalformedURLException, IOException {
URL catURL = null;
try {
catURL = new URL(fileUrl);
} catch (MalformedURLException e) {
catURL = new URL("file:///" + fileUrl);
}
URLConnection urlCon = catURL.openConnection();
try {
readCatalog(catalog, urlCon.getInputStream());
} catch (FileNotFoundException e) {
catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found",
catURL.toString());
}
}
public void readCatalog(Catalog catalog, InputStream is)
throws MalformedURLException, IOException {
catfile = is;
if (catfile == null) {
return;
}
Vector unknownEntry = null;
try {
while (true) {
String token = nextToken();
if (token == null) {
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
catfile.close();
catfile = null;
return;
}
String entryToken = null;
if (caseSensitive) {
entryToken = token;
} else {
entryToken = token.toUpperCase(Locale.ENGLISH);
}
try {
int type = CatalogEntry.getEntryType(entryToken);
int numArgs = CatalogEntry.getEntryArgCount(type);
Vector args = new Vector();
if (unknownEntry != null) {
catalog.unknownEntry(unknownEntry);
unknownEntry = null;
}
for (int count = 0; count < numArgs; count++) {
args.addElement(nextToken());
}
catalog.addEntry(new CatalogEntry(entryToken, args));
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
if (unknownEntry == null) {
unknownEntry = new Vector();
}
unknownEntry.addElement(token);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", token);
unknownEntry = null;
} else if (cex.getExceptionType() == CatalogException.UNENDED_COMMENT) {
catalog.getCatalogManager().debug.message(1, cex.getMessage());
}
}
}
} catch (CatalogException cex2) {
if (cex2.getExceptionType() == CatalogException.UNENDED_COMMENT) {
catalog.getCatalogManager().debug.message(1, cex2.getMessage());
}
}
}
/**
* The destructor.
*
* <p>Makes sure the catalog file is closed.</p>
*/
protected void finalize() {
if (catfile != null) {
try {
catfile.close();
} catch (IOException e) {
// whatever...
}
}
catfile = null;
}
// -----------------------------------------------------------------
/**
* Return the next token in the catalog file.
*
* <p>FYI: This code does not throw any sort of exception for
* a file that contains an n
*
* @return The Catalog file token from the input stream.
* @throws IOException If an error occurs reading from the stream.
*/
protected String nextToken() throws IOException, CatalogException {
String token = "";
int ch, nextch;
if (!tokenStack.empty()) {
return (String) tokenStack.pop();
}
// Skip over leading whitespace and comments
while (true) {
// skip leading whitespace
ch = catfile.read();
while (ch <= ' ') { // all ctrls are whitespace
ch = catfile.read();
if (ch < 0) {
return null;
}
}
// now 'ch' is the current char from the file
nextch = catfile.read();
if (nextch < 0) {
return null;
}
if (ch == '-' && nextch == '-') {
// we've found a comment, skip it...
ch = ' ';
nextch = nextChar();
while ((ch != '-' || nextch != '-') && nextch > 0) {
ch = nextch;
nextch = nextChar();
}
if (nextch < 0) {
throw new CatalogException(CatalogException.UNENDED_COMMENT,
"Unterminated comment in catalog file; EOF treated as end-of-comment.");
}
// Ok, we've found the end of the comment,
// loop back to the top and start again...
} else {
stack[++top] = nextch;
stack[++top] = ch;
break;
}
}
ch = nextChar();
if (ch == '"' || ch == '\'') {
int quote = ch;
while ((ch = nextChar()) != quote) {
char[] chararr = new char[1];
chararr[0] = (char) ch;
String s = new String(chararr);
token = token.concat(s);
}
return token;
} else {
// return the next whitespace or comment delimited
// string
while (ch > ' ') {
nextch = nextChar();
if (ch == '-' && nextch == '-') {
stack[++top] = ch;
stack[++top] = nextch;
return token;
} else {
char[] chararr = new char[1];
chararr[0] = (char) ch;
String s = new String(chararr);
token = token.concat(s);
ch = nextch;
}
}
return token;
}
}
/**
* Return the next logical character from the input stream.
*
* @return The next (logical) character from the input stream. The
* character may be buffered from a previous lookahead.
*
* @throws IOException If an error occurs reading from the stream.
*/
protected int nextChar() throws IOException {
if (top < 0) {
return catfile.read();
} else {
return stack[top--];
}
}
}

View File

@ -1,208 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.readers;
import java.util.Vector;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogEntry;
import com.sun.org.apache.xml.internal.resolver.CatalogException;
import com.sun.org.apache.xml.internal.resolver.helpers.PublicId;
import org.xml.sax.*;
import javax.xml.parsers.*;
/**
* Parse "XCatalog" XML Catalog files, this is the XML Catalog format
* developed by John Cowan and supported by Apache.
*
* @see Catalog
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
*/
public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser {
/** The catalog object needs to be stored by the object so that
* SAX callbacks can use it.
*/
protected Catalog catalog = null;
/** Set the current catalog. */
public void setCatalog (Catalog catalog) {
this.catalog = catalog;
debug = catalog.getCatalogManager().debug;
}
/** Get the current catalog. */
public Catalog getCatalog () {
return catalog;
}
/** Default constructor */
public XCatalogReader() {
super();
}
/** Constructor allowing for providing custom SAX parser factory */
public XCatalogReader(SAXParserFactory parserFactory, Catalog catalog) {
super(parserFactory);
setCatalog(catalog);
}
// ----------------------------------------------------------------------
// Implement the SAX ContentHandler interface
/** The SAX <code>setDocumentLocator</code> method does nothing. */
public void setDocumentLocator (Locator locator) {
return;
}
/** The SAX <code>startDocument</code> method does nothing. */
public void startDocument ()
throws SAXException {
return;
}
/** The SAX <code>endDocument</code> method does nothing. */
public void endDocument ()
throws SAXException {
return;
}
/**
* The SAX <code>startElement</code> method recognizes elements
* from the plain catalog format and instantiates CatalogEntry
* objects for them.
*
* @param namespaceURI The namespace name of the element.
* @param localName The local name of the element.
* @param qName The QName of the element.
* @param atts The list of attributes on the element.
*
* @see CatalogEntry
*/
public void startElement (String namespaceURI,
String localName,
String qName,
Attributes atts)
throws SAXException {
int entryType = -1;
Vector entryArgs = new Vector();
if (localName.equals("Base")) {
entryType = Catalog.BASE;
entryArgs.add(atts.getValue("HRef"));
debug.message(4, "Base", atts.getValue("HRef"));
} else if (localName.equals("Delegate")) {
entryType = Catalog.DELEGATE_PUBLIC;
entryArgs.add(atts.getValue("PublicID"));
entryArgs.add(atts.getValue("HRef"));
debug.message(4, "Delegate",
PublicId.normalize(atts.getValue("PublicID")),
atts.getValue("HRef"));
} else if (localName.equals("Extend")) {
entryType = Catalog.CATALOG;
entryArgs.add(atts.getValue("HRef"));
debug.message(4, "Extend", atts.getValue("HRef"));
} else if (localName.equals("Map")) {
entryType = Catalog.PUBLIC;
entryArgs.add(atts.getValue("PublicID"));
entryArgs.add(atts.getValue("HRef"));
debug.message(4, "Map",
PublicId.normalize(atts.getValue("PublicID")),
atts.getValue("HRef"));
} else if (localName.equals("Remap")) {
entryType = Catalog.SYSTEM;
entryArgs.add(atts.getValue("SystemID"));
entryArgs.add(atts.getValue("HRef"));
debug.message(4, "Remap",
atts.getValue("SystemID"),
atts.getValue("HRef"));
} else if (localName.equals("XCatalog")) {
// nop, start of catalog
} else {
// This is equivalent to an invalid catalog entry type
debug.message(1, "Invalid catalog entry type", localName);
}
if (entryType >= 0) {
try {
CatalogEntry ce = new CatalogEntry(entryType, entryArgs);
catalog.addEntry(ce);
} catch (CatalogException cex) {
if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) {
debug.message(1, "Invalid catalog entry type", localName);
} else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) {
debug.message(1, "Invalid catalog entry", localName);
}
}
}
}
/** The SAX <code>endElement</code> method does nothing. */
public void endElement (String namespaceURI,
String localName,
String qName)
throws SAXException {
return;
}
/** The SAX <code>characters</code> method does nothing. */
public void characters (char ch[], int start, int length)
throws SAXException {
return;
}
/** The SAX <code>ignorableWhitespace</code> method does nothing. */
public void ignorableWhitespace (char ch[], int start, int length)
throws SAXException {
return;
}
/** The SAX <code>processingInstruction</code> method does nothing. */
public void processingInstruction (String target, String data)
throws SAXException {
return;
}
/** The SAX <code>skippedEntity</code> method does nothing. */
public void skippedEntity (String name)
throws SAXException {
return;
}
/** The SAX <code>startPrefixMapping</code> method does nothing. */
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
return;
}
/** The SAX <code>endPrefixMapping</code> method does nothing. */
public void endPrefixMapping(String prefix)
throws SAXException {
return;
}
}

View File

@ -1,349 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.tools;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.MalformedURLException;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.EntityResolver;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.Source;
import javax.xml.transform.URIResolver;
import javax.xml.transform.TransformerException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
/**
* A SAX EntityResolver/JAXP URIResolver that uses catalogs.
*
* <p>This class implements both a SAX EntityResolver and a JAXP URIResolver.
* </p>
*
* <p>This resolver understands OASIS TR9401 catalogs, XCatalogs, and the
* current working draft of the OASIS Entity Resolution Technical
* Committee specification.</p>
*
* @see Catalog
* @see org.xml.sax.EntityResolver
* @see javax.xml.transform.URIResolver
* @deprecated The JDK internal Catalog API in package
* {@code com.sun.org.apache.xml.internal.resolver}
* is encapsulated in JDK 9. The entire implementation under the package is now
* deprecated and subject to removal in a future release. Users of the API
* should migrate to the {@linkplain javax.xml.catalog new public API}.
* <p>
* The new Catalog API is supported throughout the JDK XML Processors, which allows
* the use of Catalog by simply setting a path to a Catalog file as a property.
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
@Deprecated(since="9", forRemoval=true)
public class CatalogResolver implements EntityResolver, URIResolver {
/** Make the parser Namespace aware? */
public boolean namespaceAware = true;
/** Make the parser validating? */
public boolean validating = false;
/** The underlying catalog */
private Catalog catalog = null;
/** The catalog manager */
private CatalogManager catalogManager = CatalogManager.getStaticManager();
/** Constructor */
public CatalogResolver() {
initializeCatalogs(false);
}
/** Constructor */
public CatalogResolver(boolean privateCatalog) {
initializeCatalogs(privateCatalog);
}
/** Constructor */
public CatalogResolver(CatalogManager manager) {
catalogManager = manager;
initializeCatalogs(!catalogManager.getUseStaticCatalog());
}
/** Initialize catalog */
private void initializeCatalogs(boolean privateCatalog) {
catalog = catalogManager.getCatalog();
}
/** Return the underlying catalog */
public Catalog getCatalog() {
return catalog;
}
/**
* Implements the guts of the <code>resolveEntity</code> method
* for the SAX interface.
*
* <p>Presented with an optional public identifier and a system
* identifier, this function attempts to locate a mapping in the
* catalogs.</p>
*
* <p>If such a mapping is found, it is returned. If no mapping is
* found, null is returned.</p>
*
* @param publicId The public identifier for the entity in question.
* This may be null.
*
* @param systemId The system identifier for the entity in question.
* XML requires a system identifier on all external entities, so this
* value is always specified.
*
* @return The resolved identifier (a URI reference).
*/
public String getResolvedEntity (String publicId, String systemId) {
String resolved = null;
if (catalog == null) {
catalogManager.debug.message(1, "Catalog resolution attempted with null catalog; ignored");
return null;
}
if (systemId != null) {
try {
resolved = catalog.resolveSystem(systemId);
} catch (MalformedURLException me) {
catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
publicId);
resolved = null;
} catch (IOException ie) {
catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
resolved = null;
}
}
if (resolved == null) {
if (publicId != null) {
try {
resolved = catalog.resolvePublic(publicId, systemId);
} catch (MalformedURLException me) {
catalogManager.debug.message(1, "Malformed URL exception trying to resolve",
publicId);
} catch (IOException ie) {
catalogManager.debug.message(1, "I/O exception trying to resolve", publicId);
}
}
if (resolved != null) {
catalogManager.debug.message(2, "Resolved public", publicId, resolved);
}
} else {
catalogManager.debug.message(2, "Resolved system", systemId, resolved);
}
return resolved;
}
/**
* Implements the <code>resolveEntity</code> method
* for the SAX interface.
*
* <p>Presented with an optional public identifier and a system
* identifier, this function attempts to locate a mapping in the
* catalogs.</p>
*
* <p>If such a mapping is found, the resolver attempts to open
* the mapped value as an InputSource and return it. Exceptions are
* ignored and null is returned if the mapped value cannot be opened
* as an input source.</p>
*
* <p>If no mapping is found (or an error occurs attempting to open
* the mapped value as an input source), null is returned and the system
* will use the specified system identifier as if no entityResolver
* was specified.</p>
*
* @param publicId The public identifier for the entity in question.
* This may be null.
*
* @param systemId The system identifier for the entity in question.
* XML requires a system identifier on all external entities, so this
* value is always specified.
*
* @return An InputSource for the mapped identifier, or null.
*/
public InputSource resolveEntity (String publicId, String systemId) {
String resolved = getResolvedEntity(publicId, systemId);
if (resolved != null) {
try {
InputSource iSource = new InputSource(resolved);
iSource.setPublicId(publicId);
// Ideally this method would not attempt to open the
// InputStream, but there is a bug (in Xerces, at least)
// that causes the parser to mistakenly open the wrong
// system identifier if the returned InputSource does
// not have a byteStream.
//
// It could be argued that we still shouldn't do this here,
// but since the purpose of calling the entityResolver is
// almost certainly to open the input stream, it seems to
// do little harm.
//
URL url = new URL(resolved);
InputStream iStream = url.openStream();
iSource.setByteStream(iStream);
return iSource;
} catch (Exception e) {
catalogManager.debug.message(1,
"Failed to create InputSource ("
+ e.toString()
+ ")", resolved);
return null;
}
}
return null;
}
/** JAXP URIResolver API */
public Source resolve(String href, String base)
throws TransformerException {
String uri = href;
String fragment = null;
int hashPos = href.indexOf("#");
if (hashPos >= 0) {
uri = href.substring(0, hashPos);
fragment = href.substring(hashPos+1);
}
String result = null;
try {
result = catalog.resolveURI(href);
} catch (Exception e) {
// nop;
}
if (result == null) {
try {
URL url = null;
if (base==null) {
url = new URL(uri);
result = url.toString();
} else {
URL baseURL = new URL(base);
url = (href.length()==0 ? baseURL : new URL(baseURL, uri));
result = url.toString();
}
} catch (java.net.MalformedURLException mue) {
// try to make an absolute URI from the current base
String absBase = makeAbsolute(base);
if (!absBase.equals(base)) {
// don't bother if the absBase isn't different!
return resolve(href, absBase);
} else {
throw new TransformerException("Malformed URL "
+ href + "(base " + base + ")",
mue);
}
}
}
catalogManager.debug.message(2, "Resolved URI", href, result);
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(result));
setEntityResolver(source);
return source;
}
/**
* <p>Establish an entityResolver for newly resolved URIs.</p>
*
* <p>This is called from the URIResolver to set an EntityResolver
* on the SAX parser to be used for new XML documents that are
* encountered as a result of the document() function, xsl:import,
* or xsl:include. This is done because the XSLT processor calls
* out to the SAXParserFactory itself to create a new SAXParser to
* parse the new document. The new parser does not automatically
* inherit the EntityResolver of the original (although arguably
* it should). See below:</p>
*
* <tt>"If an application wants to set the ErrorHandler or
* EntityResolver for an XMLReader used during a transformation,
* it should use a URIResolver to return the SAXSource which
* provides (with getXMLReader) a reference to the XMLReader"</tt>
*
* <p>...quoted from page 118 of the Java API for XML
* Processing 1.1 specification</p>
*
*/
private void setEntityResolver(SAXSource source) throws TransformerException {
XMLReader reader = source.getXMLReader();
if (reader == null) {
SAXParserFactory spFactory = catalogManager.useServicesMechanism() ?
SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
spFactory.setNamespaceAware(true);
try {
reader = spFactory.newSAXParser().getXMLReader();
}
catch (ParserConfigurationException ex) {
throw new TransformerException(ex);
}
catch (SAXException ex) {
throw new TransformerException(ex);
}
}
reader.setEntityResolver(this);
source.setXMLReader(reader);
}
/** Attempt to construct an absolute URI */
private String makeAbsolute(String uri) {
if (uri == null) {
uri = "";
}
try {
URL url = new URL(uri);
return url.toString();
} catch (MalformedURLException mue) {
try {
URL fileURL = FileURL.makeURL(uri);
return fileURL.toString();
} catch (MalformedURLException mue2) {
// bail
return uri;
}
}
}
}

View File

@ -1,434 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.tools;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Locale;
import org.xml.sax.Parser;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.ErrorHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.AttributeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.SAXException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
/**
* A SAX Parser that performs catalog-based entity resolution.
*
* <p>This class implements a SAX Parser that performs entity resolution
* using the CatalogResolver. The actual, underlying parser is obtained
* from a SAXParserFactory.</p>
* </p>
*
* @deprecated This interface has been replaced by the
* {@link com.sun.org.apache.xml.internal.resolver.tools.ResolvingXMLReader} for SAX2.
* @see CatalogResolver
* @see org.xml.sax.Parser
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class ResolvingParser
implements Parser, DTDHandler, DocumentHandler, EntityResolver {
/** Suppress explanatory message?
*
* @see #parse(InputSource)
*/
private static final boolean suppressExplanation = false;
/** The underlying parser. */
private SAXParser saxParser = null;
/** The underlying reader. */
private Parser parser = null;
/** The underlying DocumentHandler. */
private DocumentHandler documentHandler = null;
/** The underlying DTDHandler. */
private DTDHandler dtdHandler = null;
/** The manager for the underlying resolver. */
private CatalogManager catalogManager = CatalogManager.getStaticManager();
/** The underlying catalog resolver. */
private CatalogResolver catalogResolver = null;
/** A separate resolver for oasis-xml-pi catalogs. */
private CatalogResolver piCatalogResolver = null;
/** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */
private boolean allowXMLCatalogPI = false;
/** The base URI of the input document, if known. */
private URL baseURL = null;
/** Constructor. */
public ResolvingParser() {
initParser();
}
/** Constructor. */
public ResolvingParser(CatalogManager manager) {
catalogManager = manager;
initParser();
}
/** Initialize the parser. */
private void initParser() {
catalogResolver = new CatalogResolver(catalogManager);
SAXParserFactory spf = catalogManager.useServicesMechanism() ?
SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
spf.setNamespaceAware(true);
spf.setValidating(false);
try {
saxParser = spf.newSAXParser();
parser = saxParser.getParser();
documentHandler = null;
dtdHandler = null;
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** Return the Catalog being used. */
public Catalog getCatalog() {
return catalogResolver.getCatalog();
}
/**
* SAX Parser API.
*
* <p>Note that the JAXP 1.1ea2 parser crashes with an InternalError if
* it encounters a system identifier that appears to be a relative URI
* that begins with a slash. For example, the declaration:</p>
*
* <pre>
* &lt;!DOCTYPE book SYSTEM "/path/to/dtd/on/my/system/docbookx.dtd">
* </pre>
*
* <p>would cause such an error. As a convenience, this method catches
* that error and prints an explanation. (Unfortunately, it's not possible
* to identify the particular system identifier that causes the problem.)
* </p>
*
* <p>The underlying error is forwarded after printing the explanatory
* message. The message is only every printed once and if
* <code>suppressExplanation</code> is set to <code>false</code> before
* parsing, it will never be printed.</p>
*/
public void parse(InputSource input)
throws IOException,
SAXException {
setupParse(input.getSystemId());
try {
parser.parse(input);
} catch (InternalError ie) {
explain(input.getSystemId());
throw ie;
}
}
/** SAX Parser API.
*
* @see #parse(InputSource)
*/
public void parse(String systemId)
throws IOException,
SAXException {
setupParse(systemId);
try {
parser.parse(systemId);
} catch (InternalError ie) {
explain(systemId);
throw ie;
}
}
/** SAX Parser API. */
public void setDocumentHandler(DocumentHandler handler) {
documentHandler = handler;
}
/** SAX Parser API. */
public void setDTDHandler(DTDHandler handler) {
dtdHandler = handler;
}
/**
* SAX Parser API.
*
* <p>The purpose of this class is to implement an entity resolver.
* Attempting to set a different one is pointless (and ignored).</p>
*/
public void setEntityResolver(EntityResolver resolver) {
// nop
}
/** SAX Parser API. */
public void setErrorHandler(ErrorHandler handler) {
parser.setErrorHandler(handler);
}
/** SAX Parser API. */
public void setLocale(Locale locale) throws SAXException {
parser.setLocale(locale);
}
/** SAX DocumentHandler API. */
public void characters(char[] ch, int start, int length)
throws SAXException {
if (documentHandler != null) {
documentHandler.characters(ch,start,length);
}
}
/** SAX DocumentHandler API. */
public void endDocument() throws SAXException {
if (documentHandler != null) {
documentHandler.endDocument();
}
}
/** SAX DocumentHandler API. */
public void endElement(String name) throws SAXException {
if (documentHandler != null) {
documentHandler.endElement(name);
}
}
/** SAX DocumentHandler API. */
public void ignorableWhitespace(char[] ch, int start, int length)
throws SAXException {
if (documentHandler != null) {
documentHandler.ignorableWhitespace(ch,start,length);
}
}
/** SAX DocumentHandler API. */
public void processingInstruction(String target, String pidata)
throws SAXException {
if (target.equals("oasis-xml-catalog")) {
URL catalog = null;
String data = pidata;
int pos = data.indexOf("catalog=");
if (pos >= 0) {
data = data.substring(pos+8);
if (data.length() > 1) {
String quote = data.substring(0,1);
data = data.substring(1);
pos = data.indexOf(quote);
if (pos >= 0) {
data = data.substring(0, pos);
try {
if (baseURL != null) {
catalog = new URL(baseURL, data);
} else {
catalog = new URL(data);
}
} catch (MalformedURLException mue) {
// nevermind
}
}
}
}
if (allowXMLCatalogPI) {
if (catalogManager.getAllowOasisXMLCatalogPI()) {
catalogManager.debug.message(4,"oasis-xml-catalog PI", pidata);
if (catalog != null) {
try {
catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString());
if (piCatalogResolver == null) {
piCatalogResolver = new CatalogResolver(true);
}
piCatalogResolver.getCatalog().parseCatalog(catalog.toString());
} catch (Exception e) {
catalogManager.debug.message(3, "Exception parsing oasis-xml-catalog: "
+ catalog.toString());
}
} else {
catalogManager.debug.message(3, "PI oasis-xml-catalog unparseable: " + pidata);
}
} else {
catalogManager.debug.message(4,"PI oasis-xml-catalog ignored: " + pidata);
}
} else {
catalogManager.debug.message(3, "PI oasis-xml-catalog occurred in an invalid place: "
+ pidata);
}
} else {
if (documentHandler != null) {
documentHandler.processingInstruction(target, pidata);
}
}
}
/** SAX DocumentHandler API. */
public void setDocumentLocator(Locator locator) {
if (documentHandler != null) {
documentHandler.setDocumentLocator(locator);
}
}
/** SAX DocumentHandler API. */
public void startDocument() throws SAXException {
if (documentHandler != null) {
documentHandler.startDocument();
}
}
/** SAX DocumentHandler API. */
public void startElement(String name, AttributeList atts)
throws SAXException {
allowXMLCatalogPI = false;
if (documentHandler != null) {
documentHandler.startElement(name,atts);
}
}
/** SAX DTDHandler API. */
public void notationDecl (String name, String publicId, String systemId)
throws SAXException {
allowXMLCatalogPI = false;
if (dtdHandler != null) {
dtdHandler.notationDecl(name,publicId,systemId);
}
}
/** SAX DTDHandler API. */
public void unparsedEntityDecl (String name,
String publicId,
String systemId,
String notationName)
throws SAXException {
allowXMLCatalogPI = false;
if (dtdHandler != null) {
dtdHandler.unparsedEntityDecl (name, publicId, systemId, notationName);
}
}
/**
* Implements the <code>resolveEntity</code> method
* for the SAX interface, using an underlying CatalogResolver
* to do the real work.
*/
public InputSource resolveEntity (String publicId, String systemId) {
allowXMLCatalogPI = false;
String resolved = catalogResolver.getResolvedEntity(publicId, systemId);
if (resolved == null && piCatalogResolver != null) {
resolved = piCatalogResolver.getResolvedEntity(publicId, systemId);
}
if (resolved != null) {
try {
InputSource iSource = new InputSource(resolved);
iSource.setPublicId(publicId);
// Ideally this method would not attempt to open the
// InputStream, but there is a bug (in Xerces, at least)
// that causes the parser to mistakenly open the wrong
// system identifier if the returned InputSource does
// not have a byteStream.
//
// It could be argued that we still shouldn't do this here,
// but since the purpose of calling the entityResolver is
// almost certainly to open the input stream, it seems to
// do little harm.
//
URL url = new URL(resolved);
InputStream iStream = url.openStream();
iSource.setByteStream(iStream);
return iSource;
} catch (Exception e) {
catalogManager.debug.message(1,
"Failed to create InputSource ("
+ e.toString()
+ ")", resolved);
return null;
}
} else {
return null;
}
}
/** Setup for parsing. */
private void setupParse(String systemId) {
allowXMLCatalogPI = true;
parser.setEntityResolver(this);
parser.setDocumentHandler(this);
parser.setDTDHandler(this);
URL cwd = null;
try {
cwd = FileURL.makeURL("basename");
} catch (MalformedURLException mue) {
cwd = null;
}
try {
baseURL = new URL(systemId);
} catch (MalformedURLException mue) {
if (cwd != null) {
try {
baseURL = new URL(cwd, systemId);
} catch (MalformedURLException mue2) {
// give up
baseURL = null;
}
} else {
// give up
baseURL = null;
}
}
}
/** Provide one possible explanation for an InternalError. */
private void explain(String systemId) {
if (!suppressExplanation) {
System.out.println("Parser probably encountered bad URI in " + systemId);
System.out.println("For example, replace '/some/uri' with 'file:/some/uri'.");
}
}
}

View File

@ -1,346 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.tools;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.XMLFilterImpl;
import com.sun.org.apache.xml.internal.resolver.Catalog;
import com.sun.org.apache.xml.internal.resolver.CatalogManager;
import com.sun.org.apache.xml.internal.resolver.helpers.FileURL;
/**
* A SAX XMLFilter that performs catalog-based entity resolution.
*
* <p>This class implements a SAX XMLFilter that performs entity resolution
* using the CatalogResolver. The actual, underlying parser is obtained
* from a SAXParserFactory.</p>
* </p>
*
* @see CatalogResolver
* @see org.xml.sax.XMLFilter
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class ResolvingXMLFilter extends XMLFilterImpl {
/**
* Suppress explanatory message?
*
* @see #parse(InputSource)
*/
private static boolean suppressExplanation = false;
/** The manager for the underlying resolver. */
CatalogManager catalogManager = CatalogManager.getStaticManager();
/** The underlying catalog resolver. */
private CatalogResolver catalogResolver = null;
/** A separate resolver for oasis-xml-pi catalogs. */
private CatalogResolver piCatalogResolver = null;
/** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */
private boolean allowXMLCatalogPI = false;
/** The base URI of the input document, if known. */
private URL baseURL = null;
/** Construct an empty XML Filter with no parent. */
public ResolvingXMLFilter() {
super();
catalogResolver = new CatalogResolver(catalogManager);
}
/** Construct an XML filter with the specified parent. */
public ResolvingXMLFilter(XMLReader parent) {
super(parent);
catalogResolver = new CatalogResolver(catalogManager);
}
/** Construct an XML filter with the specified parent. */
public ResolvingXMLFilter(CatalogManager manager) {
super();
catalogManager = manager;
catalogResolver = new CatalogResolver(catalogManager);
}
/** Construct an XML filter with the specified parent. */
public ResolvingXMLFilter(XMLReader parent, CatalogManager manager) {
super(parent);
catalogManager = manager;
catalogResolver = new CatalogResolver(catalogManager);
}
/**
* Provide accessto the underlying Catalog.
*/
public Catalog getCatalog() {
return catalogResolver.getCatalog();
}
/**
* SAX XMLReader API.
*
* <p>Note that the JAXP 1.1ea2 parser crashes with an InternalError if
* it encounters a system identifier that appears to be a relative URI
* that begins with a slash. For example, the declaration:</p>
*
* <pre>
* &lt;!DOCTYPE book SYSTEM "/path/to/dtd/on/my/system/docbookx.dtd">
* </pre>
*
* <p>would cause such an error. As a convenience, this method catches
* that error and prints an explanation. (Unfortunately, it's not possible
* to identify the particular system identifier that causes the problem.)
* </p>
*
* <p>The underlying error is forwarded after printing the explanatory
* message. The message is only every printed once and if
* <code>suppressExplanation</code> is set to <code>false</code> before
* parsing, it will never be printed.</p>
*/
public void parse(InputSource input)
throws IOException, SAXException {
allowXMLCatalogPI = true;
setupBaseURI(input.getSystemId());
try {
super.parse(input);
} catch (InternalError ie) {
explain(input.getSystemId());
throw ie;
}
}
/** SAX XMLReader API.
*
* @see #parse(InputSource)
*/
public void parse(String systemId)
throws IOException, SAXException {
allowXMLCatalogPI = true;
setupBaseURI(systemId);
try {
super.parse(systemId);
} catch (InternalError ie) {
explain(systemId);
throw ie;
}
}
/**
* Implements the <code>resolveEntity</code> method
* for the SAX interface, using an underlying CatalogResolver
* to do the real work.
*/
public InputSource resolveEntity (String publicId, String systemId) {
allowXMLCatalogPI = false;
String resolved = catalogResolver.getResolvedEntity(publicId, systemId);
if (resolved == null && piCatalogResolver != null) {
resolved = piCatalogResolver.getResolvedEntity(publicId, systemId);
}
if (resolved != null) {
try {
InputSource iSource = new InputSource(resolved);
iSource.setPublicId(publicId);
// Ideally this method would not attempt to open the
// InputStream, but there is a bug (in Xerces, at least)
// that causes the parser to mistakenly open the wrong
// system identifier if the returned InputSource does
// not have a byteStream.
//
// It could be argued that we still shouldn't do this here,
// but since the purpose of calling the entityResolver is
// almost certainly to open the input stream, it seems to
// do little harm.
//
URL url = new URL(resolved);
InputStream iStream = url.openStream();
iSource.setByteStream(iStream);
return iSource;
} catch (Exception e) {
catalogManager.debug.message(1,
"Failed to create InputSource ("
+ e.toString()
+ ")", resolved);
return null;
}
} else {
return null;
}
}
/** SAX DTDHandler API.
*
* <p>Captured here only to detect the end of the prolog so that
* we can ignore subsequent oasis-xml-catalog PIs. Otherwise
* the events are just passed through.</p>
*/
public void notationDecl (String name, String publicId, String systemId)
throws SAXException {
allowXMLCatalogPI = false;
super.notationDecl(name,publicId,systemId);
}
/** SAX DTDHandler API.
*
* <p>Captured here only to detect the end of the prolog so that
* we can ignore subsequent oasis-xml-catalog PIs. Otherwise
* the events are just passed through.</p>
*/
public void unparsedEntityDecl (String name,
String publicId,
String systemId,
String notationName)
throws SAXException {
allowXMLCatalogPI = false;
super.unparsedEntityDecl (name, publicId, systemId, notationName);
}
/** SAX ContentHandler API.
*
* <p>Captured here only to detect the end of the prolog so that
* we can ignore subsequent oasis-xml-catalog PIs. Otherwise
* the events are just passed through.</p>
*/
public void startElement (String uri, String localName, String qName,
Attributes atts)
throws SAXException {
allowXMLCatalogPI = false;
super.startElement(uri,localName,qName,atts);
}
/** SAX ContentHandler API.
*
* <p>Detect and use the oasis-xml-catalog PI if it occurs.</p>
*/
public void processingInstruction(String target, String pidata)
throws SAXException {
if (target.equals("oasis-xml-catalog")) {
URL catalog = null;
String data = pidata;
int pos = data.indexOf("catalog=");
if (pos >= 0) {
data = data.substring(pos+8);
if (data.length() > 1) {
String quote = data.substring(0,1);
data = data.substring(1);
pos = data.indexOf(quote);
if (pos >= 0) {
data = data.substring(0, pos);
try {
if (baseURL != null) {
catalog = new URL(baseURL, data);
} else {
catalog = new URL(data);
}
} catch (MalformedURLException mue) {
// nevermind
}
}
}
}
if (allowXMLCatalogPI) {
if (catalogManager.getAllowOasisXMLCatalogPI()) {
catalogManager.debug.message(4,"oasis-xml-catalog PI", pidata);
if (catalog != null) {
try {
catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString());
if (piCatalogResolver == null) {
piCatalogResolver = new CatalogResolver(true);
}
piCatalogResolver.getCatalog().parseCatalog(catalog.toString());
} catch (Exception e) {
catalogManager.debug.message(3, "Exception parsing oasis-xml-catalog: "
+ catalog.toString());
}
} else {
catalogManager.debug.message(3, "PI oasis-xml-catalog unparseable: " + pidata);
}
} else {
catalogManager.debug.message(4,"PI oasis-xml-catalog ignored: " + pidata);
}
} else {
catalogManager.debug.message(3, "PI oasis-xml-catalog occurred in an invalid place: "
+ pidata);
}
} else {
super.processingInstruction(target, pidata);
}
}
/** Save the base URI of the document being parsed. */
private void setupBaseURI(String systemId) {
URL cwd = null;
try {
cwd = FileURL.makeURL("basename");
} catch (MalformedURLException mue) {
cwd = null;
}
try {
baseURL = new URL(systemId);
} catch (MalformedURLException mue) {
if (cwd != null) {
try {
baseURL = new URL(cwd, systemId);
} catch (MalformedURLException mue2) {
// give up
baseURL = null;
}
} else {
// give up
baseURL = null;
}
}
}
/** Provide one possible explanation for an InternalError. */
private void explain(String systemId) {
if (!suppressExplanation) {
System.out.println("XMLReader probably encountered bad URI in " + systemId);
System.out.println("For example, replace '/some/uri' with 'file:/some/uri'.");
}
suppressExplanation = true;
}
}

View File

@ -1,90 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xml.internal.resolver.tools;
import javax.xml.parsers.*;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import com.sun.org.apache.xml.internal.resolver.*;
/**
* A SAX XMLReader that performs catalog-based entity resolution.
*
* <p>This class implements a SAX XMLReader that performs entity resolution
* using the CatalogResolver. The actual, underlying parser is obtained
* from a SAXParserFactory.</p>
* </p>
*
* @see CatalogResolver
* @see org.xml.sax.XMLReader
*
* @author Norman Walsh
* <a href="mailto:Norman.Walsh@Sun.COM">Norman.Walsh@Sun.COM</a>
*
* @version 1.0
*/
public class ResolvingXMLReader extends ResolvingXMLFilter {
/** Make the parser Namespace aware? */
private static final boolean namespaceAware = true;
/** Make the parser validating? */
private static final boolean validating = false;
/**
* Construct a new reader from the JAXP factory.
*
* <p>In order to do its job, a ResolvingXMLReader must in fact be
* a filter. So the only difference between this code and the filter
* code is that the constructor builds a new reader.</p>
*/
public ResolvingXMLReader() {
super();
SAXParserFactory spf = catalogManager.useServicesMechanism() ?
SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
spf.setNamespaceAware(namespaceAware);
spf.setValidating(validating);
try {
SAXParser parser = spf.newSAXParser();
setParent(parser.getXMLReader());
} catch (Exception ex) {
ex.printStackTrace();
}
}
/**
* Construct a new reader from the JAXP factory.
*
* <p>In order to do its job, a ResolvingXMLReader must in fact be
* a filter. So the only difference between this code and the filter
* code is that the constructor builds a new reader.</p>
*/
public ResolvingXMLReader(CatalogManager manager) {
super(manager);
SAXParserFactory spf = catalogManager.useServicesMechanism() ?
SAXParserFactory.newInstance() : new SAXParserFactoryImpl();
spf.setNamespaceAware(namespaceAware);
spf.setValidating(validating);
try {
SAXParser parser = spf.newSAXParser();
setParent(parser.getXMLReader());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

View File

@ -27,6 +27,17 @@
* Defines the Java API for XML Processing (JAXP), the Streaming API for XML (StAX),
* the Simple API for XML (SAX), and the W3C Document Object Model (DOM) API.
*
* @uses javax.xml.datatype.DatatypeFactory
* @uses javax.xml.parsers.DocumentBuilderFactory
* @uses javax.xml.parsers.SAXParserFactory
* @uses javax.xml.stream.XMLEventFactory
* @uses javax.xml.stream.XMLInputFactory
* @uses javax.xml.stream.XMLOutputFactory
* @uses javax.xml.transform.TransformerFactory
* @uses javax.xml.validation.SchemaFactory
* @uses javax.xml.xpath.XPathFactory
* @uses org.xml.sax.XMLReader
*
* @moduleGraph
* @since 9
*/

View File

@ -431,3 +431,5 @@ e705867d9989d00e4357f66f18b302c95e13b5e7 jdk-10+8
8c615099f3e3ca137325be34bf566b767d9e3c64 jdk-9+172
2d22d6732a73e615b9e13d6bc93bf026db3bc231 jdk-10+11
2bd967aa452c1e0e87a6173bef6fbb96ef1c521b jdk-9+173
c2296642010f1b215ac35da89e92c3ce44104e32 jdk-9+174
712a3a657654079514590d37a0f4894d43541d5c jdk-10+12

View File

@ -26,6 +26,8 @@
/**
* Defines the Java Architecture for XML Binding (JAXB) API.
*
* @uses javax.xml.bind.JAXBContextFactory
*
* @moduleGraph
* @since 9
*/

View File

@ -27,6 +27,12 @@
* Defines the Java API for XML-Based Web Services (JAX-WS), and
* the Web Services Metadata API.
*
* @uses javax.xml.soap.MessageFactory
* @uses javax.xml.soap.SAAJMetaFactory
* @uses javax.xml.soap.SOAPConnectionFactory
* @uses javax.xml.soap.SOAPFactory
* @uses javax.xml.ws.spi.Provider
*
* @moduleGraph
* @since 9
*/

View File

@ -23,6 +23,21 @@
* questions.
*/
/**
* Defines tools for JAXB classes and XML schema generation,
* including the <em>{@index schemagen schemagen tool}</em>
* and <em>{@index xjc xjc tool}</em> tools.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>{@extLink schemagen_tool_reference schemagen},
* {@extLink xjc_tool_reference xjc}
* </dl>
*
* @moduleGraph
* @since 9
*/
@Deprecated(since="9", forRemoval=true)
module jdk.xml.bind {
requires java.activation;
requires java.compiler;

View File

@ -23,6 +23,21 @@
* questions.
*/
/**
* Defines tools for JAX-WS classes and WSDL generation,
* including the <em>{@index wsgen wsgen tool}</em>
* and <em>{@index wsimport wsimport tool}</em> tools.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>{@extLink wsgen_tool_reference wsgen},
* {@extLink wsimport_tool_reference wsimport}
* </dl>
*
* @moduleGraph
* @since 9
*/
@Deprecated(since="9", forRemoval=true)
module jdk.xml.ws {
requires java.compiler;
requires java.logging;

View File

@ -428,3 +428,5 @@ df64bd4757d0d130d62a22b8143ba31d3a16ac18 jdk-10+10
0ff9ad7d067cd4fa14450cf208bf019175a0aaba jdk-9+172
7c54889c0ec649ee04643e5cace434623d0dc667 jdk-10+11
a5506b425f1bf91530d8417b57360e5d89328c0c jdk-9+173
42f18c931bd4fae5c206ccf6d8e591e4c4e69d31 jdk-9+174
5f504872a75b71f2fb19299f0d1e3395cf32eaa0 jdk-10+12

View File

@ -77,6 +77,13 @@ ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
endif
TARGETS += $(FREETYPE_TARGET_LIB)
$(eval $(call SetupCopyFiles, COPY_FREETYPE_LICENSE, \
FILES := $(FREETYPE_LICENSE), \
DEST := $(LEGAL_DST_DIR), \
))
TARGETS += $(COPY_FREETYPE_LICENSE)
endif
################################################################################

View File

@ -10,7 +10,9 @@ java.corba \
java.transaction \
java.xml.bind \
java.xml.ws \
java.xml.ws.annotation
java.xml.ws.annotation \
jdk.xml.bind \
jdk.xml.ws
aggregator_modules=\
java.se \

View File

@ -58,7 +58,7 @@ public class ExtLink implements Taglet {
static final String URL = "https://www.oracle.com/pls/topic/lookup?ctx=javase9&amp;id=";
static final Pattern TAG_PATTERN = Pattern.compile("(\\s*)(?<name>\\w+)(\\s+)(?<desc>.*)");
static final Pattern TAG_PATTERN = Pattern.compile("(?s)(\\s*)(?<name>\\w+)(\\s+)(?<desc>.*)$");
/**
* Returns the set of locations in which the tag may be used.

View File

@ -42,12 +42,22 @@ include TestFilesCompilation.gmk
# Add more directories here when needed.
BUILD_JDK_JTREG_NATIVE_SRC := \
$(JDK_TOPDIR)/test/native_sanity \
$(JDK_TOPDIR)/test/java/lang/String/nativeEncoding \
#
BUILD_JDK_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/jdk/jtreg/native
BUILD_JDK_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/jdk/jtreg
ifeq ($(OPENJDK_TARGET_OS), windows)
WIN_LIB_JAVA := $(SUPPORT_OUTPUTDIR)/native/java.base/libjava/java.lib
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := $(WIN_LIB_JAVA)
else ifeq ($(OPENJDK_TARGET_OS), solaris)
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava -lc
else
BUILD_JDK_JTREG_LIBRARIES_LIBS_libstringPlatformChars := -ljava
endif
$(eval $(call SetupTestFilesCompilation, BUILD_JDK_JTREG_LIBRARIES, \
TYPE := LIBRARY, \
SOURCE_DIRS := $(BUILD_JDK_JTREG_NATIVE_SRC), \

View File

@ -2146,8 +2146,6 @@ public abstract class ClassLoader {
* @revised 9
* @spec JPMS
*
* @see <a href="../../../technotes/guides/jar/jar.html#versioning">
* The JAR File Specification: Package Versioning</a>
* @see <a href="../../../technotes/guides/jar/jar.html#sealing">
* The JAR File Specification: Package Sealing</a>
*/

View File

@ -102,9 +102,13 @@ import jdk.internal.reflect.Reflection;
* with the {@link Package#getPackages Package.getPackages()} and
* {@link ClassLoader#getDefinedPackages} methods.
*
* @implNote
* The <a href="ClassLoader.html#builtinLoaders">builtin class loaders</a>
* do not explicitly define {@code Package} objects for packages in
* <em>named modules</em>. Instead those packages are automatically defined
* and have no specification and implementation versioning information.
*
* @jvms 5.3 Run-time package
* @see <a href="../../../technotes/guides/jar/jar.html#versioning">
* The JAR File Specification: Package Versioning</a>
* @see <a href="../../../technotes/guides/jar/jar.html#sealing">
* The JAR File Specification: Package Sealing</a>
* @see ClassLoader#definePackage(String, String, String, String, String, String, String, URL)

View File

@ -27,6 +27,7 @@ package java.lang;
import java.io.ObjectStreamField;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Native;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
@ -3063,8 +3064,8 @@ public final class String
return COMPACT_STRINGS && coder == LATIN1;
}
static final byte LATIN1 = 0;
static final byte UTF16 = 1;
@Native static final byte LATIN1 = 0;
@Native static final byte UTF16 = 1;
/*
* StringIndexOutOfBoundsException if {@code index} is

View File

@ -1212,7 +1212,7 @@ public class BitSet implements Cloneable, java.io.Serializable {
*
* <p>The stream binds to this bit set when the terminal stream operation
* commences (specifically, the spliterator for the stream is
* <a href="../Spliterator.html#binding"><em>late-binding</em></a>). If the
* <a href="Spliterator.html#binding"><em>late-binding</em></a>). If the
* bit set is modified during that operation then the result is undefined.
*
* @return a stream of integers representing set indices

View File

@ -26,6 +26,51 @@
/**
* Defines the foundational APIs of the Java SE Platform.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Providers:</dt>
* <dd> The JDK implementation of this module provides an implementation of
* the {@index jrt jrt} {@linkplain java.nio.file.spi.FileSystemProvider
* file system provider} to enumerate and read the class and resource
* files in a run-time image.
* The jrt file system can be created by calling
* {@link java.nio.file.FileSystems#newFileSystem
* FileSystems.newFileSystem(URI.create("jrt:/"))}.
* <p></dd>
* <dt class="simpleTagLabel">Tool Guides:</dt>
* <dd> {@extLink java_tool_reference java launcher},
* {@extLink keytool_tool_reference keytool}</dd>
* </dl>
*
* @provides java.nio.file.spi.FileSystemProvider
*
* @uses java.lang.System.LoggerFinder
* @uses java.net.ContentHandlerFactory
* @uses java.net.spi.URLStreamHandlerProvider
* @uses java.nio.channels.spi.AsynchronousChannelProvider
* @uses java.nio.channels.spi.SelectorProvider
* @uses java.nio.charset.spi.CharsetProvider
* @uses java.nio.file.spi.FileSystemProvider
* @uses java.nio.file.spi.FileTypeDetector
* @uses java.security.Provider
* @uses java.text.spi.BreakIteratorProvider
* @uses java.text.spi.CollatorProvider
* @uses java.text.spi.DateFormatProvider
* @uses java.text.spi.DateFormatSymbolsProvider
* @uses java.text.spi.DecimalFormatSymbolsProvider
* @uses java.text.spi.NumberFormatProvider
* @uses java.time.chrono.AbstractChronology
* @uses java.time.chrono.Chronology
* @uses java.time.zone.ZoneRulesProvider
* @uses java.util.spi.CalendarDataProvider
* @uses java.util.spi.CalendarNameProvider
* @uses java.util.spi.CurrencyNameProvider
* @uses java.util.spi.LocaleNameProvider
* @uses java.util.spi.ResourceBundleControlProvider
* @uses java.util.spi.ResourceBundleProvider
* @uses java.util.spi.TimeZoneNameProvider
* @uses java.util.spi.ToolProvider
* @uses javax.security.auth.spi.LoginModule
*
* @moduleGraph
* @since 9
*/

View File

@ -29,6 +29,7 @@
#include "jvm.h"
#include "jni.h"
#include "jni_util.h"
#include "java_lang_String.h"
/* Due to a bug in the win32 C runtime library strings
* such as "z:" need to be appended with a "." so we
@ -442,16 +443,18 @@ JNU_NewObjectByName(JNIEnv *env, const char *class_name,
return obj;
}
/* Optimized for char set ISO_8559_1 */
/* Optimized for charset ISO_8559_1 */
static jstring
newString8859_1(JNIEnv *env, const char *str)
newSizedString8859_1(JNIEnv *env, const char *str, const int len)
{
int len = (int)strlen(str);
jchar buf[512];
jchar *str1;
jstring result;
int i;
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return NULL;
if (len > 512) {
str1 = (jchar *)malloc(len * sizeof(jchar));
if (str1 == 0) {
@ -469,6 +472,13 @@ newString8859_1(JNIEnv *env, const char *str)
return result;
}
static jstring
newString8859_1(JNIEnv *env, const char *str)
{
int len = (int)strlen(str);
return newSizedString8859_1(env, str, len);
}
static const char*
getString8859_1Chars(JNIEnv *env, jstring jstr)
{
@ -501,7 +511,7 @@ getString8859_1Chars(JNIEnv *env, jstring jstr)
}
/* Optimized for char set ISO646-US (us-ascii) */
/* Optimized for charset ISO646-US (us-ascii) */
static jstring
newString646_US(JNIEnv *env, const char *str)
{
@ -573,7 +583,7 @@ static int cp1252c1chars[32] = {
0x02Dc,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
};
/* Optimized for char set Cp1252 */
/* Optimized for charset Cp1252 */
static jstring
newStringCp1252(JNIEnv *env, const char *str)
{
@ -582,6 +592,10 @@ newStringCp1252(JNIEnv *env, const char *str)
jchar *str1;
jstring result;
int i;
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return NULL;
if (len > 512) {
str1 = (jchar *)malloc(len * sizeof(jchar));
if (str1 == 0) {
@ -625,9 +639,13 @@ getStringCp1252Chars(JNIEnv *env, jstring jstr)
for (i=0; i<len; i++) {
jchar c = str[i];
if (c < 256)
result[i] = (char)c;
else switch(c) {
if (c < 256) {
if ((c >= 0x80) && (c <= 0x9f)) {
result[i] = '?';
} else {
result[i] = (char)c;
}
} else switch(c) {
case 0x20AC: result[i] = (char)0x80; break;
case 0x201A: result[i] = (char)0x82; break;
case 0x0192: result[i] = (char)0x83; break;
@ -671,8 +689,89 @@ static jstring jnuEncoding = NULL;
static jmethodID String_init_ID; /* String(byte[], enc) */
static jmethodID String_getBytes_ID; /* String.getBytes(enc) */
int getFastEncoding() {
return fastEncoding;
/* Cached field IDs */
static jfieldID String_coder_ID; /* String.coder */
static jfieldID String_value_ID; /* String.value */
static jboolean isJNUEncodingSupported = JNI_FALSE;
static jboolean jnuEncodingSupported(JNIEnv *env) {
jboolean exe;
if (isJNUEncodingSupported == JNI_TRUE) {
return JNI_TRUE;
}
isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
env, &exe,
"java/nio/charset/Charset",
"isSupported",
"(Ljava/lang/String;)Z",
jnuEncoding).z;
return isJNUEncodingSupported;
}
/* Create a new string by converting str to a heap-allocated byte array and
* calling the appropriate String constructor.
*/
static jstring
newSizedStringJava(JNIEnv *env, const char *str, const int len)
{
jstring result = NULL;
jbyteArray bytes = 0;
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return NULL;
bytes = (*env)->NewByteArray(env, len);
if (bytes != NULL) {
jclass strClazz = JNU_ClassString(env);
CHECK_NULL_RETURN(strClazz, 0);
(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *)str);
if (jnuEncodingSupported(env)) {
result = (*env)->NewObject(env, strClazz,
String_init_ID, bytes, jnuEncoding);
} else {
/*If the encoding specified in sun.jnu.encoding is not endorsed
by "Charset.isSupported" we have to fall back to use String(byte[])
explicitly here without specifying the encoding name, in which the
StringCoding class will pickup the iso-8859-1 as the fallback
converter for us.
*/
jmethodID mid = (*env)->GetMethodID(env, strClazz,
"<init>", "([B)V");
if (mid != NULL) {
result = (*env)->NewObject(env, strClazz, mid, bytes);
}
}
(*env)->DeleteLocalRef(env, bytes);
return result;
}
return NULL;
}
static jstring
newStringJava(JNIEnv *env, const char *str)
{
int len = (int)strlen(str);
return newSizedStringJava(env, str, len);
}
/* Optimized for charset UTF-8 */
static jstring
newStringUTF8(JNIEnv *env, const char *str)
{
int len;
const unsigned char *p;
unsigned char asciiCheck;
for (asciiCheck = 0, p = (const unsigned char*)str; *p != '\0'; p++) {
asciiCheck |= *p;
}
len = (int)((const char*)p - str);
if (asciiCheck < 0x80) {
// ascii fast-path
return newSizedString8859_1(env, str, len);
}
return newSizedStringJava(env, str, len);
}
/* Initialize the fast encoding. If the "sun.jnu.encoding" property
@ -718,17 +817,20 @@ initializeEncoding(JNIEnv *env)
if ((strcmp(encname, "8859_1") == 0) ||
(strcmp(encname, "ISO8859-1") == 0) ||
(strcmp(encname, "ISO8859_1") == 0) ||
(strcmp(encname, "ISO-8859-1") == 0))
(strcmp(encname, "ISO-8859-1") == 0)) {
fastEncoding = FAST_8859_1;
else if (strcmp(encname, "ISO646-US") == 0)
} else if (strcmp(encname, "UTF-8") == 0) {
fastEncoding = FAST_UTF_8;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
} else if (strcmp(encname, "ISO646-US") == 0) {
fastEncoding = FAST_646_US;
else if (strcmp(encname, "Cp1252") == 0 ||
} else if (strcmp(encname, "Cp1252") == 0 ||
/* This is a temporary fix until we move */
/* to wide character versions of all Windows */
/* calls. */
strcmp(encname, "utf-16le") == 0)
strcmp(encname, "utf-16le") == 0) {
fastEncoding = FAST_CP1252;
else {
} else {
fastEncoding = NO_FAST_ENCODING;
jnuEncoding = (jstring)(*env)->NewGlobalRef(env, enc);
}
@ -750,24 +852,10 @@ initializeEncoding(JNIEnv *env)
CHECK_NULL(String_getBytes_ID);
String_init_ID = (*env)->GetMethodID(env, strClazz,
"<init>", "([BLjava/lang/String;)V");
String_coder_ID = (*env)->GetFieldID(env, strClazz, "coder", "B");
String_value_ID = (*env)->GetFieldID(env, strClazz, "value", "[B");
}
static jboolean isJNUEncodingSupported = JNI_FALSE;
static jboolean jnuEncodingSupported(JNIEnv *env) {
jboolean exe;
if (isJNUEncodingSupported == JNI_TRUE) {
return JNI_TRUE;
}
isJNUEncodingSupported = (jboolean) JNU_CallStaticMethodByName (
env, &exe,
"java/nio/charset/Charset",
"isSupported",
"(Ljava/lang/String;)Z",
jnuEncoding).z;
return isJNUEncodingSupported;
}
JNIEXPORT jstring
NewStringPlatform(JNIEnv *env, const char *str)
{
@ -777,10 +865,6 @@ NewStringPlatform(JNIEnv *env, const char *str)
JNIEXPORT jstring JNICALL
JNU_NewStringPlatform(JNIEnv *env, const char *str)
{
jstring result = NULL;
jbyteArray hab = 0;
int len;
if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
@ -792,36 +876,9 @@ JNU_NewStringPlatform(JNIEnv *env, const char *str)
return newString646_US(env, str);
if (fastEncoding == FAST_CP1252)
return newStringCp1252(env, str);
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return NULL;
len = (int)strlen(str);
hab = (*env)->NewByteArray(env, len);
if (hab != 0) {
jclass strClazz = JNU_ClassString(env);
CHECK_NULL_RETURN(strClazz, 0);
(*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
if (jnuEncodingSupported(env)) {
result = (*env)->NewObject(env, strClazz,
String_init_ID, hab, jnuEncoding);
} else {
/*If the encoding specified in sun.jnu.encoding is not endorsed
by "Charset.isSupported" we have to fall back to use String(byte[])
explicitly here without specifying the encoding name, in which the
StringCoding class will pickup the iso-8859-1 as the fallback
converter for us.
*/
jmethodID mid = (*env)->GetMethodID(env, strClazz,
"<init>", "([B)V");
if (mid != NULL) {
result = (*env)->NewObject(env, strClazz, mid, hab);
}
}
(*env)->DeleteLocalRef(env, hab);
return result;
}
return NULL;
if (fastEncoding == FAST_UTF_8)
return newStringUTF8(env, str);
return newStringJava(env, str);
}
JNIEXPORT const char *
@ -830,27 +887,10 @@ GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
return JNU_GetStringPlatformChars(env, jstr, isCopy);
}
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
static const char* getStringBytes(JNIEnv *env, jstring jstr) {
char *result = NULL;
jbyteArray hab = 0;
if (isCopy)
*isCopy = JNI_TRUE;
if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
JNU_CHECK_EXCEPTION_RETURN(env, 0);
}
if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
return getString8859_1Chars(env, jstr);
if (fastEncoding == FAST_646_US)
return getString646_USChars(env, jstr);
if (fastEncoding == FAST_CP1252)
return getStringCp1252Chars(env, jstr);
if ((*env)->EnsureLocalCapacity(env, 2) < 0)
return 0;
@ -883,6 +923,85 @@ JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
return result;
}
static const char*
getStringUTF8(JNIEnv *env, jstring jstr)
{
int i;
char *result;
jbyteArray value;
jint len;
jbyte *str;
jint rlen;
int ri;
jbyte coder = (*env)->GetByteField(env, jstr, String_coder_ID);
if (coder != java_lang_String_LATIN1) {
return getStringBytes(env, jstr);
}
if ((*env)->EnsureLocalCapacity(env, 2) < 0) {
return NULL;
}
value = (*env)->GetObjectField(env, jstr, String_value_ID);
if (value == NULL)
return NULL;
len = (*env)->GetArrayLength(env, value);
str = (*env)->GetPrimitiveArrayCritical(env, value, NULL);
if (str == NULL) {
return NULL;
}
rlen = len;
// we need two bytes for each latin-1 char above 127 (negative jbytes)
for (i = 0; i < len; i++) {
if (str[i] < 0) {
rlen++;
}
}
result = MALLOC_MIN4(rlen);
if (result == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
JNU_ThrowOutOfMemoryError(env, 0);
return NULL;
}
for (ri = 0, i = 0; i < len; i++) {
jbyte c = str[i];
if (c < 0) {
result[ri++] = (char)(0xc0 | ((c & 0xff) >> 6));
result[ri++] = (char)(0x80 | (c & 0x3f));
} else {
result[ri++] = c;
}
}
(*env)->ReleasePrimitiveArrayCritical(env, value, str, 0);
result[rlen] = '\0';
return result;
}
JNIEXPORT const char * JNICALL
JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
{
if (isCopy)
*isCopy = JNI_TRUE;
if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
JNU_CHECK_EXCEPTION_RETURN(env, 0);
}
if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
return getString8859_1Chars(env, jstr);
if (fastEncoding == FAST_646_US)
return getString646_USChars(env, jstr);
if (fastEncoding == FAST_CP1252)
return getStringCp1252Chars(env, jstr);
if (fastEncoding == FAST_UTF_8)
return getStringUTF8(env, jstr);
else
return getStringBytes(env, jstr);
}
JNIEXPORT void JNICALL
JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str)
{

View File

@ -382,7 +382,8 @@ enum {
NO_FAST_ENCODING, /* Platform encoding is not fast */
FAST_8859_1, /* ISO-8859-1 */
FAST_CP1252, /* MS-DOS Cp1252 */
FAST_646_US /* US-ASCII : ISO646-US */
FAST_646_US, /* US-ASCII : ISO646-US */
FAST_UTF_8
};
int getFastEncoding();

View File

@ -1,362 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](input.html) | [NEXT](version.html)'
include-after: '[CONTENTS](index.html) | [PREV](input.html) | [NEXT](version.html)'
title: 'Java Object Serialization Specification: 4 - Class Descriptors'
---
- [The ObjectStreamClass Class](#the-objectstreamclass-class)
- [Dynamic Proxy Class Descriptors](#dynamic-proxy-class-descriptors)
- [Serialized Form](#serialized-form)
- [The ObjectStreamField Class](#the-objectstreamfield-class)
- [Inspecting Serializable Classes](#inspecting-serializable-classes)
- [Stream Unique Identifiers](#stream-unique-identifiers)
-------------------------------------------------------------------------------
## 4.1 The ObjectStreamClass Class
The `ObjectStreamClass` provides information about classes that are saved in a
Serialization stream. The descriptor provides the fully-qualified name of the
class and its serialization version UID. A `SerialVersionUID` identifies the
unique original class version for which this class is capable of writing
streams and from which it can read.
```
package java.io;
public class ObjectStreamClass
{
public static ObjectStreamClass lookup(Class cl);
public static ObjectStreamClass lookupAny(Class cl);
public String getName();
public Class forClass();
public ObjectStreamField[] getFields();
public long getSerialVersionUID();
public String toString();
}
```
The `lookup` method returns the `ObjectStreamClass` descriptor for the
specified class in the virtual machine. If the class has defined
`serialVersionUID` it is retrieved from the class. If the `serialVersionUID` is
not defined by the class, it is computed from the definition of the class in
the virtual machine. *I*f the specified class is not serializable or
externalizable, *null* is returned.
The `lookupAny` method behaves like the `lookup` method, except that it returns
the descriptor for any class, regardless of whether it implements
`Serializable`. The `serialVersionUID` of a class that does not implement
`Serializable` is *0L.*
The `getName` method returns the name of the class, in the same format that is
used by the `Class.getName` method.
The `forClass` method returns the `Class` in the local virtual machine if one
was found by `ObjectInputStream.resolveClass` method. Otherwise, it returns
*null*.
The `getFields` method returns an array of `ObjectStreamField` objects that
represent the serializable fields of this class.
The `getSerialVersionUID` method returns the `serialVersionUID` of this class.
Refer to [Section 4.6, "Stream Unique
Identifiers"](#stream-unique-identifiers). If not specified by the class, the
value returned is a hash computed from the class's name, interfaces, methods,
and fields using the Secure Hash Algorithm (SHA) as defined by the National
Institute of Standards.
The `toString` method returns a printable representation of the class
descriptor including the name of the class and the `serialVersionUID`.
## 4.2 Dynamic Proxy Class Descriptors
ObjectStreamClass descriptors are also used to provide information about
dynamic proxy classes (e.g., classes obtained via calls to the getProxyClass
method of java.lang.reflect.Proxy) saved in a serialization stream. A dynamic
proxy class itself has no serializable fields and a serialVersionUID of 0L. In
other words, when the Class object for a dynamic proxy class is passed to the
static lookup method of ObjectStreamClass, the returned ObjectStreamClass
instance will have the following properties:
- Invoking its getSerialVersionUID method will return 0L.
- Invoking its getFields method will return an array of length zero.
- Invoking its getField method with any String argument will return null.
## 4.3 Serialized Form
The serialized form of an ObjectStreamClass instance depends on whether or not
the Class object it represents is serializable, externalizable, or a dynamic
proxy class.
When an `ObjectStreamClass` instance that does not represent a dynamic proxy
class is written to the stream, it writes the class name and
`serialVersionUID`, flags, and the number of fields. Depending on the class,
additional information may be written:
- For non-serializable classes, the number of fields is always zero. Neither
the `SC_SERIALIZABLE` nor the `SC_EXTERNALIZABLE` flag bits are set.
- For serializable classes, the `SC_SERIALIZABLE` flag is set, the number of
fields counts the number of serializable fields and is followed by a
descriptor for each serializable field. The descriptors are written in
canonical order. The descriptors for primitive typed fields are written
first sorted by field name followed by descriptors for the object typed
fields sorted by field name. The names are sorted using `String.compareTo`.
For details of the format, refer to [Section 6.4, "Grammar for the Stream
Format"](protocol.html#grammar-for-the-stream-format).
- For externalizable classes, flags includes the `SC_EXTERNALIZABLE` flag,
and the number of fields is always zero.
- For enum types, flags includes the `SC_ENUM` flag, and the number of fields
is always zero.
When an ObjectOutputStream serializes the ObjectStreamClass descriptor for a
dynamic proxy class, as determined by passing its Class object to the
isProxyClass method of java.lang.reflect.Proxy, it writes the number of
interfaces that the dynamic proxy class implements, followed by the interface
names. Interfaces are listed in the order that they are returned by invoking
the getInterfaces method on the Class object of the dynamic proxy class.
The serialized representations of ObjectStreamClass descriptors for dynamic
proxy classes and non-dynamic proxy classes are differentiated through the use
of different typecodes (`TC_PROXYCLASSDESC` and `TC_CLASSDESC`, respectively);
for a more detailed specification of the grammar, see [Section 6.4, "Grammar
for the Stream Format"](protocol.html#grammar-for-the-stream-format).
## 4.4 The ObjectStreamField Class
An `ObjectStreamField` represents a serializable field of a serializable class.
The serializable fields of a class can be retrieved from the
`ObjectStreamClass`.
The special static serializable field, `serialPersistentFields`, is an array of
`ObjectStreamField` components that is used to override the default
serializable fields.
```
package java.io;
public class ObjectStreamField implements Comparable {
public ObjectStreamField(String fieldName,
Class fieldType);
public ObjectStreamField(String fieldName,
Class fieldType,
boolean unshared);
public String getName();
public Class getType();
public String getTypeString();
public char getTypeCode();
public boolean isPrimitive();
public boolean isUnshared();
public int getOffset();
protected void setOffset(int offset);
public int compareTo(Object obj);
public String toString();
}
```
`ObjectStreamField` objects are used to specify the serializable fields of a
class or to describe the fields present in a stream. Its constructors accept
arguments describing the field to represent: a string specifying the name of
the field, a `Class` object specifying the type of the field, and a `boolean`
flag (implicitly `false` for the two-argument constructor) indicating whether
or not values of the represented field should be read and written as "unshared"
objects if default serialization/deserialization is in use (see the
descriptions of the `ObjectInputStream.readUnshared` and
`ObjectOutputStream.writeUnshared` methods in [Section 3.1, "The
ObjectInputStream Class"](input.html#the-objectinputstream-class) and [Section
2.1, "The ObjectOutputStream Class"](output.html#the-objectoutputstream-class),
respectively).
The `getName` method returns the name of the serializable field.
The `getType` method returns the type of the field.
The `getTypeString` method returns the type signature of the field.
The `getTypeCode` method returns a character encoding of the field type ('`B`'
for `byte`, '`C`' for `char`, '`D`' for `double`, '`F`' for `float`, '`I`' for
`int`, '`J`' for `long`, '`L`' for non-array object types, '`S`' for `short`,
'`Z`' for `boolean`, and '`[`' for arrays).
The `isPrimitive` method returns `true` if the field is of primitive type, or
`false` otherwise.
The `isUnshared` method returns `true` if values of the field should be written
as "unshared" objects, or `false` otherwise.
The `getOffset` method returns the offset of the field's value within instance
data of the class defining the field.
The `setOffset` method allows `ObjectStreamField` subclasses to modify the
offset value returned by the `getOffset` method.
The `compareTo` method compares `ObjectStreamFields` for use in sorting.
Primitive fields are ranked as "smaller" than non-primitive fields; fields
otherwise equal are ranked alphabetically.
The `toString` method returns a printable representation with name and type.
## 4.5 Inspecting Serializable Classes
The program *serialver* can be used to find out if a class is serializable and
to get its `serialVersionUID`.
When invoked on the command line with one or more class names, serialver prints
the `serialVersionUID` for each class in a form suitable for copying into an
evolving class. When invoked with no arguments, it prints a usage line.
## 4.6 Stream Unique Identifiers
Each versioned class must identify the original class version for which it is
capable of writing streams and from which it can read. For example, a versioned
class must declare:
```
private static final long serialVersionUID = 3487495895819393L;
```
The stream-unique identifier is a 64-bit hash of the class name, interface
class names, methods, and fields. The value must be declared in all versions of
a class except the first. It may be declared in the original class but is not
required. The value is fixed for all compatible classes. If the SUID is not
declared for a class, the value defaults to the hash for that class. The
`serialVersionUID` for dynamic proxy classes and enum types always have the
value *0L*. Array classes cannot declare an explicit `serialVersionUID`, so
they always have the default computed value, but the requirement for matching
`serialVersionUID` values is waived for array classes.
**Note:** It is strongly recommended that all serializable classes explicitly
declare `serialVersionUID` values, since the default `serialVersionUID`
computation is highly sensitive to class details that may vary depending on
compiler implementations, and can thus result in unexpected `serialVersionUID`
conflicts during deserialization, causing deserialization to fail.
The initial version of an `Externalizable` class must output a stream data
format that is extensible in the future. The initial version of the method
`readExternal` has to be able to read the output format of all future versions
of the method `writeExternal`.
The `serialVersionUID` is computed using the signature of a stream of bytes
that reflect the class definition. The National Institute of Standards and
Technology (NIST) Secure Hash Algorithm (SHA-1) is used to compute a signature
for the stream. The first two 32-bit quantities are used to form a 64-bit hash.
A `java.lang.DataOutputStream` is used to convert primitive data types to a
sequence of bytes. The values input to the stream are defined by the Java
Virtual Machine (VM) specification for classes. Class modifiers may include the
`ACC_PUBLIC`, `ACC_FINAL`, `ACC_INTERFACE`, and `ACC_ABSTRACT` flags; other
flags are ignored and do not affect `serialVersionUID` computation. Similarly,
for field modifiers, only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`,
`ACC_STATIC`, `ACC_FINAL`, `ACC_VOLATILE`, and `ACC_TRANSIENT` flags are used
when computing `serialVersionUID` values. For constructor and method modifiers,
only the `ACC_PUBLIC`, `ACC_PRIVATE`, `ACC_PROTECTED`, `ACC_STATIC`,
`ACC_FINAL`, `ACC_SYNCHRONIZED`, `ACC_NATIVE`, `ACC_ABSTRACT` and `ACC_STRICT`
flags are used. Names and descriptors are written in the format used by the
`java.io.DataOutputStream.writeUTF` method.
The sequence of items in the stream is as follows:
1. The class name.
2. The class modifiers written as a 32-bit integer.
3. The name of each interface sorted by name.
4. For each field of the class sorted by field name (except `private static`
and `private transient` fields:
a. The name of the field.
b. The modifiers of the field written as a 32-bit integer.
c. The descriptor of the field.
5. If a class initializer exists, write out the following:
a. The name of the method, `<clinit>`.
b. The modifier of the method, `java.lang.reflect.Modifier.STATIC`,
written as a 32-bit integer.
c. The descriptor of the method, `()V`.
6. For each non-`private` constructor sorted by method name and signature:
a. The name of the method, `<init>`.
b. The modifiers of the method written as a 32-bit integer.
c. The descriptor of the method.
7. For each non-`private` method sorted by method name and signature:
a. The name of the method.
b. The modifiers of the method written as a 32-bit integer.
c. The descriptor of the method.
8. The SHA-1 algorithm is executed on the stream of bytes produced by
`DataOutputStream` and produces five 32-bit values `sha[0..4]`.
9. The hash value is assembled from the first and second 32-bit values of the
SHA-1 message digest. If the result of the message digest, the five 32-bit
words `H0 H1 H2 H3 H4`, is in an array of five `int` values named `sha`,
the hash value would be computed as follows:
```
long hash = ((sha[0] >>> 24) & 0xFF) |
((sha[0] >>> 16) & 0xFF) << 8 |
((sha[0] >>> 8) & 0xFF) << 16 |
((sha[0] >>> 0) & 0xFF) << 24 |
((sha[1] >>> 24) & 0xFF) << 32 |
((sha[1] >>> 16) & 0xFF) << 40 |
((sha[1] >>> 8) & 0xFF) << 48 |
((sha[1] >>> 0) & 0xFF) << 56;
```
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,111 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](exceptions.html) | NEXT'
include-after: '[CONTENTS](index.html) | [PREV](exceptions.html) | NEXT'
title: 'Java Object Serialization Specification: C - Example of Serializable Fields'
---
- [Example Alternate Implementation of
java.io.File](#c.1-example-alternate-implementation-of-java.io.file)
-------------------------------------------------------------------------------
## C.1 Example Alternate Implementation of java.io.File
This appendix provides a brief example of how an existing class could be
specified and implemented to interoperate with the existing implementation but
without requiring the same assumptions about the representation of the file
name as a *String*.
The system class `java.io.File` represents a filename and has methods for
parsing, manipulating files and directories by name. It has a single private
field that contains the current file name. The semantics of the methods that
parse paths depend on the current path separator which is held in a static
field. This path separator is part of the serialized state of a file so that
file name can be adjusted when read.
The serialized state of a `File` object is defined as the serializable fields
and the sequence of data values for the file. In this case, there is one of
each.
```
Serializable Fields:
String path; // path name with embedded separators
Serializable Data:
char // path name separator for path name
```
An alternate implementation might be defined as follows:
```
class File implements java.io.Serializable {
...
private String[] pathcomponents;
// Define serializable fields with the ObjectStreamClass
/**
* @serialField path String
* Path components separated by separator.
*/
private static final ObjectStreamField[] serialPersistentFields
= { new ObjectStreamField("path", String.class) };
...
/**
* @serialData Default fields followed by separator character.
*/
private void writeObject(ObjectOutputStream s)
throws IOException
{
ObjectOutputStream.PutField fields = s.putFields();
StringBuffer str = new StringBuffer();
for(int i = 0; i < pathcomponents; i++) {
str.append(separator);
str.append(pathcomponents[i]);
}
fields.put("path", str.toString());
s.writeFields();
s.writeChar(separatorChar); // Add the separator character
}
...
private void readObject(ObjectInputStream s)
throws IOException
{
ObjectInputStream.GetField fields = s.readFields();
String path = (String)fields.get("path", null);
...
char sep = s.readChar(); // read the previous separator char
// parse path into components using the separator
// and store into pathcomponents array.
}
}
```
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,97 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](security.html) | [NEXT](examples.html)'
include-after: '[CONTENTS](index.html) | [PREV](security.html) | [NEXT](examples.html)'
title: 'Java Object Serialization Specification: B - Exceptions In Object Serialization'
---
-------------------------------------------------------------------------------
All exceptions thrown by serialization classes are subclasses of
`ObjectStreamException` which is a subclass of `IOException`.
### `ObjectStreamException`
Superclass of all serialization exceptions.
### `InvalidClassException`
Thrown when a class cannot be used to restore objects for any of these reasons:
- The class does not match the serial version of the class in the stream.
- The class contains fields with invalid primitive data types.
- The `Externalizable` class does not have a public no-arg constructor.
- The `Serializable` class can not access the no-arg constructor of its
closest non-Serializable superclass.
### `NotSerializableException`
Thrown by a `readObject` or `writeObject` method to terminate serialization or
deserialization.
### `StreamCorruptedException`
Thrown:
- If the stream header is invalid.
- If control information not found.
- If control information is invalid.
- JDK 1.1.5 or less attempts to call `readExternal` on a `PROTOCOL_VERSION_2`
stream.
### `NotActiveException`
Thrown if `writeObject` state is invalid within the following
`ObjectOutputStream` methods:
- `defaultWriteObject`
- `putFields`
- `writeFields`
Thrown if `readObject` state is invalid within the following
`ObjectInputStream` methods:
- `defaultReadObject`
- `readFields`
- `registerValidation`
### `InvalidObjectException`
Thrown when a restored object cannot be made valid.
### `OptionalDataException`
Thrown by `readObject` when there is primitive data in the stream and an object
is expected. The length field of the exception indicates the number of bytes
that are available in the current block.
### `WriteAbortedException`
Thrown when reading a stream terminated by an exception that occurred while the
stream was being written.
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1,132 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: 'CONTENTS | PREV | [NEXT](serial-arch.html)'
include-after: 'CONTENTS | PREV | [NEXT](serial-arch.html)'
title: 'Java Object Serialization Specification: Contents'
---
-------------------------------------------------------------------------------
## Table of Contents
### 1 [System Architecture](serial-arch.html)
- 1.1 [Overview](serial-arch.html#overview)
- 1.2 [Writing to an Object
Stream](serial-arch.html#writing-to-an-object-stream)
- 1.3 [Reading from an Object
Stream](serial-arch.html#reading-from-an-object-stream)
- 1.4 [Object Streams as
Containers](serial-arch.html#object-streams-as-containers)
- 1.5 [Defining Serializable Fields for a
Class](serial-arch.html#defining-serializable-fields-for-a-class)
- 1.6 [Documenting Serializable Fields and Data for a
Class](serial-arch.html#documenting-serializable-fields-and-data-for-a-class)
- 1.7 [Accessing Serializable Fields of a
Class](serial-arch.html#accessing-serializable-fields-of-a-class)
- 1.8 [The ObjectOutput
Interface](serial-arch.html#the-objectoutput-interface)
- 1.9 [The ObjectInput Interface](serial-arch.html#the-objectinput-interface)
- 1.10 [The Serializable
Interface](serial-arch.html#the-serializable-interface)
- 1.11 [The Externalizable
Interface](serial-arch.html#the-externalizable-interface)
- 1.12 [Serialization of Enum
Constants](serial-arch.html#serialization-of-enum-constants)
- 1.13 [Protecting Sensitive
Information](serial-arch.html#protecting-sensitive-information)
### 2 [Object Output Classes](output.html)
- 2.1 [The ObjectOutputStream
Class](output.html#the-objectoutputstream-class)
- 2.2 [The ObjectOutputStream.PutField
Class](output.html#the-objectoutputstream.putfield-class)
- 2.3 [The writeObject Method](output.html#the-writeobject-method)
- 2.4 [The writeExternal Method](output.html#the-writeexternal-method)
- 2.5 [The writeReplace Method](output.html#the-writereplace-method)
- 2.6 [The useProtocolVersion
Method](output.html#the-useprotocolversion-method)
### 3 [Object Input Classes](input.html)
- 3.1 [The ObjectInputStream Class](input.html#the-objectinputstream-class)
- 3.2 [The ObjectInputStream.GetField
Class](input.html#the-objectinputstream.getfield-class)
- 3.3 [The ObjectInputValidation
Interface](input.html#the-objectinputvalidation-interface)
- 3.4 [The readObject Method](input.html#the-readobject-method)
- 3.5 [The readObjectNoData Method](input.html#the-readobjectnodata-method)
- 3.6 [The readExternal Method](input.html#the-readexternal-method)
- 3.7 [The readResolve Method](input.html#the-readresolve-method)
### 4 [Class Descriptors](class.html)
- 4.1 [The ObjectStreamClass Class](class.html#the-objectstreamclass-class)
- 4.2 [Dynamic Proxy Class
Descriptors](class.html#dynamic-proxy-class-descriptors)
- 4.3 [Serialized Form](class.html#serialized-form)
- 4.4 [The ObjectStreamField Class](class.html#the-objectstreamfield-class)
- 4.5 [Inspecting Serializable
Classes](class.html#inspecting-serializable-classes)
- 4.6 [Stream Unique Identifiers](class.html#stream-unique-identifiers)
### 5 [Versioning of Serializable Objects](version.html)
- 5.1 [Overview](version.html#overview)
- 5.2 [Goals](version.html#goals)
- 5.3 [Assumptions](version.html#assumptions)
- 5.4 [Who's Responsible for Versioning of
Streams](version.html#whos-responsible-for-versioning-of-streams)
- 5.5 [Compatible Java Type
Evolution](version.html#compatible-java-type-evolution)
- 5.6 [Type Changes Affecting
Serialization](version.html#type-changes-affecting-serialization)
- 5.6.1 [Incompatible Changes](version.html#incompatible-changes)
- 5.6.2 [Compatible Changes](version.html#compatible-changes)
### 6 [Object Serialization Stream Protocol](protocol.html)
- 6.1 [Overview](protocol.html#overview)
- 6.2 [Stream Elements](protocol.html#stream-elements)
- 6.3 [Stream Protocol Versions](protocol.html#stream-protocol-versions)
- 6.4 [Grammar for the Stream
Format](protocol.html#grammar-for-the-stream-format)
- 6.4.1 [Rules of the Grammar](protocol.html#rules-of-the-grammar)
- 6.4.2 [Terminal Symbols and
Constants](protocol.html#terminal-symbols-and-constants)
### A [Security in Object Serialization](security.html)
### B [Exceptions In Object Serialization](exceptions.html)
### C [Example of Serializable Fields](examples.html)
- [C.1 Example Alternate Implementation of
`java.io.File`](examples.html#c.1-example-alternate-implementation-of-java.io.file)
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,672 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](output.html) | [NEXT](class.html)'
include-after: '[CONTENTS](index.html) | [PREV](output.html) | [NEXT](class.html)'
title: 'Java Object Serialization Specification: 3 - Object Input Classes'
---
- [The ObjectInputStream Class](#the-objectinputstream-class)
- [The ObjectInputStream.GetField
Class](#the-objectinputstream.getfield-class)
- [The ObjectInputValidation Interface](#the-objectinputvalidation-interface)
- [The readObject Method](#the-readobject-method)
- [The readExternal Method](#the-readexternal-method)
- [The readResolve Method](#the-readresolve-method)
-------------------------------------------------------------------------------
## 3.1 The ObjectInputStream Class
Class `ObjectInputStream` implements object deserialization. It maintains the
state of the stream including the set of objects already deserialized. Its
methods allow primitive types and objects to be read from a stream written by
`ObjectOutputStream`. It manages restoration of the object and the objects that
it refers to from the stream.
```
package java.io;
public class ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
{
public ObjectInputStream(InputStream in)
throws StreamCorruptedException, IOException;
public final Object readObject()
throws OptionalDataException, ClassNotFoundException,
IOException;
public Object readUnshared()
throws OptionalDataException, ClassNotFoundException,
IOException;
public void defaultReadObject()
throws IOException, ClassNotFoundException,
NotActiveException;
public GetField readFields()
throws IOException;
public synchronized void registerValidation(
ObjectInputValidation obj, int prio)
throws NotActiveException, InvalidObjectException;
protected ObjectStreamClass readClassDescriptor()
throws IOException, ClassNotFoundException;
protected Class resolveClass(ObjectStreamClass v)
throws IOException, ClassNotFoundException;
protected Object resolveObject(Object obj)
throws IOException;
protected boolean enableResolveObject(boolean enable)
throws SecurityException;
protected void readStreamHeader()
throws IOException, StreamCorruptedException;
public int read() throws IOException;
public int read(byte[] data, int offset, int length)
throws IOException
public int available() throws IOException;
public void close() throws IOException;
public boolean readBoolean() throws IOException;
public byte readByte() throws IOException;
public int readUnsignedByte() throws IOException;
public short readShort() throws IOException;
public int readUnsignedShort() throws IOException;
public char readChar() throws IOException;
public int readInt() throws IOException;
public long readLong() throws IOException;
public float readFloat() throws IOException;
public double readDouble() throws IOException;
public void readFully(byte[] data) throws IOException;
public void readFully(byte[] data, int offset, int size)
throws IOException;
public int skipBytes(int len) throws IOException;
public String readLine() throws IOException;
public String readUTF() throws IOException;
// Class to provide access to serializable fields.
static abstract public class GetField
{
public ObjectStreamClass getObjectStreamClass();
public boolean defaulted(String name)
throws IOException, IllegalArgumentException;
public char get(String name, char default)
throws IOException, IllegalArgumentException;
public boolean get(String name, boolean default)
throws IOException, IllegalArgumentException;
public byte get(String name, byte default)
throws IOException, IllegalArgumentException;
public short get(String name, short default)
throws IOException, IllegalArgumentException;
public int get(String name, int default)
throws IOException, IllegalArgumentException;
public long get(String name, long default)
throws IOException, IllegalArgumentException;
public float get(String name, float default)
throws IOException, IllegalArgumentException;
public double get(String name, double default)
throws IOException, IllegalArgumentException;
public Object get(String name, Object default)
throws IOException, IllegalArgumentException;
}
protected ObjectInputStream()
throws StreamCorruptedException, IOException;
protected readObjectOverride()
throws OptionalDataException, ClassNotFoundException,
IOException;
}
```
The single-argument `ObjectInputStream` constructor requires an `InputStream`.
The constructor calls `readStreamHeader` to read and verifies the header and
version written by the corresponding `ObjectOutputStream.writeStreamHeader`
method. If a security manager is installed, this constructor checks for the
`"enableSubclassImplementation"` `SerializablePermission` when invoked directly
or indirectly by the constructor of a subclass which overrides the `readFields`
and/or `readUnshared` methods.
**Note:** The `ObjectInputStream` constructor blocks until it completes reading
the serialization stream header. Code which waits for an `ObjectInputStream` to
be constructed before creating the corresponding `ObjectOutputStream` for that
stream will deadlock, since the `ObjectInputStream` constructor will block
until a header is written to the stream, and the header will not be written to
the stream until the `ObjectOutputStream` constructor executes. This problem
can be resolved by creating the `ObjectOutputStream` before the
`ObjectInputStream`, or otherwise removing the timing dependency between
completion of `ObjectInputStream` construction and the creation of the
`ObjectOutputStream`.
The `readObject` method is used to deserialize an object from the stream. It
reads from the stream to reconstruct an object.
1. If the `ObjectInputStream` subclass is overriding the implementation, call
the `readObjectOverride` method and return. Reimplementation is described
at the end of this section.
2. If a block data record occurs in the stream, throw a `BlockDataException`
with the number of available bytes.
3. If the object in the stream is null, return null.
4. If the object in the stream is a handle to a previous object, return the
object.
5. If the object in the stream is a `Class`, read its `ObjectStreamClass`
descriptor, add it and its handle to the set of known objects, and return
the corresponding `Class` object.
6. If the object in the stream is an `ObjectStreamClass`, read in its data
according to the formats described in [Section 4.3, "Serialized
Form"](class.html#serialized-form). Add it and its handle to the set of
known objects. In versions 1.3 and later of the Java 2 SDK, Standard
Edition, the `readClassDescriptor` method is called to read in the
`ObjectStreamClass` if it represents a class that is not a dynamic proxy
class, as indicated in the stream data. If the class descriptor represents
a dynamic proxy class, call the `resolveProxyClass` method on the stream to
get the local class for the descriptor; otherwise, call the `resolveClass`
method on the stream to get the local class. If the class cannot be
resolved, throw a ClassNotFoundException. Return the resulting
`ObjectStreamClass` object.
7. If the object in the stream is a `String`, read its length information
followed by the contents of the string encoded in modified UTF-8. For
details, refer to [Section 6.2, "Stream
Elements"](protocol.html#stream-elements). Add the `String` and its handle
to the set of known objects, and proceed to Step 12.
8. If the object in the stream is an array, read its `ObjectStreamClass` and
the length of the array. Allocate the array, and add it and its handle in
the set of known objects. Read each element using the appropriate method
for its type and assign it to the array. Proceed to Step 12.
9. If the object in the stream is an enum constant, read its
`ObjectStreamClass` and the enum constant name. If the `ObjectStreamClass`
represents a class that is not an enum type, an `InvalidClassException` is
thrown. Obtain a reference to the enum constant by calling the
`java.lang.Enum.valueOf` method, passing the enum type bound to the
received `ObjectStreamClass` along with the received name as arguments. If
the `valueOf` method throws an `IllegalArgumentException`, an
`InvalidObjectException` is thrown with the `IllegalArgumentException` as
its cause. Add the enum constant and its handle in the set of known
objects, and proceed to Step 12.
10. For all other objects, the `ObjectStreamClass` of the object is read from
the stream. The local class for that `ObjectStreamClass` is retrieved. The
class must be serializable or externalizable, and must not be an enum type.
If the class does not satisfy these criteria, an `InvalidClassException` is
thrown.
11. An instance of the class is allocated. The instance and its handle are
added to the set of known objects. The contents restored appropriately:
a. For serializable objects, the no-arg constructor for the first
non-serializable supertype is run. For serializable classes, the fields
are initialized to the default value appropriate for its type. Then the
fields of each class are restored by calling class-specific
`readObject` methods, or if these are not defined, by calling the
`defaultReadObject` method. Note that field initializers and
constructors are not executed for serializable classes during
deserialization. In the normal case, the version of the class that
wrote the stream will be the same as the class reading the stream. In
this case, all of the supertypes of the object in the stream will match
the supertypes in the currently-loaded class. If the version of the
class that wrote the stream had different supertypes than the loaded
class, the `ObjectInputStream` must be more careful about restoring or
initializing the state of the differing classes. It must step through
the classes, matching the available data in the stream with the classes
of the object being restored. Data for classes that occur in the
stream, but do not occur in the object, is discarded. For classes that
occur in the object, but not in the stream, the class fields are set to
default values by default serialization.
b. For externalizable objects, the no-arg constructor for the class is run
and then the `readExternal` method is called to restore the contents of
the object.
12. Process potential substitutions by the class of the object and/or by a
subclass of `ObjectInputStream`:
a. If the class of the object is not an enum type and defines the
appropriate `readResolve` method, the method is called to allow the
object to replace itself.
b. Then if previously enabled by `enableResolveObject,` the
`resolveObject` method is called to allow subclasses of the stream to
examine and replace the object. If the previous step did replace the
original object, the `resolveObject` method is called with the
replacement object. If a replacement took place, the table of known
objects is updated so the replacement object is associated with the
handle. The replacement object is then returned from `readObject`.
All of the methods for reading primitives types only consume bytes from the
block data records in the stream. If a read for primitive data occurs when the
next item in the stream is an object, the read methods return *-1* or the
`EOFException` as appropriate. The value of a primitive type is read by a
`DataInputStream` from the block data record.
The exceptions thrown reflect errors during the traversal or exceptions that
occur on the underlying stream. If any exception is thrown, the underlying
stream is left in an unknown and unusable state.
When the reset token occurs in the stream, all of the state of the stream is
discarded. The set of known objects is cleared.
When the exception token occurs in the stream, the exception is read and a new
`WriteAbortedException` is thrown with the terminating exception as an
argument. The stream context is reset as described earlier.
The `readUnshared` method is used to read "unshared" objects from the stream.
This method is identical to `readObject`, except that it prevents subsequent
calls to `readObject` and `readUnshared` from returning additional references
to the deserialized instance returned by the original call to `readUnshared`.
Specifically:
- If `readUnshared` is called to deserialize a back-reference (the stream
representation of an object which has been written previously to the
stream), an `ObjectStreamException` will be thrown.
- If `readUnshared` returns successfully, then any subsequent attempts to
deserialize back-references to the stream handle deserialized by
`readUnshared` will cause an `ObjectStreamException` to be thrown.
Deserializing an object via `readUnshared` invalidates the stream handle
associated with the returned object. Note that this in itself does not always
guarantee that the reference returned by `readUnshared` is unique; the
deserialized object may define a `readResolve` method which returns an object
visible to other parties, or `readUnshared` may return a `Class` object or enum
constant obtainable elsewhere in the stream or through external means. If the
deserialized object defines a `readResolve` method and the invocation of that
method returns an array, then `readUnshared` returns a shallow clone of that
array; this guarantees that the returned array object is unique and cannot be
obtained a second time from an invocation of `readObject` or `readUnshared` on
the `ObjectInputStream`, even if the underlying data stream has been
manipulated.
The `defaultReadObject` method is used to read the fields and object from the
stream. It uses the class descriptor in the stream to read the fields in the
canonical order by name and type from the stream. The values are assigned to
the matching fields by name in the current class. Details of the versioning
mechanism can be found in [Section 5.5, "Compatible Java Type
Evolution"](version.html#compatible-java-type-evolution). Any field of the
object that does not appear in the stream is set to its default value. Values
that appear in the stream, but not in the object, are discarded. This occurs
primarily when a later version of a class has written additional fields that do
not occur in the earlier version. This method may only be called from the
`readObject` method while restoring the fields of a class. When called at any
other time, the `NotActiveException` is thrown.
The `readFields` method reads the values of the serializable fields from the
stream and makes them available via the `GetField` class. The `readFields`
method is only callable from within the `readObject` method of a serializable
class. It cannot be called more than once or if `defaultReadObject` has been
called. The `GetFields` object uses the current object's `ObjectStreamClass` to
verify the fields that can be retrieved for this class. The `GetFields` object
returned by `readFields` is only valid during this call to the classes
`readObject` method. The fields may be retrieved in any order. Additional data
may only be read directly from stream after `readFields` has been called.
The `registerValidation` method can be called to request a callback when the
entire graph has been restored but before the object is returned to the
original caller of `readObject`. The order of validate callbacks can be
controlled using the priority. Callbacks registered with higher values are
called before those with lower values. The object to be validated must support
the `ObjectInputValidation` interface and implement the `validateObject`
method. It is only correct to register validations during a call to a class's
`readObject` method. Otherwise, a `NotActiveException` is thrown. If the
callback object supplied to `registerValidation` is null, an
`InvalidObjectException` is thrown.
Starting with the Java SDK, Standard Edition, v1.3, the `readClassDescriptor`
method is used to read in all `ObjectStreamClass` objects.
`readClassDescriptor` is called when the `ObjectInputStream` expects a class
descriptor as the next item in the serialization stream. Subclasses of
`ObjectInputStream` may override this method to read in class descriptors that
have been written in non-standard formats (by subclasses of
`ObjectOutputStream` which have overridden the `writeClassDescriptor` method).
By default, this method reads class descriptors according to the format
described in [Section 6.4, "Grammar for the Stream
Format"](protocol.html#grammar-for-the-stream-format).
The `resolveClass` method is called while a class is being deserialized, and
after the class descriptor has been read. Subclasses may extend this method to
read other information about the class written by the corresponding subclass of
`ObjectOutputStream`. The method must find and return the class with the given
name and `serialVersionUID`. The default implementation locates the class by
calling the class loader of the closest caller of `readObject` that has a class
loader. If the class cannot be found `ClassNotFoundException` should be thrown.
Prior to JDK 1.1.6, the `resolveClass` method was required to return the same
fully qualified class name as the class name in the stream. In order to
accommodate package renaming across releases, `method` `resolveClass` only
needs to return a class with the same base class name and `SerialVersionUID` in
JDK 1.1.6 and later versions.
The `resolveObject` method is used by trusted subclasses to monitor or
substitute one object for another during deserialization. Resolving objects
must be enabled explicitly by calling `enableResolveObject` before calling
`readObject` for the first object to be resolved. Once enabled, `resolveObject`
is called once for each serializable object just prior to the first time it is
being returned from `readObject`. Note that the `resolveObject` method is not
called for objects of the specially handled classes, `Class`,
`ObjectStreamClass`, `String`, and arrays. A subclass's implementation of
`resolveObject` may return a substitute object that will be assigned or
returned instead of the original. The object returned must be of a type that is
consistent and assignable to every reference of the original object or else a
`ClassCastException` will be thrown. All assignments are type-checked. All
references in the stream to the original object will be replaced by references
to the substitute object.
The `enableResolveObject` method is called by trusted subclasses of
`ObjectOutputStream` to enable the monitoring or substitution of one object for
another during deserialization. Replacing objects is disabled until
`enableResolveObject` is called with a `true` value. It may thereafter be
disabled by setting it to `false`. The previous setting is returned. The
`enableResolveObject` method checks if the stream has permission to request
substitution during serialization. To ensure that the private state of objects
is not unintentionally exposed, only trusted streams may use `resolveObject`.
Trusted classes are those classes with a class loader equal to null or belong
to a security protection domain that provides permission to enable
substitution.
If the subclass of `ObjectInputStream` is not considered part of the system
domain, a line has to be added to the security policy file to provide to a
subclass of `ObjectInputStream` permission to call `enableResolveObject`. The
`SerializablePermission` to add is `"enableSubstitution"`.
`AccessControlException` is thrown if the protection domain of the subclass of
`ObjectStreamClass` does not have permission to `"enableSubstitution"` by
calling `enableResolveObject`. See the document Java Security Architecture (JDK
1.2) for additional information about the security model.
The `readStreamHeader` method reads and verifies the magic number and version
of the stream. If they do not match, the `StreamCorruptedMismatch` is thrown.
To override the implementation of deserialization, a subclass of
`ObjectInputStream` should call the protected no-arg `ObjectInputStream`,
constructor. There is a security check within the no-arg constructor for
`SerializablePermission "enableSubclassImplementation"` to ensure that only
trusted classes are allowed to override the default implementation. This
constructor does not allocate any private data for `ObjectInputStream` and sets
a flag that indicates that the final `readObject` method should invoke the
`readObjectOverride` method and return. All other `ObjectInputStream` methods
are not final and can be directly overridden by the subclass.
## 3.2 The ObjectInputStream.GetField Class
The class `ObjectInputStream.GetField` provides the API for getting the values
of serializable fields. The protocol of the stream is the same as used by
`defaultReadObject.` Using `readFields` to access the serializable fields does
not change the format of the stream. It only provides an alternate API to
access the values which does not require the class to have the corresponding
non-transient and non-static fields for each named serializable field. The
serializable fields are those declared using `serialPersistentFields` or if it
is not declared the non-transient and non-static fields of the object. When the
stream is read the available serializable fields are those written to the
stream when the object was serialized. If the class that wrote the stream is a
different version not all fields will correspond to the serializable fields of
the current class. The available fields can be retrieved from the
`ObjectStreamClass` of the `GetField` object.
The `getObjectStreamClass` method returns an `ObjectStreamClass` object
representing the class in the stream. It contains the list of serializable
fields.
The `defaulted` method returns *true* if the field is not present in the
stream. An `IllegalArgumentException` is thrown if the requested field is not a
serializable field of the current class.
Each `get` method returns the specified serializable field from the stream. I/O
exceptions will be thrown if the underlying stream throws an exception. An
`IllegalArgumentException` is thrown if the name or type does not match the
name and type of an field serializable field of the current class. The default
value is returned if the stream does not contain an explicit value for the
field.
## 3.3 The ObjectInputValidation Interface
This interface allows an object to be called when a complete graph of objects
has been deserialized. If the object cannot be made valid, it should throw the
`ObjectInvalidException`. Any exception that occurs during a call to
`validateObject` will terminate the validation process, and the
`InvalidObjectException` will be thrown.
```
package java.io;
public interface ObjectInputValidation
{
public void validateObject()
throws InvalidObjectException;
}
```
## 3.4 The readObject Method
For serializable objects, the `readObject` method allows a class to control the
deserialization of its own fields. Here is its signature:
```
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException;
```
Each subclass of a serializable object may define its own `readObject` method.
If a class does not implement the method, the default serialization provided by
`defaultReadObject` will be used. When implemented, the class is only
responsible for restoring its own fields, not those of its supertypes or
subtypes.
The `readObject` method of the class, if implemented, is responsible for
restoring the state of the class. The values of every field of the object
whether transient or not, static or not are set to the default value for the
fields type. Either `ObjectInputStream`'s `defaultReadObject` or `readFields`
method must be called once (and only once) before reading any optional data
written by the corresponding `writeObject` method; even if no optional data is
read, `defaultReadObject` or `readFields` must still be invoked once. If the
`readObject` method of the class attempts to read more data than is present in
the optional part of the stream for this class, the stream will return `-1` for
bytewise reads, throw an `EOFException` for primitive data reads (e.g.,
`readInt`, `readFloat`), or throw an `OptionalDataException` with the `eof`
field set to `true` for object reads.
The responsibility for the format, structure, and versioning of the optional
data lies completely with the class. The `@serialData` javadoc tag within the
javadoc comment for the `readObject` method should be used to document the
format and structure of the optional data.
If the class being restored is not present in the stream being read, then its
`readObjectNoData` method, if defined, is invoked (instead of `readObject`);
otherwise, its fields are initialized to the appropriate default values. For
further detail, see [Section 3.5, "The readObjectNoData
Method"](#the-readobjectnodata-method).
Reading an object from the `ObjectInputStream` is analogous to creating a new
object. Just as a new object's constructors are invoked in the order from the
superclass to the subclass, an object being read from a stream is deserialized
from superclass to subclass. The `readObject` or `readObjectNoData` method is
called instead of the constructor for each `Serializable` subclass during
deserialization.
One last similarity between a constructor and a `readObject` method is that
both provide the opportunity to invoke a method on an object that is not fully
constructed. Any overridable (neither private, static nor final) method called
while an object is being constructed can potentially be overridden by a
subclass. Methods called during the construction phase of an object are
resolved by the actual type of the object, not the type currently being
initialized by either its constructor or `readObject`/`readObjectNoData`
method. Therefore, calling an overridable method from within a `readObject` or
`readObjectNoData` method may result in the unintentional invocation of a
subclass method before the superclass has been fully initialized.
## 3.5 The readObjectNoData Method
For serializable objects, the `readObjectNoData` method allows a class to
control the initialization of its own fields in the event that a subclass
instance is deserialized and the serialization stream does not list the class
in question as a superclass of the deserialized object. This may occur in cases
where the receiving party uses a different version of the deserialized
instance's class than the sending party, and the receiver's version extends
classes that are not extended by the sender's version. This may also occur if
the serialization stream has been tampered; hence, `readObjectNoData` is useful
for initializing deserialized objects properly despite a "hostile" or
incomplete source stream.
```
private void readObjectNoData() throws ObjectStreamException;
```
Each serializable class may define its own `readObjectNoData` method. If a
serializable class does not define a `readObjectNoData` method, then in the
circumstances listed above the fields of the class will be initialized to their
default values (as listed in The Java Language Specification); this behavior is
consistent with that of `ObjectInputStream` prior to version 1.4 of the Java 2
SDK, Standard Edition, when support for `readObjectNoData` methods was
introduced. If a serializable class does define a `readObjectNoData` method and
the aforementioned conditions arise, then `readObjectNoData` will be invoked at
the point during deserialization when a class-defined `readObject` method would
otherwise be called had the class in question been listed by the stream as a
superclass of the instance being deserialized.
## 3.6 The readExternal Method
Objects implementing `java.io.Externalizable` must implement the `readExternal`
method to restore the entire state of the object. It must coordinate with its
superclasses to restore their state. All of the methods of `ObjectInput` are
available to restore the object's primitive typed fields and object fields.
```
public void readExternal(ObjectInput stream)
throws IOException;
```
**Note:** The `readExternal` method is public, and it raises the risk of a
client being able to overwrite an existing object from a stream. The class may
add its own checks to insure that this is only called when appropriate.
A new stream protocol version has been introduced in JDK 1.2 to correct a
problem with `Externalizable` objects. The old definition of `Externalizable`
objects required the local virtual machine to find a `readExternal` method to
be able to properly read an `Externalizable` object from the stream. The new
format adds enough information to the stream protocol so serialization can skip
an `Externalizable` object when the local `readExternal` method is not
available. Due to class evolution rules, serialization must be able to skip an
`Externalizable` object in the input stream if there is not a mapping for the
object using the local classes.
An additional benefit of the new `Externalizable` stream format is that
`ObjectInputStream` can detect attempts to read more External data than is
available, and can also skip by any data that is left unconsumed by a
`readExternal` method. The behavior of `ObjectInputStream` in response to a
read past the end of External data is the same as the behavior when a
class-defined `readObject` method attempts to read past the end of its optional
data: bytewise reads will return `-1`, primitive reads will throw
`EOFException`s, and object reads will throw `OptionalDataException`s with the
`eof` field set to `true`.
Due to the format change, JDK 1.1.6 and earlier releases are not able to read
the new format. `StreamCorruptedException` is thrown when JDK 1.1.6 or earlier
attempts to read an `Externalizable` object from a stream written in
`PROTOCOL_VERSION_2`. Compatibility issues are discussed in more detail in
[Section 6.3, "Stream Protocol
Versions"](protocol.html#stream-protocol-versions).
## 3.7 The readResolve Method
For Serializable and Externalizable classes, the `readResolve` method allows a
class to replace/resolve the object read from the stream before it is returned
to the caller. By implementing the `readResolve` method, a class can directly
control the types and instances of its own instances being deserialized. The
method is defined as follows:
```
ANY-ACCESS-MODIFIER Object readResolve()
throws ObjectStreamException;
```
The `readResolve` method is called when `ObjectInputStream` has read an object
from the stream and is preparing to return it to the caller.
`ObjectInputStream` checks whether the class of the object defines the
`readResolve` method. If the method is defined, the `readResolve` method is
called to allow the object in the stream to designate the object to be
returned. The object returned should be of a type that is compatible with all
uses. If it is not compatible, a `ClassCastException` will be thrown when the
type mismatch is discovered.
For example, a `Symbol` class could be created for which only a single instance
of each symbol binding existed within a virtual machine. The `readResolve`
method would be implemented to determine if that symbol was already defined and
substitute the preexisting equivalent `Symbol` object to maintain the identity
constraint. In this way the uniqueness of `Symbol` objects can be maintained
across serialization.
**Note:** The `readResolve` method is not invoked on the object until the
object is fully constructed, so any references to this object in its object
graph will not be updated to the new object nominated by `readResolve`.
However, during the serialization of an object with the `writeReplace` method,
all references to the original object in the replacement object's object graph
are replaced with references to the replacement object. Therefore in cases
where an object being serialized nominates a replacement object whose object
graph has a reference to the original object, deserialization will result in an
incorrect graph of objects. Furthermore, if the reference types of the object
being read (nominated by `writeReplace`) and the original object are not
compatible, the construction of the object graph will raise a
`ClassCastException`.
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,514 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](serial-arch.html) | [NEXT](input.html)'
include-after: '[CONTENTS](index.html) | [PREV](serial-arch.html) | [NEXT](input.html)'
title: 'Java Object Serialization Specification: 2 - Object Output Classes'
---
- [The ObjectOutputStream Class](#the-objectoutputstream-class)
- [The ObjectOutputStream.PutField
Class](#the-objectoutputstream.putfield-class)
- [The writeObject Method](#the-writeobject-method)
- [The writeExternal Method](#the-writeexternal-method)
- [The writeReplace Method](#the-writereplace-method)
- [The useProtocolVersion Method](#the-useprotocolversion-method)
-------------------------------------------------------------------------------
## 2.1 The ObjectOutputStream Class
Class `ObjectOutputStream` implements object serialization. It maintains the
state of the stream including the set of objects already serialized. Its
methods control the traversal of objects to be serialized to save the specified
objects and the objects to which they refer.
```
package java.io;
public class ObjectOutputStream
extends OutputStream
implements ObjectOutput, ObjectStreamConstants
{
public ObjectOutputStream(OutputStream out)
throws IOException;
public final void writeObject(Object obj)
throws IOException;
public void writeUnshared(Object obj)
throws IOException;
public void defaultWriteObject()
throws IOException, NotActiveException;
public PutField putFields()
throws IOException;
public writeFields()
throws IOException;
public void reset() throws IOException;
protected void annotateClass(Class cl) throws IOException;
protected void writeClassDescriptor(ObjectStreamClass desc)
throws IOException;
protected Object replaceObject(Object obj) throws IOException;
protected boolean enableReplaceObject(boolean enable)
throws SecurityException;
protected void writeStreamHeader() throws IOException;
public void write(int data) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
public void flush() throws IOException;
protected void drain() throws IOException;
public void close() throws IOException;
public void writeBoolean(boolean data) throws IOException;
public void writeByte(int data) throws IOException;
public void writeShort(int data) throws IOException;
public void writeChar(int data) throws IOException;
public void writeInt(int data) throws IOException;
public void writeLong(long data) throws IOException;
public void writeFloat(float data) throws IOException;
public void writeDouble(double data) throws IOException;
public void writeBytes(String data) throws IOException;
public void writeChars(String data) throws IOException;
public void writeUTF(String data) throws IOException;
// Inner class to provide access to serializable fields.
abstract static public class PutField
{
public void put(String name, boolean value)
throws IOException, IllegalArgumentException;
public void put(String name, char data)
throws IOException, IllegalArgumentException;
public void put(String name, byte data)
throws IOException, IllegalArgumentException;
public void put(String name, short data)
throws IOException, IllegalArgumentException;
public void put(String name, int data)
throws IOException, IllegalArgumentException;
public void put(String name, long data)
throws IOException, IllegalArgumentException;
public void put(String name, float data)
throws IOException, IllegalArgumentException;
public void put(String name, double data)
throws IOException, IllegalArgumentException;
public void put(String name, Object data)
throws IOException, IllegalArgumentException;
}
public void useProtocolVersion(int version) throws IOException;
protected ObjectOutputStream()
throws IOException;
protected writeObjectOverride()
throws NotActiveException, IOException;
}
```
The single-argument `ObjectOutputStream` constructor creates an
`ObjectOutputStream` that serializes objects to the given `OutputStream`. The
constructor calls `writeStreamHeader` to write a magic number and version to
the stream that will be read and verified by a corresponding call to
`readStreamHeader` in the single-argument `ObjectInputStream` constructor. If a
security manager is installed, this constructor checks for the
`"enableSubclassImplementation"` `SerializablePermission` when invoked directly
or indirectly by the constructor of a subclass which overrides the `putFields`
and/or `writeUnshared` methods.
The `writeObject` method is used to serialize an object to the stream. An
object is serialized as follows:
1. If a subclass is overriding the implementation, call the
`writeObjectOverride` method and return. Overriding the implementation is
described at the end of this section.
2. If there is data in the block-data buffer, the data is written to the
stream and the buffer is reset.
3. If the object is null, null is put in the stream and `writeObject` returns.
4. If the object has been previously replaced, as described in Step 8, write
the handle of the replacement to the stream and `writeObject` returns.
5. If the object has already been written to the stream, its handle is written
to the stream and `writeObject` returns.
6. If the object is a `Class`, the corresponding `ObjectStreamClass` is
written to the stream, a handle is assigned for the class, and
`writeObject` returns.
7. If the object is an `ObjectStreamClass`, a handle is assigned to the
object, after which it is written to the stream using one of the class
descriptor formats described in [Section 4.3, "Serialized
Form"](class.html#serialized-form). In versions 1.3 and later of the Java 2
SDK, Standard Edition, the `writeClassDescriptor` method is called to
output the `ObjectStreamClass` if it represents a class that is not a
dynamic proxy class, as determined by passing the associated `Class` object
to the `isProxyClass` method of `java.lang.reflect.Proxy`. Afterwards, an
annotation for the represented class is written: if the class is a dynamic
proxy class, then the `annotateProxyClass` method is called; otherwise, the
`annotateClass` method is called. The `writeObject` method then returns.
8. Process potential substitutions by the class of the object and/or by a
subclass of `ObjectInputStream`.
a. If the class of an object is not an enum type and defines the
appropriate `writeReplace` method, the method is called. Optionally, it
can return a substitute object to be serialized.
b. Then, if enabled by calling the `enableReplaceObject` method, the
`replaceObject` method is called to allow subclasses of
`ObjectOutputStream` to substitute for the object being serialized. If
the original object was replaced in the previous step, the
`replaceObject` method is called with the replacement object.
If the original object was replaced by either one or both steps above, the
mapping from the original object to the replacement is recorded for later
use in Step 4. Then, Steps 3 through 7 are repeated on the new object.
If the replacement object is not one of the types covered by Steps 3
through 7, processing resumes using the replacement object at Step 10.
9. <a id="java-lang-string-encoding"></a>
If the object is a `java.lang.String,` the string is written as length
information followed by the contents of the string encoded in modified
UTF-8. For details, refer to [Section 6.2, "Stream
Elements"](protocol.html#stream-elements). A handle is assigned to the
string, and `writeObject` returns.
10. If the object is an array, `writeObject` is called recursively to write the
`ObjectStreamClass` of the array. The handle for the array is assigned. It
is followed by the length of the array. Each element of the array is then
written to the stream, after which `writeObject` returns.
11. If the object is an enum constant, the `ObjectStreamClass` for the enum
type of the constant is written by recursively calling `writeObject`. It
will appear in the stream only the first time it is referenced. A handle is
assigned for the enum constant. Next, the value returned by the `name`
method of the enum constant is written as a `String` object, as described
in step 9. Note that if the same name string has appeared previously in the
stream, a back reference to it will be written. The `writeObject` method
then returns.
12. For regular objects, the `ObjectStreamClass` for the class of the object is
written by recursively calling `writeObject`. It will appear in the stream
only the first time it is referenced. A handle is assigned for the object.
13. The contents of the object are written to the stream.
a. If the object is serializable, the highest serializable class is
located. For that class, and each derived class, that class's fields
are written. If the class does not have a `writeObject` method, the
`defaultWriteObject` method is called to write the serializable fields
to the stream. If the class does have a `writeObject` method, it is
called. It may call `defaultWriteObject` or `putFields` and
`writeFields` to save the state of the object, and then it can write
other information to the stream.
b. If the object is externalizable, the `writeExternal` method of the
object is called.
c. If the object is neither serializable or externalizable, the
`NotSerializableException` is thrown.
Exceptions may occur during the traversal or may occur in the underlying
stream. For any subclass of `IOException`, the exception is written to the
stream using the exception protocol and the stream state is discarded. If a
second `IOException` is thrown while attempting to write the first exception
into the stream, the stream is left in an unknown state and
`StreamCorruptedException` is thrown from `writeObject`. For other exceptions,
the stream is aborted and left in an unknown and unusable state.
The `writeUnshared` method writes an "unshared" object to the
`ObjectOutputStream`. This method is identical to `writeObject`, except that it
always writes the given object as a new, unique object in the stream (as
opposed to a back-reference pointing to a previously serialized instance).
Specifically:
- An object written via `writeUnshared` is always serialized in the same
manner as a newly appearing object (an object that has not been written to
the stream yet), regardless of whether or not the object has been written
previously.
- If `writeObject` is used to write an object that has been previously
written with `writeUnshared`, the previous `writeUnshared` operation is
treated as if it were a write of a separate object. In other words,
`ObjectOutputStream` will never generate back-references to object data
written by calls to `writeUnshared`.
While writing an object via `writeUnshared` does not in itself guarantee a
unique reference to the object when it is deserialized, it allows a single
object to be defined multiple times in a stream, so that multiple calls to the
`ObjectInputStream.readUnshared` method (see [Section 3.1, "The
ObjectInputStream Class"](input.html#the-objectinputstream-class)) by the
receiver will not conflict. Note that the rules described above only apply to
the base-level object written with `writeUnshared`, and not to any transitively
referenced sub-objects in the object graph to be serialized.
The `defaultWriteObject` method implements the default serialization mechanism
for the current class. This method may be called only from a class's
`writeObject` method. The method writes all of the serializable fields of the
current class to the stream. If called from outside the `writeObject` method,
the `NotActiveException` is thrown.
The `putFields` method returns a `PutField` object the caller uses to set the
values of the serializable fields in the stream. The fields may be set in any
order. After all of the fields have been set, `writeFields` must be called to
write the field values in the canonical order to the stream. If a field is not
set, the default value appropriate for its type will be written to the stream.
This method may only be called from within the `writeObject` method of a
serializable class. It may not be called more than once or if
`defaultWriteObject` has been called. Only after `writeFields` has been called
can other data be written to the stream.
The `reset` method resets the stream state to be the same as if it had just
been constructed. `Reset` will discard the state of any objects already written
to the stream. The current point in the stream is marked as reset, so the
corresponding `ObjectInputStream` will reset at the same point. Objects
previously written to the stream will not be remembered as already having been
written to the stream. They will be written to the stream again. This is useful
when the contents of an object or objects must be sent again. `Reset` may not
be called while objects are being serialized. If called inappropriately, an
`IOException` is thrown.
Starting with the Java 2 SDK, Standard Edition, v1.3, the
`writeClassDescriptor` method is called when an `ObjectStreamClass` needs to be
serialized. `writeClassDescriptor` is responsible for writing a representation
of the `ObjectStreamClass` to the serialization stream. Subclasses may override
this method to customize the way in which class descriptors are written to the
serialization stream. If this method is overridden, then the corresponding
`readClassDescriptor` method in `ObjectInputStream` should also be overridden
to reconstitute the class descriptor from its custom stream representation. By
default, `writeClassDescriptor` writes class descriptors according to the
format specified in [Section 6.4, "Grammar for the Stream
Format"](protocol.html#grammar-for-the-stream-format). Note that this method
will only be called if the `ObjectOutputStream` is not using the old
serialization stream format (see [Section 6.3, "Stream Protocol
Versions"](protocol.html#stream-protocol-versions)). If the serialization
stream is using the old format (`ObjectStreamConstants.PROTOCOL_VERSION_1`),
the class descriptor will be written internally in a manner that cannot be
overridden or customized.
The `annotateClass` method is called while a `Class` is being serialized, and
after the class descriptor has been written to the stream. Subclasses may
extend this method and write other information to the stream about the class.
This information must be read by the `resolveClass` method in a corresponding
`ObjectInputStream` subclass.
An `ObjectOutputStream` subclass can implement the `replaceObject` method to
monitor or replace objects during serialization. Replacing objects must be
enabled explicitly by calling `enableReplaceObject` before calling
`writeObject` with the first object to be replaced. Once enabled,
`replaceObject` is called for each object just prior to serializing the object
for the first time. Note that the `replaceObject` method is not called for
objects of the specially handled classes, `Class` and `ObjectStreamClass`. An
implementation of a subclass may return a substitute object that will be
serialized instead of the original. The substitute object must be serializable.
All references in the stream to the original object will be replaced by the
substitute object.
When objects are being replaced, the subclass must ensure that the substituted
object is compatible with every field where the reference will be stored, or
that a complementary substitution will be made during deserialization. Objects,
whose type is not a subclass of the type of the field or array element, will
later abort the deserialization by raising a `ClassCastException` and the
reference will not be stored.
The `enableReplaceObject` method can be called by trusted subclasses of
`ObjectOutputStream` to enable the substitution of one object for another
during serialization. Replacing objects is disabled until `enableReplaceObject`
is called with a `true` value. It may thereafter be disabled by setting it to
`false`. The previous setting is returned. The `enableReplaceObject` method
checks that the stream requesting the replacement can be trusted. To ensure
that the private state of objects is not unintentionally exposed, only trusted
stream subclasses may use `replaceObject`. Trusted classes are those classes
that belong to a security protection domain with permission to enable
Serializable substitution.
If the subclass of `ObjectOutputStream` is not considered part of the system
domain, `SerializablePermission "enableSubstitution"` must be added to the
security policy file. `AccessControlException` is thrown if the protection
domain of the subclass of `ObjectInputStream` does not have permission to
`"enableSubstitution"` by calling `enableReplaceObject`. See the document Java
Security Architecture (JDK1.2) for additional information about the security
model.
The `writeStreamHeader` method writes the magic number and version to the
stream. This information must be read by the `readStreamHeader` method of
`ObjectInputStream`. Subclasses may need to implement this method to identify
the stream's unique format.
The `flush` method is used to empty any buffers being held by the stream and to
forward the flush to the underlying stream. The `drain` method may be used by
subclassers to empty only the `ObjectOutputStream`'s buffers without forcing
the underlying stream to be flushed.
All of the write methods for primitive types encode their values using a
`DataOutputStream` to put them in the standard stream format. The bytes are
buffered into block data records so they can be distinguished from the encoding
of objects. This buffering allows primitive data to be skipped if necessary for
class versioning. It also allows the stream to be parsed without invoking
class-specific methods.
To override the implementation of serialization, the subclass of
`ObjectOutputStream` should call the protected no-arg `ObjectOutputStream`,
constructor. There is a security check within the no-arg constructor for
`SerializablePermission "enableSubclassImplementation"` to ensure that only
trusted classes are allowed to override the default implementation. This
constructor does not allocate any private data for `ObjectOutputStream` and
sets a flag that indicates that the final `writeObject` method should invoke
the `writeObjectOverride` method and return. All other `ObjectOutputStream`
methods are not final and can be directly overridden by the subclass.
## 2.2 The ObjectOutputStream.PutField Class
Class `PutField` provides the API for setting values of the serializable fields
for a class when the class does not use default serialization. Each method puts
the specified named value into the stream. An `IllegalArgumentException` is
thrown if `name` does not match the name of a serializable field for the class
whose fields are being written, or if the type of the named field does not
match the second parameter type of the specific `put` method invoked.
## 2.3 The writeObject Method
For serializable objects, the `writeObject` method allows a class to control
the serialization of its own fields. Here is its signature:
```
private void writeObject(ObjectOutputStream stream)
throws IOException;
```
Each subclass of a serializable object may define its own `writeObject` method.
If a class does not implement the method, the default serialization provided by
`defaultWriteObject` will be used. When implemented, the class is only
responsible for writing its own fields, not those of its supertypes or
subtypes.
The class's `writeObject` method, if implemented, is responsible for saving the
state of the class. Either `ObjectOutputStream`'s `defaultWriteObject` or
`writeFields` method must be called once (and only once) before writing any
optional data that will be needed by the corresponding `readObject` method to
restore the state of the object; even if no optional data is written,
`defaultWriteObject` or `writeFields` must still be invoked once. If
`defaultWriteObject` or `writeFields` is not invoked once prior to the writing
of optional data (if any), then the behavior of instance deserialization is
undefined in cases where the `ObjectInputStream` cannot resolve the class which
defined the `writeObject` method in question.
The responsibility for the format, structure, and versioning of the optional
data lies completely with the class.
## 2.4 The writeExternal Method
Objects implementing `java.io.Externalizable` must implement the
`writeExternal` method to save the entire state of the object. It must
coordinate with its superclasses to save their state. All of the methods of
`ObjectOutput` are available to save the object's primitive typed fields and
object fields.
```
public void writeExternal(ObjectOutput stream)
throws IOException;
```
A new default format for writing Externalizable data has been introduced in JDK
1.2. The new format specifies that primitive data will be written in block data
mode by `writeExternal` methods. Additionally, a tag denoting the end of the
External object is appended to the stream after the `writeExternal` method
returns. The benefits of this format change are discussed in [Section 3.6, "The
readExternal Method"](input.html#the-readexternal-method). Compatibility issues
caused by this change are discussed in [Section 2.6, "The useProtocolVersion
Method"](#the-useprotocolversion-method).
## 2.5 The writeReplace Method
For Serializable and Externalizable classes, the `writeReplace` method allows a
class of an object to nominate its own replacement in the stream before the
object is written. By implementing the `writeReplace` method, a class can
directly control the types and instances of its own instances being serialized.
The method is defined as follows:
```
ANY-ACCESS-MODIFIER Object writeReplace()
throws ObjectStreamException;
```
The `writeReplace` method is called when `ObjectOutputStream` is preparing to
write the object to the stream. The `ObjectOutputStream` checks whether the
class defines the `writeReplace` method. If the method is defined, the
`writeReplace` method is called to allow the object to designate its
replacement in the stream. The object returned should be either of the same
type as the object passed in or an object that when read and resolved will
result in an object of a type that is compatible with all references to the
object. If it is not, a `ClassCastException` will occur when the type mismatch
is discovered.
## 2.6 The useProtocolVersion Method
Due to a stream protocol change that was not backwards compatible, a mechanism
has been added to enable the current Virtual Machine to write a serialization
stream that is readable by a previous release. Of course, the problems that are
corrected by the new stream format will exist when using the backwards
compatible protocol.
Stream protocol versions are discussed in [Section 6.3, "Stream Protocol
Versions"](protocol.html#stream-protocol-versions).
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,504 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](version.html) | [NEXT](security.html)'
include-after: '[CONTENTS](index.html) | [PREV](version.html) | [NEXT](security.html)'
title: 'Java Object Serialization Specification: 6 - Object Serialization Stream Protocol'
---
- [Overview](#overview)
- [Stream Elements](#stream-elements)
- [Stream Protocol Versions](#stream-protocol-versions)
- [Grammar for the Stream Format](#grammar-for-the-stream-format)
- [Example](#example)
-------------------------------------------------------------------------------
## 6.1 Overview
The stream format satisfies the following design goals:
- Is compact and is structured for efficient reading.
- Allows skipping through the stream using only the knowledge of the
structure and format of the stream. Does not require invoking any per class
code.
- Requires only stream access to the data.
## 6.2 Stream Elements
A basic structure is needed to represent objects in a stream. Each attribute of
the object needs to be represented: its classes, its fields, and data written
and later read by class-specific methods. The representation of objects in the
stream can be described with a grammar. There are special representations for
null objects, new objects, classes, arrays, strings, and back references to any
object already in the stream. Each object written to the stream is assigned a
handle that is used to refer back to the object. Handles are assigned
sequentially starting from 0x7E0000. The handles restart at 0x7E0000 when the
stream is reset.
A class object is represented by the following:
- Its `ObjectStreamClass` object.
An `ObjectStreamClass` object for a Class that is not a dynamic proxy class is
represented by the following:
- The Stream Unique Identifier (SUID) of compatible classes.
- A set of flags indicating various properties of the class, such as whether
the class defines a `writeObject` method, and whether the class is
serializable, externalizable, or an enum type
- The number of serializable fields
- The array of fields of the class that are serialized by the default
mechanismFor arrays and object fields, the type of the field is included as
a string which must be in "field descriptor" format (e.g.,
"`Ljava/lang/Object;`") as specified in The Java Virtual Machine
Specification.
- Optional block-data records or objects written by the `annotateClass`
method
- The `ObjectStreamClass` of its supertype (null if the superclass is not
serializable)
An `ObjectStreamClass` object for a dynamic proxy class is represented by the
following:
- The number of interfaces that the dynamic proxy class implements
- The names of all of the interfaces implemented by the dynamic proxy class,
listed in the order that they are returned by invoking the `getInterfaces`
method on the Class object.
- Optional block-data records or objects written by the `annotateProxyClass`
method.
- The ObjectStreamClass of its supertype, `java.lang.reflect.Proxy`.
The representation of `String` objects consists of length information followed
by the contents of the string encoded in modified UTF-8. The modified UTF-8
encoding is the same as used in the Java Virtual Machine and in the
`java.io.DataInput` and `DataOutput` interfaces; it differs from standard UTF-8
in the representation of supplementary characters and of the null character.
The form of the length information depends on the length of the string in
modified UTF-8 encoding. If the modified UTF-8 encoding of the given `String`
is less than 65536 bytes in length, the length is written as 2 bytes
representing an unsigned 16-bit integer. Starting with the Java 2 platform,
Standard Edition, v1.3, if the length of the string in modified UTF-8 encoding
is 65536 bytes or more, the length is written in 8 bytes representing a signed
64-bit integer. The typecode preceding the `String` in the serialization stream
indicates which format was used to write the `String`.
Arrays are represented by the following:
- Their `ObjectStreamClass` object.
- The number of elements.
- The sequence of values. The type of the values is implicit in the type of
the array. for example the values of a byte array are of type byte.
Enum constants are represented by the following:
- The `ObjectStreamClass` object of the constant's base enum type.
- The constant's name string.
New objects in the stream are represented by the following:
- The most derived class of the object.
- Data for each serializable class of the object, with the highest superclass
first. For each class the stream contains the following:
- The serializable fields.See [Section 1.5, "Defining Serializable Fields
for a
Class"](serial-arch.html#defining-serializable-fields-for-a-class).
- If the class has `writeObject`/`readObject` methods, there may be
optional objects and/or block-data records of primitive types written
by the `writeObject` method followed by an `endBlockData` code.
All primitive data written by classes is buffered and wrapped in block-data
records, regardless if the data is written to the stream within a `writeObject`
method or written directly to the stream from outside a `writeObject` method.
This data can only be read by the corresponding `readObject` methods or be read
directly from the stream. Objects written by the `writeObject` method terminate
any previous block-data record and are written either as regular objects or
null or back references, as appropriate. The block-data records allow error
recovery to discard any optional data. When called from within a class, the
stream can discard any data or objects until the `endBlockData`.
## 6.3 Stream Protocol Versions
It was necessary to make a change to the serialization stream format in JDK 1.2
that is not backwards compatible to all minor releases of JDK 1.1. To provide
for cases where backwards compatibility is required, a capability has been
added to indicate what `PROTOCOL_VERSION` to use when writing a serialization
stream. The method `ObjectOutputStream.useProtocolVersion` takes as a parameter
the protocol version to use to write the serialization stream.
The Stream Protocol Versions are as follows:
- `ObjectStreamConstants.PROTOCOL_VERSION_1`: Indicates the initial stream
format.
- `ObjectStreamConstants.PROTOCOL_VERSION_2`: Indicates the new external data
format. Primitive data is written in block data mode and is terminated with
`TC_ENDBLOCKDATA`.
Block data boundaries have been standardized. Primitive data written in
block data mode is normalized to not exceed 1024 byte chunks. The benefit
of this change was to tighten the specification of serialized data format
within the stream. This change is fully backward and forward compatible.
JDK 1.2 defaults to writing `PROTOCOL_VERSION_2`.
JDK 1.1 defaults to writing `PROTOCOL_VERSION_1`.
JDK 1.1.7 and greater can read both versions.
Releases prior to JDK 1.1.7 can only read `PROTOCOL_VERSION_1`.
## 6.4 Grammar for the Stream Format
The table below contains the grammar for the stream format. Nonterminal symbols
are shown in italics. Terminal symbols in a *fixed width font*. Definitions of
nonterminals are followed by a ":". The definition is followed by one or more
alternatives, each on a separate line. The following table describes the
notation:
------------- --------------------------------------------------------------
**Notation** **Meaning**
------------- --------------------------------------------------------------
(*datatype*) This token has the data type specified, such as byte.
*token*\[n\] A predefined number of occurrences of the token, that is an
array.
*x0001* A literal value expressed in hexadecimal. The number of hex
digits reflects the size of the value.
&lt;*xxx*&gt; A value read from the stream used to indicate the length of an
array.
------------- --------------------------------------------------------------
Note that the symbol (utf) is used to designate a string written using 2-byte
length information, and (long-utf) is used to designate a string written using
8-byte length information. For details, refer to [Section 6.2, "Stream
Elements"](#stream-elements).
### 6.4.1 Rules of the Grammar
A Serialized stream is represented by any stream satisfying the *stream* rule.
```
stream:
magic version contents
contents:
content
contents content
content:
object
blockdata
object:
newObject
newClass
newArray
newString
newEnum
newClassDesc
prevObject
nullReference
exception
TC_RESET
newClass:
TC_CLASS classDesc newHandle
classDesc:
newClassDesc
nullReference
(ClassDesc)prevObject // an object required to be of type ClassDesc
superClassDesc:
classDesc
newClassDesc:
TC_CLASSDESC className serialVersionUID newHandle classDescInfo
TC_PROXYCLASSDESC newHandle proxyClassDescInfo
classDescInfo:
classDescFlags fields classAnnotation superClassDesc
className:
(utf)
serialVersionUID:
(long)
classDescFlags:
(byte) // Defined in Terminal Symbols and Constants
proxyClassDescInfo:
(int)<count> proxyInterfaceName[count] classAnnotation
superClassDesc
proxyInterfaceName:
(utf)
fields:
(short)<count> fieldDesc[count]
fieldDesc:
primitiveDesc
objectDesc
primitiveDesc:
prim_typecode fieldName
objectDesc:
obj_typecode fieldName className1
fieldName:
(utf)
className1:
(String)object // String containing the field's type,
// in field descriptor format
classAnnotation:
endBlockData
contents endBlockData // contents written by annotateClass
prim_typecode:
'B' // byte
'C' // char
'D' // double
'F' // float
'I' // integer
'J' // long
'S' // short
'Z' // boolean
obj_typecode:
'[' // array
'L' // object
newArray:
TC_ARRAY classDesc newHandle (int)<size> values[size]
newObject:
TC_OBJECT classDesc newHandle classdata[] // data for each class
classdata:
nowrclass // SC_SERIALIZABLE & classDescFlag &&
// !(SC_WRITE_METHOD & classDescFlags)
wrclass objectAnnotation // SC_SERIALIZABLE & classDescFlag &&
// SC_WRITE_METHOD & classDescFlags
externalContents // SC_EXTERNALIZABLE & classDescFlag &&
// !(SC_BLOCKDATA & classDescFlags
objectAnnotation // SC_EXTERNALIZABLE & classDescFlag&&
// SC_BLOCKDATA & classDescFlags
nowrclass:
values // fields in order of class descriptor
wrclass:
nowrclass
objectAnnotation:
endBlockData
contents endBlockData // contents written by writeObject
// or writeExternal PROTOCOL_VERSION_2.
blockdata:
blockdatashort
blockdatalong
blockdatashort:
TC_BLOCKDATA (unsigned byte)<size> (byte)[size]
blockdatalong:
TC_BLOCKDATALONG (int)<size> (byte)[size]
endBlockData:
TC_ENDBLOCKDATA
externalContent: // Only parseable by readExternal
(bytes) // primitive data
object
externalContents: // externalContent written by
externalContent // writeExternal in PROTOCOL_VERSION_1.
externalContents externalContent
newString:
TC_STRING newHandle (utf)
TC_LONGSTRING newHandle (long-utf)
newEnum:
TC_ENUM classDesc newHandle enumConstantName
enumConstantName:
(String)object
prevObject:
TC_REFERENCE (int)handle
nullReference:
TC_NULL
exception:
TC_EXCEPTION reset (Throwable)object reset
magic:
STREAM_MAGIC
version:
STREAM_VERSION
values: // The size and types are described by the
// classDesc for the current object
newHandle: // The next number in sequence is assigned
// to the object being serialized or deserialized
reset: // The set of known objects is discarded
// so the objects of the exception do not
// overlap with the previously sent objects
// or with objects that may be sent after
// the exception
```
### 6.4.2 Terminal Symbols and Constants
The following symbols in `java.io.ObjectStreamConstants` define the terminal
and constant values expected in a stream.
```
final static short STREAM_MAGIC = (short)0xaced;
final static short STREAM_VERSION = 5;
final static byte TC_NULL = (byte)0x70;
final static byte TC_REFERENCE = (byte)0x71;
final static byte TC_CLASSDESC = (byte)0x72;
final static byte TC_OBJECT = (byte)0x73;
final static byte TC_STRING = (byte)0x74;
final static byte TC_ARRAY = (byte)0x75;
final static byte TC_CLASS = (byte)0x76;
final static byte TC_BLOCKDATA = (byte)0x77;
final static byte TC_ENDBLOCKDATA = (byte)0x78;
final static byte TC_RESET = (byte)0x79;
final static byte TC_BLOCKDATALONG = (byte)0x7A;
final static byte TC_EXCEPTION = (byte)0x7B;
final static byte TC_LONGSTRING = (byte) 0x7C;
final static byte TC_PROXYCLASSDESC = (byte) 0x7D;
final static byte TC_ENUM = (byte) 0x7E;
final static int baseWireHandle = 0x7E0000;
```
The flag byte *classDescFlags* may include values of
```
final static byte SC_WRITE_METHOD = 0x01; //if SC_SERIALIZABLE
final static byte SC_BLOCK_DATA = 0x08; //if SC_EXTERNALIZABLE
final static byte SC_SERIALIZABLE = 0x02;
final static byte SC_EXTERNALIZABLE = 0x04;
final static byte SC_ENUM = 0x10;
```
The flag `SC_WRITE_METHOD` is set if the Serializable class writing the stream
had a `writeObject` method that may have written additional data to the stream.
In this case a `TC_ENDBLOCKDATA` marker is always expected to terminate the
data for that class.
The flag `SC_BLOCKDATA` is set if the `Externalizable` class is written into
the stream using `STREAM_PROTOCOL_2`. By default, this is the protocol used to
write `Externalizable` objects into the stream in JDK 1.2. JDK 1.1 writes
`STREAM_PROTOCOL_1`.
The flag `SC_SERIALIZABLE` is set if the class that wrote the stream extended
`java.io.Serializable` but not `java.io.Externalizable`, the class reading the
stream must also extend `java.io.Serializable` and the default serialization
mechanism is to be used.
The flag `SC_EXTERNALIZABLE` is set if the class that wrote the stream extended
`java.io.Externalizable`, the class reading the data must also extend
`Externalizable` and the data will be read using its `writeExternal` and
`readExternal` methods.
The flag `SC_ENUM` is set if the class that wrote the stream was an enum type.
The receiver's corresponding class must also be an enum type. Data for
constants of the enum type will be written and read as described in [Section
1.12, "Serialization of Enum
Constants"](serial-arch.html#serialization-of-enum-constants).
#### Example
Consider the case of an original class and two instances in a linked list:
```
class List implements java.io.Serializable {
int value;
List next;
public static void main(String[] args) {
try {
List list1 = new List();
List list2 = new List();
list1.value = 17;
list1.next = list2;
list2.value = 19;
list2.next = null;
ByteArrayOutputStream o = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(o);
out.writeObject(list1);
out.writeObject(list2);
out.flush();
...
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
```
The resulting stream contains:
```
00: ac ed 00 05 73 72 00 04 4c 69 73 74 69 c8 8a 15 >....sr..Listi...<
10: 40 16 ae 68 02 00 02 49 00 05 76 61 6c 75 65 4c >Z......I..valueL<
20: 00 04 6e 65 78 74 74 00 06 4c 4c 69 73 74 3b 78 >..nextt..LList;x<
30: 70 00 00 00 11 73 71 00 7e 00 00 00 00 00 13 70 >p....sq.~......p<
40: 71 00 7e 00 03 >q.~..<
```
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,38 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](protocol.html) | [NEXT](exceptions.html)'
include-after: '[CONTENTS](index.html) | [PREV](protocol.html) | [NEXT](exceptions.html)'
title: 'Java Object Serialization Specification: A - Security in Object Serialization'
---
-------------------------------------------------------------------------------
Refer to the [Secure Coding Guidelines for the Java Programming
Language](http://www.oracle.com/pls/topic/lookup?ctx=javase9&id=secure_coding_guidelines_javase)
for information about security in object serialization.
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,575 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](index.html) | [NEXT](output.html)'
include-after: '[CONTENTS](index.html) | [PREV](index.html) | [NEXT](output.html)'
title: 'Java Object Serialization Specification: 1 - System Architecture'
---
- [Overview](#overview)
- [Writing to an Object Stream](#writing-to-an-object-stream)
- [Reading from an Object Stream](#reading-from-an-object-stream)
- [Object Streams as Containers](#object-streams-as-containers)
- [Defining Serializable Fields for a
Class](#defining-serializable-fields-for-a-class)
- [Documenting Serializable Fields and Data for a
Class](#documenting-serializable-fields-and-data-for-a-class)
- [Accessing Serializable Fields of a
Class](#accessing-serializable-fields-of-a-class)
- [The ObjectOutput Interface](#the-objectoutput-interface)
- [The ObjectInput Interface](#the-objectinput-interface)
- [The Serializable Interface](#the-serializable-interface)
- [The Externalizable Interface](#the-externalizable-interface)
- [Serialization of Enum Constants](#serialization-of-enum-constants)
- [Protecting Sensitive Information](#protecting-sensitive-information)
-------------------------------------------------------------------------------
## 1.1 Overview
The ability to store and retrieve Java^TM^ objects is essential to building all
but the most transient applications. The key to storing and retrieving objects
in a serialized form is representing the state of objects sufficient to
reconstruct the object(s). Objects to be saved in the stream may support either
the `Serializable` or the `Externalizable` interface. For Java^TM^ objects, the
serialized form must be able to identify and verify the Java^TM^ class from
which the contents of the object were saved and to restore the contents to a
new instance. For serializable objects, the stream includes sufficient
information to restore the fields in the stream to a compatible version of the
class. For Externalizable objects, the class is solely responsible for the
external format of its contents.
Objects to be stored and retrieved frequently refer to other objects. Those
other objects must be stored and retrieved at the same time to maintain the
relationships between the objects. When an object is stored, all of the objects
that are reachable from that object are stored as well.
The goals for serializing Java^TM^ objects are to:
- Have a simple yet extensible mechanism.
- Maintain the Java^TM^ object type and safety properties in the serialized
form.
- Be extensible to support marshaling and unmarshaling as needed for remote
objects.
- Be extensible to support simple persistence of Java^TM^ objects.
- Require per class implementation only for customization.
- Allow the object to define its external format.
## 1.2 Writing to an Object Stream
Writing objects and primitives to a stream is a straightforward process. For
example:
```
// Serialize today's date to a file.
FileOutputStream f = new FileOutputStream("tmp");
ObjectOutput s = new ObjectOutputStream(f);
s.writeObject("Today");
s.writeObject(new Date());
s.flush();
```
First an `OutputStream`, in this case a `FileOutputStream`, is needed to
receive the bytes. Then an `ObjectOutputStream` is created that writes to the
`FileOutputStream`. Next, the string "Today" and a Date object are written to
the stream. More generally, objects are written with the `writeObject` method
and primitives are written to the stream with the methods of `DataOutput`.
The `writeObject` method (see [Section 2.3, "The writeObject
Method"](output.html#the-writeobject-method)) serializes the specified object
and traverses its references to other objects in the object graph recursively
to create a complete serialized representation of the graph. Within a stream,
the first reference to any object results in the object being serialized or
externalized and the assignment of a handle for that object. Subsequent
references to that object are encoded as the handle. Using object handles
preserves sharing and circular references that occur naturally in object
graphs. Subsequent references to an object use only the handle allowing a very
compact representation.
Special handling is required for arrays, enum constants, and objects of type
`Class`, `ObjectStreamClass`, and `String`. Other objects must implement either
the `Serializable` or the `Externalizable` interface to be saved in or restored
from a stream.
Primitive data types are written to the stream with the methods in the
`DataOutput` interface, such as `writeInt`, `writeFloat`, or `writeUTF`.
Individual bytes and arrays of bytes are written with the methods of
`OutputStream`. Except for serializable fields, primitive data is written to
the stream in block-data records, with each record prefixed by a marker and an
indication of the number of bytes in the record.
`ObjectOutputStream` can be extended to customize the information about classes
in the stream or to replace objects to be serialized. Refer to the
`annotateClass` and `replaceObject` method descriptions for details.
## 1.3 Reading from an Object Stream
Reading an object from a stream, like writing, is straightforward:
```
// Deserialize a string and date from a file.
FileInputStream in = new FileInputStream("tmp");
ObjectInputStream s = new ObjectInputStream(in);
String today = (String)s.readObject();
Date date = (Date)s.readObject();
```
First an `InputStream`, in this case a `FileInputStream`, is needed as the
source stream. Then an `ObjectInputStream` is created that reads from the
`InputStream`. Next, the string "Today" and a Date object are read from the
stream. Generally, objects are read with the `readObject` method and primitives
are read from the stream with the methods of `DataInput`.
The `readObject` method deserializes the next object in the stream and
traverses its references to other objects recursively to create the complete
graph of objects serialized.
Primitive data types are read from the stream with the methods in the
`DataInput` interface, such as `readInt`, `readFloat`, or `readUTF`. Individual
bytes and arrays of bytes are read with the methods of `InputStream`. Except
for serializable fields, primitive data is read from block-data records.
`ObjectInputStream` can be extended to utilize customized information in the
stream about classes or to replace objects that have been deserialized. Refer
to the `resolveClass` and `resolveObject` method descriptions for details.
## 1.4 Object Streams as Containers
Object Serialization produces and consumes a stream of bytes that contain one
or more primitives and objects. The objects written to the stream, in turn,
refer to other objects, which are also represented in the stream. Object
Serialization produces just one stream format that encodes and stores the
contained objects.
Each object that acts as a container implements an interface which allows
primitives and objects to be stored in or retrieved from it. These interfaces
are the `ObjectOutput` and `ObjectInput` interfaces which:
- Provide a stream to write to and to read from
- Handle requests to write primitive types and objects to the stream
- Handle requests to read primitive types and objects from the stream
Each object which is to be stored in a stream must explicitly allow itself to
be stored and must implement the protocols needed to save and restore its
state. Object Serialization defines two such protocols. The protocols allow the
container to ask the object to write and read its state.
To be stored in an Object Stream, each object must implement either the
`Serializable` or the `Externalizable` interface:
- For a `Serializable` class, Object Serialization can automatically save and
restore fields of each class of an object and automatically handle classes
that evolve by adding fields or supertypes. A serializable class can
declare which of its fields are saved or restored, and write and read
optional values and objects.
- For an `Externalizable` class, Object Serialization delegates to the class
complete control over its external format and how the state of the
supertype(s) is saved and restored.
## 1.5 Defining Serializable Fields for a Class
The serializable fields of a class can be defined two different ways. Default
serializable fields of a class are defined to be the non-transient and
non-static fields. This default computation can be overridden by declaring a
special field in the `Serializable` class, `serialPersistentFields`. This field
must be initialized with an array of `ObjectStreamField` objects that list the
names and types of the serializable fields. The modifiers for the field are
required to be private, static, and final. If the field's value is null or is
otherwise not an instance of `ObjectStreamField[]`, or if the field does not
have the required modifiers, then the behavior is as if the field were not
declared at all.
For example, the following declaration duplicates the default behavior.
```
class List implements Serializable {
List next;
private static final ObjectStreamField[] serialPersistentFields
= {new ObjectStreamField("next", List.class)};
}
```
By using `serialPersistentFields` to define the Serializable fields for a
class, there no longer is a limitation that a serializable field must be a
field within the current definition of the `Serializable` class. The
`writeObject` and `readObject` methods of the `Serializable` class can map the
current implementation of the class to the serializable fields of the class
using the interface that is described in [Section 1.7, "Accessing Serializable
Fields of a Class"](#accessing-serializable-fields-of-a-class). Therefore, the
fields for a `Serializable` class can change in a later release, as long as it
maintains the mapping back to its Serializable fields that must remain
compatible across release boundaries.
**Note:** There is, however, a limitation to the use of this mechanism to
specify serializable fields for inner classes. Inner classes can only contain
final static fields that are initialized to constants or expressions built up
from constants. Consequently, it is not possible to set
`serialPersistentFields` for an inner class (though it is possible to set it
for static member classes). For other restrictions pertaining to serialization
of inner class instances, see section [Section 1.10, "The Serializable
Interface"](#the-serializable-interface).
## 1.6 Documenting Serializable Fields and Data for a Class
It is important to document the serializable state of a class to enable
interoperability with alternative implementations of a Serializable class and
to document class evolution. Documenting a serializable field gives one a final
opportunity to review whether or not the field should be serializable. The
serialization javadoc tags, `@serial`, `@serialField`, and `@serialData`,
provide a way to document the serialized form for a Serializable class within
the source code.
- The `@serial` tag should be placed in the javadoc comment for a default
serializable field. The syntax is as follows: `@serial` *field-description*
The optional *field-description* describes the meaning of the field and its
acceptable values. The *field-description* can span multiple lines. When a
field is added after the initial release, a *@since* tag indicates the
version the field was added. The *field-description* for `@serial` provides
serialization-specific documentation and is appended to the javadoc comment
for the field within the serialized form documentation.
- The `@serialField` tag is used to document an `ObjectStreamField` component
of a `serialPersistentFields` array. One of these tags should be used for
each `ObjectStreamField` component. The syntax is as follows:
`@serialField` *field-name field-type field-description*
- The `@serialData` tag describes the sequences and types of data written or
read. The tag describes the sequence and type of optional data written by
`writeObject` or all data written by the `Externalizable.writeExternal`
method. The syntax is as follows: `@serialData` *data-description*
The javadoc application recognizes the serialization javadoc tags and generates
a specification for each Serializable and Externalizable class. See [Section
C.1, "Example Alternate Implementation of
java.io.File"](examples.html#c.1-example-alternate-implementation-of-java.io.file)
for an example that uses these tags.
When a class is declared Serializable, the serializable state of the object is
defined by serializable fields (by name and type) plus optional data. Optional
data can only be written explicitly by the `writeObject` method of a
`Serializable` class. Optional data can be read by the `Serializable` class'
`readObject` method or serialization will skip unread optional data.
When a class is declared Externalizable, the data that is written to the stream
by the class itself defines the serialized state. The class must specify the
order, types, and meaning of each datum that is written to the stream. The
class must handle its own evolution, so that it can continue to read data
written by and write data that can be read by previous versions. The class must
coordinate with the superclass when saving and restoring data. The location of
the superclasses data in the stream must be specified.
The designer of a Serializable class must ensure that the information saved for
the class is appropriate for persistence and follows the
serialization-specified rules for interoperability and evolution. Class
evolution is explained in greater detail in [Chapter
5](version.html#versioning-of-serializable-objects), "Versioning of
Serializable Objects".
## 1.7 Accessing Serializable Fields of a Class
Serialization provides two mechanisms for accessing the serializable fields in
a stream:
- The default mechanism requires no customization
- The Serializable Fields API allows a class to explicitly access/set the
serializable fields by name and type
The default mechanism is used automatically when reading or writing objects
that implement the `Serializable` interface and do no further customization.
The serializable fields are mapped to the corresponding fields of the class and
values are either written to the stream from those fields or are read in and
assigned respectively. If the class provides `writeObject` and `readObject`
methods, the default mechanism can be invoked by calling `defaultWriteObject`
and `defaultReadObject`. When the `writeObject` and `readObject` methods are
implemented, the class has an opportunity to modify the serializable field
values before they are written or after they are read.
When the default mechanism cannot be used, the serializable class can use the
`putFields` method of `ObjectOutputStream` to put the values for the
serializable fields into the stream. The `writeFields` method of
`ObjectOutputStream` puts the values in the correct order, then writes them to
the stream using the existing protocol for serialization. Correspondingly, the
`readFields` method of `ObjectInputStream` reads the values from the stream and
makes them available to the class by name in any order. See [Section 2.2, "The
ObjectOutputStream.PutField
Class"](output.html#the-objectoutputstream.putfield-class) and [Section 3.2,
"The ObjectInputStream.GetField
Class"](input.html#the-objectinputstream.getfield-class) for a detailed
description of the Serializable Fields API.
## 1.8 The ObjectOutput Interface
The `ObjectOutput` interface provides an abstract, stream-based interface to
object storage. It extends the DataOutput interface so those methods can be
used for writing primitive data types. Objects that implement this interface
can be used to store primitives and objects.
```
package java.io;
public interface ObjectOutput extends DataOutput
{
public void writeObject(Object obj) throws IOException;
public void write(int b) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
public void flush() throws IOException;
public void close() throws IOException;
}
```
`The` `writeObject` method is used to write an object. The exceptions thrown
reflect errors while accessing the object or its fields, or exceptions that
occur in writing to storage. If any exception is thrown, the underlying storage
may be corrupted. If this occurs, refer to the object that is implementing this
interface for more information.
## 1.9 The ObjectInput Interface
The `ObjectInput` interface provides an abstract stream based interface to
object retrieval. It extends the `DataInput` interface so those methods for
reading primitive data types are accessible in this interface.
```
package java.io;
public interface ObjectInput extends DataInput
{
public Object readObject()
throws ClassNotFoundException, IOException;
public int read() throws IOException;
public int read(byte b[]) throws IOException;
public int read(byte b[], int off, int len) throws IOException;
public long skip(long n) throws IOException;
public int available() throws IOException;
public void close() throws IOException;
}
```
The `readObject` method is used to read and return an object. The exceptions
thrown reflect errors while accessing the objects or its fields or exceptions
that occur in reading from the storage. If any exception is thrown, the
underlying storage may be corrupted. If this occurs, refer to the object
implementing this interface for additional information.
## 1.10 The Serializable Interface
Object Serialization produces a stream with information about the Java^TM^
classes for the objects which are being saved. For serializable objects,
sufficient information is kept to restore those objects even if a different
(but compatible) version of the implementation of the class is present. The
`Serializable` interface is defined to identify classes which implement the
serializable protocol:
```
package java.io;
public interface Serializable {};
```
A Serializable class must do the following:
- Implement the `java.io.Serializable` interface
- Identify the fields that should be serializable
(Use the `serialPersistentFields` member to explicitly declare them
serializable or use the transient keyword to denote nonserializable
fields.)
- Have access to the no-arg constructor of its first nonserializable
superclass
The class can optionally define the following methods:
- A `writeObject` method to control what information is saved or to append
additional information to the stream
- A `readObject` method either to read the information written by the
corresponding `writeObject` method or to update the state of the object
after it has been restored
- A `writeReplace` method to allow a class to nominate a replacement object
to be written to the stream
(See [Section 2.5, "The writeReplace
Method"](output.html#the-writereplace-method) for additional information.)
- A `readResolve` method to allow a class to designate a replacement object
for the object just read from the stream
(See [Section 3.7, "The readResolve
Method](input.html#the-readresolve-method) for additional information.)
`ObjectOutputStream` and `ObjectInputStream` allow the serializable classes on
which they operate to evolve (allow changes to the classes that are compatible
with the earlier versions of the classes). See [Section 5.5, "Compatible Java
Type Evolution"](version.html#compatible-java-type-evolution) for information
about the mechanism which is used to allow compatible changes.
**Note:** Serialization of inner classes (i.e., nested classes that are not
static member classes), including local and anonymous classes, is strongly
discouraged for several reasons. Because inner classes declared in non-static
contexts contain implicit non-transient references to enclosing class
instances, serializing such an inner class instance will result in
serialization of its associated outer class instance as well. Synthetic fields
generated by `javac` (or other Java^TM^ compilers) to implement inner classes
are implementation dependent and may vary between compilers; differences in
such fields can disrupt compatibility as well as result in conflicting default
`serialVersionUID` values. The names assigned to local and anonymous inner
classes are also implementation dependent and may differ between compilers.
Since inner classes cannot declare static members other than compile-time
constant fields, they cannot use the `serialPersistentFields` mechanism to
designate serializable fields. Finally, because inner classes associated with
outer instances do not have zero-argument constructors (constructors of such
inner classes implicitly accept the enclosing instance as a prepended
parameter), they cannot implement `Externalizable`. None of the issues listed
above, however, apply to static member classes.
## 1.11 The Externalizable Interface
For Externalizable objects, only the identity of the class of the object is
saved by the container; the class must save and restore the contents. The
`Externalizable` interface is defined as follows:
```
package java.io;
public interface Externalizable extends Serializable
{
public void writeExternal(ObjectOutput out)
throws IOException;
public void readExternal(ObjectInput in)
throws IOException, java.lang.ClassNotFoundException;
}
```
The class of an Externalizable object must do the following:
- Implement the `java.io.Externalizable` interface
- Implement a `writeExternal` method to save the state of the object
(It must explicitly coordinate with its supertype to save its state.)
- Implement a `readExternal` method to read the data written by the
`writeExternal` method from the stream and restore the state of the object
(It must explicitly coordinate with the supertype to save its state.)
- Have the `writeExternal` and `readExternal` methods be solely responsible
for the format, if an externally defined format is written
**Note:** The `writeExternal` and `readExternal` methods are public and
raise the risk that a client may be able to write or read information in
the object other than by using its methods and fields. These methods must
be used only when the information held by the object is not sensitive or
when exposing it does not present a security risk.
- Have a public no-arg constructor
**Note:** Inner classes associated with enclosing instances cannot have
no-arg constructors, since constructors of such classes implicitly accept
the enclosing instance as a prepended parameter. Consequently the
`Externalizable` interface mechanism cannot be used for inner classes and
they should implement the `Serializable` interface, if they must be
serialized. Several limitations exist for serializable inner classes as
well, however; see [Section 1.10, "The Serializable
Interface"](#the-serializable-interface), for a full enumeration.
An Externalizable class can optionally define the following methods:
- A `writeReplace` method to allow a class to nominate a replacement object
to be written to the stream
(See [Section 2.5, "The writeReplace
Method"](output.html#the-writereplace-method) for additional information.)
- A `readResolve` method to allow a class to designate a replacement object
for the object just read from the stream
(See [Section 3.7, "The readResolve
Method"](input.html#the-readresolve-method) for additional information.)
## 1.12 Serialization of Enum Constants
Enum constants are serialized differently than ordinary serializable or
externalizable objects. The serialized form of an enum constant consists solely
of its name; field values of the constant are not present in the form. To
serialize an enum constant, `ObjectOutputStream` writes the value returned by
the enum constant's `name` method. To deserialize an enum constant,
`ObjectInputStream` reads the constant name from the stream; the deserialized
constant is then obtained by calling the `java.lang.Enum.valueOf` method,
passing the constant's enum type along with the received constant name as
arguments. Like other serializable or externalizable objects, enum constants
can function as the targets of back references appearing subsequently in the
serialization stream.
The process by which enum constants are serialized cannot be customized: any
class-specific `writeObject`, `readObject`, `readObjectNoData`, `writeReplace`,
and `readResolve` methods defined by enum types are ignored during
serialization and deserialization. Similarly, any `serialPersistentFields` or
`serialVersionUID` field declarations are also ignored--all enum types have a
fixed `serialVersionUID` of `0L`. Documenting serializable fields and data for
enum types is unnecessary, since there is no variation in the type of data
sent.
## 1.13 Protecting Sensitive Information
When developing a class that provides controlled access to resources, care must
be taken to protect sensitive information and functions. During
deserialization, the private state of the object is restored. For example, a
file descriptor contains a handle that provides access to an operating system
resource. Being able to forge a file descriptor would allow some forms of
illegal access, since restoring state is done from a stream. Therefore, the
serializing runtime must take the conservative approach and not trust the
stream to contain only valid representations of objects. To avoid compromising
a class, the sensitive state of an object must not be restored from the stream,
or it must be reverified by the class. Several techniques are available to
protect sensitive data in classes.
The easiest technique is to mark fields that contain sensitive data as *private
transient*. Transient fields are not persistent and will not be saved by any
persistence mechanism. Marking the field will prevent the state from appearing
in the stream and from being restored during deserialization. Since writing and
reading (of private fields) cannot be superseded outside of the class, the
transient fields of the class are safe.
Particularly sensitive classes should not be serialized at all. To accomplish
this, the object should not implement either the `Serializable` or the
`Externalizable` interface.
Some classes may find it beneficial to allow writing and reading but
specifically handle and revalidate the state as it is deserialized. The class
should implement `writeObject` and `readObject` methods to save and restore
only the appropriate state. If access should be denied, throwing a
`NotSerializableException` will prevent further access.
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -1,304 +0,0 @@
---
# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# 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-before: '[CONTENTS](index.html) | [PREV](class.html) | [NEXT](protocol.html)'
include-after: '[CONTENTS](index.html) | [PREV](class.html) | [NEXT](protocol.html)'
title: 'Java Object Serialization Specification: 5 - Versioning of Serializable Objects'
---
- [Overview](#overview)
- [Goals](#goals)
- [Assumptions](#assumptions)
- [Who's Responsible for Versioning of
Streams](#whos-responsible-for-versioning-of-streams)
- [Compatible Java Type Evolution](#compatible-java-type-evolution)
- [Type Changes Affecting
Serialization](#type-changes-affecting-serialization)
-------------------------------------------------------------------------------
## 5.1 Overview
When Java objects use serialization to save state in files, or as blobs in
databases, the potential arises that the version of a class reading the data is
different than the version that wrote the data.
Versioning raises some fundamental questions about the identity of a class,
including what constitutes a compatible change. A ***compatible change*** is a
change that does not affect the contract between the class and its callers.
This section describes the goals, assumptions, and a solution that attempts to
address this problem by restricting the kinds of changes allowed and by
carefully choosing the mechanisms.
The proposed solution provides a mechanism for "automatic" handling of classes
that evolve by adding fields and adding classes. Serialization will handle
versioning without class-specific methods to be implemented for each version.
The stream format can be traversed without invoking class-specific methods.
## 5.2 Goals
The goals are to:
- Support bidirectional communication between different versions of a class
operating in different virtual machines by:
- Defining a mechanism that allows Java classes to read streams written
by older versions of the same class.
- Defining a mechanism that allows Java classes to write streams intended
to be read by older versions of the same class.
- Provide default serialization for persistence and for RMI.
- Perform well and produce compact streams in simple cases, so that RMI can
use serialization.
- Be able to identify and load classes that match the exact class used to
write the stream.
- Keep the overhead low for nonversioned classes.
- Use a stream format that allows the traversal of the stream without having
to invoke methods specific to the objects saved in the stream.
## 5.3 Assumptions
The assumptions are that:
- Versioning will only apply to serializable classes since it must control
the stream format to achieve it goals. Externalizable classes will be
responsible for their own versioning which is tied to the external format.
- All data and objects must be read from, or skipped in, the stream in the
same order as they were written.
- Classes evolve individually as well as in concert with supertypes and
subtypes.
- Classes are identified by name. Two classes with the same name may be
different versions or completely different classes that can be
distinguished only by comparing their interfaces or by comparing hashes of
the interfaces.
- Default serialization will not perform any type conversions.
- The stream format only needs to support a linear sequence of type changes,
not arbitrary branching of a type.
## 5.4 Who's Responsible for Versioning of Streams
In the evolution of classes, it is the responsibility of the evolved (later
version) class to maintain the contract established by the nonevolved class.
This takes two forms. First, the evolved class must not break the existing
assumptions about the interface provided by the original version, so that the
evolved class can be used in place of the original. Secondly, when
communicating with the original (or previous) versions, the evolved class must
provide sufficient and equivalent information to allow the earlier version to
continue to satisfy the nonevolved contract.
> ![*Private serialization protocol and contract with supertype relationships
between evolved and nonevolved classes and their
instances*](images/version.gif)
For the purposes of the discussion here, each class implements and extends the
interface or contract defined by its supertype. New versions of a class, for
example `foo'`, must continue to satisfy the contract for `foo` and may extend
the interface or modify its implementation.
Communication between objects via serialization is not part of the contract
defined by these interfaces. Serialization is a private protocol between the
implementations. It is the responsibility of the implementations to communicate
sufficiently to allow each implementation to continue to satisfy the contract
expected by its clients.
## 5.5 Compatible Java Type Evolution
The Java Language Specification discusses binary compatibility of Java classes
as those classes evolve. Most of the flexibility of binary compatibility comes
from the use of late binding of symbolic references for the names of classes,
interfaces, fields, methods, and so on.
The following are the principle aspects of the design for versioning of
serialized object streams.
- The default serialization mechanism will use a symbolic model for binding
the fields in the stream to the fields in the corresponding class in the
virtual machine.
- Each class referenced in the stream will uniquely identify itself, its
supertype, and the types and names of each serializable field written to
the stream. The fields are ordered with the primitive types first sorted by
field name, followed by the object fields sorted by field name.
- Two types of data may occur in the stream for each class: required data
(corresponding directly to the serializable fields of the object); and
optional data (consisting of an arbitrary sequence of primitives and
objects). The stream format defines how the required and optional data
occur in the stream so that the whole class, the required, or the optional
parts can be skipped if necessary.
- The required data consists of the fields of the object in the order
defined by the class descriptor.
- The optional data is written to the stream and does not correspond
directly to fields of the class. The class itself is responsible for
the length, types, and versioning of this optional information.
- If defined for a class, the `writeObject`/`readObject` methods supersede
the default mechanism to write/read the state of the class. These methods
write and read the optional data for a class. The required data is written
by calling `defaultWriteObject` and read by calling `defaultReadObject`.
- The stream format of each class is identified by the use of a Stream Unique
Identifier (SUID). By default, this is the hash of the class. All later
versions of the class must declare the Stream Unique Identifier (SUID) that
they are compatible with. This guards against classes with the same name
that might inadvertently be identified as being versions of a single class.
- Subtypes of `ObjectOutputStream` and `ObjectInputStream` may include their
own information identifying the class using the `annotateClass` method; for
example, `MarshalOutputStream` embeds the URL of the class.
## 5.6 Type Changes Affecting Serialization
With these concepts, we can now describe how the design will cope with the
different cases of an evolving class. The cases are described in terms of a
stream written by some version of a class. When the stream is read back by the
same version of the class, there is no loss of information or functionality.
The stream is the only source of information about the original class. Its
class descriptions, while a subset of the original class description, are
sufficient to match up the data in the stream with the version of the class
being reconstituted.
The descriptions are from the perspective of the stream being read in order to
reconstitute either an earlier or later version of the class. In the parlance
of RPC systems, this is a "receiver makes right" system. The writer writes its
data in the most suitable form and the receiver must interpret that information
to extract the parts it needs and to fill in the parts that are not available.
### 5.6.1 Incompatible Changes
Incompatible changes to classes are those changes for which the guarantee of
interoperability cannot be maintained. The incompatible changes that may occur
while evolving a class are:
- Deleting fields - If a field is deleted in a class, the stream written will
not contain its value. When the stream is read by an earlier class, the
value of the field will be set to the default value because no value is
available in the stream. However, this default value may adversely impair
the ability of the earlier version to fulfill its contract.
- Moving classes up or down the hierarchy - This cannot be allowed since the
data in the stream appears in the wrong sequence.
- Changing a nonstatic field to static or a nontransient field to transient -
When relying on default serialization, this change is equivalent to
deleting a field from the class. This version of the class will not write
that data to the stream, so it will not be available to be read by earlier
versions of the class. As when deleting a field, the field of the earlier
version will be initialized to the default value, which can cause the class
to fail in unexpected ways.
- Changing the declared type of a primitive field - Each version of the class
writes the data with its declared type. Earlier versions of the class
attempting to read the field will fail because the type of the data in the
stream does not match the type of the field.
- Changing the `writeObject` or `readObject` method so that it no longer
writes or reads the default field data or changing it so that it attempts
to write it or read it when the previous version did not. The default field
data must consistently either appear or not appear in the stream.
- Changing a class from `Serializable` to `Externalizable` or vice versa is
an incompatible change since the stream will contain data that is
incompatible with the implementation of the available class.
- Changing a class from a non-enum type to an enum type or vice versa since
the stream will contain data that is incompatible with the implementation
of the available class.
- Removing either `Serializable` or `Externalizable` is an incompatible
change since when written it will no longer supply the fields needed by
older versions of the class.
- Adding the `writeReplace` or `readResolve` method to a class is
incompatible if the behavior would produce an object that is incompatible
with any older version of the class.
### 5.6.2 Compatible Changes
The compatible changes to a class are handled as follows:
- Adding fields - When the class being reconstituted has a field that does
not occur in the stream, that field in the object will be initialized to
the default value for its type. If class-specific initialization is needed,
the class may provide a readObject method that can initialize the field to
nondefault values.
- Adding classes - The stream will contain the type hierarchy of each object
in the stream. Comparing this hierarchy in the stream with the current
class can detect additional classes. Since there is no information in the
stream from which to initialize the object, the class's fields will be
initialized to the default values.
- Removing classes - Comparing the class hierarchy in the stream with that of
the current class can detect that a class has been deleted. In this case,
the fields and objects corresponding to that class are read from the
stream. Primitive fields are discarded, but the objects referenced by the
deleted class are created, since they may be referred to later in the
stream. They will be garbage-collected when the stream is garbage-collected
or reset.
- Adding `writeObject`/`readObject` methods - If the version reading the
stream has these methods then `readObject` is expected, as usual, to read
the required data written to the stream by the default serialization. It
should call `defaultReadObject` first before reading any optional data. The
`writeObject` method is expected as usual to call `defaultWriteObject` to
write the required data and then may write optional data.
- Removing `writeObject`/`readObject` methods - If the class reading the
stream does not have these methods, the required data will be read by
default serialization, and the optional data will be discarded.
- Adding `java.io.Serializable` - This is equivalent to adding types. There
will be no values in the stream for this class so its fields will be
initialized to default values. The support for subclassing nonserializable
classes requires that the class's supertype have a no-arg constructor and
the class itself will be initialized to default values. If the no-arg
constructor is not available, the `InvalidClassException` is thrown.
- Changing the access to a field - The access modifiers public, package,
protected, and private have no effect on the ability of serialization to
assign values to the fields.
- Changing a field from static to nonstatic or transient to nontransient -
When relying on default serialization to compute the serializable fields,
this change is equivalent to adding a field to the class. The new field
will be written to the stream but earlier classes will ignore the value
since serialization will not assign values to static or transient fields.
-------------------------------------------------------------------------------
*[Copyright](../../../legal/SMICopyright.html) &copy; 2005, 2017, Oracle
and/or its affiliates. All rights reserved.*

View File

@ -376,7 +376,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
static JNF_MEMBER_CACHE(jm_getMaxPage, sjc_CPrinterJob, "getMaxPageAttrib", "()I");
static JNF_MEMBER_CACHE(jm_getSelectAttrib, sjc_CPrinterJob, "getSelectAttrib", "()I");
static JNF_MEMBER_CACHE(jm_getNumberOfPages, jc_Pageable, "getNumberOfPages", "()I");
static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormat", "(I)Ljava/awt/print/PageFormat;");
static JNF_MEMBER_CACHE(jm_getPageFormat, sjc_CPrinterJob, "getPageFormatFromAttributes", "()Ljava/awt/print/PageFormat;");
NSMutableDictionary* printingDictionary = [dst dictionary];
@ -412,7 +412,7 @@ static void javaPrinterJobToNSPrintInfo(JNIEnv* env, jobject srcPrinterJob, jobj
[printingDictionary setObject:[NSNumber numberWithInteger:fromPage] forKey:NSPrintFirstPage];
[printingDictionary setObject:[NSNumber numberWithInteger:toPage] forKey:NSPrintLastPage];
jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat, (jint)0);
jobject page = JNFCallObjectMethod(env, srcPrinterJob, jm_getPageFormat);
if (page != NULL) {
javaPageFormatToNSPrintInfo(env, NULL, page, dst);
}

View File

@ -812,7 +812,7 @@ public class JEditorPane extends JTextComponent {
/**
* Scrolls the view to the given reference location
* (that is, the value returned by the <code>UL.getRef</code>
* (that is, the value returned by the <code>URL.getRef</code>
* method for the URL being displayed). By default, this
* method only knows how to locate a reference in an
* HTMLDocument. The implementation calls the

View File

@ -1900,7 +1900,7 @@ public class JTabbedPane extends JComponent
* Returns the accessible name of this object, or {@code null} if
* there is no accessible name.
*
* @return the accessible name of this object, nor {@code null}.
* @return the accessible name of this object, or {@code null}.
* @since 1.6
*/
public String getAccessibleName() {

View File

@ -27,6 +27,24 @@
* Defines the AWT and Swing user interface toolkits, plus APIs for
* accessibility, audio, imaging, printing, and JavaBeans.
*
* @uses java.awt.im.spi.InputMethodDescriptor
* @uses javax.accessibility.AccessibilityProvider
* @uses javax.imageio.spi.ImageInputStreamSpi
* @uses javax.imageio.spi.ImageOutputStreamSpi
* @uses javax.imageio.spi.ImageReaderSpi
* @uses javax.imageio.spi.ImageTranscoderSpi
* @uses javax.imageio.spi.ImageWriterSpi
* @uses javax.print.PrintServiceLookup
* @uses javax.print.StreamPrintServiceFactory
* @uses javax.sound.midi.spi.MidiDeviceProvider
* @uses javax.sound.midi.spi.MidiFileReader
* @uses javax.sound.midi.spi.MidiFileWriter
* @uses javax.sound.midi.spi.SoundbankReader
* @uses javax.sound.sampled.spi.AudioFileReader
* @uses javax.sound.sampled.spi.AudioFileWriter
* @uses javax.sound.sampled.spi.FormatConversionProvider
* @uses javax.sound.sampled.spi.MixerProvider
*
* @moduleGraph
* @since 9
*/

View File

@ -886,6 +886,14 @@ public abstract class RasterPrinterJob extends PrinterJob {
}
}
protected PageFormat getPageFormatFromAttributes() {
if (attributes == null || attributes.isEmpty()) {
return null;
}
return attributeToPageFormat(getPrintService(), this.attributes);
}
/**
* Presents the user a dialog for changing properties of the
* print job interactively.

View File

@ -1,776 +0,0 @@
<!--
Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation.
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.
-->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en-US" xmlns="http://www.w3.org/1999/xhtml" xml:lang=
"en-US">
<head>
<title>Java AWT Native Interface Specification and Guide</title>
</head>
<body>
<h2>The Java AWT Native Interface Specification and Guide</h2>
<h3>Introduction</h3>
<p>The Java AWT Native Interface (JAWT) comprises a small set of native
(eg C language-based) APIs that provide a standard supported way
for interaction between Java API windows and surfaces, and
platform native API windows and surfaces.
Non-Java libraries may then render to a Java owned window.
<p>
Note: in this document the terms "Java AWT Native Interface",
"AWT Native Interface" and "JAWT" are interchangeable and
refer to this same specification.
<p>
The fundamental obstacle to native rendering without JAWT is that
is that the rendering code cannot identify where to draw.
The native code needs access to information about a Java
drawing surface (such as a handle to the underlying native ID of a
<tt>Canvas</tt>), but cannot get it.</p>
Without that information (ie without JAWT) an application could
use native rendering only by creating its own top-level window
not shared at all with Java. This is unacceptable for most uses.
Except for usage via JAWT, this is considered to be entirely
internal to the Java platform implementation: private, unsupported
and undocumented.
<p>
JAWT should be supported in all headful implementations
where technically possible although this is not enforced by the JCK.
There is a platform-specific and a platform
independent portion to the API, to account for the differing
data structures and requirements of each platform.
This document specifies the platform independent portions and
also documents the platform dependent portions for the Oracle JDK
supported desktop operating environments.
For AWT the term platform is less tied to the underlying operating
system than it is to the desktop windowing environment.
<p>
Reasons for using the AWT Native Interface include
<ul>
<li>Use of a 3rd party native library not available in Java
<li>A temporary porting aid before converting legacy code to Java
<li>Rendering performance available only to native hardware accelerated APIs
<li>Interoperation with another toolkit
</ul>
<p>
Drawbacks include
<ul>
<li>A more complex application implementation, eg for painting
<li>Potential for application instability if the native library does
not interoperate properly with AWT.
<li>Increased application delivery complexity - per platform binaries
</ul>
The header file <a href="#jawt.h"> "jawt.h"</a>
in the Appendix fully specifies the APIs provided by JAWT.
<p>
An example illustrating how easy it is to use the AWT Native Interface
is presented and discussed later in this document.</p>
<p><b>JAWT usage depends on JNI</b></p>
<p>The definition of Java Standard Edition includes JNI, the Java
Native Interface. Many Java developers will never need to use it,
but the interface is the only standard supported way for a Java
language program to interact directly with
application code that has been compiled to the native machine
instructions for the host processor architecture.
JNI is used where ever there is a need for mixed languages.
These are by no means limited to cases like AWT. For example, you
could use JNI to integrate with native code that communicates with
a peripheral device, such as a scanner, connected to a system via a
USB port.</p>
<p>So JNI is general enough to be used to access almost any
sort of native library.
The rest of this document assumes a familiarity with how
to use JNI.
<p><b>How to use JAWT </b></p>
<p>In this section we describe the most common usage of the AWT
Native Interface &mdash; overriding the <tt>paint</tt> method to
direct drawing operations to a native rendering library which then
queries the Java VM to determine the information it needs in order
to render. Note, however, that any native code may use the AWT
Native Interface to learn about a target drawing surface, not just
code in a <tt>paint</tt> method.</p>
<p>The first step in hooking up a native rendering library to a
Java <tt>Canvas</tt> is to define a new class that extends
<tt>Canvas</tt> and overrides the <tt>paint</tt> method. The Java
system routes all drawing operations for a <tt>Canvas</tt> object
through the <tt>paint</tt> method, as it does for all other GUI
objects. Canvas is a good candidate for the rendering surface as
it does not have any content as a Button would.</p>
<p>The new <tt>paint</tt> method, to be implemented in the native
rendering library, must be declared as <tt>public native void</tt>
, and the native library itself is loaded at runtime by including a
call to <tt>System.loadLibrary( &quot;myRenderingLib&quot;)</tt>in
the <tt>static</tt> block of the class. The <tt>myRenderingLib</tt>
name is used for the native shared library; for Linux or the Solaris
operating environment, the actual name for the library file on disk
is <tt>libmyRenderingLib.so</tt> .</p>
<p>Here is a simple example of such a class:</p>
<pre>
import java.awt.*;
import java.awt.event.*;
public class MyCanvas extends Canvas {
static {
System.loadLibrary("myRenderingLib");
}
public native void paint(Graphics g);
public static void main(String[] args) {
Frame f = new Frame();
f.setBounds(0, 0, 500, 110);
f.add(new MyCanvas());
f.addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent ev) {
System.exit(0);
}
} );
f.show();
}
}
<br />
</pre>
<p>Note that this class has a <tt>main</tt> method that can be used
to run this code as an application for testing purposes.</p>
<p>The next step is to run the <tt>javah</tt> tool on the
<tt>MyCanvas</tt> class file above to generate a C/C++ header file
that describes the interface to the native <tt>paint</tt> method
that Java expects to be used. <tt>javah</tt> is a standard tool
included with the JDK. NB: <tt>javac -h outputdir</tt> may also be used.</p>
<p>The final step &#173; and the most interesting one &#173; is to
write the native rendering method, with an interface that conforms
to the header file that <tt>javah</tt> generated, and build it as a
standard shared library (called <tt>myRenderingLib</tt> in the
above example) by linking it, against the appropriate JDK provided
$JDK_HOME/lib/$JAWT_LIB library for the target platform.
Where JAWT_LIB has the base name "jawt" and follows platform
shared object naming rules. i.e.:
<ul>
<li>Windows: jawt.dll
<li>MacOS: libjawt.dylib
<li>Linux: libjawt.so
<li>Solaris: libjawt.so
</ul>
This code will call back to the Java virtual machine to
get the drawing surface information it needs to access the
<tt>MyCanvas</tt> peer. Once this information is available, the
code can draw directly to <tt>MyCanvas</tt> using standard drawing
routines supplied by the underlying operating system.</p>
<p>Here is sample source code for a native <tt>paint</tt> method
designed for use in a X11-based drawing environment (Linux
or Solaris) and a Java VM where the AWT Native Interface is present:</p>
<pre>
#include "MyCanvas.h"
#include "jawt_md.h"
/*
* Class: MyCanvas
* Method: paint
* Signature: (Ljava/awt/Graphics;)V
*/
JNIEXPORT void JNICALL Java_MyCanvas_paint
(JNIEnv* env, jobject canvas, jobject graphics)
{
JAWT awt;
JAWT_DrawingSurface* ds;
JAWT_DrawingSurfaceInfo* dsi;
JAWT_X11DrawingSurfaceInfo* dsi_x11;
jboolean result;
jint lock;
GC gc;
short i;
char *testString = "^^^ rendered from native code ^^^";
/* Get the AWT */
awt.version = JAWT_VERSION_9;
if (JAWT_GetAWT(env, &amp;awt) == JNI_FALSE) {
printf("AWT Not found\n");
return;
}
/* Get the drawing surface */
ds = awt.GetDrawingSurface(env, canvas);
if (ds == NULL) {
printf("NULL drawing surface\n");
return;
}
/* Lock the drawing surface */
lock = ds-&gt;Lock(ds);
if((lock &amp; JAWT_LOCK_ERROR) != 0) {
printf("Error locking surface\n");
awt.FreeDrawingSurface(ds);
return;
}
/* Get the drawing surface info */
dsi = ds-&gt;GetDrawingSurfaceInfo(ds);
if (dsi == NULL) {
printf("Error getting surface info\n");
ds-&gt;Unlock(ds);
awt.FreeDrawingSurface(ds);
return;
}
/* Get the platform-specific drawing info */
dsi_x11 = (JAWT_X11DrawingSurfaceInfo*)dsi-&gt;platformInfo;
/* Now paint */
gc = XCreateGC(dsi_x11-&gt;display, dsi_x11-&gt;drawable, 0, 0);
XSetBackground(dsi_x11-&gt;display, gc, 0);
for (i=0; i&lt;36;i++)
{
XSetForeground(dsi_x11-&gt;display, gc, 10*i);
XFillRectangle(dsi_x11-&gt;display, dsi_x11-&gt;drawable, gc,
10*i, 5, 90, 90);
}
XSetForeground(dsi_x11-&gt;display, gc, 155);
XDrawImageString(dsi_x11-&gt;display, dsi_x11-&gt;drawable, gc,
100, 110, testString, strlen(testString));
XFreeGC(dsi_x11-&gt;display, gc);
/* Free the drawing surface info */
ds-&gt;FreeDrawingSurfaceInfo(dsi);
/* Unlock the drawing surface */
ds-&gt;Unlock(ds);
/* Free the drawing surface */
awt.FreeDrawingSurface(ds);
}
</pre>
<p>The key data structure here is <tt>JAWT</tt> , which is defined
in <tt>jawt.h</tt> (included by <tt>jawt_md.h)</tt> ; it provides
access to all the information the native code needs to get the job
done. The first part of the native method is boilerplate: it
populates the <tt>JAWT</tt> structure, gets a
<tt>JAWT_DrawingSurface</tt> structure, locks the surface (only one
drawing engine at a time, please!), then gets a
<tt>JAWT_DrawingSurfaceInfo</tt> structure that contains a pointer
(in the <tt>platformInfo</tt> field) to the necessary
platform-specific drawing information. It also includes the
bounding rectangle of the drawing surface and the current clipping
region.</p>
<p>The structure of the information pointed to by
<tt>platformInfo</tt> is defined in a machine-dependent header file
called <tt>jawt_md.h</tt>. For X11 drawing, it includes
information about the X11 display and X11 drawable associated with
<tt>MyCanvas</tt>. After the drawing operations are completed,
there is more boilerplate code as <tt>JAWT_DrawingSurfaceInfo</tt>
is freed and <tt>JAWT_DrawingSurface</tt> is unlocked and
freed.</p>
<p>The corresponding code for the GDI API on the Microsoft Windows platform would
be structured similarly, but would include the version of
<tt>jawt_md.h</tt> for Microsoft Windows and the structure located
in the <tt>platformInfo</tt> field of drawing surface info would be
cast as a <tt>JAWT_Win32DrawingSurfaceInfo*</tt> . And, of course,
the actual drawing operations would need to be changed to those
appropriate for the Microsoft Windows platform.
The same also for MacOS.
</p>
<p><b>Summary</b></p>
<p>The ability to draw directly into a Java <tt>Canvas</tt> from a
native code library is extremely useful for developers planning to
migrate a legacy software system to Java, especially one that
includes a high-performance rendering engine. It makes it much
easier to migrate in stages, leaving performance-sensitive
rendering code alone, while other less-sensitive portions of code
are converted to Java. The result can be a modern Java-centric
application, providing the benefit of portability and development
efficiency, but one that does not sacrifice an investment in
performance of a key piece of native code.</p>
<p><b>References</b></p>
<p>The definitive reference to the Java Native Interface is <i>The
Java Native Interface: Programmer's Guide and Specification</i> by
Sheng Liang. This book was published in June
1999 by Addison-Wesley. The ISBN is 0-201-32577-2.</p>
<p><b>Appendix</b></p>
<p><b>Header Files for jawt.h and jawt_md.h</b></p>
<a name="jawt.h"></a>
<p>jawt.h</p>
<pre>
#ifndef _JAVASOFT_JAWT_H_
#define _JAVASOFT_JAWT_H_
#include "jni.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* AWT native interface.
*
* The AWT native interface allows a native C or C++ application a means
* by which to access native structures in AWT. This is to facilitate moving
* legacy C and C++ applications to Java and to target the needs of the
* developers who need to do their own native rendering to canvases
* for performance or other reasons.
*
* Conversely it also provides mechanisms for an application which already
* has a native window to provide that to AWT for AWT rendering.
*
* Since every platform may be different in its native data structures
* and APIs for windowing systems the application must necessarily
* provided per-platform source and compile and deliver per-platform
* native code to use this API.
*
* These interfaces are not part of the Java SE specification and
* a VM is not required to implement this API. However it is strongly
* recommended that all implementations which support headful AWT
* also support these interfaces.
*
*/
/*
* AWT Native Drawing Surface (JAWT_DrawingSurface).
*
* For each platform, there is a native drawing surface structure. This
* platform-specific structure can be found in jawt_md.h. It is recommended
* that additional platforms follow the same model. It is also recommended
* that VMs on all platforms support the existing structures in jawt_md.h.
*
*******************
* EXAMPLE OF USAGE:
*******************
*
* On Microsoft Windows, a programmer wishes to access the HWND of a canvas
* to perform native rendering into it. The programmer has declared the
* paint() method for their canvas subclass to be native:
*
*
* MyCanvas.java:
*
* import java.awt.*;
*
* public class MyCanvas extends Canvas {
*
* static {
* System.loadLibrary("mylib");
* }
*
* public native void paint(Graphics g);
* }
*
*
* myfile.c:
*
* #include "jawt_md.h"
* #include &lt;assert.h&gt;
*
* JNIEXPORT void JNICALL
* Java_MyCanvas_paint(JNIEnv* env, jobject canvas, jobject graphics)
* {
* JAWT awt;
* JAWT_DrawingSurface* ds;
* JAWT_DrawingSurfaceInfo* dsi;
* JAWT_Win32DrawingSurfaceInfo* dsi_win;
* jboolean result;
* jint lock;
*
* // Get the AWT. Request version 9 to access features in that release.
* awt.version = JAWT_VERSION_9;
* result = JAWT_GetAWT(env, &amp;awt);
* assert(result != JNI_FALSE);
*
* // Get the drawing surface
* ds = awt.GetDrawingSurface(env, canvas);
* assert(ds != NULL);
*
* // Lock the drawing surface
* lock = ds-&gt;Lock(ds);
* assert((lock &amp; JAWT_LOCK_ERROR) == 0);
*
* // Get the drawing surface info
* dsi = ds-&gt;GetDrawingSurfaceInfo(ds);
*
* // Get the platform-specific drawing info
* dsi_win = (JAWT_Win32DrawingSurfaceInfo*)dsi-&gt;platformInfo;
*
* //////////////////////////////
* // !!! DO PAINTING HERE !!! //
* //////////////////////////////
*
* // Free the drawing surface info
* ds-&gt;FreeDrawingSurfaceInfo(dsi);
*
* // Unlock the drawing surface
* ds-&gt;Unlock(ds);
*
* // Free the drawing surface
* awt.FreeDrawingSurface(ds);
* }
*
*/
/*
* JAWT_Rectangle
* Structure for a native rectangle.
*/
typedef struct jawt_Rectangle {
jint x;
jint y;
jint width;
jint height;
} JAWT_Rectangle;
struct jawt_DrawingSurface;
/*
* JAWT_DrawingSurfaceInfo
* Structure for containing the underlying drawing information of a component.
*/
typedef struct jawt_DrawingSurfaceInfo {
/*
* Pointer to the platform-specific information. This can be safely
* cast to a JAWT_Win32DrawingSurfaceInfo on Microsoft Windows or a
* JAWT_X11DrawingSurfaceInfo on Linux and Solaris. On MacOS this is a
* pointer to a NSObject that conforms to the JAWT_SurfaceLayers protocol.
* See jawt_md.h for details.
*/
void* platformInfo;
/* Cached pointer to the underlying drawing surface */
struct jawt_DrawingSurface* ds;
/* Bounding rectangle of the drawing surface */
JAWT_Rectangle bounds;
/* Number of rectangles in the clip */
jint clipSize;
/* Clip rectangle array */
JAWT_Rectangle* clip;
} JAWT_DrawingSurfaceInfo;
#define JAWT_LOCK_ERROR 0x00000001
#define JAWT_LOCK_CLIP_CHANGED 0x00000002
#define JAWT_LOCK_BOUNDS_CHANGED 0x00000004
#define JAWT_LOCK_SURFACE_CHANGED 0x00000008
/*
* JAWT_DrawingSurface
* Structure for containing the underlying drawing information of a component.
* All operations on a JAWT_DrawingSurface MUST be performed from the same
* thread as the call to GetDrawingSurface.
*/
typedef struct jawt_DrawingSurface {
/* Cached reference to the Java environment of the calling thread.
* If Lock(), Unlock(), GetDrawingSurfaceInfo() or
* FreeDrawingSurfaceInfo() are called from a different thread,
* this data member should be set before calling those functions.
*/
JNIEnv* env;
/* Cached reference to the target object */
jobject target;
/*
* Lock the surface of the target component for native rendering.
* When finished drawing, the surface must be unlocked with
* Unlock(). This function returns a bitmask with one or more of the
* following values:
*
* JAWT_LOCK_ERROR - When an error has occurred and the surface could not
* be locked.
*
* JAWT_LOCK_CLIP_CHANGED - When the clip region has changed.
*
* JAWT_LOCK_BOUNDS_CHANGED - When the bounds of the surface have changed.
*
* JAWT_LOCK_SURFACE_CHANGED - When the surface itself has changed
*/
jint (JNICALL *Lock)
(struct jawt_DrawingSurface* ds);
/*
* Get the drawing surface info.
* The value returned may be cached, but the values may change if
* additional calls to Lock() or Unlock() are made.
* Lock() must be called before this can return a valid value.
* Returns NULL if an error has occurred.
* When finished with the returned value, FreeDrawingSurfaceInfo must be
* called.
*/
JAWT_DrawingSurfaceInfo* (JNICALL *GetDrawingSurfaceInfo)
(struct jawt_DrawingSurface* ds);
/*
* Free the drawing surface info.
*/
void (JNICALL *FreeDrawingSurfaceInfo)
(JAWT_DrawingSurfaceInfo* dsi);
/*
* Unlock the drawing surface of the target component for native rendering.
*/
void (JNICALL *Unlock)
(struct jawt_DrawingSurface* ds);
} JAWT_DrawingSurface;
/*
* JAWT
* Structure for containing native AWT functions.
*/
typedef struct jawt {
/*
* Version of this structure. This must always be set before
* calling JAWT_GetAWT(). It affects the functions returned.
* Must be one of the known pre-defined versions.
*/
jint version;
/*
* Return a drawing surface from a target jobject. This value
* may be cached.
* Returns NULL if an error has occurred.
* Target must be a java.awt.Component (should be a Canvas
* or Window for native rendering).
* FreeDrawingSurface() must be called when finished with the
* returned JAWT_DrawingSurface.
*/
JAWT_DrawingSurface* (JNICALL *GetDrawingSurface)
(JNIEnv* env, jobject target);
/*
* Free the drawing surface allocated in GetDrawingSurface.
*/
void (JNICALL *FreeDrawingSurface)
(JAWT_DrawingSurface* ds);
/*
* Since 1.4
* Locks the entire AWT for synchronization purposes
*/
void (JNICALL *Lock)(JNIEnv* env);
/*
* Since 1.4
* Unlocks the entire AWT for synchronization purposes
*/
void (JNICALL *Unlock)(JNIEnv* env);
/*
* Since 1.4
* Returns a reference to a java.awt.Component from a native
* platform handle. On Windows, this corresponds to an HWND;
* on Solaris and Linux, this is a Drawable. For other platforms,
* see the appropriate machine-dependent header file for a description.
* The reference returned by this function is a local
* reference that is only valid in this environment.
* This function returns a NULL reference if no component could be
* found with matching platform information.
*/
jobject (JNICALL *GetComponent)(JNIEnv* env, void* platformInfo);
/**
* Since 9
* Creates a java.awt.Frame placed in a native container. Container is
* referenced by the native platform handle. For example on Windows this
* corresponds to an HWND. For other platforms, see the appropriate
* machine-dependent header file for a description. The reference returned
* by this function is a local reference that is only valid in this
* environment. This function returns a NULL reference if no frame could be
* created with matching platform information.
*/
jobject (JNICALL *CreateEmbeddedFrame) (JNIEnv *env, void* platformInfo);
/**
* Since 9
* Moves and resizes the embedded frame. The new location of the top-left
* corner is specified by x and y parameters relative to the native parent
* component. The new size is specified by width and height.
*
* The embedded frame should be created by CreateEmbeddedFrame() method, or
* this function will not have any effect.
*
* java.awt.Component.setLocation() and java.awt.Component.setBounds() for
* EmbeddedFrame really don't move it within the native parent. These
* methods always locate the embedded frame at (0, 0) for backward
* compatibility. To allow moving embedded frames this method was
* introduced, and it works just the same way as setLocation() and
* setBounds() for usual, non-embedded components.
*
* Using usual get/setLocation() and get/setBounds() together with this new
* method is not recommended.
*/
void (JNICALL *SetBounds) (JNIEnv *env, jobject embeddedFrame,
jint x, jint y, jint w, jint h);
/**
* Since 9
* Synthesize a native message to activate or deactivate an EmbeddedFrame
* window depending on the value of parameter doActivate, if "true"
* activates the window; otherwise, deactivates the window.
*
* The embedded frame should be created by CreateEmbeddedFrame() method, or
* this function will not have any effect.
*/
void (JNICALL *SynthesizeWindowActivation) (JNIEnv *env,
jobject embeddedFrame, jboolean doActivate);
} JAWT;
/*
* Get the AWT native structure. This function returns JNI_FALSE if
* an error occurs.
*/
_JNI_IMPORT_OR_EXPORT_
jboolean JNICALL JAWT_GetAWT(JNIEnv* env, JAWT* awt);
/*
* Specify one of these constants as the JAWT.version
* Specifying an earlier version will limit the available functions to
* those provided in that earlier version of JAWT.
* See the "Since" note on each API. Methods with no "Since"
* may be presumed to be present in JAWT_VERSION_1_3.
*/
#define JAWT_VERSION_1_3 0x00010003
#define JAWT_VERSION_1_4 0x00010004
#define JAWT_VERSION_1_7 0x00010007
#define JAWT_VERSION_9 0x00090000
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !_JAVASOFT_JAWT_H_ */
</pre>
<p>jawt_md.h (Linux/Solaris/X11 operating environment version)</p>
<pre>
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include &lt;X11/Xlib.h&gt;
#include &lt;X11/Xutil.h&gt;
#include &lt;X11/Intrinsic.h&gt;
#include "jawt.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* X11-specific declarations for AWT native interface.
* See notes in jawt.h for an example of use.
*/
typedef struct jawt_X11DrawingSurfaceInfo {
Drawable drawable;
Display* display;
VisualID visualID;
Colormap colormapID;
int depth;
} JAWT_X11DrawingSurfaceInfo;
#ifdef __cplusplus
}
#endif
#endif /* !_JAVASOFT_JAWT_MD_H_ */
</pre>
<p>jawt_md.h (Microsoft Windows version)</p>
<pre>
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include &lt;windows.h&gt;
#include "jawt.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Microsoft Windows specific declarations for AWT native interface.
* See notes in jawt.h for an example of use.
*/
typedef struct jawt_Win32DrawingSurfaceInfo {
/* Native window, DDB, or DIB handle */
union {
HWND hwnd;
HBITMAP hbitmap;
void* pbits;
};
/*
* This HDC should always be used instead of the HDC returned from
* BeginPaint() or any calls to GetDC().
*/
HDC hdc;
HPALETTE hpalette;
} JAWT_Win32DrawingSurfaceInfo;
#ifdef __cplusplus
}
#endif
#endif /* !_JAVASOFT_JAWT_MD_H_ */
</pre>
<p>jawt_md.h (MacOS version)</p>
<pre>
#ifndef _JAVASOFT_JAWT_MD_H_
#define _JAVASOFT_JAWT_MD_H_
#include "jawt.h"
#ifdef __OBJC__
#import <QuartzCore/CALayer.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* MacOS specific declarations for AWT native interface.
* See notes in jawt.h for an example of use.
*/
/*
* When calling JAWT_GetAWT with a JAWT version less than 1.7, you must pass this
* flag or you will not be able to get a valid drawing surface and JAWT_GetAWT will
* return false. This is to maintain compatibility with applications that used the
* interface with Java 6 which had multiple rendering models. This flag is not necessary
* when JAWT version 1.7 or greater is used as this is the only supported rendering mode.
*
* Example:
* JAWT awt;
* awt.version = JAWT_VERSION_1_4 | JAWT_MACOSX_USE_CALAYER;
* jboolean success = JAWT_GetAWT(env, &awt);
*/
#define JAWT_MACOSX_USE_CALAYER 0x80000000
/*
* When the native Cocoa toolkit is in use, the pointer stored in
* JAWT_DrawingSurfaceInfo->platformInfo points to a NSObject that conforms to the
* JAWT_SurfaceLayers protocol. Setting the layer property of this object will cause the
* specified layer to be overlaid on the Components rectangle. If the window the
* Component belongs to has a CALayer attached to it, this layer will be accessible via
* the windowLayer property.
*/
#ifdef __OBJC__
@protocol JAWT_SurfaceLayers
@property (readwrite, retain) CALayer *layer;
@property (readonly) CALayer *windowLayer;
@end
#endif
#ifdef __cplusplus
}
#endif
#endif /* !_JAVASOFT_JAWT_MD_H_ */
</pre>
<!-- Body text ends here -->
</body>
</html>

View File

@ -24,27 +24,27 @@
*/
/**
* Defines the RMI Connector for the Java Management Extensions (JMX) Remote API.
* <P>
* The {@linkplain javax.management.remote.rmi RMI connector} is a connector
* for the JMX Remote API that uses RMI to transmit client requests to a remote
* MBean server.
* Defines the {@linkplain javax.management.remote.rmi RMI connector}
* for the Java Management Extensions (JMX) Remote API.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Providers:</dt>
* <dd>This module provides
* {@link javax.management.remote.JMXConnectorProvider} service
* that creates the JMX connector clients using RMI protocol.
* Instances of {@code JMXConnector} can be obtained via the
* {@link javax.management.remote.JMXConnectorFactory#newJMXConnector
* JMXConnectorFactory.newJMXConnector} factory method.
* It also provides {@link javax.management.remote.JMXConnectorServerProvider} service
* that creates the JMX connector servers using RMI protocol.
* Instances of {@code JMXConnectorServer} can be obtained via the
* {@link javax.management.remote.JMXConnectorServerFactory#newJMXConnectorServer
* JMXConnectorServerFactory.newJMXConnectorServer} factory method.
* </dd>
* </dl>
*
* @provides javax.management.remote.JMXConnectorProvider
* A provider of {@code JMXConnector} for the RMI protocol.<br>
* Instances of {@code JMXConnector} using the RMI protocol
* are usually created by the {@link
* javax.management.remote.JMXConnectorFactory} which will locate
* and load the appropriate {@code JMXConnectorProvider} service
* implementation for the given protocol.
*
* @provides javax.management.remote.JMXConnectorServerProvider
* A provider of {@code JMXConnectorServer} for the RMI protocol.<br>
* Instances of {@code JMXConnectorServer} using the RMI protocol
* are usually created by the {@link
* javax.management.remote.JMXConnectorServerFactory} which will locate
* and load the appropriate {@code JMXConnectorServerProvider} service
* implementation for the given protocol.
*
* @moduleGraph
* @since 9

View File

@ -29,6 +29,9 @@
* The JMX API consists of interfaces for monitoring and management of the
* JVM and other components in the Java runtime.
*
* @uses javax.management.remote.JMXConnectorProvider
* @uses javax.management.remote.JMXConnectorServerProvider
*
* @moduleGraph
* @since 9
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,6 +28,8 @@ package com.sun.jndi.ldap;
import java.util.Hashtable;
import java.util.Vector;
import java.util.EventObject;
import java.util.Iterator;
import java.util.Map;
import javax.naming.*;
import javax.naming.event.*;
@ -204,31 +206,35 @@ final class EventSupport {
* Removes {@code l} from all notifiers in this context.
*/
synchronized void removeNamingListener(NamingListener l) {
if (debug) System.err.println("EventSupport removing listener");
if (debug) {
System.err.println("EventSupport removing listener");
}
// Go through list of notifiers, remove 'l' from each.
// If 'l' is notifier's only listener, remove notifier too.
for (NamingEventNotifier notifier : notifiers.values()) {
Iterator<NamingEventNotifier> iterator = notifiers.values().iterator();
while (iterator.hasNext()) {
NamingEventNotifier notifier = iterator.next();
if (notifier != null) {
if (debug)
if (debug) {
System.err.println("EventSupport removing listener from notifier");
}
notifier.removeNamingListener(l);
if (!notifier.hasNamingListeners()) {
if (debug)
if (debug) {
System.err.println("EventSupport stopping notifier");
}
notifier.stop();
notifiers.remove(notifier.info);
iterator.remove();
}
}
}
// Remove from list of unsolicited notifier
if (debug) System.err.println("EventSupport removing unsolicited: " +
unsolicited);
if (debug) {
System.err.println("EventSupport removing unsolicited: " + unsolicited);
}
if (unsolicited != null) {
unsolicited.removeElement(l);
}
}
synchronized boolean hasUnsolicited() {

View File

@ -26,6 +26,8 @@
/**
* Defines the Preferences API.
*
* @uses java.util.prefs.PreferencesFactory
*
* @moduleGraph
* @since 9
*/
@ -35,4 +37,3 @@ module java.prefs {
exports java.util.prefs;
uses java.util.prefs.PreferencesFactory;
}

View File

@ -26,6 +26,21 @@
/**
* Defines the Remote Method Invocation (RMI) API.
*
* <p> The JDK implementation of this module includes
* the <em>{@index rmiregistry rmiregistry tool}</em> tool to start a remote
* object registry, and the <em>{@index rmid rmid tool}</em> tool to start
* the activation system daemon.
*
* <p>
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:</dt>
* <dd> {@extLink rmiregistry_tool_reference rmiregistry},
* {@extLink rmid_tool_reference rmid}
* </dd>
* </dl>
*
* @uses java.rmi.server.RMIClassLoaderSpi
*
* @moduleGraph
* @since 9
*/

View File

@ -26,6 +26,19 @@
/**
* Defines the Scripting API.
*
* <p> The JDK implementation of this module includes a language-independent
* command-line script shell, <em>{@index jrunscript jrunscript tool}</em>,
* that supports executing JavaScript and other languages if its corresponding
* script engine is installed.
*
* <p>
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd> {@extLink jrunscript_tool_reference jrunscript}</dd>
* </dl>
*
* @uses javax.script.ScriptEngineFactory
*
* @moduleGraph
* @since 9
*/
@ -33,4 +46,3 @@ module java.scripting {
exports javax.script;
uses javax.script.ScriptEngineFactory;
}

View File

@ -34,6 +34,7 @@
*/
@SuppressWarnings({"deprecation",
"removal"}) // java.corba and other modules
@Deprecated(since="9", forRemoval=true)
module java.se.ee {
requires transitive java.se;

View File

@ -29,6 +29,15 @@
* The modules defining CORBA and Java EE APIs are not required by
* this module, but they are required by {@code java.se.ee}.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Optional for Java SE Platform:</dt>
* <dd>
* <a href="../specs/jni/index.html">Java Native Interface (JNI)</a><br>
* <a href="../specs/jvmti.html">Java Virtual Machine Tool Interface (JVM TI)</a><br>
* <a href="../specs/jdwp/jdwp-spec.html">Java Debug Wire Protocol (JDWP)</a><br>
* </dd>
* </dl>
*
* @moduleGraph
* @since 9
*/

View File

@ -26,6 +26,8 @@
/**
* Defines the JDBC RowSet API.
*
* @uses javax.sql.rowset.RowSetFactory
*
* @moduleGraph
* @since 9
*/
@ -39,4 +41,3 @@ module java.sql.rowset {
exports javax.sql.rowset.spi;
uses javax.sql.rowset.RowSetFactory;
}

View File

@ -26,6 +26,8 @@
/**
* Defines the JDBC API.
*
* @uses java.sql.Driver
*
* @moduleGraph
* @since 9
*/
@ -38,4 +40,3 @@ module java.sql {
exports javax.transaction.xa;
uses java.sql.Driver;
}

View File

@ -26,6 +26,8 @@
/**
* Defines the attach API.
*
* @uses com.sun.tools.attach.spi.AttachProvider
*
* @moduleGraph
* @since 9
*/
@ -39,4 +41,3 @@ module jdk.attach {
uses com.sun.tools.attach.spi.AttachProvider;
provides com.sun.tools.attach.spi.AttachProvider with sun.tools.attach.AttachProviderImpl;
}

View File

@ -24,9 +24,11 @@
*/
/**
* {@link java.nio.charset.Charset Charset} provider for the charsets that
* Provides {@link java.nio.charset.Charset charsets} that
* are not in {@code java.base} (mostly double byte and IBM charsets).
*
* @provides java.nio.charset.spi.CharsetProvider
*
* @moduleGraph
* @since 9
*/
@ -34,4 +36,3 @@ module jdk.charsets {
provides java.nio.charset.spi.CharsetProvider
with sun.nio.cs.ext.ExtendedCharsets;
}

View File

@ -24,7 +24,9 @@
*/
/**
* The SunPKCS11 security provider.
* Provides the implementation of the SunPKCS11 security provider.
*
* @provides java.security.Provider
*
* @moduleGraph
* @since 9
@ -34,4 +36,3 @@ module jdk.crypto.cryptoki {
requires jdk.crypto.ec;
provides java.security.Provider with sun.security.pkcs11.SunPKCS11;
}

View File

@ -24,7 +24,9 @@
*/
/**
* The SunEC security provider.
* Provides the implementation of the SunEC security provider.
*
* @provides java.security.Provider
*
* @moduleGraph
* @since 9
@ -32,4 +34,3 @@
module jdk.crypto.ec {
provides java.security.Provider with sun.security.ec.SunEC;
}

View File

@ -24,8 +24,9 @@
*/
/**
* The SunMSCAPI security provider.
* Provides the implementation of the SunMSCAPI security provider.
*
* @provides java.security.Provider
* @moduleGraph
* @since 9
*/

View File

@ -24,8 +24,9 @@
*/
/**
* The OracleUCrypto security provider.
* Provides the implementation of the OracleUCrypto security provider.
*
* @provides java.security.Provider
* @moduleGraph
* @since 9
*/

View File

@ -24,7 +24,7 @@
*/
/**
* Implementation of the edit pad service.
* Provides the implementation of the edit pad service used by {@link jdk.jshell}.
*
* @moduleGraph
* @since 9

View File

@ -26,6 +26,8 @@
/**
* Defines the JDK-specific API for HTTP server.
*
* @uses com.sun.net.httpserver.spi.HttpServerProvider
*
* @moduleGraph
* @since 9
*/
@ -35,4 +37,3 @@ module jdk.httpserver {
exports com.sun.net.httpserver.spi;
uses com.sun.net.httpserver.spi.HttpServerProvider;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -111,47 +111,56 @@ class Http2Connection {
*/
// A small class that allows to control the state of
// the connection preface. This is just a thin wrapper
// over a CountDownLatch.
private final class PrefaceController {
// A small class that allows to control frames with respect to the state of
// the connection preface. Any data received before the connection
// preface is sent will be buffered.
private final class FramesController {
volatile boolean prefaceSent;
private final CountDownLatch latch = new CountDownLatch(1);
volatile List<ByteBufferReference> pending;
// This method returns immediately if the preface is sent,
// and blocks until the preface is sent if not.
// In the common case this where the preface is already sent
// this will cost not more than a volatile read.
void waitUntilPrefaceSent() {
boolean processReceivedData(FramesDecoder decoder, ByteBufferReference buf)
throws IOException
{
// if preface is not sent, buffers data in the pending list
if (!prefaceSent) {
try {
// If the preface is not sent then await on the latch
Log.logTrace("Waiting until connection preface is sent");
latch.await();
Log.logTrace("Preface sent: resuming reading");
assert prefaceSent;
} catch (InterruptedException e) {
String msg = Utils.stackTrace(e);
Log.logTrace(msg);
shutdown(e);
synchronized (this) {
if (!prefaceSent) {
if (pending == null) pending = new ArrayList<>();
pending.add(buf);
return false;
}
}
}
// Preface is sent. Checks for pending data and flush it.
// We rely on this method being called from within the readlock,
// so we know that no other thread could execute this method
// concurrently while we're here.
// This ensures that later incoming buffers will not
// be processed before we have flushed the pending queue.
// No additional synchronization is therefore necessary here.
List<ByteBufferReference> pending = this.pending;
this.pending = null;
if (pending != null) {
// flush pending data
for (ByteBufferReference b : pending) {
decoder.decode(b);
}
}
// push the received buffer to the frames decoder.
decoder.decode(buf);
return true;
}
// Mark that the connection preface is sent
void markPrefaceSent() {
assert !prefaceSent;
prefaceSent = true;
// Release the latch. If asyncReceive was scheduled it will
// be waiting for the release and will be woken up by this
// call. If not, then the semaphore will no longer be used after
// this.
latch.countDown();
synchronized (this) {
prefaceSent = true;
}
}
boolean isPrefaceSent() {
return prefaceSent;
}
}
volatile boolean closed;
@ -176,7 +185,7 @@ class Http2Connection {
* Each of this connection's Streams MUST use this controller.
*/
private final WindowController windowController = new WindowController();
private final PrefaceController prefaceController = new PrefaceController();
private final FramesController framesController = new FramesController();
final WindowUpdateSender windowUpdater;
static final int DEFAULT_FRAME_SIZE = 16 * 1024;
@ -409,11 +418,11 @@ class Http2Connection {
// SettingsFrame sent by the server) before the connection
// preface is fully sent might result in the server
// sending a GOAWAY frame with 'invalid_preface'.
prefaceController.waitUntilPrefaceSent();
synchronized (readlock) {
assert prefaceController.isPrefaceSent();
try {
framesDecoder.decode(buffer);
// the readlock ensures that the order of incoming buffers
// is preserved.
framesController.processReceivedData(framesDecoder, buffer);
} catch (Throwable e) {
String msg = Utils.stackTrace(e);
Log.logTrace(msg);
@ -646,7 +655,8 @@ class Http2Connection {
Log.logFrames(sf, "OUT");
// send preface bytes and SettingsFrame together
connection.write(ref.get());
// mark preface sent.
framesController.markPrefaceSent();
Log.logTrace("PREFACE_BYTES sent");
Log.logTrace("Settings Frame sent");
@ -654,8 +664,10 @@ class Http2Connection {
// minus the initial 64 K specified in protocol
final int len = client2.client().getReceiveBufferSize() - (64 * 1024 - 1);
windowUpdater.sendWindowUpdate(len);
// there will be an ACK to the windows update - which should
// cause any pending data stored before the preface was sent to be
// flushed (see PrefaceController).
Log.logTrace("finished sending connection preface");
prefaceController.markPrefaceSent();
}
/**

View File

@ -344,7 +344,13 @@ class HttpClientImpl extends HttpClient {
c.configureBlocking(false);
SelectionKey key = c.keyFor(selector);
SelectorAttachment sa;
if (key == null) {
if (key == null || !key.isValid()) {
if (key != null) {
// key is canceled.
// invoke selectNow() to purge it
// before registering the new event.
selector.selectNow();
}
sa = new SelectorAttachment(c, selector);
} else {
sa = (SelectorAttachment) key.attachment();

View File

@ -62,6 +62,7 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
private volatile Consumer<ByteBufferReference> asyncReceiver;
private volatile Consumer<Throwable> errorReceiver;
private volatile Supplier<ByteBufferReference> readBufferSupplier;
private boolean asyncReading;
private final AsyncWriteQueue asyncOutputQ = new AsyncWriteQueue(this::asyncOutput);
@ -70,6 +71,9 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
@Override
public void startReading() {
try {
synchronized(reading) {
asyncReading = true;
}
client.registerEvent(new ReadEvent());
} catch (IOException e) {
shutdown();
@ -78,6 +82,9 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
@Override
public void stopAsyncReading() {
synchronized(reading) {
asyncReading = false;
}
client.cancelRegistration(chan);
}
@ -279,7 +286,7 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
void asyncRead() {
synchronized (reading) {
try {
while (true) {
while (asyncReading) {
ByteBufferReference buf = readBufferSupplier.get();
int n = chan.read(buf.get());
if (n == -1) {
@ -325,7 +332,7 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
return -1;
}
Utils.flipToMark(buf, mark);
String s = "Receive (" + n + " bytes) ";
// String s = "Receive (" + n + " bytes) ";
//debugPrint(s, buf);
return n;
}
@ -393,6 +400,10 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
shutdown();
}
@Override
public String toString() {
return super.toString() + "/" + chan;
}
}
// used in blocking channels only
@ -422,6 +433,11 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
public void abort() {
close();
}
@Override
public String toString() {
return super.toString() + "/" + chan;
}
}
@Override
@ -447,7 +463,8 @@ class PlainHttpConnection extends HttpConnection implements AsyncConnection {
CompletableFuture<Void> whenReceivingResponse() {
CompletableFuture<Void> cf = new MinimalFuture<>();
try {
client.registerEvent(new ReceiveResponseEvent(cf));
ReceiveResponseEvent evt = new ReceiveResponseEvent(cf);
client.registerEvent(evt);
} catch (IOException e) {
cf.completeExceptionally(e);
}

View File

@ -803,7 +803,9 @@ class Stream<T> extends ExchangeImpl<T> {
completeResponseExceptionally(e);
try {
// will send a RST_STREAM frame
connection.resetStream(streamid, ResetFrame.CANCEL);
if (streamid != 0) {
connection.resetStream(streamid, ResetFrame.CANCEL);
}
} catch (IOException ex) {
Log.logError(ex);
}

View File

@ -25,7 +25,21 @@
/**
* Defines tools for manipulating Java Archive (JAR) files,
* including the jar and jarsigner tools.
* including the <em>{@index jar jar tool}</em> and
* <em>{@index jarsigner jarsigner tool}</em> tools.
*
* <p> This module provides the equivalent of command-line access to
* <em>jar</em> via the {@link java.util.spi.ToolProvider ToolProvider} SPI.
* Instances of the tool can be obtained by calling
* {@link java.util.spi.ToolProvider#findFirst ToolProvider.findFirst}
* or the {@link java.util.ServiceLoader service loader} with the name
* {@code "jar"}.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>{@extLink jar_tool_reference jar},
* {@extLink jarsigner_tool_reference jarsigner}
* </dl>
*
* @moduleGraph
* @since 9
@ -36,4 +50,3 @@ module jdk.jartool {
provides java.util.spi.ToolProvider with sun.tools.jar.JarToolProvider;
}

View File

@ -24,8 +24,20 @@
*/
/**
* Defines tools for diagnostics and troubleshooting a JVM,
* including the jcmd, jps, jstat and other diagnostics tools.
* Defines tools for diagnostics and troubleshooting a JVM
* such as the <em>{@index jcmd jcmd tool}</em>, <em>{@index jps jps tool}</em>,
* <em>{@index jstat jstat tool}</em> tools.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>
* {@extLink jcmd_tool_reference jcmd},
* {@extLink jinfo_tool_reference jinfo},
* {@extLink jmap_tool_reference jmap},
* {@extLink jps_tool_reference jps},
* {@extLink jstack_tool_reference jstack},
* {@extLink jstat_tool_reference jstat}
* </dl>
*
* @moduleGraph
* @since 9

View File

@ -24,8 +24,16 @@
*/
/**
* Defines the JMX graphical tool, jconsole, for monitoring and managing
* a running application.
* Defines the JMX graphical tool, <em>{@index jconsole jconsole}</em>,
* for monitoring and managing a running application.
*
* <dl style="font-family:'DejaVu Sans', Arial, Helvetica, sans serif">
* <dt class="simpleTagLabel">Tool Guides:
* <dd>{@extLink jconsole_tool_reference jconsole},
* {@extLink using_jconsole Using JConsole}
* </dl>
*
* @uses com.sun.tools.jconsole.JConsolePlugin
*
* @moduleGraph
* @since 9

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