# HG changeset patch # User mullan # Date 1290439113 18000 # Node ID ff70dc612d95e5b60c61b3928ccc8e7aa4f6b4f1 # Parent 9fefa27862512f0ad02cdc831104e45d21fe9e8c# Parent a38f3099e518bb0edc08407038dead7e490fd895 Merge diff -r 9fefa2786251 -r ff70dc612d95 jdk/make/mkdemo/nio/zipfs/Makefile --- a/jdk/make/mkdemo/nio/zipfs/Makefile Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/make/mkdemo/nio/zipfs/Makefile Mon Nov 22 10:18:33 2010 -0500 @@ -42,3 +42,10 @@ # include $(BUILDDIR)/common/Demo.gmk +#EXTJAR = $(EXTDIR)/$(DEMONAME).jar +# +#all : build $(EXTJAR) +# +#$(EXTJAR) : $(DEMO_JAR) +# $(prep-target) +# $(CP) $(DEMO_JAR) $(EXTJAR) diff -r 9fefa2786251 -r ff70dc612d95 jdk/make/sun/nio/cs/FILES_java.gmk --- a/jdk/make/sun/nio/cs/FILES_java.gmk Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/make/sun/nio/cs/FILES_java.gmk Mon Nov 22 10:18:33 2010 -0500 @@ -85,6 +85,7 @@ sun/io/ByteToCharCp500.java \ sun/io/ByteToCharCp737.java \ sun/io/ByteToCharCp775.java \ + sun/io/ByteToCharCp833.java \ sun/io/ByteToCharCp834.java \ sun/io/ByteToCharCp838.java \ sun/io/ByteToCharCp850.java \ @@ -214,6 +215,7 @@ sun/io/CharToByteCp500.java \ sun/io/CharToByteCp737.java \ sun/io/CharToByteCp775.java \ + sun/io/CharToByteCp833.java \ sun/io/CharToByteCp834.java \ sun/io/CharToByteCp838.java \ sun/io/CharToByteCp850.java \ @@ -331,6 +333,7 @@ sun/nio/cs/ext/IBM420.java \ sun/nio/cs/ext/IBM424.java \ sun/nio/cs/ext/IBM500.java \ + sun/nio/cs/ext/IBM833.java \ sun/nio/cs/ext/IBM838.java \ sun/nio/cs/ext/IBM856.java \ sun/nio/cs/ext/IBM860.java \ diff -r 9fefa2786251 -r ff70dc612d95 jdk/make/tools/CharsetMapping/IBM833.c2b --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/tools/CharsetMapping/IBM833.c2b Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,94 @@ +0x5A U+FF01 +0x7F U+FF02 +0x7B U+FF03 +0x5B U+FF04 +0x6C U+FF05 +0x50 U+FF06 +0x7D U+FF07 +0x4D U+FF08 +0x5D U+FF09 +0x5C U+FF0A +0x4E U+FF0B +0x6B U+FF0C +0x60 U+FF0D +0x4B U+FF0E +0x61 U+FF0F +0xF0 U+FF10 +0xF1 U+FF11 +0xF2 U+FF12 +0xF3 U+FF13 +0xF4 U+FF14 +0xF5 U+FF15 +0xF6 U+FF16 +0xF7 U+FF17 +0xF8 U+FF18 +0xF9 U+FF19 +0x7A U+FF1A +0x5E U+FF1B +0x4C U+FF1C +0x7E U+FF1D +0x6E U+FF1E +0x6F U+FF1F +0x7C U+FF20 +0xC1 U+FF21 +0xC2 U+FF22 +0xC3 U+FF23 +0xC4 U+FF24 +0xC5 U+FF25 +0xC6 U+FF26 +0xC7 U+FF27 +0xC8 U+FF28 +0xC9 U+FF29 +0xD1 U+FF2A +0xD2 U+FF2B +0xD3 U+FF2C +0xD4 U+FF2D +0xD5 U+FF2E +0xD6 U+FF2F +0xD7 U+FF30 +0xD8 U+FF31 +0xD9 U+FF32 +0xE2 U+FF33 +0xE3 U+FF34 +0xE4 U+FF35 +0xE5 U+FF36 +0xE6 U+FF37 +0xE7 U+FF38 +0xE8 U+FF39 +0xE9 U+FF3A +0x70 U+FF3B +0xB2 U+FF3C +0x80 U+FF3D +0xB0 U+FF3E +0x6D U+FF3F +0x79 U+FF40 +0x81 U+FF41 +0x82 U+FF42 +0x83 U+FF43 +0x84 U+FF44 +0x85 U+FF45 +0x86 U+FF46 +0x87 U+FF47 +0x88 U+FF48 +0x89 U+FF49 +0x91 U+FF4A +0x92 U+FF4B +0x93 U+FF4C +0x94 U+FF4D +0x95 U+FF4E +0x96 U+FF4F +0x97 U+FF50 +0x98 U+FF51 +0x99 U+FF52 +0xA2 U+FF53 +0xA3 U+FF54 +0xA4 U+FF55 +0xA5 U+FF56 +0xA6 U+FF57 +0xA7 U+FF58 +0xA8 U+FF59 +0xA9 U+FF5A +0xC0 U+FF5B +0x4F U+FF5C +0xD0 U+FF5D +0xA1 U+FF5E diff -r 9fefa2786251 -r ff70dc612d95 jdk/make/tools/CharsetMapping/IBM833.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/tools/CharsetMapping/IBM833.map Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,217 @@ +0x00 U+0000 +0x01 U+0001 +0x02 U+0002 +0x03 U+0003 +0x37 U+0004 +0x2D U+0005 +0x2E U+0006 +0x2F U+0007 +0x16 U+0008 +0x05 U+0009 +0x25 U+000A +0x0B U+000B +0x0C U+000C +0x0D U+000D +0x0E U+000E +0x0F U+000F +0x10 U+0010 +0x11 U+0011 +0x12 U+0012 +0x13 U+0013 +0x3C U+0014 +0x3D U+0015 +0x32 U+0016 +0x26 U+0017 +0x18 U+0018 +0x19 U+0019 +0x3F U+001A +0x27 U+001B +0x1C U+001C +0x1D U+001D +0x1E U+001E +0x1F U+001F +0x40 U+0020 +0x5A U+0021 +0x7F U+0022 +0x7B U+0023 +0x5B U+0024 +0x6C U+0025 +0x50 U+0026 +0x7D U+0027 +0x4D U+0028 +0x5D U+0029 +0x5C U+002A +0x4E U+002B +0x6B U+002C +0x60 U+002D +0x4B U+002E +0x61 U+002F +0xF0 U+0030 +0xF1 U+0031 +0xF2 U+0032 +0xF3 U+0033 +0xF4 U+0034 +0xF5 U+0035 +0xF6 U+0036 +0xF7 U+0037 +0xF8 U+0038 +0xF9 U+0039 +0x7A U+003A +0x5E U+003B +0x4C U+003C +0x7E U+003D +0x6E U+003E +0x6F U+003F +0x7C U+0040 +0xC1 U+0041 +0xC2 U+0042 +0xC3 U+0043 +0xC4 U+0044 +0xC5 U+0045 +0xC6 U+0046 +0xC7 U+0047 +0xC8 U+0048 +0xC9 U+0049 +0xD1 U+004A +0xD2 U+004B +0xD3 U+004C +0xD4 U+004D +0xD5 U+004E +0xD6 U+004F +0xD7 U+0050 +0xD8 U+0051 +0xD9 U+0052 +0xE2 U+0053 +0xE3 U+0054 +0xE4 U+0055 +0xE5 U+0056 +0xE6 U+0057 +0xE7 U+0058 +0xE8 U+0059 +0xE9 U+005A +0x70 U+005B +0xB2 U+005C +0x80 U+005D +0xB0 U+005E +0x6D U+005F +0x79 U+0060 +0x81 U+0061 +0x82 U+0062 +0x83 U+0063 +0x84 U+0064 +0x85 U+0065 +0x86 U+0066 +0x87 U+0067 +0x88 U+0068 +0x89 U+0069 +0x91 U+006A +0x92 U+006B +0x93 U+006C +0x94 U+006D +0x95 U+006E +0x96 U+006F +0x97 U+0070 +0x98 U+0071 +0x99 U+0072 +0xA2 U+0073 +0xA3 U+0074 +0xA4 U+0075 +0xA5 U+0076 +0xA6 U+0077 +0xA7 U+0078 +0xA8 U+0079 +0xA9 U+007A +0xC0 U+007B +0x4F U+007C +0xD0 U+007D +0xA1 U+007E +0x07 U+007F +0x20 U+0080 +0x21 U+0081 +0x22 U+0082 +0x23 U+0083 +0x24 U+0084 +0x15 U+0085 +0x06 U+0086 +0x17 U+0087 +0x28 U+0088 +0x29 U+0089 +0x2A U+008A +0x2B U+008B +0x2C U+008C +0x09 U+008D +0x0A U+008E +0x1B U+008F +0x30 U+0090 +0x31 U+0091 +0x1A U+0092 +0x33 U+0093 +0x34 U+0094 +0x35 U+0095 +0x36 U+0096 +0x08 U+0097 +0x38 U+0098 +0x39 U+0099 +0x3A U+009A +0x3B U+009B +0x04 U+009C +0x14 U+009D +0x3E U+009E +0xFF U+009F +0x4A U+00A2 +0x6A U+00A6 +0x5F U+00AC +0xA0 U+203E +0xE0 U+20A9 +0x42 U+FFA0 +0x43 U+FFA1 +0x44 U+FFA2 +0x45 U+FFA3 +0x46 U+FFA4 +0x47 U+FFA5 +0x48 U+FFA6 +0x49 U+FFA7 +0x52 U+FFA8 +0x53 U+FFA9 +0x54 U+FFAA +0x55 U+FFAB +0x56 U+FFAC +0x57 U+FFAD +0x58 U+FFAE +0x59 U+FFAF +0x62 U+FFB0 +0x63 U+FFB1 +0x64 U+FFB2 +0x65 U+FFB3 +0x66 U+FFB4 +0x67 U+FFB5 +0x68 U+FFB6 +0x69 U+FFB7 +0x72 U+FFB8 +0x73 U+FFB9 +0x74 U+FFBA +0x75 U+FFBB +0x76 U+FFBC +0x77 U+FFBD +0x78 U+FFBE +0x8A U+FFC2 +0x8B U+FFC3 +0x8C U+FFC4 +0x8D U+FFC5 +0x8E U+FFC6 +0x8F U+FFC7 +0x9A U+FFCA +0x9B U+FFCB +0x9C U+FFCC +0x9D U+FFCD +0x9E U+FFCE +0x9F U+FFCF +0xAA U+FFD2 +0xAB U+FFD3 +0xAC U+FFD4 +0xAD U+FFD5 +0xAE U+FFD6 +0xAF U+FFD7 +0xBA U+FFDA +0xBB U+FFDB +0xBC U+FFDC diff -r 9fefa2786251 -r ff70dc612d95 jdk/make/tools/CharsetMapping/extsbcs --- a/jdk/make/tools/CharsetMapping/extsbcs Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/make/tools/CharsetMapping/extsbcs Mon Nov 22 10:18:33 2010 -0500 @@ -32,6 +32,7 @@ IBM420 IBM420 Cp420 false sun.nio.cs.ext IBM424 IBM424 Cp424 false sun.nio.cs.ext IBM500 IBM500 Cp500 false sun.nio.cs.ext +IBM833 IBM833 Cp833 false sun.nio.cs.ext IBM838 IBM-Thai Cp838 false sun.nio.cs.ext IBM856 x-IBM856 Cp856 false sun.nio.cs.ext IBM860 IBM860 Cp860 false sun.nio.cs.ext diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java --- a/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java Mon Nov 22 10:18:33 2010 -0500 @@ -91,6 +91,7 @@ return context; } +//BEGIN_TIGER_EXCLUDE /** * Called by the HttpsServer to configure the parameters * for a https connection currently being established. @@ -111,4 +112,5 @@ public void configure (HttpsParameters params) { params.setSSLParameters (getSSLContext().getDefaultSSLParameters()); } +//END_TIGER_EXCLUDE } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java --- a/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java Mon Nov 22 10:18:33 2010 -0500 @@ -25,7 +25,9 @@ package com.sun.net.httpserver; import java.net.InetSocketAddress; +//BEGIN_TIGER_EXCLUDE import javax.net.ssl.SSLParameters; +//END_TIGER_EXCLUDE /** * Represents the set of parameters for each https @@ -67,6 +69,7 @@ */ public abstract InetSocketAddress getClientAddress(); +//BEGIN_TIGER_EXCLUDE /** * Sets the SSLParameters to use for this HttpsParameters. * The parameters must be supported by the SSLContext contained @@ -79,6 +82,7 @@ * invalid or unsupported. */ public abstract void setSSLParameters (SSLParameters params); +//END_TIGER_EXCLUDE /** * Returns a copy of the array of ciphersuites or null if none diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties --- a/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle.properties Mon Nov 22 10:18:33 2010 -0500 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -140,7 +140,7 @@ #WebRowSetXmlReader exception wrsxmlreader.invalidcp = End of RowSet reached. Invalid cursor position wrsxmlreader.readxml = readXML : {0} -wrsxmlreader.parseerr = ** Parsing Error : {0} , line : {0} , uri : {0} +wrsxmlreader.parseerr = ** Parsing Error : {0} , line : {1} , uri : {2} #WebRowSetXmlWriter exceptions wrsxmlwriter.ioex = IOException : {0} @@ -151,7 +151,7 @@ #XmlReaderContentHandler exceptions xmlrch.errmap = Error setting Map : {0} xmlrch.errmetadata = Error setting metadata : {0} -xmlrch.errinsert = Error inserting values : {0} +xmlrch.errinsertval = Error inserting values : {0} xmlrch.errconstr = Error constructing row : {0} xmlrch.errdel = Error deleting row : {0} xmlrch.errinsert = Error constructing insert row : {0} @@ -161,7 +161,7 @@ xmlrch.chars = characters : xmlrch.badvalue = Bad value ; non-nullable property xmlrch.badvalue1 = Bad value ; non-nullable metadata -xmlrch.warning = ** Warning : {0} , line : {0} , uri : {0} +xmlrch.warning = ** Warning : {0} , line : {1} , uri : {2} #RIOptimisticProvider Exceptions riop.locking = Locking classification is not supported diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java --- a/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Mon Nov 22 10:18:33 2010 -0500 @@ -738,7 +738,7 @@ // columnValue now need to be reset to the empty string columnValue = ""; } catch (SQLException ex) { - throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsert").toString(), ex.getMessage())); + throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsertval").toString(), ex.getMessage())); } break; case RowTag: diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/io/BufferedInputStream.java --- a/jdk/src/share/classes/java/io/BufferedInputStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/io/BufferedInputStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -395,7 +395,11 @@ * or an I/O error occurs. */ public synchronized int available() throws IOException { - return getInIfOpen().available() + (count - pos); + int n = count - pos; + int avail = getInIfOpen().available(); + return n > (Integer.MAX_VALUE - avail) + ? Integer.MAX_VALUE + : n + avail; } /** diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/io/PushbackInputStream.java --- a/jdk/src/share/classes/java/io/PushbackInputStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/io/PushbackInputStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -273,7 +273,11 @@ */ public int available() throws IOException { ensureOpen(); - return (buf.length - pos) + super.available(); + int n = buf.length - pos; + int avail = super.available(); + return n > (Integer.MAX_VALUE - avail) + ? Integer.MAX_VALUE + : n + avail; } /** diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/lang/Readable.java --- a/jdk/src/share/classes/java/lang/Readable.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/lang/Readable.java Mon Nov 22 10:18:33 2010 -0500 @@ -44,11 +44,11 @@ * rewinding of the buffer is performed. * * @param cb the buffer to read characters into - * @return @return The number of char values added to the buffer, + * @return The number of {@code char} values added to the buffer, * or -1 if this source of characters is at its end * @throws IOException if an I/O error occurs * @throws NullPointerException if cb is null - * @throws ReadOnlyBufferException if cb is a read only buffer + * @throws java.nio.ReadOnlyBufferException if cb is a read only buffer */ public int read(java.nio.CharBuffer cb) throws IOException; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/nio/StringCharBuffer.java --- a/jdk/src/share/classes/java/nio/StringCharBuffer.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/nio/StringCharBuffer.java Mon Nov 22 10:18:33 2010 -0500 @@ -47,7 +47,7 @@ 0, this.remaining(), this.remaining(), - this.position()); + offset + this.position()); } private StringCharBuffer(CharSequence s, diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/sql/SQLPermission.java --- a/jdk/src/share/classes/java/sql/SQLPermission.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/sql/SQLPermission.java Mon Nov 22 10:18:33 2010 -0500 @@ -84,7 +84,7 @@ * {@code setJNDIContext} and {@code setLogger} * Permits an application to specify the JNDI context from which the * {@code SyncProvider} implementations can be retrieved from and the logging - * object to be used by the{@codeSyncProvider} implementation. + * object to be used by the {@code SyncProvider} implementation. * * * diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/util/Formatter.java --- a/jdk/src/share/classes/java/util/Formatter.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/util/Formatter.java Mon Nov 22 10:18:33 2010 -0500 @@ -1581,6 +1581,7 @@ * instance of the Java virtual machine. * * {@code 'Z'} + * '\u005a' * A string representing the abbreviation for the time zone. This * value will be adjusted as necessary for Daylight Saving Time. For * {@code long}, {@link Long}, and {@link Date} the time zone used is diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/java/util/jar/JarInputStream.java --- a/jdk/src/share/classes/java/util/jar/JarInputStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/java/util/jar/JarInputStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -28,6 +28,7 @@ import java.util.zip.*; import java.io.*; import sun.security.util.ManifestEntryVerifier; +import sun.misc.JarIndex; /** * The JarInputStream class is used to read the contents of @@ -47,7 +48,8 @@ private JarEntry first; private JarVerifier jv; private ManifestEntryVerifier mev; - + private final boolean doVerify; + private boolean tryManifest; /** * Creates a new JarInputStream and reads the optional @@ -72,25 +74,33 @@ */ public JarInputStream(InputStream in, boolean verify) throws IOException { super(in); + this.doVerify = verify; + + // This implementation assumes the META-INF/MANIFEST.MF entry + // should be either the first or the second entry (when preceded + // by the dir META-INF/). It skips the META-INF/ and then + // "consumes" the MANIFEST.MF to initialize the Manifest object. JarEntry e = (JarEntry)super.getNextEntry(); - if (e != null && e.getName().equalsIgnoreCase("META-INF/")) e = (JarEntry)super.getNextEntry(); + first = checkManifest(e); + } + private JarEntry checkManifest(JarEntry e) + throws IOException + { if (e != null && JarFile.MANIFEST_NAME.equalsIgnoreCase(e.getName())) { man = new Manifest(); byte bytes[] = getBytes(new BufferedInputStream(this)); man.read(new ByteArrayInputStream(bytes)); - //man.read(new BufferedInputStream(this)); closeEntry(); - if (verify) { + if (doVerify) { jv = new JarVerifier(bytes); mev = new ManifestEntryVerifier(man); } - first = getNextJarEntry(); - } else { - first = e; + return (JarEntry)super.getNextEntry(); } + return e; } private byte[] getBytes(InputStream is) @@ -98,10 +108,7 @@ { byte[] buffer = new byte[8192]; ByteArrayOutputStream baos = new ByteArrayOutputStream(2048); - int n; - - baos.reset(); while ((n = is.read(buffer, 0, buffer.length)) != -1) { baos.write(buffer, 0, n); } @@ -133,8 +140,14 @@ JarEntry e; if (first == null) { e = (JarEntry)super.getNextEntry(); + if (tryManifest) { + e = checkManifest(e); + tryManifest = false; + } } else { e = first; + if (first.getName().equalsIgnoreCase(JarIndex.INDEX_NAME)) + tryManifest = true; first = null; } if (jv != null && e != null) { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/io/ByteToCharCp833.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/io/ByteToCharCp833.java Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,42 @@ +/* + * 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 sun.io; + +import sun.nio.cs.ext.IBM833; + +public class ByteToCharCp833 extends ByteToCharSingleByte { + + private final static IBM833 nioCoder = new IBM833(); + + public String getCharacterEncoding() { + return "Cp833"; + } + + public ByteToCharCp833() { + super.byteToCharTable = nioCoder.getDecoderSingleByteMappings(); + } +} + diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/io/CharToByteCp833.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/sun/io/CharToByteCp833.java Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,46 @@ +/* + * 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 sun.io; + +import sun.nio.cs.ext.IBM833; + +public class CharToByteCp833 extends CharToByteSingleByte { + + private final static IBM833 nioCoder = new IBM833(); + + public String getCharacterEncoding() { + return "Cp833"; + } + + public CharToByteCp833() { + super.mask1 = 0xFF00; + super.mask2 = 0x00FF; + super.shift = 8; + super.index1 = nioCoder.getEncoderIndex1(); + super.index2 = nioCoder.getEncoderIndex2(); + } +} + diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/io/CharacterEncoding.java --- a/jdk/src/share/classes/sun/io/CharacterEncoding.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/io/CharacterEncoding.java Mon Nov 22 10:18:33 2010 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, 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 @@ -406,6 +406,11 @@ aliasTable.put("cp775", "Cp775"); aliasTable.put("775", "Cp775"); + aliasTable.put("ibm833", "Cp833"); + aliasTable.put("ibm-833", "Cp833"); + aliasTable.put("cp833", "Cp833"); + aliasTable.put("833", "Cp833"); + aliasTable.put("ibm834", "Cp834"); aliasTable.put("ibm-834", "Cp834"); aliasTable.put("cp834", "Cp834"); diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java --- a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -110,6 +110,7 @@ if (remaining == 0) { eof = true; consumeCRLF(); + t.getServerImpl().requestCompleted (t.getConnection()); return -1; } needToReadHeader = false; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/Event.java --- a/jdk/src/share/classes/sun/net/httpserver/Event.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/Event.java Mon Nov 22 10:18:33 2010 -0500 @@ -40,5 +40,7 @@ class WriteFinishedEvent extends Event { WriteFinishedEvent (ExchangeImpl t) { super (t); + assert !t.writefinished; + t.writefinished = true; } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java --- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Mon Nov 22 10:18:33 2010 -0500 @@ -38,6 +38,7 @@ Headers reqHdrs, rspHdrs; Request req; String method; + boolean writefinished; URI uri; HttpConnection connection; long reqContentLen; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java --- a/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -56,6 +56,9 @@ int n = in.read(b, off, len); if (n > -1) { remaining -= n; + if (remaining == 0) { + t.getServerImpl().requestCompleted (t.getConnection()); + } } return n; } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/HttpConnection.java --- a/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java Mon Nov 22 10:18:33 2010 -0500 @@ -55,10 +55,15 @@ SelectionKey selectionKey; String protocol; long time; + volatile long creationTime; // time this connection was created + volatile long rspStartedTime; // time we started writing the response int remaining; boolean closed = false; Logger logger; + public enum State {IDLE, REQUEST, RESPONSE}; + volatile State state; + public String toString() { String s = null; if (chan != null) { @@ -78,6 +83,14 @@ context = ctx; } + State getState() { + return state; + } + + void setState (State s) { + state = s; + } + void setParameters ( InputStream in, OutputStream rawout, SocketChannel chan, SSLEngine engine, SSLStreams sslStreams, SSLContext sslContext, String protocol, diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/Request.java --- a/jdk/src/share/classes/sun/net/httpserver/Request.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/Request.java Mon Nov 22 10:18:33 2010 -0500 @@ -201,32 +201,22 @@ static class ReadStream extends InputStream { SocketChannel channel; - SelectorCache sc; - Selector selector; ByteBuffer chanbuf; - SelectionKey key; - int available; byte[] one; - boolean closed = false, eof = false; + private boolean closed = false, eof = false; ByteBuffer markBuf; /* reads may be satisifed from this buffer */ boolean marked; boolean reset; int readlimit; static long readTimeout; ServerImpl server; - - static { - readTimeout = ServerConfig.getReadTimeout(); - } + final static int BUFSIZE = 8 * 1024; public ReadStream (ServerImpl server, SocketChannel chan) throws IOException { this.channel = chan; this.server = server; - sc = SelectorCache.getSelectorCache(); - selector = sc.getSelector(); - chanbuf = ByteBuffer.allocate (8* 1024); - key = chan.register (selector, SelectionKey.OP_READ); - available = 0; + chanbuf = ByteBuffer.allocate (BUFSIZE); + chanbuf.clear(); one = new byte[1]; closed = marked = reset = false; } @@ -255,6 +245,12 @@ return -1; } + assert channel.isBlocking(); + + if (off < 0 || srclen < 0|| srclen > (b.length-off)) { + throw new IndexOutOfBoundsException (); + } + if (reset) { /* satisfy from markBuf */ canreturn = markBuf.remaining (); willreturn = canreturn>srclen ? srclen : canreturn; @@ -263,17 +259,19 @@ reset = false; } } else { /* satisfy from channel */ - canreturn = available(); - while (canreturn == 0 && !eof) { - block (); - canreturn = available(); + chanbuf.clear (); + if (srclen < BUFSIZE) { + chanbuf.limit (srclen); } - if (eof) { + do { + willreturn = channel.read (chanbuf); + } while (willreturn == 0); + if (willreturn == -1) { + eof = true; return -1; } - willreturn = canreturn>srclen ? srclen : canreturn; + chanbuf.flip (); chanbuf.get(b, off, willreturn); - available -= willreturn; if (marked) { /* copy into markBuf */ try { @@ -286,6 +284,11 @@ return willreturn; } + public boolean markSupported () { + return true; + } + + /* Does not query the OS socket */ public synchronized int available () throws IOException { if (closed) throw new IOException ("Stream is closed"); @@ -296,36 +299,7 @@ if (reset) return markBuf.remaining(); - if (available > 0) - return available; - - chanbuf.clear (); - available = channel.read (chanbuf); - if (available > 0) { - chanbuf.flip(); - } else if (available == -1) { - eof = true; - available = 0; - } - return available; - } - - /** - * block() only called when available==0 and buf is empty - */ - private synchronized void block () throws IOException { - long currtime = server.getTime(); - long maxtime = currtime + readTimeout; - - while (currtime < maxtime) { - if (selector.select (readTimeout) == 1) { - selector.selectedKeys().clear(); - available (); - return; - } - currtime = server.getTime(); - } - throw new SocketTimeoutException ("no data received"); + return chanbuf.remaining(); } public void close () throws IOException { @@ -333,8 +307,6 @@ return; } channel.close (); - selector.selectNow(); - sc.freeSelector(selector); closed = true; } @@ -362,23 +334,14 @@ SocketChannel channel; ByteBuffer buf; SelectionKey key; - SelectorCache sc; - Selector selector; boolean closed; byte[] one; ServerImpl server; - static long writeTimeout; - - static { - writeTimeout = ServerConfig.getWriteTimeout(); - } public WriteStream (ServerImpl server, SocketChannel channel) throws IOException { this.channel = channel; this.server = server; - sc = SelectorCache.getSelectorCache(); - selector = sc.getSelector(); - key = channel.register (selector, SelectionKey.OP_WRITE); + assert channel.isBlocking(); closed = false; one = new byte [1]; buf = ByteBuffer.allocate (4096); @@ -411,31 +374,14 @@ l -= n; if (l == 0) return; - block(); } } - void block () throws IOException { - long currtime = server.getTime(); - long maxtime = currtime + writeTimeout; - - while (currtime < maxtime) { - if (selector.select (writeTimeout) == 1) { - selector.selectedKeys().clear (); - return; - } - currtime = server.getTime(); - } - throw new SocketTimeoutException ("write blocked too long"); - } - - public void close () throws IOException { if (closed) return; + //server.logStackTrace ("Request.OS.close: isOpen="+channel.isOpen()); channel.close (); - selector.selectNow(); - sc.freeSelector(selector); closed = true; } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/SSLStreams.java --- a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java Mon Nov 22 10:18:33 2010 -0500 @@ -53,8 +53,6 @@ EngineWrapper wrapper; OutputStream os; InputStream is; - static long readTimeout = ServerConfig.getReadTimeout(); - static long writeTimeout = ServerConfig.getWriteTimeout(); /* held by thread doing the hand-shake on this connection */ Lock handshaking = new ReentrantLock(); @@ -77,10 +75,13 @@ if (cfg != null) { Parameters params = new Parameters (cfg, addr); cfg.configure (params); +//BEGIN_TIGER_EXCLUDE SSLParameters sslParams = params.getSSLParameters(); if (sslParams != null) { engine.setSSLParameters (sslParams); - } else { + } else +//END_TIGER_EXCLUDE + { /* tiger compatibility */ if (params.getCipherSuites() != null) { try { @@ -104,7 +105,6 @@ class Parameters extends HttpsParameters { InetSocketAddress addr; - SSLParameters params; HttpsConfigurator cfg; Parameters (HttpsConfigurator cfg, InetSocketAddress addr) { @@ -117,12 +117,15 @@ public HttpsConfigurator getHttpsConfigurator() { return cfg; } +//BEGIN_TIGER_EXCLUDE + SSLParameters params; public void setSSLParameters (SSLParameters p) { params = p; } SSLParameters getSSLParameters () { return params; } +//END_TIGER_EXCLUDE } /** @@ -245,9 +248,6 @@ SocketChannel chan; SSLEngine engine; - SelectorCache sc; - Selector write_selector, read_selector; - SelectionKey wkey, rkey; Object wrapLock, unwrapLock; ByteBuffer unwrap_src, wrap_dst; boolean closed = false; @@ -260,16 +260,9 @@ unwrapLock = new Object(); unwrap_src = allocate(BufType.PACKET); wrap_dst = allocate(BufType.PACKET); - sc = SelectorCache.getSelectorCache(); - write_selector = sc.getSelector(); - wkey = chan.register (write_selector, SelectionKey.OP_WRITE); - read_selector = sc.getSelector(); - wkey = chan.register (read_selector, SelectionKey.OP_READ); } void close () throws IOException { - sc.freeSelector (write_selector); - sc.freeSelector (read_selector); } /* try to wrap and send the data in src. Handles OVERFLOW. @@ -304,15 +297,7 @@ wrap_dst.flip(); int l = wrap_dst.remaining(); assert l == r.result.bytesProduced(); - long currtime = time.getTime(); - long maxtime = currtime + writeTimeout; while (l>0) { - write_selector.select(writeTimeout); // timeout - currtime = time.getTime(); - if (currtime > maxtime) { - throw new SocketTimeoutException ("write timed out"); - } - write_selector.selectedKeys().clear(); l -= chan.write (wrap_dst); } } @@ -342,20 +327,12 @@ needData = true; } synchronized (unwrapLock) { - int x,y; + int x; do { if (needData) { - long currTime = time.getTime(); - long maxtime = currTime + readTimeout; do { - if (currTime > maxtime) { - throw new SocketTimeoutException ("read timedout"); - } - y = read_selector.select (readTimeout); - currTime = time.getTime(); - } while (y != 1); - read_selector.selectedKeys().clear(); x = chan.read (unwrap_src); + } while (x == 0); if (x == -1) { throw new IOException ("connection closed for reading"); } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/SelectorCache.java --- a/jdk/src/share/classes/sun/net/httpserver/SelectorCache.java Mon Nov 22 10:16:07 2010 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.net.httpserver; - -import java.util.*; -import java.nio.*; -import java.net.*; -import java.io.*; -import java.security.*; -import java.nio.channels.*; - -/* - * Implements a cache of java.nio.channels.Selector - * where Selectors are allocated on demand and placed - * in a temporary cache for a period of time, so they - * can be reused. If a period of between 2 and 4 minutes - * elapses without being used, then they are closed. - */ -public class SelectorCache { - - static SelectorCache cache = null; - - private SelectorCache () { - freeSelectors = new LinkedList(); - CacheCleaner c = AccessController.doPrivileged( - new PrivilegedAction() { - public CacheCleaner run() { - CacheCleaner cleaner = new CacheCleaner(); - cleaner.setDaemon (true); - return cleaner; - } - }); - c.start(); - } - - /** - * factory method for creating single instance - */ - public static SelectorCache getSelectorCache () { - synchronized (SelectorCache.class) { - if (cache == null) { - cache = new SelectorCache (); - } - } - return cache; - } - - private static class SelectorWrapper { - private Selector sel; - private boolean deleteFlag; - private SelectorWrapper (Selector sel) { - this.sel = sel; - this.deleteFlag = false; - } - public Selector getSelector() { return sel;} - public boolean getDeleteFlag () {return deleteFlag;} - public void setDeleteFlag (boolean b) {deleteFlag = b;} - } - - /* list of free selectors. Can be re-allocated for a period - * of time, after which if not allocated will be closed - * and removed from the list (by CacheCleaner thread) - */ - LinkedList freeSelectors; - - synchronized Selector getSelector () throws IOException { - SelectorWrapper wrapper = null; - Selector selector; - - if (freeSelectors.size() > 0) { - wrapper = freeSelectors.remove(); - selector = wrapper.getSelector(); - } else { - selector = Selector.open(); - } - return selector; - } - - synchronized void freeSelector (Selector selector) { - freeSelectors.add (new SelectorWrapper (selector)); - } - - /* Thread ensures that entries on freeSelector list - * remain there for at least 2 minutes and no longer - * than 4 minutes. - */ - class CacheCleaner extends Thread { - public void run () { - long timeout = ServerConfig.getSelCacheTimeout() * 1000; - while (true) { - try {Thread.sleep (timeout); } catch (Exception e) {} - synchronized (freeSelectors) { - ListIterator l = freeSelectors.listIterator(); - while (l.hasNext()) { - SelectorWrapper w = l.next(); - if (w.getDeleteFlag()) { - /* 2nd pass. Close the selector */ - try { - w.getSelector().close(); - } catch (IOException e) {} - l.remove(); - } else { - /* 1st pass. Set the flag */ - w.setDeleteFlag (true); - } - } - } - } - } - } -} diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/ServerConfig.java --- a/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java Mon Nov 22 10:18:33 2010 -0500 @@ -27,6 +27,8 @@ import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; +import java.util.logging.Logger; +import java.security.PrivilegedAction; /** * Parameters that users will not likely need to set @@ -37,23 +39,26 @@ static int clockTick; - static int defaultClockTick = 10000 ; // 10 sec. + static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec. /* These values must be a reasonable multiple of clockTick */ - static long defaultReadTimeout = 20 ; // 20 sec. - static long defaultWriteTimeout = 60 ; // 60 sec. - static long defaultIdleInterval = 300 ; // 5 min - static long defaultSelCacheTimeout = 120 ; // seconds - static int defaultMaxIdleConnections = 200 ; + static final long DEFAULT_IDLE_INTERVAL = 300 ; // 5 min + static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ; - static long defaultDrainAmount = 64 * 1024; + static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever + static final long DEFAULT_MAX_RSP_TIME = -1; // default: forever + static final long DEFAULT_TIMER_MILLIS = 1000; - static long readTimeout; - static long writeTimeout; + static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024; + static long idleInterval; - static long selCacheTimeout; static long drainAmount; // max # of bytes to drain from an inputstream static int maxIdleConnections; + + // max time a request or response is allowed to take + static long maxReqTime; + static long maxRspTime; + static long timerMillis; static boolean debug = false; static { @@ -61,49 +66,79 @@ idleInterval = ((Long)java.security.AccessController.doPrivileged( new sun.security.action.GetLongAction( "sun.net.httpserver.idleInterval", - defaultIdleInterval))).longValue() * 1000; + DEFAULT_IDLE_INTERVAL))).longValue() * 1000; clockTick = ((Integer)java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.httpserver.clockTick", - defaultClockTick))).intValue(); + DEFAULT_CLOCK_TICK))).intValue(); maxIdleConnections = ((Integer)java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.httpserver.maxIdleConnections", - defaultMaxIdleConnections))).intValue(); - - readTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.readTimeout", - defaultReadTimeout))).longValue()* 1000; - - selCacheTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.selCacheTimeout", - defaultSelCacheTimeout))).longValue()* 1000; - - writeTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.writeTimeout", - defaultWriteTimeout))).longValue()* 1000; + DEFAULT_MAX_IDLE_CONNECTIONS))).intValue(); drainAmount = ((Long)java.security.AccessController.doPrivileged( new sun.security.action.GetLongAction( "sun.net.httpserver.drainAmount", - defaultDrainAmount))).longValue(); + DEFAULT_DRAIN_AMOUNT))).longValue(); + + maxReqTime = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.maxReqTime", + DEFAULT_MAX_REQ_TIME))).longValue(); + + maxRspTime = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.maxRspTime", + DEFAULT_MAX_RSP_TIME))).longValue(); + + timerMillis = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.timerMillis", + DEFAULT_TIMER_MILLIS))).longValue(); debug = ((Boolean)java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.httpserver.debug"))).booleanValue(); } - static long getReadTimeout () { - return readTimeout; - } + + static void checkLegacyProperties (final Logger logger) { + + // legacy properties that are no longer used + // print a warning to logger if they are set. - static long getSelCacheTimeout () { - return selCacheTimeout; + java.security.AccessController.doPrivileged( + new PrivilegedAction() { + public Void run () { + if (System.getProperty("sun.net.httpserver.readTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.readTimeout "+ + "property is no longer used. "+ + "Use sun.net.httpserver.maxReqTime instead." + ); + } + if (System.getProperty("sun.net.httpserver.writeTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.writeTimeout "+ + "property is no longer used. Use "+ + "sun.net.httpserver.maxRspTime instead." + ); + } + if (System.getProperty("sun.net.httpserver.selCacheTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.selCacheTimeout "+ + "property is no longer used." + ); + } + return null; + } + } + ); } static boolean debugEnabled () { @@ -122,11 +157,19 @@ return maxIdleConnections; } - static long getWriteTimeout () { - return writeTimeout; - } - static long getDrainAmount () { return drainAmount; } + + static long getMaxReqTime () { + return maxReqTime; + } + + static long getMaxRspTime () { + return maxRspTime; + } + + static long getTimerMillis () { + return timerMillis; + } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/net/httpserver/ServerImpl.java --- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java Mon Nov 22 10:18:33 2010 -0500 @@ -37,6 +37,7 @@ import javax.net.ssl.*; import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; +import sun.net.httpserver.HttpConnection.State; /** * Provides implementation for both HTTP and HTTPS @@ -55,6 +56,12 @@ private SelectionKey listenerKey; private Set idleConnections; private Set allConnections; + /* following two are used to keep track of the times + * when a connection/request is first received + * and when we start to send the response + */ + private Set reqConnections; + private Set rspConnections; private List events; private Object lolock = new Object(); private volatile boolean finished = false; @@ -62,14 +69,19 @@ private boolean bound = false; private boolean started = false; private volatile long time; /* current time */ + private volatile long subticks = 0; private volatile long ticks; /* number of clock ticks since server started */ private HttpServer wrapper; final static int CLOCK_TICK = ServerConfig.getClockTick(); final static long IDLE_INTERVAL = ServerConfig.getIdleInterval(); final static int MAX_IDLE_CONNECTIONS = ServerConfig.getMaxIdleConnections(); + final static long TIMER_MILLIS = ServerConfig.getTimerMillis (); + final static long MAX_REQ_TIME=getTimeMillis(ServerConfig.getMaxReqTime()); + final static long MAX_RSP_TIME=getTimeMillis(ServerConfig.getMaxRspTime()); + final static boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1; - private Timer timer; + private Timer timer, timer1; private Logger logger; ServerImpl ( @@ -79,6 +91,7 @@ this.protocol = protocol; this.wrapper = wrapper; this.logger = Logger.getLogger ("com.sun.net.httpserver"); + ServerConfig.checkLegacyProperties (logger); https = protocol.equalsIgnoreCase ("https"); this.address = addr; contexts = new ContextList(); @@ -94,9 +107,18 @@ dispatcher = new Dispatcher(); idleConnections = Collections.synchronizedSet (new HashSet()); allConnections = Collections.synchronizedSet (new HashSet()); + reqConnections = Collections.synchronizedSet (new HashSet()); + rspConnections = Collections.synchronizedSet (new HashSet()); time = System.currentTimeMillis(); timer = new Timer ("server-timer", true); timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK); + if (timer1Enabled) { + timer1 = new Timer ("server-timer1", true); + timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS); + logger.config ("HttpServer timer1 enabled period in ms: "+TIMER_MILLIS); + logger.config ("MAX_REQ_TIME: "+MAX_REQ_TIME); + logger.config ("MAX_RSP_TIME: "+MAX_RSP_TIME); + } events = new LinkedList(); logger.config ("HttpServer created "+protocol+" "+ addr); } @@ -181,6 +203,9 @@ allConnections.clear(); idleConnections.clear(); timer.cancel(); + if (timer1Enabled) { + timer1.cancel(); + } } Dispatcher dispatcher; @@ -236,13 +261,6 @@ } } - int resultSize () { - synchronized (lolock) { - return events.size (); - } - } - - /* main server listener task */ class Dispatcher implements Runnable { @@ -257,7 +275,7 @@ if (terminating && exchanges == 0) { finished = true; } - SocketChannel chan = c.getChannel(); + responseCompleted (c); LeftOverInputStream is = t.getOriginalInputStream(); if (!is.isEOF()) { t.close = true; @@ -268,17 +286,10 @@ } else { if (is.isDataBuffered()) { /* don't re-enable the interestops, just handle it */ + requestStarted (c); handle (c.getChannel(), c); } else { - /* re-enable interestops */ - SelectionKey key = c.getSelectionKey(); - if (key.isValid()) { - key.interestOps ( - key.interestOps()|SelectionKey.OP_READ - ); - } - c.time = getTime() + IDLE_INTERVAL; - idleConnections.add (c); + connsToRegister.add (c); } } } @@ -290,22 +301,51 @@ } } + final LinkedList connsToRegister = + new LinkedList(); + + void reRegister (HttpConnection c) { + /* re-register with selector */ + try { + SocketChannel chan = c.getChannel(); + chan.configureBlocking (false); + SelectionKey key = chan.register (selector, SelectionKey.OP_READ); + key.attach (c); + c.selectionKey = key; + c.time = getTime() + IDLE_INTERVAL; + idleConnections.add (c); + } catch (IOException e) { + dprint(e); + logger.log(Level.FINER, "Dispatcher(8)", e); + c.close(); + } + } + public void run() { while (!finished) { try { - - /* process the events list first */ + ListIterator li = + connsToRegister.listIterator(); + for (HttpConnection c : connsToRegister) { + reRegister(c); + } + connsToRegister.clear(); - while (resultSize() > 0) { - Event r; - synchronized (lolock) { - r = events.remove(0); + List list = null; + selector.select(1000); + synchronized (lolock) { + if (events.size() > 0) { + list = events; + events = new LinkedList(); + } + } + + if (list != null) { + for (Event r: list) { handleEvent (r); } } - selector.select(1000); - /* process the selected list now */ Set selected = selector.selectedKeys(); @@ -327,6 +367,7 @@ c.selectionKey = newkey; c.setChannel (chan); newkey.attach (c); + requestStarted (c); allConnections.add (c); } else { try { @@ -334,27 +375,44 @@ boolean closed; SocketChannel chan = (SocketChannel)key.channel(); HttpConnection conn = (HttpConnection)key.attachment(); - // interestOps will be restored at end of read - key.interestOps (0); + + key.cancel(); + chan.configureBlocking (true); + if (idleConnections.remove(conn)) { + // was an idle connection so add it + // to reqConnections set. + requestStarted (conn); + } handle (chan, conn); } else { assert false; } + } catch (CancelledKeyException e) { + handleException(key, null); } catch (IOException e) { - HttpConnection conn = (HttpConnection)key.attachment(); - logger.log ( - Level.FINER, "Dispatcher (2)", e - ); - conn.close(); + handleException(key, e); } } } + // call the selector just to process the cancelled keys + selector.selectNow(); + } catch (IOException e) { + logger.log (Level.FINER, "Dispatcher (4)", e); } catch (Exception e) { - logger.log (Level.FINER, "Dispatcher (3)", e); + e.printStackTrace(); + logger.log (Level.FINER, "Dispatcher (7)", e); } } } + private void handleException (SelectionKey key, Exception e) { + HttpConnection conn = (HttpConnection)key.attachment(); + if (e != null) { + logger.log (Level.FINER, "Dispatcher (2)", e); + } + closeConnection(conn); + } + public void handle (SocketChannel chan, HttpConnection conn) throws IOException { @@ -363,10 +421,10 @@ executor.execute (t); } catch (HttpError e1) { logger.log (Level.FINER, "Dispatcher (4)", e1); - conn.close(); + closeConnection(conn); } catch (IOException e) { logger.log (Level.FINER, "Dispatcher (5)", e); - conn.close(); + closeConnection(conn); } } } @@ -390,7 +448,26 @@ return logger; } - /* per exchange task */ + private void closeConnection(HttpConnection conn) { + conn.close(); + allConnections.remove(conn); + switch (conn.getState()) { + case REQUEST: + reqConnections.remove(conn); + break; + case RESPONSE: + rspConnections.remove(conn); + break; + case IDLE: + idleConnections.remove(conn); + break; + } + assert !reqConnections.remove(conn); + assert !rspConnections.remove(conn); + assert !idleConnections.remove(conn); + } + + /* per exchange task */ class Exchange implements Runnable { SocketChannel chan; @@ -450,8 +527,7 @@ requestLine = req.requestLine(); if (requestLine == null) { /* connection closed */ - connection.close(); - allConnections.remove(connection); + closeConnection(connection); return; } int space = requestLine.indexOf (' '); @@ -482,6 +558,9 @@ if (s != null) { clen = Long.parseLong(s); } + if (clen == 0) { + requestCompleted (connection); + } } ctx = contexts.findContext (protocol, uri.getPath()); if (ctx == null) { @@ -560,7 +639,7 @@ } catch (IOException e1) { logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1); - connection.close(); + closeConnection(connection); } catch (NumberFormatException e3) { reject (Code.HTTP_BAD_REQUEST, requestLine, "NumberFormatException thrown"); @@ -569,7 +648,7 @@ requestLine, "URISyntaxException thrown"); } catch (Exception e4) { logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4); - connection.close(); + closeConnection(connection); } } @@ -591,47 +670,60 @@ rejected = true; logReply (code, requestStr, message); sendReply ( - code, true, "

