Merge
authormullan
Mon, 22 Nov 2010 10:18:33 -0500
changeset 7292 ff70dc612d95
parent 7291 9fefa2786251 (current diff)
parent 7288 a38f3099e518 (diff)
child 7293 e70d5e55fd1d
Merge
jdk/src/share/classes/sun/net/httpserver/SelectorCache.java
--- 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)
--- 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 \
--- /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
--- /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
--- 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
--- 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
 }
--- 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
--- 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
--- 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:
--- 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;
     }
 
     /**
--- 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;
     }
 
     /**
--- 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 <tt>char</tt> 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;
 
--- 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,
--- 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}</td>
  *   <td>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.</td>
+ *   object to be used by the {@code SyncProvider} implementation.</td>
  * </tr>
  *
  * <tr>
--- 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.
  *
  * <tr><td valign="top">{@code 'Z'}
+ *     <td valign="top"> <tt>'&#92;u005a'</tt>
  *     <td> 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
--- 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 <code>JarInputStream</code> 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 <code>JarInputStream</code> 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) {
--- /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();
+    }
+}
+
--- /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();
+    }
+}
+
--- 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");
--- 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;
--- 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;
     }
 }
--- 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;
--- 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;
     }
--- 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,
--- 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;
         }
     }
--- 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");
                         }
--- 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<SelectorWrapper>();
-        CacheCleaner c = AccessController.doPrivileged(
-            new PrivilegedAction<CacheCleaner>() {
-            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<SelectorWrapper> 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<SelectorWrapper> 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);
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
--- 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<Void>() {
+                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;
+    }
 }
--- 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<HttpConnection> idleConnections;
     private Set<HttpConnection> 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<HttpConnection> reqConnections;
+    private Set<HttpConnection> rspConnections;
     private List<Event> 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<HttpConnection>());
         allConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
+        reqConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
+        rspConnections = Collections.synchronizedSet (new HashSet<HttpConnection>());
         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<Event>();
         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<HttpConnection> connsToRegister =
+                new LinkedList<HttpConnection>();
+
+        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<HttpConnection> li =
+                        connsToRegister.listIterator();
+                    for (HttpConnection c : connsToRegister) {
+                        reRegister(c);
+                    }
+                    connsToRegister.clear();
 
-                    while (resultSize() > 0) {
-                        Event r;
-                        synchronized (lolock) {
-                            r = events.remove(0);
+                    List<Event> list = null;
+                    selector.select(1000);
+                    synchronized (lolock) {
+                        if (events.size() > 0) {
+                            list = events;
+                            events = new LinkedList<Event>();
+                        }
+                    }
+
+                    if (list != null) {
+                        for (Event r: list) {
                             handleEvent (r);
                         }
                     }
 
-                    selector.select(1000);
-
                     /* process the selected list now  */
 
                     Set<SelectionKey> 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, "<h1>"+code+Code.msg(code)+"</h1>"+message
+                code, false, "<h1>"+code+Code.msg(code)+"</h1>"+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) + "<TRUNCATED>";
+        } 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<HttpConnection> toClose = new LinkedList<HttpConnection>();
+            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<HttpConnection>();
+            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<e.length; i++) {
+            b.append (e[i].toString()).append("\n");
+        }
+        logger.finest (b.toString());
+    }
+
+    static long getTimeMillis(long secs) {
+        if (secs == -1) {
+            return -1;
+        } else {
+            return secs * 1000;
+        }
+    }
 }
--- a/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Mon Nov 22 10:16:07 2010 -0500
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java	Mon Nov 22 10:18:33 2010 -0500
@@ -358,7 +358,7 @@
     private static class Encoder extends CharsetEncoder {
 
         private Encoder(Charset cs) {
-            super(cs, 1.1f, 4.0f);
+            super(cs, 1.1f, 3.0f);
         }
 
         public boolean canEncode(char c) {
--- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Mon Nov 22 10:16:07 2010 -0500
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Mon Nov 22 10:18:33 2010 -0500
@@ -778,6 +778,13 @@
                     "csIBM500"
                 });
 
+        charset("x-IBM833", "IBM833",
+                new String[] {
+                     "cp833",
+                     "ibm833",
+                     "ibm-833"
+                 });
+
         //EBCDIC DBCS-only Korean
         charset("x-IBM834", "IBM834",
                 new String[] {
--- a/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Mon Nov 22 10:16:07 2010 -0500
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java	Mon Nov 22 10:18:33 2010 -0500
@@ -250,16 +250,16 @@
         else return null;
     }
 
-    Ticket readData() throws IOException, RealmException, KrbApErrException, Asn1Exception {
+    byte[] readData() throws IOException {
         int length;
         length = read(4);
-        if (length > 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 <CCacheInputStream>");
-            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;
     }
 }
--- 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<Credentials> ();
         while (cis.available() > 0) {
-            credentialsList.addElement(cis.readCred(version));
+            Credentials cred = cis.readCred(version);
+            if (cred != null) {
+                credentialsList.addElement(cred);
+            }
         }
         cis.close();
     }
--- 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) {
--- 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).
  *
