Merge
authortbell
Fri, 05 Dec 2008 09:51:13 -0800
changeset 1638 f5d84a55742b
parent 1637 bfa39b25f0fc (diff)
parent 1625 dec82d3745bc (current diff)
child 1639 a97859015238
child 1696 aef312419918
child 1742 e0cbca71b3dd
Merge
--- a/jdk/make/common/shared/Sanity.gmk	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/make/common/shared/Sanity.gmk	Fri Dec 05 09:51:13 2008 -0800
@@ -1350,10 +1350,11 @@
 $(ALSA_VERSION_CHECK).c:
 	@$(prep-target)
 	@$(ECHO) "#include <alsa/asoundlib.h>\n" \
-                  "int main(char** argv, int argc) {\n" \
-                   "  printf(\"%s\", SND_LIB_VERSION_STR);\n" \
-                    "  return 0;\n" \
-                    "}\n" \
+		 "#include <stdio.h>\n" \
+		 "int main(int argc, char** argv) {\n" \
+		 "  printf(\"%s\", SND_LIB_VERSION_STR);\n" \
+		 "  return 0;\n" \
+		 "}\n" \
                     > $@
 endif
 
--- a/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java	Fri Dec 05 09:51:13 2008 -0800
@@ -70,6 +70,7 @@
 import javax.management.ListenerNotFoundException;
 import javax.management.MBeanException;
 import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanPermission;
 import javax.management.MBeanRegistration;
 import javax.management.MBeanRegistrationException;
@@ -1045,8 +1046,10 @@
             Object resource = getResource(mbean);
             MBeanInjector.inject(resource, mbs, name);
             if (MBeanInjector.injectsSendNotification(resource)) {
+                MBeanNotificationInfo[] mbnis =
+                        mbean.getMBeanInfo().getNotifications();
                 NotificationBroadcasterSupport nbs =
-                        new NotificationBroadcasterSupport();
+                        new NotificationBroadcasterSupport(mbnis);
                 MBeanInjector.injectSendNotification(resource, nbs);
                 mbean = NotifySupport.wrap(mbean, nbs);
             }
--- a/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java	Fri Dec 05 09:51:13 2008 -0800
@@ -44,6 +44,7 @@
 import javax.management.ImmutableDescriptor;
 import javax.management.IntrospectionException;
 import javax.management.InvalidAttributeValueException;
+import javax.management.JMX;
 import javax.management.MBean;
 import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanConstructorInfo;
@@ -79,7 +80,7 @@
  * ancestor with ConvertingMethod.  But that would mean an extra object
  * for every Method in every Standard MBean interface.
  */
