changeset 4325:36724da65fef

Merge
author michaelm
date Mon, 02 May 2011 20:17:18 +0100
parents 60b4039f60f9 (current diff) d08d77ad2d7b (diff)
children 827b4bb47da7 85cbf90d88b9 7c9780ea0c5a
files
diffstat 16 files changed, 738 insertions(+), 168 deletions(-) [+]
line wrap: on
line diff
--- a/make/docs/Makefile	Mon May 02 20:11:18 2011 +0100
+++ b/make/docs/Makefile	Mon May 02 20:17:18 2011 +0100
@@ -51,6 +51,7 @@
 DEV_DOCS_URL-6 = http://download.oracle.com/javase/6/docs/index.html
 DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html
 DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
+DOCS_BASE_URL = http://download.oracle.com/javase/7/docs
 
 # Url to Java Language Spec
 #JLS3_URL = http://java.sun.com/docs/books/jls/
@@ -205,7 +206,13 @@
                 -use					\
                 -keywords				\
 		$(ADDITIONAL_JAVADOCFLAGS)
-ADDITIONAL_JAVADOCFLAGS =
+
+ifdef OPENJDK
+  ADDITIONAL_JAVADOCFLAGS =				\
+                -Xdocrootparent $(DOCS_BASE_URL)
+else
+  ADDITIONAL_JAVADOCFLAGS =
+endif
 
 # Draft used for non-fcs documents
 JDK_IS_FCS = false
--- a/src/share/classes/java/beans/DefaultPersistenceDelegate.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/java/beans/DefaultPersistenceDelegate.java	Mon May 02 20:17:18 2011 +0100
@@ -26,6 +26,7 @@
 
 import java.util.*;
 import java.lang.reflect.*;
+import java.util.Objects;
 import sun.reflect.misc.*;
 
 
@@ -181,10 +182,6 @@
         return method;
     }
 
