# HG changeset patch # User tbell # Date 1228499473 28800 # Node ID f5d84a55742b07ac2d95dcebbd20b4c565b7bc62 # Parent bfa39b25f0fc9acb6ed5f9323d708798a217935f# Parent dec82d3745bcc23ef13f88986f4b4bf1f39107e2 Merge diff -r dec82d3745bc -r f5d84a55742b jdk/make/common/shared/Sanity.gmk --- 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 \n" \ - "int main(char** argv, int argc) {\n" \ - " printf(\"%s\", SND_LIB_VERSION_STR);\n" \ - " return 0;\n" \ - "}\n" \ + "#include \n" \ + "int main(int argc, char** argv) {\n" \ + " printf(\"%s\", SND_LIB_VERSION_STR);\n" \ + " return 0;\n" \ + "}\n" \ > $@ endif diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java --- 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); } diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java --- 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 { +public abstract class MBeanIntrospector { static final class PerInterfaceMap extends WeakHashMap, WeakReference>> {} @@ -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) diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/java/nio/Buffer.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/java/nio/ByteBufferAs-X-Buffer.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/java/nio/Direct-X-Buffer.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/java/nio/Heap-X-Buffer.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/java/nio/channels/Channels.java --- 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); } diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/javax/management/JMX.java --- 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; } /** diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/javax/management/StandardEmitterMBean.java --- 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[] 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 { diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/javax/management/StandardMBean.java --- 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 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. diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/javax/management/openmbean/CompositeDataSupport.java --- 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 itemNames; must not be null. * * @throws IllegalArgumentException compositeType is null, or - * itemNames[] or itemValues[] is null or empty, or one + * itemNames[] or itemValues[] is null, or one * of the elements in itemNames[] is a null or empty string, or * itemNames[] and itemValues[] are not of the same size. * diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/sun/management/jmxremote/LocalRMIServerSocketFactory.java --- 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; } diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java --- 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 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 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); } } - } diff -r dec82d3745bc -r f5d84a55742b jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java --- 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" }); diff -r dec82d3745bc -r f5d84a55742b jdk/src/windows/native/java/lang/java_props_md.c --- 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) { diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/Basic-X.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/Basic.java --- 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 */ diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicByte.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicChar.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicDouble.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicFloat.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicInt.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicLong.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/BasicShort.java --- 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(); diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/genBasic.sh --- 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$2.java + java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3 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 diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/Buffer/genCopyDirectMemory.sh --- 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=$3CopyDirect$2Memory.java + java build.tools.spp.Spp -K$1 -Dtype=$1 -DType=$2 -DFulltype=$3CopyDirect$2Memory.java } gen byte Byte Byte @@ -37,3 +37,4 @@ gen float Float Float gen double Double Double +rm -rf build diff -r dec82d3745bc -r f5d84a55742b jdk/test/java/nio/channels/Channels/Basic.java --- 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); diff -r dec82d3745bc -r f5d84a55742b jdk/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java --- 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 @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); } } diff -r dec82d3745bc -r f5d84a55742b jdk/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java --- 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) { diff -r dec82d3745bc -r f5d84a55742b jdk/test/lib/security/cacerts/VerifyCACerts.java --- 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 fpMap = new HashMap(); + + 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 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]); + } } diff -r dec82d3745bc -r f5d84a55742b jdk/test/sun/management/jmxremote/LocalRMIServerSocketFactoryTest.java --- /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 queue = + new SynchronousQueue(); + + 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"); + + } +}