OpenJDK / jdk / jdk
changeset 7552:f59d93c5d52b
Merge
author | lana |
---|---|
date | Mon, 13 Dec 2010 16:25:26 -0800 |
parents | 110025c97f09 dc77388d186a |
children | 56c291480429 |
files | jdk/src/share/demo/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipCoder.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileStore.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java |
diffstat | 188 files changed, 8407 insertions(+), 6419 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/make/common/shared/Defs-linux.gmk Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/common/shared/Defs-linux.gmk Mon Dec 13 16:25:26 2010 -0800 @@ -123,7 +123,7 @@ # GCC29_COMPILER_PATH: is the path to where the gcc 2.9 compiler is installed # NOTE: Must end with / so that it could be empty, allowing PATH usage. -ifneq "$(origin ALT_GCC29_COMPILER_PATH)" "undefined" +ifdef ALT_GCC29_COMPILER_PATH GCC29_COMPILER_PATH :=$(call PrefixPath,$(ALT_GCC29_COMPILER_PATH)) else GCC29_COMPILER_PATH = $(JDK_DEVTOOLS_DIR)/$(PLATFORM)/gcc29/usr/
--- a/jdk/make/common/shared/Defs-versions.gmk Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/common/shared/Defs-versions.gmk Mon Dec 13 16:25:26 2010 -0800 @@ -65,7 +65,7 @@ # If we are using freetype, the freetype version expected. # # REQUIRED_GCC_VER -# Solaris and Linux only. The required version of gcc/g++ for the plugin. +# Solaris and Linux only. The required version of gcc/g++ for the legacy OJI plugin. # # REQUIRED_LINK_VER # Windows only: The version of link.exe expected.
--- a/jdk/make/common/shared/Sanity.gmk Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/common/shared/Sanity.gmk Mon Dec 13 16:25:26 2010 -0800 @@ -99,12 +99,16 @@ echo "RedHat"; \ elif [ -f /etc/SuSE-release ] ; then \ echo "SuSE"; \ + elif [ -f /etc/lsb-release ] ; then \ + $(EGREP) DISTRIB_ID /etc/lsb-release | $(SED) -e 's@.*DISTRIB_ID=\(.*\)@\1@'; \ else \ echo "Unknown"; \ fi) OS_VARIANT_VERSION := $(shell \ if [ "$(OS_VARIANT_NAME)" = "Fedora" ] ; then \ $(CAT) /etc/fedora-release | $(HEAD) -1 | $(NAWK) '{ print $$3; }' ; \ + elif [ -f /etc/lsb-release ] ; then \ + $(EGREP) DISTRIB_RELEASE /etc/lsb-release | $(SED) -e 's@.*DISTRIB_RELEASE=\(.*\)@\1@'; \ fi) ALSA_INCLUDE=/usr/include/alsa/version.h ALSA_LIBRARY=/usr/lib/libasound.so @@ -279,7 +283,7 @@ fi ###################################################### -# Check the OS version (windows and linus have release name checks) +# Check the OS version (windows and linux have release name checks) # NOTE: OPENJDK explicitly does not check for OS release information. # Unless we know for sure that it will not build somewhere, we cannot # generate a fatal sanity error, and a warning about the official @@ -1476,20 +1480,20 @@ endif ###################################################### -# Check the Solaris GNU c++ compiler for solaris plugin +# Check the GNU C++ compiler for OJI plugin ###################################################### sane-gcc-compiler: -ifeq ($(PLATFORM), solaris) - ifndef OPENJDK - @if [ -r $(GCC_COMPILER_PATH) ]; then \ - if [ ! "$(GCC_VER)" = $(REQUIRED_GCC_VERSION) ]; then \ - $(ECHO) "ERROR: The Solaris GCC compiler version must be $(REQUIRED_GCC_VERSION). \n" \ +ifndef OPENJDK + ifeq ($(PLATFORM), solaris) + @if [ -r $(GCC_COMPILER_PATH) ]; then \ + if [ ! "$(GCC_VER)" = $(REQUIRED_GCC_VER) ]; then \ + $(ECHO) "ERROR: The Solaris GCC compiler version must be $(REQUIRED_GCC_VER). \n" \ " You are using the following compiler version: $(GCC_VER) \n" \ " The compiler was obtained from the following location: \n" \ " $(GCC_COMPILER_PATH) \n" \ " Please change your compiler. \n" \ "" >> $(ERROR_FILE) ; \ - fi \ + fi \ else \ $(ECHO) "ERROR: You do not have a valid GCC_COMPILER_PATH setting. \n" \ " Please check your access to \n" \ @@ -1501,15 +1505,16 @@ endif ifeq ($(PLATFORM), linux) + ifeq ($(ARCH_DATA_MODEL), 32) ifdef ALT_GCC29_COMPILER_PATH @if [ ! -x $(ALT_GCC29_COMPILER_PATH)/bin/gcc ]; then \ - $(ECHO) "ERROR: You do not have a valid ALT_GCC29_COMPILER_PATH setting. \n" \ + $(ECHO) "ERROR: You do not have a valid ALT_GCC29_COMPILER_PATH setting. \n" \ " Please check your access to \n" \ " $(ALT_GCC29_COMPILER_PATH)/bin/gcc \n" \ " This will affect you if you build the plugin target. \n" \ "" >> $(ERROR_FILE) ; \ fi - endif + else ifdef ALT_GCC29_PLUGIN_LIB_PATH @if [ ! -r $(ALT_GCC29_PLUGIN_LIB_PATH)/libjavaplugin_oji.so ]; then \ $(ECHO) "Error: You do not have a valid ALT_GCC29_PLUGIN_LIB_PATH setting. \n" \ @@ -1523,13 +1528,15 @@ $(ECHO) "ERROR: You do not have a valid GCC29_COMPILER_PATH setting. \n" \ " Please check your access to \n" \ " $(GCC29_COMPILER_PATH) \n" \ - " and/or check your value of ALT_GCC29_COMPILER_PATH. \n" \ + " and/or check your value of ALT_GCC29_COMPILER_PATH or ALT_GCC29_PLUGIN_LIB_PATH \n" \ " This will affect you if you build the plugin target. \n" \ "" >> $(ERROR_FILE) ; \ fi - endif - endif -endif + endif # ALT_GCC29_PLUGIN_LIB_PATH + endif # ALT_GCC29_COMPILER_PATH + endif # ARCH_DATA_MODEL, 32 + endif # LINUX +endif # OPEN_JDK ######################################################
--- a/jdk/make/docs/Makefile Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/docs/Makefile Mon Dec 13 16:25:26 2010 -0800 @@ -190,7 +190,6 @@ # Common javadoc options used by all COMMON_JAVADOCFLAGS = \ $(NO_PROPRIETARY_API_WARNINGS) \ - -source 1.5 \ -quiet \ -use \ -keywords \
--- a/jdk/make/java/java/FILES_java.gmk Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/java/java/FILES_java.gmk Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1996, 2010, 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 @@ -137,6 +137,7 @@ java/lang/Comparable.java \ java/lang/Readable.java \ java/lang/Override.java \ + java/lang/SafeVarargs.java \ java/lang/SuppressWarnings.java \ java/lang/ref/Reference.java \ java/lang/ref/SoftReference.java \
--- a/jdk/make/mkdemo/nio/zipfs/Makefile Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/make/mkdemo/nio/zipfs/Makefile Mon Dec 13 16:25:26 2010 -0800 @@ -33,8 +33,8 @@ include $(BUILDDIR)/common/Defs.gmk DEMO_ROOT = $(SHARE_SRC)/demo/nio/$(DEMONAME) -DEMO_TOPFILES = ./README.txt -DEMO_SRCDIR = $(DEMO_ROOT) +DEMO_TOPFILES = README.txt Demo.java +DEMO_SRCDIR = $(DEMO_ROOT)/src DEMO_DESTDIR = $(DEMODIR)/nio/$(DEMONAME) # @@ -42,10 +42,10 @@ # include $(BUILDDIR)/common/Demo.gmk -#EXTJAR = $(EXTDIR)/$(DEMONAME).jar -# -#all : build $(EXTJAR) -# -#$(EXTJAR) : $(DEMO_JAR) -# $(prep-target) -# $(CP) $(DEMO_JAR) $(EXTJAR) +EXTJAR = $(EXTDIR)/$(DEMONAME).jar + +all : build $(EXTJAR) + +$(EXTJAR) : $(DEMO_JAR) + $(prep-target) + $(CP) $(DEMO_JAR) $(EXTJAR)
--- a/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/BasicControl.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, 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 @@ -113,6 +113,6 @@ * ASN.1 BER encoded value. */ public byte[] getEncodedValue() { - return value; + return value == null ? null : value.clone(); } }
--- a/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/com/sun/jndi/ldap/Filter.java Mon Dec 13 16:25:26 2010 -0800 @@ -427,7 +427,10 @@ } } else { // descriptor - if (filter[i] != '-' && + // The underscore ("_") character is not allowed by + // the LDAP specification. We allow it here to + // tolerate the incorrect use in practice. + if (filter[i] != '-' && filter[i] != '_' && !(filter[i] >= '0' && filter[i] <= '9') && !(filter[i] >= 'A' && filter[i] <= 'Z') && !(filter[i] >= 'a' && filter[i] <= 'z')) { @@ -467,7 +470,10 @@ break; } - if (filter[i] != '-' && + // The underscore ("_") character is not allowed by + // the LDAP specification. We allow it here to + // tolerate the incorrect use in practice. + if (filter[i] != '-' && filter[i] != '_' && !(filter[i] >= '0' && filter[i] <= '9') && !(filter[i] >= 'A' && filter[i] <= 'Z') && !(filter[i] >= 'a' && filter[i] <= 'z')) { @@ -515,7 +521,10 @@ } } else { // descriptor - if (filter[j] != '-' && + // The underscore ("_") character is not allowed by + // the LDAP specification. We allow it here to + // tolerate the incorrect use in practice. + if (filter[j] != '-' && filter[j] != '_' && !(filter[j] >= '0' && filter[j] <= '9') && !(filter[j] >= 'A' && filter[j] <= 'Z') && !(filter[j] >= 'a' && filter[j] <= 'z')) {
--- a/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ package com.sun.security.auth.module; -import javax.security.auth.login.LoginException; - /** * <p> This class implementation retrieves and makes available NT * security information for the current user. @@ -124,7 +122,7 @@ * @return the group SIDs for the current NT user. */ public String[] getGroupIDs() { - return groupIDs; + return groupIDs == null ? null : groupIDs.clone(); } /**
--- a/jdk/src/share/classes/com/sun/security/auth/module/SolarisSystem.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/com/sun/security/auth/module/SolarisSystem.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package com.sun.security.auth.module; -import javax.security.auth.*; -import javax.security.auth.login.*; - /** * <p> This class implementation retrieves and makes available Solaris * UID/GID/groups information for the current user. @@ -92,6 +89,6 @@ * @return the supplementary groups for the current Solaris user. */ public long[] getGroups() { - return groups; + return groups == null ? null : groups.clone(); } }
--- a/jdk/src/share/classes/com/sun/security/auth/module/UnixSystem.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/com/sun/security/auth/module/UnixSystem.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,6 @@ package com.sun.security.auth.module; -import javax.security.auth.*; -import javax.security.auth.login.*; - /** * <p> This class implementation retrieves and makes available Unix * UID/GID/groups information for the current user. @@ -92,6 +89,6 @@ * @return the supplementary groups for the current Unix user. */ public long[] getGroups() { - return groups; + return groups == null ? null : groups.clone(); } }
--- a/jdk/src/share/classes/java/io/FileOutputStream.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/io/FileOutputStream.java Mon Dec 13 16:25:26 2010 -0800 @@ -56,7 +56,15 @@ */ private final FileDescriptor fd; - private FileChannel channel= null; + /** + * True if the file is opened for append. + */ + private final boolean append; + + /** + * The associated channel, initalized lazily. + */ + private FileChannel channel; private final Object closeLock = new Object(); private volatile boolean closed = false; @@ -196,7 +204,9 @@ if (name == null) { throw new NullPointerException(); } - fd = new FileDescriptor(); + this.fd = new FileDescriptor(); + this.append = append; + fd.incrementAndGetUseCount(); open(name, append); } @@ -232,7 +242,8 @@ if (security != null) { security.checkWrite(fdObj); } - fd = fdObj; + this.fd = fdObj; + this.append = false; /* * FileDescriptor is being shared by streams. @@ -251,22 +262,36 @@ throws FileNotFoundException; /** + * Writes the specified byte to this file output stream. + * + * @param b the byte to be written. + * @param append {@code true} if the write operation first + * advances the position to the end of file + */ + private native void write(int b, boolean append) throws IOException; + + /** * Writes the specified byte to this file output stream. Implements * the <code>write</code> method of <code>OutputStream</code>. * * @param b the byte to be written. * @exception IOException if an I/O error occurs. */ - public native void write(int b) throws IOException; + public void write(int b) throws IOException { + write(b, append); + } /** * Writes a sub array as a sequence of bytes. * @param b the data to be written * @param off the start offset in the data * @param len the number of bytes that are written + * @param append {@code true} to first advance the position to the + * end of file * @exception IOException If an I/O error has occurred. */ - private native void writeBytes(byte b[], int off, int len) throws IOException; + private native void writeBytes(byte b[], int off, int len, boolean append) + throws IOException; /** * Writes <code>b.length</code> bytes from the specified byte array @@ -276,7 +301,7 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[]) throws IOException { - writeBytes(b, 0, b.length); + writeBytes(b, 0, b.length, append); } /** @@ -289,7 +314,7 @@ * @exception IOException if an I/O error occurs. */ public void write(byte b[], int off, int len) throws IOException { - writeBytes(b, off, len); + writeBytes(b, off, len, append); } /** @@ -372,7 +397,7 @@ public FileChannel getChannel() { synchronized (this) { if (channel == null) { - channel = FileChannelImpl.open(fd, false, true, this); + channel = FileChannelImpl.open(fd, false, true, append, this); /* * Increment fd's use count. Invoking the channel's close()
--- a/jdk/src/share/classes/java/io/ObjectInputStream.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java Mon Dec 13 16:25:26 2010 -0800 @@ -3498,8 +3498,8 @@ return ((int[]) array).clone(); } else if (array instanceof long[]) { return ((long[]) array).clone(); - } else if (array instanceof double[]) { - return ((double[]) array).clone(); + } else if (array instanceof short[]) { + return ((short[]) array).clone(); } else { throw new AssertionError(); }
--- a/jdk/src/share/classes/java/lang/Double.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/lang/Double.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2010, 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 @@ -973,7 +973,8 @@ if (d1 > d2) return 1; // Neither val is NaN, thisVal is larger - long thisBits = Double.doubleToLongBits(d1); + // Cannot use doubleToRawLongBits because of possibility of NaNs. + long thisBits = Double.doubleToLongBits(d1); long anotherBits = Double.doubleToLongBits(d2); return (thisBits == anotherBits ? 0 : // Values are equal
--- a/jdk/src/share/classes/java/lang/Float.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/lang/Float.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2010, 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 @@ -872,12 +872,13 @@ * @since 1.4 */ public static int compare(float f1, float f2) { - if (f1 < f2) + if (f1 < f2) return -1; // Neither val is NaN, thisVal is smaller if (f1 > f2) return 1; // Neither val is NaN, thisVal is larger - int thisBits = Float.floatToIntBits(f1); + // Cannot use floatToRawIntBits because of possibility of NaNs. + int thisBits = Float.floatToIntBits(f1); int anotherBits = Float.floatToIntBits(f2); return (thisBits == anotherBits ? 0 : // Values are equal
--- a/jdk/src/share/classes/java/lang/ProcessBuilder.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/lang/ProcessBuilder.java Mon Dec 13 16:25:26 2010 -0800 @@ -537,7 +537,11 @@ */ public File file() { return null; } - FileOutputStream toFileOutputStream() throws IOException { + /** + * When redirected to a destination file, indicates if the output + * is to be written to the end of the file. + */ + boolean append() { throw new UnsupportedOperationException(); } @@ -588,9 +592,7 @@ public String toString() { return "redirect to write to file \"" + file + "\""; } - FileOutputStream toFileOutputStream() throws IOException { - return new FileOutputStream(file, false); - } + boolean append() { return false; } }; } @@ -620,9 +622,7 @@ public String toString() { return "redirect to append to file \"" + file + "\""; } - FileOutputStream toFileOutputStream() throws IOException { - return new FileOutputStream(file, true); - } + boolean append() { return true; } }; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/lang/SafeVarargs.java Mon Dec 13 16:25:26 2010 -0800 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import java.lang.annotation.*; + +/** + * A programmer assertion that the body of the annotated method or + * constructor does not perform potentially unsafe operations on its + * varargs parameter. Applying this annotation to a method or + * constructor suppresses unchecked warnings about a + * <i>non-reifiable</i> variable-arity (vararg) type and suppresses + * unchecked warnings about parameterized array creation at call + * sites. + * + * <p> In addition to the usage restrictions imposed by its {@link + * Target @Target} meta-annotation, compilers are required to implement + * additional usage restrictions on this annotation type; it is a + * compile-time error if a method or constructor declaration is + * annotated with a {@code @SafeVarargs} annotation, and either: + + * <ul> + * <li> the declaration is a fixed-arity method or constructor + * + * <li> the declaration is a variable-arity method that is neither + * {@code static} nor {@code final}. + * + * </ul> + * + * <p> Compilers are encouraged to issue warnings when this annotation + * type is applied to a method or constructor declaration where: + * + * <ul> + * + * <li> The variable-arity parameter has a reifiable element type, + * which includes primitive types, {@code Object}, and {@code String}. + * (The unchecked warnings this annotation type suppresses already do + * not occur for a reifiable element type.) + * + * <li> The body of the method or constructor declaration performs + * potentially unsafe operations, such as an assignment to an element + * of the variable-arity parameter's array that generates an unchecked + * warning. + * + * <p>Future versions of the platform may mandate compiler errors for + * such unsafe operations. + * + * </ul> + * + * @jls3 4.7 Reifiable Types + * @jls3 8.4.1 Formal Parameters + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.CONSTRUCTOR, ElementType.METHOD}) +public @interface SafeVarargs {}
--- a/jdk/src/share/classes/java/lang/StrictMath.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/lang/StrictMath.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, 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 @@ -801,8 +801,9 @@ return (a >= b) ? a : b; } - private static long negativeZeroFloatBits = Float.floatToIntBits(-0.0f); - private static long negativeZeroDoubleBits = Double.doubleToLongBits(-0.0d); + // Use raw bit-wise conversions on guaranteed non-NaN arguments. + private static long negativeZeroFloatBits = Float.floatToRawIntBits(-0.0f); + private static long negativeZeroDoubleBits = Double.doubleToRawLongBits(-0.0d); /** * Returns the greater of two {@code float} values. That is, @@ -819,9 +820,12 @@ * @return the larger of {@code a} and {@code b}. */ public static float max(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(a) == negativeZeroFloatBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0f) && + (b == 0.0f) && + (Float.floatToRawIntBits(a) == negativeZeroFloatBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a >= b) ? a : b; @@ -842,9 +846,12 @@ * @return the larger of {@code a} and {@code b}. */ public static double max(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(a) == negativeZeroDoubleBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0d) && + (b == 0.0d) && + (Double.doubleToRawLongBits(a) == negativeZeroDoubleBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a >= b) ? a : b; @@ -893,9 +900,12 @@ * @return the smaller of {@code a} and {@code b.} */ public static float min(float a, float b) { - if (a != a) return a; // a is NaN - if ((a == 0.0f) && (b == 0.0f) - && (Float.floatToIntBits(b) == negativeZeroFloatBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0f) && + (b == 0.0f) && + (Float.floatToRawIntBits(b) == negativeZeroFloatBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a <= b) ? a : b; @@ -916,9 +926,12 @@ * @return the smaller of {@code a} and {@code b}. */ public static double min(double a, double b) { - if (a != a) return a; // a is NaN - if ((a == 0.0d) && (b == 0.0d) - && (Double.doubleToLongBits(b) == negativeZeroDoubleBits)) { + if (a != a) + return a; // a is NaN + if ((a == 0.0d) && + (b == 0.0d) && + (Double.doubleToRawLongBits(b) == negativeZeroDoubleBits)) { + // Raw conversion ok since NaN can't map to -0.0. return b; } return (a <= b) ? a : b;
--- a/jdk/src/share/classes/java/lang/Thread.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/lang/Thread.java Mon Dec 13 16:25:26 2010 -0800 @@ -209,7 +209,7 @@ * initialized to indicate thread 'not yet started' */ - private int threadStatus = 0; + private volatile int threadStatus = 0; private static synchronized long nextThreadID() {
--- a/jdk/src/share/classes/java/nio/charset/Charset.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/nio/charset/Charset.java Mon Dec 13 16:25:26 2010 -0800 @@ -275,18 +275,17 @@ /* -- Static methods -- */ - private static String bugLevel = null; + private static volatile String bugLevel = null; static boolean atBugLevel(String bl) { // package-private - if (bugLevel == null) { + String level = bugLevel; + if (level == null) { if (!sun.misc.VM.isBooted()) return false; - bugLevel = AccessController.doPrivileged( - new GetPropertyAction("sun.nio.cs.bugLevel")); - if (bugLevel == null) - bugLevel = ""; + bugLevel = level = AccessController.doPrivileged( + new GetPropertyAction("sun.nio.cs.bugLevel", "")); } - return (bugLevel != null) && bugLevel.equals(bl); + return level.equals(bl); } /**
--- a/jdk/src/share/classes/java/security/CodeSigner.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/security/CodeSigner.java Mon Dec 13 16:25:26 2010 -0800 @@ -25,7 +25,7 @@ package java.security; -import java.io.Serializable; +import java.io.*; import java.security.cert.CRL; import java.security.cert.CertPath; import sun.misc.JavaSecurityCodeSignerAccess; @@ -205,4 +205,10 @@ }); } + // Explicitly reset hash code value to -1 + private void readObject(ObjectInputStream ois) + throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + myhash = -1; + } }
--- a/jdk/src/share/classes/java/security/Timestamp.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/security/Timestamp.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,12 @@ package java.security; -import java.io.Serializable; +import java.io.*; +import java.security.cert.Certificate; import java.security.cert.CertPath; import java.security.cert.X509Extension; import java.util.Date; +import java.util.List; /** * This class encapsulates information about a signed timestamp. @@ -142,8 +144,20 @@ StringBuffer sb = new StringBuffer(); sb.append("("); sb.append("timestamp: " + timestamp); - sb.append("TSA: " + signerCertPath.getCertificates().get(0)); + List<? extends Certificate> certs = signerCertPath.getCertificates(); + if (!certs.isEmpty()) { + sb.append("TSA: " + certs.get(0)); + } else { + sb.append("TSA: <empty>"); + } sb.append(")"); return sb.toString(); } + + // Explicitly reset hash code value to -1 + private void readObject(ObjectInputStream ois) + throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + myhash = -1; + } }
--- a/jdk/src/share/classes/java/util/AbstractCollection.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/AbstractCollection.java Mon Dec 13 16:25:26 2010 -0800 @@ -96,14 +96,14 @@ * @throws NullPointerException {@inheritDoc} */ public boolean contains(Object o) { - Iterator<E> e = iterator(); + Iterator<E> it = iterator(); if (o==null) { - while (e.hasNext()) - if (e.next()==null) + while (it.hasNext()) + if (it.next()==null) return true; } else { - while (e.hasNext()) - if (o.equals(e.next())) + while (it.hasNext()) + if (o.equals(it.next())) return true; } return false; @@ -269,18 +269,18 @@ * @throws NullPointerException {@inheritDoc} */ public boolean remove(Object o) { - Iterator<E> e = iterator(); + Iterator<E> it = iterator(); if (o==null) { - while (e.hasNext()) { - if (e.next()==null) { - e.remove(); + while (it.hasNext()) { + if (it.next()==null) { + it.remove(); return true; } } } else { - while (e.hasNext()) { - if (o.equals(e.next())) { - e.remove(); + while (it.hasNext()) { + if (o.equals(it.next())) { + it.remove(); return true; } } @@ -304,9 +304,8 @@ * @see #contains(Object) */ public boolean containsAll(Collection<?> c) { - Iterator<?> e = c.iterator(); - while (e.hasNext()) - if (!contains(e.next())) + for (Object e : c) + if (!contains(e)) return false; return true; } @@ -331,11 +330,9 @@ */ public boolean addAll(Collection<? extends E> c) { boolean modified = false; - Iterator<? extends E> e = c.iterator(); - while (e.hasNext()) { - if (add(e.next())) + for (E e : c) + if (add(e)) modified = true; - } return modified; } @@ -362,10 +359,10 @@ */ public boolean removeAll(Collection<?> c) { boolean modified = false; - Iterator<?> e = iterator(); - while (e.hasNext()) { - if (c.contains(e.next())) { - e.remove(); + Iterator<?> it = iterator(); + while (it.hasNext()) { + if (c.contains(it.next())) { + it.remove(); modified = true; } } @@ -395,10 +392,10 @@ */ public boolean retainAll(Collection<?> c) { boolean modified = false; - Iterator<E> e = iterator(); - while (e.hasNext()) { - if (!c.contains(e.next())) { - e.remove(); + Iterator<E> it = iterator(); + while (it.hasNext()) { + if (!c.contains(it.next())) { + it.remove(); modified = true; } } @@ -421,10 +418,10 @@ * @throws UnsupportedOperationException {@inheritDoc} */ public void clear() { - Iterator<E> e = iterator(); - while (e.hasNext()) { - e.next(); - e.remove(); + Iterator<E> it = iterator(); + while (it.hasNext()) { + it.next(); + it.remove(); } } @@ -442,18 +439,18 @@ * @return a string representation of this collection */ public String toString() { - Iterator<E> i = iterator(); - if (! i.hasNext()) + Iterator<E> it = iterator(); + if (! it.hasNext()) return "[]"; StringBuilder sb = new StringBuilder(); sb.append('['); for (;;) { - E e = i.next(); + E e = it.next(); sb.append(e == this ? "(this Collection)" : e); - if (! i.hasNext()) + if (! it.hasNext()) return sb.append(']').toString(); - sb.append(", "); + sb.append(',').append(' '); } }
--- a/jdk/src/share/classes/java/util/AbstractList.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/AbstractList.java Mon Dec 13 16:25:26 2010 -0800 @@ -175,15 +175,15 @@ * @throws NullPointerException {@inheritDoc} */ public int indexOf(Object o) { - ListIterator<E> e = listIterator(); + ListIterator<E> it = listIterator(); if (o==null) { - while (e.hasNext()) - if (e.next()==null) - return e.previousIndex(); + while (it.hasNext()) + if (it.next()==null) + return it.previousIndex(); } else { - while (e.hasNext()) - if (o.equals(e.next())) - return e.previousIndex(); + while (it.hasNext()) + if (o.equals(it.next())) + return it.previousIndex(); } return -1; } @@ -200,15 +200,15 @@ * @throws NullPointerException {@inheritDoc} */ public int lastIndexOf(Object o) { - ListIterator<E> e = listIterator(size()); + ListIterator<E> it = listIterator(size()); if (o==null) { - while (e.hasPrevious()) - if (e.previous()==null) - return e.nextIndex(); + while (it.hasPrevious()) + if (it.previous()==null) + return it.nextIndex(); } else { - while (e.hasPrevious()) - if (o.equals(e.previous())) - return e.nextIndex(); + while (it.hasPrevious()) + if (o.equals(it.previous())) + return it.nextIndex(); } return -1; } @@ -517,7 +517,7 @@ ListIterator<E> e1 = listIterator(); ListIterator e2 = ((List) o).listIterator(); - while(e1.hasNext() && e2.hasNext()) { + while (e1.hasNext() && e2.hasNext()) { E o1 = e1.next(); Object o2 = e2.next(); if (!(o1==null ? o2==null : o1.equals(o2)))
--- a/jdk/src/share/classes/java/util/AbstractMap.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/AbstractMap.java Mon Dec 13 16:25:26 2010 -0800 @@ -523,7 +523,7 @@ sb.append(value == this ? "(this Map)" : value); if (! i.hasNext()) return sb.append('}').toString(); - sb.append(", "); + sb.append(',').append(' '); } }
--- a/jdk/src/share/classes/java/util/ArrayList.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/ArrayList.java Mon Dec 13 16:25:26 2010 -0800 @@ -120,9 +120,9 @@ /** * Constructs an empty list with the specified initial capacity. * - * @param initialCapacity the initial capacity of the list - * @exception IllegalArgumentException if the specified initial capacity - * is negative + * @param initialCapacity the initial capacity of the list + * @throws IllegalArgumentException if the specified initial capacity + * is negative */ public ArrayList(int initialCapacity) { super(); @@ -173,7 +173,7 @@ * necessary, to ensure that it can hold at least the number of elements * specified by the minimum capacity argument. * - * @param minCapacity the desired minimum capacity + * @param minCapacity the desired minimum capacity */ public void ensureCapacity(int minCapacity) { if (minCapacity > 0)
--- a/jdk/src/share/classes/java/util/Collections.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/Collections.java Mon Dec 13 16:25:26 2010 -0800 @@ -124,7 +124,7 @@ * * <p>The implementation takes equal advantage of ascending and * descending order in its input array, and can take advantage of - * ascending and descending order in different parts of the the same + * ascending and descending order in different parts of the same * input array. It is well-suited to merging two or more sorted arrays: * simply concatenate the arrays and sort the resulting array. * @@ -184,7 +184,7 @@ * * <p>The implementation takes equal advantage of ascending and * descending order in its input array, and can take advantage of - * ascending and descending order in different parts of the the same + * ascending and descending order in different parts of the same * input array. It is well-suited to merging two or more sorted arrays: * simply concatenate the arrays and sort the resulting array. * @@ -823,7 +823,7 @@ i -= size; displaced = list.set(i, displaced); nMoved ++; - } while(i != cycleStart); + } while (i != cycleStart); } } @@ -1452,9 +1452,9 @@ * when o is a Map.Entry, and calls o.setValue. */ public boolean containsAll(Collection<?> coll) { - Iterator<?> e = coll.iterator(); - while (e.hasNext()) - if (!contains(e.next())) // Invokes safe contains() above + Iterator<?> it = coll.iterator(); + while (it.hasNext()) + if (!contains(it.next())) // Invokes safe contains() above return false; return true; } @@ -1482,12 +1482,12 @@ UnmodifiableEntry(Map.Entry<? extends K, ? extends V> e) {this.e = e;} - public K getKey() {return e.getKey();} - public V getValue() {return e.getValue();} + public K getKey() {return e.getKey();} + public V getValue() {return e.getValue();} public V setValue(V value) { throw new UnsupportedOperationException(); } - public int hashCode() {return e.hashCode();} + public int hashCode() {return e.hashCode();} public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; @@ -1495,7 +1495,7 @@ return eq(e.getKey(), t.getKey()) && eq(e.getValue(), t.getValue()); } - public String toString() {return e.toString();} + public String toString() {return e.toString();} } } } @@ -1562,7 +1562,7 @@ * <pre> * Collection c = Collections.synchronizedCollection(myCollection); * ... - * synchronized(c) { + * synchronized (c) { * Iterator i = c.iterator(); // Must be in the synchronized block * while (i.hasNext()) * foo(i.next()); @@ -1611,19 +1611,19 @@ } public int size() { - synchronized(mutex) {return c.size();} + synchronized (mutex) {return c.size();} } public boolean isEmpty() { - synchronized(mutex) {return c.isEmpty();} + synchronized (mutex) {return c.isEmpty();} } public boolean contains(Object o) { - synchronized(mutex) {return c.contains(o);} + synchronized (mutex) {return c.contains(o);} } public Object[] toArray() { - synchronized(mutex) {return c.toArray();} + synchronized (mutex) {return c.toArray();} } public <T> T[] toArray(T[] a) { - synchronized(mutex) {return c.toArray(a);} + synchronized (mutex) {return c.toArray(a);} } public Iterator<E> iterator() { @@ -1631,32 +1631,32 @@ } public boolean add(E e) { - synchronized(mutex) {return c.add(e);} + synchronized (mutex) {return c.add(e);} } public boolean remove(Object o) { - synchronized(mutex) {return c.remove(o);} + synchronized (mutex) {return c.remove(o);} } public boolean containsAll(Collection<?> coll) { - synchronized(mutex) {return c.containsAll(coll);} + synchronized (mutex) {return c.containsAll(coll);} } public boolean addAll(Collection<? extends E> coll) { - synchronized(mutex) {return c.addAll(coll);} + synchronized (mutex) {return c.addAll(coll);} } public boolean removeAll(Collection<?> coll) { - synchronized(mutex) {return c.removeAll(coll);} + synchronized (mutex) {return c.removeAll(coll);} } public boolean retainAll(Collection<?> coll) { - synchronized(mutex) {return c.retainAll(coll);} + synchronized (mutex) {return c.retainAll(coll);} } public void clear() { - synchronized(mutex) {c.clear();} + synchronized (mutex) {c.clear();} } public String toString() { - synchronized(mutex) {return c.toString();} + synchronized (mutex) {return c.toString();} } private void writeObject(ObjectOutputStream s) throws IOException { - synchronized(mutex) {s.defaultWriteObject();} + synchronized (mutex) {s.defaultWriteObject();} } } @@ -1671,7 +1671,7 @@ * <pre> * Set s = Collections.synchronizedSet(new HashSet()); * ... - * synchronized(s) { + * synchronized (s) { * Iterator i = s.iterator(); // Must be in the synchronized block * while (i.hasNext()) * foo(i.next()); @@ -1709,10 +1709,10 @@ } public boolean equals(Object o) { - synchronized(mutex) {return c.equals(o);} + synchronized (mutex) {return c.equals(o);} } public int hashCode() { - synchronized(mutex) {return c.hashCode();} + synchronized (mutex) {return c.hashCode();} } } @@ -1728,7 +1728,7 @@ * <pre> * SortedSet s = Collections.synchronizedSortedSet(new TreeSet()); * ... - * synchronized(s) { + * synchronized (s) { * Iterator i = s.iterator(); // Must be in the synchronized block * while (i.hasNext()) * foo(i.next()); @@ -1739,7 +1739,7 @@ * SortedSet s = Collections.synchronizedSortedSet(new TreeSet()); * SortedSet s2 = s.headSet(foo); * ... - * synchronized(s) { // Note: s, not s2!!! + * synchronized (s) { // Note: s, not s2!!! * Iterator i = s2.iterator(); // Must be in the synchronized block * while (i.hasNext()) * foo(i.next()); @@ -1766,7 +1766,7 @@ { private static final long serialVersionUID = 8695801310862127406L; - final private SortedSet<E> ss; + private final SortedSet<E> ss; SynchronizedSortedSet(SortedSet<E> s) { super(s); @@ -1778,31 +1778,31 @@ } public Comparator<? super E> comparator() { - synchronized(mutex) {return ss.comparator();} + synchronized (mutex) {return ss.comparator();} } public SortedSet<E> subSet(E fromElement, E toElement) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedSet<E>( ss.subSet(fromElement, toElement), mutex); } } public SortedSet<E> headSet(E toElement) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedSet<E>(ss.headSet(toElement), mutex); } } public SortedSet<E> tailSet(E fromElement) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedSet<E>(ss.tailSet(fromElement),mutex); } } public E first() { - synchronized(mutex) {return ss.first();} + synchronized (mutex) {return ss.first();} } public E last() { - synchronized(mutex) {return ss.last();} + synchronized (mutex) {return ss.last();} } } @@ -1817,7 +1817,7 @@ * <pre> * List list = Collections.synchronizedList(new ArrayList()); * ... - * synchronized(list) { + * synchronized (list) { * Iterator i = list.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); @@ -1863,34 +1863,34 @@ } public boolean equals(Object o) { - synchronized(mutex) {return list.equals(o);} + synchronized (mutex) {return list.equals(o);} } public int hashCode() { - synchronized(mutex) {return list.hashCode();} + synchronized (mutex) {return list.hashCode();} } public E get(int index) { - synchronized(mutex) {return list.get(index);} + synchronized (mutex) {return list.get(index);} } public E set(int index, E element) { - synchronized(mutex) {return list.set(index, element);} + synchronized (mutex) {return list.set(index, element);} } public void add(int index, E element) { - synchronized(mutex) {list.add(index, element);} + synchronized (mutex) {list.add(index, element);} } public E remove(int index) { - synchronized(mutex) {return list.remove(index);} + synchronized (mutex) {return list.remove(index);} } public int indexOf(Object o) { - synchronized(mutex) {return list.indexOf(o);} + synchronized (mutex) {return list.indexOf(o);} } public int lastIndexOf(Object o) { - synchronized(mutex) {return list.lastIndexOf(o);} + synchronized (mutex) {return list.lastIndexOf(o);} } public boolean addAll(int index, Collection<? extends E> c) { - synchronized(mutex) {return list.addAll(index, c);} + synchronized (mutex) {return list.addAll(index, c);} } public ListIterator<E> listIterator() { @@ -1902,7 +1902,7 @@ } public List<E> subList(int fromIndex, int toIndex) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedList<E>(list.subList(fromIndex, toIndex), mutex); } @@ -1943,7 +1943,7 @@ } public List<E> subList(int fromIndex, int toIndex) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedRandomAccessList<E>( list.subList(fromIndex, toIndex), mutex); } @@ -1975,7 +1975,7 @@ * ... * Set s = m.keySet(); // Needn't be in synchronized block * ... - * synchronized(m) { // Synchronizing on m, not s! + * synchronized (m) { // Synchronizing on m, not s! * Iterator i = s.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); @@ -2016,32 +2016,32 @@ } public int size() { - synchronized(mutex) {return m.size();} + synchronized (mutex) {return m.size();} } public boolean isEmpty() { - synchronized(mutex) {return m.isEmpty();} + synchronized (mutex) {return m.isEmpty();} } public boolean containsKey(Object key) { - synchronized(mutex) {return m.containsKey(key);} + synchronized (mutex) {return m.containsKey(key);} } public boolean containsValue(Object value) { - synchronized(mutex) {return m.containsValue(value);} + synchronized (mutex) {return m.containsValue(value);} } public V get(Object key) { - synchronized(mutex) {return m.get(key);} + synchronized (mutex) {return m.get(key);} } public V put(K key, V value) { - synchronized(mutex) {return m.put(key, value);} + synchronized (mutex) {return m.put(key, value);} } public V remove(Object key) { - synchronized(mutex) {return m.remove(key);} + synchronized (mutex) {return m.remove(key);} } public void putAll(Map<? extends K, ? extends V> map) { - synchronized(mutex) {m.putAll(map);} + synchronized (mutex) {m.putAll(map);} } public void clear() { - synchronized(mutex) {m.clear();} + synchronized (mutex) {m.clear();} } private transient Set<K> keySet = null; @@ -2049,7 +2049,7 @@ private transient Collection<V> values = null; public Set<K> keySet() { - synchronized(mutex) { + synchronized (mutex) { if (keySet==null) keySet = new SynchronizedSet<K>(m.keySet(), mutex); return keySet; @@ -2057,7 +2057,7 @@ } public Set<Map.Entry<K,V>> entrySet() { - synchronized(mutex) { + synchronized (mutex) { if (entrySet==null) entrySet = new SynchronizedSet<Map.Entry<K,V>>(m.entrySet(), mutex); return entrySet; @@ -2065,7 +2065,7 @@ } public Collection<V> values() { - synchronized(mutex) { + synchronized (mutex) { if (values==null) values = new SynchronizedCollection<V>(m.values(), mutex); return values; @@ -2073,16 +2073,16 @@ } public boolean equals(Object o) { - synchronized(mutex) {return m.equals(o);} + synchronized (mutex) {return m.equals(o);} } public int hashCode() { - synchronized(mutex) {return m.hashCode();} + synchronized (mutex) {return m.hashCode();} } public String toString() { - synchronized(mutex) {return m.toString();} + synchronized (mutex) {return m.toString();} } private void writeObject(ObjectOutputStream s) throws IOException { - synchronized(mutex) {s.defaultWriteObject();} + synchronized (mutex) {s.defaultWriteObject();} } } @@ -2101,7 +2101,7 @@ * ... * Set s = m.keySet(); // Needn't be in synchronized block * ... - * synchronized(m) { // Synchronizing on m, not s! + * synchronized (m) { // Synchronizing on m, not s! * Iterator i = s.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); @@ -2114,7 +2114,7 @@ * ... * Set s2 = m2.keySet(); // Needn't be in synchronized block * ... - * synchronized(m) { // Synchronizing on m, not m2 or s2! + * synchronized (m) { // Synchronizing on m, not m2 or s2! * Iterator i = s.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); @@ -2154,31 +2154,31 @@ } public Comparator<? super K> comparator() { - synchronized(mutex) {return sm.comparator();} + synchronized (mutex) {return sm.comparator();} } public SortedMap<K,V> subMap(K fromKey, K toKey) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedMap<K,V>( sm.subMap(fromKey, toKey), mutex); } } public SortedMap<K,V> headMap(K toKey) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedMap<K,V>(sm.headMap(toKey), mutex); } } public SortedMap<K,V> tailMap(K fromKey) { - synchronized(mutex) { + synchronized (mutex) { return new SynchronizedSortedMap<K,V>(sm.tailMap(fromKey),mutex); } } public K firstKey() { - synchronized(mutex) {return sm.firstKey();} + synchronized (mutex) {return sm.firstKey();} } public K lastKey() { - synchronized(mutex) {return sm.lastKey();} + synchronized (mutex) {return sm.lastKey();} } } @@ -3317,7 +3317,7 @@ { private static final long serialVersionUID = 3193687207550431679L; - final private E element; + private final E element; SingletonSet(E e) {element = e;} @@ -3448,7 +3448,7 @@ * @param o the element to appear repeatedly in the returned list. * @return an immutable list consisting of <tt>n</tt> copies of the * specified object. - * @throws IllegalArgumentException if n < 0. + * @throws IllegalArgumentException if {@code n < 0} * @see List#addAll(Collection) * @see List#addAll(int, Collection) */
--- a/jdk/src/share/classes/java/util/ComparableTimSort.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/ComparableTimSort.java Mon Dec 13 16:25:26 2010 -0800 @@ -207,7 +207,7 @@ * @param lo the index of the first element in the range to be sorted * @param hi the index after the last element in the range to be sorted * @param start the index of the first element in the range that is - * not already known to be sorted (@code lo <= start <= hi} + * not already known to be sorted ({@code lo <= start <= hi}) */ @SuppressWarnings("fallthrough") private static void binarySort(Object[] a, int lo, int hi, int start) { @@ -245,7 +245,7 @@ */ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case - switch(n) { + switch (n) { case 2: a[left + 2] = a[left + 1]; case 1: a[left + 1] = a[left]; break; @@ -275,7 +275,7 @@ * @param a the array in which a run is to be counted and possibly reversed * @param lo index of the first element in the run * @param hi index after the last element that may be contained in the run. - It is required that @code{lo < hi}. + It is required that {@code lo < hi}. * @return the length of the run beginning at the specified position in * the specified array */ @@ -288,7 +288,7 @@ // Find end of run, and reverse range if descending if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending - while(runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0) + while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0) runHi++; reverseRange(a, lo, runHi); } else { // Ascending
--- a/jdk/src/share/classes/java/util/FormattableFlags.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/FormattableFlags.java Mon Dec 13 16:25:26 2010 -0800 @@ -59,10 +59,10 @@ * <pre> * out.toUpperCase() </pre> * - * <p> This flag corresponds to <tt>'^'</tt> (<tt>'\u005e'</tt>) in + * <p> This flag corresponds to <tt>'S'</tt> (<tt>'\u0053'</tt>) in * the format specifier. */ - public static final int UPPERCASE = 1<<1; // '^' + public static final int UPPERCASE = 1<<1; // 'S' /** * Requires the output to use an alternate form. The definition of the
--- a/jdk/src/share/classes/java/util/Random.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/Random.java Mon Dec 13 16:25:26 2010 -0800 @@ -77,9 +77,9 @@ */ private final AtomicLong seed; - private final static long multiplier = 0x5DEECE66DL; - private final static long addend = 0xBL; - private final static long mask = (1L << 48) - 1; + private static final long multiplier = 0x5DEECE66DL; + private static final long addend = 0xBL; + private static final long mask = (1L << 48) - 1; /** * Creates a new random number generator. This constructor sets @@ -285,7 +285,7 @@ * @return the next pseudorandom, uniformly distributed {@code int} * value between {@code 0} (inclusive) and {@code n} (exclusive) * from this random number generator's sequence - * @exception IllegalArgumentException if n is not positive + * @throws IllegalArgumentException if n is not positive * @since 1.2 */
--- a/jdk/src/share/classes/java/util/Stack.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/Stack.java Mon Dec 13 16:25:26 2010 -0800 @@ -73,9 +73,9 @@ * Removes the object at the top of this stack and returns that * object as the value of this function. * - * @return The object at the top of this stack (the last item - * of the <tt>Vector</tt> object). - * @exception EmptyStackException if this stack is empty. + * @return The object at the top of this stack (the last item + * of the <tt>Vector</tt> object). + * @throws EmptyStackException if this stack is empty. */ public synchronized E pop() { E obj; @@ -91,9 +91,9 @@ * Looks at the object at the top of this stack without removing it * from the stack. * - * @return the object at the top of this stack (the last item - * of the <tt>Vector</tt> object). - * @exception EmptyStackException if this stack is empty. + * @return the object at the top of this stack (the last item + * of the <tt>Vector</tt> object). + * @throws EmptyStackException if this stack is empty. */ public synchronized E peek() { int len = size();
--- a/jdk/src/share/classes/java/util/TimSort.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/TimSort.java Mon Dec 13 16:25:26 2010 -0800 @@ -239,7 +239,7 @@ * @param lo the index of the first element in the range to be sorted * @param hi the index after the last element in the range to be sorted * @param start the index of the first element in the range that is - * not already known to be sorted (@code lo <= start <= hi} + * not already known to be sorted ({@code lo <= start <= hi}) * @param c comparator to used for the sort */ @SuppressWarnings("fallthrough") @@ -278,7 +278,7 @@ */ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case - switch(n) { + switch (n) { case 2: a[left + 2] = a[left + 1]; case 1: a[left + 1] = a[left]; break; @@ -308,7 +308,7 @@ * @param a the array in which a run is to be counted and possibly reversed * @param lo index of the first element in the run * @param hi index after the last element that may be contained in the run. - It is required that @code{lo < hi}. + It is required that {@code lo < hi}. * @param c the comparator to used for the sort * @return the length of the run beginning at the specified position in * the specified array @@ -322,7 +322,7 @@ // Find end of run, and reverse range if descending if (c.compare(a[runHi++], a[lo]) < 0) { // Descending - while(runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) + while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) runHi++; reverseRange(a, lo, runHi); } else { // Ascending
--- a/jdk/src/share/classes/java/util/TreeMap.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/TreeMap.java Mon Dec 13 16:25:26 2010 -0800 @@ -1056,11 +1056,11 @@ public Comparator<? super E> comparator() { return m.comparator(); } public E pollFirst() { Map.Entry<E,Object> e = m.pollFirstEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public E pollLast() { Map.Entry<E,Object> e = m.pollLastEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public boolean remove(Object o) { int oldSize = size(); @@ -1196,7 +1196,7 @@ * Test two values for equality. Differs from o1.equals(o2) only in * that it copes with {@code null} o1 properly. */ - final static boolean valEquals(Object o1, Object o2) { + static final boolean valEquals(Object o1, Object o2) { return (o1==null ? o2==null : o1.equals(o2)); } @@ -1204,7 +1204,7 @@ * Return SimpleImmutableEntry for entry, or null if null */ static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) { - return e == null? null : + return (e == null) ? null : new AbstractMap.SimpleImmutableEntry<K,V>(e); } @@ -1212,7 +1212,7 @@ * Return key for entry, or null if null */ static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) { - return e == null? null : e.key; + return (e == null) ? null : e.key; } /** @@ -1237,7 +1237,7 @@ /** * @serial include */ - static abstract class NavigableSubMap<K,V> extends AbstractMap<K,V> + abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, java.io.Serializable { /** * The backing map. @@ -1412,11 +1412,11 @@ } public final V get(Object key) { - return !inRange(key)? null : m.get(key); + return !inRange(key) ? null : m.get(key); } public final V remove(Object key) { - return !inRange(key)? null : m.remove(key); + return !inRange(key) ? null : m.remove(key); } public final Map.Entry<K,V> ceilingEntry(K key) { @@ -1559,7 +1559,8 @@ if (!inRange(key)) return false; TreeMap.Entry<K,V> node = m.getEntry(key); - if (node!=null && valEquals(node.getValue(),entry.getValue())){ + if (node!=null && valEquals(node.getValue(), + entry.getValue())) { m.deleteEntry(node); return true; } @@ -1724,7 +1725,7 @@ false, toKey, inclusive); } - public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive){ + public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new AscendingSubMap(m, @@ -1805,7 +1806,7 @@ toEnd, hi, hiInclusive); } - public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive){ + public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) { if (!inRange(fromKey, inclusive)) throw new IllegalArgumentException("fromKey out of range"); return new DescendingSubMap(m, @@ -2143,7 +2144,7 @@ // If strictly internal, copy successor's element to p and then make p // point to successor. if (p.left != null && p.right != null) { - Entry<K,V> s = successor (p); + Entry<K,V> s = successor(p); p.key = s.key; p.value = s.value; p = s;
--- a/jdk/src/share/classes/java/util/TreeSet.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/TreeSet.java Mon Dec 13 16:25:26 2010 -0800 @@ -452,7 +452,7 @@ */ public E pollFirst() { Map.Entry<E,?> e = m.pollFirstEntry(); - return (e == null)? null : e.getKey(); + return (e == null) ? null : e.getKey(); } /** @@ -460,7 +460,7 @@ */ public E pollLast() { Map.Entry<E,?> e = m.pollLastEntry(); - return (e == null)? null : e.getKey(); + return (e == null) ? null : e.getKey(); } /**
--- a/jdk/src/share/classes/java/util/Vector.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/Vector.java Mon Dec 13 16:25:26 2010 -0800 @@ -919,7 +919,7 @@ * elements (optional), or if the specified collection is null * @since 1.2 */ - public synchronized boolean retainAll(Collection<?> c) { + public synchronized boolean retainAll(Collection<?> c) { return super.retainAll(c); }
--- a/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/AbstractExecutorService.java Mon Dec 13 16:25:26 2010 -0800 @@ -51,20 +51,20 @@ * <p> <b>Extension example</b>. Here is a sketch of a class * that customizes {@link ThreadPoolExecutor} to use * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>: - * <pre> + * <pre> {@code * public class CustomThreadPoolExecutor extends ThreadPoolExecutor { * - * static class CustomTask<V> implements RunnableFuture<V> {...} + * static class CustomTask<V> implements RunnableFuture<V> {...} * - * protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) { - * return new CustomTask<V>(c); + * protected <V> RunnableFuture<V> newTaskFor(Callable<V> c) { + * return new CustomTask<V>(c); * } - * protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) { - * return new CustomTask<V>(r, v); + * protected <V> RunnableFuture<V> newTaskFor(Runnable r, V v) { + * return new CustomTask<V>(r, v); * } * // ... add constructors, etc. - * } - * </pre> + * }}</pre> + * * @since 1.5 * @author Doug Lea */ @@ -106,7 +106,7 @@ */ public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); - RunnableFuture<Object> ftask = newTaskFor(task, null); + RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } @@ -158,7 +158,7 @@ // Record exceptions so that if we fail to obtain any // result, we can throw the last exception we got. ExecutionException ee = null; - long lastTime = (timed)? System.nanoTime() : 0; + long lastTime = timed ? System.nanoTime() : 0; Iterator<? extends Callable<T>> it = tasks.iterator(); // Start one task for sure; the rest incrementally @@ -191,8 +191,6 @@ --active; try { return f.get(); - } catch (InterruptedException ie) { - throw ie; } catch (ExecutionException eex) { ee = eex; } catch (RuntimeException rex) {
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Mon Dec 13 16:25:26 2010 -0800 @@ -1270,7 +1270,7 @@ * for each key-value mapping, followed by a null pair. * The key-value mappings are emitted in no particular order. */ - private void writeObject(java.io.ObjectOutputStream s) throws IOException { + private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); for (int k = 0; k < segments.length; ++k) { @@ -1298,7 +1298,7 @@ * @param s the stream */ private void readObject(java.io.ObjectInputStream s) - throws IOException, ClassNotFoundException { + throws IOException, ClassNotFoundException { s.defaultReadObject(); // Initialize each segment to be minimally sized, and let grow.
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java Mon Dec 13 16:25:26 2010 -0800 @@ -38,7 +38,6 @@ import java.util.AbstractCollection; import java.util.ArrayList; import java.util.Collection; -import java.util.ConcurrentModificationException; import java.util.Deque; import java.util.Iterator; import java.util.NoSuchElementException; @@ -212,7 +211,7 @@ * The actual representation we use is that p.next == p means to * goto the first node (which in turn is reached by following prev * pointers from head), and p.next == null && p.prev == p means - * that the iteration is at an end and that p is a (final static) + * that the iteration is at an end and that p is a (static final) * dummy node, NEXT_TERMINATOR, and not the last active node. * Finishing the iteration when encountering such a TERMINATOR is * good enough for read-only traversals, so such traversals can use @@ -271,7 +270,7 @@ */ private transient volatile Node<E> tail; - private final static Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR; + private static final Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR; static { PREV_TERMINATOR = new Node<Object>(null); @@ -401,7 +400,7 @@ } } - private final static int HOPS = 2; + private static final int HOPS = 2; /** * Unlinks non-null node x. @@ -871,7 +870,7 @@ /** * Inserts the specified element at the front of this deque. * - * @throws NullPointerException {@inheritDoc} + * @throws NullPointerException if the specified element is null */ public void addFirst(E e) { linkFirst(e); @@ -882,7 +881,7 @@ * * <p>This method is equivalent to {@link #add}. * - * @throws NullPointerException {@inheritDoc} + * @throws NullPointerException if the specified element is null */ public void addLast(E e) { linkLast(e); @@ -892,7 +891,7 @@ * Inserts the specified element at the front of this deque. * * @return {@code true} always - * @throws NullPointerException {@inheritDoc} + * @throws NullPointerException if the specified element is null */ public boolean offerFirst(E e) { linkFirst(e); @@ -905,7 +904,7 @@ * <p>This method is equivalent to {@link #add}. * * @return {@code true} always - * @throws NullPointerException {@inheritDoc} + * @throws NullPointerException if the specified element is null */ public boolean offerLast(E e) { linkLast(e); @@ -940,7 +939,7 @@ /** * @throws NoSuchElementException {@inheritDoc} */ - public E getLast() { + public E getLast() { return screenNullResult(peekLast()); } @@ -1016,7 +1015,7 @@ * * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element - * @throws NullPointerException if the specified element is {@code null} + * @throws NullPointerException if the specified element is null */ public boolean removeFirstOccurrence(Object o) { checkNotNull(o); @@ -1037,7 +1036,7 @@ * * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element - * @throws NullPointerException if the specified element is {@code null} + * @throws NullPointerException if the specified element is null */ public boolean removeLastOccurrence(Object o) { checkNotNull(o); @@ -1110,7 +1109,7 @@ * * @param o element to be removed from this deque, if present * @return {@code true} if the deque contained the specified element - * @throws NullPointerException if the specified element is {@code null} + * @throws NullPointerException if the specified element is null */ public boolean remove(Object o) { return removeFirstOccurrence(o); @@ -1165,7 +1164,7 @@ beginningOfTheEnd.lazySetPrev(p); // CAS piggyback if (p.casNext(null, beginningOfTheEnd)) { // Successful CAS is the linearization point - // for all elements to be added to this queue. + // for all elements to be added to this deque. if (!casTail(t, last)) { // Try a little harder to update tail, // since we may be adding many elements. @@ -1251,12 +1250,12 @@ * Returns an iterator over the elements in this deque in proper sequence. * The elements will be returned in order from first (head) to last (tail). * - * <p>The returned {@code Iterator} is a "weakly consistent" iterator that + * <p>The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this deque in proper sequence */ @@ -1269,12 +1268,12 @@ * sequential order. The elements will be returned in order from * last (tail) to first (head). * - * <p>The returned {@code Iterator} is a "weakly consistent" iterator that + * <p>The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this deque in reverse order */
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java Mon Dec 13 16:25:26 2010 -0800 @@ -65,8 +65,8 @@ * <p>Iterators are <i>weakly consistent</i>, returning elements * reflecting the state of the queue at some point at or since the * creation of the iterator. They do <em>not</em> throw {@link - * ConcurrentModificationException}, and may proceed concurrently with - * other operations. Elements contained in the queue since the creation + * java.util.ConcurrentModificationException}, and may proceed concurrently + * with other operations. Elements contained in the queue since the creation * of the iterator will be returned exactly once. * * <p>Beware that, unlike in most collections, the {@code size} method @@ -634,12 +634,12 @@ * Returns an iterator over the elements in this queue in proper sequence. * The elements will be returned in order from first (head) to last (tail). * - * <p>The returned {@code Iterator} is a "weakly consistent" iterator that + * <p>The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue in proper sequence */
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentSkipListSet.java Mon Dec 13 16:25:26 2010 -0800 @@ -362,12 +362,12 @@ public E pollFirst() { Map.Entry<E,Object> e = m.pollFirstEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); } public E pollLast() { Map.Entry<E,Object> e = m.pollLastEntry(); - return e == null? null : e.getKey(); + return (e == null) ? null : e.getKey(); }
--- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArrayList.java Mon Dec 13 16:25:26 2010 -0800 @@ -547,7 +547,7 @@ * @param fromIndex index of first element to be removed * @param toIndex index after last element to be removed * @throws IndexOutOfBoundsException if fromIndex or toIndex out of range - * (@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) + * ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex}) */ private void removeRange(int fromIndex, int toIndex) { final ReentrantLock lock = this.lock; @@ -989,7 +989,7 @@ } private static class COWIterator<E> implements ListIterator<E> { - /** Snapshot of the array **/ + /** Snapshot of the array */ private final Object[] snapshot; /** Index of element to be returned by subsequent call to next. */ private int cursor;
--- a/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/CopyOnWriteArraySet.java Mon Dec 13 16:25:26 2010 -0800 @@ -59,24 +59,23 @@ * copy-on-write set to maintain a set of Handler objects that * perform some action upon state updates. * - * <pre> + * <pre> {@code * class Handler { void handle(); ... } * * class X { - * private final CopyOnWriteArraySet<Handler> handlers - * = new CopyOnWriteArraySet<Handler>(); - * public void addHandler(Handler h) { handlers.add(h); } + * private final CopyOnWriteArraySet<Handler> handlers + * = new CopyOnWriteArraySet<Handler>(); + * public void addHandler(Handler h) { handlers.add(h); } * - * private long internalState; - * private synchronized void changeState() { internalState = ...; } + * private long internalState; + * private synchronized void changeState() { internalState = ...; } * - * public void update() { - * changeState(); - * for (Handler handler : handlers) - * handler.handle(); - * } - * } - * </pre> + * public void update() { + * changeState(); + * for (Handler handler : handlers) + * handler.handle(); + * } + * }}</pre> * * <p>This class is a member of the * <a href="{@docRoot}/../technotes/guides/collections/index.html">
--- a/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/CountDownLatch.java Mon Dec 13 16:25:26 2010 -0800 @@ -175,7 +175,7 @@ } protected int tryAcquireShared(int acquires) { - return getState() == 0? 1 : -1; + return (getState() == 0) ? 1 : -1; } protected boolean tryReleaseShared(int releases) {
--- a/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/DelayQueue.java Mon Dec 13 16:25:26 2010 -0800 @@ -482,12 +482,14 @@ /** * Returns an iterator over all the elements (both expired and * unexpired) in this queue. The iterator does not return the - * elements in any particular order. The returned - * <tt>Iterator</tt> is a "weakly consistent" iterator that will - * never throw {@link ConcurrentModificationException}, and - * guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed - * to) reflect any modifications subsequent to construction. + * elements in any particular order. + * + * <p>The returned iterator is a "weakly consistent" iterator that + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this queue */
--- a/jdk/src/share/classes/java/util/concurrent/Exchanger.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/Exchanger.java Mon Dec 13 16:25:26 2010 -0800 @@ -355,7 +355,9 @@ else if (y == null && // Try to occupy slot.compareAndSet(null, me)) { if (index == 0) // Blocking wait for slot 0 - return timed? awaitNanos(me, slot, nanos): await(me, slot); + return timed ? + awaitNanos(me, slot, nanos) : + await(me, slot); Object v = spinWait(me, slot); // Spin wait for non-0 if (v != CANCEL) return v; @@ -597,8 +599,8 @@ * dormant until one of two things happens: * <ul> * <li>Some other thread enters the exchange; or - * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current - * thread. + * <li>Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread. * </ul> * <p>If the current thread: * <ul> @@ -616,7 +618,7 @@ */ public V exchange(V x) throws InterruptedException { if (!Thread.interrupted()) { - Object v = doExchange(x == null? NULL_ITEM : x, false, 0); + Object v = doExchange((x == null) ? NULL_ITEM : x, false, 0); if (v == NULL_ITEM) return null; if (v != CANCEL) @@ -671,7 +673,7 @@ public V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException { if (!Thread.interrupted()) { - Object v = doExchange(x == null? NULL_ITEM : x, + Object v = doExchange((x == null) ? NULL_ITEM : x, true, unit.toNanos(timeout)); if (v == NULL_ITEM) return null;
--- a/jdk/src/share/classes/java/util/concurrent/Executor.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/Executor.java Mon Dec 13 16:25:26 2010 -0800 @@ -79,37 +79,37 @@ * serializes the submission of tasks to a second executor, * illustrating a composite executor. * - * <pre> + * <pre> {@code * class SerialExecutor implements Executor { - * final Queue<Runnable> tasks = new ArrayDeque<Runnable>(); - * final Executor executor; - * Runnable active; + * final Queue<Runnable> tasks = new ArrayDeque<Runnable>(); + * final Executor executor; + * Runnable active; * - * SerialExecutor(Executor executor) { - * this.executor = executor; + * SerialExecutor(Executor executor) { + * this.executor = executor; + * } + * + * public synchronized void execute(final Runnable r) { + * tasks.offer(new Runnable() { + * public void run() { + * try { + * r.run(); + * } finally { + * scheduleNext(); + * } + * } + * }); + * if (active == null) { + * scheduleNext(); * } + * } * - * public synchronized void execute(final Runnable r) { - * tasks.offer(new Runnable() { - * public void run() { - * try { - * r.run(); - * } finally { - * scheduleNext(); - * } - * } - * }); - * if (active == null) { - * scheduleNext(); - * } + * protected synchronized void scheduleNext() { + * if ((active = tasks.poll()) != null) { + * executor.execute(active); * } - * - * protected synchronized void scheduleNext() { - * if ((active = tasks.poll()) != null) { - * executor.execute(active); - * } - * } - * }</pre> + * } + * }}</pre> * * The <tt>Executor</tt> implementations provided in this package * implement {@link ExecutorService}, which is a more extensive
--- a/jdk/src/share/classes/java/util/concurrent/ExecutorCompletionService.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ExecutorCompletionService.java Mon Dec 13 16:25:26 2010 -0800 @@ -197,7 +197,8 @@ return completionQueue.poll(); } - public Future<V> poll(long timeout, TimeUnit unit) throws InterruptedException { + public Future<V> poll(long timeout, TimeUnit unit) + throws InterruptedException { return completionQueue.poll(timeout, unit); }
--- a/jdk/src/share/classes/java/util/concurrent/Executors.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/Executors.java Mon Dec 13 16:25:26 2010 -0800 @@ -83,7 +83,7 @@ * * @param nThreads the number of threads in the pool * @return the newly created thread pool - * @throws IllegalArgumentException if <tt>nThreads <= 0</tt> + * @throws IllegalArgumentException if {@code nThreads <= 0} */ public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, @@ -108,7 +108,7 @@ * @param threadFactory the factory to use when creating new threads * @return the newly created thread pool * @throws NullPointerException if threadFactory is null - * @throws IllegalArgumentException if <tt>nThreads <= 0</tt> + * @throws IllegalArgumentException if {@code nThreads <= 0} */ public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, @@ -242,7 +242,7 @@ * @param corePoolSize the number of threads to keep in the pool, * even if they are idle. * @return a newly created scheduled thread pool - * @throws IllegalArgumentException if <tt>corePoolSize < 0</tt> + * @throws IllegalArgumentException if {@code corePoolSize < 0} */ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); @@ -256,7 +256,7 @@ * @param threadFactory the factory to use when the executor * creates a new thread. * @return a newly created scheduled thread pool - * @throws IllegalArgumentException if <tt>corePoolSize < 0</tt> + * @throws IllegalArgumentException if {@code corePoolSize < 0} * @throws NullPointerException if threadFactory is null */ public static ScheduledExecutorService newScheduledThreadPool( @@ -562,8 +562,8 @@ DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); - group = (s != null)? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); + group = (s != null) ? s.getThreadGroup() : + Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; @@ -669,7 +669,7 @@ FinalizableDelegatedExecutorService(ExecutorService executor) { super(executor); } - protected void finalize() { + protected void finalize() { super.shutdown(); } }
--- a/jdk/src/share/classes/java/util/concurrent/Future.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/Future.java Mon Dec 13 16:25:26 2010 -0800 @@ -47,21 +47,21 @@ * computation has completed, the computation cannot be cancelled. * If you would like to use a <tt>Future</tt> for the sake * of cancellability but not provide a usable result, you can - * declare types of the form <tt>Future<?></tt> and + * declare types of the form {@code Future<?>} and * return <tt>null</tt> as a result of the underlying task. * * <p> * <b>Sample Usage</b> (Note that the following classes are all * made-up.) <p> - * <pre> + * <pre> {@code * interface ArchiveSearcher { String search(String target); } * class App { * ExecutorService executor = ... * ArchiveSearcher searcher = ... * void showSearch(final String target) * throws InterruptedException { - * Future<String> future - * = executor.submit(new Callable<String>() { + * Future<String> future + * = executor.submit(new Callable<String>() { * public String call() { * return searcher.search(target); * }}); @@ -70,20 +70,18 @@ * displayText(future.get()); // use future * } catch (ExecutionException ex) { cleanup(); return; } * } - * } - * </pre> + * }}</pre> * * The {@link FutureTask} class is an implementation of <tt>Future</tt> that * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>. * For example, the above construction with <tt>submit</tt> could be replaced by: - * <pre> - * FutureTask<String> future = - * new FutureTask<String>(new Callable<String>() { + * <pre> {@code + * FutureTask<String> future = + * new FutureTask<String>(new Callable<String>() { * public String call() { * return searcher.search(target); * }}); - * executor.execute(future); - * </pre> + * executor.execute(future);}</pre> * * <p>Memory consistency effects: Actions taken by the asynchronous computation * <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
--- a/jdk/src/share/classes/java/util/concurrent/FutureTask.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/FutureTask.java Mon Dec 13 16:25:26 2010 -0800 @@ -85,7 +85,7 @@ * @param result the result to return on successful completion. If * you don't need a particular result, consider using * constructions of the form: - * <tt>Future<?> f = new FutureTask<Object>(runnable, null)</tt> + * {@code Future<?> f = new FutureTask<Void>(runnable, null)} * @throws NullPointerException if runnable is null */ public FutureTask(Runnable runnable, V result) {
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java Mon Dec 13 16:25:26 2010 -0800 @@ -1004,12 +1004,13 @@ /** * Returns an iterator over the elements in this deque in proper sequence. * The elements will be returned in order from first (head) to last (tail). - * The returned {@code Iterator} is a "weakly consistent" iterator that + * + * <p>The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. * * @return an iterator over the elements in this deque in proper sequence */ @@ -1021,12 +1022,13 @@ * Returns an iterator over the elements in this deque in reverse * sequential order. The elements will be returned in order from * last (tail) to first (head). - * The returned {@code Iterator} is a "weakly consistent" iterator that + * + * <p>The returned iterator is a "weakly consistent" iterator that * will never throw {@link java.util.ConcurrentModificationException - * ConcurrentModificationException}, - * and guarantees to traverse elements as they existed upon - * construction of the iterator, and may (but is not guaranteed to) - * reflect any modifications subsequent to construction. + * ConcurrentModificationException}, and guarantees to traverse + * elements as they existed upon construction of the iterator, and + * may (but is not guaranteed to) reflect any modifications + * subsequent to construction. */ public Iterator<E> descendingIterator() { return new DescendingItr();
--- a/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/RecursiveAction.java Mon Dec 13 16:25:26 2010 -0800 @@ -159,7 +159,9 @@ protected abstract void compute(); /** - * Always returns null. + * Always returns {@code null}. + * + * @return {@code null} always */ public final Void getRawResult() { return null; }
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledExecutorService.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ScheduledExecutorService.java Mon Dec 13 16:25:26 2010 -0800 @@ -72,24 +72,23 @@ * Here is a class with a method that sets up a ScheduledExecutorService * to beep every ten seconds for an hour: * - * <pre> + * <pre> {@code * import static java.util.concurrent.TimeUnit.*; * class BeeperControl { - * private final ScheduledExecutorService scheduler = - * Executors.newScheduledThreadPool(1); + * private final ScheduledExecutorService scheduler = + * Executors.newScheduledThreadPool(1); * - * public void beepForAnHour() { - * final Runnable beeper = new Runnable() { - * public void run() { System.out.println("beep"); } - * }; - * final ScheduledFuture<?> beeperHandle = - * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); - * scheduler.schedule(new Runnable() { - * public void run() { beeperHandle.cancel(true); } - * }, 60 * 60, SECONDS); - * } - * } - * </pre> + * public void beepForAnHour() { + * final Runnable beeper = new Runnable() { + * public void run() { System.out.println("beep"); } + * }; + * final ScheduledFuture<?> beeperHandle = + * scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); + * scheduler.schedule(new Runnable() { + * public void run() { beeperHandle.cancel(true); } + * }, 60 * 60, SECONDS); + * } + * }}</pre> * * @since 1.5 * @author Doug Lea
--- a/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java Mon Dec 13 16:25:26 2010 -0800 @@ -62,8 +62,8 @@ * time of cancellation. * * <p>Successive executions of a task scheduled via - * <code>scheduleAtFixedRate</code> or - * <code>scheduleWithFixedDelay</code> do not overlap. While different + * {@code scheduleAtFixedRate} or + * {@code scheduleWithFixedDelay} do not overlap. While different * executions may be performed by different threads, the effects of * prior executions <a * href="package-summary.html#MemoryVisibility"><i>happen-before</i></a> @@ -436,7 +436,7 @@ * @throws NullPointerException if {@code threadFactory} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, - ThreadFactory threadFactory) { + ThreadFactory threadFactory) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), threadFactory); } @@ -453,7 +453,7 @@ * @throws NullPointerException if {@code handler} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, - RejectedExecutionHandler handler) { + RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), handler); } @@ -473,8 +473,8 @@ * {@code handler} is null */ public ScheduledThreadPoolExecutor(int corePoolSize, - ThreadFactory threadFactory, - RejectedExecutionHandler handler) { + ThreadFactory threadFactory, + RejectedExecutionHandler handler) { super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS, new DelayedWorkQueue(), threadFactory, handler); }
--- a/jdk/src/share/classes/java/util/concurrent/Semaphore.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/Semaphore.java Mon Dec 13 16:25:26 2010 -0800 @@ -223,7 +223,7 @@ /** * NonFair version */ - final static class NonfairSync extends Sync { + static final class NonfairSync extends Sync { private static final long serialVersionUID = -2694183684443567898L; NonfairSync(int permits) { @@ -238,7 +238,7 @@ /** * Fair version */ - final static class FairSync extends Sync { + static final class FairSync extends Sync { private static final long serialVersionUID = 2014338818796000944L; FairSync(int permits) { @@ -282,7 +282,7 @@ * else {@code false} */ public Semaphore(int permits, boolean fair) { - sync = (fair)? new FairSync(permits) : new NonfairSync(permits); + sync = fair ? new FairSync(permits) : new NonfairSync(permits); } /**
--- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java Mon Dec 13 16:25:26 2010 -0800 @@ -63,9 +63,9 @@ */ public class ThreadLocalRandom extends Random { // same constants as Random, but must be redeclared because private - private final static long multiplier = 0x5DEECE66DL; - private final static long addend = 0xBL; - private final static long mask = (1L << 48) - 1; + private static final long multiplier = 0x5DEECE66DL; + private static final long addend = 0xBL; + private static final long mask = (1L << 48) - 1; /** * The random seed. We can't use super.seed.
--- a/jdk/src/share/classes/java/util/concurrent/TimeUnit.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/TimeUnit.java Mon Dec 13 16:25:26 2010 -0800 @@ -53,12 +53,12 @@ * java.util.concurrent.locks.Lock lock} is not available: * * <pre> Lock lock = ...; - * if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ... + * if (lock.tryLock(50L, TimeUnit.MILLISECONDS)) ... * </pre> * while this code will timeout in 50 seconds: * <pre> * Lock lock = ...; - * if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ... + * if (lock.tryLock(50L, TimeUnit.SECONDS)) ... * </pre> * * Note however, that there is no guarantee that a particular timeout @@ -291,7 +291,8 @@ abstract int excessNanos(long d, long m); /** - * Performs a timed <tt>Object.wait</tt> using this time unit. + * Performs a timed {@link Object#wait(long, int) Object.wait} + * using this time unit. * This is a convenience method that converts timeout arguments * into the form required by the <tt>Object.wait</tt> method. * @@ -299,21 +300,22 @@ * method (see {@link BlockingQueue#poll BlockingQueue.poll}) * using: * - * <pre> public synchronized Object poll(long timeout, TimeUnit unit) throws InterruptedException { - * while (empty) { - * unit.timedWait(this, timeout); - * ... - * } - * }</pre> + * <pre> {@code + * public synchronized Object poll(long timeout, TimeUnit unit) + * throws InterruptedException { + * while (empty) { + * unit.timedWait(this, timeout); + * ... + * } + * }}</pre> * * @param obj the object to wait on * @param timeout the maximum time to wait. If less than * or equal to zero, do not wait at all. - * @throws InterruptedException if interrupted while waiting. - * @see Object#wait(long, int) + * @throws InterruptedException if interrupted while waiting */ public void timedWait(Object obj, long timeout) - throws InterruptedException { + throws InterruptedException { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); @@ -322,17 +324,18 @@ } /** - * Performs a timed <tt>Thread.join</tt> using this time unit. + * Performs a timed {@link Thread#join(long, int) Thread.join} + * using this time unit. * This is a convenience method that converts time arguments into the * form required by the <tt>Thread.join</tt> method. + * * @param thread the thread to wait for * @param timeout the maximum time to wait. If less than * or equal to zero, do not wait at all. - * @throws InterruptedException if interrupted while waiting. - * @see Thread#join(long, int) + * @throws InterruptedException if interrupted while waiting */ public void timedJoin(Thread thread, long timeout) - throws InterruptedException { + throws InterruptedException { if (timeout > 0) { long ms = toMillis(timeout); int ns = excessNanos(timeout, ms); @@ -341,13 +344,14 @@ } /** - * Performs a <tt>Thread.sleep</tt> using this unit. + * Performs a {@link Thread#sleep(long, int) Thread.sleep} using + * this time unit. * This is a convenience method that converts time arguments into the * form required by the <tt>Thread.sleep</tt> method. + * * @param timeout the minimum time to sleep. If less than * or equal to zero, do not sleep at all. - * @throws InterruptedException if interrupted while sleeping. - * @see Thread#sleep + * @throws InterruptedException if interrupted while sleeping */ public void sleep(long timeout) throws InterruptedException { if (timeout > 0) {
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java Mon Dec 13 16:25:26 2010 -0800 @@ -55,7 +55,7 @@ * @author Doug Lea * @param <T> The type of the object holding the updatable field */ -public abstract class AtomicIntegerFieldUpdater<T> { +public abstract class AtomicIntegerFieldUpdater<T> { /** * Creates and returns an updater for objects with the given field. * The Class argument is needed to check that reflective types and @@ -279,7 +279,7 @@ sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } catch(Exception ex) { + } catch (Exception ex) { throw new RuntimeException(ex); }
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java Mon Dec 13 16:25:26 2010 -0800 @@ -55,7 +55,7 @@ * @author Doug Lea * @param <T> The type of the object holding the updatable field */ -public abstract class AtomicLongFieldUpdater<T> { +public abstract class AtomicLongFieldUpdater<T> { /** * Creates and returns an updater for objects with the given field. * The Class argument is needed to check that reflective types and @@ -278,7 +278,7 @@ sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } catch(Exception ex) { + } catch (Exception ex) { throw new RuntimeException(ex); } @@ -331,7 +331,7 @@ if (cclass.isInstance(obj)) { return; } - throw new RuntimeException ( + throw new RuntimeException( new IllegalAccessException("Class " + cclass.getName() + " can not access a protected member of class " + @@ -361,7 +361,7 @@ sun.reflect.misc.ReflectUtil.ensureMemberAccess( caller, tclass, null, modifiers); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); - } catch(Exception ex) { + } catch (Exception ex) { throw new RuntimeException(ex); } @@ -387,7 +387,7 @@ public boolean compareAndSet(T obj, long expect, long update) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); - synchronized(this) { + synchronized (this) { long v = unsafe.getLong(obj, offset); if (v != expect) return false; @@ -402,7 +402,7 @@ public void set(T obj, long newValue) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); - synchronized(this) { + synchronized (this) { unsafe.putLong(obj, offset, newValue); } } @@ -413,7 +413,7 @@ public long get(T obj) { if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); - synchronized(this) { + synchronized (this) { return unsafe.getLong(obj, offset); } } @@ -422,7 +422,7 @@ if (cclass.isInstance(obj)) { return; } - throw new RuntimeException ( + throw new RuntimeException( new IllegalAccessException("Class " + cclass.getName() + " can not access a protected member of class " +
--- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java Mon Dec 13 16:25:26 2010 -0800 @@ -45,13 +45,13 @@ * independently subject to atomic updates. For example, a tree node * might be declared as * - * <pre> + * <pre> {@code * class Node { * private volatile Node left, right; * - * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater = + * private static final AtomicReferenceFieldUpdater<Node, Node> leftUpdater = * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "left"); - * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = + * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); * * Node getLeft() { return left; } @@ -59,8 +59,7 @@ * return leftUpdater.compareAndSet(this, expect, update); * } * // ... and so on - * } - * </pre> + * }}</pre> * * <p>Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. @@ -74,7 +73,7 @@ * @param <T> The type of the object holding the updatable field * @param <V> The type of the field */ -public abstract class AtomicReferenceFieldUpdater<T, V> { +public abstract class AtomicReferenceFieldUpdater<T, V> { /** * Creates and returns an updater for objects with the given field. @@ -291,7 +290,7 @@ if (cclass.isInstance(obj)) { return; } - throw new RuntimeException ( + throw new RuntimeException( new IllegalAccessException("Class " + cclass.getName() + " can not access a protected member of class " +
--- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java Mon Dec 13 16:25:26 2010 -0800 @@ -990,7 +990,8 @@ * can represent anything you like. * @throws InterruptedException if the current thread is interrupted */ - public final void acquireInterruptibly(long arg) throws InterruptedException { + public final void acquireInterruptibly(long arg) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) @@ -1014,7 +1015,8 @@ * @return {@code true} if acquired; {@code false} if timed out * @throws InterruptedException if the current thread is interrupted */ - public final boolean tryAcquireNanos(long arg, long nanosTimeout) throws InterruptedException { + public final boolean tryAcquireNanos(long arg, long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquire(arg) || @@ -1070,7 +1072,8 @@ * you like. * @throws InterruptedException if the current thread is interrupted */ - public final void acquireSharedInterruptibly(long arg) throws InterruptedException { + public final void acquireSharedInterruptibly(long arg) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) @@ -1093,7 +1096,8 @@ * @return {@code true} if acquired; {@code false} if timed out * @throws InterruptedException if the current thread is interrupted */ - public final boolean tryAcquireSharedNanos(long arg, long nanosTimeout) throws InterruptedException { + public final boolean tryAcquireSharedNanos(long arg, long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquireShared(arg) >= 0 || @@ -1841,7 +1845,8 @@ * <li> If interrupted while blocked in step 4, throw InterruptedException. * </ol> */ - public final long awaitNanos(long nanosTimeout) throws InterruptedException { + public final long awaitNanos(long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); @@ -1885,7 +1890,8 @@ * <li> If timed out while blocked in step 4, return false, else true. * </ol> */ - public final boolean awaitUntil(Date deadline) throws InterruptedException { + public final boolean awaitUntil(Date deadline) + throws InterruptedException { if (deadline == null) throw new NullPointerException(); long abstime = deadline.getTime(); @@ -1928,7 +1934,8 @@ * <li> If timed out while blocked in step 4, return false, else true. * </ol> */ - public final boolean await(long time, TimeUnit unit) throws InterruptedException { + public final boolean await(long time, TimeUnit unit) + throws InterruptedException { if (unit == null) throw new NullPointerException(); long nanosTimeout = unit.toNanos(time); @@ -2084,7 +2091,7 @@ /** * CAS waitStatus field of a node. */ - private final static boolean compareAndSetWaitStatus(Node node, + private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) { return unsafe.compareAndSwapInt(node, waitStatusOffset, @@ -2094,7 +2101,7 @@ /** * CAS next field of a node. */ - private final static boolean compareAndSetNext(Node node, + private static final boolean compareAndSetNext(Node node, Node expect, Node update) { return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
--- a/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java Mon Dec 13 16:25:26 2010 -0800 @@ -265,7 +265,7 @@ * boolean isSignalled() { return getState() != 0; } * * protected int tryAcquireShared(int ignore) { - * return isSignalled()? 1 : -1; + * return isSignalled() ? 1 : -1; * } * * protected boolean tryReleaseShared(int ignore) { @@ -1213,7 +1213,8 @@ * can represent anything you like. * @throws InterruptedException if the current thread is interrupted */ - public final void acquireInterruptibly(int arg) throws InterruptedException { + public final void acquireInterruptibly(int arg) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (!tryAcquire(arg)) @@ -1237,7 +1238,8 @@ * @return {@code true} if acquired; {@code false} if timed out * @throws InterruptedException if the current thread is interrupted */ - public final boolean tryAcquireNanos(int arg, long nanosTimeout) throws InterruptedException { + public final boolean tryAcquireNanos(int arg, long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquire(arg) || @@ -1293,7 +1295,8 @@ * you like. * @throws InterruptedException if the current thread is interrupted */ - public final void acquireSharedInterruptibly(int arg) throws InterruptedException { + public final void acquireSharedInterruptibly(int arg) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); if (tryAcquireShared(arg) < 0) @@ -1316,7 +1319,8 @@ * @return {@code true} if acquired; {@code false} if timed out * @throws InterruptedException if the current thread is interrupted */ - public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) throws InterruptedException { + public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); return tryAcquireShared(arg) >= 0 || @@ -2062,7 +2066,8 @@ * <li> If interrupted while blocked in step 4, throw InterruptedException. * </ol> */ - public final long awaitNanos(long nanosTimeout) throws InterruptedException { + public final long awaitNanos(long nanosTimeout) + throws InterruptedException { if (Thread.interrupted()) throw new InterruptedException(); Node node = addConditionWaiter(); @@ -2106,7 +2111,8 @@ * <li> If timed out while blocked in step 4, return false, else true. * </ol> */ - public final boolean awaitUntil(Date deadline) throws InterruptedException { + public final boolean awaitUntil(Date deadline) + throws InterruptedException { if (deadline == null) throw new NullPointerException(); long abstime = deadline.getTime(); @@ -2149,7 +2155,8 @@ * <li> If timed out while blocked in step 4, return false, else true. * </ol> */ - public final boolean await(long time, TimeUnit unit) throws InterruptedException { + public final boolean await(long time, TimeUnit unit) + throws InterruptedException { if (unit == null) throw new NullPointerException(); long nanosTimeout = unit.toNanos(time); @@ -2305,7 +2312,7 @@ /** * CAS waitStatus field of a node. */ - private final static boolean compareAndSetWaitStatus(Node node, + private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) { return unsafe.compareAndSwapInt(node, waitStatusOffset, @@ -2315,7 +2322,7 @@ /** * CAS next field of a node. */ - private final static boolean compareAndSetNext(Node node, + private static final boolean compareAndSetNext(Node node, Node expect, Node update) { return unsafe.compareAndSwapObject(node, nextOffset, expect, update);
--- a/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/LockSupport.java Mon Dec 13 16:25:26 2010 -0800 @@ -200,8 +200,8 @@ * <li>Some other thread invokes {@link #unpark unpark} with the * current thread as the target; or * - * <li>Some other thread {@linkplain Thread#interrupt interrupts} the current - * thread; or + * <li>Some other thread {@linkplain Thread#interrupt interrupts} + * the current thread; or * * <li>The specified waiting time elapses; or *
--- a/jdk/src/share/classes/java/util/concurrent/locks/ReentrantLock.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/ReentrantLock.java Mon Dec 13 16:25:26 2010 -0800 @@ -116,7 +116,7 @@ * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */ - static abstract class Sync extends AbstractQueuedSynchronizer { + abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = -5179523762034025860L; /** @@ -200,7 +200,7 @@ /** * Sync object for non-fair locks */ - final static class NonfairSync extends Sync { + static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; /** @@ -222,7 +222,7 @@ /** * Sync object for fair locks */ - final static class FairSync extends Sync { + static final class FairSync extends Sync { private static final long serialVersionUID = -3000897897090466540L; final void lock() { @@ -269,7 +269,7 @@ * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { - sync = (fair)? new FairSync() : new NonfairSync(); + sync = fair ? new FairSync() : new NonfairSync(); } /** @@ -440,7 +440,8 @@ * @throws NullPointerException if the time unit is null * */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); }
--- a/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java Mon Dec 13 16:25:26 2010 -0800 @@ -155,7 +155,7 @@ * } * // Downgrade by acquiring read lock before releasing write lock * rwl.readLock().lock(); - * } finally { + * } finally { * rwl.writeLock().unlock(); // Unlock write, still hold read * } * } @@ -215,7 +215,8 @@ * @author Doug Lea * */ -public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable { +public class ReentrantReadWriteLock + implements ReadWriteLock, java.io.Serializable { private static final long serialVersionUID = -6992448646407690164L; /** Inner class providing readlock */ private final ReentrantReadWriteLock.ReadLock readerLock; @@ -251,7 +252,7 @@ * Synchronization implementation for ReentrantReadWriteLock. * Subclassed into fair and nonfair versions. */ - static abstract class Sync extends AbstractQueuedSynchronizer { + abstract static class Sync extends AbstractQueuedSynchronizer { private static final long serialVersionUID = 6317671515068378041L; /* @@ -618,7 +619,7 @@ final Thread getOwner() { // Must read state before owner to ensure memory consistency - return ((exclusiveCount(getState()) == 0)? + return ((exclusiveCount(getState()) == 0) ? null : getExclusiveOwnerThread()); } @@ -669,7 +670,7 @@ /** * Nonfair version of Sync */ - final static class NonfairSync extends Sync { + static final class NonfairSync extends Sync { private static final long serialVersionUID = -8159625535654395037L; final boolean writerShouldBlock() { return false; // writers can always barge @@ -689,7 +690,7 @@ /** * Fair version of Sync */ - final static class FairSync extends Sync { + static final class FairSync extends Sync { private static final long serialVersionUID = -2274990926593161451L; final boolean writerShouldBlock() { return hasQueuedPredecessors(); @@ -702,7 +703,7 @@ /** * The lock returned by method {@link ReentrantReadWriteLock#readLock}. */ - public static class ReadLock implements Lock, java.io.Serializable { + public static class ReadLock implements Lock, java.io.Serializable { private static final long serialVersionUID = -5992448646407690164L; private final Sync sync; @@ -867,7 +868,8 @@ * @throws NullPointerException if the time unit is null * */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException { return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout)); } @@ -908,7 +910,7 @@ /** * The lock returned by method {@link ReentrantReadWriteLock#writeLock}. */ - public static class WriteLock implements Lock, java.io.Serializable { + public static class WriteLock implements Lock, java.io.Serializable { private static final long serialVersionUID = -4992448646407690164L; private final Sync sync; @@ -1108,7 +1110,8 @@ * @throws NullPointerException if the time unit is null * */ - public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException { + public boolean tryLock(long timeout, TimeUnit unit) + throws InterruptedException { return sync.tryAcquireNanos(1, unit.toNanos(timeout)); }
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/java/util/zip/ZipFile.java Mon Dec 13 16:25:26 2010 -0800 @@ -315,7 +315,7 @@ private static native void freeEntry(long jzfile, long jzentry); // the outstanding inputstreams that need to be closed. - private Set<ZipFileInputStream> streams = new HashSet<ZipFileInputStream>(); + private Set<InputStream> streams = new HashSet<>(); /** * Returns an input stream for reading the contents of the specified @@ -348,55 +348,58 @@ return null; } in = new ZipFileInputStream(jzentry); - streams.add(in); - } - final ZipFileInputStream zfin = in; - switch (getEntryMethod(jzentry)) { - case STORED: - return zfin; - case DEFLATED: - // MORE: Compute good size for inflater stream: - long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack - if (size > 65536) size = 8192; - if (size <= 0) size = 4096; - return new InflaterInputStream(zfin, getInflater(), (int)size) { - private boolean isClosed = false; - public void close() throws IOException { - if (!isClosed) { - releaseInflater(inf); - this.in.close(); - isClosed = true; + switch (getEntryMethod(jzentry)) { + case STORED: + streams.add(in); + return in; + case DEFLATED: + final ZipFileInputStream zfin = in; + // MORE: Compute good size for inflater stream: + long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack + if (size > 65536) size = 8192; + if (size <= 0) size = 4096; + InputStream is = new InflaterInputStream(zfin, getInflater(), (int)size) { + private boolean isClosed = false; + + public void close() throws IOException { + if (!isClosed) { + super.close(); + releaseInflater(inf); + isClosed = true; + } } - } - // Override fill() method to provide an extra "dummy" byte - // at the end of the input stream. This is required when - // using the "nowrap" Inflater option. - protected void fill() throws IOException { - if (eof) { - throw new EOFException( - "Unexpected end of ZLIB input stream"); + // Override fill() method to provide an extra "dummy" byte + // at the end of the input stream. This is required when + // using the "nowrap" Inflater option. + protected void fill() throws IOException { + if (eof) { + throw new EOFException( + "Unexpected end of ZLIB input stream"); + } + len = this.in.read(buf, 0, buf.length); + if (len == -1) { + buf[0] = 0; + len = 1; + eof = true; + } + inf.setInput(buf, 0, len); } - len = this.in.read(buf, 0, buf.length); - if (len == -1) { - buf[0] = 0; - len = 1; - eof = true; + private boolean eof; + + public int available() throws IOException { + if (isClosed) + return 0; + long avail = zfin.size() - inf.getBytesWritten(); + return avail > (long) Integer.MAX_VALUE ? + Integer.MAX_VALUE : (int) avail; } - inf.setInput(buf, 0, len); - } - private boolean eof; - - public int available() throws IOException { - if (isClosed) - return 0; - long avail = zfin.size() - inf.getBytesWritten(); - return avail > (long) Integer.MAX_VALUE ? - Integer.MAX_VALUE : (int) avail; - } - }; - default: - throw new ZipException("invalid compression method"); + }; + streams.add(is); + return is; + default: + throw new ZipException("invalid compression method"); + } } } @@ -539,9 +542,9 @@ closeRequested = true; if (streams.size() !=0) { - Set<ZipFileInputStream> copy = streams; - streams = new HashSet<ZipFileInputStream>(); - for (ZipFileInputStream is: copy) + Set<InputStream> copy = streams; + streams = new HashSet<InputStream>(); + for (InputStream is: copy) is.close(); }
--- a/jdk/src/share/classes/javax/sql/rowset/serial/SerialBlob.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/javax/sql/rowset/serial/SerialBlob.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, 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 @@ -166,8 +166,9 @@ length = (int)len; } - if (pos < 1 || length - pos < 0 ) { - throw new SerialException("Invalid arguments: position cannot be less that 1"); + if (pos < 1 || len - pos < 0 ) { + throw new SerialException("Invalid arguments: position cannot be " + + "less than 1 or greater than the length of the SerialBlob"); } pos--; // correct pos to array index
--- a/jdk/src/share/classes/sun/misc/FpUtils.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/misc/FpUtils.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010 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 @@ -29,9 +29,9 @@ import sun.misc.DoubleConsts; /** - * The class <code>FpUtils</code> contains static utility methods for - * manipulating and inspecting <code>float</code> and - * <code>double</code> floating-point numbers. These methods include + * The class {@code FpUtils} contains static utility methods for + * manipulating and inspecting {@code float} and + * {@code double} floating-point numbers. These methods include * functionality recommended or required by the IEEE 754 * floating-point standard. * @@ -136,7 +136,7 @@ // tests for exception cases. /** - * Returns unbiased exponent of a <code>double</code>. + * Returns unbiased exponent of a {@code double}. */ public static int getExponent(double d){ /* @@ -149,7 +149,7 @@ } /** - * Returns unbiased exponent of a <code>float</code>. + * Returns unbiased exponent of a {@code float}. */ public static int getExponent(float f){ /* @@ -185,15 +185,15 @@ * Returns the first floating-point argument with the sign of the * second floating-point argument. Note that unlike the {@link * FpUtils#copySign(double, double) copySign} method, this method - * does not require NaN <code>sign</code> arguments to be treated + * does not require NaN {@code sign} arguments to be treated * as positive values; implementations are permitted to treat some * NaN arguments as positive and other NaN arguments as negative * to allow greater performance. * * @param magnitude the parameter providing the magnitude of the result * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of <code>magnitude</code> - * and the sign of <code>sign</code>. + * @return a value with the magnitude of {@code magnitude} + * and the sign of {@code sign}. * @author Joseph D. Darcy */ public static double rawCopySign(double magnitude, double sign) { @@ -208,15 +208,15 @@ * Returns the first floating-point argument with the sign of the * second floating-point argument. Note that unlike the {@link * FpUtils#copySign(float, float) copySign} method, this method - * does not require NaN <code>sign</code> arguments to be treated + * does not require NaN {@code sign} arguments to be treated * as positive values; implementations are permitted to treat some * NaN arguments as positive and other NaN arguments as negative * to allow greater performance. * * @param magnitude the parameter providing the magnitude of the result * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of <code>magnitude</code> - * and the sign of <code>sign</code>. + * @return a value with the magnitude of {@code magnitude} + * and the sign of {@code sign}. * @author Joseph D. Darcy */ public static float rawCopySign(float magnitude, float sign) { @@ -230,129 +230,129 @@ /* ***************************************************************** */ /** - * Returns <code>true</code> if the argument is a finite - * floating-point value; returns <code>false</code> otherwise (for + * Returns {@code true} if the argument is a finite + * floating-point value; returns {@code false} otherwise (for * NaN and infinity arguments). * - * @param d the <code>double</code> value to be tested - * @return <code>true</code> if the argument is a finite - * floating-point value, <code>false</code> otherwise. + * @param d the {@code double} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. */ public static boolean isFinite(double d) { return Math.abs(d) <= DoubleConsts.MAX_VALUE; } /** - * Returns <code>true</code> if the argument is a finite - * floating-point value; returns <code>false</code> otherwise (for + * Returns {@code true} if the argument is a finite + * floating-point value; returns {@code false} otherwise (for * NaN and infinity arguments). * - * @param f the <code>float</code> value to be tested - * @return <code>true</code> if the argument is a finite - * floating-point value, <code>false</code> otherwise. + * @param f the {@code float} value to be tested + * @return {@code true} if the argument is a finite + * floating-point value, {@code false} otherwise. */ public static boolean isFinite(float f) { return Math.abs(f) <= FloatConsts.MAX_VALUE; } /** - * Returns <code>true</code> if the specified number is infinitely - * large in magnitude, <code>false</code> otherwise. + * Returns {@code true} if the specified number is infinitely + * large in magnitude, {@code false} otherwise. * * <p>Note that this method is equivalent to the {@link * Double#isInfinite(double) Double.isInfinite} method; the * functionality is included in this class for convenience. * * @param d the value to be tested. - * @return <code>true</code> if the value of the argument is positive - * infinity or negative infinity; <code>false</code> otherwise. + * @return {@code true} if the value of the argument is positive + * infinity or negative infinity; {@code false} otherwise. */ public static boolean isInfinite(double d) { return Double.isInfinite(d); } /** - * Returns <code>true</code> if the specified number is infinitely - * large in magnitude, <code>false</code> otherwise. + * Returns {@code true} if the specified number is infinitely + * large in magnitude, {@code false} otherwise. * * <p>Note that this method is equivalent to the {@link * Float#isInfinite(float) Float.isInfinite} method; the * functionality is included in this class for convenience. * * @param f the value to be tested. - * @return <code>true</code> if the argument is positive infinity or - * negative infinity; <code>false</code> otherwise. + * @return {@code true} if the argument is positive infinity or + * negative infinity; {@code false} otherwise. */ public static boolean isInfinite(float f) { return Float.isInfinite(f); } /** - * Returns <code>true</code> if the specified number is a - * Not-a-Number (NaN) value, <code>false</code> otherwise. + * Returns {@code true} if the specified number is a + * Not-a-Number (NaN) value, {@code false} otherwise. * * <p>Note that this method is equivalent to the {@link * Double#isNaN(double) Double.isNaN} method; the functionality is * included in this class for convenience. * * @param d the value to be tested. - * @return <code>true</code> if the value of the argument is NaN; - * <code>false</code> otherwise. + * @return {@code true} if the value of the argument is NaN; + * {@code false} otherwise. */ public static boolean isNaN(double d) { return Double.isNaN(d); } /** - * Returns <code>true</code> if the specified number is a - * Not-a-Number (NaN) value, <code>false</code> otherwise. + * Returns {@code true} if the specified number is a + * Not-a-Number (NaN) value, {@code false} otherwise. * * <p>Note that this method is equivalent to the {@link * Float#isNaN(float) Float.isNaN} method; the functionality is * included in this class for convenience. * * @param f the value to be tested. - * @return <code>true</code> if the argument is NaN; - * <code>false</code> otherwise. + * @return {@code true} if the argument is NaN; + * {@code false} otherwise. */ public static boolean isNaN(float f) { return Float.isNaN(f); } /** - * Returns <code>true</code> if the unordered relation holds + * Returns {@code true} if the unordered relation holds * between the two arguments. When two floating-point values are * unordered, one value is neither less than, equal to, nor * greater than the other. For the unordered relation to be true, - * at least one argument must be a <code>NaN</code>. + * at least one argument must be a {@code NaN}. * * @param arg1 the first argument * @param arg2 the second argument - * @return <code>true</code> if at least one argument is a NaN, - * <code>false</code> otherwise. + * @return {@code true} if at least one argument is a NaN, + * {@code false} otherwise. */ public static boolean isUnordered(double arg1, double arg2) { return isNaN(arg1) || isNaN(arg2); } /** - * Returns <code>true</code> if the unordered relation holds + * Returns {@code true} if the unordered relation holds * between the two arguments. When two floating-point values are * unordered, one value is neither less than, equal to, nor * greater than the other. For the unordered relation to be true, - * at least one argument must be a <code>NaN</code>. + * at least one argument must be a {@code NaN}. * * @param arg1 the first argument * @param arg2 the second argument - * @return <code>true</code> if at least one argument is a NaN, - * <code>false</code> otherwise. + * @return {@code true} if at least one argument is a NaN, + * {@code false} otherwise. */ public static boolean isUnordered(float arg1, float arg2) { return isNaN(arg1) || isNaN(arg2); } /** - * Returns unbiased exponent of a <code>double</code>; for + * Returns unbiased exponent of a {@code double}; for * subnormal values, the number is treated as if it were * normalized. That is for all finite, non-zero, positive numbers * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is @@ -378,7 +378,6 @@ return (1<<30); // 2^30 else // infinite value return (1<<28); // 2^28 - // break; case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal if(d == 0.0) { @@ -414,18 +413,16 @@ exponent < DoubleConsts.MIN_EXPONENT); return exponent; } - // break; default: assert( exponent >= DoubleConsts.MIN_EXPONENT && exponent <= DoubleConsts.MAX_EXPONENT); return exponent; - // break; } } /** - * Returns unbiased exponent of a <code>float</code>; for + * Returns unbiased exponent of a {@code float}; for * subnormal values, the number is treated as if it were * normalized. That is for all finite, non-zero, positive numbers * <i>x</i>, <code>scalb(<i>x</i>, -ilogb(<i>x</i>))</code> is @@ -451,7 +448,6 @@ return (1<<30); // 2^30 else // infinite value return (1<<28); // 2^28 - // break; case FloatConsts.MIN_EXPONENT-1: // zero or subnormal if(f == 0.0f) { @@ -487,13 +483,11 @@ exponent < FloatConsts.MIN_EXPONENT); return exponent; } - // break; default: assert( exponent >= FloatConsts.MIN_EXPONENT && exponent <= FloatConsts.MAX_EXPONENT); return exponent; - // break; } } @@ -534,22 +528,22 @@ */ /** - * Return <code>d</code> × - * 2<sup><code>scale_factor</code></sup> rounded as if performed + * Return {@code d} × + * 2<sup>{@code scale_factor}</sup> rounded as if performed * by a single correctly rounded floating-point multiply to a * member of the double value set. See <a * href="http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#9208">§4.2.3</a> * of the <a href="http://java.sun.com/docs/books/jls/html/">Java * Language Specification</a> for a discussion of floating-point * value sets. If the exponent of the result is between the - * <code>double</code>'s minimum exponent and maximum exponent, + * {@code double}'s minimum exponent and maximum exponent, * the answer is calculated exactly. If the exponent of the - * result would be larger than <code>doubles</code>'s maximum + * result would be larger than {@code doubles}'s maximum * exponent, an infinity is returned. Note that if the result is - * subnormal, precision may be lost; that is, when <code>scalb(x, - * n)</code> is subnormal, <code>scalb(scalb(x, n), -n)</code> may + * subnormal, precision may be lost; that is, when {@code scalb(x, + * n)} is subnormal, {@code scalb(scalb(x, n), -n)} may * not equal <i>x</i>. When the result is non-NaN, the result has - * the same sign as <code>d</code>. + * the same sign as {@code d}. * *<p> * Special cases: @@ -562,8 +556,8 @@ * </ul> * * @param d number to be scaled by a power of two. - * @param scale_factor power of 2 used to scale <code>d</code> - * @return <code>d * </code>2<sup><code>scale_factor</code></sup> + * @param scale_factor power of 2 used to scale {@code d} + * @return {@code d * }2<sup>{@code scale_factor}</sup> * @author Joseph D. Darcy */ public static double scalb(double d, int scale_factor) { @@ -644,22 +638,22 @@ } /** - * Return <code>f </code>× - * 2<sup><code>scale_factor</code></sup> rounded as if performed + * Return {@code f} × + * 2<sup>{@code scale_factor}</sup> rounded as if performed * by a single correctly rounded floating-point multiply to a * member of the float value set. See <a * href="http://java.sun.com/docs/books/jls/second_edition/html/typesValues.doc.html#9208">§4.2.3</a> * of the <a href="http://java.sun.com/docs/books/jls/html/">Java * Language Specification</a> for a discussion of floating-point * value set. If the exponent of the result is between the - * <code>float</code>'s minimum exponent and maximum exponent, the + * {@code float}'s minimum exponent and maximum exponent, the * answer is calculated exactly. If the exponent of the result - * would be larger than <code>float</code>'s maximum exponent, an + * would be larger than {@code float}'s maximum exponent, an * infinity is returned. Note that if the result is subnormal, - * precision may be lost; that is, when <code>scalb(x, n)</code> - * is subnormal, <code>scalb(scalb(x, n), -n)</code> may not equal + * precision may be lost; that is, when {@code scalb(x, n)} + * is subnormal, {@code scalb(scalb(x, n), -n)} may not equal * <i>x</i>. When the result is non-NaN, the result has the same - * sign as <code>f</code>. + * sign as {@code f}. * *<p> * Special cases: @@ -672,8 +666,8 @@ * </ul> * * @param f number to be scaled by a power of two. - * @param scale_factor power of 2 used to scale <code>f</code> - * @return <code>f * </code>2<sup><code>scale_factor</code></sup> + * @param scale_factor power of 2 used to scale {@code f} + * @return {@code f * }2<sup>{@code scale_factor}</sup> * @author Joseph D. Darcy */ public static float scalb(float f, int scale_factor) { @@ -709,34 +703,34 @@ * <ul> * <li> If either argument is a NaN, then NaN is returned. * - * <li> If both arguments are signed zeros, <code>direction</code> + * <li> If both arguments are signed zeros, {@code direction} * is returned unchanged (as implied by the requirement of * returning the second argument if the arguments compare as * equal). * - * <li> If <code>start</code> is - * ±<code>Double.MIN_VALUE</code> and <code>direction</code> + * <li> If {@code start} is + * ±{@code Double.MIN_VALUE} and {@code direction} * has a value such that the result should have a smaller - * magnitude, then a zero with the same sign as <code>start</code> + * magnitude, then a zero with the same sign as {@code start} * is returned. * - * <li> If <code>start</code> is infinite and - * <code>direction</code> has a value such that the result should - * have a smaller magnitude, <code>Double.MAX_VALUE</code> with the - * same sign as <code>start</code> is returned. + * <li> If {@code start} is infinite and + * {@code direction} has a value such that the result should + * have a smaller magnitude, {@code Double.MAX_VALUE} with the + * same sign as {@code start} is returned. * - * <li> If <code>start</code> is equal to ± - * <code>Double.MAX_VALUE</code> and <code>direction</code> has a + * <li> If {@code start} is equal to ± + * {@code Double.MAX_VALUE} and {@code direction} has a * value such that the result should have a larger magnitude, an - * infinity with same sign as <code>start</code> is returned. + * infinity with same sign as {@code start} is returned. * </ul> * * @param start starting floating-point value * @param direction value indicating which of - * <code>start</code>'s neighbors or <code>start</code> should + * {@code start}'s neighbors or {@code start} should * be returned - * @return The floating-point number adjacent to <code>start</code> in the - * direction of <code>direction</code>. + * @return The floating-point number adjacent to {@code start} in the + * direction of {@code direction}. * @author Joseph D. Darcy */ public static double nextAfter(double start, double direction) { @@ -809,34 +803,34 @@ * <ul> * <li> If either argument is a NaN, then NaN is returned. * - * <li> If both arguments are signed zeros, a <code>float</code> - * zero with the same sign as <code>direction</code> is returned + * <li> If both arguments are signed zeros, a {@code float} + * zero with the same sign as {@code direction} is returned * (as implied by the requirement of returning the second argument * if the arguments compare as equal). * - * <li> If <code>start</code> is - * ±<code>Float.MIN_VALUE</code> and <code>direction</code> + * <li> If {@code start} is + * ±{@code Float.MIN_VALUE} and {@code direction} * has a value such that the result should have a smaller - * magnitude, then a zero with the same sign as <code>start</code> + * magnitude, then a zero with the same sign as {@code start} * is returned. * - * <li> If <code>start</code> is infinite and - * <code>direction</code> has a value such that the result should - * have a smaller magnitude, <code>Float.MAX_VALUE</code> with the - * same sign as <code>start</code> is returned. + * <li> If {@code start} is infinite and + * {@code direction} has a value such that the result should + * have a smaller magnitude, {@code Float.MAX_VALUE} with the + * same sign as {@code start} is returned. * - * <li> If <code>start</code> is equal to ± - * <code>Float.MAX_VALUE</code> and <code>direction</code> has a + * <li> If {@code start} is equal to ± + * {@code Float.MAX_VALUE} and {@code direction} has a * value such that the result should have a larger magnitude, an - * infinity with same sign as <code>start</code> is returned. + * infinity with same sign as {@code start} is returned. * </ul> * * @param start starting floating-point value * @param direction value indicating which of - * <code>start</code>'s neighbors or <code>start</code> should + * {@code start}'s neighbors or {@code start} should * be returned - * @return The floating-point number adjacent to <code>start</code> in the - * direction of <code>direction</code>. + * @return The floating-point number adjacent to {@code start} in the + * direction of {@code direction}. * @author Joseph D. Darcy */ public static float nextAfter(float start, double direction) { @@ -900,12 +894,12 @@ } /** - * Returns the floating-point value adjacent to <code>d</code> in + * Returns the floating-point value adjacent to {@code d} in * the direction of positive infinity. This method is - * semantically equivalent to <code>nextAfter(d, - * Double.POSITIVE_INFINITY)</code>; however, a <code>nextUp</code> + * semantically equivalent to {@code nextAfter(d, + * Double.POSITIVE_INFINITY)}; however, a {@code nextUp} * implementation may run faster than its equivalent - * <code>nextAfter</code> call. + * {@code nextAfter} call. * * <p>Special Cases: * <ul> @@ -915,7 +909,7 @@ * positive infinity. * * <li> If the argument is zero, the result is - * <code>Double.MIN_VALUE</code> + * {@code Double.MIN_VALUE} * * </ul> * @@ -935,12 +929,12 @@ } /** - * Returns the floating-point value adjacent to <code>f</code> in + * Returns the floating-point value adjacent to {@code f} in * the direction of positive infinity. This method is - * semantically equivalent to <code>nextAfter(f, - * Double.POSITIVE_INFINITY)</code>; however, a <code>nextUp</code> + * semantically equivalent to {@code nextAfter(f, + * Double.POSITIVE_INFINITY)}; however, a {@code nextUp} * implementation may run faster than its equivalent - * <code>nextAfter</code> call. + * {@code nextAfter} call. * * <p>Special Cases: * <ul> @@ -950,7 +944,7 @@ * positive infinity. * * <li> If the argument is zero, the result is - * <code>Float.MIN_VALUE</code> + * {@code Float.MIN_VALUE} * * </ul> * @@ -970,12 +964,12 @@ } /** - * Returns the floating-point value adjacent to <code>d</code> in + * Returns the floating-point value adjacent to {@code d} in * the direction of negative infinity. This method is - * semantically equivalent to <code>nextAfter(d, - * Double.NEGATIVE_INFINITY)</code>; however, a - * <code>nextDown</code> implementation may run faster than its - * equivalent <code>nextAfter</code> call. + * semantically equivalent to {@code nextAfter(d, + * Double.NEGATIVE_INFINITY)}; however, a + * {@code nextDown} implementation may run faster than its + * equivalent {@code nextAfter} call. * * <p>Special Cases: * <ul> @@ -985,7 +979,7 @@ * negative infinity. * * <li> If the argument is zero, the result is - * <code>-Double.MIN_VALUE</code> + * {@code -Double.MIN_VALUE} * * </ul> * @@ -1007,12 +1001,12 @@ } /** - * Returns the floating-point value adjacent to <code>f</code> in + * Returns the floating-point value adjacent to {@code f} in * the direction of negative infinity. This method is - * semantically equivalent to <code>nextAfter(f, - * Float.NEGATIVE_INFINITY)</code>; however, a - * <code>nextDown</code> implementation may run faster than its - * equivalent <code>nextAfter</code> call. + * semantically equivalent to {@code nextAfter(f, + * Float.NEGATIVE_INFINITY)}; however, a + * {@code nextDown} implementation may run faster than its + * equivalent {@code nextAfter} call. * * <p>Special Cases: * <ul> @@ -1022,7 +1016,7 @@ * negative infinity. * * <li> If the argument is zero, the result is - * <code>-Float.MIN_VALUE</code> + * {@code -Float.MIN_VALUE} * * </ul> * @@ -1046,13 +1040,13 @@ /** * Returns the first floating-point argument with the sign of the * second floating-point argument. For this method, a NaN - * <code>sign</code> argument is always treated as if it were + * {@code sign} argument is always treated as if it were * positive. * * @param magnitude the parameter providing the magnitude of the result * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of <code>magnitude</code> - * and the sign of <code>sign</code>. + * @return a value with the magnitude of {@code magnitude} + * and the sign of {@code sign}. * @author Joseph D. Darcy * @since 1.5 */ @@ -1063,13 +1057,13 @@ /** * Returns the first floating-point argument with the sign of the * second floating-point argument. For this method, a NaN - * <code>sign</code> argument is always treated as if it were + * {@code sign} argument is always treated as if it were * positive. * * @param magnitude the parameter providing the magnitude of the result * @param sign the parameter providing the sign of the result - * @return a value with the magnitude of <code>magnitude</code> - * and the sign of <code>sign</code>. + * @return a value with the magnitude of {@code magnitude} + * and the sign of {@code sign}. * @author Joseph D. Darcy */ public static float copySign(float magnitude, float sign) { @@ -1078,8 +1072,8 @@ /** * Returns the size of an ulp of the argument. An ulp of a - * <code>double</code> value is the positive distance between this - * floating-point value and the <code>double</code> value next + * {@code double} value is the positive distance between this + * floating-point value and the {@code double} value next * larger in magnitude. Note that for non-NaN <i>x</i>, * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. * @@ -1089,8 +1083,8 @@ * <li> If the argument is positive or negative infinity, then the * result is positive infinity. * <li> If the argument is positive or negative zero, then the result is - * <code>Double.MIN_VALUE</code>. - * <li> If the argument is ±<code>Double.MAX_VALUE</code>, then + * {@code Double.MIN_VALUE}. + * <li> If the argument is ±{@code Double.MAX_VALUE}, then * the result is equal to 2<sup>971</sup>. * </ul> * @@ -1105,11 +1099,9 @@ switch(exp) { case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity return Math.abs(d); - // break; case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal return Double.MIN_VALUE; - // break default: assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT; @@ -1126,14 +1118,13 @@ return Double.longBitsToDouble(1L << (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) )); } - // break } } /** * Returns the size of an ulp of the argument. An ulp of a - * <code>float</code> value is the positive distance between this - * floating-point value and the <code>float</code> value next + * {@code float} value is the positive distance between this + * floating-point value and the {@code float} value next * larger in magnitude. Note that for non-NaN <i>x</i>, * <code>ulp(-<i>x</i>) == ulp(<i>x</i>)</code>. * @@ -1143,8 +1134,8 @@ * <li> If the argument is positive or negative infinity, then the * result is positive infinity. * <li> If the argument is positive or negative zero, then the result is - * <code>Float.MIN_VALUE</code>. - * <li> If the argument is ±<code>Float.MAX_VALUE</code>, then + * {@code Float.MIN_VALUE}. + * <li> If the argument is ±{@code Float.MAX_VALUE}, then * the result is equal to 2<sup>104</sup>. * </ul> * @@ -1159,11 +1150,9 @@ switch(exp) { case FloatConsts.MAX_EXPONENT+1: // NaN or infinity return Math.abs(f); - // break; case FloatConsts.MIN_EXPONENT-1: // zero or subnormal return FloatConsts.MIN_VALUE; - // break default: assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT; @@ -1180,7 +1169,6 @@ return Float.intBitsToFloat(1 << (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) )); } - // break } }
--- a/jdk/src/share/classes/sun/misc/VM.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/misc/VM.java Mon Dec 13 16:25:26 2010 -0800 @@ -25,6 +25,7 @@ package sun.misc; +import static java.lang.Thread.State.*; import java.util.Properties; import java.util.HashMap; import java.util.Map; @@ -332,69 +333,37 @@ } } - + /** + * Returns Thread.State for the given threadStatus + */ public static Thread.State toThreadState(int threadStatus) { - // Initialize the threadStateMap - initThreadStateMap(); - - Thread.State s = threadStateMap.get(threadStatus); - if (s == null) { - // default to RUNNABLE if the threadStatus value is unknown - s = Thread.State.RUNNABLE; + if ((threadStatus & JVMTI_THREAD_STATE_RUNNABLE) != 0) { + return RUNNABLE; + } else if ((threadStatus & JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) != 0) { + return BLOCKED; + } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_INDEFINITELY) != 0) { + return WAITING; + } else if ((threadStatus & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) != 0) { + return TIMED_WAITING; + } else if ((threadStatus & JVMTI_THREAD_STATE_TERMINATED) != 0) { + return TERMINATED; + } else if ((threadStatus & JVMTI_THREAD_STATE_ALIVE) == 0) { + return NEW; + } else { + return RUNNABLE; } - return s; } - // a map of threadStatus values to the corresponding Thread.State - private static Map<Integer, Thread.State> threadStateMap = null; - private static Map<Integer, String> threadStateNames = null; - - private synchronized static void initThreadStateMap() { - if (threadStateMap != null) { - return; - } - - final Thread.State[] ts = Thread.State.values(); - - final int[][] vmThreadStateValues = new int[ts.length][]; - final String[][] vmThreadStateNames = new String[ts.length][]; - getThreadStateValues(vmThreadStateValues, vmThreadStateNames); - - threadStateMap = new HashMap<Integer, Thread.State>(); - threadStateNames = new HashMap<Integer, String>(); - for (int i = 0; i < ts.length; i++) { - String state = ts[i].name(); - int[] values = null; - String[] names = null; - for (int j = 0; j < ts.length; j++) { - if (vmThreadStateNames[j][0].startsWith(state)) { - values = vmThreadStateValues[j]; - names = vmThreadStateNames[j]; - } - } - if (values == null) { - throw new InternalError("No VM thread state mapped to " + - state); - } - if (values.length != names.length) { - throw new InternalError("VM thread state values and names " + - " mapped to " + state + ": length not matched" ); - } - for (int k = 0; k < values.length; k++) { - threadStateMap.put(values[k], ts[i]); - threadStateNames.put(values[k], names[k]); - } - } - } - // Fill in vmThreadStateValues with int arrays, each of which contains - // the threadStatus values mapping to the Thread.State enum constant. - // Fill in vmThreadStateNames with String arrays, each of which contains - // the name of each threadStatus value of the format: - // <Thread.State.name()>[.<Substate name>] - // e.g. WAITING.OBJECT_WAIT - // - private native static void getThreadStateValues(int[][] vmThreadStateValues, - String[][] vmThreadStateNames); + /* The threadStatus field is set by the VM at state transition + * in the hotspot implementation. Its value is set according to + * the JVM TI specification GetThreadState function. + */ + private final static int JVMTI_THREAD_STATE_ALIVE = 0x0001; + private final static int JVMTI_THREAD_STATE_TERMINATED = 0x0002; + private final static int JVMTI_THREAD_STATE_RUNNABLE = 0x0004; + private final static int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400; + private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; + private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; static { initialize();
--- a/jdk/src/share/classes/sun/net/httpserver/Request.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/net/httpserver/Request.java Mon Dec 13 16:25:26 2010 -0800 @@ -129,9 +129,22 @@ hdrs = new Headers(); char s[] = new char[10]; + int len = 0; + int firstc = is.read(); + + // check for empty headers + if (firstc == CR || firstc == LF) { + int c = is.read(); + if (c == CR || c == LF) { + return hdrs; + } + s[0] = (char)firstc; + len = 1; + firstc = c; + } + while (firstc != LF && firstc != CR && firstc >= 0) { - int len = 0; int keyend = -1; int c; boolean inKey = firstc > ' '; @@ -191,6 +204,7 @@ else v = String.copyValueOf(s, keyend, len - keyend); hdrs.add (k,v); + len = 0; } return hdrs; }
--- a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java Mon Dec 13 16:25:26 2010 -0800 @@ -74,8 +74,8 @@ private void configureEngine(HttpsConfigurator cfg, InetSocketAddress addr){ if (cfg != null) { Parameters params = new Parameters (cfg, addr); +//BEGIN_TIGER_EXCLUDE cfg.configure (params); -//BEGIN_TIGER_EXCLUDE SSLParameters sslParams = params.getSSLParameters(); if (sslParams != null) { engine.setSSLParameters (sslParams);
--- a/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java Mon Dec 13 16:25:26 2010 -0800 @@ -42,7 +42,7 @@ static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec. /* These values must be a reasonable multiple of clockTick */ - static final long DEFAULT_IDLE_INTERVAL = 300 ; // 5 min + static final long DEFAULT_IDLE_INTERVAL = 30 ; // 5 min static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ; static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever
--- a/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/nio/ch/FileChannelImpl.java Mon Dec 13 16:25:26 2010 -0800 @@ -39,12 +39,11 @@ public class FileChannelImpl extends FileChannel { + // Memory allocation size for mapping buffers + private static final long allocationGranularity; // Used to make native read and write calls - private static final FileDispatcher nd; - - // Memory allocation size for mapping buffers - private static final long allocationGranularity; + private final FileDispatcher nd; // File descriptor private final FileDescriptor fd; @@ -63,22 +62,29 @@ private final Object positionLock = new Object(); private FileChannelImpl(FileDescriptor fd, boolean readable, - boolean writable, Object parent) + boolean writable, boolean append, Object parent) { this.fd = fd; this.readable = readable; this.writable = writable; this.parent = parent; + this.nd = new FileDispatcherImpl(append); } - // Invoked by getChannel() methods - // of java.io.File{Input,Output}Stream and RandomAccessFile - // + // Used by FileInputStream.getChannel() and RandomAccessFile.getChannel() public static FileChannel open(FileDescriptor fd, boolean readable, boolean writable, Object parent) { - return new FileChannelImpl(fd, readable, writable, parent); + return new FileChannelImpl(fd, readable, writable, false, parent); + } + + // Used by FileOutputStream.getChannel + public static FileChannel open(FileDescriptor fd, + boolean readable, boolean writable, + boolean append, Object parent) + { + return new FileChannelImpl(fd, readable, writable, append, parent); } private void ensureOpen() throws IOException { @@ -704,6 +710,9 @@ private static class Unmapper implements Runnable { + // may be required to close file + private static final NativeDispatcher nd = new FileDispatcherImpl(); + // keep track of mapped buffer usage static volatile int count; static volatile long totalSize; @@ -1119,7 +1128,6 @@ static { Util.load(); allocationGranularity = initIDs(); - nd = new FileDispatcherImpl(); } }
--- a/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Mon Dec 13 16:25:26 2010 -0800 @@ -144,7 +144,7 @@ protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { int mark = src.position(); - if (!doneBOM) { + if (!doneBOM && src.hasRemaining()) { if (dst.remaining() < 4) return CoderResult.OVERFLOW; put(BOM_BIG, dst);
--- a/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Mon Dec 13 16:25:26 2010 -0800 @@ -70,13 +70,12 @@ protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) { int mark = src.position(); - if (needsMark) { + if (needsMark && src.hasRemaining()) { if (dst.remaining() < 2) return CoderResult.OVERFLOW; put(BYTE_ORDER_MARK, dst); needsMark = false; } - try { while (src.hasRemaining()) { char c = src.get();
--- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, 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 @@ -138,13 +138,7 @@ instance.getSeedBytes(result); } - void getSeedBytes(byte[] result) { - for (int i = 0; i < result.length; i++) { - result[i] = getSeedByte(); - } - } - - abstract byte getSeedByte(); + abstract void getSeedBytes(byte[] result); /** * Retrieve some system information, hashed. @@ -369,6 +363,13 @@ } } + @Override + void getSeedBytes(byte[] result) { + for (int i = 0; i < result.length; i++) { + result[i] = getSeedByte(); + } + } + byte getSeedByte() { byte b = 0; @@ -455,8 +456,7 @@ static class URLSeedGenerator extends SeedGenerator { private String deviceName; - private BufferedInputStream devRandom; - + private InputStream devRandom; /** * The constructor is only called once to construct the one @@ -465,7 +465,7 @@ */ URLSeedGenerator(String egdurl) throws IOException { - if (egdurl == null) { + if (egdurl == null) { throw new IOException("No random source specified"); } deviceName = egdurl; @@ -478,41 +478,78 @@ private void init() throws IOException { final URL device = new URL(deviceName); - devRandom = java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction<BufferedInputStream>() { - public BufferedInputStream run() { - try { - return new BufferedInputStream(device.openStream()); - } catch (IOException ioe) { - return null; + try { + devRandom = java.security.AccessController.doPrivileged + (new java.security.PrivilegedExceptionAction<InputStream>() { + public InputStream run() throws IOException { + /* + * return a FileInputStream for file URLs and + * avoid buffering. The openStream() call wraps + * InputStream in a BufferedInputStream which + * can buffer up to 8K bytes. This read is a + * performance issue for entropy sources which + * can be slow to replenish. + */ + if (device.getProtocol().equalsIgnoreCase("file")) { + File deviceFile = getDeviceFile(device); + return new FileInputStream(deviceFile); + } else { + return device.openStream(); } } }); - - if (devRandom == null) { - throw new IOException("failed to open " + device); + } catch (Exception e) { + throw new IOException("Failed to open " + deviceName, e.getCause()); } } - byte getSeedByte() { - byte b[] = new byte[1]; - int stat; + /* + * Use a URI to access this File. Previous code used a URL + * which is less strict on syntax. If we encounter a + * URISyntaxException we make best efforts for backwards + * compatibility. e.g. space character in deviceName string. + * + * Method called within PrivilegedExceptionAction block. + */ + private File getDeviceFile(URL device) throws IOException { try { - stat = devRandom.read(b, 0, b.length); + URI deviceURI = device.toURI(); + if(deviceURI.isOpaque()) { + // File constructor does not accept opaque URI + URI localDir = new File(System.getProperty("user.dir")).toURI(); + String uriPath = localDir.toString() + + deviceURI.toString().substring(5); + return new File(URI.create(uriPath)); + } else { + return new File(deviceURI); + } + } catch (URISyntaxException use) { + /* + * Make best effort to access this File. + * We can try using the URL path. + */ + return new File(device.getPath()); + } + } + + @Override + void getSeedBytes(byte[] result) { + int len = result.length; + int read = 0; + try { + while (read < len) { + int count = devRandom.read(result, read, len - read); + // /dev/random blocks - should never have EOF + if (count < 0) + throw new InternalError("URLSeedGenerator " + deviceName + + " reached end of file"); + read += count; + } } catch (IOException ioe) { throw new InternalError("URLSeedGenerator " + deviceName + " generated exception: " + ioe.getMessage()); } - if (stat == b.length) { - return b[0]; - } else if (stat == -1) { - throw new InternalError("URLSeedGenerator " + deviceName + - " reached end of file"); - } else { - throw new InternalError("URLSeedGenerator " + deviceName + - " failed read"); - } } }
--- a/jdk/src/share/classes/sun/security/rsa/RSASignature.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/rsa/RSASignature.java Mon Dec 13 16:25:26 2010 -0800 @@ -185,6 +185,11 @@ // verify the data and return the result. See JCA doc protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + if (sigBytes.length != RSACore.getByteLength(publicKey)) { + throw new SignatureException("Signature length not correct: got " + + sigBytes.length + " but was expecting " + + RSACore.getByteLength(publicKey)); + } byte[] digest = getDigestValue(); try { byte[] decrypted = RSACore.rsa(sigBytes, publicKey);
--- a/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/ssl/RSAClientKeyExchange.java Mon Dec 13 16:25:26 2010 -0800 @@ -103,7 +103,8 @@ String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ? "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); KeyGenerator kg = JsseJce.getKeyGenerator(s); - kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor)); + kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor), + generator); preMaster = kg.generateKey(); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java Mon Dec 13 16:25:26 2010 -0800 @@ -658,7 +658,9 @@ boolean inScope = (inStoreOrScope & IN_SCOPE) != 0; notSignedByAlias |= (inStoreOrScope & NOT_ALIAS) != 0; - aliasNotInStore |= isSigned && (!inStore && !inScope); + if (keystore != null) { + aliasNotInStore |= isSigned && (!inStore && !inScope); + } // Only used when -verbose provided StringBuffer sb = null; @@ -723,7 +725,7 @@ if (signatureRelated(name)) { // Entries inside META-INF and other unsigned // entries are grouped separately. - label = "-" + label.substring(1); + label = "-" + label; } // The label finally contains 2 parts separated by '|': @@ -752,7 +754,7 @@ List<String> files = s.getValue(); String key = s.getKey(); if (key.charAt(0) == '-') { // the signature-related group - key = ' ' + key.substring(1); + key = key.substring(1); } int pipe = key.indexOf('|'); if (verbose.equals("all")) { @@ -889,7 +891,7 @@ * Note: no newline character at the end */ String printCert(String tab, Certificate c, boolean checkValidityPeriod, - long now) { + long now, boolean checkUsage) { StringBuilder certStr = new StringBuilder(); String space = rb.getString("SPACE"); @@ -959,24 +961,26 @@ } certStr.append("]"); - boolean[] bad = new boolean[3]; - checkCertUsage(x509Cert, bad); - if (bad[0] || bad[1] || bad[2]) { - String x = ""; - if (bad[0]) { - x ="KeyUsage"; - } - if (bad[1]) { - if (x.length() > 0) x = x + ", "; - x = x + "ExtendedKeyUsage"; - } - if (bad[2]) { - if (x.length() > 0) x = x + ", "; - x = x + "NetscapeCertType"; - } - certStr.append("\n").append(tab) + if (checkUsage) { + boolean[] bad = new boolean[3]; + checkCertUsage(x509Cert, bad); + if (bad[0] || bad[1] || bad[2]) { + String x = ""; + if (bad[0]) { + x ="KeyUsage"; + } + if (bad[1]) { + if (x.length() > 0) x = x + ", "; + x = x + "ExtendedKeyUsage"; + } + if (bad[2]) { + if (x.length() > 0) x = x + ", "; + x = x + "NetscapeCertType"; + } + certStr.append("\n").append(tab) .append(MessageFormat.format(rb.getString( ".{0}.extension.does.not.support.code.signing."), x)); + } } } return certStr.toString(); @@ -1335,7 +1339,7 @@ certUrl); } System.out.println(rb.getString("TSA.certificate.") + - printCert("", tsaCert, false, 0)); + printCert("", tsaCert, false, 0, false)); } if (signingMechanism != null) { System.out.println( @@ -1544,10 +1548,13 @@ s.append(printTimestamp(tab, timestamp)); s.append('\n'); } - // display the certificate(s) + // display the certificate(s). The first one is end-enity cert and + // its KeyUsage should be checked. + boolean first = true; for (Certificate c : certs) { - s.append(printCert(tab, c, true, now)); + s.append(printCert(tab, c, true, now, first)); s.append('\n'); + first = false; } try { CertPath cp = certificateFactory.generateCertPath(certs); @@ -1847,7 +1854,7 @@ // We don't meant to print anything, the next call // checks validity and keyUsage etc - printCert("", certChain[0], true, 0); + printCert("", certChain[0], true, 0, true); try { CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain));
--- a/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/tools/policytool/PolicyTool.java Mon Dec 13 16:25:26 2010 -0800 @@ -49,7 +49,7 @@ /** * PolicyTool may be used by users and administrators to configure the * overall java security policy (currently stored in the policy file). - * Using PolicyTool administators may add and remove policies from + * Using PolicyTool administrators may add and remove policies from * the policy file. <p> * * @see java.security.Policy @@ -1343,11 +1343,6 @@ PolicyTool.rb.getString ("Actions."); - /* gridbag index for display OverWriteFile (OW) components */ - public static final int OW_LABEL = 0; - public static final int OW_OK_BUTTON = 1; - public static final int OW_CANCEL_BUTTON = 2; - /* gridbag index for display PolicyEntry (PE) components */ public static final int PE_CODEBASE_LABEL = 0; public static final int PE_CODEBASE_TEXTFIELD = 1; @@ -1523,44 +1518,6 @@ } /** - * ask user if they want to overwrite an existing file - */ - void displayOverWriteFileDialog(String filename, int nextEvent) { - - // find where the PolicyTool gui is - Point location = tw.getLocationOnScreen(); - setBounds(location.x + 75, location.y + 100, 400, 150); - setLayout(new GridBagLayout()); - - // ask the user if they want to over write the existing file - MessageFormat form = new MessageFormat(PolicyTool.rb.getString - ("OK.to.overwrite.existing.file.filename.")); - Object[] source = {filename}; - Label label = new Label(form.format(source)); - tw.addNewComponent(this, label, OW_LABEL, - 0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.BOTH, - tw.TOP_PADDING); - - // OK button - Button button = new Button(PolicyTool.rb.getString("OK")); - button.addActionListener(new OverWriteFileOKButtonListener - (tool, tw, this, filename, nextEvent)); - tw.addNewComponent(this, button, OW_OK_BUTTON, - 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.VERTICAL, - tw.TOP_PADDING); - - // Cancel button - // -- if the user hits cancel, do NOT go on to the next event - button = new Button(PolicyTool.rb.getString("Cancel")); - button.addActionListener(new CancelButtonListener(this)); - tw.addNewComponent(this, button, OW_CANCEL_BUTTON, - 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.VERTICAL, - tw.TOP_PADDING); - - setVisible(true); - } - - /** * pop up a dialog so the user can enter info to add a new PolicyEntry * - if edit is TRUE, then the user is editing an existing entry * and we should display the original info as well. @@ -2339,47 +2296,39 @@ return; // get the entered filename - String filename = new String(fd.getDirectory() + fd.getFile()); + File saveAsFile = new File(fd.getDirectory(), fd.getFile()); + String filename = saveAsFile.getPath(); fd.dispose(); - // see if the file already exists - File saveAsFile = new File(filename); - if (saveAsFile.exists()) { - // display a dialog box for the user to enter policy info - ToolDialog td = new ToolDialog - (PolicyTool.rb.getString("Overwrite.File"), tool, tw, true); - td.displayOverWriteFileDialog(filename, nextEvent); - } else { - try { - // save the policy entries to a file - tool.savePolicy(filename); - - // display status - MessageFormat form = new MessageFormat(PolicyTool.rb.getString - ("Policy.successfully.written.to.filename")); - Object[] source = {filename}; - tw.displayStatusDialog(null, form.format(source)); - - // display the new policy filename - TextField newFilename = (TextField)tw.getComponent - (tw.MW_FILENAME_TEXTFIELD); - newFilename.setText(filename); - tw.setVisible(true); - - // now continue with the originally requested command - // (QUIT, NEW, or OPEN) - userSaveContinue(tool, tw, this, nextEvent); - - } catch (FileNotFoundException fnfe) { - if (filename == null || filename.equals("")) { - tw.displayErrorDialog(null, new FileNotFoundException - (PolicyTool.rb.getString("null.filename"))); - } else { - tw.displayErrorDialog(null, fnfe); - } - } catch (Exception ee) { - tw.displayErrorDialog(null, ee); + try { + // save the policy entries to a file + tool.savePolicy(filename); + + // display status + MessageFormat form = new MessageFormat(PolicyTool.rb.getString + ("Policy.successfully.written.to.filename")); + Object[] source = {filename}; + tw.displayStatusDialog(null, form.format(source)); + + // display the new policy filename + TextField newFilename = (TextField)tw.getComponent + (tw.MW_FILENAME_TEXTFIELD); + newFilename.setText(filename); + tw.setVisible(true); + + // now continue with the originally requested command + // (QUIT, NEW, or OPEN) + userSaveContinue(tool, tw, this, nextEvent); + + } catch (FileNotFoundException fnfe) { + if (filename == null || filename.equals("")) { + tw.displayErrorDialog(null, new FileNotFoundException + (PolicyTool.rb.getString("null.filename"))); + } else { + tw.displayErrorDialog(null, fnfe); } + } catch (Exception ee) { + tw.displayErrorDialog(null, ee); } } @@ -2494,7 +2443,7 @@ return; // get the entered filename - String policyFile = new String(fd.getDirectory() + fd.getFile()); + String policyFile = new File(fd.getDirectory(), fd.getFile()).getPath(); try { // open the policy file @@ -2862,67 +2811,6 @@ } /** - * Event handler for OverWriteFileOKButton button - */ -class OverWriteFileOKButtonListener implements ActionListener { - - private PolicyTool tool; - private ToolWindow tw; - private ToolDialog td; - private String filename; - private int nextEvent; - - OverWriteFileOKButtonListener(PolicyTool tool, ToolWindow tw, - ToolDialog td, String filename, int nextEvent) { - this.tool = tool; - this.tw = tw; - this.td = td; - this.filename = filename; - this.nextEvent = nextEvent; - } - - public void actionPerformed(ActionEvent e) { - try { - // save the policy entries to a file - tool.savePolicy(filename); - - // display status - MessageFormat form = new MessageFormat - (PolicyTool.rb.getString - ("Policy.successfully.written.to.filename")); - Object[] source = {filename}; - tw.displayStatusDialog(null, form.format(source)); - - // display the new policy filename - TextField newFilename = (TextField)tw.getComponent - (tw.MW_FILENAME_TEXTFIELD); - newFilename.setText(filename); - tw.setVisible(true); - - // now continue with the originally requested command - // (QUIT, NEW, or OPEN) - td.setVisible(false); - td.dispose(); - td.userSaveContinue(tool, tw, td, nextEvent); - - } catch (FileNotFoundException fnfe) { - if (filename == null || filename.equals("")) { - tw.displayErrorDialog(null, new FileNotFoundException - (PolicyTool.rb.getString("null.filename"))); - } else { - tw.displayErrorDialog(null, fnfe); - } - td.setVisible(false); - td.dispose(); - } catch (Exception ee) { - tw.displayErrorDialog(null, ee); - td.setVisible(false); - td.dispose(); - } - } -} - -/** * Event handler for AddEntryDoneButton button * * -- if edit is TRUE, then we are EDITing an existing PolicyEntry
--- a/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/util/ManifestEntryVerifier.java Mon Dec 13 16:25:26 2010 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,16 @@ private static final Debug debug = Debug.getInstance("jar"); + /** + * Holder class to lazily load Sun provider. NOTE: if + * Providers.getSunProvider returned a cached provider, we could avoid the + * need for caching the provider with this holder class; we should try to + * revisit this in JDK 8. + */ + private static class SunProviderHolder { + private static final Provider instance = Providers.getSunProvider(); + } + /** the created digest objects */ HashMap<String, MessageDigest> createdDigests; @@ -125,7 +135,7 @@ try { digest = MessageDigest.getInstance - (algorithm, Providers.getSunProvider()); + (algorithm, SunProviderHolder.instance); createdDigests.put(algorithm, digest); } catch (NoSuchAlgorithmException nsae) { // ignore @@ -185,7 +195,10 @@ Hashtable<String, CodeSigner[]> sigFileSigners) throws JarException { - if (skip) return null; + // MANIFEST.MF should not be skipped. It has signers. + if (skip && !entry.getName().equals(JarFile.MANIFEST_NAME)) { + return null; + } if (signers != null) return signers;
--- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java Mon Dec 13 16:25:26 2010 -0800 @@ -265,6 +265,9 @@ debug.println("processSignature unsigned name = "+name); } } + + // MANIFEST.MF is always regarded as signed + updateSigners(newSigners, signers, JarFile.MANIFEST_NAME); } /**
--- a/jdk/src/share/demo/nio/zipfs/Demo.java Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/demo/nio/zipfs/Demo.java Mon Dec 13 16:25:26 2010 -0800 @@ -45,12 +45,7 @@ /* * ZipFileSystem usage demo * - * java [-cp .../zipfs.jar:./] Demo action ZipfileName [...] - * - * To deploy the provider, either copy the zipfs.jar into JDK/JRE - * extensions directory or add - * <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar - * into your class path as showed above. + * java Demo action ZipfileName [...] * * @author Xueming Shen */ @@ -153,14 +148,11 @@ Action action = Action.valueOf(args[0]); Map<String, Object> env = env = new HashMap<>(); if (action == Action.create) - env.put("createNew", true); + env.put("create", "true"); if (action == Action.tlist || action == Action.twalk) env.put("buildDirTree", true); + FileSystem fs = FileSystems.newFileSystem(Paths.get(args[1]), env, null); - FileSystem fs = FileSystems.newFileSystem( - URI.create("zip" + Paths.get(args[1]).toUri().toString().substring(4)), - env, - null); try { FileSystem fs2; Path path, src, dst; @@ -207,19 +199,13 @@ src.copyTo(dst, COPY_ATTRIBUTES); break; case zzmove: - fs2 = FileSystems.newFileSystem( - URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)), - env, - null); + fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); //sf1.getPath(args[3]).moveTo(fs2.getPath(args[3])); z2zmove(fs, fs2, args[3]); fs2.close(); break; case zzcopy: - fs2 = FileSystems.newFileSystem( - URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)), - env, - null); + fs2 = FileSystems.newFileSystem(Paths.get(args[2]), env, null); //sf1.getPath(args[3]).copyTo(fs2.getPath(args[3])); z2zcopy(fs, fs2, args[3]); fs2.close();
--- a/jdk/src/share/demo/nio/zipfs/META-INF/services/java.nio.file.spi.FileSystemProvider Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -com.sun.nio.zipfs.ZipFileSystemProvider -com.sun.nio.zipfs.JarFileSystemProvider -
--- a/jdk/src/share/demo/nio/zipfs/README.txt Mon Dec 13 16:22:29 2010 -0800 +++ b/jdk/src/share/demo/nio/zipfs/README.txt Mon Dec 13 16:25:26 2010 -0800 @@ -1,10 +1,6 @@ ZipFileSystem is a file system provider that treats the contents of a zip or JAR file as a java.nio.file.FileSystem. -To deploy the provider you must copy zipfs.jar into your extensions -directory or else add <JDK_HOME>/demo/nio/zipfs/zipfs.jar -to your class path. - The factory methods defined by the java.nio.file.FileSystems class can be used to create a FileSystem, eg: @@ -15,9 +11,9 @@ -or - // locate file system by URI + // locate file system by the legacy JAR URL syntax Map<String,?> env = Collections.emptyMap(); - URI uri = URI.create("zip:///mydir/foo.jar"); + URI uri = URI.create("jar:file:/mydir/foo.jar"); FileSystem fs = FileSystems.newFileSystem(uri, env); Once a FileSystem is created then classes in the java.nio.file package @@ -26,4 +22,6 @@ Path mf = fs.getPath("/META-INF/MANIFEST.MF"); InputStream in = mf.newInputStream(); +See Demo.java for more interesting usages. +
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Sun Microsystems nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.sun.nio.zipfs; - -import java.nio.file.*; -import java.nio.file.spi.*; -import java.nio.file.attribute.*; -import java.nio.file.spi.FileSystemProvider; - -import java.net.URI; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.channels.FileChannel; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class JarFileSystemProvider extends ZipFileSystemProvider -{ - - @Override - public String getScheme() { - return "jar"; - } - - @Override - protected Path uriToPath(URI uri) { - String scheme = uri.getScheme(); - if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) { - throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'"); - } - try { - String uristr = uri.toString(); - int end = uristr.indexOf("!/"); - uristr = uristr.substring(4, (end == -1) ? uristr.length() : end); - uri = new URI(uristr); - return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null)) - .toAbsolutePath(); - } catch (URISyntaxException e) { - throw new AssertionError(e); //never thrown - } - } - - @Override - public Path getPath(URI uri) { - FileSystem fs = getFileSystem(uri); - String path = uri.getFragment(); - if (path == null) { - String uristr = uri.toString(); - int off = uristr.indexOf("!/"); - if (off != -1) - path = uristr.substring(off + 2); - } - if (path != null) - return fs.getPath(path); - throw new IllegalArgumentException("URI: " - + uri - + " does not contain path fragment ex. jar:///c:/foo.zip!/BAR"); - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipCoder.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CoderResult; -import java.nio.charset.CodingErrorAction; -import java.util.Arrays; - -/** - * Utility class for zipfile name and comment decoding and encoding - * - * @author Xueming Shen - */ - -final class ZipCoder { - - String toString(byte[] ba, int length) { - CharsetDecoder cd = decoder().reset(); - int len = (int)(length * cd.maxCharsPerByte()); - char[] ca = new char[len]; - if (len == 0) - return new String(ca); - ByteBuffer bb = ByteBuffer.wrap(ba, 0, length); - CharBuffer cb = CharBuffer.wrap(ca); - CoderResult cr = cd.decode(bb, cb, true); - if (!cr.isUnderflow()) - throw new IllegalArgumentException(cr.toString()); - cr = cd.flush(cb); - if (!cr.isUnderflow()) - throw new IllegalArgumentException(cr.toString()); - return new String(ca, 0, cb.position()); - } - - String toString(byte[] ba) { - return toString(ba, ba.length); - } - - byte[] getBytes(String s) { - CharsetEncoder ce = encoder().reset(); - char[] ca = s.toCharArray(); - int len = (int)(ca.length * ce.maxBytesPerChar()); - byte[] ba = new byte[len]; - if (len == 0) - return ba; - ByteBuffer bb = ByteBuffer.wrap(ba); - CharBuffer cb = CharBuffer.wrap(ca); - CoderResult cr = ce.encode(cb, bb, true); - if (!cr.isUnderflow()) - throw new IllegalArgumentException(cr.toString()); - cr = ce.flush(bb); - if (!cr.isUnderflow()) - throw new IllegalArgumentException(cr.toString()); - if (bb.position() == ba.length) // defensive copy? - return ba; - else - return Arrays.copyOf(ba, bb.position()); - } - - // assume invoked only if "this" is not utf8 - byte[] getBytesUTF8(String s) { - if (isutf8) - return getBytes(s); - if (utf8 == null) - utf8 = new ZipCoder(Charset.forName("UTF-8")); - return utf8.getBytes(s); - } - - String toStringUTF8(byte[] ba, int len) { - if (isutf8) - return toString(ba, len); - if (utf8 == null) - utf8 = new ZipCoder(Charset.forName("UTF-8")); - return utf8.toString(ba, len); - } - - boolean isUTF8() { - return isutf8; - } - - private Charset cs; - private boolean isutf8; - private ZipCoder utf8; - - private ZipCoder(Charset cs) { - this.cs = cs; - this.isutf8 = cs.name().equals("UTF-8"); - } - - static ZipCoder get(Charset charset) { - return new ZipCoder(charset); - } - - static ZipCoder get(String csn) { - try { - return new ZipCoder(Charset.forName(csn)); - } catch (Throwable t) { - t.printStackTrace(); - } - return new ZipCoder(Charset.defaultCharset()); - } - - private final ThreadLocal<CharsetDecoder> decTL = new ThreadLocal<>(); - private final ThreadLocal<CharsetEncoder> encTL = new ThreadLocal<>(); - - private CharsetDecoder decoder() { - CharsetDecoder dec = decTL.get(); - if (dec == null) { - dec = cs.newDecoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - decTL.set(dec); - } - return dec; - } - - private CharsetEncoder encoder() { - CharsetEncoder enc = encTL.get(); - if (enc == null) { - enc = cs.newEncoder() - .onMalformedInput(CodingErrorAction.REPORT) - .onUnmappableCharacter(CodingErrorAction.REPORT); - encTL.set(enc); - } - return enc; - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - - -/** - * - * @author Xueming Shen - */ - -class ZipConstants { - /* - * Compression methods - */ - static final int METHOD_STORED = 0; - static final int METHOD_DEFLATED = 8; - static final int METHOD_DEFLATED64 = 9; - static final int METHOD_BZIP2 = 12; - static final int METHOD_LZMA = 14; - static final int METHOD_LZ77 = 19; - static final int METHOD_AES = 99; - - /* - * General purpose big flag - */ - static final int FLAG_ENCRYPTED = 0x01; - static final int FLAG_DATADESCR = 0x08; // crc, size and csize in dd - static final int FLAG_EFS = 0x800; // If this bit is set the filename and - // comment fields for this file must be - // encoded using UTF-8. - /* - * Header signatures - */ - static long LOCSIG = 0x04034b50L; // "PK\003\004" - static long EXTSIG = 0x08074b50L; // "PK\007\008" - static long CENSIG = 0x02014b50L; // "PK\001\002" - static long ENDSIG = 0x06054b50L; // "PK\005\006" - - /* - * Header sizes in bytes (including signatures) - */ - static final int LOCHDR = 30; // LOC header size - static final int EXTHDR = 16; // EXT header size - static final int CENHDR = 46; // CEN header size - static final int ENDHDR = 22; // END header size - - /* - * Local file (LOC) header field offsets - */ - static final int LOCVER = 4; // version needed to extract - static final int LOCFLG = 6; // general purpose bit flag - static final int LOCHOW = 8; // compression method - static final int LOCTIM = 10; // modification time - static final int LOCCRC = 14; // uncompressed file crc-32 value - static final int LOCSIZ = 18; // compressed size - static final int LOCLEN = 22; // uncompressed size - static final int LOCNAM = 26; // filename length - static final int LOCEXT = 28; // extra field length - - /* - * Extra local (EXT) header field offsets - */ - static final int EXTCRC = 4; // uncompressed file crc-32 value - static final int EXTSIZ = 8; // compressed size - static final int EXTLEN = 12; // uncompressed size - - /* - * Central directory (CEN) header field offsets - */ - static final int CENVEM = 4; // version made by - static final int CENVER = 6; // version needed to extract - static final int CENFLG = 8; // encrypt, decrypt flags - static final int CENHOW = 10; // compression method - static final int CENTIM = 12; // modification time - static final int CENCRC = 16; // uncompressed file crc-32 value - static final int CENSIZ = 20; // compressed size - static final int CENLEN = 24; // uncompressed size - static final int CENNAM = 28; // filename length - static final int CENEXT = 30; // extra field length - static final int CENCOM = 32; // comment length - static final int CENDSK = 34; // disk number start - static final int CENATT = 36; // internal file attributes - static final int CENATX = 38; // external file attributes - static final int CENOFF = 42; // LOC header offset - - /* - * End of central directory (END) header field offsets - */ - static final int ENDSUB = 8; // number of entries on this disk - static final int ENDTOT = 10; // total number of entries - static final int ENDSIZ = 12; // central directory size in bytes - static final int ENDOFF = 16; // offset of first CEN header - static final int ENDCOM = 20; // zip file comment length - - /* - * ZIP64 constants - */ - static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006" - static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007" - static final int ZIP64_ENDHDR = 56; // ZIP64 end header size - static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size - static final int ZIP64_EXTHDR = 24; // EXT header size - static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID - - static final int ZIP64_MINVAL32 = 0xFFFF; - static final long ZIP64_MINVAL = 0xFFFFFFFFL; - - /* - * Zip64 End of central directory (END) header field offsets - */ - static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir - static final int ZIP64_ENDVEM = 12; // version made by - static final int ZIP64_ENDVER = 14; // version needed to extract - static final int ZIP64_ENDNMD = 16; // number of this disk - static final int ZIP64_ENDDSK = 20; // disk number of start - static final int ZIP64_ENDTOD = 24; // total number of entries on this disk - static final int ZIP64_ENDTOT = 32; // total number of entries - static final int ZIP64_ENDSIZ = 40; // central directory size in bytes - static final int ZIP64_ENDOFF = 48; // offset of first CEN header - static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector - - /* - * Zip64 End of central directory locator field offsets - */ - static final int ZIP64_LOCDSK = 4; // disk number start - static final int ZIP64_LOCOFF = 8; // offset of zip64 end - static final int ZIP64_LOCTOT = 16; // total number of disks - - /* - * Zip64 Extra local (EXT) header field offsets - */ - static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value - static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte - static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte - - /* - * Extra field header ID - */ - static final int EXTID_ZIP64 = 0x0001; // ZIP64 - static final int EXTID_NTFS = 0x000a; // NTFS - static final int EXTID_UNIX = 0x000d; // UNIX - static final int EXTID_EFS = 0x0017; // Strong Encryption - static final int EXTID_EXTT = 0x5455; // Info-ZIP Extended Timestamp - - /* - * fields access methods - */ - /////////////////////////////////////////////////////// - static final int CH(byte[] b, int n) { - return b[n] & 0xff; - } - - static final int SH(byte[] b, int n) { - return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8); - } - - static final long LG(byte[] b, int n) { - return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL; - } - - static final long LL(byte[] b, int n) { - return (LG(b, n)) | (LG(b, n + 4) << 32); - } - - static final long GETSIG(byte[] b) { - return LG(b, 0); - } - - // local file (LOC) header fields - static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature - static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract - static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags - static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method - static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time - static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data - static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size - static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size - static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length - static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length - - // extra local (EXT) header fields - static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data - static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size - static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size - - // end of central directory header (END) fields - static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk - static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries - static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size - static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset - static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of zip file comment - static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);} - - // zip64 end of central directory recoder fields - static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk - static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries - static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size - static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset - static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset - - // central directory header (CEN) fields - static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); } - static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); } - static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); } - static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); } - static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);} - static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);} - static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);} - static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);} - static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);} - static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);} - static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);} - static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);} - static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);} - static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);} - static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);} - static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);} - - /* The END header is followed by a variable length comment of size < 64k. */ - static final long END_MAXLEN = 0xFFFF + ENDHDR; - static final int READBLOCKSZ = 128; -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.nio.file.DirectoryStream; -import java.nio.file.ClosedDirectoryStreamException; -import java.nio.file.NotDirectoryException; -import java.nio.file.Path; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.io.IOException; - -/** - * - * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal - */ - -public class ZipDirectoryStream implements DirectoryStream<Path> { - - private final ZipFileSystem zipfs; - private final byte[] path; - private final DirectoryStream.Filter<? super Path> filter; - private volatile boolean isClosed; - private volatile Iterator<Path> itr; - - ZipDirectoryStream(ZipPath zipPath, - DirectoryStream.Filter<? super java.nio.file.Path> filter) - throws IOException - { - this.zipfs = zipPath.getFileSystem(); - this.path = zipPath.getResolvedPath(); - this.filter = filter; - // sanity check - if (!zipfs.isDirectory(path)) - throw new NotDirectoryException(zipPath.toString()); - } - - @Override - public synchronized Iterator<Path> iterator() { - if (isClosed) - throw new ClosedDirectoryStreamException(); - if (itr != null) - throw new IllegalStateException("Iterator has already been returned"); - - try { - itr = zipfs.iteratorOf(path, filter); - } catch (IOException e) { - throw new IllegalStateException(e); - } - return new Iterator<>() { - private Path next; - @Override - public boolean hasNext() { - if (isClosed) - return false; - return itr.hasNext(); - } - - @Override - public synchronized Path next() { - if (isClosed) - throw new NoSuchElementException(); - return itr.next(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public synchronized void close() throws IOException { - isClosed = true; - } - - -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -package com.sun.nio.zipfs; - -import java.nio.file.attribute.BasicFileAttributeView; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileTime; -import java.io.IOException; -import java.util.LinkedHashMap; - -/* - * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal - */ - -public class ZipFileAttributeView implements BasicFileAttributeView -{ - private static enum AttrID { - size, - creationTime, - lastAccessTime, - lastModifiedTime, - isDirectory, - isRegularFile, - isSymbolicLink, - isOther, - fileKey, - compressedSize, - crc, - method - }; - - private final ZipPath path; - private final boolean isZipView; - - private ZipFileAttributeView(ZipPath path, boolean isZipView) { - this.path = path; - this.isZipView = isZipView; - } - - static <V extends FileAttributeView> V get(ZipPath path, Class<V> type) { - if (type == null) - throw new NullPointerException(); - if (type == BasicFileAttributeView.class) - return (V)new ZipFileAttributeView(path, false); - if (type == ZipFileAttributeView.class) - return (V)new ZipFileAttributeView(path, true); - return null; - } - - static ZipFileAttributeView get(ZipPath path, String type) { - if (type == null) - throw new NullPointerException(); - if (type.equals("basic")) - return new ZipFileAttributeView(path, false); - if (type.equals("zip")) - return new ZipFileAttributeView(path, true); - return null; - } - - @Override - public String name() { - return isZipView ? "zip" : "basic"; - } - - public ZipFileAttributes readAttributes() throws IOException - { - return path.getAttributes(); - } - - @Override - public void setTimes(FileTime lastModifiedTime, - FileTime lastAccessTime, - FileTime createTime) - throws IOException - { - path.setTimes(lastModifiedTime, lastAccessTime, createTime); - } - - void setAttribute(String attribute, Object value) - throws IOException - { - try { - if (AttrID.valueOf(attribute) == AttrID.lastModifiedTime) - setTimes ((FileTime)value, null, null); - if (AttrID.valueOf(attribute) == AttrID.lastAccessTime) - setTimes (null, (FileTime)value, null); - if (AttrID.valueOf(attribute) == AttrID.creationTime) - setTimes (null, null, (FileTime)value); - return; - } catch (IllegalArgumentException x) {} - throw new UnsupportedOperationException("'" + attribute + - "' is unknown or read-only attribute"); - } - - public Object getAttribute(String attribute, boolean domap) - throws IOException - { - ZipFileAttributes zfas = readAttributes(); - if (!domap) { - try { - return attribute(AttrID.valueOf(attribute), zfas); - } catch (IllegalArgumentException x) {} - return null; - } - LinkedHashMap<String, Object> map = new LinkedHashMap<>(); - if ("*".equals(attribute)) { - for (AttrID id : AttrID.values()) { - try { - map.put(id.name(), attribute(id, zfas)); - } catch (IllegalArgumentException x) {} - } - } else { - String[] as = attribute.split(","); - for (String a : as) { - try { - map.put(a, attribute(AttrID.valueOf(a), zfas)); - } catch (IllegalArgumentException x) {} - } - } - return map; - } - - Object attribute(AttrID id, ZipFileAttributes zfas) { - switch (id) { - case size: - return zfas.size(); - case creationTime: - return zfas.creationTime(); - case lastAccessTime: - return zfas.lastAccessTime(); - case lastModifiedTime: - return zfas.lastModifiedTime(); - case isDirectory: - return zfas.isDirectory(); - case isRegularFile: - return zfas.isRegularFile(); - case isSymbolicLink: - return zfas.isSymbolicLink(); - case isOther: - return zfas.isOther(); - case fileKey: - return zfas.fileKey(); - case compressedSize: - if (isZipView) - return zfas.compressedSize(); - break; - case crc: - if (isZipView) - return zfas.crc(); - break; - case method: - if (isZipView) - return zfas.method(); - break; - } - return null; - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -package com.sun.nio.zipfs; - -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.util.Arrays; -import java.util.Formatter; -import static com.sun.nio.zipfs.ZipUtils.*; - -/** - * - * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal - */ - -public class ZipFileAttributes implements BasicFileAttributes - -{ - private final ZipFileSystem.Entry e; - - ZipFileAttributes(ZipFileSystem.Entry e) { - this.e = e; - } - - ///////// basic attributes /////////// - @Override - public FileTime creationTime() { - if (e.ctime != -1) - return FileTime.fromMillis(e.ctime); - return null; - } - - @Override - public boolean isDirectory() { - return e.isDir(); - } - - @Override - public boolean isOther() { - return false; - } - - @Override - public boolean isRegularFile() { - return !e.isDir(); - } - - @Override - public FileTime lastAccessTime() { - if (e.atime != -1) - return FileTime.fromMillis(e.atime); - return null; - } - - @Override - public FileTime lastModifiedTime() { - return FileTime.fromMillis(e.mtime); - } - - @Override - public long size() { - return e.size; - } - - @Override - public boolean isSymbolicLink() { - return false; - } - - @Override - public Object fileKey() { - return null; - } - - ///////// zip entry attributes /////////// - public long compressedSize() { - return e.csize; - } - - public long crc() { - return e.crc; - } - - public int method() { - return e.method; - } - - public byte[] extra() { - if (e.extra != null) - return Arrays.copyOf(e.extra, e.extra.length); - return null; - } - - public byte[] comment() { - if (e.comment != null) - return Arrays.copyOf(e.comment, e.comment.length); - return null; - } - - public String toString() { - StringBuilder sb = new StringBuilder(1024); - Formatter fm = new Formatter(sb); - if (creationTime() != null) - fm.format(" creationTime : %tc%n", creationTime().toMillis()); - else - fm.format(" creationTime : null%n"); - - if (lastAccessTime() != null) - fm.format(" lastAccessTime : %tc%n", lastAccessTime().toMillis()); - else - fm.format(" lastAccessTime : null%n"); - fm.format(" lastModifiedTime: %tc%n", lastModifiedTime().toMillis()); - fm.format(" isRegularFile : %b%n", isRegularFile()); - fm.format(" isDirectory : %b%n", isDirectory()); - fm.format(" isSymbolicLink : %b%n", isSymbolicLink()); - fm.format(" isOther : %b%n", isOther()); - fm.format(" fileKey : %s%n", fileKey()); - fm.format(" size : %d%n", size()); - fm.format(" compressedSize : %d%n", compressedSize()); - fm.format(" crc : %x%n", crc()); - fm.format(" method : %d%n", method()); - fm.close(); - return sb.toString(); - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileStore.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.io.IOException; -import java.nio.file.FileStore; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileStoreAttributeView; -import java.nio.file.attribute.FileStoreSpaceAttributeView; -import java.nio.file.attribute.FileStoreSpaceAttributes; -import java.nio.file.attribute.Attributes; -import java.nio.file.attribute.BasicFileAttributeView; -import java.util.Formatter; - -/* - * - * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal - */ - -public class ZipFileStore extends FileStore { - - private final ZipFileSystem zfs; - - ZipFileStore(ZipPath zpath) { - this.zfs = (ZipFileSystem)zpath.getFileSystem(); - } - - @Override - public String name() { - return zfs.toString() + "/"; - } - - @Override - public String type() { - return "zipfs"; - } - - @Override - public boolean isReadOnly() { - return zfs.isReadOnly(); - } - - @Override - public boolean supportsFileAttributeView(Class<? extends FileAttributeView> type) { - return (type == BasicFileAttributeView.class || - type == ZipFileAttributeView.class); - } - - @Override - public boolean supportsFileAttributeView(String name) { - return name.equals("basic") || name.equals("zip"); - } - - @Override - @SuppressWarnings("unchecked") - public <V extends FileStoreAttributeView> V getFileStoreAttributeView(Class<V> type) { - if (type == null) - throw new NullPointerException(); - if (type == FileStoreSpaceAttributeView.class) - return (V) new ZipFileStoreAttributeView(this); - return null; - } - - @Override - public Object getAttribute(String attribute) throws IOException { - if (attribute.equals("space:totalSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().totalSpace(); - if (attribute.equals("space:usableSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().usableSpace(); - if (attribute.equals("space:unallocatedSpace")) - return new ZipFileStoreAttributeView(this).readAttributes().unallocatedSpace(); - throw new UnsupportedOperationException("does not support the given attribute"); - } - - private static class ZipFileStoreAttributeView implements FileStoreSpaceAttributeView { - - private final ZipFileStore fileStore; - - public ZipFileStoreAttributeView(ZipFileStore fileStore) { - this.fileStore = fileStore; - } - - @Override - public String name() { - return "space"; - } - - @Override - public FileStoreSpaceAttributes readAttributes() throws IOException { - final String file = fileStore.name(); - Path path = FileSystems.getDefault().getPath(file); - final long size = Attributes.readBasicFileAttributes(path).size(); - final FileStore fstore = path.getFileStore(); - final FileStoreSpaceAttributes fstoreAttrs = - Attributes.readFileStoreSpaceAttributes(fstore); - return new FileStoreSpaceAttributes() { - public long totalSpace() { - return size; - } - - public long usableSpace() { - if (!fstore.isReadOnly()) - return fstoreAttrs.usableSpace(); - return 0; - } - - public long unallocatedSpace() { - if (!fstore.isReadOnly()) - return fstoreAttrs.unallocatedSpace(); - return 0; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - Formatter fm = new Formatter(sb); - fm.format("FileStoreSpaceAttributes[%s]%n", file); - fm.format(" totalSpace: %d%n", totalSpace()); - fm.format(" usableSpace: %d%n", usableSpace()); - fm.format(" unallocSpace: %d%n", unallocatedSpace()); - fm.close(); - return sb.toString(); - } - }; - } - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2367 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.ByteBuffer; -import java.nio.MappedByteBuffer; -import java.nio.channels.*; -import java.nio.file.*; -import java.nio.file.attribute.*; -import java.nio.file.spi.*; -import java.util.*; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; -import java.util.regex.Pattern; -import java.util.zip.CRC32; -import java.util.zip.Inflater; -import java.util.zip.Deflater; -import java.util.zip.InflaterInputStream; -import java.util.zip.DeflaterOutputStream; -import java.util.zip.ZipException; -import java.util.zip.ZipError; -import static java.lang.Boolean.*; -import static com.sun.nio.zipfs.ZipConstants.*; -import static com.sun.nio.zipfs.ZipUtils.*; -import static java.nio.file.StandardOpenOption.*; -import static java.nio.file.StandardCopyOption.*; - -/** - * A FileSystem built on a zip file - * - * @author Xueming Shen - */ - -public class ZipFileSystem extends FileSystem { - - private final ZipFileSystemProvider provider; - private final ZipPath defaultdir; - private boolean readOnly = false; - private final Path zfpath; - private final ZipCoder zc; - - // configurable by env map - private final String defaultDir; // default dir for the file system - private final String nameEncoding; // default encoding for name/comment - private final boolean buildDirTree; // build a dir tree for directoryStream ops - private final boolean useTempFile; // use a temp file for newOS, default - // is to use BAOS for better performance - private final boolean createNew; // create a new zip if not exists - private static final boolean isWindows = - System.getProperty("os.name").startsWith("Windows"); - - ZipFileSystem(ZipFileSystemProvider provider, - Path zfpath, - Map<String, ?> env) - throws IOException - { - // configurable env setup - this.buildDirTree = TRUE.equals(env.get("buildDirTreea")); - this.useTempFile = TRUE.equals(env.get("useTempFile")); - this.createNew = TRUE.equals(env.get("createNew")); - this.nameEncoding = env.containsKey("nameEncoding") ? - (String)env.get("nameEncoding") : "UTF-8"; - this.defaultDir = env.containsKey("default.dir") ? - (String)env.get("default.dir") : "/"; - if (this.defaultDir.charAt(0) != '/') - throw new IllegalArgumentException("default dir should be absolute"); - - this.provider = provider; - this.zfpath = zfpath; - if (zfpath.notExists()) { - if (createNew) { - OutputStream os = zfpath.newOutputStream(CREATE_NEW, WRITE); - new END().write(os, 0); - os.close(); - } else { - throw new FileSystemNotFoundException(zfpath.toString()); - } - } - zfpath.checkAccess(AccessMode.READ); // sm and existence check - try { - zfpath.checkAccess(AccessMode.WRITE); - } catch (AccessDeniedException x) { - this.readOnly = true; - } - this.zc = ZipCoder.get(nameEncoding); - this.defaultdir = new ZipPath(this, getBytes(defaultDir)); - this.ch = zfpath.newByteChannel(READ); - this.cen = initCEN(); - } - - @Override - public FileSystemProvider provider() { - return provider; - } - - @Override - public String getSeparator() { - return "/"; - } - - @Override - public boolean isOpen() { - return isOpen; - } - - @Override - public boolean isReadOnly() { - return readOnly; - } - - private void checkWritable() throws IOException { - if (readOnly) - throw new ReadOnlyFileSystemException(); - } - - @Override - public Iterable<Path> getRootDirectories() { - ArrayList<Path> pathArr = new ArrayList<>(); - pathArr.add(new ZipPath(this, new byte[]{'/'})); - return pathArr; - } - - ZipPath getDefaultDir() { // package private - return defaultdir; - } - - @Override - public ZipPath getPath(String path) { - if (path.length() == 0) - throw new InvalidPathException(path, "path should not be empty"); - return new ZipPath(this, getBytes(path)); - } - - @Override - public UserPrincipalLookupService getUserPrincipalLookupService() { - throw new UnsupportedOperationException(); - } - - @Override - public WatchService newWatchService() { - throw new UnsupportedOperationException(); - } - - FileStore getFileStore(ZipPath path) { - return new ZipFileStore(path); - } - - @Override - public Iterable<FileStore> getFileStores() { - ArrayList<FileStore> list = new ArrayList<>(1); - list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'}))); - return list; - } - - private static final Set<String> supportedFileAttributeViews = - Collections.unmodifiableSet( - new HashSet<String>(Arrays.asList("basic", "zip"))); - - @Override - public Set<String> supportedFileAttributeViews() { - return supportedFileAttributeViews; - } - - @Override - public String toString() { - return zfpath.toString(); - } - - Path getZipFile() { - return zfpath; - } - - private static final String GLOB_SYNTAX = "glob"; - private static final String REGEX_SYNTAX = "regex"; - - @Override - public PathMatcher getPathMatcher(String syntaxAndInput) { - int pos = syntaxAndInput.indexOf(':'); - if (pos <= 0 || pos == syntaxAndInput.length()) { - throw new IllegalArgumentException(); - } - String syntax = syntaxAndInput.substring(0, pos); - String input = syntaxAndInput.substring(pos + 1); - String expr; - if (syntax.equals(GLOB_SYNTAX)) { - expr = toRegexPattern(input); - } else { - if (syntax.equals(REGEX_SYNTAX)) { - expr = input; - } else { - throw new UnsupportedOperationException("Syntax '" + syntax + - "' not recognized"); - } - } - // return matcher - final Pattern pattern = Pattern.compile(expr); - return new PathMatcher() { - @Override - public boolean matches(Path path) { - return pattern.matcher(path.toString()).matches(); - } - }; - } - - @Override - public void close() throws IOException { - beginWrite(); - try { - if (!isOpen) - return; - isOpen = false; // set closed - } finally { - endWrite(); - } - if (!streams.isEmpty()) { // unlock and close all remaining streams - Set<InputStream> copy = new HashSet<>(streams); - for (InputStream is: copy) - is.close(); - } - beginWrite(); // lock and sync - try { - sync(); - ch.close(); // close the ch just in case no update - } finally { // and sync dose not close the ch - endWrite(); - } - - synchronized (inflaters) { - for (Inflater inf : inflaters) - inf.end(); - } - synchronized (deflaters) { - for (Deflater def : deflaters) - def.end(); - } - - synchronized (tmppaths) { - for (Path p: tmppaths) { - try { - p.deleteIfExists(); - } catch (IOException x) { - x.printStackTrace(); - } - } - } - provider.removeFileSystem(zfpath); - } - - ZipFileAttributes getFileAttributes(byte[] path) - throws IOException - { - Entry e; - beginRead(); - try { - ensureOpen(); - e = getEntry0(path); - } finally { - endRead(); - } - if (e == null) { - if (path.length == 0) { - e = new Entry(new byte[0]); // root - } else if (buildDirTree) { - IndexNode inode = getDirs().get(IndexNode.keyOf(path)); - if (inode == null) - return null; - e = new Entry(inode.name); - } else { - return null; - } - e.method = METHOD_STORED; // STORED for dir - BasicFileAttributes bfas = Attributes.readBasicFileAttributes(zfpath); - if (bfas.lastModifiedTime() != null) - e.mtime = bfas.lastModifiedTime().toMillis(); - if (bfas.lastAccessTime() != null) - e.atime = bfas.lastAccessTime().toMillis(); - if (bfas.creationTime() != null) - e.ctime = bfas.creationTime().toMillis(); - } - return new ZipFileAttributes(e); - } - - void setTimes(byte[] path, FileTime mtime, FileTime atime, FileTime ctime) - throws IOException - { - checkWritable(); - beginWrite(); - try { - ensureOpen(); - Entry e = getEntry0(path); // ensureOpen checked - if (e == null) - throw new NoSuchFileException(getString(path)); - if (e.type == Entry.CEN) - e.type = Entry.COPY; // copy e - if (mtime != null) - e.mtime = mtime.toMillis(); - if (atime != null) - e.atime = atime.toMillis(); - if (ctime != null) - e.ctime = ctime.toMillis(); - update(e); - } finally { - endWrite(); - } - } - - boolean exists(byte[] path) - throws IOException - { - beginRead(); - try { - ensureOpen(); - return getEntry0(path) != null; - } finally { - endRead(); - } - } - - boolean isDirectory(byte[] path) - throws IOException - { - if (buildDirTree) - return getDirs().containsKey(IndexNode.keyOf(path)); - - beginRead(); - try { - Entry e = getEntry0(path); - return (e != null && e.isDir()) || path.length == 0; - } finally { - endRead(); - } - } - - private ZipPath toZipPath(byte[] path) { - // make it absolute - byte[] p = new byte[path.length + 1]; - p[0] = '/'; - System.arraycopy(path, 0, p, 1, path.length); - return new ZipPath(this, p); - } - - // returns the list of child paths of "path" - Iterator<Path> iteratorOf(byte[] path, - DirectoryStream.Filter<? super Path> filter) - throws IOException - { - beginWrite(); // iteration of inodes needs exclusive lock - try { - ensureOpen(); - if (buildDirTree) { - IndexNode inode = getDirs().get(IndexNode.keyOf(path)); - if (inode == null) - throw new NotDirectoryException(getString(path)); - List<Path> list = new ArrayList<>(); - IndexNode child = inode.child; - while (child != null) { - ZipPath zp = toZipPath(child.name); - if (filter == null || filter.accept(zp)) - list.add(zp); - child = child.sibling; - } - return list.iterator(); - } - - if (!isDirectory(path)) - throw new NotDirectoryException(getString(path)); - List<Path> list = new ArrayList<>(); - path = toDirectoryPath(path); - for (IndexNode key : inodes.keySet()) { - if (!isParentOf(path, key.name)) // is "path" the parent of "name" - continue; - int off = path.length; - while (off < key.name.length) { - if (key.name[off] == '/') - break; - off++; - } - if (off < (key.name.length - 1)) - continue; - ZipPath zp = toZipPath(key.name); - if (filter == null || filter.accept(zp)) - list.add(zp); - } - return list.iterator(); - } finally { - endWrite(); - } - } - - void createDirectory(byte[] dir, FileAttribute<?>... attrs) - throws IOException - { - checkWritable(); - dir = toDirectoryPath(dir); - beginWrite(); - try { - ensureOpen(); - if (dir.length == 0 || exists(dir)) // root dir, or exiting dir - throw new FileAlreadyExistsException(getString(dir)); - - checkParents(dir); - Entry e = new Entry(dir, Entry.NEW); - e.method = METHOD_STORED; // STORED for dir - update(e); - } finally { - endWrite(); - } - } - - void copyFile(boolean deletesrc, byte[]src, byte[] dst, CopyOption... options) - throws IOException - { - checkWritable(); - if (Arrays.equals(src, dst)) - return; // do nothing, src and dst are the same - - beginWrite(); - try { - ensureOpen(); - Entry eSrc = getEntry0(src); // ensureOpen checked - if (eSrc == null) - throw new NoSuchFileException(getString(src)); - if (eSrc.isDir()) { // spec says to create dst dir - createDirectory(dst); - return; - } - boolean hasReplace = false; - boolean hasCopyAttrs = false; - for (CopyOption opt : options) { - if (opt == REPLACE_EXISTING) - hasReplace = true; - else if (opt == COPY_ATTRIBUTES) - hasCopyAttrs = true; - } - Entry eDst = getEntry0(dst); - if (eDst != null) { - if (!hasReplace) - throw new FileAlreadyExistsException(getString(dst)); - } else { - checkParents(dst); - } - Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry - u.name = dst; // change name - if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH) - { - u.type = eSrc.type; // make it the same type - if (!deletesrc) { // if it's not "rename", just take the data - if (eSrc.bytes != null) - u.bytes = Arrays.copyOf(eSrc.bytes, eSrc.bytes.length); - else if (eSrc.file != null) { - u.file = getTempPathForEntry(null); - eSrc.file.copyTo(u.file, REPLACE_EXISTING); - } - } - } - if (!hasCopyAttrs) - u.mtime = u.atime= u.ctime = System.currentTimeMillis(); - update(u); - if (deletesrc) - updateDelete(eSrc); - } finally { - endWrite(); - } - } - - // Returns an output stream for writing the contents into the specified - // entry. - OutputStream newOutputStream(byte[] path, OpenOption... options) - throws IOException - { - checkWritable(); - boolean hasCreateNew = false; - boolean hasCreate = false; - boolean hasAppend = false; - for (OpenOption opt: options) { - if (opt == READ) - throw new IllegalArgumentException("READ not allowed"); - if (opt == CREATE_NEW) - hasCreateNew = true; - if (opt == CREATE) - hasCreate = true; - if (opt == APPEND) - hasAppend = true; - } - beginRead(); // only need a readlock, the "update()" will - try { // try to obtain a writelock when the os is - ensureOpen(); // being closed. - Entry e = getEntry0(path); - if (e != null) { - if (e.isDir() || hasCreateNew) - throw new FileAlreadyExistsException(getString(path)); - if (hasAppend) { - InputStream is = getInputStream(e); - OutputStream os = getOutputStream(new Entry(e, Entry.NEW)); - copyStream(is, os); - is.close(); - return os; - } - return getOutputStream(new Entry(e, Entry.NEW)); - } else { - if (!hasCreate && !hasCreateNew) - throw new NoSuchFileException(getString(path)); - checkParents(path); - return getOutputStream(new Entry(path, Entry.NEW)); - } - } finally { - endRead(); - } - } - - // Returns an input stream for reading the contents of the specified - // file entry. - InputStream newInputStream(byte[] path) throws IOException { - beginRead(); - try { - ensureOpen(); - Entry e = getEntry0(path); - if (e == null) - throw new NoSuchFileException(getString(path)); - if (e.isDir()) - throw new FileSystemException(getString(path), "is a directory", null); - return getInputStream(e); - } finally { - endRead(); - } - } - - private void checkOptions(Set<? extends OpenOption> options) { - // check for options of null type and option is an intance of StandardOpenOption - for (OpenOption option : options) { - if (option == null) - throw new NullPointerException(); - if (!(option instanceof StandardOpenOption)) - throw new IllegalArgumentException(); - } - } - - // Returns a Writable/ReadByteChannel for now. Might consdier to use - // newFileChannel() instead, which dump the entry data into a regular - // file on the default file system and create a FileChannel on top of - // it. - SeekableByteChannel newByteChannel(byte[] path, - Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - checkOptions(options); - if (options.contains(StandardOpenOption.WRITE) || - options.contains(StandardOpenOption.APPEND)) { - checkWritable(); - beginRead(); - try { - final WritableByteChannel wbc = Channels.newChannel( - newOutputStream(path, options.toArray(new OpenOption[0]))); - long leftover = 0; - if (options.contains(StandardOpenOption.APPEND)) { - Entry e = getEntry0(path); - if (e != null && e.size >= 0) - leftover = e.size; - } - final long offset = leftover; - return new SeekableByteChannel() { - long written = offset; - public boolean isOpen() { - return wbc.isOpen(); - } - - public long position() throws IOException { - return written; - } - - public SeekableByteChannel position(long pos) - throws IOException - { - throw new UnsupportedOperationException(); - } - - public int read(ByteBuffer dst) throws IOException { - throw new UnsupportedOperationException(); - } - - public SeekableByteChannel truncate(long size) - throws IOException - { - throw new UnsupportedOperationException(); - } - - public int write(ByteBuffer src) throws IOException { - int n = wbc.write(src); - written += n; - return n; - } - - public long size() throws IOException { - return written; - } - - public void close() throws IOException { - wbc.close(); - } - }; - } finally { - endRead(); - } - } else { - beginRead(); - try { - ensureOpen(); - Entry e = getEntry0(path); - if (e == null || e.isDir()) - throw new NoSuchFileException(getString(path)); - final ReadableByteChannel rbc = - Channels.newChannel(getInputStream(e)); - final long size = e.size; - return new SeekableByteChannel() { - long read = 0; - public boolean isOpen() { - return rbc.isOpen(); - } - - public long position() throws IOException { - return read; - } - - public SeekableByteChannel position(long pos) - throws IOException - { - throw new UnsupportedOperationException(); - } - - public int read(ByteBuffer dst) throws IOException { - return rbc.read(dst); - } - - public SeekableByteChannel truncate(long size) - throws IOException - { - throw new NonWritableChannelException(); - } - - public int write (ByteBuffer src) throws IOException { - throw new NonWritableChannelException(); - } - - public long size() throws IOException { - return size; - } - - public void close() throws IOException { - rbc.close(); - } - }; - } finally { - endRead(); - } - } - } - - // Returns a FileChannel of the specified entry. - // - // This implementation creates a temporary file on the default file system, - // copy the entry data into it if the entry exists, and then create a - // FileChannel on top of it. - FileChannel newFileChannel(byte[] path, - Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - checkOptions(options); - final boolean forWrite = (options.contains(StandardOpenOption.WRITE) || - options.contains(StandardOpenOption.APPEND)); - beginRead(); - try { - ensureOpen(); - Entry e = getEntry0(path); - if (forWrite) { - checkWritable(); - if (e == null) { - if (!options.contains(StandardOpenOption.CREATE_NEW)) - throw new NoSuchFileException(getString(path)); - } else { - if (options.contains(StandardOpenOption.CREATE_NEW)) - throw new FileAlreadyExistsException(getString(path)); - if (e.isDir()) - throw new FileAlreadyExistsException("directory <" - + getString(path) + "> exists"); - } - options.remove(StandardOpenOption.CREATE_NEW); // for tmpfile - } else if (e == null || e.isDir()) { - throw new NoSuchFileException(getString(path)); - } - - final boolean isFCH = (e != null && e.type == Entry.FILECH); - final Path tmpfile = isFCH ? e.file : getTempPathForEntry(path); - final FileChannel fch = tmpfile.getFileSystem() - .provider() - .newFileChannel(tmpfile, options, attrs); - final Entry u = isFCH ? e : new Entry(path, tmpfile, Entry.FILECH); - if (forWrite) { - u.flag = FLAG_DATADESCR; - u.method = METHOD_DEFLATED; - } - // is there a better way to hook into the FileChannel's close method? - return new FileChannel() { - public int write(ByteBuffer src) throws IOException { - return fch.write(src); - } - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException - { - return fch.write(srcs, offset, length); - } - public long position() throws IOException { - return fch.position(); - } - public FileChannel position(long newPosition) - throws IOException - { - fch.position(newPosition); - return this; - } - public long size() throws IOException { - return fch.size(); - } - public FileChannel truncate(long size) - throws IOException - { - fch.truncate(size); - return this; - } - public void force(boolean metaData) - throws IOException - { - fch.force(metaData); - } - public long transferTo(long position, long count, - WritableByteChannel target) - throws IOException - { - return fch.transferTo(position, count, target); - } - public long transferFrom(ReadableByteChannel src, - long position, long count) - throws IOException - { - return fch.transferFrom(src, position, count); - } - public int read(ByteBuffer dst) throws IOException { - return fch.read(dst); - } - public int read(ByteBuffer dst, long position) - throws IOException - { - return fch.read(dst, position); - } - public long read(ByteBuffer[] dsts, int offset, int length) - throws IOException - { - return fch.read(dsts, offset, length); - } - public int write(ByteBuffer src, long position) - throws IOException - { - return fch.write(src, position); - } - public MappedByteBuffer map(MapMode mode, - long position, long size) - throws IOException - { - throw new UnsupportedOperationException(); - } - public FileLock lock(long position, long size, boolean shared) - throws IOException - { - return fch.lock(position, size, shared); - } - public FileLock tryLock(long position, long size, boolean shared) - throws IOException - { - return fch.tryLock(position, size, shared); - } - protected void implCloseChannel() throws IOException { - fch.close(); - if (forWrite) { - u.mtime = System.currentTimeMillis(); - u.size = Attributes.readBasicFileAttributes(u.file).size(); - update(u); - } else { - if (!isFCH) // if this is a new fch for reading - removeTempPathForEntry(tmpfile); - } - } - }; - } finally { - endRead(); - } - } - - // the outstanding input streams that need to be closed - private Set<InputStream> streams = - Collections.synchronizedSet(new HashSet<InputStream>()); - - // the ex-channel and ex-path that need to close when their outstanding - // input streams are all closed by the obtainers. - private Set<ExChannelCloser> exChClosers = new HashSet<>(); - - private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>()); - private Path getTempPathForEntry(byte[] path) throws IOException { - Path tmpPath = createTempFileInSameDirectoryAs(zfpath); - if (path != null) { - Entry e = getEntry0(path); - if (e != null) { - InputStream is = newInputStream(path); - OutputStream os = tmpPath.newOutputStream(WRITE); - try { - copyStream(is, os); - } finally { - is.close(); - os.close(); - } - } - } - return tmpPath; - } - - private void removeTempPathForEntry(Path path) throws IOException { - path.delete(); - tmppaths.remove(path); - } - - // check if all parents really exit. ZIP spec does not require - // the existence of any "parent directory". - private void checkParents(byte[] path) throws IOException { - beginRead(); - try { - while ((path = getParent(path)) != null) { - if (!inodes.containsKey(IndexNode.keyOf(path))) - throw new NoSuchFileException(getString(path)); - } - } finally { - endRead(); - } - } - - private static byte[] getParent(byte[] path) { - int off = path.length - 1; - if (off > 0 && path[off] == '/') // isDirectory - off--; - while (off > 0 && path[off] != '/') { off--; } - if (off == 0) - return null; // top entry - return Arrays.copyOf(path, off + 1); - } - - // If "starter" is the parent directory of "path" - private static boolean isParentOf(byte[] p, byte[] c) { - final int plen = p.length; - if (plen == 0) // root dir - return true; - if (plen >= c.length) - return false; - int n = 0; - while (n < plen) { - if (p[n] != c[n]) - return false; - n++; - } - if (p[n - 1] != '/' && (c[n] != '/' || n == c.length - 1)) - return false; - return true; - } - - private final void beginWrite() { - rwlock.writeLock().lock(); - } - - private final void endWrite() { - rwlock.writeLock().unlock(); - } - - private final void beginRead() { - rwlock.readLock().lock(); - } - - private final void endRead() { - rwlock.readLock().unlock(); - } - - /////////////////////////////////////////////////////////////////// - - private volatile boolean isOpen = true; - private final SeekableByteChannel ch; // channel to the zipfile - final byte[] cen; // CEN & ENDHDR - private END end; - private long locpos; // position of first LOC header (usually 0) - - private final ReadWriteLock rwlock = new ReentrantReadWriteLock(); - - // name -> pos (in cen), IndexNode itself can be used as a "key" - private LinkedHashMap<IndexNode, IndexNode> inodes; - - final byte[] getBytes(String name) { - return zc.getBytes(name); - } - - final String getString(byte[] name) { - return zc.toString(name); - } - - protected void finalize() throws IOException { - close(); - } - - private long getDataPos(Entry e) throws IOException { - if (e.locoff == -1) { - Entry e2 = getEntry0(e.name); - if (e2 == null) - throw new ZipException("invalid loc for entry <" + e.name + ">"); - e.locoff = e2.locoff; - } - byte[] buf = new byte[LOCHDR]; - if (readFullyAt(buf, 0, buf.length, e.locoff) != buf.length) - throw new ZipException("invalid loc for entry <" + e.name + ">"); - return locpos + e.locoff + LOCHDR + LOCNAM(buf) + LOCEXT(buf); - } - - // Reads len bytes of data from the specified offset into buf. - // Returns the total number of bytes read. - // Each/every byte read from here (except the cen, which is mapped). - final long readFullyAt(byte[] buf, int off, long len, long pos) - throws IOException - { - ByteBuffer bb = ByteBuffer.wrap(buf); - bb.position(off); - bb.limit((int)(off + len)); - return readFullyAt(bb, pos); - } - - private final long readFullyAt(ByteBuffer bb, long pos) - throws IOException - { - synchronized(ch) { - return ch.position(pos).read(bb); - } - } - - // Searches for end of central directory (END) header. The contents of - // the END header will be read and placed in endbuf. Returns the file - // position of the END header, otherwise returns -1 if the END header - // was not found or an error occurred. - private END findEND() throws IOException - { - byte[] buf = new byte[READBLOCKSZ]; - long ziplen = ch.size(); - long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0; - long minPos = minHDR - (buf.length - ENDHDR); - - for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR)) - { - int off = 0; - if (pos < 0) { - // Pretend there are some NUL bytes before start of file - off = (int)-pos; - Arrays.fill(buf, 0, off, (byte)0); - } - int len = buf.length - off; - if (readFullyAt(buf, off, len, pos + off) != len) - zerror("zip END header not found"); - - // Now scan the block backwards for END header signature - for (int i = buf.length - ENDHDR; i >= 0; i--) { - if (buf[i+0] == (byte)'P' && - buf[i+1] == (byte)'K' && - buf[i+2] == (byte)'\005' && - buf[i+3] == (byte)'\006' && - (pos + i + ENDHDR + ENDCOM(buf, i) == ziplen)) { - // Found END header - buf = Arrays.copyOfRange(buf, i, i + ENDHDR); - END end = new END(); - end.endsub = ENDSUB(buf); - end.centot = ENDTOT(buf); - end.cenlen = ENDSIZ(buf); - end.cenoff = ENDOFF(buf); - end.comlen = ENDCOM(buf); - end.endpos = pos + i; - if (end.cenlen == ZIP64_MINVAL || - end.cenoff == ZIP64_MINVAL || - end.centot == ZIP64_MINVAL32) - { - // need to find the zip64 end; - byte[] loc64 = new byte[ZIP64_LOCHDR]; - if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR) - != loc64.length) { - return end; - } - long end64pos = ZIP64_LOCOFF(loc64); - byte[] end64buf = new byte[ZIP64_ENDHDR]; - if (readFullyAt(end64buf, 0, end64buf.length, end64pos) - != end64buf.length) { - return end; - } - // end64 found, re-calcualte everything. - end.cenlen = ZIP64_ENDSIZ(end64buf); - end.cenoff = ZIP64_ENDOFF(end64buf); - end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g - end.endpos = end64pos; - } - return end; - } - } - } - zerror("zip END header not found"); - return null; //make compiler happy - } - - // Reads zip file central directory. Returns the file position of first - // CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL - // then the error was a zip format error and zip->msg has the error text. - // Always pass in -1 for knownTotal; it's used for a recursive call. - private byte[] initCEN() throws IOException { - end = findEND(); - if (end.endpos == 0) { - inodes = new LinkedHashMap<>(10); - locpos = 0; - return null; // only END header present - } - if (end.cenlen > end.endpos) - zerror("invalid END header (bad central directory size)"); - long cenpos = end.endpos - end.cenlen; // position of CEN table - - // Get position of first local file (LOC) header, taking into - // account that there may be a stub prefixed to the zip file. - locpos = cenpos - end.cenoff; - if (locpos < 0) - zerror("invalid END header (bad central directory offset)"); - - // read in the CEN and END - byte[] cen = new byte[(int)(end.cenlen + ENDHDR)]; - if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { - zerror("read CEN tables failed"); - } - // Iterate through the entries in the central directory - inodes = new LinkedHashMap<>(end.centot + 1); - int pos = 0; - int limit = cen.length - ENDHDR; - while (pos < limit) { - if (CENSIG(cen, pos) != CENSIG) - zerror("invalid CEN header (bad signature)"); - int method = CENHOW(cen, pos); - int nlen = CENNAM(cen, pos); - int elen = CENEXT(cen, pos); - int clen = CENCOM(cen, pos); - if ((CENFLG(cen, pos) & 1) != 0) - zerror("invalid CEN header (encrypted entry)"); - if (method != METHOD_STORED && method != METHOD_DEFLATED) - zerror("invalid CEN header (unsupported compression method: " + method + ")"); - if (pos + CENHDR + nlen > limit) - zerror("invalid CEN header (bad header size)"); - byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen); - IndexNode inode = new IndexNode(name, pos); - inodes.put(inode, inode); - // skip ext and comment - pos += (CENHDR + nlen + elen + clen); - } - if (pos + ENDHDR != cen.length) { - zerror("invalid CEN header (bad header size)"); - } - return cen; - } - - private void ensureOpen() throws IOException { - if (!isOpen) - throw new ClosedFileSystemException(); - } - - // Creates a new empty temporary file in the same directory as the - // specified file. A variant of File.createTempFile. - private Path createTempFileInSameDirectoryAs(Path path) - throws IOException - { - Path parent = path.toAbsolutePath().getParent(); - String dir = (parent == null)? "." : parent.toString(); - Path tmpPath = File.createTempFile("zipfstmp", null, new File(dir)).toPath(); - tmppaths.add(tmpPath); - return tmpPath; - } - - ////////////////////update & sync ////////////////////////////////////// - - private boolean hasUpdate = false; - - private void updateDelete(Entry e) { - beginWrite(); - try { - inodes.remove(IndexNode.keyOf(e.name)); //inodes.remove(e.name); - hasUpdate = true; - dirs = null; - } finally { - endWrite(); - } - } - - private void update(Entry e) { - beginWrite(); - try { - inodes.put(IndexNode.keyOf(e.name), e); //inodes.put(e, e); - hasUpdate = true; - dirs = null; - } finally { - endWrite(); - } - } - - // copy over the whole LOC entry (header if necessary, data and ext) from - // old zip to the new one. - private long copyLOCEntry(Entry e, boolean updateHeader, - OutputStream os, - long written, byte[] buf) - throws IOException - { - long locoff = e.locoff; // where to read - e.locoff = written; // update the e.locoff with new value - - // calculate the size need to write out - long size = 0; - // if there is A ext - if ((e.flag & FLAG_DATADESCR) != 0) { - if (e.size >= ZIP64_MINVAL || e.csize >= ZIP64_MINVAL) - size = 24; - else - size = 16; - } - // read loc, use the original loc.elen/nlen - if (readFullyAt(buf, 0, LOCHDR , locoff) != LOCHDR) - throw new ZipException("loc: reading failed"); - if (updateHeader) { - locoff += LOCHDR + LOCNAM(buf) + LOCEXT(buf); // skip header - size += e.csize; - written = e.writeLOC(os) + size; - } else { - os.write(buf, 0, LOCHDR); // write out the loc header - locoff += LOCHDR; - size += LOCNAM(buf) + LOCEXT(buf) + LOCSIZ(buf); - written = LOCHDR + size; - } - int n; - while (size > 0 && - (n = (int)readFullyAt(buf, 0, buf.length, locoff)) != -1) - { - if (size < n) - n = (int)size; - os.write(buf, 0, n); - size -= n; - locoff += n; - } - return written; - } - - // sync the zip file system, if there is any udpate - private void sync() throws IOException { - //System.out.printf("->sync(%s) starting....!%n", toString()); - - // check ex-closer - if (!exChClosers.isEmpty()) { - for (ExChannelCloser ecc : exChClosers) { - if (ecc.streams.isEmpty()) { - ecc.ch.close(); - ecc.path.delete(); - exChClosers.remove(ecc); - } - } - } - if (!hasUpdate) - return; - Path tmpFile = createTempFileInSameDirectoryAs(zfpath); - OutputStream os = tmpFile.newOutputStream(WRITE); - ArrayList<Entry> elist = new ArrayList<>(inodes.size()); - long written = 0; - byte[] buf = new byte[8192]; - Entry e = null; - - // write loc - for (IndexNode inode : inodes.values()) { - if (inode instanceof Entry) { // an updated inode - e = (Entry)inode; - try { - if (e.type == Entry.COPY) { - // entry copy: the only thing changed is the "name" - // and "nlen" in LOC header, so we udpate/rewrite the - // LOC in new file and simply copy the rest (data and - // ext) without enflating/deflating from the old zip - // file LOC entry. - written += copyLOCEntry(e, true, os, written, buf); - } else { // NEW or FILECH - e.locoff = written; - written += e.writeLOC(os); // write loc header - if (e.bytes != null) { // in-memory, deflated - os.write(e.bytes); // already - written += e.bytes.length; - } else if (e.file != null) { // tmp file - InputStream is = e.file.newInputStream(); - int n; - if (e.type == Entry.NEW) { // deflated already - while ((n = is.read(buf)) != -1) { - os.write(buf, 0, n); - written += n; - } - } else if (e.type == Entry.FILECH) { - // the data are not deflated, use ZEOS - OutputStream os2 = new EntryOutputStream(e, os); - while ((n = is.read(buf)) != -1) { - os2.write(buf, 0, n); - } - os2.close(); - written += e.csize; - if ((e.flag & FLAG_DATADESCR) != 0) - written += e.writeEXT(os); - } - is.close(); - e.file.delete(); - tmppaths.remove(e.file); - } else { - // dir, 0-length data - } - } - elist.add(e); - } catch (IOException x) { - x.printStackTrace(); // skip any in-accurate entry - } - } else { // unchanged inode - e = Entry.readCEN(this, inode.pos); - try { - written += copyLOCEntry(e, false, os, written, buf); - elist.add(e); - } catch (IOException x) { - x.printStackTrace(); // skip any wrong entry - } - } - } - - // now write back the cen and end table - end.cenoff = written; - for (Entry entry : elist) { - written += entry.writeCEN(os); - } - end.centot = elist.size(); - end.cenlen = written - end.cenoff; - end.write(os, written); - os.close(); - - if (!streams.isEmpty()) { - // - // TBD: ExChannelCloser should not be necessary if we only - // sync when being closed, all streams should have been - // closed already. Keep the logic here for now. - // - // There are outstanding input streams open on existing "ch", - // so, don't close the "cha" and delete the "file for now, let - // the "ex-channel-closer" to handle them - ExChannelCloser ecc = new ExChannelCloser( - createTempFileInSameDirectoryAs(zfpath), - ch, - streams); - zfpath.moveTo(ecc.path, REPLACE_EXISTING); - exChClosers.add(ecc); - streams = Collections.synchronizedSet(new HashSet<InputStream>()); - } else { - ch.close(); - zfpath.delete(); - } - - tmpFile.moveTo(zfpath, REPLACE_EXISTING); - hasUpdate = false; // clear - /* - if (isOpen) { - ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen" - cen = initCEN(); - } - */ - //System.out.printf("->sync(%s) done!%n", toString()); - } - - private Entry getEntry0(byte[] path) throws IOException { - if (path == null) - throw new NullPointerException("path"); - if (path.length == 0) - return null; - IndexNode inode = null; - IndexNode key = IndexNode.keyOf(path); - if ((inode = inodes.get(key)) == null) { - if (path[path.length -1] == '/') // already has a slash - return null; - path = Arrays.copyOf(path, path.length + 1); - path[path.length - 1] = '/'; - if ((inode = inodes.get(key.as(path))) == null) - return null; - } - if (inode instanceof Entry) - return (Entry)inode; - return Entry.readCEN(this, inode.pos); - } - - // Test if the "name" a parent directory of any entry (dir empty) - boolean isAncestor(byte[] name) { - for (Map.Entry<IndexNode, IndexNode> entry : inodes.entrySet()) { - byte[] ename = entry.getKey().name; - if (isParentOf(name, ename)) - return true; - } - return false; - } - - public void deleteFile(byte[] path, boolean failIfNotExists) - throws IOException - { - checkWritable(); - Entry e = getEntry0(path); - if (e == null) { - if (path != null && path.length == 0) - throw new ZipException("root directory </> can't not be delete"); - if (failIfNotExists) - throw new NoSuchFileException(getString(path)); - } else { - if (e.isDir() && isAncestor(path)) - throw new DirectoryNotEmptyException(getString(path)); - updateDelete(e); - } - } - - private static void copyStream(InputStream is, OutputStream os) - throws IOException - { - byte[] copyBuf = new byte[8192]; - int n; - while ((n = is.read(copyBuf)) != -1) { - os.write(copyBuf, 0, n); - } - } - - // Returns an out stream for either - // (1) writing the contents of a new entry, if the entry exits, or - // (2) updating/replacing the contents of the specified existing entry. - private OutputStream getOutputStream(Entry e) throws IOException { - - if (e.mtime == -1) - e.mtime = System.currentTimeMillis(); - if (e.method == -1) - e.method = METHOD_DEFLATED; // TBD: use default method - // store size, compressed size, and crc-32 in LOC header - e.flag = 0; - if (zc.isUTF8()) - e.flag |= FLAG_EFS; - OutputStream os; - if (useTempFile) { - e.file = getTempPathForEntry(null); - os = e.file.newOutputStream(WRITE); - } else { - os = new ByteArrayOutputStream((e.size > 0)? (int)e.size : 8192); - } - return new EntryOutputStream(e, os); - } - - private InputStream getInputStream(Entry e) - throws IOException - { - InputStream eis = null; - - if (e.type == Entry.NEW) { - if (e.bytes != null) - eis = new ByteArrayInputStream(e.bytes); - else if (e.file != null) - eis = e.file.newInputStream(); - else - throw new ZipException("update entry data is missing"); - } else if (e.type == Entry.FILECH) { - // FILECH result is un-compressed. - eis = e.file.newInputStream(); - // TBD: wrap to hook close() - // streams.add(eis); - return eis; - } else { // untouced CEN or COPY - eis = new EntryInputStream(e, ch); - } - if (e.method == METHOD_DEFLATED) { - // MORE: Compute good size for inflater stream: - long bufSize = e.size + 2; // Inflater likes a bit of slack - if (bufSize > 65536) - bufSize = 8192; - final long size = e.size; - eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) { - - private boolean isClosed = false; - public void close() throws IOException { - if (!isClosed) { - releaseInflater(inf); - this.in.close(); - isClosed = true; - streams.remove(this); - } - } - // Override fill() method to provide an extra "dummy" byte - // at the end of the input stream. This is required when - // using the "nowrap" Inflater option. (it appears the new - // zlib in 7 does not need it, but keep it for now) - protected void fill() throws IOException { - if (eof) { - throw new EOFException( - "Unexpected end of ZLIB input stream"); - } - len = this.in.read(buf, 0, buf.length); - if (len == -1) { - buf[0] = 0; - len = 1; - eof = true; - } - inf.setInput(buf, 0, len); - } - private boolean eof; - - public int available() throws IOException { - if (isClosed) - return 0; - long avail = size - inf.getBytesWritten(); - return avail > (long) Integer.MAX_VALUE ? - Integer.MAX_VALUE : (int) avail; - } - }; - } else if (e.method == METHOD_STORED) { - // TBD: wrap/ it does not seem necessary - } else { - throw new ZipException("invalid compression method"); - } - streams.add(eis); - return eis; - } - - // Inner class implementing the input stream used to read - // a (possibly compressed) zip file entry. - private class EntryInputStream extends InputStream { - private final SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might - // point to a new channel after sync() - private long pos; // current position within entry data - protected long rem; // number of remaining bytes within entry - protected final long size; // uncompressed size of this entry - - EntryInputStream(Entry e, SeekableByteChannel zfch) - throws IOException - { - this.zfch = zfch; - rem = e.csize; - size = e.size; - pos = getDataPos(e); - } - public int read(byte b[], int off, int len) throws IOException { - ensureOpen(); - if (rem == 0) { - return -1; - } - if (len <= 0) { - return 0; - } - if (len > rem) { - len = (int) rem; - } - // readFullyAt() - long n = 0; - ByteBuffer bb = ByteBuffer.wrap(b); - bb.position(off); - bb.limit(off + len); - synchronized(zfch) { - n = zfch.position(pos).read(bb); - } - if (n > 0) { - pos += n; - rem -= n; - } - if (rem == 0) { - close(); - } - return (int)n; - } - public int read() throws IOException { - byte[] b = new byte[1]; - if (read(b, 0, 1) == 1) { - return b[0] & 0xff; - } else { - return -1; - } - } - public long skip(long n) throws IOException { - ensureOpen(); - if (n > rem) - n = rem; - pos += n; - rem -= n; - if (rem == 0) { - close(); - } - return n; - } - public int available() { - return rem > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) rem; - } - - public long size() { - return size; - } - public void close() { - rem = 0; - streams.remove(this); - } - } - - class EntryOutputStream extends DeflaterOutputStream - { - private CRC32 crc; - private Entry e; - private long written; - - EntryOutputStream(Entry e, OutputStream os) - throws IOException - { - super(os, getDeflater()); - if (e == null) - throw new NullPointerException("Zip entry is null"); - this.e = e; - crc = new CRC32(); - } - - @Override - public void write(byte b[], int off, int len) throws IOException { - if (e.type != Entry.FILECH) // only from sync - ensureOpen(); - if (off < 0 || len < 0 || off > b.length - len) { - throw new IndexOutOfBoundsException(); - } else if (len == 0) { - return; - } - switch (e.method) { - case METHOD_DEFLATED: - super.write(b, off, len); - break; - case METHOD_STORED: - written += len; - out.write(b, off, len); - break; - default: - throw new ZipException("invalid compression method"); - } - crc.update(b, off, len); - } - - @Override - public void close() throws IOException { - // TBD ensureOpen(); - switch (e.method) { - case METHOD_DEFLATED: - finish(); - e.size = def.getBytesRead(); - e.csize = def.getBytesWritten(); - e.crc = crc.getValue(); - break; - case METHOD_STORED: - // we already know that both e.size and e.csize are the same - e.size = e.csize = written; - e.crc = crc.getValue(); - break; - default: - throw new ZipException("invalid compression method"); - } - //crc.reset(); - if (out instanceof ByteArrayOutputStream) - e.bytes = ((ByteArrayOutputStream)out).toByteArray(); - - if (e.type == Entry.FILECH) { - releaseDeflater(def); - return; - } - super.close(); - releaseDeflater(def); - update(e); - } - } - - static void zerror(String msg) { - throw new ZipError(msg); - } - - // Maxmum number of de/inflater we cache - private final int MAX_FLATER = 20; - // List of available Inflater objects for decompression - private final List<Inflater> inflaters = new ArrayList<>(); - - // Gets an inflater from the list of available inflaters or allocates - // a new one. - private Inflater getInflater() { - synchronized (inflaters) { - int size = inflaters.size(); - if (size > 0) { - Inflater inf = (Inflater)inflaters.remove(size - 1); - return inf; - } else { - return new Inflater(true); - } - } - } - - // Releases the specified inflater to the list of available inflaters. - private void releaseInflater(Inflater inf) { - synchronized (inflaters) { - if (inflaters.size() < MAX_FLATER) { - inf.reset(); - inflaters.add(inf); - } else { - inf.end(); - } - } - } - - // List of available Deflater objects for compression - private final List<Deflater> deflaters = new ArrayList<>(); - - // Gets an deflater from the list of available deflaters or allocates - // a new one. - private Deflater getDeflater() { - synchronized (deflaters) { - int size = deflaters.size(); - if (size > 0) { - Deflater def = (Deflater)deflaters.remove(size - 1); - return def; - } else { - return new Deflater(Deflater.DEFAULT_COMPRESSION, true); - } - } - } - - // Releases the specified inflater to the list of available inflaters. - private void releaseDeflater(Deflater def) { - synchronized (deflaters) { - if (inflaters.size() < MAX_FLATER) { - def.reset(); - deflaters.add(def); - } else { - def.end(); - } - } - } - - // End of central directory record - static class END { - int disknum; - int sdisknum; - int endsub; // endsub - int centot; // 4 bytes - long cenlen; // 4 bytes - long cenoff; // 4 bytes - int comlen; // comment length - byte[] comment; - - /* members of Zip64 end of central directory locator */ - int diskNum; - long endpos; - int disktot; - - void write(OutputStream os, long offset) throws IOException { - boolean hasZip64 = false; - long xlen = cenlen; - long xoff = cenoff; - if (xlen >= ZIP64_MINVAL) { - xlen = ZIP64_MINVAL; - hasZip64 = true; - } - if (xoff >= ZIP64_MINVAL) { - xoff = ZIP64_MINVAL; - hasZip64 = true; - } - int count = centot; - if (count >= ZIP64_MINVAL32) { - count = ZIP64_MINVAL32; - hasZip64 = true; - } - if (hasZip64) { - long off64 = offset; - //zip64 end of central directory record - writeInt(os, ZIP64_ENDSIG); // zip64 END record signature - writeLong(os, ZIP64_ENDHDR - 12); // size of zip64 end - writeShort(os, 45); // version made by - writeShort(os, 45); // version needed to extract - writeInt(os, 0); // number of this disk - writeInt(os, 0); // central directory start disk - writeLong(os, centot); // number of directory entires on disk - writeLong(os, centot); // number of directory entires - writeLong(os, cenlen); // length of central directory - writeLong(os, cenoff); // offset of central directory - - //zip64 end of central directory locator - writeInt(os, ZIP64_LOCSIG); // zip64 END locator signature - writeInt(os, 0); // zip64 END start disk - writeLong(os, off64); // offset of zip64 END - writeInt(os, 1); // total number of disks (?) - } - writeInt(os, ENDSIG); // END record signature - writeShort(os, 0); // number of this disk - writeShort(os, 0); // central directory start disk - writeShort(os, count); // number of directory entries on disk - writeShort(os, count); // total number of directory entries - writeInt(os, xlen); // length of central directory - writeInt(os, xoff); // offset of central directory - if (comment != null) { // zip file comment - writeShort(os, comment.length); - writeBytes(os, comment); - } else { - writeShort(os, 0); - } - } - } - - // Internal node that links a "name" to its pos in cen table. - // The node itself can be used as a "key" to lookup itself in - // the HashMap inodes. - static class IndexNode { - byte[] name; - int hashcode; // node is hashable/hashed by its name - int pos = -1; // postion in cen table, -1 menas the - // entry does not exists in zip file - IndexNode(byte[] name, int pos) { - as(name); - this.pos = pos; - } - - final static IndexNode keyOf(byte[] name) { // get a lookup key; - return new IndexNode(name, -1); - } - - final IndexNode as(byte[] name) { // reuse the node, mostly - this.name = name; // as a lookup "key" - this.hashcode = Arrays.hashCode(name); - return this; - } - - public boolean equals(Object other) { - if (!(other instanceof IndexNode)) - return false; - return Arrays.equals(name, ((IndexNode)other).name); - } - - public int hashCode() { - return hashcode; - } - - IndexNode() {} - IndexNode sibling; - IndexNode child; // 1st child - } - - static class Entry extends IndexNode { - - static final int CEN = 1; // entry read from cen - static final int NEW = 2; // updated contents in bytes or file - static final int FILECH = 3; // fch update in "file" - static final int COPY = 4; // copy of a CEN entry - - byte[] bytes; // updated content bytes - Path file; // use tmp file to store bytes; - int type = CEN; // default is the entry read from cen - - // entry attributes - int version; - int flag; - int method = -1; // compression method - long mtime = -1; // last modification time (in DOS time) - long atime = -1; // last access time - long ctime = -1; // create time - long crc = -1; // crc-32 of entry data - long csize = -1; // compressed size of entry data - long size = -1; // uncompressed size of entry data - byte[] extra; - - // cen - int versionMade; - int disk; - int attrs; - long attrsEx; - long locoff; - byte[] comment; - - Entry() {} - - Entry(byte[] name) { - this.name = name; - this.mtime = System.currentTimeMillis(); - this.crc = 0; - this.size = 0; - this.csize = 0; - this.method = METHOD_DEFLATED; - } - - Entry(byte[] name, int type) { - this(name); - this.type = type; - } - - Entry (Entry e, int type) { - this.version = e.version; - this.name = e.name; - this.ctime = e.ctime; - this.atime = e.atime; - this.mtime = e.mtime; - this.crc = e.crc; - this.size = e.size; - this.csize = e.csize; - this.method = e.method; - this.extra = e.extra; - this.versionMade = e.versionMade; - this.disk = e.disk; - this.attrs = e.attrs; - this.attrsEx = e.attrsEx; - this.locoff = e.locoff; - this.comment = e.comment; - - this.type = type; - } - - Entry (byte[] name, Path file, int type) { - this(name, type); - this.file = file; - this.method = METHOD_STORED; - } - - boolean isDir() { - return name != null && - (name.length == 0 || - name[name.length - 1] == '/'); - } - - int version() throws ZipException { - if (method == METHOD_DEFLATED) - return 20; - else if (method == METHOD_STORED) - return 10; - throw new ZipException("unsupported compression method"); - } - - ///////////////////// CEN ////////////////////// - static Entry readCEN(ZipFileSystem zipfs, int pos) - throws IOException - { - return new Entry().cen(zipfs, pos); - } - - private Entry cen(ZipFileSystem zipfs, int pos) - throws IOException - { - byte[] cen = zipfs.cen; - if (CENSIG(cen, pos) != CENSIG) - zerror("invalid CEN header (bad signature)"); - versionMade = CENVEM(cen, pos); - version = CENVER(cen, pos); - flag = CENFLG(cen, pos); - method = CENHOW(cen, pos); - mtime = dosToJavaTime(CENTIM(cen, pos)); - crc = CENCRC(cen, pos); - csize = CENSIZ(cen, pos); - size = CENLEN(cen, pos); - int nlen = CENNAM(cen, pos); - int elen = CENEXT(cen, pos); - int clen = CENCOM(cen, pos); - disk = CENDSK(cen, pos); - attrs = CENATT(cen, pos); - attrsEx = CENATX(cen, pos); - locoff = CENOFF(cen, pos); - - pos += CENHDR; - name = Arrays.copyOfRange(cen, pos, pos + nlen); - - pos += nlen; - if (elen > 0) { - extra = Arrays.copyOfRange(cen, pos, pos + elen); - pos += elen; - readExtra(zipfs); - } - if (clen > 0) { - comment = Arrays.copyOfRange(cen, pos, pos + clen); - } - return this; - } - - int writeCEN(OutputStream os) throws IOException - { - int written = CENHDR; - int version0 = version(); - - long csize0 = csize; - long size0 = size; - long locoff0 = locoff; - int elen64 = 0; // extra for ZIP64 - int elenNTFS = 0; // extra for NTFS (a/c/mtime) - int elenEXTT = 0; // extra for Extended Timestamp - - // confirm size/length - int nlen = (name != null) ? name.length : 0; - int elen = (extra != null) ? extra.length : 0; - int clen = (comment != null) ? comment.length : 0; - if (csize >= ZIP64_MINVAL) { - csize0 = ZIP64_MINVAL; - elen64 += 8; // csize(8) - } - if (size >= ZIP64_MINVAL) { - size0 = ZIP64_MINVAL; // size(8) - elen64 += 8; - } - if (locoff >= ZIP64_MINVAL) { - locoff0 = ZIP64_MINVAL; - elen64 += 8; // offset(8) - } - if (elen64 != 0) - elen64 += 4; // header and data sz 4 bytes - - if (atime != -1) { - if (isWindows) // use NTFS - elenNTFS = 36; // total 36 bytes - else // Extended Timestamp otherwise - elenEXTT = 9; // only mtime in cen - } - writeInt(os, CENSIG); // CEN header signature - if (elen64 != 0) { - writeShort(os, 45); // ver 4.5 for zip64 - writeShort(os, 45); - } else { - writeShort(os, version0); // version made by - writeShort(os, version0); // version needed to extract - } - writeShort(os, flag); // general purpose bit flag - writeShort(os, method); // compression method - // last modification time - writeInt(os, (int)javaToDosTime(mtime)); - writeInt(os, crc); // crc-32 - writeInt(os, csize0); // compressed size - writeInt(os, size0); // uncompressed size - writeShort(os, name.length); - writeShort(os, elen + elen64 + elenNTFS + elenEXTT); - - if (comment != null) { - writeShort(os, Math.min(clen, 0xffff)); - } else { - writeShort(os, 0); - } - writeShort(os, 0); // starting disk number - writeShort(os, 0); // internal file attributes (unused) - writeInt(os, 0); // external file attributes (unused) - writeInt(os, locoff0); // relative offset of local header - writeBytes(os, name); - if (elen64 != 0) { - writeShort(os, EXTID_ZIP64);// Zip64 extra - writeShort(os, elen64); // size of "this" extra block - if (size0 == ZIP64_MINVAL) - writeLong(os, size); - if (csize0 == ZIP64_MINVAL) - writeLong(os, csize); - if (locoff0 == ZIP64_MINVAL) - writeLong(os, locoff); - } - if (elenNTFS != 0) { - // System.out.println("writing NTFS:" + elenNTFS); - writeShort(os, EXTID_NTFS); - writeShort(os, elenNTFS - 4); - writeInt(os, 0); // reserved - writeShort(os, 0x0001); // NTFS attr tag - writeShort(os, 24); - writeLong(os, javaToWinTime(mtime)); - writeLong(os, javaToWinTime(atime)); - writeLong(os, javaToWinTime(ctime)); - } - if (elenEXTT != 0) { - writeShort(os, EXTID_EXTT); - writeShort(os, elenEXTT - 4); - if (ctime == -1) - os.write(0x3); // mtime and atime - else - os.write(0x7); // mtime, atime and ctime - writeInt(os, javaToUnixTime(mtime)); - } - if (extra != null) // whatever not recognized - writeBytes(os, extra); - if (comment != null) //TBD: 0, Math.min(commentBytes.length, 0xffff)); - writeBytes(os, comment); - return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT; - } - - ///////////////////// LOC ////////////////////// - static Entry readLOC(ZipFileSystem zipfs, long pos) - throws IOException - { - return readLOC(zipfs, pos, new byte[1024]); - } - - static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf) - throws IOException - { - return new Entry().loc(zipfs, pos, buf); - } - - Entry loc(ZipFileSystem zipfs, long pos, byte[] buf) - throws IOException - { - assert (buf.length >= LOCHDR); - if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) - throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) - throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); - //startPos = pos; - version = LOCVER(buf); - flag = LOCFLG(buf); - method = LOCHOW(buf); - mtime = dosToJavaTime(LOCTIM(buf)); - crc = LOCCRC(buf); - csize = LOCSIZ(buf); - size = LOCLEN(buf); - int nlen = LOCNAM(buf); - int elen = LOCEXT(buf); - - name = new byte[nlen]; - if (zipfs.readFullyAt(name, 0, nlen, pos + LOCHDR) != nlen) { - throw new ZipException("loc: name reading failed"); - } - if (elen > 0) { - extra = new byte[elen]; - if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen) - != elen) { - throw new ZipException("loc: ext reading failed"); - } - } - pos += (LOCHDR + nlen + elen); - if ((flag & FLAG_DATADESCR) != 0) { - // Data Descriptor - Entry e = zipfs.getEntry0(name); // get the size/csize from cen - if (e == null) - throw new ZipException("loc: name not found in cen"); - size = e.size; - csize = e.csize; - pos += (method == METHOD_STORED ? size : csize); - if (size >= ZIP64_MINVAL || csize >= ZIP64_MINVAL) - pos += 24; - else - pos += 16; - } else { - if (extra != null && - (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) { - // zip64 ext: must include both size and csize - int off = 0; - while (off + 20 < elen) { // HeaderID+DataSize+Data - int sz = SH(extra, off + 2); - if (SH(extra, off) == EXTID_ZIP64 && sz == 16) { - size = LL(extra, off + 4); - csize = LL(extra, off + 12); - break; - } - off += (sz + 4); - } - } - pos += (method == METHOD_STORED ? size : csize); - } - return this; - } - - int writeLOC(OutputStream os) - throws IOException - { - writeInt(os, LOCSIG); // LOC header signature - int version = version(); - - int nlen = (name != null) ? name.length : 0; - int elen = (extra != null) ? extra.length : 0; - int elen64 = 0; - int elenEXTT = 0; - if ((flag & FLAG_DATADESCR) != 0) { - writeShort(os, version()); // version needed to extract - writeShort(os, flag); // general purpose bit flag - writeShort(os, method); // compression method - // last modification time - writeInt(os, (int)javaToDosTime(mtime)); - // store size, uncompressed size, and crc-32 in data descriptor - // immediately following compressed entry data - writeInt(os, 0); - writeInt(os, 0); - writeInt(os, 0); - } else { - if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) { - elen64 = 20; //headid(2) + size(2) + size(8) + csize(8) - writeShort(os, 45); // ver 4.5 for zip64 - } else { - writeShort(os, version()); // version needed to extract - } - writeShort(os, flag); // general purpose bit flag - writeShort(os, method); // compression method - writeInt(os, mtime); // last modification time - writeInt(os, crc); // crc-32 - if (elen64 != 0) { - writeInt(os, ZIP64_MINVAL); - writeInt(os, ZIP64_MINVAL); - } else { - writeInt(os, csize); // compressed size - writeInt(os, size); // uncompressed size - } - } - if (atime != -1 && !isWindows) { // on unix use "ext time" - if (ctime == -1) - elenEXTT = 13; - else - elenEXTT = 17; - } - writeShort(os, name.length); - writeShort(os, elen + elen64 + elenEXTT); - writeBytes(os, name); - if (elen64 != 0) { - writeShort(os, EXTID_ZIP64); - writeShort(os, 16); - writeLong(os, size); - writeLong(os, csize); - } - if (elenEXTT != 0) { - writeShort(os, EXTID_EXTT); - writeShort(os, elenEXTT - 4);// size for the folowing data block - if (ctime == -1) - os.write(0x3); // mtime and atime - else - os.write(0x7); // mtime, atime and ctime - writeInt(os, javaToUnixTime(mtime)); - writeInt(os, javaToUnixTime(atime)); - if (ctime != -1) - writeInt(os, javaToUnixTime(ctime)); - } - if (extra != null) { - writeBytes(os, extra); - } - return LOCHDR + name.length + elen + elen64 + elenEXTT; - } - - // Data Descriptior - int writeEXT(OutputStream os) - throws IOException - { - writeInt(os, EXTSIG); // EXT header signature - writeInt(os, crc); // crc-32 - if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) { - writeLong(os, csize); - writeLong(os, size); - return 24; - } else { - writeInt(os, csize); // compressed size - writeInt(os, size); // uncompressed size - return 16; - } - } - - // read NTFS, UNIX and ZIP64 data from cen.extra - void readExtra(ZipFileSystem zipfs) throws IOException { - if (extra == null) - return; - int elen = extra.length; - int off = 0; - int newOff = 0; - while (off + 4 < elen) { - // extra spec: HeaderID+DataSize+Data - int pos = off; - int tag = SH(extra, pos); - int sz = SH(extra, pos + 2); - pos += 4; - if (pos + sz > elen) // invalid data - break; - switch (tag) { - case EXTID_ZIP64 : - if (size == ZIP64_MINVAL) { - if (pos + 8 > elen) // invalid zip64 extra - break; // fields, just skip - size = LL(extra, pos); - pos += 8; - } - if (csize == ZIP64_MINVAL) { - if (pos + 8 > elen) - break; - csize = LL(extra, pos); - pos += 8; - } - if (locoff == ZIP64_MINVAL) { - if (pos + 8 > elen) - break; - locoff = LL(extra, pos); - pos += 8; - } - break; - case EXTID_NTFS: - pos += 4; // reserved 4 bytes - if (SH(extra, pos) != 0x0001) - break; - if (SH(extra, pos + 2) != 24) - break; - // override the loc field, datatime here is - // more "accurate" - mtime = winToJavaTime(LL(extra, pos + 4)); - atime = winToJavaTime(LL(extra, pos + 12)); - ctime = winToJavaTime(LL(extra, pos + 20)); - break; - case EXTID_EXTT: - // spec says the Extened timestamp in cen only has mtime - // need to read the loc to get the extra a/ctime - byte[] buf = new byte[LOCHDR]; - if (zipfs.readFullyAt(buf, 0, buf.length , locoff) - != buf.length) - throw new ZipException("loc: reading failed"); - if (LOCSIG(buf) != LOCSIG) - throw new ZipException("loc: wrong sig ->" - + Long.toString(LOCSIG(buf), 16)); - - int locElen = LOCEXT(buf); - if (locElen < 9) // EXTT is at lease 9 bytes - break; - int locNlen = LOCNAM(buf); - buf = new byte[locElen]; - if (zipfs.readFullyAt(buf, 0, buf.length , locoff + LOCHDR + locNlen) - != buf.length) - throw new ZipException("loc extra: reading failed"); - int locPos = 0; - while (locPos + 4 < buf.length) { - int locTag = SH(buf, locPos); - int locSZ = SH(buf, locPos + 2); - locPos += 4; - if (locTag != EXTID_EXTT) { - locPos += locSZ; - continue; - } - int flag = CH(buf, locPos++); - if ((flag & 0x1) != 0) { - mtime = unixToJavaTime(LG(buf, locPos)); - locPos += 4; - } - if ((flag & 0x2) != 0) { - atime = unixToJavaTime(LG(buf, locPos)); - locPos += 4; - } - if ((flag & 0x4) != 0) { - ctime = unixToJavaTime(LG(buf, locPos)); - locPos += 4; - } - break; - } - break; - default: // unknown tag - System.arraycopy(extra, off, extra, newOff, sz + 4); - newOff += (sz + 4); - } - off += (sz + 4); - } - if (newOff != 0 && newOff != extra.length) - extra = Arrays.copyOf(extra, newOff); - else - extra = null; - } - } - - private static class ExChannelCloser { - Path path; - SeekableByteChannel ch; - Set<InputStream> streams; - ExChannelCloser(Path path, - SeekableByteChannel ch, - Set<InputStream> streams) - { - this.path = path; - this.ch = ch; - this.streams = streams; - } - } - - // ZIP directory has two issues: - // (1) ZIP spec does not require the ZIP file to include - // directory entry - // (2) all entries are not stored/organized in a "tree" - // structure. - // A possible solution is to build the node tree ourself as - // implemented below. - private HashMap<IndexNode, IndexNode> dirs; - private IndexNode root; - private IndexNode addToDir(IndexNode child) { - IndexNode cinode = dirs.get(child); - if (cinode != null) - return cinode; - - byte[] cname = child.name; - byte[] pname = getParent(cname); - IndexNode pinode; - - if (pname != null) - pinode = addToDir(IndexNode.keyOf(pname)); - else - pinode = root; - cinode = inodes.get(child); - if (cname[cname.length -1] != '/') { // not a dir - cinode.sibling = pinode.child; - pinode.child = cinode; - return null; - } - //cinode = dirs.get(child); - if (cinode == null) // pseudo directry entry - cinode = new IndexNode(cname, -1); - cinode.sibling = pinode.child; - pinode.child = cinode; - - dirs.put(child, cinode); - return cinode; - } - - private HashMap<IndexNode, IndexNode> getDirs() - throws IOException - { - beginWrite(); - try { - if (dirs != null) - return dirs; - dirs = new HashMap<>(); - root = new IndexNode(new byte[0], -1); - dirs.put(root, root); - for (IndexNode node : inodes.keySet()) - addToDir(node); - return dirs; - } finally { - endWrite(); - } - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.io.IOException; -import java.nio.channels.FileChannel; -import java.nio.file.FileRef; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystemAlreadyExistsException; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.ProviderMismatchException; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.spi.FileSystemProvider; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/* - * - * @author Xueming Shen, Rajendra Gutupalli, Jaya Hangal - */ - -public class ZipFileSystemProvider extends FileSystemProvider { - - - private final Map<Path, ZipFileSystem> filesystems = new HashMap<>(); - - public ZipFileSystemProvider() {} - - @Override - public String getScheme() { - return "zip"; - } - - protected Path uriToPath(URI uri) { - String scheme = uri.getScheme(); - if ((scheme == null) || !scheme.equalsIgnoreCase(getScheme())) { - throw new IllegalArgumentException("URI scheme is not '" + getScheme() + "'"); - } - try { - return Paths.get(new URI("file", uri.getHost(), uri.getPath(), null)) - .toAbsolutePath(); - } catch (URISyntaxException e) { - throw new AssertionError(e); //never thrown - } - } - - @Override - public FileSystem newFileSystem(URI uri, Map<String, ?> env) - throws IOException - { - return newFileSystem(uriToPath(uri), env); - } - - @Override - public FileSystem newFileSystem(FileRef file, Map<String, ?> env) - throws IOException - { - if (!(file instanceof Path)) - throw new UnsupportedOperationException(); - Path path = (Path)file; - if (!path.toUri().getScheme().equalsIgnoreCase("file")) { - throw new UnsupportedOperationException(); - } - return newFileSystem(path, env); - } - - private FileSystem newFileSystem(Path path, Map<String, ?> env) - throws IOException - { - synchronized(filesystems) { - Path realPath = null; - if (path.exists()) { - realPath = path.toRealPath(true); - if (filesystems.containsKey(realPath)) - throw new FileSystemAlreadyExistsException(); - } - ZipFileSystem zipfs = new ZipFileSystem(this, path, env); - if (realPath == null) - realPath = path.toRealPath(true); - filesystems.put(realPath, zipfs); - return zipfs; - } - } - - @Override - public Path getPath(URI uri) { - FileSystem fs = getFileSystem(uri); - String fragment = uri.getFragment(); - if (fragment == null) { - throw new IllegalArgumentException("URI: " - + uri - + " does not contain path fragment ex. zip:///c:/foo.zip#/BAR"); - } - return fs.getPath(fragment); - } - - @Override - public FileChannel newFileChannel(Path path, - Set<? extends OpenOption> options, - FileAttribute<?>... attrs) - throws IOException - { - if (path == null) - throw new NullPointerException("path is null"); - if (path instanceof ZipPath) - return ((ZipPath)path).newFileChannel(options, attrs); - throw new ProviderMismatchException(); - } - - @Override - public FileSystem getFileSystem(URI uri) { - synchronized (filesystems) { - ZipFileSystem zipfs = null; - try { - zipfs = filesystems.get(uriToPath(uri).toRealPath(true)); - } catch (IOException x) { - // ignore the ioe from toRealPath(), return FSNFE - } - if (zipfs == null) - throw new FileSystemNotFoundException(); - return zipfs; - } - } - - void removeFileSystem(Path zfpath) throws IOException { - synchronized (filesystems) { - filesystems.remove(zfpath.toRealPath(true)); - } - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.nio.file.Paths; -import java.util.Collections; -import java.util.Iterator; -import java.util.Map; -import com.sun.nio.zipfs.ZipFileSystem.Entry; -import static com.sun.nio.zipfs.ZipConstants.*; -import static com.sun.nio.zipfs.ZipUtils.*; - -/** - * Print all loc and cen headers of the ZIP file - * - * @author Xueming Shen - */ - -public class ZipInfo { - - public static void main(String[] args) throws Throwable { - if (args.length < 1) { - print("Usage: java ZipInfo zfname"); - } else { - Map<String, ?> env = Collections.emptyMap(); - ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider() - .newFileSystem(Paths.get(args[0]), env)); - byte[] cen = zfs.cen; - if (cen == null) { - print("zip file is empty%n"); - return; - } - int pos = 0; - byte[] buf = new byte[1024]; - int no = 1; - while (pos + CENHDR < cen.length) { - print("----------------#%d--------------------%n", no++); - printCEN(cen, pos); - - // use size CENHDR as the extra bytes to read, just in case the - // loc.extra is bigger than the cen.extra, try to avoid to read - // twice - long len = LOCHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENHDR; - if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) - zfs.zerror("read loc header failed"); - if (LOCEXT(buf) > CENEXT(cen, pos) + CENHDR) { - // have to read the second time; - len = LOCHDR + LOCNAM(buf) + LOCEXT(buf); - if (zfs.readFullyAt(buf, 0, len, locoff(cen, pos)) != len) - zfs.zerror("read loc header failed"); - } - printLOC(buf); - pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos); - } - zfs.close(); - } - } - - static void print(String fmt, Object... objs) { - System.out.printf(fmt, objs); - } - - static void printLOC(byte[] loc) { - print("%n"); - print("[Local File Header]%n"); - print(" Signature : %#010x%n", LOCSIG(loc)); - if (LOCSIG(loc) != LOCSIG) { - print(" Wrong signature!"); - return; - } - print(" Version : %#6x [%d.%d]%n", - LOCVER(loc), LOCVER(loc) / 10, LOCVER(loc) % 10); - print(" Flag : %#6x%n", LOCFLG(loc)); - print(" Method : %#6x%n", LOCHOW(loc)); - print(" LastMTime : %#10x [%tc]%n", - LOCTIM(loc), dosToJavaTime(LOCTIM(loc))); - print(" CRC : %#10x%n", LOCCRC(loc)); - print(" CSize : %#10x%n", LOCSIZ(loc)); - print(" Size : %#10x%n", LOCLEN(loc)); - print(" NameLength : %#6x [%s]%n", - LOCNAM(loc), new String(loc, LOCHDR, LOCNAM(loc))); - print(" ExtraLength : %#6x%n", LOCEXT(loc)); - if (LOCEXT(loc) != 0) - printExtra(loc, LOCHDR + LOCNAM(loc), LOCEXT(loc)); - } - - static void printCEN(byte[] cen, int off) { - print("[Central Directory Header]%n"); - print(" Signature : %#010x%n", CENSIG(cen, off)); - if (CENSIG(cen, off) != CENSIG) { - print(" Wrong signature!"); - return; - } - print(" VerMadeby : %#6x [%d, %d.%d]%n", - CENVEM(cen, off), (CENVEM(cen, off) >> 8), - (CENVEM(cen, off) & 0xff) / 10, - (CENVEM(cen, off) & 0xff) % 10); - print(" VerExtract : %#6x [%d.%d]%n", - CENVER(cen, off), CENVER(cen, off) / 10, CENVER(cen, off) % 10); - print(" Flag : %#6x%n", CENFLG(cen, off)); - print(" Method : %#6x%n", CENHOW(cen, off)); - print(" LastMTime : %#10x [%tc]%n", - CENTIM(cen, off), dosToJavaTime(CENTIM(cen, off))); - print(" CRC : %#10x%n", CENCRC(cen, off)); - print(" CSize : %#10x%n", CENSIZ(cen, off)); - print(" Size : %#10x%n", CENLEN(cen, off)); - print(" NameLen : %#6x [%s]%n", - CENNAM(cen, off), new String(cen, off + CENHDR, CENNAM(cen, off))); - print(" ExtraLen : %#6x%n", CENEXT(cen, off)); - if (CENEXT(cen, off) != 0) - printExtra(cen, off + CENHDR + CENNAM(cen, off), CENEXT(cen, off)); - print(" CommentLen : %#6x%n", CENCOM(cen, off)); - print(" DiskStart : %#6x%n", CENDSK(cen, off)); - print(" Attrs : %#6x%n", CENATT(cen, off)); - print(" AttrsEx : %#10x%n", CENATX(cen, off)); - print(" LocOff : %#10x%n", CENOFF(cen, off)); - - } - - static long locoff(byte[] cen, int pos) { - long locoff = CENOFF(cen, pos); - if (locoff == ZIP64_MINVAL) { //ZIP64 - int off = pos + CENHDR + CENNAM(cen, pos); - int end = off + CENEXT(cen, pos); - while (off + 4 < end) { - int tag = SH(cen, off); - int sz = SH(cen, off + 2); - if (tag != EXTID_ZIP64) { - off += 4 + sz; - continue; - } - off += 4; - if (CENLEN(cen, pos) == ZIP64_MINVAL) - off += 8; - if (CENSIZ(cen, pos) == ZIP64_MINVAL) - off += 8; - return LL(cen, off); - } - // should never be here - } - return locoff; - } - - static void printExtra(byte[] extra, int off, int len) { - int end = off + len; - while (off + 4 < end) { - int tag = SH(extra, off); - int sz = SH(extra, off + 2); - print(" [tag=0x%04x, sz=%d, data= ", tag, sz); - if (off + sz > end) { - print(" Error: Invalid extra data, beyond extra length"); - break; - } - off += 4; - for (int i = 0; i < sz; i++) - print("%02x ", extra[off + i]); - print("]%n"); - switch (tag) { - case EXTID_ZIP64 : - print(" ->ZIP64: "); - int pos = off; - while (pos + 8 <= off + sz) { - print(" *0x%x ", LL(extra, pos)); - pos += 8; - } - print("%n"); - break; - case EXTID_NTFS: - print(" ->PKWare NTFS%n"); - // 4 bytes reserved - if (SH(extra, off + 4) != 0x0001 || SH(extra, off + 6) != 24) - print(" Error: Invalid NTFS sub-tag or subsz"); - print(" mtime:%tc%n", - winToJavaTime(LL(extra, off + 8))); - print(" atime:%tc%n", - winToJavaTime(LL(extra, off + 16))); - print(" ctime:%tc%n", - winToJavaTime(LL(extra, off + 24))); - break; - case EXTID_EXTT: - print(" ->Inof-ZIP Extended Timestamp: flag=%x%n",extra[off]); - pos = off + 1 ; - while (pos + 4 <= off + sz) { - print(" *%tc%n", - unixToJavaTime(LG(extra, pos))); - pos += 4; - } - break; - default: - } - off += sz; - } - } -}
--- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java Mon Dec 13 16:22:29 2010 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,961 +0,0 @@ -/* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of Oracle nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.sun.nio.zipfs; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.nio.channels.FileChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.*; -import java.nio.file.DirectoryStream.Filter; -import java.nio.file.attribute.BasicFileAttributeView; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.FileTime; -import java.util.*; -import static java.nio.file.StandardOpenOption.*; -import static java.nio.file.StandardCopyOption.*; - -/** - * - * @author Xueming Shen, Rajendra Gutupalli,Jaya Hangal - */ - -public class ZipPath extends Path { - - private final ZipFileSystem zfs; - private final byte[] path; - private volatile int[] offsets; - private int hashcode = 0; // cached hashcode (created lazily) - - ZipPath(ZipFileSystem zfs, byte[] path) { - this(zfs, path, false); - } - - ZipPath(ZipFileSystem zfs, byte[] path, boolean normalized) - { - this.zfs = zfs; - if (normalized) - this.path = path; - else - this.path = normalize(path); - } - - @Override - public ZipPath getRoot() { - if (this.isAbsolute()) - return new ZipPath(zfs, new byte[]{path[0]}); - else - return null; - } - - @Override - public Path getName() { - initOffsets(); - int count = offsets.length; - if (count == 0) - return null; // no elements so no name - if (count == 1 && path[0] != '/') - return this; - int lastOffset = offsets[count-1]; - int len = path.length - lastOffset; - byte[] result = new byte[len]; - System.arraycopy(path, lastOffset, result, 0, len); - return new ZipPath(zfs, result); - } - - @Override - public ZipPath getParent() { - initOffsets(); - int count = offsets.length; - if (count == 0) // no elements so no parent - return null; - int len = offsets[count-1] - 1; - if (len <= 0) // parent is root only (may be null) - return getRoot(); - byte[] result = new byte[len]; - System.arraycopy(path, 0, result, 0, len); - return new ZipPath(zfs, result); - } - - @Override - public int getNameCount() { - initOffsets(); - return offsets.length; - } - - @Override - public ZipPath getName(int index) { - initOffsets(); - if (index < 0 || index >= offsets.length) - throw new IllegalArgumentException(); - int begin = offsets[index]; - int len; - if (index == (offsets.length-1)) - len = path.length - begin; - else - len = offsets[index+1] - begin - 1; - // construct result - byte[] result = new byte[len]; - System.arraycopy(path, begin, result, 0, len); - return new ZipPath(zfs, result); - } - - @Override - public ZipPath subpath(int beginIndex, int endIndex) { - initOffsets(); - if (beginIndex < 0 || - beginIndex >= offsets.length || - endIndex > offsets.length || - beginIndex >= endIndex) - throw new IllegalArgumentException(); - - // starting offset and length - int begin = offsets[beginIndex]; - int len; - if (endIndex == offsets.length) - len = path.length - begin; - else - len = offsets[endIndex] - begin - 1; - // construct result - byte[] result = new byte[len]; - System.arraycopy(path, begin, result, 0, len); - return new ZipPath(zfs, result); - } - - @Override - public ZipPath toRealPath(boolean resolveLinks) throws IOException { - ZipPath realPath = new ZipPath(zfs, getResolvedPath()); - realPath.checkAccess(); - return realPath; - } - - @Override - public boolean isHidden() { - return false; - } - - @Override - public ZipPath toAbsolutePath() { - if (isAbsolute()) { - return this; - } else { - //add / bofore the existing path - byte[] defaultdir = zfs.getDefaultDir().path; - int defaultlen = defaultdir.length; - boolean endsWith = (defaultdir[defaultlen - 1] == '/'); - byte[] t = null; - if (endsWith) - t = new byte[defaultlen + path.length]; - else - t = new byte[defaultlen + 1 + path.length]; - System.arraycopy(defaultdir, 0, t, 0, defaultlen); - if (!endsWith) - t[defaultlen++] = '/'; - System.arraycopy(path, 0, t, defaultlen, path.length); - return new ZipPath(zfs, t, true); // normalized - } - } - - @Override - public URI toUri() { - String zfPath = zfs.toString(); - if (File.separatorChar == '\\') // replace all separators by '/' - zfPath = "/" + zfPath.replace("\\", "/"); - try { - return new URI("zip", "", - zfPath, - zfs.getString(toAbsolutePath().path)); - } catch (Exception ex) { - throw new AssertionError(ex); - } - } - - private boolean equalsNameAt(ZipPath other, int index) { - int mbegin = offsets[index]; - int mlen = 0; - if (index == (offsets.length-1)) - mlen = path.length - mbegin; - else - mlen = offsets[index + 1] - mbegin - 1; - int obegin = other.offsets[index]; - int olen = 0; - if (index == (other.offsets.length - 1)) - olen = other.path.length - obegin; - else - olen = other.offsets[index + 1] - obegin - 1; - if (mlen != olen) - return false; - int n = 0; - while(n < mlen) { - if (path[mbegin + n] != other.path[obegin + n]) - return false; - n++; - } - return true; - } - - @Override - public Path relativize(Path other) { - final ZipPath o = checkPath(other); - if (o.equals(this)) - return null; - if (/* this.getFileSystem() != o.getFileSystem() || */ - this.isAbsolute() != o.isAbsolute()) { - throw new IllegalArgumentException(); - } - int mc = this.getNameCount(); - int oc = o.getNameCount(); - int n = Math.min(mc, oc); - int i = 0; - while (i < n) { - if (!equalsNameAt(o, i)) - break; - i++; - } - int dotdots = mc - i; - int len = dotdots * 3 - 1; - if (i < oc) - len += (o.path.length - o.offsets[i] + 1); - byte[] result = new byte[len]; - - int pos = 0; - while (dotdots > 0) { - result[pos++] = (byte)'.'; - result[pos++] = (byte)'.'; - if (pos < len) // no tailing slash at the end - result[pos++] = (byte)'/'; - dotdots--; - } - if (i < oc) - System.arraycopy(o.path, o.offsets[i], - result, pos, - o.path.length - o.offsets[i]); - return new ZipPath(getFileSystem(), result); - } - - @Override - public ZipFileSystem getFileSystem() { - return zfs; - } - - @Override - public boolean isAbsolute() { - return (this.path[0] == '/'); - } - - @Override - public ZipPath resolve(Path other) { - if (other == null) - return this; - final ZipPath o = checkPath(other); - if (o.isAbsolute()) - return o; - byte[] resolved = null; - if (this.path[path.length - 1] == '/') { - resolved = new byte[path.length + o.path.length]; - System.arraycopy(path, 0, resolved, 0, path.length); - System.arraycopy(o.path, 0, resolved, path.length, o.path.length); - } else { - resolved = new byte[path.length + 1 + o.path.length]; - System.arraycopy(path, 0, resolved, 0, path.length); - resolved[path.length] = '/'; - System.arraycopy(o.path, 0, resolved, path.length + 1, o.path.length); - } - return new ZipPath(zfs, resolved); - } - - @Override - public ZipPath resolve(String other) { - return resolve(getFileSystem().getPath(other)); - } - - @Override - public boolean startsWith(Path other) { - final ZipPath o = checkPath(other); - if (o.isAbsolute() != this.isAbsolute()) - return false; - final int oCount = o.getNameCount(); - if (getNameCount() < oCount) - return false; - for (int i = 0; i < oCount; i++) { - if (!o.getName(i).equals(getName(i))) - return false; - } - return true; - } - - @Override - public boolean endsWith(Path other) { - final ZipPath o = checkPath(other); - if (o.isAbsolute()) - return this.isAbsolute() ? this.equals(o) : false; - int i = o.getNameCount(); - int j = this.getNameCount(); - if (j < i) - return false; - for (--i, --j; i >= 0; i--, j--) { - if (!o.getName(i).equals(this.getName(j))) - return false; - } - return true; - } - - @Override - public Path normalize() { - byte[] resolved = getResolved(); - if (resolved == path) // no change - return this; - if (resolved.length == 0) - return null; - return new ZipPath(zfs, resolved, true); - } - - private ZipPath checkPath(Path path) { - if (path == null) - throw new NullPointerException(); - if (!(path instanceof ZipPath)) - throw new ProviderMismatchException(); - return (ZipPath) path; - } - - // create offset list if not already created - private void initOffsets() { - if (offsets == null) { - int count, index; - // count names - count = 0; - index = 0; - while (index < path.length) { - byte c = path[index++]; - if (c != '/') { - count++; - while (index < path.length && path[index] != '/') - index++; - } - } - // populate offsets - int[] result = new int[count]; - count = 0; - index = 0; - while (index < path.length) { - byte c = path[index]; - if (c == '/') { - index++; - } else { - result[count++] = index++; - while (index < path.length && path[index] != '/') - index++; - } - } - synchronized (this) { - if (offsets == null) - offsets = result; - } - } - } - - // resolved path for locating zip entry inside the zip file, - // the result path does not contain ./ and .. components - private volatile byte[] resolved = null; - byte[] getResolvedPath() { - byte[] r = resolved; - if (r == null) { - if (isAbsolute()) - r = getResolved(); - else - r = toAbsolutePath().getResolvedPath(); - if (r[0] == '/') - r = Arrays.copyOfRange(r, 1, r.length); - resolved = r; - } - return resolved; - } - - // removes redundant slashs, replace "\" to zip separator "/" - // and check for invalid characters - private byte[] normalize(byte[] path) { - if (path.length == 0) - return path; - byte prevC = 0; - for (int i = 0; i < path.length; i++) { - byte c = path[i]; - if (c == '\\') - return normalize(path, i); - if (c == (byte)'/' && prevC == '/') - return normalize(path, i - 1); - if (c == '\u0000') - throw new InvalidPathException(zfs.getString(path), - "Path: nul character not allowed"); - prevC = c; - } - return path; - } - - private byte[] normalize(byte[] path, int off) { - byte[] to = new byte[path.length]; - int n = 0; - while (n < off) { - to[n] = path[n]; - n++; - } - int m = n; - byte prevC = 0; - while (n < path.length) { - byte c = path[n++]; - if (c == (byte)'\\') - c = (byte)'/'; - if (c == (byte)'/' && prevC == (byte)'/') - continue; - if (c == '\u0000') - throw new InvalidPathException(zfs.getString(path), - "Path: nul character not allowed"); - to[m++] = c; - prevC = c; - } - if (m > 1 && to[m - 1] == '/') - m--; - return (m == to.length)? to : Arrays.copyOf(to, m); - } - - // Remove DotSlash(./) and resolve DotDot (..) components - private byte[] getResolved() { - if (path.length == 0) - return path; - for (int i = 0; i < path.length; i++) { - byte c = path[i]; - if (c == (byte)'.') - return resolve0(); - } - return path; - } - - // TBD: performance, avoid initOffsets - private byte[] resolve0() { - byte[] to = new byte[path.length]; - int nc = getNameCount(); - int[] lastM = new int[nc]; - int lastMOff = -1; - int m = 0; - for (int i = 0; i < nc; i++) { - int n = offsets[i]; - int len = (i == offsets.length - 1)? - (path.length - n):(offsets[i + 1] - n - 1); - if (len == 1 && path[n] == (byte)'.') - continue; - if (len == 2 && path[n] == '.' && path[n + 1] == '.') { - if (lastMOff >= 0) { - m = lastM[lastMOff--]; // retreat - continue; - } - if (path[0] == '/') { // "/../xyz" skip - if (m == 0) - to[m++] = '/'; - } else { // "../xyz" -> "../xyz" - if (m != 0 && to[m-1] != '/') - to[m++] = '/'; - while (len-- > 0) - to[m++] = path[n++]; - } - continue; - } - if (m == 0 && path[0] == '/' || // absolute path - m != 0 && to[m-1] != '/') { // not the first name - to[m++] = '/'; - } - lastM[++lastMOff] = m; - while (len-- > 0) - to[m++] = path[n++]; - } - if (m > 1 && to[m - 1] == '/') - m--; - return (m == to.length)? to : Arrays.copyOf(to, m); - } - - @Override - public String toString() { - return zfs.getString(path); - } - - @Override - public int hashCode() { - int h = hashcode; - if (h == 0) - hashcode = h = Arrays.hashCode(path); - return h; - } - - @Override - public boolean equals(Object obj) { - return obj != null && - obj instanceof ZipPath && - this.zfs == ((ZipPath)obj).zfs && - compareTo((Path) obj) == 0; - } - - @Override - public int compareTo(Path other) { - final ZipPath o = checkPath(other); - int len1 = this.path.length; - int len2 = o.path.length; - - int n = Math.min(len1, len2); - byte v1[] = this.path; - byte v2[] = o.path; - - int k = 0; - while (k < n) { - int c1 = v1[k] & 0xff; - int c2 = v2[k] & 0xff; - if (c1 != c2) - return c1 - c2; - k++; - } - return len1 - len2; - } - - @Override - public Path createSymbolicLink( - Path target, FileAttribute<?>... attrs) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path createLink( - Path existing) throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path readSymbolicLink() throws IOException { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public Path createDirectory(FileAttribute<?>... attrs) - throws IOException - { - zfs.createDirectory(getResolvedPath(), attrs); - return this; - } - - public final Path createFile(FileAttribute<?>... attrs) - throws IOException - { - OutputStream os = newOutputStream(CREATE_NEW, WRITE); - try { - os.close(); - } catch (IOException x) {} - return this; - } - - @Override - public InputStream newInputStream(OpenOption... options) - throws IOException { - if (options.length > 0) { - for (OpenOption opt : options) { - if (opt != READ) - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } - } - return zfs.newInputStream(getResolvedPath()); - } - - private static final DirectoryStream.Filter<Path> acceptAllFilter = - new DirectoryStream.Filter<>() { - @Override public boolean accept(Path entry) { return true; } - }; - - @Override - public final DirectoryStream<Path> newDirectoryStream() throws IOException { - return newDirectoryStream(acceptAllFilter); - } - - @Override - public DirectoryStream<Path> newDirectoryStream(Filter<? super Path> filter) - throws IOException - { - return new ZipDirectoryStream(this, filter); - } - - @Override - public final DirectoryStream<Path> newDirectoryStream(String glob) - throws IOException - { - // avoid creating a matcher if all entries are required. - if (glob.equals("*")) - return newDirectoryStream(); - - // create a matcher and return a filter that uses it. - final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<>() { - @Override - public boolean accept(Path entry) { - return matcher.matches(entry.getName()); - } - }; - return newDirectoryStream(filter); - } - - @Override - public final void delete() throws IOException { - zfs.deleteFile(getResolvedPath(), true); - } - - @Override - public final void deleteIfExists() throws IOException { - zfs.deleteFile(getResolvedPath(), false); - } - - ZipFileAttributes getAttributes() throws IOException - { - ZipFileAttributes zfas = zfs.getFileAttributes(getResolvedPath());