-    private static boolean equals(Object o1, Object o2) {
-        return (o1 == null) ? (o2 == null) : o1.equals(o2);
-    }
-
     private void doProperty(Class type, PropertyDescriptor pd, Object oldInstance, Object newInstance, Encoder out) throws Exception {
         Method getter = pd.getReadMethod();
         Method setter = pd.getWriteMethod();
@@ -195,7 +192,7 @@
             Object oldValue = oldGetExp.getValue();
             Object newValue = newGetExp.getValue();
             out.writeExpression(oldGetExp);
-            if (!equals(newValue, out.get(oldValue))) {
+            if (!Objects.equals(newValue, out.get(oldValue))) {
                 // Search for a static constant with this value;
                 Object e = (Object[])pd.getValue("enumerationValues");
                 if (e instanceof Object[] && Array.getLength(e) % 3 == 0) {
@@ -233,7 +230,7 @@
                 Object oldValue = oldGetExp.getValue();
                 Object newValue = newGetExp.getValue();
                 out.writeExpression(oldGetExp);
-                if (!equals(newValue, out.get(oldValue))) {
+                if (!Objects.equals(newValue, out.get(oldValue))) {
                     out.writeStatement(new Statement(field, "set", new Object[] { oldInstance, oldValue }));
                 }
             }
--- a/src/share/classes/java/beans/MetaData.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/java/beans/MetaData.java	Mon May 02 20:17:18 2011 +0100
@@ -56,6 +56,8 @@
 
 import sun.swing.PrintColorUIResource;
 
+import java.util.Objects;
+
 /*
  * Like the <code>Intropector</code>, the <code>MetaData</code> class
  * contains <em>meta</em> objects that describe the way
@@ -134,7 +136,7 @@
                 Object oldValue = oldGetExp.getValue();
                 Object newValue = newGetExp.getValue();
                 out.writeExpression(oldGetExp);
-                if (!MetaData.equals(newValue, out.get(oldValue))) {
+                if (!Objects.equals(newValue, out.get(oldValue))) {
                     // System.out.println("Not equal: " + newGetExp + " != " + actualGetExp);
                     // invokeStatement(Array.class, "set", new Object[]{oldInstance, index, oldValue}, out);
                     DefaultPersistenceDelegate.invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
@@ -635,7 +637,7 @@
                 Object oldValue = oldGetExp.getValue();
                 Object newValue = newGetExp.getValue();
                 out.writeExpression(oldGetExp);
-                if (!MetaData.equals(newValue, out.get(oldValue))) {
+                if (!Objects.equals(newValue, out.get(oldValue))) {
                     invokeStatement(oldInstance, "set", new Object[]{index, oldValue}, out);
                 }
             }
@@ -675,7 +677,7 @@
                 Object oldValue = oldGetExp.getValue();
                 Object newValue = newGetExp.getValue();
                 out.writeExpression(oldGetExp);
-                if (!MetaData.equals(newValue, out.get(oldValue))) {
+                if (!Objects.equals(newValue, out.get(oldValue))) {
                     invokeStatement(oldInstance, "put", new Object[]{oldKey, oldValue}, out);
                 } else if ((newValue == null) && !newMap.containsKey(oldKey)) {
                     // put oldValue(=null?) if oldKey is absent in newMap
@@ -899,17 +901,17 @@
         if (!(oldInstance instanceof java.awt.Window)) {
             Object oldBackground = c.isBackgroundSet() ? c.getBackground() : null;
             Object newBackground = c2.isBackgroundSet() ? c2.getBackground() : null;
-            if (!MetaData.equals(oldBackground, newBackground)) {
+            if (!Objects.equals(oldBackground, newBackground)) {
                 invokeStatement(oldInstance, "setBackground", new Object[] { oldBackground }, out);
             }
             Object oldForeground = c.isForegroundSet() ? c.getForeground() : null;
             Object newForeground = c2.isForegroundSet() ? c2.getForeground() : null;
-            if (!MetaData.equals(oldForeground, newForeground)) {
+            if (!Objects.equals(oldForeground, newForeground)) {
                 invokeStatement(oldInstance, "setForeground", new Object[] { oldForeground }, out);
             }
             Object oldFont = c.isFontSet() ? c.getFont() : null;
             Object newFont = c2.isFontSet() ? c2.getFont() : null;
-            if (!MetaData.equals(oldFont, newFont)) {
+            if (!Objects.equals(oldFont, newFont)) {
                 invokeStatement(oldInstance, "setFont", new Object[] { oldFont }, out);
             }
         }
@@ -1306,10 +1308,6 @@
         internalPersistenceDelegates.put("java.util.RegularEnumSet", new java_util_EnumSet_PersistenceDelegate());
     }
 
-    /*pp*/ static boolean equals(Object o1, Object o2) {
-        return (o1 == null) ? (o2 == null) : o1.equals(o2);
-    }
-
     public synchronized static PersistenceDelegate getPersistenceDelegate(Class type) {
         if (type == null) {
             return nullPersistenceDelegate;
--- a/src/share/classes/java/lang/StringCoding.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/java/lang/StringCoding.java	Mon May 02 20:17:18 2011 +0100
@@ -222,13 +222,13 @@
                 off = 0;
             }
         }
+        cd.onMalformedInput(CodingErrorAction.REPLACE)
+          .onUnmappableCharacter(CodingErrorAction.REPLACE)
+          .reset();
         if (cd instanceof ArrayDecoder) {
             int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
             return safeTrim(ca, clen, cs, isTrusted);
         } else {
-            cd.onMalformedInput(CodingErrorAction.REPLACE)
-              .onUnmappableCharacter(CodingErrorAction.REPLACE)
-              .reset();
             ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
             CharBuffer cb = CharBuffer.wrap(ca);
             try {
@@ -356,13 +356,13 @@
                 off = 0;
             }
         }
+        ce.onMalformedInput(CodingErrorAction.REPLACE)
+          .onUnmappableCharacter(CodingErrorAction.REPLACE)
+          .reset();
         if (ce instanceof ArrayEncoder) {
             int blen = ((ArrayEncoder)ce).encode(ca, off, len, ba);
             return safeTrim(ba, blen, cs, isTrusted);
         } else {
-            ce.onMalformedInput(CodingErrorAction.REPLACE)
-              .onUnmappableCharacter(CodingErrorAction.REPLACE)
-              .reset();
             ByteBuffer bb = ByteBuffer.wrap(ba);
             CharBuffer cb = CharBuffer.wrap(ca, off, len);
             try {
--- a/src/share/classes/java/net/HttpCookie.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/java/net/HttpCookie.java	Mon May 02 20:17:18 2011 +0100
@@ -34,6 +34,7 @@
 
 import java.lang.NullPointerException;  // for javadoc
 import java.util.Locale;
+import java.util.Objects;
 
 /**
  * An HttpCookie object represents an http cookie, which carries state
@@ -817,7 +818,7 @@
         //   3. and have same path (case-sensitive).
         return equalsIgnoreCase(getName(), other.getName()) &&
                equalsIgnoreCase(getDomain(), other.getDomain()) &&
-               equals(getPath(), other.getPath());
+               Objects.equals(getPath(), other.getPath());
     }
 
 
@@ -1162,14 +1163,6 @@
         return false;
     }
 
-    private static boolean equals(String s, String t) {
-        if (s == t) return true;
-        if ((s != null) && (t != null)) {
-            return s.equals(t);
-        }
-        return false;
-    }
-
     private static boolean startsWithIgnoreCase(String s, String start) {
         if (s == null || start == null) return false;
 
--- a/src/share/classes/java/util/zip/ZipCoder.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/java/util/zip/ZipCoder.java	Mon May 02 20:17:18 2011 +0100
@@ -34,6 +34,8 @@
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 import java.util.Arrays;
+import sun.nio.cs.ArrayDecoder;
+import sun.nio.cs.ArrayEncoder;
 
 /**
  * Utility class for zipfile name and comment decoding and encoding
@@ -47,6 +49,15 @@
         char[] ca = new char[len];
         if (len == 0)
             return new String(ca);
+        // UTF-8 only for now. Other ArrayDeocder only handles
+        // CodingErrorAction.REPLACE mode. ZipCoder uses
+        // REPORT mode.
+        if (isUTF8 && cd instanceof ArrayDecoder) {
+            int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca);
+            if (clen == -1)    // malformed
+                throw new IllegalArgumentException("MALFORMED");
+            return new String(ca, 0, clen);
+        }
         ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
         CharBuffer cb = CharBuffer.wrap(ca);
         CoderResult cr = cd.decode(bb, cb, true);
@@ -69,6 +80,14 @@
         byte[] ba = new byte[len];
         if (len == 0)
             return ba;
+        // UTF-8 only for now. Other ArrayDeocder only handles
+        // CodingErrorAction.REPLACE mode.
+        if (isUTF8 && ce instanceof ArrayEncoder) {
+            int blen = ((ArrayEncoder)ce).encode(ca, 0, ca.length, ba);
+            if (blen == -1)    // malformed
+                throw new IllegalArgumentException("MALFORMED");
+            return Arrays.copyOf(ba, blen);
+        }
         ByteBuffer bb = ByteBuffer.wrap(ba);
         CharBuffer cb = CharBuffer.wrap(ca);
         CoderResult cr = ce.encode(cb, bb, true);
@@ -85,7 +104,7 @@
 
     // assume invoked only if "this" is not utf8
     byte[] getBytesUTF8(String s) {
-        if (isutf8)
+        if (isUTF8)
             return getBytes(s);
         if (utf8 == null)
             utf8 = new ZipCoder(StandardCharset.UTF_8);
@@ -94,7 +113,7 @@
 
 
     String toStringUTF8(byte[] ba, int len) {
-        if (isutf8)
+        if (isUTF8)
             return toString(ba, len);
         if (utf8 == null)
             utf8 = new ZipCoder(StandardCharset.UTF_8);
@@ -102,18 +121,18 @@
     }
 
     boolean isUTF8() {
-        return isutf8;
+        return isUTF8;
     }
 
     private Charset cs;
     private CharsetDecoder dec;
     private CharsetEncoder enc;
-    private boolean isutf8;
+    private boolean isUTF8;
     private ZipCoder utf8;
 
     private ZipCoder(Charset cs) {
         this.cs = cs;
-        this.isutf8 = cs.name().equals(StandardCharset.UTF_8.name());
+        this.isUTF8 = cs.name().equals(StandardCharset.UTF_8.name());
     }
 
     static ZipCoder get(Charset charset) {
--- a/src/share/classes/sun/nio/cs/UTF_8.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/sun/nio/cs/UTF_8.java	Mon May 02 20:17:18 2011 +0100
@@ -32,6 +32,7 @@
 import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CharsetEncoder;
 import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
 
 /* Legal UTF-8 Byte Sequences
  *
@@ -77,7 +78,8 @@
         dst.position(dp - dst.arrayOffset());
     }
 
-    private static class Decoder extends CharsetDecoder {
+    private static class Decoder extends CharsetDecoder
+                                 implements ArrayDecoder {
         private Decoder(Charset cs) {
             super(cs, 1.0f, 1.0f);
         }
@@ -353,9 +355,132 @@
             else
                 return decodeBufferLoop(src, dst);
         }
+
+        private static ByteBuffer getByteBuffer(ByteBuffer bb, byte[] ba, int sp)
+        {
+            if (bb == null)
+                bb = ByteBuffer.wrap(ba);
+            bb.position(sp);
+            return bb;
+        }
+
+        // returns -1 if there is malformed byte(s) and the
+        // "action" for malformed input is not REPLACE.
+        public int decode(byte[] sa, int sp, int len, char[] da) {
+            final int sl = sp + len;
+            int dp = 0;
+            int dlASCII = Math.min(len, da.length);
+            ByteBuffer bb = null;  // only necessary if malformed
+
+            // ASCII only optimized loop
+            while (dp < dlASCII && sa[sp] >= 0)
+                da[dp++] = (char) sa[sp++];
+
+            while (sp < sl) {
+                int b1 = sa[sp++];
+                if (b1 >= 0) {
+                    // 1 byte, 7 bits: 0xxxxxxx
+                    da[dp++] = (char) b1;
+                } else if ((b1 >> 5) == -2) {
+                    // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
+                    if (sp < sl) {
+                        int b2 = sa[sp++];
+                        if (isMalformed2(b1, b2)) {
+                            if (malformedInputAction() != CodingErrorAction.REPLACE)
+                                return -1;
+                            da[dp++] = replacement().charAt(0);
+                            sp--;            // malformedN(bb, 2) always returns 1
+                        } else {
+                            da[dp++] = (char) (((b1 << 6) ^ b2)^
+                                           (((byte) 0xC0 << 6) ^
+                                            ((byte) 0x80 << 0)));
+                        }
+                        continue;
+                    }
+                    if (malformedInputAction() != CodingErrorAction.REPLACE)
+                        return -1;
+                    da[dp++] = replacement().charAt(0);
+                    return dp;
+                } else if ((b1 >> 4) == -2) {
+                    // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
+                    if (sp + 1 < sl) {
+                        int b2 = sa[sp++];
+                        int b3 = sa[sp++];
+                        if (isMalformed3(b1, b2, b3)) {
+                            if (malformedInputAction() != CodingErrorAction.REPLACE)
+                                return -1;
+                            da[dp++] = replacement().charAt(0);
+                            sp -=3;
+                            bb = getByteBuffer(bb, sa, sp);
+                            sp += malformedN(bb, 3).length();
+                        } else {
+                            da[dp++] = (char)((b1 << 12) ^
+                                              (b2 <<  6) ^
+                                              (b3 ^
+                                              (((byte) 0xE0 << 12) ^
+                                              ((byte) 0x80 <<  6) ^
+                                              ((byte) 0x80 <<  0))));
+                        }
+                        continue;
+                    }
+                    if (malformedInputAction() != CodingErrorAction.REPLACE)
+                        return -1;
+                    da[dp++] = replacement().charAt(0);
+                    return dp;
+                } else if ((b1 >> 3) == -2) {
+                    // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+                    if (sp + 2 < sl) {
+                        int b2 = sa[sp++];
+                        int b3 = sa[sp++];
+                        int b4 = sa[sp++];
+                        int uc = ((b1 << 18) ^
+                                  (b2 << 12) ^
+                                  (b3 <<  6) ^
+                                  (b4 ^
+                                   (((byte) 0xF0 << 18) ^
+                                   ((byte) 0x80 << 12) ^
+                                   ((byte) 0x80 <<  6) ^
+                                   ((byte) 0x80 <<  0))));
+                        if (isMalformed4(b2, b3, b4) ||
+                            // shortest form check
+                            !Character.isSupplementaryCodePoint(uc)) {
+                            if (malformedInputAction() != CodingErrorAction.REPLACE)
+                                return -1;
+                            da[dp++] = replacement().charAt(0);
+                            sp -= 4;
+                            bb = getByteBuffer(bb, sa, sp);
+                            sp += malformedN(bb, 4).length();
+                        } else {
+                            da[dp++] = Character.highSurrogate(uc);
+                            da[dp++] = Character.lowSurrogate(uc);
+                        }
+                        continue;
+                    }
+                    if (malformedInputAction() != CodingErrorAction.REPLACE)
+                        return -1;
+                    da[dp++] = replacement().charAt(0);
+                    return dp;
+                } else {
+                    if (malformedInputAction() != CodingErrorAction.REPLACE)
+                        return -1;
+                    da[dp++] = replacement().charAt(0);
+                    sp--;
+                    bb = getByteBuffer(bb, sa, sp);
+                    CoderResult cr = malformedN(bb, 1);
+                    if (!cr.isError()) {
+                        // leading byte for 5 or 6-byte, but don't have enough
+                        // bytes in buffer to check. Consumed rest as malformed.
+                        return dp;
+                    }
+                    sp +=  cr.length();
+                }
+            }
+            return dp;
+        }
     }
 
-    private static class Encoder extends CharsetEncoder {
+    private static class Encoder extends CharsetEncoder
+                                 implements ArrayEncoder {
 
         private Encoder(Charset cs) {
             super(cs, 1.1f, 3.0f);
@@ -495,5 +620,50 @@
             else
                 return encodeBufferLoop(src, dst);
         }
+
+        // returns -1 if there is malformed char(s) and the
+        // "action" for malformed input is not REPLACE.
+        public int encode(char[] sa, int sp, int len, byte[] da) {
+            int sl = sp + len;
+            int dp = 0;
+            int dlASCII = dp + Math.min(len, da.length);
+
+            // ASCII only optimized loop
+            while (dp < dlASCII && sa[sp] < '\u0080')
+                da[dp++] = (byte) sa[sp++];
+
+            while (sp < sl) {
+                char c = sa[sp++];
+                if (c < 0x80) {
+                    // Have at most seven bits
+                    da[dp++] = (byte)c;
+                } else if (c < 0x800) {
+                    // 2 bytes, 11 bits
+                    da[dp++] = (byte)(0xc0 | (c >> 6));
+                    da[dp++] = (byte)(0x80 | (c & 0x3f));
+                } else if (Character.isSurrogate(c)) {
+                    if (sgp == null)
+                        sgp = new Surrogate.Parser();
+                    int uc = sgp.parse(c, sa, sp - 1, sl);
+                    if (uc < 0) {
+                        if (malformedInputAction() != CodingErrorAction.REPLACE)
+                            return -1;
+                        da[dp++] = replacement()[0];
+                    } else {
+                        da[dp++] = (byte)(0xf0 | ((uc >> 18)));
+                        da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
+                        da[dp++] = (byte)(0x80 | ((uc >>  6) & 0x3f));
+                        da[dp++] = (byte)(0x80 | (uc & 0x3f));
+                        sp++;  // 2 chars
+                    }
+                } else {
+                    // 3 bytes, 16 bits
+                    da[dp++] = (byte)(0xe0 | ((c >> 12)));
+                    da[dp++] = (byte)(0x80 | ((c >>  6) & 0x3f));
+                    da[dp++] = (byte)(0x80 | (c & 0x3f));
+                }
+            }
+            return dp;
+        }
     }
 }
--- a/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/sun/security/jgss/spnego/NegTokenInit.java	Mon May 02 20:17:18 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -152,75 +152,50 @@
                                 "did not have the Sequence tag");
             }
 
-            // parse SEQUENCE of mechTypes, if present
-            if (tmp1.data.available() > 0) {
+            // parse various fields if present
+            int lastField = -1;
+            while (tmp1.data.available() > 0) {
                 DerValue tmp2 = tmp1.data.getDerValue();
-                if (!tmp2.isContextSpecific((byte)0x00)) {
-                    throw new IOException("SPNEGO NegoTokenInit : " +
-                        "did not have the right context tag for mechTypes");
-                }
-                // get the DER-encoded sequence of mechTypes
-                DerInputStream mValue = tmp2.data;
-                mechTypes = mValue.toByteArray();
+                if (tmp2.isContextSpecific((byte)0x00)) {
+                    // get the DER-encoded sequence of mechTypes
+                    lastField = checkNextField(lastField, 0);
+                    DerInputStream mValue = tmp2.data;
+                    mechTypes = mValue.toByteArray();
 
-                // read all the mechTypes
-                DerValue[] mList = mValue.getSequence(0);
-                mechTypeList = new Oid[mList.length];
-                ObjectIdentifier mech = null;
-                for (int i = 0; i < mList.length; i++) {
-                    mech = mList[i].getOID();
+                    // read all the mechTypes
+                    DerValue[] mList = mValue.getSequence(0);
+                    mechTypeList = new Oid[mList.length];
+                    ObjectIdentifier mech = null;
+                    for (int i = 0; i < mList.length; i++) {
+                        mech = mList[i].getOID();
+                        if (DEBUG) {
+                            System.out.println("SpNegoToken NegTokenInit: " +
+                                    "reading Mechanism Oid = " + mech);
+                        }
+                        mechTypeList[i] = new Oid(mech.toString());
+                    }
+                } else if (tmp2.isContextSpecific((byte)0x01)) {
+                    lastField = checkNextField(lastField, 1);
+                    // received reqFlags, skip it
+                } else if (tmp2.isContextSpecific((byte)0x02)) {
+                    lastField = checkNextField(lastField, 2);
                     if (DEBUG) {
                         System.out.println("SpNegoToken NegTokenInit: " +
-                                "reading Mechanism Oid = " + mech);
+                                            "reading Mech Token");
                     }
-                    mechTypeList[i] = new Oid(mech.toString());
-                }
-            }
-
-            // parse mechToken, if present (skip reqFlags)
-            if (tmp1.data.available() > 0) {
-                DerValue tmp3 = tmp1.data.getDerValue();
-                if (tmp3.isContextSpecific((byte)0x01)) {
-                    // received reqFlags, skip it
-                    // now parse next field mechToken
-                    if (tmp1.data.available() > 0) {
-                        tmp3 = tmp1.data.getDerValue();
+                    mechToken = tmp2.data.getOctetString();
+                } else if (tmp2.isContextSpecific((byte)0x03)) {
+                    lastField = checkNextField(lastField, 3);
+                    if (!GSSUtil.useMSInterop()) {
+                        mechListMIC = tmp2.data.getOctetString();
+                        if (DEBUG) {
+                            System.out.println("SpNegoToken NegTokenInit: " +
+                                    "MechListMIC Token = " +
+                                    getHexBytes(mechListMIC));
+                        }
                     }
                 }
-                if (!tmp3.isContextSpecific((byte)0x02)) {
-                    throw new IOException("SPNEGO NegoTokenInit : " +
-                        "did not have the right context tag for mechToken");
-                }
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenInit: " +
-                                        "reading Mech Token");
-                }
-                mechToken = tmp3.data.getOctetString();
             }
-
-            // parse mechListMIC, if present and not in MS interop mode
-            if (!GSSUtil.useMSInterop() && (tmp1.data.available() > 0)) {
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenInit: " +
-                                        "receiving MechListMIC");
-                }
-                DerValue tmp6 = tmp1.data.getDerValue();
-                if (!tmp6.isContextSpecific((byte)0x03)) {
-                    throw new IOException("SPNEGO NegoTokenInit : " +
-                        "did not have the right context tag for MICToken");
-                }
-                mechListMIC = tmp6.data.getOctetString();
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenInit: " +
-                        "MechListMIC Token = " + getHexBytes(mechListMIC));
-                }
-            } else {
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenInit : " +
-                                        "no MIC token included");
-                }
-            }
-
         } catch (IOException e) {
             throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
                 "Invalid SPNEGO NegTokenInit token : " + e.getMessage());
--- a/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/sun/security/jgss/spnego/NegTokenTarg.java	Mon May 02 20:17:18 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -153,69 +153,40 @@
                         "did not have the Sequence tag");
             }
 
-            // parse negResult, if present
-            if (tmp1.data.available() > 0) {
+            // parse various fields if present
+            int lastField = -1;
+            while (tmp1.data.available() > 0) {
                 DerValue tmp2 = tmp1.data.getDerValue();
-                if (!tmp2.isContextSpecific((byte)0x00)) {
-                        throw new IOException("SPNEGO NegoTokenTarg : " +
-                        "did not have the right context tag for negResult");
-                }
-                negResult = tmp2.data.getEnumerated();
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenTarg: negotiated" +
-                                " result = " + getNegoResultString(negResult));
-                }
-            }
-
-            // parse supportedMech, if present
-            if (tmp1.data.available() > 0) {
-                DerValue tmp3 = tmp1.data.getDerValue();
-                if (!tmp3.isContextSpecific((byte)0x01)) {
-                    throw new IOException("SPNEGO NegoTokenTarg : " +
-                        "did not have the right context tag for supportedMech");
-                }
-                ObjectIdentifier mech = tmp3.data.getOID();
-                supportedMech = new Oid(mech.toString());
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenTarg: " +
-                                "supported mechanism = " + supportedMech);
+                if (tmp2.isContextSpecific((byte)0x00)) {
+                    lastField = checkNextField(lastField, 0);
+                    negResult = tmp2.data.getEnumerated();
+                    if (DEBUG) {
+                        System.out.println("SpNegoToken NegTokenTarg: negotiated" +
+                                    " result = " + getNegoResultString(negResult));
+                    }
+                } else if (tmp2.isContextSpecific((byte)0x01)) {
+                    lastField = checkNextField(lastField, 1);
+                    ObjectIdentifier mech = tmp2.data.getOID();
+                    supportedMech = new Oid(mech.toString());
+                    if (DEBUG) {
+                        System.out.println("SpNegoToken NegTokenTarg: " +
+                                    "supported mechanism = " + supportedMech);
+                    }
+                } else if (tmp2.isContextSpecific((byte)0x02)) {
+                    lastField = checkNextField(lastField, 2);
+                    responseToken = tmp2.data.getOctetString();
+                } else if (tmp2.isContextSpecific((byte)0x03)) {
+                    lastField = checkNextField(lastField, 3);
+                    if (!GSSUtil.useMSInterop()) {
+                        mechListMIC = tmp2.data.getOctetString();
+                        if (DEBUG) {
+                            System.out.println("SpNegoToken NegTokenTarg: " +
+                                                "MechListMIC Token = " +
+                                                getHexBytes(mechListMIC));
+                        }
+                    }
                 }
             }
-
-            // parse ResponseToken, if present
-            if (tmp1.data.available() > 0) {
-                DerValue tmp4 = tmp1.data.getDerValue();
-                if (!tmp4.isContextSpecific((byte)0x02)) {
-                    throw new IOException("SPNEGO NegoTokenTarg : did not" +
-                        " have the right context tag for response token");
-                }
-                responseToken = tmp4.data.getOctetString();
-            }
-
-            // parse mechListMIC if present and not in MS interop
-            if (!GSSUtil.useMSInterop() && (tmp1.data.available() > 0)) {
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenTarg: " +
-                                                "receiving MechListMIC");
-                }
-                DerValue tmp5 = tmp1.data.getDerValue();
-                if (!tmp5.isContextSpecific((byte)0x03)) {
-                    throw new IOException("SPNEGO NegoTokenTarg : " +
-                        "did not have the right context tag for mechListMIC");
-                }
-                mechListMIC = tmp5.data.getOctetString();
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenTarg: " +
-                                        "MechListMIC Token = " +
-                                        getHexBytes(mechListMIC));
-                }
-            } else {
-                if (DEBUG) {
-                    System.out.println("SpNegoToken NegTokenTarg : " +
-                                        "no MIC token included");
-                }
-            }
-
         } catch (IOException e) {
             throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
                 "Invalid SPNEGO NegTokenTarg token : " + e.getMessage());
--- a/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java	Mon May 02 20:11:18 2011 +0100
+++ b/src/share/classes/sun/security/jgss/spnego/SpNegoToken.java	Mon May 02 20:17:18 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -187,4 +187,21 @@
                 return ("Unknown Negotiated Result: " + result);
         }
     }
+
+    /**
+     * Checks if the context tag in a sequence is in correct order. The "last"
+     * value must be smaller than "current".
+     * @param last the last tag seen
+     * @param current the current tag
+     * @return the current tag, used as the next value for last
+     * @throws GSSException if there's a wrong order
+     */
+    static int checkNextField(int last, int current) throws GSSException {
+        if (last < current) {
+            return current;
+        } else {
+            throw new GSSException(GSSException.DEFECTIVE_TOKEN, -1,
+                "Invalid SpNegoToken token : wrong order");
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/nio/cs/StrCodingBenchmarkUTF8.java	Mon May 02 20:17:18 2011 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.*;
+import java.nio.*;
+import java.nio.charset.*;
+
+public class StrCodingBenchmarkUTF8 {
+
+    public static void main(String[] args) throws Throwable {
+
+        final int itrs = Integer.getInteger("iterations", 100000);
+        final int size = 2048;
+        final int subsize    = Integer.getInteger("subsize", 128);
+        final Random rnd = new Random();
+        final int maxchar    = 0x7f;
+
+        Charset charset = Charset.forName("UTF-8");
+        final String csn = charset.name();
+        final Charset cs = charset;
+
+        int[] starts = new int[] { 0, 0x80, 0x800, 0x10000};
+        for (int nb = 1; nb <= 4; nb++) {
+
+            final CharsetEncoder enc = cs.newEncoder();
+
+            char[] cc = new char[size];
+            int i = 0;
+            while (i < size - 3) {
+                i += Character.toChars(starts[nb - 1] + rnd.nextInt(maxchar), cc, i);
+            }
+
+            final String string = new String(cc);
+            final byte[] bytes  = string.getBytes(cs);
+
+            System.out.printf("%n--------%s[nb=%d]---------%n", csn, nb);
+            int sz = 12;
+            while (sz < size) {
+                System.out.printf("   [len=%d]%n", sz);
+                final byte[] bs  = Arrays.copyOf(bytes, sz);
+                final String str = new String(bs, csn);
+                StrCodingBenchmark.Job[] jobs = {
+                    new StrCodingBenchmark.Job("String decode: csn") {
+                    public void work() throws Throwable {
+                        for (int i = 0; i < itrs; i++)
+                            new String(bs, csn);
+                    }},
+
+                    new StrCodingBenchmark.Job("String decode: cs") {
+                    public void work() throws Throwable {
+                        for (int i = 0; i < itrs; i++)
+                            new String(bs, cs);
+                    }},
+
+                    new StrCodingBenchmark.Job("String encode: csn") {
+                    public void work() throws Throwable {
+                        for (int i = 0; i < itrs; i++)
+                                str.getBytes(csn);
+                    }},
+
+                    new StrCodingBenchmark.Job("String encode: cs") {
+                    public void work() throws Throwable {
+                         for (int i = 0; i < itrs; i++)
+                          str.getBytes(cs);
+                    }},
+                };
+                StrCodingBenchmark.time(StrCodingBenchmark.filter(null, jobs));
+                sz <<= 1;
+            }
+        }
+    }
+}
--- a/test/sun/nio/cs/TestStringCoding.java	Mon May 02 20:11:18 2011 +0100
+++ b/test/sun/nio/cs/TestStringCoding.java	Mon May 02 20:17:18 2011 +0100
@@ -24,7 +24,7 @@
  */
 
 /* @test
-   @bug 6636323 6636319
+   @bug 6636323 6636319 7040220
    @summary Test if StringCoding and NIO result have the same de/encoding result
  * @run main/othervm/timeout=2000 TestStringCoding
  */
@@ -111,6 +111,8 @@
         //encode unmappable surrogates
         if (enc instanceof sun.nio.cs.ArrayEncoder &&
             cs.contains(Charset.forName("ASCII"))) {
+            if (cs.name().equals("UTF-8"))    // utf8 handles surrogates
+                return;
             enc.replaceWith(new byte[] { (byte)'A'});
             sun.nio.cs.ArrayEncoder cae = (sun.nio.cs.ArrayEncoder)enc;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/nio/cs/TestStringCodingUTF8.java	Mon May 02 20:17:18 2011 +0100
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 7040220
+   @summary Test if StringCoding and NIO result have the same de/encoding result for UTF-8
+ * @run main/othervm/timeout=2000 TestStringCodingUTF8
+ */
+
+import java.util.*;
+import java.nio.*;
+import java.nio.charset.*;
+
+public class TestStringCodingUTF8 {
+    public static void main(String[] args) throws Throwable {
+        test();
+        // security manager on
+        System.setSecurityManager(new PermissiveSecurityManger());
+        test();
+    }
+
+    static void test() throws Throwable {
+        Charset cs = Charset.forName("UTF-8");
+        char[] bmp = new char[0x10000];
+        for (int i = 0; i < 0x10000; i++) {
+            bmp[i] = (char)i;
+        }
+        test(cs, bmp, 0, bmp.length);
+
+        ArrayList<Integer> list = new ArrayList<>(0x20000);
+        for (int i = 0; i < 0x20000; i++) {
+            list.add(i, i);
+        }
+        Collections.shuffle(list);
+        int j = 0;
+        char[] bmpsupp = new char[0x30000];
+        for (int i = 0; i < 0x20000; i++) {
+            j += Character.toChars(list.get(i), bmpsupp, j);
+        }
+        assert (j == bmpsupp.length);
+        test(cs, bmpsupp, 0, bmpsupp.length);
+
+        // randomed "off" and "len" on shuffled data
+        Random rnd = new Random();
+        int maxlen = 1000;
+        int itr = 5000;
+        for (int i = 0; i < itr; i++) {
+            int off = rnd.nextInt(bmpsupp.length - maxlen);
+            int len = rnd.nextInt(maxlen);
+            test(cs, bmpsupp, off, len);
+        }
+
+        // random length of bytes, test the edge corner case
+        for (int i = 0; i < itr; i++) {
+            byte[] ba = new byte[rnd.nextInt(maxlen)];
+            rnd.nextBytes(ba);
+            //new String(csn);
+            if (!new String(ba, cs.name()).equals(
+                 new String(decode(cs, ba, 0, ba.length))))
+                throw new RuntimeException("new String(csn) failed");
+            //new String(cs);
+            if (!new String(ba, cs).equals(
+                 new String(decode(cs, ba, 0, ba.length))))
+                throw new RuntimeException("new String(cs) failed");
+        }
+        System.out.println("done!");
+    }
+
+    static void test(Charset cs, char[] ca, int off, int len) throws Throwable {
+        String str = new String(ca, off, len);
+        byte[] ba = encode(cs, ca, off, len);
+
+        //getBytes(csn);
+        byte[] baStr = str.getBytes(cs.name());
+        if (!Arrays.equals(ba, baStr))
+            throw new RuntimeException("getBytes(csn) failed");
+
+        //getBytes(cs);
+        baStr = str.getBytes(cs);
+        if (!Arrays.equals(ba, baStr))
+            throw new RuntimeException("getBytes(cs) failed");
+
+        //new String(csn);
+        if (!new String(ba, cs.name()).equals(new String(decode(cs, ba, 0, ba.length))))
+            throw new RuntimeException("new String(csn) failed");
+
+        //new String(cs);
+        if (!new String(ba, cs).equals(new String(decode(cs, ba, 0, ba.length))))
+            throw new RuntimeException("new String(cs) failed");
+    }
+
+    // copy/paste of the StringCoding.decode()
+    static char[] decode(Charset cs, byte[] ba, int off, int len) {
+        CharsetDecoder cd = cs.newDecoder();
+        int en = (int)(len * cd.maxCharsPerByte());
+        char[] ca = new char[en];
+        if (len == 0)
+            return ca;
+        cd.onMalformedInput(CodingErrorAction.REPLACE)
+          .onUnmappableCharacter(CodingErrorAction.REPLACE)
+          .reset();
+
+        ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        try {
+            CoderResult cr = cd.decode(bb, cb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = cd.flush(cb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            throw new Error(x);
+        }
+        return Arrays.copyOf(ca, cb.position());
+    }
+
+    // copy/paste of the StringCoding.encode()
+    static byte[] encode(Charset cs, char[] ca, int off, int len) {
+        CharsetEncoder ce = cs.newEncoder();
+        int en = (int)(len * ce.maxBytesPerChar());
+        byte[] ba = new byte[en];
+        if (len == 0)
+            return ba;
+        ce.onMalformedInput(CodingErrorAction.REPLACE)
+          .onUnmappableCharacter(CodingErrorAction.REPLACE)
+          .reset();
+        ByteBuffer bb = ByteBuffer.wrap(ba);
+        CharBuffer cb = CharBuffer.wrap(ca, off, len);
+        try {
+            CoderResult cr = ce.encode(cb, bb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = ce.flush(bb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            throw new Error(x);
+        }
+        return Arrays.copyOf(ba, bb.position());
+    }
+
+    static class PermissiveSecurityManger extends SecurityManager {
+        @Override public void checkPermission(java.security.Permission p) {}
+    }
+}
--- a/test/sun/nio/cs/TestUTF8.java	Mon May 02 20:11:18 2011 +0100
+++ b/test/sun/nio/cs/TestUTF8.java	Mon May 02 20:17:18 2011 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4486841
+ * @bug 4486841 7040220
  * @summary Test UTF-8 charset
  */
 
@@ -70,6 +70,32 @@
         return dec.decode(bbf, cbf, true);
     }
 
+    // copy/paste of the StringCoding.decode()
+    static char[] decode(Charset cs, byte[] ba, int off, int len) {
+        CharsetDecoder cd = cs.newDecoder();
+        int en = (int)(len * cd.maxCharsPerByte());
+        char[] ca = new char[en];
+        if (len == 0)
+            return ca;
+        cd.onMalformedInput(CodingErrorAction.REPLACE)
+          .onUnmappableCharacter(CodingErrorAction.REPLACE)
+          .reset();
+
+        ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
+        CharBuffer cb = CharBuffer.wrap(ca);
+        try {
+            CoderResult cr = cd.decode(bb, cb, true);
+            if (!cr.isUnderflow())
+                cr.throwException();
+            cr = cd.flush(cb);
+            if (!cr.isUnderflow())
+                cr.throwException();
+        } catch (CharacterCodingException x) {
+            throw new Error(x);
+        }
+        return Arrays.copyOf(ca, cb.position());
+    }
+
     static byte[] encode(char[] cc, String csn, boolean testDirect)
         throws Exception {
         ByteBuffer bbf;
@@ -142,7 +168,14 @@
         bb = encode(cc, csn, true);
         ccO = decode(bb, csn, true);
         if (!Arrays.equals(cc, ccO)) {
-            System.out.printf("    (direct) failed");
+            System.out.print("    (direct) failed");
+        }
+        // String.getBytes()/toCharArray() goes to ArrayDe/Encoder path
+        if (!Arrays.equals(bb, new String(cc).getBytes(csn))) {
+            System.out.printf("    String.getBytes() failed");
+        }
+        if (!Arrays.equals(cc, new String(bb, csn).toCharArray())) {
+            System.out.printf("    String.toCharArray() failed");
         }
         System.out.println();
     }
@@ -168,6 +201,12 @@
         if (!Arrays.equals(cc, ccO)) {
             System.out.printf("    decoding(direct) failed%n");
         }
+        // new String(bb, csn).getBytes(csn) will not return
+        // the 6 bytes surrogates as in bb, so only test
+        // toCharArray() here.
+        if (!Arrays.equals(cc, new String(bb, csn).toCharArray())) {
+            System.out.printf("    String.toCharArray() failed");
+        }
     }
 
     static void compare(String csn1, String csn2) throws Exception {
@@ -274,6 +313,7 @@
     static void checkMalformed(String csn) throws Exception {
         boolean failed = false;
         System.out.printf("    Check malformed <%s>...%n", csn);
+        Charset cs = Charset.forName(csn);
         for (boolean direct: new boolean[] {false, true}) {
             for (byte[] bins : malformed) {
                 int mlen = bins[0];
@@ -285,10 +325,15 @@
                         ashex += Integer.toBinaryString((int)bin[i] & 0xff);
                 }
                 if (!cr.isMalformed()) {
-                    System.out.printf("        FAIL(direct=%b): [%s] not malformed.\n", direct, ashex);
+                    System.out.printf("        FAIL(direct=%b): [%s] not malformed.%n", direct, ashex);
                     failed = true;
                 } else if (cr.length() != mlen) {
-                    System.out.printf("        FAIL(direct=%b): [%s] malformed[len=%d].\n", direct, ashex, cr.length());
+                    System.out.printf("        FAIL(direct=%b): [%s] malformed[len=%d].%n", direct, ashex, cr.length());
+                    failed = true;
+                }
+                if (!Arrays.equals(decode(cs, bin, 0, bin.length),
+                                   new String(bin, csn).toCharArray())) {
+                    System.out.printf("        FAIL(new String(bb, %s)) failed%n", csn);
                     failed = true;
                 }
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/jgss/spnego/NegTokenTargFields.java	Mon May 02 20:17:18 2011 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7040151
+ * @summary SPNEGO GSS code does not parse tokens in accordance to RFC 2478
+ * @compile -XDignore.symbol.file NegTokenTargFields.java
+ * @run main NegTokenTargFields nomech
+ * @run main/fail NegTokenTargFields badorder
+ */
+
+import sun.security.jgss.spnego.NegTokenTarg;
+
+public class NegTokenTargFields {
+
+    // A hand-crafted NegTokenTarg with negResult and responseToken only
+    public static byte[] nomech = {
+        (byte)0xA1, (byte)0x0F, (byte)0x30, (byte)0x0D,
+        (byte)0xA0, (byte)0x03, (byte)0x0A, (byte)0x01,
+        (byte)0x02, (byte)0xA2, (byte)0x02, (byte)0x04,
+        (byte)0x00, (byte)0xA3, (byte)0x02, (byte)0x04,
+        (byte)0x00,
+    };
+
+    // A hand-crafted NegTokenTarg with negResult and supportedMech in wrong order
+    public static byte[] badorder = {
+        (byte)0xA1, (byte)0x1E, (byte)0x30, (byte)0x1C,
+        (byte)0xA1, (byte)0x0B, (byte)0x06, (byte)0x09,
+        (byte)0x2A, (byte)0x86, (byte)0x48, (byte)0x86,
+        (byte)0xF7, (byte)0x12, (byte)0x01, (byte)0x02,
+        (byte)0x02, (byte)0xA0, (byte)0x03, (byte)0x0A,
+        (byte)0x01, (byte)0x00, (byte)0xA2, (byte)0x03,
+        (byte)0x04, (byte)0x01, (byte)0x00, (byte)0xA3,
+        (byte)0x03, (byte)0x04, (byte)0x01, (byte)0x00,
+    };
+
+    public static void main(String[] args) throws Exception {
+        byte[] buf = (byte[])NegTokenTargFields.class.getField(args[0]).get(null);
+        new NegTokenTarg(buf);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/security/krb5/auto/SPNEGO.java	Mon May 02 20:17:18 2011 +0100
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7040151
+ * @summary SPNEGO GSS code does not parse tokens in accordance to RFC 2478
+ * @compile -XDignore.symbol.file SPNEGO.java
+ * @run main/othervm SPNEGO
+ */
+
+import sun.security.jgss.GSSUtil;
+
+// The basic krb5 test skeleton you can copy from
+public class SPNEGO {
+
+    public static void main(String[] args) throws Exception {
+
+        new OneKDC(null).writeJAASConf();
+
+        Context c, s;
+        c = Context.fromJAAS("client");
+        s = Context.fromJAAS("server");
+
+        c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_SPNEGO_MECH_OID);
+        s.startAsServer(GSSUtil.GSS_SPNEGO_MECH_OID);
+
+        Context.handshake(c, s);
+
+        Context.transmit("i say high --", c, s);
+        Context.transmit("   you say low", s, c);
+
+        s.dispose();
+        c.dispose();
+    }
+}