--- 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).
  *
--- 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).
  *
--- 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,    // <java Demo copyin_attrs zipfile src dst>
+                         // copy an external src file into zipfile
+                         // as entry dst, with attributes (timestamp)
+
         copyout,         // <java Demo copyout zipfile src dst>
                          // copy zipfile entry src" out to file dst
 
+        copyout_attrs,   // <java Demo copyout_attrs zipfile src dst>
+
         zzmove,          // <java Demo zzmove zfsrc zfdst path>
                          // move entry path/dir from zfsrc to zfdst
 
@@ -94,6 +100,9 @@
         setmtime,        // <java Demo setmtime zipfile "MM/dd/yy-HH:mm:ss" path...>
                          // set the lastModifiedTime of entry path
 
+        setatime,        // <java Demo setatime zipfile "MM/dd/yy-HH:mm:ss" path...>
+        setctime,        // <java Demo setctime zipfile "MM/dd/yy-HH:mm:ss" path...>
+
         lsdir,           // <java Demo lsdir zipfile dir>
                          // list dir's direct child files/dirs
 
@@ -135,12 +144,14 @@
 
         attrs2,          // <java Demo attrs2 zipfile file [...]>
                          // test different ways to print attrs
+
+        prof,
     }
 
     public static void main(String[] args) throws Throwable {
 
-        Action action = Action.valueOf(args[0]);;
-        Map<String, Object> env = env = new HashMap<String, Object>();
+        Action action = Action.valueOf(args[0]);
+        Map<String, Object> 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()) {
--- 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 <JDK_HOME>/demo/nio/ZipFileSystem/zipfs.jar
+directory or else add <JDK_HOME>/demo/nio/zipfs/zipfs.jar
 to your class path.
 
 The factory methods defined by the java.nio.file.FileSystems class can be
@@ -10,8 +10,8 @@
 
    // use file type detection
    Map<String,?> 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
 
--- 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");
+    }
 }
--- 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;
--- 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<Path>() {
+        return new Iterator<>() {
             private Path next;
             @Override
             public boolean hasNext() {
--- 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 +
--- 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
--- 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<FileStore> getFileStores() {
-        ArrayList<FileStore> list = new ArrayList<FileStore>(1);
+        ArrayList<FileStore> 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<InputStream> 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<IndexNode> 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<? super Path> 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<Path> list = new ArrayList<Path>();
+                List<Path> 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<Path> list = new ArrayList<Path>();
-            EntryName[] entries = getEntryNames();
+            List<Path> 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<ExChannelCloser> exChClosers = new HashSet<>();
 
-    private Set<Path> tmppaths = new HashSet<>();
+    private Set<Path> tmppaths = Collections.synchronizedSet(new HashSet<Path>());
     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<EntryName, IndexNode> 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<IndexNode, IndexNode> 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<EntryName, IndexNode>(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<EntryName, IndexNode>(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<Entry> 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<EntryName, IndexNode> entry : inodes.entrySet()) {
+        for (Map.Entry<IndexNode, IndexNode> 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<Inflater> inflaters = new ArrayList<>();
+    private final List<Inflater> 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<Deflater> deflaters = new ArrayList<>();
+    private final List<Deflater> 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<EntryName, IndexNode> dirs;
+    private HashMap<IndexNode, IndexNode> 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<EntryName, IndexNode> getDirs()
+    private HashMap<IndexNode, IndexNode> 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<EntryName, IndexNode>();
-        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;
     }
 }
--- 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<Path, ZipFileSystem> 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));
         }
     }
 }
--- 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<String, ?> 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<ZipFileSystem.IndexNode> 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;
+        }
     }
 }