"+code+Code.msg(code)+"

"+message + code, false, "

"+code+Code.msg(code)+"

"+message ); - /* connection is already closed by sendReply, now remove it */ - allConnections.remove(connection); + closeConnection(connection); } void sendReply ( int code, boolean closeNow, String text) { try { - String s = "HTTP/1.1 " + code + Code.msg(code) + "\r\n"; + StringBuilder builder = new StringBuilder (512); + builder.append ("HTTP/1.1 ") + .append (code).append (Code.msg(code)).append ("\r\n"); + if (text != null && text.length() != 0) { - s = s + "Content-Length: "+text.length()+"\r\n"; - s = s + "Content-Type: text/html\r\n"; + builder.append ("Content-Length: ") + .append (text.length()).append ("\r\n") + .append ("Content-Type: text/html\r\n"); } else { - s = s + "Content-Length: 0\r\n"; + builder.append ("Content-Length: 0\r\n"); text = ""; } if (closeNow) { - s = s + "Connection: close\r\n"; + builder.append ("Connection: close\r\n"); } - s = s + "\r\n" + text; + builder.append ("\r\n").append (text); + String s = builder.toString(); byte[] b = s.getBytes("ISO8859_1"); rawout.write (b); rawout.flush(); if (closeNow) { - connection.close(); + closeConnection(connection); } } catch (IOException e) { logger.log (Level.FINER, "ServerImpl.sendReply", e); - connection.close(); + closeConnection(connection); } } } void logReply (int code, String requestStr, String text) { + if (!logger.isLoggable(Level.FINE)) { + return; + } if (text == null) { text = ""; } - String message = requestStr + " [" + code + " " + + String r; + if (requestStr.length() > 80) { + r = requestStr.substring (0, 80) + ""; + } else { + r = requestStr; + } + String message = r + " [" + code + " " + Code.msg(code) + "] ("+text+")"; logger.fine (message); } @@ -667,6 +759,34 @@ return wrapper; } + void requestStarted (HttpConnection c) { + c.creationTime = getTime(); + c.setState (State.REQUEST); + reqConnections.add (c); + } + + // called after a request has been completely read + // by the server. This stops the timer which would + // close the connection if the request doesn't arrive + // quickly enough. It then starts the timer + // that ensures the client reads the response in a timely + // fashion. + + void requestCompleted (HttpConnection c) { + assert c.getState() == State.REQUEST; + reqConnections.remove (c); + c.rspStartedTime = getTime(); + rspConnections.add (c); + c.setState (State.RESPONSE); + } + + // called after response has been sent + void responseCompleted (HttpConnection c) { + assert c.getState() == State.RESPONSE; + rspConnections.remove (c); + c.setState (State.IDLE); + } + /** * TimerTask run every CLOCK_TICK ms */ @@ -689,4 +809,62 @@ } } } + + class ServerTimerTask1 extends TimerTask { + + // runs every TIMER_MILLIS + public void run () { + LinkedList toClose = new LinkedList(); + time = System.currentTimeMillis(); + synchronized (reqConnections) { + if (MAX_REQ_TIME != -1) { + for (HttpConnection c : reqConnections) { + if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) { + toClose.add (c); + } + } + for (HttpConnection c : toClose) { + logger.log (Level.FINE, "closing: no request: " + c); + reqConnections.remove (c); + allConnections.remove (c); + c.close(); + } + } + } + toClose = new LinkedList(); + synchronized (rspConnections) { + if (MAX_RSP_TIME != -1) { + for (HttpConnection c : rspConnections) { + if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) { + toClose.add (c); + } + } + for (HttpConnection c : toClose) { + logger.log (Level.FINE, "closing: no response: " + c); + rspConnections.remove (c); + allConnections.remove (c); + c.close(); + } + } + } + } + } + + void logStackTrace (String s) { + logger.finest (s); + StringBuilder b = new StringBuilder (); + StackTraceElement[] e = Thread.currentThread().getStackTrace(); + for (int i=0; i 0) { + if (length == 0) { + return null; + } else { byte[] bytes = new byte[length]; read(bytes, 0, length); - Ticket ticket = new Ticket(bytes); - return ticket; + return bytes; } - else return null; } boolean[] readFlags() throws IOException { @@ -328,6 +328,17 @@ } return flags; } + + /** + * Reads the next cred in stream. + * @return the next cred, null if ticket or second_ticket unparseable. + * + * Note: MIT krb5 1.8.1 might generate a config entry with server principal + * X-CACHECONF:/krb5_ccache_conf_data/fast_avail/krbtgt/REALM@REALM. The + * entry is used by KDC to inform the client that it support certain + * features. Its ticket is not a valid krb5 ticket and thus this method + * returns null. + */ Credentials readCred(int version) throws IOException,RealmException, KrbApErrException, Asn1Exception { PrincipalName cpname = readPrincipal(version); if (DEBUG) @@ -367,17 +378,17 @@ if (auData != null) { auData = new AuthorizationData(auDataEntry); } - Ticket ticket = readData(); - if (DEBUG) { - System.out.println(">>>DEBUG "); - if (ticket == null) { - System.out.println("///ticket is null"); - } + byte[] ticketData = readData(); + byte[] ticketData2 = readData(); + + try { + return new Credentials(cpname, spname, key, authtime, starttime, + endtime, renewTill, skey, tFlags, + addrs, auData, + ticketData != null ? new Ticket(ticketData) : null, + ticketData2 != null ? new Ticket(ticketData2) : null); + } catch (Exception e) { // If any of new Ticket(*) fails. + return null; } - Ticket secTicket = readData(); - Credentials cred = new Credentials(cpname, spname, key, authtime, starttime, - endtime, renewTill, skey, tFlags, - addrs, auData, ticket, secTicket); - return cred; } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java --- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java Mon Nov 22 10:18:33 2010 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, 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 @@ -186,7 +186,10 @@ primaryRealm = primaryPrincipal.getRealm(); credentialsList = new Vector (); while (cis.available() > 0) { - credentialsList.addElement(cis.readCred(version)); + Credentials cred = cis.readCred(version); + if (cred != null) { + credentialsList.addElement(cred); + } } cis.close(); } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java --- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java Mon Nov 22 10:18:33 2010 -0500 @@ -74,7 +74,7 @@ // DEC: return the length of trailing padding bytes given the specified // padded data int unpad(byte[] paddedData, int len) - throws BadPaddingException; + throws BadPaddingException, IllegalBlockSizeException; } private static class PKCS5Padding implements Padding { @@ -96,9 +96,10 @@ } public int unpad(byte[] paddedData, int len) - throws BadPaddingException { - if (len < 1 || len > paddedData.length) { - throw new BadPaddingException("Invalid pad array length!"); + throws BadPaddingException, IllegalBlockSizeException { + if ((len < 1) || (len % blockSize != 0)) { + throw new IllegalBlockSizeException + ("Input length must be multiples of " + blockSize); } byte padValue = paddedData[len - 1]; if (padValue < 1 || padValue > blockSize) { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/security/ssl/Krb5Helper.java --- a/jdk/src/share/classes/sun/security/ssl/Krb5Helper.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/security/ssl/Krb5Helper.java Mon Nov 22 10:18:33 2010 -0500 @@ -10,7 +10,7 @@ * * 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 + * 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). * diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/security/ssl/Krb5Proxy.java --- a/jdk/src/share/classes/sun/security/ssl/Krb5Proxy.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/security/ssl/Krb5Proxy.java Mon Nov 22 10:18:33 2010 -0500 @@ -10,7 +10,7 @@ * * 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 + * 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). * diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java --- a/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java Mon Nov 22 10:18:33 2010 -0500 @@ -10,7 +10,7 @@ * * 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 + * 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). * diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/Demo.java --- a/jdk/src/share/demo/nio/zipfs/Demo.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/Demo.java Mon Nov 22 10:18:33 2010 -0500 @@ -75,9 +75,15 @@ // copy an external src file into zipfile // as entry dst + copyin_attrs, // + // copy an external src file into zipfile + // as entry dst, with attributes (timestamp) + copyout, // // copy zipfile entry src" out to file dst + copyout_attrs, // + zzmove, // // move entry path/dir from zfsrc to zfdst @@ -94,6 +100,9 @@ setmtime, // // set the lastModifiedTime of entry path + setatime, // + setctime, // + lsdir, // // list dir's direct child files/dirs @@ -135,12 +144,14 @@ attrs2, // // test different ways to print attrs + + prof, } public static void main(String[] args) throws Throwable { - Action action = Action.valueOf(args[0]);; - Map env = env = new HashMap(); + Action action = Action.valueOf(args[0]); + Map env = env = new HashMap<>(); if (action == Action.create) env.put("createNew", true); if (action == Action.tlist || action == Action.twalk) @@ -185,6 +196,16 @@ dst = fs.getPath(args[3]); src.copyTo(dst); break; + case copyin_attrs: + src = Paths.get(args[2]); + dst = fs.getPath(args[3]); + src.copyTo(dst, COPY_ATTRIBUTES); + break; + case copyout_attrs: + src = fs.getPath(args[2]); + dst = Paths.get(args[3]); + src.copyTo(dst, COPY_ATTRIBUTES); + break; case zzmove: fs2 = FileSystems.newFileSystem( URI.create("zip" + Paths.get(args[2]).toUri().toString().substring(4)), @@ -206,6 +227,7 @@ case attrs: for (int i = 2; i < args.length; i++) { path = fs.getPath(args[i]); + System.out.println(path); System.out.println( Attributes.readBasicFileAttributes(path).toString()); } @@ -221,6 +243,28 @@ Attributes.readBasicFileAttributes(path).toString()); } break; + case setctime: + df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); + newDatetime = df.parse(args[2]); + for (int i = 3; i < args.length; i++) { + path = fs.getPath(args[i]); + path.setAttribute("creationTime", + FileTime.fromMillis(newDatetime.getTime())); + System.out.println( + Attributes.readBasicFileAttributes(path).toString()); + } + break; + case setatime: + df = new SimpleDateFormat("MM/dd/yyyy-HH:mm:ss"); + newDatetime = df.parse(args[2]); + for (int i = 3; i < args.length; i++) { + path = fs.getPath(args[i]); + path.setAttribute("lastAccessTime", + FileTime.fromMillis(newDatetime.getTime())); + System.out.println( + Attributes.readBasicFileAttributes(path).toString()); + } + break; case attrsspace: path = fs.getPath("/"); FileStore fstore = path.getFileStore(); @@ -293,6 +337,7 @@ case attrs2: for (int i = 2; i < args.length; i++) { path = fs.getPath(args[i]); + System.out.printf("%n%s%n", path); System.out.println("-------(1)---------"); System.out.println( Attributes.readBasicFileAttributes(path).toString()); @@ -308,6 +353,13 @@ } } break; + case prof: + list(fs.getPath("/"), false); + while (true) { + Thread.sleep(10000); + //list(fs.getPath("/"), true); + System.out.println("sleeping..."); + } } } catch (Exception x) { x.printStackTrace(); @@ -501,10 +553,11 @@ } private static void list(Path path, boolean verbose ) throws IOException { - if (verbose) - System.out.println(Attributes.readBasicFileAttributes(path).toString()); - else - System.out.printf(" %s%n", path.toString()); + if (!"/".equals(path.toString())) { + System.out.printf(" %s%n", path.toString()); + if (verbose) + System.out.println(Attributes.readBasicFileAttributes(path).toString()); + } if (path.notExists()) return; if (Attributes.readBasicFileAttributes(path).isDirectory()) { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/README.txt --- a/jdk/src/share/demo/nio/zipfs/README.txt Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/README.txt Mon Nov 22 10:18:33 2010 -0500 @@ -2,7 +2,7 @@ JAR file as a java.nio.file.FileSystem. To deploy the provider you must copy zipfs.jar into your extensions -directory or else add /demo/nio/ZipFileSystem/zipfs.jar +directory or else add /demo/nio/zipfs/zipfs.jar to your class path. The factory methods defined by the java.nio.file.FileSystems class can be @@ -10,8 +10,8 @@ // use file type detection Map env = Collections.emptyMap(); - Path jarfile = Path.get("foo.jar"); - FileSystem fs = FileSystems.newFileSystem(jarfile, env); + Path jarfile = Paths.get("foo.jar"); + FileSystem fs = FileSystems.newFileSystem(jarfile, env, null); -or diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/JarFileSystemProvider.java Mon Nov 22 10:18:33 2010 -0500 @@ -68,4 +68,21 @@ 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"); + } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipConstants.java Mon Nov 22 10:18:33 2010 -0500 @@ -31,7 +31,6 @@ package com.sun.nio.zipfs; -import java.nio.ByteBuffer; /** * @@ -48,6 +47,7 @@ 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 @@ -168,7 +168,8 @@ 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 @@ -226,34 +227,23 @@ 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 - ////////////////////////////////////////// - static final int CH(ByteBuffer b, int pos) { - return b.get(pos) & 0xff; - } - static final int SH(ByteBuffer b, int pos) { - return b.getShort(pos) & 0xffff; - } - static final long LG(ByteBuffer b, int pos) { - return b.getInt(pos) & 0xffffffffL; - } - - // central directory header (END) fields - static final long CENSIG(ByteBuffer b, int pos) { return LG(b, pos + 0); } - static final int CENVEM(ByteBuffer b, int pos) { return SH(b, pos + 4); } - static final int CENVER(ByteBuffer b, int pos) { return SH(b, pos + 6); } - static final int CENFLG(ByteBuffer b, int pos) { return SH(b, pos + 8); } - static final int CENHOW(ByteBuffer b, int pos) { return SH(b, pos + 10);} - static final long CENTIM(ByteBuffer b, int pos) { return LG(b, pos + 12);} - static final long CENCRC(ByteBuffer b, int pos) { return LG(b, pos + 16);} - static final long CENSIZ(ByteBuffer b, int pos) { return LG(b, pos + 20);} - static final long CENLEN(ByteBuffer b, int pos) { return LG(b, pos + 24);} - static final int CENNAM(ByteBuffer b, int pos) { return SH(b, pos + 28);} - static final int CENEXT(ByteBuffer b, int pos) { return SH(b, pos + 30);} - static final int CENCOM(ByteBuffer b, int pos) { return SH(b, pos + 32);} - static final int CENDSK(ByteBuffer b, int pos) { return SH(b, pos + 34);} - static final int CENATT(ByteBuffer b, int pos) { return SH(b, pos + 36);} - static final long CENATX(ByteBuffer b, int pos) { return LG(b, pos + 38);} - static final long CENOFF(ByteBuffer b, int pos) { return LG(b, pos + 42);} + // 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; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipDirectoryStream.java Mon Nov 22 10:18:33 2010 -0500 @@ -38,7 +38,6 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.io.IOException; -import static com.sun.nio.zipfs.ZipUtils.*; /** * @@ -77,7 +76,7 @@ } catch (IOException e) { throw new IllegalStateException(e); } - return new Iterator() { + return new Iterator<>() { private Path next; @Override public boolean hasNext() { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributeView.java Mon Nov 22 10:18:33 2010 -0500 @@ -32,7 +32,6 @@ package com.sun.nio.zipfs; -import java.nio.file.ReadOnlyFileSystemException; import java.nio.file.attribute.BasicFileAttributeView; import java.nio.file.attribute.FileAttributeView; import java.nio.file.attribute.FileTime; @@ -113,6 +112,10 @@ 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 + diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileAttributes.java Mon Nov 22 10:18:33 2010 -0500 @@ -56,7 +56,7 @@ @Override public FileTime creationTime() { if (e.ctime != -1) - return FileTime.fromMillis(dosToJavaTime(e.ctime)); + return FileTime.fromMillis(e.ctime); return null; } @@ -78,13 +78,13 @@ @Override public FileTime lastAccessTime() { if (e.atime != -1) - return FileTime.fromMillis(dosToJavaTime(e.atime)); + return FileTime.fromMillis(e.atime); return null; } @Override public FileTime lastModifiedTime() { - return FileTime.fromMillis(dosToJavaTime(e.mtime)); + return FileTime.fromMillis(e.mtime); } @Override @@ -103,10 +103,6 @@ } ///////// zip entry attributes /////////// - public byte[] name() { - return Arrays.copyOf(e.name, e.name.length); - } - public long compressedSize() { return e.csize; } @@ -132,10 +128,13 @@ } public String toString() { - StringBuilder sb = new StringBuilder(); + StringBuilder sb = new StringBuilder(1024); Formatter fm = new Formatter(sb); - fm.format("[/%s]%n", new String(e.name)); // TBD encoding - fm.format(" creationTime : %s%n", creationTime()); + 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 diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystem.java Mon Nov 22 10:18:33 2010 -0500 @@ -35,19 +35,18 @@ import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import java.nio.MappedByteBuffer; import java.nio.channels.*; import java.nio.file.*; import java.nio.file.attribute.*; import java.nio.file.spi.*; -import java.net.URI; 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; @@ -76,8 +75,6 @@ private final Path zfpath; private final ZipCoder zc; - private final Object lock = new Object(); - // configurable by env map private final String defaultDir; // default dir for the file system private final String nameEncoding; // default encoding for name/comment @@ -85,6 +82,8 @@ 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, @@ -92,13 +91,13 @@ throws IOException { // configurable env setup - this.buildDirTree = TRUE.equals(env.get("buildDirTree")); - this.useTempFile = TRUE.equals(env.get("useTempFile")); - this.createNew = TRUE.equals(env.get("createNew")); + 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") : "/"; + this.defaultDir = env.containsKey("default.dir") ? + (String)env.get("default.dir") : "/"; if (this.defaultDir.charAt(0) != '/') throw new IllegalArgumentException("default dir should be absolute"); @@ -121,7 +120,8 @@ } this.zc = ZipCoder.get(nameEncoding); this.defaultdir = new ZipPath(this, getBytes(defaultDir)); - initZipFile(); + this.ch = zfpath.newByteChannel(READ); + this.cen = initCEN(); } @Override @@ -183,7 +183,7 @@ @Override public Iterable getFileStores() { - ArrayList list = new ArrayList(1); + ArrayList list = new ArrayList<>(1); list.add(new ZipFileStore(new ZipPath(this, new byte[]{'/'}))); return list; } @@ -240,19 +240,27 @@ @Override public void close() throws IOException { - synchronized (lock) { + beginWrite(); + try { if (!isOpen) return; - isOpen = false; - if (!streams.isEmpty()) { - synchronized(streams) { - for (InputStream is: streams) - is.close(); - } - } + isOpen = false; // set closed + } finally { + endWrite(); + } + if (!streams.isEmpty()) { // unlock and close all remaining streams + Set copy = new HashSet<>(streams); + for (InputStream is: copy) + is.close(); + } + beginWrite(); // lock and sync + try { sync(); - ch.close(); + 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(); @@ -261,97 +269,101 @@ for (Deflater def : deflaters) def.end(); } - for (Path p: tmppaths) { - try { - p.deleteIfExists(); - } catch (IOException x) { - x.printStackTrace(); + + synchronized (tmppaths) { + for (Path p: tmppaths) { + try { + p.deleteIfExists(); + } catch (IOException x) { + x.printStackTrace(); + } } } provider.removeFileSystem(zfpath); } - ZipFileAttributes[] getAllAttributes() throws IOException { - ensureOpen(); - int n = inodes.size(); - ZipFileAttributes[] zes = new ZipFileAttributes[n]; - Iterator itr = inodes.values().iterator(); - int i = 0; - while(itr.hasNext()) { - zes[i++] = new ZipFileAttributes(Entry.readCEN(cen, itr.next().pos)); - } - return zes; - } - - EntryName[] getEntryNames() throws IOException { - ensureOpen(); - return inodes.keySet().toArray(new EntryName[0]); - } - ZipFileAttributes getFileAttributes(byte[] path) throws IOException { - synchronized (lock) { - Entry e = getEntry0(path); - if (e == null) { - if (path.length == 0) { - e = new Entry(new byte[0]); // root - } else if (buildDirTree) { - IndexNode inode = getDirs().get(new EntryName(path)); - if (inode == null) - return null; - e = new Entry(inode.name); - } else { + 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.method = METHOD_STORED; // STORED for dir - BasicFileAttributes bfas = Attributes.readBasicFileAttributes(zfpath); - if (bfas.lastModifiedTime() != null) - e.mtime = javaToDosTime(bfas.lastModifiedTime().toMillis()); - if (bfas.lastAccessTime() != null) - e.atime = javaToDosTime(bfas.lastAccessTime().toMillis()); - if (bfas.creationTime() != null) - e.ctime = javaToDosTime(bfas.creationTime().toMillis()); + e = new Entry(inode.name); + } else { + return null; } - return new ZipFileAttributes(e); + 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(); - synchronized (lock) { + 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 = javaToDosTime(mtime.toMillis()); + e.mtime = mtime.toMillis(); if (atime != null) - e.atime = javaToDosTime(atime.toMillis()); + e.atime = atime.toMillis(); if (ctime != null) - e.ctime = javaToDosTime(ctime.toMillis()); + e.ctime = ctime.toMillis(); update(e); + } finally { + endWrite(); } } boolean exists(byte[] path) throws IOException { - return getEntry0(path) != null; + beginRead(); + try { + ensureOpen(); + return getEntry0(path) != null; + } finally { + endRead(); + } } boolean isDirectory(byte[] path) throws IOException { - synchronized (lock) { - if (buildDirTree) { - return getDirs().containsKey(new EntryName(path)); - } + if (buildDirTree) + return getDirs().containsKey(IndexNode.keyOf(path)); + + beginRead(); + try { Entry e = getEntry0(path); return (e != null && e.isDir()) || path.length == 0; + } finally { + endRead(); } } @@ -368,12 +380,14 @@ DirectoryStream.Filter filter) throws IOException { - synchronized (lock) { + beginWrite(); // iteration of inodes needs exclusive lock + try { + ensureOpen(); if (buildDirTree) { - IndexNode inode = getDirs().get(new EntryName(path)); + IndexNode inode = getDirs().get(IndexNode.keyOf(path)); if (inode == null) throw new NotDirectoryException(getString(path)); - List list = new ArrayList(); + List list = new ArrayList<>(); IndexNode child = inode.child; while (child != null) { ZipPath zp = toZipPath(child.name); @@ -386,25 +400,26 @@ if (!isDirectory(path)) throw new NotDirectoryException(getString(path)); - List list = new ArrayList(); - EntryName[] entries = getEntryNames(); + List list = new ArrayList<>(); path = toDirectoryPath(path); - for (EntryName en :entries) { - if (!isParentOf(path, en.name)) // is "path" the parent of "name" + for (IndexNode key : inodes.keySet()) { + if (!isParentOf(path, key.name)) // is "path" the parent of "name" continue; int off = path.length; - while (off < en.name.length) { - if (en.name[off] == '/') + while (off < key.name.length) { + if (key.name[off] == '/') break; off++; } - if (off < (en.name.length - 1)) + if (off < (key.name.length - 1)) continue; - ZipPath zp = toZipPath(en.name); + ZipPath zp = toZipPath(key.name); if (filter == null || filter.accept(zp)) list.add(zp); } return list.iterator(); + } finally { + endWrite(); } } @@ -413,16 +428,18 @@ { checkWritable(); dir = toDirectoryPath(dir); - synchronized (lock) { + beginWrite(); + try { ensureOpen(); - // pseudo root dir, or exiting dir - if (dir.length == 0 || exists(dir)) + 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 + e.method = METHOD_STORED; // STORED for dir update(e); + } finally { + endWrite(); } } @@ -432,7 +449,10 @@ checkWritable(); if (Arrays.equals(src, dst)) return; // do nothing, src and dst are the same - synchronized (lock) { + + beginWrite(); + try { + ensureOpen(); Entry eSrc = getEntry0(src); // ensureOpen checked if (eSrc == null) throw new NoSuchFileException(getString(src)); @@ -457,11 +477,6 @@ } Entry u = new Entry(eSrc, Entry.COPY); // copy eSrc entry u.name = dst; // change name - // don't touch the "nlen and elen" here. writeLOC() always - // re-calculate from "name" and "extra" for the correct length, - // copyLOCEntry however needs the original lengths to skip the - // loc header. - // u.nlen = dst.length; if (eSrc.type == Entry.NEW || eSrc.type == Entry.FILECH) { u.type = eSrc.type; // make it the same type @@ -475,10 +490,12 @@ } } if (!hasCopyAttrs) - u.mtime = u.atime= u.ctime = javaToDosTime(System.currentTimeMillis()); + u.mtime = u.atime= u.ctime = System.currentTimeMillis(); update(u); if (deletesrc) updateDelete(eSrc); + } finally { + endWrite(); } } @@ -501,7 +518,9 @@ if (opt == APPEND) hasAppend = true; } - synchronized (lock) { + 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) @@ -512,27 +531,33 @@ copyStream(is, os); is.close(); return os; - } - return getOutputStream(new Entry(e, Entry.NEW)); + } + 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 { - synchronized (lock) { + 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(); } } @@ -559,78 +584,111 @@ if (options.contains(StandardOpenOption.WRITE) || options.contains(StandardOpenOption.APPEND)) { checkWritable(); - 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; + 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; } - public void close() throws IOException { - wbc.close(); - } - }; + 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 { - 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(); - } - }; + 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(); + } } } @@ -647,125 +705,131 @@ checkOptions(options); final boolean forWrite = (options.contains(StandardOpenOption.WRITE) || options.contains(StandardOpenOption.APPEND)); - Entry e = getEntry0(path); - if (forWrite) { - checkWritable(); - if (e == null) { + 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); + } 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)); } - 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); + + 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; } - 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 = javaToDosTime(System.currentTimeMillis()); - u.size = Attributes.readBasicFileAttributes(u.file).size(); - update(u); - } else { - if (!isFCH) // if this is a new fch for reading - removeTempPathForEntry(tmpfile); + // 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 @@ -776,11 +840,9 @@ // input streams are all closed by the obtainers. private Set exChClosers = new HashSet<>(); - private Set tmppaths = new HashSet<>(); + private Set tmppaths = Collections.synchronizedSet(new HashSet()); private Path getTempPathForEntry(byte[] path) throws IOException { Path tmpPath = createTempFileInSameDirectoryAs(zfpath); - tmppaths.add(tmpPath); - if (path != null) { Entry e = getEntry0(path); if (e != null) { @@ -805,9 +867,14 @@ // check if all parents really exit. ZIP spec does not require // the existence of any "parent directory". private void checkParents(byte[] path) throws IOException { - while ((path = getParent(path)) != null) { - if (!inodes.containsKey(new EntryName(path))) - throw new NoSuchFileException(getString(path)); + beginRead(); + try { + while ((path = getParent(path)) != null) { + if (!inodes.containsKey(IndexNode.keyOf(path))) + throw new NoSuchFileException(getString(path)); + } + } finally { + endRead(); } } @@ -839,25 +906,40 @@ return true; } - /////////////////////////////////////////////////////////////////// - private void initZipFile() throws IOException { - ch = zfpath.newByteChannel(READ); - initCEN(); + 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 SeekableByteChannel ch; // channel to the zipfile - ByteBuffer cen; // CEN & ENDHDR + 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) - // name -> pos (in cen), package private for ZipInfo - LinkedHashMap inodes; + private final ReadWriteLock rwlock = new ReentrantReadWriteLock(); - byte[] getBytes(String name) { + // name -> pos (in cen), IndexNode itself can be used as a "key" + private LinkedHashMap inodes; + + final byte[] getBytes(String name) { return zc.getBytes(name); } - String getString(byte[] name) { + + final String getString(byte[] name) { return zc.toString(name); } @@ -881,7 +963,7 @@ // 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). - private long readFullyAt(byte[] buf, int off, long len, long pos) + final long readFullyAt(byte[] buf, int off, long len, long pos) throws IOException { ByteBuffer bb = ByteBuffer.wrap(buf); @@ -890,7 +972,7 @@ return readFullyAt(bb, pos); } - private long readFullyAt(ByteBuffer bb, long pos) + private final long readFullyAt(ByteBuffer bb, long pos) throws IOException { synchronized(ch) { @@ -971,12 +1053,12 @@ // 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 long initCEN() throws IOException { + private byte[] initCEN() throws IOException { end = findEND(); if (end.endpos == 0) { - inodes = new LinkedHashMap(10); + inodes = new LinkedHashMap<>(10); locpos = 0; - return 0; // only END header present + return null; // only END header present } if (end.cenlen > end.endpos) zerror("invalid END header (bad central directory size)"); @@ -989,18 +1071,14 @@ zerror("invalid END header (bad central directory offset)"); // read in the CEN and END - cen = ByteBuffer.allocate((int)(end.cenlen + ENDHDR)); - if (readFullyAt(cen, cenpos) != end.cenlen + ENDHDR) { + byte[] cen = new byte[(int)(end.cenlen + ENDHDR)]; + if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { zerror("read CEN tables failed"); } - cen.order(ByteOrder.LITTLE_ENDIAN).flip(); - // Iterate through the entries in the central directory - inodes = new LinkedHashMap(end.centot + 1); + inodes = new LinkedHashMap<>(end.centot + 1); int pos = 0; - int limit = cen.remaining() - ENDHDR; - int i = 0; - byte[] bBuf = new byte[1024]; + int limit = cen.length - ENDHDR; while (pos < limit) { if (CENSIG(cen, pos) != CENSIG) zerror("invalid CEN header (bad signature)"); @@ -1011,24 +1089,19 @@ if ((CENFLG(cen, pos) & 1) != 0) zerror("invalid CEN header (encrypted entry)"); if (method != METHOD_STORED && method != METHOD_DEFLATED) - zerror("invalid CEN header (bad compression method: " + method + ")"); + zerror("invalid CEN header (unsupported compression method: " + method + ")"); if (pos + CENHDR + nlen > limit) zerror("invalid CEN header (bad header size)"); - if (bBuf.length < nlen) - bBuf = new byte[nlen]; - cen.position(pos + CENHDR); - byte[] name = new byte[nlen]; - cen.get(name); - inodes.put(new EntryName(name), new IndexNode(name, pos)); + byte[] name = Arrays.copyOfRange(cen, pos + CENHDR, pos + CENHDR + nlen); + IndexNode inode = new IndexNode(name, pos); + inodes.put(inode, inode); // skip ext and comment - cen.position(pos += (CENHDR + nlen + elen + clen)); - i++; + pos += (CENHDR + nlen + elen + clen); } - if (cen.remaining() != ENDHDR) { + if (pos + ENDHDR != cen.length) { zerror("invalid CEN header (bad header size)"); } - dirs = null; // clear the dir map - return cenpos; + return cen; } private void ensureOpen() throws IOException { @@ -1038,27 +1111,40 @@ // Creates a new empty temporary file in the same directory as the // specified file. A variant of File.createTempFile. - private static Path createTempFileInSameDirectoryAs(Path path) + private Path createTempFileInSameDirectoryAs(Path path) throws IOException { Path parent = path.toAbsolutePath().getParent(); String dir = (parent == null)? "." : parent.toString(); - return File.createTempFile("zipfstmp", null, new File(dir)).toPath(); + 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) { - EntryName en = new EntryName(e.name); - inodes.remove(en); - hasUpdate = true; + beginWrite(); + try { + inodes.remove(IndexNode.keyOf(e.name)); //inodes.remove(e.name); + hasUpdate = true; + dirs = null; + } finally { + endWrite(); + } } private void update(Entry e) { - EntryName en = new EntryName(e.name); - inodes.put(en, e); - hasUpdate = true; + 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 @@ -1080,13 +1166,18 @@ else size = 16; } - if (updateHeader) { // if we need update the loc header - locoff += LOCHDR + e.nlen + e.elen; // skip header + // 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 { - size += LOCHDR + e.nlen + e.elen + e.csize; - written = size; + 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 && @@ -1103,7 +1194,7 @@ // sync the zip file system, if there is any udpate private void sync() throws IOException { - assert Thread.holdsLock(this); + //System.out.printf("->sync(%s) starting....!%n", toString()); // check ex-closer if (!exChClosers.isEmpty()) { @@ -1117,7 +1208,6 @@ } if (!hasUpdate) return; - Path tmpFile = createTempFileInSameDirectoryAs(zfpath); OutputStream os = tmpFile.newOutputStream(WRITE); ArrayList elist = new ArrayList<>(inodes.size()); @@ -1174,7 +1264,7 @@ x.printStackTrace(); // skip any in-accurate entry } } else { // unchanged inode - e = Entry.readCEN(cen, inode.pos); + e = Entry.readCEN(this, inode.pos); try { written += copyLOCEntry(e, false, os, written, buf); elist.add(e); @@ -1195,6 +1285,11 @@ 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 @@ -1209,45 +1304,41 @@ ch.close(); zfpath.delete(); } + tmpFile.moveTo(zfpath, REPLACE_EXISTING); hasUpdate = false; // clear - + /* if (isOpen) { ch = zfpath.newByteChannel(READ); // re-fresh "ch" and "cen" - initCEN(); + cen = initCEN(); } - //System.out.println("->sync() done!"); + */ + //System.out.printf("->sync(%s) done!%n", toString()); } private Entry getEntry0(byte[] path) throws IOException { - assert Thread.holdsLock(this); - if (path == null) throw new NullPointerException("path"); if (path.length == 0) return null; - EntryName en = new EntryName(path); IndexNode inode = null; - synchronized (lock) { - ensureOpen(); - if ((inode = inodes.get(en)) == null) { - if (path[path.length -1] == '/') // already has a slash - return null; - path = Arrays.copyOf(path, path.length + 1); - path[path.length - 1] = '/'; - en.name(path); - if ((inode = inodes.get(en)) == null) - return null; - } - if (inode instanceof Entry) - return (Entry)inode; - return Entry.readCEN(cen, inode.pos); + 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 entry : inodes.entrySet()) { + for (Map.Entry entry : inodes.entrySet()) { byte[] ename = entry.getKey().name; if (isParentOf(name, ename)) return true; @@ -1259,18 +1350,16 @@ throws IOException { checkWritable(); - synchronized(lock) { - 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); - } + 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); } } @@ -1289,9 +1378,8 @@ // (2) updating/replacing the contents of the specified existing entry. private OutputStream getOutputStream(Entry e) throws IOException { - ensureOpen(); if (e.mtime == -1) - e.mtime = javaToDosTime(System.currentTimeMillis()); + 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 @@ -1334,7 +1422,7 @@ long bufSize = e.size + 2; // Inflater likes a bit of slack if (bufSize > 65536) bufSize = 8192; - final long size = e.size;; + final long size = e.size; eis = new InflaterInputStream(eis, getInflater(), (int)bufSize) { private boolean isClosed = false; @@ -1343,6 +1431,7 @@ releaseInflater(inf); this.in.close(); isClosed = true; + streams.remove(this); } } // Override fill() method to provide an extra "dummy" byte @@ -1372,7 +1461,9 @@ Integer.MAX_VALUE : (int) avail; } }; - } else if (e.method != METHOD_STORED) { + } else if (e.method == METHOD_STORED) { + // TBD: wrap/ it does not seem necessary + } else { throw new ZipException("invalid compression method"); } streams.add(eis); @@ -1382,11 +1473,11 @@ // Inner class implementing the input stream used to read // a (possibly compressed) zip file entry. private class EntryInputStream extends InputStream { - private SeekableByteChannel zfch; // local ref to zipfs's "ch". zipfs.ch might + 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 long size; // uncompressed size of this entry + protected final long size; // uncompressed size of this entry EntryInputStream(Entry e, SeekableByteChannel zfch) throws IOException @@ -1527,14 +1618,14 @@ } } - private static void zerror(String msg) { + 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 List inflaters = new ArrayList<>(); + private final List inflaters = new ArrayList<>(); // Gets an inflater from the list of available inflaters or allocates // a new one. @@ -1563,7 +1654,7 @@ } // List of available Deflater objects for compression - private List deflaters = new ArrayList<>(); + private final List deflaters = new ArrayList<>(); // Gets an deflater from the list of available deflaters or allocates // a new one. @@ -1660,44 +1751,40 @@ } } - // wrapper for the byte[] name - static class EntryName { + // 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 - - public EntryName (byte[] name) { - name(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; } - void name(byte[] name) { - this.name = name; + 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 EntryName)) + if (!(other instanceof IndexNode)) return false; - return Arrays.equals(name, ((EntryName)other).name); + return Arrays.equals(name, ((IndexNode)other).name); } public int hashCode() { return hashcode; } - } - - // can simply use Integer instead, if we don't use it to - // build a internal node tree. - static class IndexNode { - byte[] name; - int pos = -1; // postion in cen table, -1 menas the - // entry does not exists in zip file - IndexNode(byte[] name, int pos) { - this.name = name; - this.pos = pos; - } IndexNode() {} - IndexNode sibling; IndexNode child; // 1st child } @@ -1723,37 +1810,25 @@ long crc = -1; // crc-32 of entry data long csize = -1; // compressed size of entry data long size = -1; // uncompressed size of entry data - int nlen; - int elen; byte[] extra; - // loc - long startPos; - long endPos; // exclusive - // cen int versionMade; int disk; int attrs; long attrsEx; long locoff; - - int clen; byte[] comment; - // ZIP64 flag - boolean hasZip64; - Entry() {} Entry(byte[] name) { - this.name = name; - //this.nlen = name.length; - this.mtime = javaToDosTime(System.currentTimeMillis()); - this.crc = 0; - this.size = 0; - this.csize = 0; - this.method = METHOD_DEFLATED; + 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) { @@ -1761,16 +1836,9 @@ this.type = type; } - Entry (byte[] name, Path file, int type) { - this(name, type); - this.file = file; - this.method = METHOD_STORED; - } - - Entry(Entry e) { + Entry (Entry e, int type) { this.version = e.version; - this.name = e.name; // copyOf? - this.nlen = e.nlen; + this.name = e.name; this.ctime = e.ctime; this.atime = e.atime; this.mtime = e.mtime; @@ -1778,25 +1846,21 @@ this.size = e.size; this.csize = e.csize; this.method = e.method; - this.extra = (e.extra == null)? - null:Arrays.copyOf(e.extra, e.extra.length); - this.elen = e.elen; + 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.clen = e.clen; - this.comment = (e.comment == null)? - null:Arrays.copyOf(e.comment, e.comment.length); - this.startPos = e.startPos; - this.endPos = e.endPos; - this.hasZip64 = e.hasZip64;; + this.comment = e.comment; + + this.type = type; } - Entry (Entry e, int type) { - this(e); - this.type = type; + Entry (byte[] name, Path file, int type) { + this(name, type); + this.file = file; + this.method = METHOD_STORED; } boolean isDir() { @@ -1814,77 +1878,45 @@ } ///////////////////// CEN ////////////////////// - static Entry readCEN(ByteBuffer cen, int pos) throws IOException + static Entry readCEN(ZipFileSystem zipfs, int pos) + throws IOException { - return new Entry().cen(cen, pos); + return new Entry().cen(zipfs, pos); } - private Entry cen(ByteBuffer cen, int pos) throws IOException + 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 = CENTIM(cen, pos); + mtime = dosToJavaTime(CENTIM(cen, pos)); crc = CENCRC(cen, pos); csize = CENSIZ(cen, pos); size = CENLEN(cen, pos); - nlen = CENNAM(cen, pos); - elen = CENEXT(cen, pos); - clen = CENCOM(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); - cen.position(pos + CENHDR); - name = new byte[nlen]; - cen.get(name); + pos += CENHDR; + name = Arrays.copyOfRange(cen, pos, pos + nlen); + pos += nlen; if (elen > 0) { - extra = new byte[elen]; - cen.get(extra); - if (csize == ZIP64_MINVAL || size == ZIP64_MINVAL || - locoff == ZIP64_MINVAL) { - int off = 0; - while (off + 4 < elen) { - // extra spec: HeaderID+DataSize+Data - int sz = SH(extra, off + 2); - if (SH(extra, off) == EXTID_ZIP64) { - off += 4; - if (size == ZIP64_MINVAL) { - // if invalid zip64 extra fields, just skip - if (sz < 8 || (off + 8) > elen) - break; - size = LL(extra, off); - sz -= 8; - off += 8; - } - if (csize == ZIP64_MINVAL) { - if (sz < 8 || (off + 8) > elen) - break; - csize = LL(extra, off); - sz -= 8; - off += 8; - } - if (locoff == ZIP64_MINVAL) { - if (sz < 8 || (off + 8) > elen) - break; - locoff = LL(extra, off); - sz -= 8; - off += 8; - } - break; - } - off += (sz + 4); - } - } + extra = Arrays.copyOfRange(cen, pos, pos + elen); + pos += elen; + readExtra(zipfs); } if (clen > 0) { - comment = new byte[clen]; - cen.get(comment); + comment = Arrays.copyOfRange(cen, pos, pos + clen); } return this; } @@ -1897,31 +1929,37 @@ long csize0 = csize; long size0 = size; long locoff0 = locoff; - int e64len = 0; + 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 - nlen = (name != null) ? name.length : 0; - elen = (extra != null) ? extra.length : 0; - clen = (comment != null) ? comment.length : 0; - - boolean hasZip64 = false; + 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; - e64len += 8; // csize(8) - hasZip64 = true; + elen64 += 8; // csize(8) } if (size >= ZIP64_MINVAL) { size0 = ZIP64_MINVAL; // size(8) - e64len += 8; - hasZip64 = true; + elen64 += 8; } if (locoff >= ZIP64_MINVAL) { locoff0 = ZIP64_MINVAL; - e64len += 8; // offset(8) - hasZip64 = true; + 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 (hasZip64) { + if (elen64 != 0) { writeShort(os, 45); // ver 4.5 for zip64 writeShort(os, 45); } else { @@ -1930,18 +1968,14 @@ } writeShort(os, flag); // general purpose bit flag writeShort(os, method); // compression method - writeInt(os, mtime); // last modification time + // 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 (hasZip64) { - // + headid(2) + datasize(2) - writeShort(os, e64len + 4 + elen); - } else { - writeShort(os, elen); - } if (comment != null) { writeShort(os, Math.min(clen, 0xffff)); } else { @@ -1952,9 +1986,9 @@ writeInt(os, 0); // external file attributes (unused) writeInt(os, locoff0); // relative offset of local header writeBytes(os, name); - if (hasZip64) { + if (elen64 != 0) { writeShort(os, EXTID_ZIP64);// Zip64 extra - writeShort(os, e64len); + writeShort(os, elen64); // size of "this" extra block if (size0 == ZIP64_MINVAL) writeLong(os, size); if (csize0 == ZIP64_MINVAL) @@ -1962,58 +1996,73 @@ if (locoff0 == ZIP64_MINVAL) writeLong(os, locoff); } - if (extra != null) { - writeBytes(os, extra); + 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 (comment != null) { - //TBD: 0, Math.min(commentBytes.length, 0xffff)); + 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 + (hasZip64?(e64len + 4):0); + return CENHDR + nlen + elen + clen + elen64 + elenNTFS + elenEXTT; } ///////////////////// LOC ////////////////////// - static Entry readLOC(ZipFileSystem zf, long pos) + static Entry readLOC(ZipFileSystem zipfs, long pos) throws IOException { - return readLOC(zf, pos, new byte[1024]); + return readLOC(zipfs, pos, new byte[1024]); } - static Entry readLOC(ZipFileSystem zf, long pos, byte[] buf) + static Entry readLOC(ZipFileSystem zipfs, long pos, byte[] buf) throws IOException { - return new Entry().loc(zf, pos, buf); + return new Entry().loc(zipfs, pos, buf); } - Entry loc(ZipFileSystem zf, long pos, byte[] buf) + Entry loc(ZipFileSystem zipfs, long pos, byte[] buf) throws IOException { assert (buf.length >= LOCHDR); - if (zf.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) { + if (zipfs.readFullyAt(buf, 0, LOCHDR , pos) != LOCHDR) throw new ZipException("loc: reading failed"); - } - if (LOCSIG(buf) != LOCSIG) { + if (LOCSIG(buf) != LOCSIG) throw new ZipException("loc: wrong sig ->" + Long.toString(LOCSIG(buf), 16)); - } - startPos = pos; + //startPos = pos; version = LOCVER(buf); flag = LOCFLG(buf); method = LOCHOW(buf); - mtime = LOCTIM(buf); + mtime = dosToJavaTime(LOCTIM(buf)); crc = LOCCRC(buf); csize = LOCSIZ(buf); size = LOCLEN(buf); - nlen = LOCNAM(buf); - elen = LOCEXT(buf); + int nlen = LOCNAM(buf); + int elen = LOCEXT(buf); name = new byte[nlen]; - if (zf.readFullyAt(name, 0, nlen, pos + LOCHDR) != 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 (zf.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen) + if (zipfs.readFullyAt(extra, 0, elen, pos + LOCHDR + nlen) != elen) { throw new ZipException("loc: ext reading failed"); } @@ -2021,7 +2070,7 @@ pos += (LOCHDR + nlen + elen); if ((flag & FLAG_DATADESCR) != 0) { // Data Descriptor - Entry e = zf.getEntry0(name); // get the size/csize from cen + 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; @@ -2032,7 +2081,6 @@ else pos += 16; } else { - boolean hasZip64 = false; if (extra != null && (size == ZIP64_MINVAL || csize == ZIP64_MINVAL)) { // zip64 ext: must include both size and csize @@ -2042,7 +2090,6 @@ if (SH(extra, off) == EXTID_ZIP64 && sz == 16) { size = LL(extra, off + 4); csize = LL(extra, off + 12); - hasZip64 = true; break; } off += (sz + 4); @@ -2050,7 +2097,6 @@ } pos += (method == METHOD_STORED ? size : csize); } - endPos = pos; return this; } @@ -2058,14 +2104,18 @@ throws IOException { writeInt(os, LOCSIG); // LOC header signature + int version = version(); - 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 - writeInt(os, mtime); // last modification time - + // 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); @@ -2073,7 +2123,7 @@ writeInt(os, 0); } else { if (csize >= ZIP64_MINVAL || size >= ZIP64_MINVAL) { - hasZip64 = true; + 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 @@ -2082,29 +2132,45 @@ writeShort(os, method); // compression method writeInt(os, mtime); // last modification time writeInt(os, crc); // crc-32 - if (hasZip64) { + if (elen64 != 0) { writeInt(os, ZIP64_MINVAL); writeInt(os, ZIP64_MINVAL); - //TBD: e.elen += 20; //headid(2) + size(2) + size(8) + csize(8) } 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 + (hasZip64 ? 20 : 0)); + writeShort(os, elen + elen64 + elenEXTT); writeBytes(os, name); - if (hasZip64) { - // TBD: should we update extra directory? + 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 + (hasZip64 ? 20 : 0); + return LOCHDR + name.length + elen + elen64 + elenEXTT; } // Data Descriptior @@ -2125,17 +2191,18 @@ } // read NTFS, UNIX and ZIP64 data from cen.extra - void readExtra() { + 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 sz = SH(extra, off + 2); - int tag = SH(extra, off); - off += 4; 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) { @@ -2165,18 +2232,66 @@ break; if (SH(extra, pos + 2) != 24) break; - mtime = LL(extra, pos + 4); - atime = LL(extra, pos + 12); - ctime = LL(extra, pos + 20); + // 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_UNIX: - atime = LG(extra, pos); - mtime = LG(extra, pos + 4); + 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: // unknow + default: // unknown tag + System.arraycopy(extra, off, extra, newOff, sz + 4); + newOff += (sz + 4); } - off += sz; + off += (sz + 4); } + if (newOff != 0 && newOff != extra.length) + extra = Arrays.copyOf(extra, newOff); + else + extra = null; } } @@ -2201,9 +2316,9 @@ // structure. // A possible solution is to build the node tree ourself as // implemented below. - private HashMap dirs; + private HashMap dirs; private IndexNode root; - private IndexNode addToDir(EntryName child) { + private IndexNode addToDir(IndexNode child) { IndexNode cinode = dirs.get(child); if (cinode != null) return cinode; @@ -2213,7 +2328,7 @@ IndexNode pinode; if (pname != null) - pinode = addToDir(new EntryName(pname)); + pinode = addToDir(IndexNode.keyOf(pname)); else pinode = root; cinode = inodes.get(child); @@ -2222,8 +2337,8 @@ pinode.child = cinode; return null; } - cinode = dirs.get(child); - if (cinode == null) // pseudo directry entry + //cinode = dirs.get(child); + if (cinode == null) // pseudo directry entry cinode = new IndexNode(cname, -1); cinode.sibling = pinode.child; pinode.child = cinode; @@ -2232,26 +2347,21 @@ return cinode; } - private HashMap getDirs() + private HashMap getDirs() throws IOException { - if (hasUpdate) - sync(); - if (dirs != null) + 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; - dirs = new HashMap(); - byte[] empty = new byte[0]; - root = new IndexNode(empty, -1); - dirs.put(new EntryName(empty), root); - - EntryName[] names = inodes.keySet().toArray(new EntryName[0]); - int i = names.length; - while (--i >= 0) { - addToDir(names[i]); + } finally { + endWrite(); } - // for (int i EntryName en : inodes.keySet()) { - // addToDir(en); - // } - return dirs; } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipFileSystemProvider.java Mon Nov 22 10:18:33 2010 -0500 @@ -55,6 +55,8 @@ */ public class ZipFileSystemProvider extends FileSystemProvider { + + private final Map filesystems = new HashMap<>(); public ZipFileSystemProvider() {} @@ -101,10 +103,16 @@ throws IOException { synchronized(filesystems) { - if (filesystems.containsKey(path)) - throw new FileSystemAlreadyExistsException(); + Path realPath = null; + if (path.exists()) { + realPath = path.toRealPath(true); + if (filesystems.containsKey(realPath)) + throw new FileSystemAlreadyExistsException(); + } ZipFileSystem zipfs = new ZipFileSystem(this, path, env); - filesystems.put(path, zipfs); + if (realPath == null) + realPath = path.toRealPath(true); + filesystems.put(realPath, zipfs); return zipfs; } } @@ -137,16 +145,21 @@ @Override public FileSystem getFileSystem(URI uri) { synchronized (filesystems) { - ZipFileSystem zipfs = filesystems.get(uriToPath(uri)); + 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) { + void removeFileSystem(Path zfpath) throws IOException { synchronized (filesystems) { - filesystems.remove(zfpath); + filesystems.remove(zfpath.toRealPath(true)); } } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipInfo.java Mon Nov 22 10:18:33 2010 -0500 @@ -31,7 +31,6 @@ package com.sun.nio.zipfs; -import java.io.PrintStream; import java.nio.file.Paths; import java.util.Collections; import java.util.Iterator; @@ -41,7 +40,7 @@ import static com.sun.nio.zipfs.ZipUtils.*; /** - * Print the loc and cen tables of the ZIP file + * Print all loc and cen headers of the ZIP file * * @author Xueming Shen */ @@ -49,34 +48,38 @@ public class ZipInfo { public static void main(String[] args) throws Throwable { - if (args.length < 2) { - print("Usage: java ZipInfo [cen|loc] zfname"); + if (args.length < 1) { + print("Usage: java ZipInfo zfname"); } else { Map env = Collections.emptyMap(); ZipFileSystem zfs = (ZipFileSystem)(new ZipFileSystemProvider() - .newFileSystem(Paths.get(args[1]), env)); - - long pos = 0; + .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); - if ("loc".equals(args[0])) { - print("[Local File Header]%n"); - byte[] buf = new byte[1024]; - for (int i = 0; i < zfs.getEntryNames().length; i++) { - Entry loc = Entry.readLOC(zfs, pos, buf); - print("--------loc[%x]--------%n", pos); - printLOC(loc); - pos = loc.endPos; + // 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"); } - } if ("cen".equals(args[0])) { - int i = 0; - Iterator itr = zfs.inodes.values().iterator(); - print("[Central Directory Header]%n"); - while (itr.hasNext()) { - Entry cen = Entry.readCEN(zfs.cen, itr.next().pos); - print("--------cen[%d]--------%n", i); - printCEN(cen); - i++; - } + printLOC(buf); + pos += CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos); } zfs.close(); } @@ -86,47 +89,135 @@ System.out.printf(fmt, objs); } - static void printLOC(Entry loc) { - print(" [%x, %x]%n", loc.startPos, loc.endPos); - print(" Signature : %8x%n", LOCSIG); - print(" Version : %4x [%d.%d]%n", - loc.version, loc. version/10, loc. version%10); - print(" Flag : %4x%n", loc.flag); - print(" Method : %4x%n", loc. method); - print(" LastMTime : %8x [%tc]%n", - loc.mtime, dosToJavaTime(loc.mtime)); - print(" CRC : %8x%n", loc.crc); - print(" CSize : %8x%n", loc.csize); - print(" Size : %8x%n", loc.size); - print(" NameLength : %4x [%s]%n", - loc.nlen, new String(loc.name)); - print(" ExtraLength : %4x%n", loc.elen); - if (loc.hasZip64) - print(" *ZIP64*%n"); + 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 void printCEN(Entry cen) { - print(" Signature : %08x%n", CENSIG); - print(" VerMadeby : %4x [%d.%d]%n", - cen.versionMade, cen.versionMade/10, cen.versionMade%10); - print(" VerExtract : %4x [%d.%d]%n", - cen.version, cen.version/10, cen.version%10); - print(" Flag : %4x%n", cen.flag); - print(" Method : %4x%n", cen.method); - print(" LastMTime : %8x [%tc]%n", - cen.mtime, dosToJavaTime(cen.mtime)); - print(" CRC : %8x%n", cen.crc); - print(" CSize : %8x%n", cen.csize); - print(" Size : %8x%n", cen.size); - print(" NameLen : %4x [%s]%n", - cen.nlen, new String(cen.name)); - print(" ExtraLen : %4x%n", cen.elen); - print(" CommentLen : %4x%n", cen.clen); - print(" DiskStart : %4x%n", cen.disk); - print(" Attrs : %4x%n", cen.attrs); - print(" AttrsEx : %8x%n", cen.attrsEx); - print(" LocOff : %8x%n", cen.locoff); - if (cen.hasZip64) - print(" *ZIP64*%n"); + 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; + } } } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipPath.java Mon Nov 22 10:18:33 2010 -0500 @@ -32,24 +32,19 @@ package com.sun.nio.zipfs; import java.io.File; -import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; -import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SeekableByteChannel; import java.nio.file.*; import java.nio.file.DirectoryStream.Filter; -import java.nio.file.spi.FileSystemProvider; 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 java.util.regex.Matcher; -import java.util.regex.Pattern; import static java.nio.file.StandardOpenOption.*; import static java.nio.file.StandardCopyOption.*; @@ -599,7 +594,7 @@ } private static final DirectoryStream.Filter acceptAllFilter = - new DirectoryStream.Filter() { + new DirectoryStream.Filter<>() { @Override public boolean accept(Path entry) { return true; } }; @@ -625,7 +620,7 @@ // create a matcher and return a filter that uses it. final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob); - DirectoryStream.Filter filter = new DirectoryStream.Filter() { + DirectoryStream.Filter filter = new DirectoryStream.Filter<>() { @Override public boolean accept(Path entry) { return matcher.matches(entry.getName()); @@ -758,7 +753,7 @@ @Override public Iterator iterator() { - return new Iterator() { + return new Iterator<>() { private int i = 0; @Override @@ -803,7 +798,7 @@ @Override public SeekableByteChannel newByteChannel(OpenOption... options) throws IOException { - Set set = new HashSet(options.length); + Set set = new HashSet<>(options.length); Collections.addAll(set, options); return newByteChannel(set); } @@ -908,7 +903,7 @@ if (opt == REPLACE_EXISTING) replaceExisting = true; else if (opt == COPY_ATTRIBUTES) - copyAttrs = false; + copyAttrs = true; } // attributes of source file ZipFileAttributes zfas = getAttributes(); @@ -951,7 +946,9 @@ BasicFileAttributeView view = target.getFileAttributeView(BasicFileAttributeView.class); try { - view.setTimes(zfas.lastModifiedTime(), null, null); + view.setTimes(zfas.lastModifiedTime(), + zfas.lastAccessTime(), + zfas.creationTime()); } catch (IOException x) { // rollback? try { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java --- a/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/demo/nio/zipfs/com/sun/nio/zipfs/ZipUtils.java Mon Nov 22 10:18:33 2010 -0500 @@ -36,6 +36,7 @@ import java.util.Arrays; import java.util.Date; import java.util.regex.PatternSyntaxException; +import java.util.concurrent.TimeUnit; /** * @@ -48,7 +49,7 @@ * Writes a 16-bit short to the output stream in little-endian byte order. */ public static void writeShort(OutputStream os, int v) throws IOException { - os.write((v >>> 0) & 0xff); + os.write(v & 0xff); os.write((v >>> 8) & 0xff); } @@ -56,7 +57,7 @@ * Writes a 32-bit int to the output stream in little-endian byte order. */ public static void writeInt(OutputStream os, long v) throws IOException { - os.write((int)((v >>> 0) & 0xff)); + os.write((int)(v & 0xff)); os.write((int)((v >>> 8) & 0xff)); os.write((int)((v >>> 16) & 0xff)); os.write((int)((v >>> 24) & 0xff)); @@ -66,7 +67,7 @@ * Writes a 64-bit int to the output stream in little-endian byte order. */ public static void writeLong(OutputStream os, long v) throws IOException { - os.write((int)((v >>> 0) & 0xff)); + os.write((int)(v & 0xff)); os.write((int)((v >>> 8) & 0xff)); os.write((int)((v >>> 16) & 0xff)); os.write((int)((v >>> 24) & 0xff)); @@ -132,6 +133,27 @@ d.getSeconds() >> 1; } + + // used to adjust values between Windows and java epoch + private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; + public static final long winToJavaTime(long wtime) { + return TimeUnit.MILLISECONDS.convert( + wtime / 10 + WINDOWS_EPOCH_IN_MICROSECONDS, TimeUnit.MICROSECONDS); + } + + public static final long javaToWinTime(long time) { + return (TimeUnit.MICROSECONDS.convert(time, TimeUnit.MILLISECONDS) + - WINDOWS_EPOCH_IN_MICROSECONDS) * 10; + } + + public static final long unixToJavaTime(long utime) { + return TimeUnit.MILLISECONDS.convert(utime, TimeUnit.SECONDS); + } + + public static final long javaToUnixTime(long time) { + return TimeUnit.SECONDS.convert(time, TimeUnit.MILLISECONDS); + } + private static final String regexMetaChars = ".^$+{[]|()"; private static final String globMetaChars = "\\*?[{"; private static boolean isRegexMeta(char c) { diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/lib/security/sunpkcs11-solaris.cfg --- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg Mon Nov 22 10:18:33 2010 -0500 @@ -31,5 +31,9 @@ CKM_SHA256_RSA_PKCS CKM_SHA384_RSA_PKCS CKM_SHA512_RSA_PKCS +# the following mechanisms are disabled to ensure backward compatibility (Solaris bug 6545046) + CKM_DES_CBC_PAD + CKM_DES3_CBC_PAD + CKM_AES_CBC_PAD } diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/native/java/util/zip/zip_util.c --- a/jdk/src/share/native/java/util/zip/zip_util.c Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/native/java/util/zip/zip_util.c Mon Nov 22 10:18:33 2010 -0500 @@ -314,7 +314,7 @@ if (pos < 0) { /* Pretend there are some NUL bytes before start of file */ off = -pos; - memset(buf, '\0', off); + memset(buf, '\0', (size_t)off); } if (readFullyAt(zfd, buf + off, sizeof(buf) - off, @@ -426,7 +426,7 @@ isMetaName(const char *name, int length) { const char *s; - if (length < sizeof("META-INF/") - 1) + if (length < (int)sizeof("META-INF/") - 1) return 0; for (s = "META-INF/"; *s != '\0'; s++) { char c = *name++; @@ -912,7 +912,7 @@ ZFILE zfd = zip->zfd; char *cen; if (bufsize > zip->len - cenpos) - bufsize = zip->len - cenpos; + bufsize = (jint)(zip->len - cenpos); if ((cen = malloc(bufsize)) == NULL) goto Catch; if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch; censize = CENSIZE(cen); @@ -1256,6 +1256,9 @@ * file had been previously locked with ZIP_Lock(). Returns the * number of bytes read, or -1 if an error occurred. If zip->msg != 0 * then a zip error occurred and zip->msg contains the error text. + * + * The current implementation does not support reading an entry that + * has the size bigger than 2**32 bytes in ONE invocation. */ jint ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len) @@ -1276,7 +1279,7 @@ if (len <= 0) return 0; if (len > entry_size - pos) - len = entry_size - pos; + len = (jint)(entry_size - pos); /* Get file offset to start reading data */ start = ZIP_GetEntryDataOffset(zip, entry); @@ -1306,6 +1309,9 @@ * from ZIP/JAR files specified in the class path. It is defined here * so that it can be dynamically loaded by the runtime if the zip library * is found. + * + * The current implementation does not support reading an entry that + * has the size bigger than 2**32 bytes in ONE invocation. */ jboolean InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg) @@ -1314,7 +1320,6 @@ char tmp[BUF_SIZE]; jlong pos = 0; jlong count = entry->csize; - jboolean status; *msg = 0; /* Reset error message */ @@ -1330,10 +1335,10 @@ } strm.next_out = buf; - strm.avail_out = entry->size; + strm.avail_out = (uInt)entry->size; while (count > 0) { - jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : count; + jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count; ZIP_Lock(zip); n = ZIP_Read(zip, entry, pos, tmp, n); ZIP_Unlock(zip); @@ -1368,12 +1373,16 @@ return JNI_TRUE; } +/* + * The current implementation does not support reading an entry that + * has the size bigger than 2**32 bytes in ONE invocation. + */ jzentry * JNICALL ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP) { jzentry *entry = ZIP_GetEntry(zip, name, 0); if (entry) { - *sizeP = entry->size; + *sizeP = (jint)entry->size; *nameLenP = strlen(entry->name); } return entry; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/native/java/util/zip/zlib-1.2.3/compress.c --- a/jdk/src/share/native/java/util/zip/zlib-1.2.3/compress.c Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.3/compress.c Mon Nov 22 10:18:33 2010 -0500 @@ -75,7 +75,7 @@ deflateEnd(&stream); return err == Z_OK ? Z_BUF_ERROR : err; } - *destLen = stream.total_out; + *destLen = (uLong)stream.total_out; err = deflateEnd(&stream); return err; diff -r 9fefa2786251 -r ff70dc612d95 jdk/src/share/native/java/util/zip/zlib-1.2.3/uncompr.c --- a/jdk/src/share/native/java/util/zip/zlib-1.2.3/uncompr.c Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/src/share/native/java/util/zip/zlib-1.2.3/uncompr.c Mon Nov 22 10:18:33 2010 -0500 @@ -78,7 +78,7 @@ return Z_DATA_ERROR; return err; } - *destLen = stream.total_out; + *destLen = (uLong)stream.total_out; err = inflateEnd(&stream); return err; diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/ProblemList.txt Mon Nov 22 10:18:33 2010 -0500 @@ -734,10 +734,6 @@ # Problems on windows, jmap.exe hangs? (these run jmap), fails on Solaris 10 x86 java/util/concurrent/locks/Lock/TimedAcquireLeak.java generic-all -# Solaris sparc client, some failures, "1 not equal to 3"? -# also Linux problems with samevm mode, -server linux i586? 1 not equal to 3? -java/util/concurrent/Executors/AutoShutdown.java generic-all - # Fails on solaris-sparc -server (Set not equal to copy. 1) java/util/EnumSet/EnumSetBash.java solaris-sparc diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/com/sun/net/httpserver/Test.java --- a/jdk/test/com/sun/net/httpserver/Test.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/com/sun/net/httpserver/Test.java Mon Nov 22 10:18:33 2010 -0500 @@ -22,8 +22,20 @@ */ import com.sun.net.httpserver.*; +import java.util.logging.*; public class Test { + + static Logger logger; + + static void enableLogging() { + logger = Logger.getLogger("com.sun.net.httpserver"); + Handler h = new ConsoleHandler(); + h.setLevel(Level.ALL); + logger.setLevel(Level.ALL); + logger.addHandler(h); + } + static void delay () { try { Thread.sleep (1000); diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/com/sun/net/httpserver/Test1.java --- a/jdk/test/com/sun/net/httpserver/Test1.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/com/sun/net/httpserver/Test1.java Mon Nov 22 10:18:33 2010 -0500 @@ -25,6 +25,7 @@ * @test * @bug 6270015 * @run main/othervm Test1 + * @run main/othervm -Dsun.net.httpserver.maxReqTime=10 Test1 * @summary Light weight HTTP server */ diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/com/sun/net/httpserver/Test13.java --- a/jdk/test/com/sun/net/httpserver/Test13.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/com/sun/net/httpserver/Test13.java Mon Nov 22 10:18:33 2010 -0500 @@ -31,6 +31,7 @@ import com.sun.net.httpserver.*; import java.util.concurrent.*; +import java.util.logging.*; import java.io.*; import java.net.*; @@ -45,12 +46,19 @@ static SSLContext ctx; + final static int NUM = 32; // was 32 + static boolean fail = false; public static void main (String[] args) throws Exception { HttpServer s1 = null; HttpsServer s2 = null; ExecutorService executor=null; + Logger l = Logger.getLogger ("com.sun.net.httpserver"); + Handler ha = new ConsoleHandler(); + ha.setLevel(Level.ALL); + l.setLevel(Level.ALL); + l.addHandler(ha); try { String root = System.getProperty ("test.src")+ "/docs"; System.out.print ("Test13: "); @@ -70,10 +78,10 @@ int port = s1.getAddress().getPort(); int httpsport = s2.getAddress().getPort(); - Runner r[] = new Runner[64]; - for (int i=0; i<32; i++) { + Runner r[] = new Runner[NUM*2]; + for (int i=0; i()); - try { // prepare a src Path src = getTempPath(); @@ -146,13 +145,6 @@ Path fs2Path = getTempPath(); Path fs3Path = getTempPath(); - if (fs1Path.exists()) - fs1Path.delete(); - if (fs2Path.exists()) - fs2Path.delete(); - if (fs3Path.exists()) - fs3Path.delete(); - // create a new filesystem, copy everything from fs Map env = new HashMap(); env.put("createNew", true); @@ -280,7 +272,6 @@ walk(fs4.getPath("/")); System.out.println("closing: fs4"); fs4.close(); - System.out.printf("failed=%d%n", failed); fs1Path.delete(); @@ -426,6 +417,8 @@ } private static void mkdirs(Path path) throws IOException { + if (path.exists()) + return; path = path.toAbsolutePath(); Path parent = path.getParent(); if (parent != null) { diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/nio/Buffer/StringCharBufferSliceTest.java --- a/jdk/test/java/nio/Buffer/StringCharBufferSliceTest.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/java/nio/Buffer/StringCharBufferSliceTest.java Mon Nov 22 10:18:33 2010 -0500 @@ -22,7 +22,7 @@ */ /* @test - * @bug 4997655 + * @bug 4997655 7000913 * @summary (bf) CharBuffer.slice() on wrapped CharSequence results in wrong position */ @@ -76,11 +76,26 @@ } System.out.println( + ">>> StringCharBufferSliceTest-main: testing slice with result of slice"); + buff.position(0); + buff.limit(buff.capacity()); + slice = buff.slice(); + for (int i=0; i<4; i++) { + slice.position(i); + CharBuffer nextSlice = slice.slice(); + if (nextSlice.position() != 0) + throw new RuntimeException("New buffer's position should be zero"); + if (!nextSlice.equals(slice)) + throw new RuntimeException("New buffer should be equal"); + slice = nextSlice; + } + + System.out.println( ">>> StringCharBufferSliceTest-main: testing toString."); buff.position(4); buff.limit(7); slice = buff.slice(); - if (! slice.toString().equals("tes")) { + if (!slice.toString().equals("tes")) { throw new RuntimeException("bad toString() after slice(): " + slice.toString()); } @@ -104,6 +119,7 @@ || dupe.charAt(2) != 's' || dupe.charAt(3) != 't') { throw new RuntimeException("bad duplicate() after slice(): '" + dupe + "'"); } + System.out.println(">>> StringCharBufferSliceTest-main: done!"); } diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh Mon Nov 22 10:18:33 2010 -0500 @@ -68,11 +68,10 @@ ;; esac -# remove old class files cd ${TESTCLASSES}${FILESEP} -rm -f ClassLoaderDeadlock.class -rm -rf provider -mkdir provider +if [ ! -d provider ] ; then + mkdir provider +fi # compile the test program ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ @@ -88,4 +87,11 @@ -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \ ClassLoaderDeadlock -exit $? +STATUS=$? + +# clean up +rm -f 'ClassLoaderDeadlock.class' 'ClassLoaderDeadlock$1.class' \ +'ClassLoaderDeadlock$DelayClassLoader.class' \ +provider${FILESEP}HashProvider.class + +exit $STATUS diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock2.sh Mon Nov 22 10:18:33 2010 -0500 @@ -26,7 +26,6 @@ # @test # @bug 6440846 -# @ignore until 6203816 is dealt with. # @summary make sure we do not deadlock between ExtClassLoader and AppClassLoader # @author Valerie Peng # @run shell/timeout=20 Deadlock2.sh @@ -71,11 +70,14 @@ # remove old class files cd ${TESTCLASSES} -rm -f Deadlock2*.class if [ -d testlib ] ; then rm -rf testlib fi -cp -r ${TESTJAVA}${FILESEP}lib${FILESEP}ext testlib +if [ -d ${TESTJAVA}${FILESEP}lib${FILESEP}ext ] ; then + cp -r ${TESTJAVA}${FILESEP}lib${FILESEP}ext testlib +else + cp -r ${TESTJAVA}${FILESEP}jre${FILESEP}lib${FILESEP}ext testlib +fi # compile and package the test program ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/util/concurrent/Executors/AutoShutdown.java --- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java Mon Nov 22 10:18:33 2010 -0500 @@ -32,21 +32,40 @@ import java.util.*; import java.util.concurrent.*; import static java.util.concurrent.Executors.*; +import java.util.concurrent.Phaser; public class AutoShutdown { - private static void waitForFinalizersToRun() throws Throwable { - System.gc(); System.runFinalization(); Thread.sleep(10); - System.gc(); System.runFinalization(); Thread.sleep(10); + private static void waitForFinalizersToRun() { + for (int i = 0; i < 2; i++) + tryWaitForFinalizersToRun(); + } + + private static void tryWaitForFinalizersToRun() { + System.gc(); + final CountDownLatch fin = new CountDownLatch(1); + new Object() { protected void finalize() { fin.countDown(); }}; + System.gc(); + try { fin.await(); } + catch (InterruptedException ie) { throw new Error(ie); } } private static void realMain(String[] args) throws Throwable { - Runnable trivialRunnable = new Runnable() { public void run() {}}; + final Phaser phaser = new Phaser(3); + Runnable trivialRunnable = new Runnable() { + public void run() { + phaser.arriveAndAwaitAdvance(); + } + }; int count0 = Thread.activeCount(); - newSingleThreadExecutor().execute(trivialRunnable); - newSingleThreadExecutor(defaultThreadFactory()).execute(trivialRunnable); - Thread.sleep(100); + Executor e1 = newSingleThreadExecutor(); + Executor e2 = newSingleThreadExecutor(defaultThreadFactory()); + e1.execute(trivialRunnable); + e2.execute(trivialRunnable); + phaser.arriveAndAwaitAdvance(); equal(Thread.activeCount(), count0 + 2); - waitForFinalizersToRun(); + e1 = e2 = null; + for (int i = 0; i < 10 && Thread.activeCount() > count0; i++) + tryWaitForFinalizersToRun(); equal(Thread.activeCount(), count0); } diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/util/jar/JarInputStream/BadSignedJar.jar Binary file jdk/test/java/util/jar/JarInputStream/BadSignedJar.jar has changed diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/jar/JarInputStream/TestIndexedJarWithBadSignature.java Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,57 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6544278 + * @summary Confirm the JarInputStream throws the SecurityException when + * verifying an indexed jar file with corrupted signature + */ + +import java.io.IOException; +import java.io.FileInputStream; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; + +public class TestIndexedJarWithBadSignature { + + public static void main(String...args) throws Throwable { + try (JarInputStream jis = new JarInputStream( + new FileInputStream(System.getProperty("tst.src", ".") + + System.getProperty("file.separator") + + "BadSignedJar.jar"))) + { + JarEntry je1 = jis.getNextJarEntry(); + while(je1!=null){ + System.out.println("Jar Entry1==>"+je1.getName()); + je1 = jis.getNextJarEntry(); // This should throw Security Exception + } + throw new RuntimeException( + "Test Failed:Security Exception not being thrown"); + } catch (IOException ie){ + ie.printStackTrace(); + } catch (SecurityException e) { + System.out.println("Test passed: Security Exception thrown as expected"); + } + } +} diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/sun/nio/cs/CheckHistoricalNames.java --- a/jdk/test/sun/nio/cs/CheckHistoricalNames.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/sun/nio/cs/CheckHistoricalNames.java Mon Nov 22 10:18:33 2010 -0500 @@ -22,7 +22,7 @@ */ /* @test - @bug 4513767 4961027 + @bug 4513767 4961027 6217210 @summary Checks canonical names match between old and (NIO) core charsets */ import java.io.InputStreamReader; @@ -154,6 +154,7 @@ checkHistoricalName("Cp500"); checkHistoricalName("Cp737"); checkHistoricalName("Cp775"); + checkHistoricalName("Cp833"); checkHistoricalName("Cp838"); checkHistoricalName("Cp850"); checkHistoricalName("Cp852"); @@ -228,6 +229,7 @@ checkMappedName("IBM856", "Cp856"); checkMappedName("IBM857", "Cp857"); checkMappedName("IBM00858", "Cp858"); + checkMappedName("IBM833", "Cp833"); checkMappedName("IBM860", "Cp860"); checkMappedName("IBM861", "Cp861"); checkMappedName("IBM862", "Cp862"); diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/sun/security/krb5/UnknownCCEntry.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/UnknownCCEntry.java Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,219 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 6979329 + * @summary CCacheInputStream fails to read ticket cache files from Kerberos 1.8.1 + */ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileOutputStream; +import sun.security.krb5.internal.ccache.CCacheInputStream; +import sun.security.krb5.internal.ccache.CredentialsCache; + +public class UnknownCCEntry { + public static void main(String[] args) throws Exception { + // This is a ccache file generated on a test machine: + // Default principal: dummy@MAX.LOCAL + // Valid starting Expires Service principal + // 08/24/10 10:37:28 08/25/10 10:37:28 krbtgt/MAX.LOCAL@MAX.LOCAL + // Flags: FI, Etype (skey, tkt): AES-128 CTS mode with 96-bit SHA-1 + // HMAC, AES-256 CTS mode with 96-bit SHA-1 HMAC + byte[] krb5cc = { + (byte)0x05, (byte)0x04, (byte)0x00, (byte)0x0C, + (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x08, + (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFA, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x05, (byte)0x64, (byte)0x75, (byte)0x6D, + (byte)0x6D, (byte)0x79, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x09, (byte)0x4D, (byte)0x41, + (byte)0x58, (byte)0x2E, (byte)0x4C, (byte)0x4F, + (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x64, + (byte)0x75, (byte)0x6D, (byte)0x6D, (byte)0x79, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x06, (byte)0x6B, (byte)0x72, (byte)0x62, + (byte)0x74, (byte)0x67, (byte)0x74, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x09, (byte)0x4D, + (byte)0x41, (byte)0x58, (byte)0x2E, (byte)0x4C, + (byte)0x4F, (byte)0x43, (byte)0x41, (byte)0x4C, + (byte)0x00, (byte)0x11, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x10, (byte)0x92, (byte)0x1D, + (byte)0x1A, (byte)0x0C, (byte)0x7F, (byte)0xB8, + (byte)0x01, (byte)0x2E, (byte)0xC9, (byte)0xF5, + (byte)0x7B, (byte)0x92, (byte)0x81, (byte)0xCA, + (byte)0x49, (byte)0xC5, (byte)0x4C, (byte)0x73, + (byte)0x30, (byte)0x68, (byte)0x4C, (byte)0x73, + (byte)0x30, (byte)0x68, (byte)0x4C, (byte)0x74, + (byte)0x81, (byte)0xE8, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x40, + (byte)0x41, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x01, (byte)0x29, (byte)0x61, + (byte)0x82, (byte)0x01, (byte)0x25, (byte)0x30, + (byte)0x82, (byte)0x01, (byte)0x21, (byte)0xA0, + (byte)0x03, (byte)0x02, (byte)0x01, (byte)0x05, + (byte)0xA1, (byte)0x0B, (byte)0x1B, (byte)0x09, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0xA2, (byte)0x1E, (byte)0x30, + (byte)0x1C, (byte)0xA0, (byte)0x03, (byte)0x02, + (byte)0x01, (byte)0x00, (byte)0xA1, (byte)0x15, + (byte)0x30, (byte)0x13, (byte)0x1B, (byte)0x06, + (byte)0x6B, (byte)0x72, (byte)0x62, (byte)0x74, + (byte)0x67, (byte)0x74, (byte)0x1B, (byte)0x09, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0xA3, (byte)0x81, (byte)0xEC, + (byte)0x30, (byte)0x81, (byte)0xE9, (byte)0xA0, + (byte)0x03, (byte)0x02, (byte)0x01, (byte)0x12, + (byte)0xA1, (byte)0x03, (byte)0x02, (byte)0x01, + (byte)0x01, (byte)0xA2, (byte)0x81, (byte)0xDC, + (byte)0x04, (byte)0x81, (byte)0xD9, (byte)0xFB, + (byte)0x4B, (byte)0xD2, (byte)0x55, (byte)0x33, + (byte)0xA8, (byte)0x1A, (byte)0xE6, (byte)0xB5, + (byte)0x3D, (byte)0x67, (byte)0x46, (byte)0x69, + (byte)0x6F, (byte)0x0A, (byte)0x64, (byte)0xE7, + (byte)0x3D, (byte)0xEF, (byte)0x22, (byte)0xBE, + (byte)0x81, (byte)0x32, (byte)0xF3, (byte)0x72, + (byte)0xB4, (byte)0x50, (byte)0xE3, (byte)0xC3, + (byte)0xDB, (byte)0xE5, (byte)0x38, (byte)0x3C, + (byte)0x60, (byte)0xC8, (byte)0x08, (byte)0x53, + (byte)0x44, (byte)0x6F, (byte)0xDF, (byte)0x55, + (byte)0x67, (byte)0x32, (byte)0x02, (byte)0xDD, + (byte)0x6B, (byte)0xFB, (byte)0x23, (byte)0x1A, + (byte)0x88, (byte)0x71, (byte)0xE0, (byte)0xF8, + (byte)0xBB, (byte)0x51, (byte)0x1E, (byte)0x76, + (byte)0xC9, (byte)0x1F, (byte)0x45, (byte)0x9B, + (byte)0xA0, (byte)0xA5, (byte)0x61, (byte)0x45, + (byte)0x9E, (byte)0x65, (byte)0xB8, (byte)0xD6, + (byte)0x0E, (byte)0x3C, (byte)0xD9, (byte)0x56, + (byte)0xD6, (byte)0xA6, (byte)0xDD, (byte)0x36, + (byte)0x21, (byte)0x25, (byte)0x0E, (byte)0xE6, + (byte)0xAD, (byte)0xA0, (byte)0x3A, (byte)0x9B, + (byte)0x21, (byte)0x87, (byte)0xE2, (byte)0xAF, + (byte)0x3A, (byte)0xEF, (byte)0x75, (byte)0x85, + (byte)0xA8, (byte)0xD7, (byte)0xE5, (byte)0x46, + (byte)0xD8, (byte)0x5C, (byte)0x17, (byte)0x4E, + (byte)0x64, (byte)0x51, (byte)0xDB, (byte)0x38, + (byte)0x8E, (byte)0x6B, (byte)0x02, (byte)0x05, + (byte)0x46, (byte)0x77, (byte)0xD0, (byte)0x75, + (byte)0x8A, (byte)0xE0, (byte)0x42, (byte)0x5E, + (byte)0x8D, (byte)0x49, (byte)0x86, (byte)0xDE, + (byte)0x6C, (byte)0xBC, (byte)0xAF, (byte)0x10, + (byte)0x9A, (byte)0x97, (byte)0x64, (byte)0xA6, + (byte)0xBD, (byte)0xDB, (byte)0x01, (byte)0x40, + (byte)0xA9, (byte)0x3D, (byte)0x74, (byte)0x99, + (byte)0xDC, (byte)0x63, (byte)0x34, (byte)0x40, + (byte)0x31, (byte)0x57, (byte)0xC7, (byte)0x70, + (byte)0x9F, (byte)0xCE, (byte)0xC6, (byte)0x7B, + (byte)0x00, (byte)0x5B, (byte)0x02, (byte)0x5C, + (byte)0xC7, (byte)0x81, (byte)0x40, (byte)0x4D, + (byte)0xA7, (byte)0xB1, (byte)0xD2, (byte)0xEA, + (byte)0x8E, (byte)0xEC, (byte)0xA0, (byte)0xB3, + (byte)0x03, (byte)0x29, (byte)0xB8, (byte)0x44, + (byte)0xD7, (byte)0xA1, (byte)0x2B, (byte)0x37, + (byte)0x9D, (byte)0x19, (byte)0x11, (byte)0x1D, + (byte)0x58, (byte)0xE8, (byte)0x06, (byte)0xE7, + (byte)0x06, (byte)0xE3, (byte)0xF7, (byte)0xEF, + (byte)0x05, (byte)0xA9, (byte)0x05, (byte)0x93, + (byte)0x42, (byte)0x94, (byte)0x5A, (byte)0xD6, + (byte)0xA0, (byte)0x24, (byte)0x3A, (byte)0x52, + (byte)0x92, (byte)0xA3, (byte)0x79, (byte)0x98, + (byte)0x3C, (byte)0x68, (byte)0x55, (byte)0x1B, + (byte)0x6A, (byte)0xC5, (byte)0x83, (byte)0x89, + (byte)0x5A, (byte)0x79, (byte)0x5C, (byte)0x52, + (byte)0xBA, (byte)0xB8, (byte)0xF7, (byte)0x72, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x05, (byte)0x64, (byte)0x75, (byte)0x6D, + (byte)0x6D, (byte)0x79, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x0C, (byte)0x58, (byte)0x2D, + (byte)0x43, (byte)0x41, (byte)0x43, (byte)0x48, + (byte)0x45, (byte)0x43, (byte)0x4F, (byte)0x4E, + (byte)0x46, (byte)0x3A, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x15, (byte)0x6B, (byte)0x72, + (byte)0x62, (byte)0x35, (byte)0x5F, (byte)0x63, + (byte)0x63, (byte)0x61, (byte)0x63, (byte)0x68, + (byte)0x65, (byte)0x5F, (byte)0x63, (byte)0x6F, + (byte)0x6E, (byte)0x66, (byte)0x5F, (byte)0x64, + (byte)0x61, (byte)0x74, (byte)0x61, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x0A, (byte)0x66, + (byte)0x61, (byte)0x73, (byte)0x74, (byte)0x5F, + (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x69, + (byte)0x6C, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x1A, (byte)0x6B, (byte)0x72, (byte)0x62, + (byte)0x74, (byte)0x67, (byte)0x74, (byte)0x2F, + (byte)0x4D, (byte)0x41, (byte)0x58, (byte)0x2E, + (byte)0x4C, (byte)0x4F, (byte)0x43, (byte)0x41, + (byte)0x4C, (byte)0x40, (byte)0x4D, (byte)0x41, + (byte)0x58, (byte)0x2E, (byte)0x4C, (byte)0x4F, + (byte)0x43, (byte)0x41, (byte)0x4C, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, (byte)0x03, (byte)0x79, (byte)0x65, + (byte)0x73, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x00, + }; + + File f = File.createTempFile("ccache", "cc", new File(".")); + FileOutputStream fout = new FileOutputStream(f); + fout.write(krb5cc); + fout.close(); + + CredentialsCache cc = CredentialsCache.getInstance(f.getPath()); + if (!cc.getDefaultCreds().getServicePrincipal().getNameStrings()[0] + .equals("krbtgt")) { + throw new Exception("No TGT found"); + } + } +} diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java Mon Nov 22 10:18:33 2010 -0500 @@ -0,0 +1,132 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6687725 + * @summary Test internal PKCS5Padding impl with various error conditions. + * @author Valerie Peng + * @library .. + */ +import java.io.*; +import java.nio.*; +import java.util.*; + +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; + +public class TestPKCS5PaddingError extends PKCS11Test { + private static class CI { // class for holding Cipher Information + String transformation; + String keyAlgo; + + CI(String transformation, String keyAlgo) { + this.transformation = transformation; + this.keyAlgo = keyAlgo; + } + } + + private static final CI[] TEST_LIST = { + // algorithms which use the native padding impl + new CI("DES/CBC/PKCS5Padding", "DES"), + new CI("DESede/CBC/PKCS5Padding", "DESede"), + new CI("AES/CBC/PKCS5Padding", "AES"), + // algorithms which use SunPKCS11's own padding impl + new CI("DES/ECB/PKCS5Padding", "DES"), + new CI("DESede/ECB/PKCS5Padding", "DESede"), + new CI("AES/ECB/PKCS5Padding", "AES"), + }; + + private static StringBuffer debugBuf = new StringBuffer(); + + public void main(Provider p) throws Exception { + boolean status = true; + Random random = new Random(); + + try { + byte[] plainText = new byte[200]; + + for (int i = 0; i < TEST_LIST.length; i++) { + CI currTest = TEST_LIST[i]; + System.out.println("===" + currTest.transformation + "==="); + try { + KeyGenerator kg = + KeyGenerator.getInstance(currTest.keyAlgo, p); + SecretKey key = kg.generateKey(); + Cipher c1 = Cipher.getInstance(currTest.transformation, + "SunJCE"); + c1.init(Cipher.ENCRYPT_MODE, key); + byte[] cipherText = c1.doFinal(plainText); + AlgorithmParameters params = c1.getParameters(); + Cipher c2 = Cipher.getInstance(currTest.transformation, p); + c2.init(Cipher.DECRYPT_MODE, key, params); + + // 1st test: wrong output length + // NOTE: Skip NSS since it reports CKR_DEVICE_ERROR when + // the data passed to its EncryptUpdate/DecryptUpdate is + // not multiple of blocks + if (!p.getName().equals("SunPKCS11-NSS")) { + try { + System.out.println("Testing with wrong cipherText length"); + c2.doFinal(cipherText, 0, cipherText.length - 2); + } catch (IllegalBlockSizeException ibe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + } + // 2nd test: wrong padding value + try { + System.out.println("Testing with wrong padding bytes"); + cipherText[cipherText.length - 1]++; + c2.doFinal(cipherText); + } catch (BadPaddingException bpe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + System.out.println("DONE"); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping unsupported algorithm: " + + nsae); + } + } + } catch (Exception ex) { + // print out debug info when exception is encountered + if (debugBuf != null) { + System.out.println(debugBuf.toString()); + debugBuf = new StringBuffer(); + } + throw ex; + } + } + + public static void main(String[] args) throws Exception { + main(new TestPKCS5PaddingError()); + } +} diff -r 9fefa2786251 -r ff70dc612d95 jdk/test/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java --- a/jdk/test/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java Mon Nov 22 10:16:07 2010 -0500 +++ b/jdk/test/sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java Mon Nov 22 10:18:33 2010 -0500 @@ -23,7 +23,7 @@ /** * @test - * @bug 4917233 6461727 6490213 + * @bug 4917233 6461727 6490213 6720456 * @summary test the KeyGenerator * @author Andreas Sterbenz * @library .. @@ -104,7 +104,7 @@ // Different PKCS11 impls have different ranges // of supported key sizes for variable-key-length // algorithms. - // Solaris> Blowfish: 32-128 bits, RC4: 8-128 bits + // Solaris> Blowfish: 32-128 or even 448 bits, RC4: 8-128 bits or as much as 2048 bits // NSS> Blowfish: n/a, RC4: 8-2048 bits // However, we explicitly disallowed key sizes less // than 40-bits. @@ -114,8 +114,8 @@ test("Blowfish", 32, p, TestResult.FAIL); test("Blowfish", 40, p, TestResult.PASS); test("Blowfish", 128, p, TestResult.PASS); - test("Blowfish", 136, p, TestResult.FAIL); - test("Blowfish", 448, p, TestResult.FAIL); + test("Blowfish", 136, p, TestResult.TBD); + test("Blowfish", 448, p, TestResult.TBD); test("Blowfish", 456, p, TestResult.FAIL); test("ARCFOUR", 0, p, TestResult.FAIL); @@ -124,7 +124,7 @@ test("ARCFOUR", 128, p, TestResult.PASS); if (p.getName().equals("SunPKCS11-Solaris")) { - test("ARCFOUR", 1024, p, TestResult.FAIL); + test("ARCFOUR", 1024, p, TestResult.TBD); } else if (p.getName().equals("SunPKCS11-NSS")) { test("ARCFOUR", 1024, p, TestResult.PASS); test("ARCFOUR", 2048, p, TestResult.PASS);