-abstract class MBeanIntrospector<M> {
+public abstract class MBeanIntrospector<M> {
     static final class PerInterfaceMap<M>
             extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {}
 
@@ -538,24 +539,25 @@
     }
 
     static MBeanNotificationInfo[] findNotifications(Object moi) {
-        if (!(moi instanceof NotificationBroadcaster))
-            return null;
-        MBeanNotificationInfo[] mbn =
-                ((NotificationBroadcaster) moi).getNotificationInfo();
-        if (mbn == null || mbn.length == 0)
-            return findNotificationsFromAnnotations(moi.getClass());
-        MBeanNotificationInfo[] result =
-                new MBeanNotificationInfo[mbn.length];
-        for (int i = 0; i < mbn.length; i++) {
-            MBeanNotificationInfo ni = mbn[i];
-            if (ni.getClass() != MBeanNotificationInfo.class)
-                ni = (MBeanNotificationInfo) ni.clone();
-            result[i] = ni;
+        if (moi instanceof NotificationBroadcaster) {
+            MBeanNotificationInfo[] mbn =
+                    ((NotificationBroadcaster) moi).getNotificationInfo();
+            if (mbn != null && mbn.length > 0) {
+                MBeanNotificationInfo[] result =
+                        new MBeanNotificationInfo[mbn.length];
+                for (int i = 0; i < mbn.length; i++) {
+                    MBeanNotificationInfo ni = mbn[i];
+                    if (ni.getClass() != MBeanNotificationInfo.class)
+                        ni = (MBeanNotificationInfo) ni.clone();
+                    result[i] = ni;
+                }
+                return result;
+            }
         }
-        return result;
+        return findNotificationsFromAnnotations(moi.getClass());
     }
 
-    private static MBeanNotificationInfo[] findNotificationsFromAnnotations(
+    public static MBeanNotificationInfo[] findNotificationsFromAnnotations(
             Class<?> mbeanClass) {
         Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass);
         if (c == null)
--- a/jdk/src/share/classes/java/nio/Buffer.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/java/nio/Buffer.java	Fri Dec 05 09:51:13 2008 -0800
@@ -543,6 +543,10 @@
         return mark;
     }
 
+    final void discardMark() {                          // package-private
+        mark = -1;
+    }
+
     static void checkBounds(int off, int len, int size) { // package-private
         if ((off | len | (off + len) | (size - (off + len))) < 0)
             throw new IndexOutOfBoundsException();
--- a/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java	Fri Dec 05 09:51:13 2008 -0800
@@ -150,6 +150,7 @@
         sb.compact();
         position(rem);
         limit(capacity());
+        discardMark();
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
--- a/jdk/src/share/classes/java/nio/Direct-X-Buffer.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/java/nio/Direct-X-Buffer.java	Fri Dec 05 09:51:13 2008 -0800
@@ -365,6 +365,7 @@
         unsafe.copyMemory(ix(pos), ix(0), rem << $LG_BYTES_PER_VALUE$);
         position(rem);
         limit(capacity());
+        discardMark();
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
--- a/jdk/src/share/classes/java/nio/Heap-X-Buffer.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/java/nio/Heap-X-Buffer.java	Fri Dec 05 09:51:13 2008 -0800
@@ -222,6 +222,7 @@
         System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
         position(remaining());
         limit(capacity());
+        discardMark();
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
--- a/jdk/src/share/classes/java/nio/channels/Channels.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/java/nio/channels/Channels.java	Fri Dec 05 09:51:13 2008 -0800
@@ -65,6 +65,10 @@
 
     private Channels() { }              // No instantiation
 
+    private static void checkNotNull(Object o, String name) {
+        if (o == null)
+            throw new NullPointerException("\"" + name + "\" is null!");
+    }
 
     /**
      * Write all remaining bytes in buffer to the given channel.
@@ -120,6 +124,7 @@
      * @return  A new input stream
      */
     public static InputStream newInputStream(ReadableByteChannel ch) {
+        checkNotNull(ch, "ch");
         return new sun.nio.ch.ChannelInputStream(ch);
     }
 
@@ -138,6 +143,8 @@
      * @return  A new output stream
      */
     public static OutputStream newOutputStream(final WritableByteChannel ch) {
+        checkNotNull(ch, "ch");
+
         return new OutputStream() {
 
                 private ByteBuffer bb = null;
@@ -193,9 +200,7 @@
      * @return  A new readable byte channel
      */
     public static ReadableByteChannel newChannel(final InputStream in) {
-        if (in == null) {
-            throw new NullPointerException();
-        }
+        checkNotNull(in, "in");
 
         if (in instanceof FileInputStream &&
             FileInputStream.class.equals(in.getClass())) {
@@ -270,9 +275,7 @@
      * @return  A new writable byte channel
      */
     public static WritableByteChannel newChannel(final OutputStream out) {
-        if (out == null) {
-            throw new NullPointerException();
-        }
+        checkNotNull(out, "out");
 
         if (out instanceof FileOutputStream &&
             FileOutputStream.class.equals(out.getClass())) {
@@ -357,8 +360,8 @@
                                    CharsetDecoder dec,
                                    int minBufferCap)
     {
-        dec.reset();
-        return StreamDecoder.forDecoder(ch, dec, minBufferCap);
+        checkNotNull(ch, "ch");
+        return StreamDecoder.forDecoder(ch, dec.reset(), minBufferCap);
     }
 
     /**
@@ -393,6 +396,7 @@
     public static Reader newReader(ReadableByteChannel ch,
                                    String csName)
     {
+        checkNotNull(csName, "csName");
         return newReader(ch, Charset.forName(csName).newDecoder(), -1);
     }
 
@@ -425,8 +429,8 @@
                                    final CharsetEncoder enc,
                                    final int minBufferCap)
     {
-        enc.reset();
-        return StreamEncoder.forEncoder(ch, enc, minBufferCap);
+        checkNotNull(ch, "ch");
+        return StreamEncoder.forEncoder(ch, enc.reset(), minBufferCap);
     }
 
     /**
@@ -461,6 +465,7 @@
     public static Writer newWriter(WritableByteChannel ch,
                                    String csName)
     {
+        checkNotNull(csName, "csName");
         return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
     }
 
--- a/jdk/src/share/classes/javax/management/JMX.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/javax/management/JMX.java	Fri Dec 05 09:51:13 2008 -0800
@@ -51,8 +51,6 @@
      * this class.
      */
     static final JMX proof = new JMX();
-    private static final ClassLogger logger =
-        new ClassLogger("javax.management.misc", "JMX");
 
     private JMX() {}
 
@@ -824,11 +822,16 @@
      */
     public static boolean isNotificationSource(Object mbean)
             throws NotCompliantMBeanException {
-        if (mbean instanceof NotificationBroadcaster)
-            return true;
-        Object resource = (mbean instanceof DynamicWrapperMBean) ?
-            ((DynamicWrapperMBean) mbean).getWrappedObject() : mbean;
-        return (MBeanInjector.injectsSendNotification(resource));
+        for (int i = 0; i < 2; i++) {
+            if (mbean instanceof NotificationBroadcaster ||
+                    MBeanInjector.injectsSendNotification(mbean))
+                return true;
+            if (mbean instanceof DynamicWrapperMBean)
+                mbean = ((DynamicWrapperMBean) mbean).getWrappedObject();
+            else
+                break;
+        }
+        return false;
     }
 
     /**
--- a/jdk/src/share/classes/javax/management/StandardEmitterMBean.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/javax/management/StandardEmitterMBean.java	Fri Dec 05 09:51:13 2008 -0800
@@ -26,6 +26,7 @@
 package javax.management;
 
 import com.sun.jmx.mbeanserver.MBeanInjector;
+import com.sun.jmx.mbeanserver.MBeanIntrospector;
 import static javax.management.JMX.MBeanOptions;
 
 /**
@@ -195,10 +196,12 @@
                                     MBeanOptions options,
                                     NotificationEmitter emitter) {
         super(implementation, mbeanInterface, options);
+        MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(implementation);
         if (emitter == null)
-            emitter = defaultEmitter();
+            emitter = defaultEmitter(defaultMBNIs);
         this.emitter = emitter;
-        this.notificationInfo = emitter.getNotificationInfo();
+        this.notificationInfo =
+                firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs);
         injectEmitter();
     }
 
@@ -320,15 +323,23 @@
     protected StandardEmitterMBean(Class<?> mbeanInterface, MBeanOptions options,
                                    NotificationEmitter emitter) {
         super(mbeanInterface, options);
+        MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(this);
         if (emitter == null)
-            emitter = defaultEmitter();
+            emitter = defaultEmitter(defaultMBNIs);
         this.emitter = emitter;
-        this.notificationInfo = emitter.getNotificationInfo();
+        this.notificationInfo =
+                firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs);
         injectEmitter();
     }
 
-    private NotificationEmitter defaultEmitter() {
-        MBeanNotificationInfo[] mbnis = getNotificationInfo();
+    private static MBeanNotificationInfo[] defaultMBNIs(Object mbean) {
+        return MBeanIntrospector.findNotificationsFromAnnotations(
+                mbean.getClass());
+    }
+
+    private NotificationEmitter defaultEmitter(MBeanNotificationInfo[] defaultMBNIs) {
+        MBeanNotificationInfo[] mbnis =
+                firstNonEmpty(getNotificationInfo(), defaultMBNIs);
         // Will be null unless getNotificationInfo() is overridden,
         // since the notificationInfo field has not been set at this point.
         if (mbnis == null)
@@ -336,6 +347,14 @@
         return new NotificationBroadcasterSupport(mbnis);
     }
 
+    private static <T> T[] firstNonEmpty(T[]... items) {
+        for (T[] t : items) {
+            if (t != null && t.length != 0)
+                return t;
+        }
+        return null;
+    }
+
     private void injectEmitter() {
         if (emitter instanceof SendNotification) {
             try {
--- a/jdk/src/share/classes/javax/management/StandardMBean.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/javax/management/StandardMBean.java	Fri Dec 05 09:51:13 2008 -0800
@@ -1058,10 +1058,6 @@
         cachedMBeanInfo = info;
     }
 
-    private boolean isMXBean() {
-        return mbean.isMXBean();
-    }
-
     private static <T> boolean identicalArrays(T[] a, T[] b) {
         if (a == b)
             return true;
@@ -1466,7 +1462,7 @@
             // Check for "MBeanNotificationInfo[] getNotificationInfo()"
             // method.
             //
-            // This method is only taken into account for the MBeanInfo
+            // This method is taken into account for the MBeanInfo
             // immutability checks if and only if the given subclass is
             // StandardEmitterMBean itself or can be assigned to
             // StandardEmitterMBean.
--- a/jdk/src/share/classes/javax/management/openmbean/CompositeDataSupport.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/javax/management/openmbean/CompositeDataSupport.java	Fri Dec 05 09:51:13 2008 -0800
@@ -101,7 +101,7 @@
      * the same size as <tt>itemNames</tt>; must not be null.
      *
      * @throws IllegalArgumentException <tt>compositeType</tt> is null, or
-     * <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
+     * <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null, or one
      * of the elements in <tt>itemNames[]</tt> is a null or empty string, or
      * <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
      *
--- a/jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java	Fri Dec 05 09:51:13 2008 -0800
@@ -49,13 +49,34 @@
         return new ServerSocket(port) {
             @Override
             public Socket accept() throws IOException {
-                Socket socket = super.accept();
-                InetAddress remoteAddr = socket.getInetAddress();
+                final Socket socket = super.accept();
+                final InetAddress remoteAddr = socket.getInetAddress();
                 final String msg = "The server sockets created using the " +
-                        "LocalRMIServerSocketFactory only accept connections " +
-                        "from clients running on the host where the RMI " +
-                        "remote objects have been exported.";
-                if (remoteAddr.isAnyLocalAddress()) {
+                       "LocalRMIServerSocketFactory only accept connections " +
+                       "from clients running on the host where the RMI " +
+                       "remote objects have been exported.";
+
+                if (remoteAddr == null) {
+                    // Though unlikeky, the socket could be already
+                    // closed... Send a more detailed message in
+                    // this case. Also avoid throwing NullPointerExceptiion
+                    //
+                    String details = "";
+                    if (socket.isClosed()) {
+                        details = " Socket is closed.";
+                    } else if (!socket.isConnected()) {
+                        details = " Socket is not connected";
+                    }
+                    try {
+                        socket.close();
+                    } catch (Exception ok) {
+                        // ok - this is just cleanup before throwing detailed
+                        // exception.
+                    }
+                    throw new IOException(msg +
+                            " Couldn't determine client address." +
+                            details);
+                } else if (remoteAddr.isLoopbackAddress()) {
                     // local address: accept the connection.
                     return socket;
                 }
--- a/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java	Fri Dec 05 09:51:13 2008 -0800
@@ -29,32 +29,58 @@
 /**
  * OutputStream that sends the output to the underlying stream using chunked
  * encoding as specified in RFC 2068.
- *
- * @author  Alan Bateman
  */
 public class ChunkedOutputStream extends PrintStream {
 
     /* Default chunk size (including chunk header) if not specified */
     static final int DEFAULT_CHUNK_SIZE = 4096;
+    private static final byte[] CRLF = {'\r', '\n'};
+    private static final int CRLF_SIZE = CRLF.length;
+    private static final byte[] FOOTER = CRLF;
+    private static final int FOOTER_SIZE = CRLF_SIZE;
+    private static final byte[] EMPTY_CHUNK_HEADER = getHeader(0);
+    private static final int EMPTY_CHUNK_HEADER_SIZE = getHeaderSize(0);
 
     /* internal buffer */
     private byte buf[];
+    /* size of data (excluding footers and headers) already stored in buf */
+    private int size;
+    /* current index in buf (i.e. buf[count] */
     private int count;
+    /* number of bytes to be filled up to complete a data chunk
+     * currently being built */
+    private int spaceInCurrentChunk;
 
     /* underlying stream */
     private PrintStream out;
 
     /* the chunk size we use */
-    private int preferredChunkSize;
-
-    /* if the users write buffer is bigger than this size, we
-     * write direct from the users buffer instead of copying
-     */
-    static final int MAX_BUF_SIZE = 10 * 1024;
+    private int preferredChunkDataSize;
+    private int preferedHeaderSize;
+    private int preferredChunkGrossSize;
+    /* header for a complete Chunk */
+    private byte[] completeHeader;
 
     /* return the size of the header for a particular chunk size */
-    private int headerSize(int size) {
-        return 2 + (Integer.toHexString(size)).length();
+    private static int getHeaderSize(int size) {
+        return (Integer.toHexString(size)).length() + CRLF_SIZE;
+    }
+
+    /* return a header for a particular chunk size */
+    private static byte[] getHeader(int size){
+        try {
+            String hexStr =  Integer.toHexString(size);
+            byte[] hexBytes = hexStr.getBytes("US-ASCII");
+            byte[] header = new byte[getHeaderSize(size)];
+            for (int i=0; i<hexBytes.length; i++)
+                header[i] = hexBytes[i];
+            header[hexBytes.length] = CRLF[0];
+            header[hexBytes.length+1] = CRLF[1];
+            return header;
+        } catch (java.io.UnsupportedEncodingException e) {
+            /* This should never happen */
+            throw new InternalError(e.getMessage());
+        }
     }
 
     public ChunkedOutputStream(PrintStream o) {
@@ -63,111 +89,114 @@
 
     public ChunkedOutputStream(PrintStream o, int size) {
         super(o);
-
         out = o;
 
         if (size <= 0) {
             size = DEFAULT_CHUNK_SIZE;
         }
+
         /* Adjust the size to cater for the chunk header - eg: if the
          * preferred chunk size is 1k this means the chunk size should
-         * be 1019 bytes (differs by 5 from preferred size because of
-         * 3 bytes for chunk size in hex and CRLF).
+         * be 1017 bytes (differs by 7 from preferred size because of
+         * 3 bytes for chunk size in hex and CRLF (header) and CRLF (footer)).
+         *
+         * If headerSize(adjusted_size) is shorter then headerSize(size)
+         * then try to use the extra byte unless headerSize(adjusted_size+1)
+         * increases back to headerSize(size)
          */
         if (size > 0) {
-            int adjusted_size = size - headerSize(size);
-            if (adjusted_size + headerSize(adjusted_size) < size) {
+            int adjusted_size = size - getHeaderSize(size) - FOOTER_SIZE;
+            if (getHeaderSize(adjusted_size+1) < getHeaderSize(size)){
                 adjusted_size++;
             }
             size = adjusted_size;
         }
 
         if (size > 0) {
-            preferredChunkSize = size;
+            preferredChunkDataSize = size;
         } else {
-            preferredChunkSize = DEFAULT_CHUNK_SIZE - headerSize(DEFAULT_CHUNK_SIZE);
+            preferredChunkDataSize = DEFAULT_CHUNK_SIZE -
+                    getHeaderSize(DEFAULT_CHUNK_SIZE) - FOOTER_SIZE;
         }
 
+        preferedHeaderSize = getHeaderSize(preferredChunkDataSize);
+        preferredChunkGrossSize = preferedHeaderSize + preferredChunkDataSize
+                + FOOTER_SIZE;
+        completeHeader = getHeader(preferredChunkDataSize);
+
         /* start with an initial buffer */
-        buf = new byte[preferredChunkSize + 32];
+        buf = new byte[preferredChunkDataSize + 32];
+        reset();
     }
 
     /*
-     * If flushAll is true, then all data is flushed in one chunk.
-     *
-     * If false and the size of the buffer data exceeds the preferred
-     * chunk size then chunks are flushed to the output stream.
-     * If there isn't enough data to make up a complete chunk,
-     * then the method returns.
+     * Flush a buffered, completed chunk to an underlying stream. If the data in
+     * the buffer is insufficient to build up a chunk of "preferredChunkSize"
+     * then the data do not get flushed unless flushAll is true. If flushAll is
+     * true then the remaining data builds up a last chunk which size is smaller
+     * than preferredChunkSize, and then the last chunk gets flushed to
+     * underlying stream. If flushAll is true and there is no data in a buffer
+     * at all then an empty chunk (containing a header only) gets flushed to
+     * underlying stream.
      */
-    private void flush(byte[] buf, boolean flushAll) {
-        flush (buf, flushAll, 0);
-    }
-
-    private void flush(byte[] buf, boolean flushAll, int offset) {
-        int chunkSize;
+     private void flush(boolean flushAll) {
+        if (spaceInCurrentChunk == 0) {
+            /* flush a completed chunk to underlying stream */
+            out.write(buf, 0, preferredChunkGrossSize);
+            out.flush();
+            reset();
+        } else if (flushAll){
+            /* complete the last chunk and flush it to underlying stream */
+            if (size > 0){
+                /* adjust a header start index in case the header of the last
+                 * chunk is shorter then preferedHeaderSize */
 
-        do {
-            if (count < preferredChunkSize) {
-                if (!flushAll) {
-                    break;
-                }
-                chunkSize = count;
+                int adjustedHeaderStartIndex = preferedHeaderSize -
+                        getHeaderSize(size);
+
+                /* write header */
+                System.arraycopy(getHeader(size), 0, buf,
+                        adjustedHeaderStartIndex, getHeaderSize(size));
+
+                /* write footer */
+                buf[count++] = FOOTER[0];
+                buf[count++] = FOOTER[1];
+
+                //send the last chunk to underlying stream
+                out.write(buf, adjustedHeaderStartIndex, count - adjustedHeaderStartIndex);
             } else {
-                chunkSize = preferredChunkSize;
-            }
-
-            byte[] bytes = null;
-            try {
-                bytes = (Integer.toHexString(chunkSize)).getBytes("US-ASCII");
-            } catch (java.io.UnsupportedEncodingException e) {
-                //This should never happen.
-                throw new InternalError(e.getMessage());
+                //send an empty chunk (containing just a header) to underlying stream
+                out.write(EMPTY_CHUNK_HEADER, 0, EMPTY_CHUNK_HEADER_SIZE);
             }
 
-            out.write(bytes, 0, bytes.length);
-            out.write((byte)'\r');
-            out.write((byte)'\n');
-            if (chunkSize > 0) {
-                out.write(buf, offset, chunkSize);
-                out.write((byte)'\r');
-                out.write((byte)'\n');
-            }
             out.flush();
-            if (checkError()) {
-                break;
-            }
-            if (chunkSize > 0) {
-                count -= chunkSize;
-                offset += chunkSize;
-            }
-        } while (count > 0);
-
-        if (!checkError() && count > 0) {
-            System.arraycopy(buf, offset, this.buf, 0, count);
-        }
+            reset();
+         }
     }
 
+    @Override
     public boolean checkError() {
         return out.checkError();
     }
 
-    /*
-     * Check if we have enough data for a chunk and if so flush to the
-     * underlying output stream.
-     */
-    private void checkFlush() {
-        if (count >= preferredChunkSize) {
-            flush(buf, false);
-        }
-    }
-
     /* Check that the output stream is still open */
     private void ensureOpen() {
         if (out == null)
             setError();
     }
 
+   /*
+    * Writes data from b[] to an internal buffer and stores the data as data
+    * chunks of a following format: {Data length in Hex}{CRLF}{data}{CRLF}
+    * The size of the data is preferredChunkSize. As soon as a completed chunk
+    * is read from b[] a process of reading from b[] suspends, the chunk gets
+    * flushed to the underlying stream and then the reading process from b[]
+    * continues. When there is no more sufficient data in b[] to build up a
+    * chunk of preferredChunkSize size the data get stored as an incomplete
+    * chunk of a following format: {space for data length}{CRLF}{data}
+    * The size of the data is of course smaller than preferredChunkSize.
+    */
+    @Override
     public synchronized void write(byte b[], int off, int len) {
         ensureOpen();
         if ((off < 0) || (off > b.length) || (len < 0) ||
@@ -177,81 +206,95 @@
             return;
         }
 
-        int l = preferredChunkSize - count;
+        /* if b[] contains enough data then one loop cycle creates one complete
+         * data chunk with a header, body and a footer, and then flushes the
+         * chunk to the underlying stream. Otherwise, the last loop cycle
+         * creates incomplete data chunk with empty header and with no footer
+         * and stores this incomplete chunk in an internal buffer buf[]
+         */
+        int bytesToWrite = len;
+        int inputIndex = off;  /* the index of the byte[] currently being written */
+
+        do {
+            /* enough data to complete a chunk */
+            if (bytesToWrite >= spaceInCurrentChunk) {
 
-        if ((len > MAX_BUF_SIZE) && (len > l)) {
-            /* current chunk is empty just write the data */
-            if (count == 0) {
-                count = len;
-                flush (b, false, off);
-                return;
-            }
+                /* header */
+                for (int i=0; i<completeHeader.length; i++)
+                    buf[i] = completeHeader[i];
+
+                /* data */
+                System.arraycopy(b, inputIndex, buf, count, spaceInCurrentChunk);
+                inputIndex += spaceInCurrentChunk;
+                bytesToWrite -= spaceInCurrentChunk;
+                count += spaceInCurrentChunk;
 
-            /* first finish the current chunk */
-            if (l > 0) {
-                System.arraycopy(b, off, buf, count, l);
-                count = preferredChunkSize;
-                flush(buf, false);
+                /* footer */
+                buf[count++] = FOOTER[0];
+                buf[count++] = FOOTER[1];
+                spaceInCurrentChunk = 0; //chunk is complete
+
+                flush(false);
+                if (checkError()){
+                    break;
+                }
             }
 
-            count = len - l;
-            /* Now write the rest of the data */
-            flush (b, false, l+off);
-        } else {
-            int newcount = count + len;
+            /* not enough data to build a chunk */
+            else {
+                /* header */
+                /* do not write header if not enough bytes to build a chunk yet */
 
-            if (newcount > buf.length) {
-                byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
-                System.arraycopy(buf, 0, newbuf, 0, count);
-                buf = newbuf;
+                /* data */
+                System.arraycopy(b, inputIndex, buf, count, bytesToWrite);
+                count += bytesToWrite;
+                size += bytesToWrite;
+                spaceInCurrentChunk -= bytesToWrite;
+                bytesToWrite = 0;
+
+                /* footer */
+                /* do not write header if not enough bytes to build a chunk yet */
             }
-            System.arraycopy(b, off, buf, count, len);
-            count = newcount;
-            checkFlush();
-        }
+        } while (bytesToWrite > 0);
     }
 
-    public synchronized void write(int b) {
-        ensureOpen();
-        int newcount = count + 1;
-        if (newcount > buf.length) {
-            byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)];
-            System.arraycopy(buf, 0, newbuf, 0, count);
-            buf = newbuf;
-        }
-        buf[count] = (byte)b;
-        count = newcount;
-        checkFlush();
+    @Override
+    public synchronized void write(int _b) {
+        byte b[] = {(byte)_b};
+        write(b, 0, 1);
     }
 
     public synchronized void reset() {
-        count = 0;
+        count = preferedHeaderSize;
+        size = 0;
+        spaceInCurrentChunk = preferredChunkDataSize;
     }
 
     public int size() {
-        return count;
+        return size;
     }
 
+    @Override
     public synchronized void close() {
         ensureOpen();
 
         /* if we have buffer a chunked send it */
-        if (count > 0) {
-            flush(buf, true);
+        if (size > 0) {
+            flush(true);
         }
 
         /* send a zero length chunk */
-        flush(buf, true);
+        flush(true);
 
         /* don't close the underlying stream */
         out = null;
     }
 
+    @Override
     public synchronized void flush() {
         ensureOpen();
-        if (count > 0) {
-            flush(buf, true);
+        if (size > 0) {
+            flush(true);
         }
     }
-
 }
--- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java	Fri Dec 05 09:51:13 2008 -0800
@@ -770,6 +770,7 @@
                 new String[] {
                     "cp834",
                     "ibm834",
+                    "834",
                     "ibm-834"
         });
 
--- a/jdk/src/windows/native/java/lang/java_props_md.c	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/src/windows/native/java/lang/java_props_md.c	Fri Dec 05 09:51:13 2008 -0800
@@ -38,6 +38,12 @@
 #define VER_PLATFORM_WIN32_WINDOWS 1
 #endif
 
+#ifndef PROCESSOR_ARCHITECTURE_AMD64
+#define PROCESSOR_ARCHITECTURE_AMD64 9
+#endif
+
+typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
+
 #define SHELL_KEY "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
 
 /* Encodings for Windows language groups. According to
@@ -674,9 +680,22 @@
     {
         char buf[100];
         OSVERSIONINFOEX ver;
+        SYSTEM_INFO si;
+        PGNSI pGNSI;
+
         ver.dwOSVersionInfoSize = sizeof(ver);
         GetVersionEx((OSVERSIONINFO *) &ver);
 
+        ZeroMemory(&si, sizeof(SYSTEM_INFO));
+        // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.
+        pGNSI = (PGNSI) GetProcAddress(
+                GetModuleHandle(TEXT("kernel32.dll")),
+                "GetNativeSystemInfo");
+        if(NULL != pGNSI)
+            pGNSI(&si);
+        else
+            GetSystemInfo(&si);
+
         /*
          * From msdn page on OSVERSIONINFOEX, current as of this
          * writing, decoding of dwMajorVersion and dwMinorVersion.
@@ -690,9 +709,14 @@
          * Windows 3.51                 3               51
          * Windows NT 4.0               4               0
          * Windows 2000                 5               0
-         * Windows XP                   5               1
+         * Windows XP 32 bit            5               1
          * Windows Server 2003 family   5               2
+         * Windows XP 64 bit            5               2
+         *       where ((&ver.wServicePackMinor) + 2) = 1
+         *       and  si.wProcessorArchitecture = 9
          * Windows Vista family         6               0
+         * Windows 2008                 6               0
+         *       where ((&ver.wServicePackMinor) + 2) = 1
          *
          * This mapping will presumably be augmented as new Windows
          * versions are released.
@@ -720,7 +744,25 @@
                 switch (ver.dwMinorVersion) {
                 case  0: sprops.os_name = "Windows 2000";         break;
                 case  1: sprops.os_name = "Windows XP";           break;
-                case  2: sprops.os_name = "Windows 2003";         break;
+                case  2:
+                   /*
+                    * From MSDN OSVERSIONINFOEX and SYSTEM_INFO documentation:
+                    *
+                    * "Because the version numbers for Windows Server 2003
+                    * and Windows XP 6u4 bit are identical, you must also test
+                    * whether the wProductType member is VER_NT_WORKSTATION.
+                    * and si.wProcessorArchitecture is
+                    * PROCESSOR_ARCHITECTURE_AMD64 (which is 9)
+                    * If it is, the operating system is Windows XP 64 bit;
+                    * otherwise, it is Windows Server 2003."
+                    */
+                    if(ver.wProductType == VER_NT_WORKSTATION &&
+                       si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
+                        sprops.os_name = "Windows XP"; /* 64 bit */
+                    } else {
+                        sprops.os_name = "Windows 2003";
+                    }
+                    break;
                 default: sprops.os_name = "Windows NT (unknown)"; break;
                 }
             } else if (ver.dwMajorVersion == 6) {
--- a/jdk/test/java/nio/Buffer/Basic-X.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/Basic-X.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 #warn This file is preprocessed before being compiled
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class Basic$Type$
@@ -184,32 +185,57 @@
         b.position(p);
     }
 
+    private static void compact(Buffer b) {
+        try {
+            Class<?> cl = b.getClass();
+            Method m = cl.getDeclaredMethod("compact");
+            m.setAccessible(true);
+            m.invoke(b);
+        } catch (Exception e) {
+            fail(e.getMessage(), b);
+        }
+    }
+
+    private static void checkInvalidMarkException(final Buffer b) {
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+            public void run() {
+                b.mark();
+                compact(b);
+                b.reset();
+            }});
+    }
+
     private static void testViews(int level, ByteBuffer b, boolean direct) {
 
         ShortBuffer sb = b.asShortBuffer();
         BasicShort.test(level, sb, direct);
         checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(sb);
 
         CharBuffer cb = b.asCharBuffer();
         BasicChar.test(level, cb, direct);
         checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(cb);
 
         IntBuffer ib = b.asIntBuffer();
         BasicInt.test(level, ib, direct);
         checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(ib);
 
         LongBuffer lb = b.asLongBuffer();
         BasicLong.test(level, lb, direct);
         checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(lb);
 
         FloatBuffer fb = b.asFloatBuffer();
         BasicFloat.test(level, fb, direct);
         checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
+        checkInvalidMarkException(fb);
 
         DoubleBuffer db = b.asDoubleBuffer();
         BasicDouble.test(level, db, direct);
         checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
-
+        checkInvalidMarkException(db);
     }
 
     private static void testHet(int level, ByteBuffer b) {
@@ -288,8 +314,11 @@
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), ($type$)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/Basic.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/Basic.java	Fri Dec 05 09:51:13 2008 -0800
@@ -25,7 +25,7 @@
  * @summary Unit test for buffers
  * @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
  *      4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 6231529
- *      6221101 6234263 6535542 6591971
+ *      6221101 6234263 6535542 6591971 6593946
  * @author Mark Reinhold
  */
 
--- a/jdk/test/java/nio/Buffer/BasicByte.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicByte.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicByte
@@ -184,32 +185,57 @@
         b.position(p);
     }
 
+    private static void compact(Buffer b) {
+        try {
+            Class<?> cl = b.getClass();
+            Method m = cl.getDeclaredMethod("compact");
+            m.setAccessible(true);
+            m.invoke(b);
+        } catch (Exception e) {
+            fail(e.getMessage(), b);
+        }
+    }
+
+    private static void checkInvalidMarkException(final Buffer b) {
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+            public void run() {
+                b.mark();
+                compact(b);
+                b.reset();
+            }});
+    }
+
     private static void testViews(int level, ByteBuffer b, boolean direct) {
 
         ShortBuffer sb = b.asShortBuffer();
         BasicShort.test(level, sb, direct);
         checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(sb);
 
         CharBuffer cb = b.asCharBuffer();
         BasicChar.test(level, cb, direct);
         checkBytes(b, new byte[] { 0, (byte)ic(0) });
+        checkInvalidMarkException(cb);
 
         IntBuffer ib = b.asIntBuffer();
         BasicInt.test(level, ib, direct);
         checkBytes(b, new byte[] { 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(ib);
 
         LongBuffer lb = b.asLongBuffer();
         BasicLong.test(level, lb, direct);
         checkBytes(b, new byte[] { 0, 0, 0, 0, 0, 0, 0, (byte)ic(0) });
+        checkInvalidMarkException(lb);
 
         FloatBuffer fb = b.asFloatBuffer();
         BasicFloat.test(level, fb, direct);
         checkBytes(b, new byte[] { 0x42, (byte)0xc2, 0, 0 });
+        checkInvalidMarkException(fb);
 
         DoubleBuffer db = b.asDoubleBuffer();
         BasicDouble.test(level, db, direct);
         checkBytes(b, new byte[] { 0x40, 0x58, 0x40, 0, 0, 0, 0, 0 });
-
+        checkInvalidMarkException(db);
     }
 
     private static void testHet(int level, ByteBuffer b) {
@@ -288,8 +314,11 @@
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (byte)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicChar.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicChar.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicChar
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (char)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicDouble.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicDouble.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicDouble
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (double)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicFloat.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicFloat.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicFloat
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (float)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicInt.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicInt.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicInt
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (int)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicLong.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicLong.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicLong
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (long)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/BasicShort.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/BasicShort.java	Fri Dec 05 09:51:13 2008 -0800
@@ -31,6 +31,7 @@
 // -- This file was mechanically generated: Do not edit! -- //
 
 import java.nio.*;
+import java.lang.reflect.Method;
 
 
 public class BasicShort
@@ -283,13 +284,41 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
     private static void tryCatch(Buffer b, Class ex, Runnable thunk) {
         boolean caught = false;
         try {
             thunk.run();
         } catch (Throwable x) {
-            if (ex.isAssignableFrom(x.getClass()))
+            if (ex.isAssignableFrom(x.getClass())) {
                 caught = true;
+            } else {
+                fail(x.getMessage() + " not expected");
+            }
         }
         if (!caught)
             fail(ex.getName() + " not thrown", b);
@@ -356,7 +385,6 @@
 
         // Exceptions
 
-        boolean caught = false;
         relPut(b);
         b.limit(b.capacity() / 2);
         b.position(b.limit());
@@ -386,6 +414,14 @@
                     b.put(b.limit(), (short)42);
                 }});
 
+        tryCatch(b, InvalidMarkException.class, new Runnable() {
+                public void run() {
+                    b.position(0);
+                    b.mark();
+                    b.compact();
+                    b.reset();
+                }});
+
         // Values
 
         b.clear();
--- a/jdk/test/java/nio/Buffer/genBasic.sh	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/genBasic.sh	Fri Dec 05 09:51:13 2008 -0800
@@ -23,10 +23,10 @@
 # have any questions.
 #
 
-SPP='sh ../../../../make/java/nio/spp.sh'
+javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java
 
 gen() {
-  $SPP -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java >Basic$2.java
+    java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 <Basic-X.java >Basic$2.java
 }
 
 gen byte Byte Byte
@@ -36,3 +36,5 @@
 gen long Long Long
 gen float Float Float
 gen double Double Double
+
+rm -rf build
--- a/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/Buffer/genCopyDirectMemory.sh	Fri Dec 05 09:51:13 2008 -0800
@@ -23,10 +23,10 @@
 # have any questions.
 #
 
-SPP='sh ../../../../make/java/nio/spp.sh'
+javac -d . ../../../../make/tools/src/build/tools/spp/Spp.java > Spp.java
 
 gen() {
-  $SPP -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java >CopyDirect$2Memory.java
+    java  build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3<CopyDirect-X-Memory.java >CopyDirect$2Memory.java
 }
 
 gen byte Byte Byte
@@ -37,3 +37,4 @@
 gen float Float Float
 gen double Double Double
 
+rm -rf build
--- a/jdk/test/java/nio/channels/Channels/Basic.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/java/nio/channels/Channels/Basic.java	Fri Dec 05 09:51:13 2008 -0800
@@ -22,12 +22,13 @@
  */
 
 /* @test
- * @bug 4417152 4481572 6248930
+ * @bug 4417152 4481572 6248930 6725399
  * @summary Test Channels basic functionality
  */
 
 import java.io.*;
 import java.nio.*;
+import java.nio.charset.*;
 import java.nio.channels.*;
 
 
@@ -50,22 +51,106 @@
         test();
     }
 
+    static void failNpeExpected() {
+        throw new RuntimeException("Did not get the expected NullPointerException.");
+    }
+
     private static void test() throws Exception {
+        //Test if methods of Channels throw NPE with null argument(s)
+        try {
+            Channels.newInputStream((ReadableByteChannel)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newOutputStream((WritableByteChannel)null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
         try {
             ReadableByteChannel channel = Channels.newChannel((InputStream)null);
-
-            throw new RuntimeException("Did not get the expected NullPointerException.");
-        } catch (NullPointerException ne) {
-            // OK. As expected.
-        }
+            failNpeExpected();
+        } catch (NullPointerException ne) {}  // OK. As expected.
 
         try {
             WritableByteChannel channel = Channels.newChannel((OutputStream)null);
+            failNpeExpected();
+        } catch (NullPointerException ne) {}  // OK. As expected.
 
-            throw new RuntimeException("Did not get the expected NullPointerException.");
-        } catch (NullPointerException ne) {
-            // OK. As expected.
-        }
+        WritableByteChannel wbc = new WritableByteChannel() {
+            public int write(ByteBuffer src) { return 0; }
+            public void close() throws IOException { }
+            public boolean isOpen() { return true; }
+        };
+
+        ReadableByteChannel rbc = new ReadableByteChannel() {
+            public int read(ByteBuffer dst) { return 0; }
+            public void close() {}
+            public boolean isOpen() { return true; }
+        };
+
+        try {
+            Channels.newReader((ReadableByteChannel)null,
+                               Charset.defaultCharset().newDecoder(),
+                               -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader(rbc, (CharsetDecoder)null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader((ReadableByteChannel)null,
+                               Charset.defaultCharset().name());
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newReader(rbc, null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+
+        try {
+            Channels.newReader(null, null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter((WritableByteChannel)null,
+                               Charset.defaultCharset().newEncoder(),
+                               -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(null, null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(wbc, null, -1);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter((WritableByteChannel)null,
+                               Charset.defaultCharset().name());
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(wbc, null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
+        try {
+            Channels.newWriter(null, null);
+            failNpeExpected();
+        } catch (NullPointerException npe) {}
+
 
         try {
             blah = File.createTempFile("blah", null);
--- a/jdk/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java	Fri Dec 05 09:51:13 2008 -0800
@@ -22,8 +22,8 @@
  */
 
 /*
- * @test %M% %I%
- * @bug 6323980
+ * @test
+ * @bug 6323980 6772779
  * @summary Test &#64;NotificationInfo annotation
  * @author Eamonn McManus
  * @run main/othervm -ea AnnotatedNotificationInfoTest
@@ -32,6 +32,7 @@
 import java.io.Serializable;
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Field;
+import java.util.Arrays;
 import javax.annotation.Resource;
 import javax.management.AttributeChangeNotification;
 import javax.management.Description;
@@ -134,6 +135,23 @@
 
     private static Object mbeanIntf5 = new Intf5Impl();
 
+    @NotificationInfo(
+            types = {"foo", "bar"},
+            notificationClass = AttributeChangeNotification.class,
+            description = @Description(
+                value = "description",
+                bundleBaseName = "bundle",
+                key = "key"),
+            descriptorFields = {"foo=bar"})
+    public static interface Intf6MBean {}
+
+    public static class Intf6 implements Intf6MBean {
+        @Resource
+        private volatile SendNotification send;
+    }
+
+    private static Object mbeanIntf6 = new Intf6();
+
     public static interface Impl1MBean {}
 
     @NotificationInfo(
@@ -202,22 +220,21 @@
 
     private static Object mbeanMBean2 = new MBean2();
 
-    // Following disabled until we support it
-//    @MBean
-//    @NotificationInfo(
-//            types = {"foo", "bar"},
-//            notificationClass = AttributeChangeNotification.class,
-//            description = @Description(
-//                value = "description",
-//                bundleBaseName = "bundle",
-//                key = "key"),
-//            descriptorFields = {"foo=bar"})
-//    public static class MBean3 {
-//        @Resource
-//        private volatile SendNotification send;
-//    }
-//
-//    private static Object mbeanMBean3 = new MBean3();
+    @MBean
+    @NotificationInfo(
+            types = {"foo", "bar"},
+            notificationClass = AttributeChangeNotification.class,
+            description = @Description(
+                value = "description",
+                bundleBaseName = "bundle",
+                key = "key"),
+            descriptorFields = {"foo=bar"})
+    public static class MBean3 {
+        @Resource
+        private volatile SendNotification send;
+    }
+
+    private static Object mbeanMBean3 = new MBean3();
 
     @MXBean
     @NotificationInfo(
@@ -237,6 +254,23 @@
 
     private static Object mbeanMXBean2 = new MXBean2();
 
+    // Classes for the second test.  This tests the simplest case, which is
+    // the first example in the javadoc for @NotificationInfo.  Notice that
+    // this MBean is not a NotificationBroadcaster and does not inject a
+    // SendNotification!  That should possibly be an error, but it's currently
+    // allowed by the spec.
+    @NotificationInfo(types={"com.example.notifs.create",
+                             "com.example.notifs.destroy"})
+    public static interface CacheMBean {
+        public int getCachedNum();
+    }
+
+    public static class Cache implements CacheMBean {
+        public int getCachedNum() {
+            return 0;
+        }
+    }
+
     public static void main(String[] args) throws Exception {
         if (!AnnotatedNotificationInfoTest.class.desiredAssertionStatus())
             throw new Exception("Test must be run with -ea");
@@ -267,5 +301,14 @@
             assert mbnis[0].equals(expected) : mbnis[0];
             mbs.unregisterMBean(on);
         }
+
+        mbs.registerMBean(new Cache(), on);
+        MBeanInfo mbi = mbs.getMBeanInfo(on);
+        MBeanNotificationInfo[] mbnis = mbi.getNotifications();
+        assert mbnis.length == 1 : mbnis.length;
+        String[] types = mbnis[0].getNotifTypes();
+        String[] expectedTypes =
+                CacheMBean.class.getAnnotation(NotificationInfo.class).types();
+        assert Arrays.equals(types, expectedTypes) : Arrays.toString(types);
     }
 }
--- a/jdk/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java	Fri Dec 05 09:51:13 2008 -0800
@@ -23,14 +23,27 @@
 
 /*
  * @test DynamicWrapperMBeanTest
- * @bug 6624232
+ * @bug 6624232 6776225
  * @summary Test the DynamicWrapperMBean interface
  * @author Eamonn McManus
  */
 
 import java.lang.management.ManagementFactory;
+import javax.annotation.Resource;
+import javax.management.JMX;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
 import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcaster;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationInfo;
+import javax.management.NotificationListener;
 import javax.management.ObjectName;
+import javax.management.SendNotification;
+import javax.management.StandardEmitterMBean;
 import javax.management.StandardMBean;
 import javax.management.modelmbean.ModelMBeanInfo;
 import javax.management.modelmbean.ModelMBeanInfoSupport;
@@ -39,6 +52,25 @@
 import static javax.management.StandardMBean.Options;
 
 public class DynamicWrapperMBeanTest {
+    private static String failure;
+
+    public static void main(String[] args) throws Exception {
+        wrapTest();
+        notifTest();
+
+        if (failure == null)
+            System.out.println("TEST PASSED");
+        else
+            throw new Exception("TEST FAILED: " + failure);
+    }
+
+    private static final Options wrappedVisOpts = new Options();
+    private static final Options wrappedInvisOpts = new Options();
+    static {
+        wrappedVisOpts.setWrappedObjectVisible(true);
+        wrappedInvisOpts.setWrappedObjectVisible(false);
+    }
+
     public static interface WrappedMBean {
         public void sayHello();
     }
@@ -48,19 +80,13 @@
         }
     }
 
-    private static String failure;
-
-    public static void main(String[] args) throws Exception {
+    private static void wrapTest() throws Exception {
         if (Wrapped.class.getClassLoader() ==
                 StandardMBean.class.getClassLoader()) {
             throw new Exception(
                     "TEST ERROR: Resource and StandardMBean have same ClassLoader");
         }
 
-        Options wrappedVisOpts = new Options();
-        wrappedVisOpts.setWrappedObjectVisible(true);
-        Options wrappedInvisOpts = new Options();
-        wrappedInvisOpts.setWrappedObjectVisible(false);
         assertEquals("Options withWrappedObjectVisible(false)",
                      new Options(), wrappedInvisOpts);
 
@@ -138,8 +164,223 @@
         assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource",
                 true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName()));
 
-        if (failure != null)
-            throw new Exception("TEST FAILED: " + failure);
+        mbs.unregisterMBean(visibleName);
+        mbs.unregisterMBean(invisibleName);
+    }
+
+    private static enum WrapType {
+        NBS("NotificationBroadcasterSupport"),
+        INJ("@Resource SendNotification"),
+        STD_MBEAN_NBS("StandardMBean delegating to NotificationBroadcasterSupport"),
+        STD_MBEAN_INJ("StandardMBean delegating to @Resource SendNotification"),
+        STD_MBEAN_SUB_NBS("StandardMBean subclass implementing NotificationBroadcaster"),
+        STD_MBEAN_SUB_INJ("StandardMBean subclass with @Resource SendNotification"),
+        STD_EMIT_MBEAN_NBS("StandardEmitterMBean delegating to NotificationBroadcasterSupport"),
+        STD_EMIT_MBEAN_INJ("StandardEmitterMBean delegating to @Resource SendNotification"),
+        STD_EMIT_MBEAN_SUB("StandardEmitterMBean subclass"),
+        STD_EMIT_MBEAN_SUB_INJ("StandardEmitterMBean subclass with @Resource SendNotification");
+
+        WrapType(String s) {
+            this.s = s;
+        }
+
+        @Override
+        public String toString() {
+            return s;
+        }
+
+        private final String s;
+    }
+
+    @NotificationInfo(
+        types = {"foo", "bar"}
+    )
+    public static interface BroadcasterMBean {
+        public void send(Notification n);
+    }
+
+    public static class Broadcaster
+            extends NotificationBroadcasterSupport implements BroadcasterMBean {
+        public void send(Notification n) {
+            super.sendNotification(n);
+        }
+    }
+
+    public static interface SendNotifMBean extends BroadcasterMBean {
+    }
+
+    public static class SendNotif implements SendNotifMBean {
+        @Resource
+        private volatile SendNotification sendNotif;
+
+        public void send(Notification n) {
+            sendNotif.sendNotification(n);
+        }
+    }
+
+    public static class StdBroadcaster
+            extends StandardMBean
+            implements BroadcasterMBean, NotificationBroadcaster {
+        private final NotificationBroadcasterSupport nbs =
+                new NotificationBroadcasterSupport();
+
+        public StdBroadcaster() throws Exception {
+            super(BroadcasterMBean.class);
+        }
+
+        public void send(Notification n) {
+            nbs.sendNotification(n);
+        }
+
+        public void addNotificationListener(NotificationListener listener,
+                NotificationFilter filter, Object handback) {
+            nbs.addNotificationListener(listener, filter, handback);
+        }
+
+        public MBeanNotificationInfo[] getNotificationInfo() {
+            return null;
+        }
+
+        public void removeNotificationListener(NotificationListener listener)
+                throws ListenerNotFoundException {
+            nbs.removeNotificationListener(listener);
+        }
+    }
+
+    public static class StdSendNotif
+            extends StandardMBean implements SendNotifMBean {
+        @Resource
+        private volatile SendNotification sendNotif;
+
+        public StdSendNotif() throws Exception {
+            super(SendNotifMBean.class);
+        }
+
+        public void send(Notification n) {
+            sendNotif.sendNotification(n);
+        }
+    }
+
+    public static class StdEmitterBroadcaster // :-)
+            extends StandardEmitterMBean
+            implements BroadcasterMBean {
+
+        public StdEmitterBroadcaster() throws Exception {
+            super(BroadcasterMBean.class, null);
+        }
+
+        public void send(Notification n) {
+            super.sendNotification(n);
+        }
+    }
+
+    // This case is unlikely - if you're using @Resource SendNotification
+    // then there's no point in using StandardEmitterMBean, since
+    // StandardMBean would suffice.
+    public static class StdEmitterSendNotif
+            extends StandardEmitterMBean implements SendNotifMBean {
+        @Resource
+        private volatile SendNotification sendNotif;
+
+        public StdEmitterSendNotif() {
+            super(SendNotifMBean.class, null);
+        }
+
+        public void send(Notification n) {
+            sendNotif.sendNotification(n);
+        }
+    }
+
+    // Test that JMX.isNotificationSource and
+    // mbs.isInstanceOf("NotificationBroadcaster") work correctly even when
+    // the MBean is a broadcaster by virtue of its wrapped resource.
+    // Test that we find the MBeanNotificationInfo[] from the @NotificationInfo
+    // annotation on BroadcasterMBean.  We cover a large number of different
+    // MBean types, but all ultimately implement that interface.
+    private static void notifTest() throws Exception {
+        System.out.println("===Testing notification senders===");
+
+        for (WrapType wrapType : WrapType.values()) {
+            System.out.println("---" + wrapType);
+
+            final Object mbean;
+
+            switch (wrapType) {
+            case NBS:
+                // An MBean that extends NotificationBroadcasterSupport
+                mbean = new Broadcaster();
+                break;
+            case INJ:
+                // An MBean that injects SendNotification
+                mbean = new SendNotif();
+                break;
+            case STD_MBEAN_NBS:
+                // A StandardMBean that delegates to a NotificationBroadcasterSupport
+                mbean = new StandardMBean(
+                        new Broadcaster(), BroadcasterMBean.class, wrappedVisOpts);
+                break;
+            case STD_MBEAN_INJ:
+                // A StandardMBean that delegates to an object that injects
+                // SendNotification
+                mbean = new StandardMBean(
+                        new SendNotif(), BroadcasterMBean.class, wrappedVisOpts);
+                break;
+            case STD_EMIT_MBEAN_NBS: {
+                // A StandardEmitterMBean that delegates to a NotificationBroadcasterSupport
+                Broadcaster broadcaster = new Broadcaster();
+                mbean = new StandardEmitterMBean(
+                        broadcaster, BroadcasterMBean.class, wrappedVisOpts,
+                        broadcaster);
+                break;
+            }
+            case STD_EMIT_MBEAN_INJ: {
+                // A StandardEmitterMBean that delegates to an object that injects
+                // SendNotification
+                SendNotif sendNotif = new SendNotif();
+                mbean = new StandardEmitterMBean(
+                        sendNotif, BroadcasterMBean.class, wrappedVisOpts,
+                        null);
+                break;
+            }
+            case STD_MBEAN_SUB_NBS:
+                // A subclass of StandardMBean that implements NotificationBroadcaster
+                mbean = new StdBroadcaster();
+                break;
+            case STD_MBEAN_SUB_INJ:
+                // A subclass of StandardMBean that injects SendNotification
+                mbean = new StdSendNotif();
+                break;
+            case STD_EMIT_MBEAN_SUB:
+                // A subclass of StandardEmitterMBean
+                mbean = new StdEmitterBroadcaster();
+                break;
+            case STD_EMIT_MBEAN_SUB_INJ:
+                // A subclass of StandardEmitterMBean that injects SendNotification
+                // (which is a rather strange thing to do and probably a user
+                // misunderstanding but we should do the right thing anyway).
+                mbean = new StdEmitterSendNotif();
+                break;
+            default:
+                throw new AssertionError();
+            }
+
+            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+            final ObjectName name = new ObjectName("a:type=Sender");
+            mbs.registerMBean(mbean, name);
+            boolean isBroadcaster = mbs.isInstanceOf(
+                    name, NotificationBroadcaster.class.getName());
+            assertEquals("JMX.isNotificationSource(mbean)",
+                    true, JMX.isNotificationSource(mbean));
+            assertEquals("isInstanceOf(NotificationBroadcaster)",
+                    true, isBroadcaster);
+            MBeanNotificationInfo[] mbnis =
+                    mbs.getMBeanInfo(name).getNotifications();
+            assertEquals("MBeanNotificationInfo not empty",
+                    true, (mbnis.length > 0));
+
+            mbs.unregisterMBean(name);
+        }
     }
 
     private static void assertEquals(String what, Object expect, Object actual) {
--- a/jdk/test/lib/security/cacerts/VerifyCACerts.java	Thu Dec 04 11:10:25 2008 -0800
+++ b/jdk/test/lib/security/cacerts/VerifyCACerts.java	Fri Dec 05 09:51:13 2008 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-2008 Sun Microsystems, Inc.  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
@@ -23,11 +23,12 @@
 
 /**
  * @test
- * @bug 4400624 6321453
+ * @bug 4400624 6321453 6728890 6732157 6754779 6768559
  * @summary Make sure all self-signed root cert signatures are valid
  */
 import java.io.FileInputStream;
 import java.security.KeyStore;
+import java.security.MessageDigest;
 import java.security.cert.*;
 import java.util.*;
 
@@ -39,25 +40,102 @@
         System.getProperty("file.separator") + "security" +
         System.getProperty("file.separator") + "cacerts";
 
+    private static boolean atLeastOneFailed = false;
+
+    private static MessageDigest md;
+
+    // map of cert alias to SHA1 fingerprint
+    private static Map<String, String> fpMap = new HashMap<String, String>();
+
+    private static String[][] entries = {
+        { "swisssignsilverg2ca", "9B:AA:E5:9F:56:EE:21:CB:43:5A:BE:25:93:DF:A7:F0:40:D1:1D:CB"},
+        { "swisssigngoldg2ca", "D8:C5:38:8A:B7:30:1B:1B:6E:D4:7A:E6:45:25:3A:6F:9F:1A:27:61"},
+        { "swisssignplatinumg2ca", "56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66"},
+        { "verisigntsaca", "BE:36:A4:56:2F:B2:EE:05:DB:B3:D3:23:23:AD:F4:45:08:4E:D6:56"},
+        { "camerfirmachambersignca", "4A:BD:EE:EC:95:0D:35:9C:89:AE:C7:52:A1:2C:5B:29:F6:D6:AA:0C"},
+        { "camerfirmachambersca", "78:6A:74:AC:76:AB:14:7F:9C:6A:30:50:BA:9E:A8:7E:FE:9A:CE:3C"},
+        { "camerfirmachamberscommerceca", "6E:3A:55:A4:19:0C:19:5C:93:84:3C:C0:DB:72:2E:31:30:61:F0:B1"},
+        { "deutschetelekomrootca2", "85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF"},
+    };
+
+    static {
+        for (String[] entry : entries) {
+            fpMap.put(entry[0], entry[1]);
+        }
+    };
+
     public static void main(String[] args) throws Exception {
+        md = MessageDigest.getInstance("SHA1");
+        KeyStore ks = KeyStore.getInstance("JKS");
+        ks.load(new FileInputStream(cacertsFileName), "changeit".toCharArray());
 
+        // check that all entries in the map are in the keystore
+        for (String alias : fpMap.keySet()) {
+            if (!ks.isCertificateEntry(alias)) {
+                atLeastOneFailed = true;
+                System.err.println(alias + " is not in cacerts");
+            }
+        }
         // pull all the trusted self-signed CA certs out of the cacerts file
         // and verify their signatures
-        KeyStore ks = KeyStore.getInstance("JKS");
-        ks.load(new FileInputStream(cacertsFileName), "changeit".toCharArray());
         Enumeration<String> aliases = ks.aliases();
         while (aliases.hasMoreElements()) {
             String alias = aliases.nextElement();
             System.out.println("Verifying " + alias);
-            if (!ks.isCertificateEntry(alias))
-                throw new Exception(alias + " is not a trusted cert entry");
+            if (!ks.isCertificateEntry(alias)) {
+                atLeastOneFailed = true;
+                System.err.println(alias + " is not a trusted cert entry");
+            }
             Certificate cert = ks.getCertificate(alias);
             // remember the GTE CyberTrust CA cert for further tests
             if (alias.equals("gtecybertrustca")) {
-                throw new Exception
+                atLeastOneFailed = true;
+                System.err.println
                     ("gtecybertrustca is expired and should be deleted");
             }
             cert.verify(cert.getPublicKey());
+            if (!checkFingerprint(alias, cert)) {
+                atLeastOneFailed = true;
+                System.err.println
+                    (alias + " SHA1 fingerprint is incorrect");
+            }
+        }
+
+        if (atLeastOneFailed) {
+            throw new Exception("At least one cacert test failed");
         }
     }
+
+    private static boolean checkFingerprint(String alias, Certificate cert)
+        throws Exception {
+        String fingerprint = fpMap.get(alias);
+        if (fingerprint == null) {
+            // no entry for alias
+            return true;
+        }
+        System.out.println("Checking fingerprint of " + alias);
+        byte[] digest = md.digest(cert.getEncoded());
+        return fingerprint.equals(toHexString(digest));
+    }
+
+    private static String toHexString(byte[] block) {
+        StringBuffer buf = new StringBuffer();
+        int len = block.length;
+        for (int i = 0; i < len; i++) {
+             byte2hex(block[i], buf);
+             if (i < len-1) {
+                 buf.append(":");
+             }
+        }
+        return buf.toString();
+    }
+
+    private static void byte2hex(byte b, StringBuffer buf) {
+        char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
+                            '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+        int high = ((b & 0xf0) >> 4);
+        int low = (b & 0x0f);
+        buf.append(hexChars[high]);
+        buf.append(hexChars[low]);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java	Fri Dec 05 09:51:13 2008 -0800
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ *  @test LocalRMIServerSocketFactoryTest.java
+ *  @bug 6774170
+ *  @summary Connect to a server socket returned by the LocalRMIServerSocketFactory.
+ *
+ *  @author Daniel Fuchs
+ *
+ *  @run compile -XDignore.symbol.file=true -source 1.6 -g LocalRMIServerSocketFactoryTest.java
+ *  @run main LocalRMIServerSocketFactoryTest
+ */
+
+import sun.management.jmxremote.LocalRMIServerSocketFactory;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.concurrent.SynchronousQueue;
+
+public class LocalRMIServerSocketFactoryTest {
+
+    private static final SynchronousQueue<Exception> queue =
+            new SynchronousQueue<Exception>();
+
+    static final class Result extends Exception {
+
+        private Result() {
+            super("SUCCESS: No exception was thrown");
+        }
+        static final Result SUCCESS = new Result();
+    }
+
+    private static void checkError(String message) throws Exception {
+
+        // Wait for the server to set the error field.
+        final Exception x = queue.take();
+
+        if (x == Result.SUCCESS) {
+            return;
+        }
+
+
+        // case of 6674166: this is very unlikely to happen, even if
+        //     both 6674166 and 6774170 aren't fixed. If it happens
+        //     however, it might indicate that neither defects are fixed.
+
+        if (x instanceof NullPointerException) {
+            throw new Exception(message + " - " +
+                    "Congratulations! it seems you have triggered 6674166. " +
+                    "Neither 6674166 nor 6774170 seem to be fixed: " + x, x);
+        } else if (x instanceof IOException) {
+            throw new Exception(message + " - " +
+                    "Unexpected IOException. Maybe you triggered 6674166? " +
+                    x, x);
+        } else if (x != null) {
+            throw new Exception(message + " - " +
+                    "Ouch, that's bad. " +
+                    "This is a new kind of unexpected exception " +
+                    x, x);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        final LocalRMIServerSocketFactory f =
+                new LocalRMIServerSocketFactory();
+        final ServerSocket s = f.createServerSocket(0);
+        final int port = s.getLocalPort();
+        Thread t = new Thread() {
+
+            public void run() {
+                while (true) {
+                    Exception error = Result.SUCCESS;
+                    try {
+                        System.err.println("Accepting: ");
+                        final Socket ss = s.accept();
+                        System.err.println(ss.getInetAddress() + " accepted");
+                    } catch (Exception x) {
+                        x.printStackTrace();
+                        error = x;
+                    } finally {
+                        try {
+                            // wait for the client to get the exception.
+                            queue.put(error);
+                        } catch (Exception x) {
+                            // too bad!
+                            System.err.println("Could't send result to client!");
+                            x.printStackTrace();
+                            return;
+                        }
+                    }
+                }
+            }
+        };
+        t.setDaemon(true);
+        t.start();
+
+        System.err.println("new Socket((String)null, port)");
+        final Socket s1 = new Socket((String) null, port);
+        checkError("new Socket((String)null, port)");
+        s1.close();
+        System.err.println("new Socket((String)null, port): PASSED");
+
+        System.err.println("new Socket(InetAddress.getByName(null), port)");
+        final Socket s2 = new Socket(InetAddress.getByName(null), port);
+        checkError("new Socket(InetAddress.getByName(null), port)");
+        s2.close();
+        System.err.println("new Socket(InetAddress.getByName(null), port): PASSED");
+
+        System.err.println("new Socket(localhost, port)");
+        final Socket s3 = new Socket("localhost", port);
+        checkError("new Socket(localhost, port)");
+        s3.close();
+        System.err.println("new Socket(localhost, port): PASSED");
+
+        System.err.println("new Socket(127.0.0.1, port)");
+        final Socket s4 = new Socket("127.0.0.1", port);
+        checkError("new Socket(127.0.0.1, port)");
+        s4.close();
+        System.err.println("new Socket(127.0.0.1, port): PASSED");
+
+    }
+}