--- 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<Path> acceptAllFilter =
-        new DirectoryStream.Filter<Path>() {
+        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<Path> filter = new DirectoryStream.Filter<Path>() {
+        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<>() {
             @Override
             public boolean accept(Path entry)  {
                 return matcher.matches(entry.getName());
@@ -758,7 +753,7 @@
 
     @Override
     public Iterator<Path> iterator() {
-        return new Iterator<Path>() {
+        return new Iterator<>() {
             private int i = 0;
 
             @Override
@@ -803,7 +798,7 @@
     @Override
     public SeekableByteChannel newByteChannel(OpenOption... options)
             throws IOException {
-        Set<OpenOption> set = new HashSet<OpenOption>(options.length);
+        Set<OpenOption> 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 {
--- 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) {
--- 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
 }
 
--- 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;
--- 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;
--- 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;
--- 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
 
--- 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);
--- 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
  */
 
--- 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<NUM; i++) {
                 r[i] = new Runner (true, "http", root+"/test1", port, "smallfile.txt", 23);
-                r[i+32] = new Runner (true, "https", root+"/test1", port, "smallfile.txt", 23);
+                r[i+NUM] = new Runner (true, "https", root+"/test1", httpsport, "smallfile.txt", 23);
             }
             start (r);
             join (r);
@@ -91,6 +99,7 @@
 
     static void start (Runner[] x) {
         for (int i=0; i<x.length; i++) {
+            if (x[i] != null)
             x[i].start();
         }
     }
@@ -98,6 +107,7 @@
     static void join (Runner[] x) {
         for (int i=0; i<x.length; i++) {
             try {
+                if (x[i] != null)
                 x[i].join();
             } catch (InterruptedException e) {}
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/net/httpserver/bugs/6725892/Test.java	Mon Nov 22 10:18:33 2010 -0500
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2005, 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.
+ *
+ * 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 6725892
+ * @run main/othervm -Dsun.net.httpserver.maxReqTime=2 Test
+ * @summary
+ */
+
+import com.sun.net.httpserver.*;
+
+import java.util.concurrent.*;
+import java.util.logging.*;
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+
+public class Test {
+
+    static HttpServer s1;
+    static int port;
+    static URL url;
+    static final String RESPONSE_BODY = "response";
+    static boolean failed = false;
+
+    static class Handler implements HttpHandler {
+
+        public void handle (HttpExchange t)
+            throws IOException
+        {
+            InputStream is = t.getRequestBody();
+            InetSocketAddress rem = t.getRemoteAddress();
+            System.out.println ("Request from: " + rem);
+            while (is.read () != -1) ;
+            is.close();
+            String requrl = t.getRequestURI().toString();
+            OutputStream os = t.getResponseBody();
+            t.sendResponseHeaders (200, RESPONSE_BODY.length());
+            os.write (RESPONSE_BODY.getBytes());
+            t.close();
+        }
+    }
+
+    public static void main (String[] args) throws Exception {
+
+        ExecutorService exec = Executors.newCachedThreadPool();
+
+        try {
+            InetSocketAddress addr = new InetSocketAddress (0);
+            s1 = HttpServer.create (addr, 0);
+            HttpHandler h = new Handler ();
+            HttpContext c1 = s1.createContext ("/", h);
+            s1.setExecutor(exec);
+            s1.start();
+
+            port = s1.getAddress().getPort();
+            System.out.println ("Server on port " + port);
+            url = new URL ("http://127.0.0.1:"+port+"/foo");
+            test1();
+            test2();
+            test3();
+            Thread.sleep (2000);
+        } catch (Exception e) {
+            e.printStackTrace();
+            System.out.println ("FAIL");
+            throw new RuntimeException ();
+        } finally {
+            s1.stop(0);
+            System.out.println ("After Shutdown");
+            exec.shutdown();
+        }
+    }
+
+    // open TCP connection without sending anything. Check server closes it.
+
+    static void test1() throws IOException {
+        failed = false;
+        Socket s = new Socket ("127.0.0.1", port);
+        InputStream is = s.getInputStream();
+        // server should close connection after 2 seconds. We wait up to 10
+        s.setSoTimeout (10000);
+        try {
+            is.read();
+        } catch (SocketTimeoutException e) {
+            failed = true;
+        }
+        s.close();
+        if (failed) {
+            System.out.println ("test1: FAIL");
+            throw new RuntimeException ();
+        } else {
+            System.out.println ("test1: OK");
+        }
+    }
+
+    // send request and don't read response. Check server closes connection
+
+    static void test2() throws IOException {
+        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
+        urlc.setReadTimeout (20 * 1000);
+        InputStream is = urlc.getInputStream();
+        // we won't read response and check if it times out
+        // on server. If it timesout at client then there is a problem
+        try {
+            Thread.sleep (10 * 1000);
+            while (is.read() != -1) ;
+        } catch (InterruptedException e) {
+            System.out.println (e);
+            System.out.println ("test2: FAIL");
+            throw new RuntimeException ("unexpected error");
+        } catch (SocketTimeoutException e1) {
+            System.out.println (e1);
+            System.out.println ("test2: FAIL");
+            throw new RuntimeException ("client timedout");
+        } finally {
+            is.close();
+        }
+        System.out.println ("test2: OK");
+    }
+
+    // same as test2, but repeated with multiple connections
+    // including a number of valid request/responses
+
+    // Worker: a thread opens a connection to the server in one of three modes.
+    // NORMAL - sends a request, waits for response, and checks valid response
+    // REQUEST - sends a partial request, and blocks, to see if
+    //                  server closes the connection.
+    // RESPONSE - sends a request, partially reads response and blocks,
+    //                  to see if server closes the connection.
+
+    static class Worker extends Thread {
+        CountDownLatch latch;
+        Mode mode;
+
+        enum Mode {
+            REQUEST,    // block during sending of request
+            RESPONSE,   // block during reading of response
+            NORMAL      // don't block
+        };
+
+        Worker (CountDownLatch latch, Mode mode) {
+            this.latch = latch;
+            this.mode = mode;
+        }
+
+        void fail(String msg) {
+            System.out.println (msg);
+            failed = true;
+        }
+
+        public void run () {
+            HttpURLConnection urlc;
+            InputStream is = null;
+
+            try {
+                urlc = (HttpURLConnection) url.openConnection();
+                urlc.setReadTimeout (20 * 1000);
+                urlc.setDoOutput(true);
+            } catch (IOException e) {
+                fail("Worker: failed to connect to server");
+                latch.countDown();
+                return;
+            }
+            try {
+                OutputStream os = urlc.getOutputStream();
+                os.write ("foo".getBytes());
+                if (mode == Mode.REQUEST) {
+                    Thread.sleep (3000);
+                }
+                os.close();
+                is = urlc.getInputStream();
+                if (mode == Mode.RESPONSE) {
+                    Thread.sleep (3000);
+                }
+                if (!checkResponse (is, RESPONSE_BODY)) {
+                    fail ("Worker: response");
+                }
+                is.close();
+                return;
+            } catch (InterruptedException e0) {
+                fail("Worker: timedout");
+            } catch (SocketTimeoutException e1) {
+                fail("Worker: timedout");
+            } catch (IOException e2) {
+                switch (mode) {
+                  case NORMAL:
+                    fail ("Worker: " + e2.getMessage());
+                    break;
+                  case RESPONSE:
+                    if (is == null) {
+                        fail ("Worker: " + e2.getMessage());
+                        break;
+                    }
+                  // default: is ok
+                }
+            } finally {
+                latch.countDown();
+            }
+        }
+    }
+
+    static final int NUM = 20;
+
+    static void test3() throws Exception {
+        failed = false;
+        CountDownLatch l = new CountDownLatch (NUM*3);
+        Worker[] workers = new Worker[NUM*3];
+        for (int i=0; i<NUM; i++) {
+            workers[i*3] = new Worker (l, Worker.Mode.NORMAL);
+            workers[i*3+1] = new Worker (l, Worker.Mode.REQUEST);
+            workers[i*3+2] = new Worker (l, Worker.Mode.RESPONSE);
+            workers[i*3].start();
+            workers[i*3+1].start();
+            workers[i*3+2].start();
+        }
+        l.await();
+        for (int i=0; i<NUM*3; i++) {
+            workers[i].join();
+        }
+        if (failed) {
+            throw new RuntimeException ("test3: failed");
+        }
+        System.out.println ("test3: OK");
+    }
+
+    static boolean checkResponse (InputStream is, String resp) {
+        try {
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            byte[] buf = new byte [64];
+            int c;
+            while ((c=is.read(buf)) != -1) {
+                bos.write (buf, 0, c);
+            }
+            bos.close();
+            if (!bos.toString().equals(resp)) {
+                System.out.println ("Wrong response: " + bos.toString());
+                return false;
+            }
+        } catch (IOException e) {
+            System.out.println (e);
+            return false;
+        }
+        return true;
+    }
+}
--- a/jdk/test/com/sun/net/httpserver/bugs/B6401598.java	Mon Nov 22 10:16:07 2010 -0500
+++ b/jdk/test/com/sun/net/httpserver/bugs/B6401598.java	Mon Nov 22 10:18:33 2010 -0500
@@ -83,7 +83,7 @@
                         server = HttpServer.create(new InetSocketAddress(0), 400);
                         server.createContext("/server/", new MyHandler());
                         exec = Executors.newFixedThreadPool(3);
-                        server.setExecutor(null);
+                        server.setExecutor(exec);
                         port = server.getAddress().getPort();
                         server.start();
 
--- a/jdk/test/demo/zipfs/ZipFSTester.java	Mon Nov 22 10:16:07 2010 -0500
+++ b/jdk/test/demo/zipfs/ZipFSTester.java	Mon Nov 22 10:18:33 2010 -0500
@@ -64,7 +64,6 @@
         fs0.close();                // sync to file
 
         fs = newZipFileSystem(tmpfsPath, new HashMap<String, Object>());
-
         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<String, Object> env = new HashMap<String, Object>();
         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) {
--- 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!");
     }
 
--- 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
--- 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 \
--- 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);
     }
 
Binary file jdk/test/java/util/jar/JarInputStream/BadSignedJar.jar has changed
--- /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");
+        }
+    }
+}
--- 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");
--- /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");
+        }
+    }
+}
--- /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());
+    }
+}
--- 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);