From 64c60db32c6536df601bec1ad0da38b4400891a0 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Mon, 15 Nov 2010 14:32:49 -0800 Subject: [PATCH 1/5] 6848930: JSN security test jce/Global/Cipher/PKCS5Padding cannot thrown expected BadPaddingException Disabled CKM_DES_CBC_PAD, CKM_DES3_CBC_PAD, CKM_AES_CBC_PAD mechs by default and use our own internal padding impl. Reviewed-by: wetmore --- jdk/src/share/lib/security/sunpkcs11-solaris.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg index 4ceccc3d08d..d0b34ca134d 100644 --- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg +++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg @@ -31,5 +31,9 @@ disabledMechanisms = { CKM_SHA256_RSA_PKCS CKM_SHA384_RSA_PKCS CKM_SHA512_RSA_PKCS +# the following mechanisms are disabled to ensure backward compatibility (Solaris bug 6545046) + CKM_DES_CBC_PAD + CKM_DES3_CBC_PAD + CKM_AES_CBC_PAD } From 0ec3c185d5723e0bf6522923af4a12cae1534392 Mon Sep 17 00:00:00 2001 From: Valerie Peng Date: Mon, 15 Nov 2010 14:38:41 -0800 Subject: [PATCH 2/5] 6687725: Internal PKCS5Padding impl should throw IllegalBlockSizeException and not BadPaddingException Changed to throw IllegalBlockSizeException when the data length isn't multiples of block size Reviewed-by: wetmore --- .../sun/security/pkcs11/P11Cipher.java | 9 +- .../pkcs11/Cipher/TestPKCS5PaddingError.java | 132 ++++++++++++++++++ 2 files changed, 137 insertions(+), 4 deletions(-) create mode 100644 jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java index 1ea39e799d1..5568887a5f6 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java @@ -74,7 +74,7 @@ final class P11Cipher extends CipherSpi { // DEC: return the length of trailing padding bytes given the specified // padded data int unpad(byte[] paddedData, int len) - throws BadPaddingException; + throws BadPaddingException, IllegalBlockSizeException; } private static class PKCS5Padding implements Padding { @@ -96,9 +96,10 @@ final class P11Cipher extends CipherSpi { } public int unpad(byte[] paddedData, int len) - throws BadPaddingException { - if (len < 1 || len > paddedData.length) { - throw new BadPaddingException("Invalid pad array length!"); + throws BadPaddingException, IllegalBlockSizeException { + if ((len < 1) || (len % blockSize != 0)) { + throw new IllegalBlockSizeException + ("Input length must be multiples of " + blockSize); } byte padValue = paddedData[len - 1]; if (padValue < 1 || padValue > blockSize) { diff --git a/jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java b/jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java new file mode 100644 index 00000000000..f0721daa2e5 --- /dev/null +++ b/jdk/test/sun/security/pkcs11/Cipher/TestPKCS5PaddingError.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 6687725 + * @summary Test internal PKCS5Padding impl with various error conditions. + * @author Valerie Peng + * @library .. + */ +import java.io.*; +import java.nio.*; +import java.util.*; + +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; + +public class TestPKCS5PaddingError extends PKCS11Test { + private static class CI { // class for holding Cipher Information + String transformation; + String keyAlgo; + + CI(String transformation, String keyAlgo) { + this.transformation = transformation; + this.keyAlgo = keyAlgo; + } + } + + private static final CI[] TEST_LIST = { + // algorithms which use the native padding impl + new CI("DES/CBC/PKCS5Padding", "DES"), + new CI("DESede/CBC/PKCS5Padding", "DESede"), + new CI("AES/CBC/PKCS5Padding", "AES"), + // algorithms which use SunPKCS11's own padding impl + new CI("DES/ECB/PKCS5Padding", "DES"), + new CI("DESede/ECB/PKCS5Padding", "DESede"), + new CI("AES/ECB/PKCS5Padding", "AES"), + }; + + private static StringBuffer debugBuf = new StringBuffer(); + + public void main(Provider p) throws Exception { + boolean status = true; + Random random = new Random(); + + try { + byte[] plainText = new byte[200]; + + for (int i = 0; i < TEST_LIST.length; i++) { + CI currTest = TEST_LIST[i]; + System.out.println("===" + currTest.transformation + "==="); + try { + KeyGenerator kg = + KeyGenerator.getInstance(currTest.keyAlgo, p); + SecretKey key = kg.generateKey(); + Cipher c1 = Cipher.getInstance(currTest.transformation, + "SunJCE"); + c1.init(Cipher.ENCRYPT_MODE, key); + byte[] cipherText = c1.doFinal(plainText); + AlgorithmParameters params = c1.getParameters(); + Cipher c2 = Cipher.getInstance(currTest.transformation, p); + c2.init(Cipher.DECRYPT_MODE, key, params); + + // 1st test: wrong output length + // NOTE: Skip NSS since it reports CKR_DEVICE_ERROR when + // the data passed to its EncryptUpdate/DecryptUpdate is + // not multiple of blocks + if (!p.getName().equals("SunPKCS11-NSS")) { + try { + System.out.println("Testing with wrong cipherText length"); + c2.doFinal(cipherText, 0, cipherText.length - 2); + } catch (IllegalBlockSizeException ibe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + } + // 2nd test: wrong padding value + try { + System.out.println("Testing with wrong padding bytes"); + cipherText[cipherText.length - 1]++; + c2.doFinal(cipherText); + } catch (BadPaddingException bpe) { + // expected + } catch (Exception ex) { + System.out.println("Error: Unexpected Ex " + ex); + ex.printStackTrace(); + } + System.out.println("DONE"); + } catch (NoSuchAlgorithmException nsae) { + System.out.println("Skipping unsupported algorithm: " + + nsae); + } + } + } catch (Exception ex) { + // print out debug info when exception is encountered + if (debugBuf != null) { + System.out.println(debugBuf.toString()); + debugBuf = new StringBuffer(); + } + throw ex; + } + } + + public static void main(String[] args) throws Exception { + main(new TestPKCS5PaddingError()); + } +} From e4d948e846fe03fb2e124fa96d7bae5f34f257ff Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 17 Nov 2010 14:29:51 +0000 Subject: [PATCH 3/5] 6725892: Http server stability issues Reviewed-by: chegar --- .../sun/net/httpserver/HttpsConfigurator.java | 2 + .../sun/net/httpserver/HttpsParameters.java | 4 + .../net/httpserver/ChunkedInputStream.java | 1 + .../classes/sun/net/httpserver/Event.java | 2 + .../sun/net/httpserver/ExchangeImpl.java | 1 + .../httpserver/FixedLengthInputStream.java | 3 + .../sun/net/httpserver/HttpConnection.java | 13 + .../classes/sun/net/httpserver/Request.java | 108 ++----- .../sun/net/httpserver/SSLStreams.java | 41 +-- .../sun/net/httpserver/SelectorCache.java | 134 --------- .../sun/net/httpserver/ServerConfig.java | 119 +++++--- .../sun/net/httpserver/ServerImpl.java | 284 ++++++++++++++---- jdk/test/com/sun/net/httpserver/Test.java | 12 + jdk/test/com/sun/net/httpserver/Test1.java | 1 + jdk/test/com/sun/net/httpserver/Test13.java | 16 +- .../sun/net/httpserver/bugs/6725892/Test.java | 273 +++++++++++++++++ .../com/sun/net/httpserver/bugs/B6401598.java | 2 +- 17 files changed, 674 insertions(+), 342 deletions(-) delete mode 100644 jdk/src/share/classes/sun/net/httpserver/SelectorCache.java create mode 100644 jdk/test/com/sun/net/httpserver/bugs/6725892/Test.java diff --git a/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java b/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java index a299c1acf5e..355242b8aa4 100644 --- a/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java +++ b/jdk/src/share/classes/com/sun/net/httpserver/HttpsConfigurator.java @@ -91,6 +91,7 @@ public class HttpsConfigurator { return context; } +//BEGIN_TIGER_EXCLUDE /** * Called by the HttpsServer to configure the parameters * for a https connection currently being established. @@ -111,4 +112,5 @@ public class HttpsConfigurator { public void configure (HttpsParameters params) { params.setSSLParameters (getSSLContext().getDefaultSSLParameters()); } +//END_TIGER_EXCLUDE } diff --git a/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java b/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java index c54e917c02e..d4dc1ee3cf8 100644 --- a/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java +++ b/jdk/src/share/classes/com/sun/net/httpserver/HttpsParameters.java @@ -25,7 +25,9 @@ package com.sun.net.httpserver; import java.net.InetSocketAddress; +//BEGIN_TIGER_EXCLUDE import javax.net.ssl.SSLParameters; +//END_TIGER_EXCLUDE /** * Represents the set of parameters for each https @@ -67,6 +69,7 @@ public abstract class HttpsParameters { */ public abstract InetSocketAddress getClientAddress(); +//BEGIN_TIGER_EXCLUDE /** * Sets the SSLParameters to use for this HttpsParameters. * The parameters must be supported by the SSLContext contained @@ -79,6 +82,7 @@ public abstract class HttpsParameters { * invalid or unsupported. */ public abstract void setSSLParameters (SSLParameters params); +//END_TIGER_EXCLUDE /** * Returns a copy of the array of ciphersuites or null if none diff --git a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java index 8a7c88ac603..6339e87bd44 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java +++ b/jdk/src/share/classes/sun/net/httpserver/ChunkedInputStream.java @@ -110,6 +110,7 @@ class ChunkedInputStream extends LeftOverInputStream { if (remaining == 0) { eof = true; consumeCRLF(); + t.getServerImpl().requestCompleted (t.getConnection()); return -1; } needToReadHeader = false; diff --git a/jdk/src/share/classes/sun/net/httpserver/Event.java b/jdk/src/share/classes/sun/net/httpserver/Event.java index fa7512b99e8..e3109eeb618 100644 --- a/jdk/src/share/classes/sun/net/httpserver/Event.java +++ b/jdk/src/share/classes/sun/net/httpserver/Event.java @@ -40,5 +40,7 @@ class Event { class WriteFinishedEvent extends Event { WriteFinishedEvent (ExchangeImpl t) { super (t); + assert !t.writefinished; + t.writefinished = true; } } diff --git a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java index 26453e6973e..edf813e2814 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -38,6 +38,7 @@ class ExchangeImpl { Headers reqHdrs, rspHdrs; Request req; String method; + boolean writefinished; URI uri; HttpConnection connection; long reqContentLen; diff --git a/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java b/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java index a98779295cb..abc5bf9244b 100644 --- a/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java +++ b/jdk/src/share/classes/sun/net/httpserver/FixedLengthInputStream.java @@ -56,6 +56,9 @@ class FixedLengthInputStream extends LeftOverInputStream { int n = in.read(b, off, len); if (n > -1) { remaining -= n; + if (remaining == 0) { + t.getServerImpl().requestCompleted (t.getConnection()); + } } return n; } diff --git a/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java b/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java index 6d2cf7f954c..adb79556fc5 100644 --- a/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java +++ b/jdk/src/share/classes/sun/net/httpserver/HttpConnection.java @@ -55,10 +55,15 @@ class HttpConnection { SelectionKey selectionKey; String protocol; long time; + volatile long creationTime; // time this connection was created + volatile long rspStartedTime; // time we started writing the response int remaining; boolean closed = false; Logger logger; + public enum State {IDLE, REQUEST, RESPONSE}; + volatile State state; + public String toString() { String s = null; if (chan != null) { @@ -78,6 +83,14 @@ class HttpConnection { context = ctx; } + State getState() { + return state; + } + + void setState (State s) { + state = s; + } + void setParameters ( InputStream in, OutputStream rawout, SocketChannel chan, SSLEngine engine, SSLStreams sslStreams, SSLContext sslContext, String protocol, diff --git a/jdk/src/share/classes/sun/net/httpserver/Request.java b/jdk/src/share/classes/sun/net/httpserver/Request.java index 56c2e137f57..a51664b32b0 100644 --- a/jdk/src/share/classes/sun/net/httpserver/Request.java +++ b/jdk/src/share/classes/sun/net/httpserver/Request.java @@ -201,32 +201,22 @@ class Request { static class ReadStream extends InputStream { SocketChannel channel; - SelectorCache sc; - Selector selector; ByteBuffer chanbuf; - SelectionKey key; - int available; byte[] one; - boolean closed = false, eof = false; + private boolean closed = false, eof = false; ByteBuffer markBuf; /* reads may be satisifed from this buffer */ boolean marked; boolean reset; int readlimit; static long readTimeout; ServerImpl server; - - static { - readTimeout = ServerConfig.getReadTimeout(); - } + final static int BUFSIZE = 8 * 1024; public ReadStream (ServerImpl server, SocketChannel chan) throws IOException { this.channel = chan; this.server = server; - sc = SelectorCache.getSelectorCache(); - selector = sc.getSelector(); - chanbuf = ByteBuffer.allocate (8* 1024); - key = chan.register (selector, SelectionKey.OP_READ); - available = 0; + chanbuf = ByteBuffer.allocate (BUFSIZE); + chanbuf.clear(); one = new byte[1]; closed = marked = reset = false; } @@ -255,6 +245,12 @@ class Request { return -1; } + assert channel.isBlocking(); + + if (off < 0 || srclen < 0|| srclen > (b.length-off)) { + throw new IndexOutOfBoundsException (); + } + if (reset) { /* satisfy from markBuf */ canreturn = markBuf.remaining (); willreturn = canreturn>srclen ? srclen : canreturn; @@ -263,17 +259,19 @@ class Request { reset = false; } } else { /* satisfy from channel */ - canreturn = available(); - while (canreturn == 0 && !eof) { - block (); - canreturn = available(); + chanbuf.clear (); + if (srclen < BUFSIZE) { + chanbuf.limit (srclen); } - if (eof) { + do { + willreturn = channel.read (chanbuf); + } while (willreturn == 0); + if (willreturn == -1) { + eof = true; return -1; } - willreturn = canreturn>srclen ? srclen : canreturn; + chanbuf.flip (); chanbuf.get(b, off, willreturn); - available -= willreturn; if (marked) { /* copy into markBuf */ try { @@ -286,6 +284,11 @@ class Request { return willreturn; } + public boolean markSupported () { + return true; + } + + /* Does not query the OS socket */ public synchronized int available () throws IOException { if (closed) throw new IOException ("Stream is closed"); @@ -296,36 +299,7 @@ class Request { if (reset) return markBuf.remaining(); - if (available > 0) - return available; - - chanbuf.clear (); - available = channel.read (chanbuf); - if (available > 0) { - chanbuf.flip(); - } else if (available == -1) { - eof = true; - available = 0; - } - return available; - } - - /** - * block() only called when available==0 and buf is empty - */ - private synchronized void block () throws IOException { - long currtime = server.getTime(); - long maxtime = currtime + readTimeout; - - while (currtime < maxtime) { - if (selector.select (readTimeout) == 1) { - selector.selectedKeys().clear(); - available (); - return; - } - currtime = server.getTime(); - } - throw new SocketTimeoutException ("no data received"); + return chanbuf.remaining(); } public void close () throws IOException { @@ -333,8 +307,6 @@ class Request { return; } channel.close (); - selector.selectNow(); - sc.freeSelector(selector); closed = true; } @@ -362,23 +334,14 @@ class Request { SocketChannel channel; ByteBuffer buf; SelectionKey key; - SelectorCache sc; - Selector selector; boolean closed; byte[] one; ServerImpl server; - static long writeTimeout; - - static { - writeTimeout = ServerConfig.getWriteTimeout(); - } public WriteStream (ServerImpl server, SocketChannel channel) throws IOException { this.channel = channel; this.server = server; - sc = SelectorCache.getSelectorCache(); - selector = sc.getSelector(); - key = channel.register (selector, SelectionKey.OP_WRITE); + assert channel.isBlocking(); closed = false; one = new byte [1]; buf = ByteBuffer.allocate (4096); @@ -411,31 +374,14 @@ class Request { l -= n; if (l == 0) return; - block(); } } - void block () throws IOException { - long currtime = server.getTime(); - long maxtime = currtime + writeTimeout; - - while (currtime < maxtime) { - if (selector.select (writeTimeout) == 1) { - selector.selectedKeys().clear (); - return; - } - currtime = server.getTime(); - } - throw new SocketTimeoutException ("write blocked too long"); - } - - public void close () throws IOException { if (closed) return; + //server.logStackTrace ("Request.OS.close: isOpen="+channel.isOpen()); channel.close (); - selector.selectNow(); - sc.freeSelector(selector); closed = true; } } diff --git a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java index fed7f4b4943..8578177a61b 100644 --- a/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java +++ b/jdk/src/share/classes/sun/net/httpserver/SSLStreams.java @@ -53,8 +53,6 @@ class SSLStreams { EngineWrapper wrapper; OutputStream os; InputStream is; - static long readTimeout = ServerConfig.getReadTimeout(); - static long writeTimeout = ServerConfig.getWriteTimeout(); /* held by thread doing the hand-shake on this connection */ Lock handshaking = new ReentrantLock(); @@ -77,10 +75,13 @@ class SSLStreams { if (cfg != null) { Parameters params = new Parameters (cfg, addr); cfg.configure (params); +//BEGIN_TIGER_EXCLUDE SSLParameters sslParams = params.getSSLParameters(); if (sslParams != null) { engine.setSSLParameters (sslParams); - } else { + } else +//END_TIGER_EXCLUDE + { /* tiger compatibility */ if (params.getCipherSuites() != null) { try { @@ -104,7 +105,6 @@ class SSLStreams { class Parameters extends HttpsParameters { InetSocketAddress addr; - SSLParameters params; HttpsConfigurator cfg; Parameters (HttpsConfigurator cfg, InetSocketAddress addr) { @@ -117,12 +117,15 @@ class SSLStreams { public HttpsConfigurator getHttpsConfigurator() { return cfg; } +//BEGIN_TIGER_EXCLUDE + SSLParameters params; public void setSSLParameters (SSLParameters p) { params = p; } SSLParameters getSSLParameters () { return params; } +//END_TIGER_EXCLUDE } /** @@ -245,9 +248,6 @@ class SSLStreams { SocketChannel chan; SSLEngine engine; - SelectorCache sc; - Selector write_selector, read_selector; - SelectionKey wkey, rkey; Object wrapLock, unwrapLock; ByteBuffer unwrap_src, wrap_dst; boolean closed = false; @@ -260,16 +260,9 @@ class SSLStreams { unwrapLock = new Object(); unwrap_src = allocate(BufType.PACKET); wrap_dst = allocate(BufType.PACKET); - sc = SelectorCache.getSelectorCache(); - write_selector = sc.getSelector(); - wkey = chan.register (write_selector, SelectionKey.OP_WRITE); - read_selector = sc.getSelector(); - wkey = chan.register (read_selector, SelectionKey.OP_READ); } void close () throws IOException { - sc.freeSelector (write_selector); - sc.freeSelector (read_selector); } /* try to wrap and send the data in src. Handles OVERFLOW. @@ -304,15 +297,7 @@ class SSLStreams { wrap_dst.flip(); int l = wrap_dst.remaining(); assert l == r.result.bytesProduced(); - long currtime = time.getTime(); - long maxtime = currtime + writeTimeout; while (l>0) { - write_selector.select(writeTimeout); // timeout - currtime = time.getTime(); - if (currtime > maxtime) { - throw new SocketTimeoutException ("write timed out"); - } - write_selector.selectedKeys().clear(); l -= chan.write (wrap_dst); } } @@ -342,20 +327,12 @@ class SSLStreams { needData = true; } synchronized (unwrapLock) { - int x,y; + int x; do { if (needData) { - long currTime = time.getTime(); - long maxtime = currTime + readTimeout; do { - if (currTime > maxtime) { - throw new SocketTimeoutException ("read timedout"); - } - y = read_selector.select (readTimeout); - currTime = time.getTime(); - } while (y != 1); - read_selector.selectedKeys().clear(); x = chan.read (unwrap_src); + } while (x == 0); if (x == -1) { throw new IOException ("connection closed for reading"); } diff --git a/jdk/src/share/classes/sun/net/httpserver/SelectorCache.java b/jdk/src/share/classes/sun/net/httpserver/SelectorCache.java deleted file mode 100644 index afd87c02235..00000000000 --- a/jdk/src/share/classes/sun/net/httpserver/SelectorCache.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.net.httpserver; - -import java.util.*; -import java.nio.*; -import java.net.*; -import java.io.*; -import java.security.*; -import java.nio.channels.*; - -/* - * Implements a cache of java.nio.channels.Selector - * where Selectors are allocated on demand and placed - * in a temporary cache for a period of time, so they - * can be reused. If a period of between 2 and 4 minutes - * elapses without being used, then they are closed. - */ -public class SelectorCache { - - static SelectorCache cache = null; - - private SelectorCache () { - freeSelectors = new LinkedList(); - CacheCleaner c = AccessController.doPrivileged( - new PrivilegedAction() { - public CacheCleaner run() { - CacheCleaner cleaner = new CacheCleaner(); - cleaner.setDaemon (true); - return cleaner; - } - }); - c.start(); - } - - /** - * factory method for creating single instance - */ - public static SelectorCache getSelectorCache () { - synchronized (SelectorCache.class) { - if (cache == null) { - cache = new SelectorCache (); - } - } - return cache; - } - - private static class SelectorWrapper { - private Selector sel; - private boolean deleteFlag; - private SelectorWrapper (Selector sel) { - this.sel = sel; - this.deleteFlag = false; - } - public Selector getSelector() { return sel;} - public boolean getDeleteFlag () {return deleteFlag;} - public void setDeleteFlag (boolean b) {deleteFlag = b;} - } - - /* list of free selectors. Can be re-allocated for a period - * of time, after which if not allocated will be closed - * and removed from the list (by CacheCleaner thread) - */ - LinkedList freeSelectors; - - synchronized Selector getSelector () throws IOException { - SelectorWrapper wrapper = null; - Selector selector; - - if (freeSelectors.size() > 0) { - wrapper = freeSelectors.remove(); - selector = wrapper.getSelector(); - } else { - selector = Selector.open(); - } - return selector; - } - - synchronized void freeSelector (Selector selector) { - freeSelectors.add (new SelectorWrapper (selector)); - } - - /* Thread ensures that entries on freeSelector list - * remain there for at least 2 minutes and no longer - * than 4 minutes. - */ - class CacheCleaner extends Thread { - public void run () { - long timeout = ServerConfig.getSelCacheTimeout() * 1000; - while (true) { - try {Thread.sleep (timeout); } catch (Exception e) {} - synchronized (freeSelectors) { - ListIterator l = freeSelectors.listIterator(); - while (l.hasNext()) { - SelectorWrapper w = l.next(); - if (w.getDeleteFlag()) { - /* 2nd pass. Close the selector */ - try { - w.getSelector().close(); - } catch (IOException e) {} - l.remove(); - } else { - /* 1st pass. Set the flag */ - w.setDeleteFlag (true); - } - } - } - } - } - } -} diff --git a/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java b/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java index d4c87847547..cae3cdd84d9 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java +++ b/jdk/src/share/classes/sun/net/httpserver/ServerConfig.java @@ -27,6 +27,8 @@ package sun.net.httpserver; import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; +import java.util.logging.Logger; +import java.security.PrivilegedAction; /** * Parameters that users will not likely need to set @@ -37,23 +39,26 @@ class ServerConfig { static int clockTick; - static int defaultClockTick = 10000 ; // 10 sec. + static final int DEFAULT_CLOCK_TICK = 10000 ; // 10 sec. /* These values must be a reasonable multiple of clockTick */ - static long defaultReadTimeout = 20 ; // 20 sec. - static long defaultWriteTimeout = 60 ; // 60 sec. - static long defaultIdleInterval = 300 ; // 5 min - static long defaultSelCacheTimeout = 120 ; // seconds - static int defaultMaxIdleConnections = 200 ; + static final long DEFAULT_IDLE_INTERVAL = 300 ; // 5 min + static final int DEFAULT_MAX_IDLE_CONNECTIONS = 200 ; - static long defaultDrainAmount = 64 * 1024; + static final long DEFAULT_MAX_REQ_TIME = -1; // default: forever + static final long DEFAULT_MAX_RSP_TIME = -1; // default: forever + static final long DEFAULT_TIMER_MILLIS = 1000; + + static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024; - static long readTimeout; - static long writeTimeout; static long idleInterval; - static long selCacheTimeout; static long drainAmount; // max # of bytes to drain from an inputstream static int maxIdleConnections; + + // max time a request or response is allowed to take + static long maxReqTime; + static long maxRspTime; + static long timerMillis; static boolean debug = false; static { @@ -61,49 +66,79 @@ class ServerConfig { idleInterval = ((Long)java.security.AccessController.doPrivileged( new sun.security.action.GetLongAction( "sun.net.httpserver.idleInterval", - defaultIdleInterval))).longValue() * 1000; + DEFAULT_IDLE_INTERVAL))).longValue() * 1000; clockTick = ((Integer)java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.httpserver.clockTick", - defaultClockTick))).intValue(); + DEFAULT_CLOCK_TICK))).intValue(); maxIdleConnections = ((Integer)java.security.AccessController.doPrivileged( new sun.security.action.GetIntegerAction( "sun.net.httpserver.maxIdleConnections", - defaultMaxIdleConnections))).intValue(); - - readTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.readTimeout", - defaultReadTimeout))).longValue()* 1000; - - selCacheTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.selCacheTimeout", - defaultSelCacheTimeout))).longValue()* 1000; - - writeTimeout = ((Long)java.security.AccessController.doPrivileged( - new sun.security.action.GetLongAction( - "sun.net.httpserver.writeTimeout", - defaultWriteTimeout))).longValue()* 1000; + DEFAULT_MAX_IDLE_CONNECTIONS))).intValue(); drainAmount = ((Long)java.security.AccessController.doPrivileged( new sun.security.action.GetLongAction( "sun.net.httpserver.drainAmount", - defaultDrainAmount))).longValue(); + DEFAULT_DRAIN_AMOUNT))).longValue(); + + maxReqTime = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.maxReqTime", + DEFAULT_MAX_REQ_TIME))).longValue(); + + maxRspTime = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.maxRspTime", + DEFAULT_MAX_RSP_TIME))).longValue(); + + timerMillis = ((Long)java.security.AccessController.doPrivileged( + new sun.security.action.GetLongAction( + "sun.net.httpserver.timerMillis", + DEFAULT_TIMER_MILLIS))).longValue(); debug = ((Boolean)java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction( "sun.net.httpserver.debug"))).booleanValue(); } - static long getReadTimeout () { - return readTimeout; - } - static long getSelCacheTimeout () { - return selCacheTimeout; + static void checkLegacyProperties (final Logger logger) { + + // legacy properties that are no longer used + // print a warning to logger if they are set. + + java.security.AccessController.doPrivileged( + new PrivilegedAction() { + public Void run () { + if (System.getProperty("sun.net.httpserver.readTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.readTimeout "+ + "property is no longer used. "+ + "Use sun.net.httpserver.maxReqTime instead." + ); + } + if (System.getProperty("sun.net.httpserver.writeTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.writeTimeout "+ + "property is no longer used. Use "+ + "sun.net.httpserver.maxRspTime instead." + ); + } + if (System.getProperty("sun.net.httpserver.selCacheTimeout") + !=null) + { + logger.warning ("sun.net.httpserver.selCacheTimeout "+ + "property is no longer used." + ); + } + return null; + } + } + ); } static boolean debugEnabled () { @@ -122,11 +157,19 @@ class ServerConfig { return maxIdleConnections; } - static long getWriteTimeout () { - return writeTimeout; - } - static long getDrainAmount () { return drainAmount; } + + static long getMaxReqTime () { + return maxReqTime; + } + + static long getMaxRspTime () { + return maxRspTime; + } + + static long getTimerMillis () { + return timerMillis; + } } diff --git a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java index a8b02878082..08edeaf8a80 100644 --- a/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java +++ b/jdk/src/share/classes/sun/net/httpserver/ServerImpl.java @@ -37,6 +37,7 @@ import java.util.logging.Level; import javax.net.ssl.*; import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; +import sun.net.httpserver.HttpConnection.State; /** * Provides implementation for both HTTP and HTTPS @@ -55,6 +56,12 @@ class ServerImpl implements TimeSource { private SelectionKey listenerKey; private Set idleConnections; private Set allConnections; + /* following two are used to keep track of the times + * when a connection/request is first received + * and when we start to send the response + */ + private Set reqConnections; + private Set rspConnections; private List events; private Object lolock = new Object(); private volatile boolean finished = false; @@ -62,14 +69,19 @@ class ServerImpl implements TimeSource { private boolean bound = false; private boolean started = false; private volatile long time; /* current time */ + private volatile long subticks = 0; private volatile long ticks; /* number of clock ticks since server started */ private HttpServer wrapper; final static int CLOCK_TICK = ServerConfig.getClockTick(); final static long IDLE_INTERVAL = ServerConfig.getIdleInterval(); final static int MAX_IDLE_CONNECTIONS = ServerConfig.getMaxIdleConnections(); + final static long TIMER_MILLIS = ServerConfig.getTimerMillis (); + final static long MAX_REQ_TIME=getTimeMillis(ServerConfig.getMaxReqTime()); + final static long MAX_RSP_TIME=getTimeMillis(ServerConfig.getMaxRspTime()); + final static boolean timer1Enabled = MAX_REQ_TIME != -1 || MAX_RSP_TIME != -1; - private Timer timer; + private Timer timer, timer1; private Logger logger; ServerImpl ( @@ -79,6 +91,7 @@ class ServerImpl implements TimeSource { this.protocol = protocol; this.wrapper = wrapper; this.logger = Logger.getLogger ("com.sun.net.httpserver"); + ServerConfig.checkLegacyProperties (logger); https = protocol.equalsIgnoreCase ("https"); this.address = addr; contexts = new ContextList(); @@ -94,9 +107,18 @@ class ServerImpl implements TimeSource { dispatcher = new Dispatcher(); idleConnections = Collections.synchronizedSet (new HashSet()); allConnections = Collections.synchronizedSet (new HashSet()); + reqConnections = Collections.synchronizedSet (new HashSet()); + rspConnections = Collections.synchronizedSet (new HashSet()); time = System.currentTimeMillis(); timer = new Timer ("server-timer", true); timer.schedule (new ServerTimerTask(), CLOCK_TICK, CLOCK_TICK); + if (timer1Enabled) { + timer1 = new Timer ("server-timer1", true); + timer1.schedule (new ServerTimerTask1(),TIMER_MILLIS,TIMER_MILLIS); + logger.config ("HttpServer timer1 enabled period in ms: "+TIMER_MILLIS); + logger.config ("MAX_REQ_TIME: "+MAX_REQ_TIME); + logger.config ("MAX_RSP_TIME: "+MAX_RSP_TIME); + } events = new LinkedList(); logger.config ("HttpServer created "+protocol+" "+ addr); } @@ -181,6 +203,9 @@ class ServerImpl implements TimeSource { allConnections.clear(); idleConnections.clear(); timer.cancel(); + if (timer1Enabled) { + timer1.cancel(); + } } Dispatcher dispatcher; @@ -236,13 +261,6 @@ class ServerImpl implements TimeSource { } } - int resultSize () { - synchronized (lolock) { - return events.size (); - } - } - - /* main server listener task */ class Dispatcher implements Runnable { @@ -257,7 +275,7 @@ class ServerImpl implements TimeSource { if (terminating && exchanges == 0) { finished = true; } - SocketChannel chan = c.getChannel(); + responseCompleted (c); LeftOverInputStream is = t.getOriginalInputStream(); if (!is.isEOF()) { t.close = true; @@ -268,17 +286,10 @@ class ServerImpl implements TimeSource { } else { if (is.isDataBuffered()) { /* don't re-enable the interestops, just handle it */ + requestStarted (c); handle (c.getChannel(), c); } else { - /* re-enable interestops */ - SelectionKey key = c.getSelectionKey(); - if (key.isValid()) { - key.interestOps ( - key.interestOps()|SelectionKey.OP_READ - ); - } - c.time = getTime() + IDLE_INTERVAL; - idleConnections.add (c); + connsToRegister.add (c); } } } @@ -290,21 +301,50 @@ class ServerImpl implements TimeSource { } } + final LinkedList connsToRegister = + new LinkedList(); + + void reRegister (HttpConnection c) { + /* re-register with selector */ + try { + SocketChannel chan = c.getChannel(); + chan.configureBlocking (false); + SelectionKey key = chan.register (selector, SelectionKey.OP_READ); + key.attach (c); + c.selectionKey = key; + c.time = getTime() + IDLE_INTERVAL; + idleConnections.add (c); + } catch (IOException e) { + dprint(e); + logger.log(Level.FINER, "Dispatcher(8)", e); + c.close(); + } + } + public void run() { while (!finished) { try { + ListIterator li = + connsToRegister.listIterator(); + for (HttpConnection c : connsToRegister) { + reRegister(c); + } + connsToRegister.clear(); - /* process the events list first */ - - while (resultSize() > 0) { - Event r; - synchronized (lolock) { - r = events.remove(0); - handleEvent (r); + List list = null; + selector.select(1000); + synchronized (lolock) { + if (events.size() > 0) { + list = events; + events = new LinkedList(); } } - selector.select(1000); + if (list != null) { + for (Event r: list) { + handleEvent (r); + } + } /* process the selected list now */ @@ -327,6 +367,7 @@ class ServerImpl implements TimeSource { c.selectionKey = newkey; c.setChannel (chan); newkey.attach (c); + requestStarted (c); allConnections.add (c); } else { try { @@ -334,27 +375,44 @@ class ServerImpl implements TimeSource { boolean closed; SocketChannel chan = (SocketChannel)key.channel(); HttpConnection conn = (HttpConnection)key.attachment(); - // interestOps will be restored at end of read - key.interestOps (0); + + key.cancel(); + chan.configureBlocking (true); + if (idleConnections.remove(conn)) { + // was an idle connection so add it + // to reqConnections set. + requestStarted (conn); + } handle (chan, conn); } else { assert false; } + } catch (CancelledKeyException e) { + handleException(key, null); } catch (IOException e) { - HttpConnection conn = (HttpConnection)key.attachment(); - logger.log ( - Level.FINER, "Dispatcher (2)", e - ); - conn.close(); + handleException(key, e); } } } + // call the selector just to process the cancelled keys + selector.selectNow(); + } catch (IOException e) { + logger.log (Level.FINER, "Dispatcher (4)", e); } catch (Exception e) { - logger.log (Level.FINER, "Dispatcher (3)", e); + e.printStackTrace(); + logger.log (Level.FINER, "Dispatcher (7)", e); } } } + private void handleException (SelectionKey key, Exception e) { + HttpConnection conn = (HttpConnection)key.attachment(); + if (e != null) { + logger.log (Level.FINER, "Dispatcher (2)", e); + } + closeConnection(conn); + } + public void handle (SocketChannel chan, HttpConnection conn) throws IOException { @@ -363,10 +421,10 @@ class ServerImpl implements TimeSource { executor.execute (t); } catch (HttpError e1) { logger.log (Level.FINER, "Dispatcher (4)", e1); - conn.close(); + closeConnection(conn); } catch (IOException e) { logger.log (Level.FINER, "Dispatcher (5)", e); - conn.close(); + closeConnection(conn); } } } @@ -390,7 +448,26 @@ class ServerImpl implements TimeSource { return logger; } - /* per exchange task */ + private void closeConnection(HttpConnection conn) { + conn.close(); + allConnections.remove(conn); + switch (conn.getState()) { + case REQUEST: + reqConnections.remove(conn); + break; + case RESPONSE: + rspConnections.remove(conn); + break; + case IDLE: + idleConnections.remove(conn); + break; + } + assert !reqConnections.remove(conn); + assert !rspConnections.remove(conn); + assert !idleConnections.remove(conn); + } + + /* per exchange task */ class Exchange implements Runnable { SocketChannel chan; @@ -450,8 +527,7 @@ class ServerImpl implements TimeSource { requestLine = req.requestLine(); if (requestLine == null) { /* connection closed */ - connection.close(); - allConnections.remove(connection); + closeConnection(connection); return; } int space = requestLine.indexOf (' '); @@ -482,6 +558,9 @@ class ServerImpl implements TimeSource { if (s != null) { clen = Long.parseLong(s); } + if (clen == 0) { + requestCompleted (connection); + } } ctx = contexts.findContext (protocol, uri.getPath()); if (ctx == null) { @@ -560,7 +639,7 @@ class ServerImpl implements TimeSource { } catch (IOException e1) { logger.log (Level.FINER, "ServerImpl.Exchange (1)", e1); - connection.close(); + closeConnection(connection); } catch (NumberFormatException e3) { reject (Code.HTTP_BAD_REQUEST, requestLine, "NumberFormatException thrown"); @@ -569,7 +648,7 @@ class ServerImpl implements TimeSource { requestLine, "URISyntaxException thrown"); } catch (Exception e4) { logger.log (Level.FINER, "ServerImpl.Exchange (2)", e4); - connection.close(); + closeConnection(connection); } } @@ -591,47 +670,60 @@ class ServerImpl implements TimeSource { rejected = true; logReply (code, requestStr, message); sendReply ( - code, true, "

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

"+message + code, false, "

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

"+message ); - /* connection is already closed by sendReply, now remove it */ - allConnections.remove(connection); + closeConnection(connection); } void sendReply ( int code, boolean closeNow, String text) { try { - String s = "HTTP/1.1 " + code + Code.msg(code) + "\r\n"; + StringBuilder builder = new StringBuilder (512); + builder.append ("HTTP/1.1 ") + .append (code).append (Code.msg(code)).append ("\r\n"); + if (text != null && text.length() != 0) { - s = s + "Content-Length: "+text.length()+"\r\n"; - s = s + "Content-Type: text/html\r\n"; + builder.append ("Content-Length: ") + .append (text.length()).append ("\r\n") + .append ("Content-Type: text/html\r\n"); } else { - s = s + "Content-Length: 0\r\n"; + builder.append ("Content-Length: 0\r\n"); text = ""; } if (closeNow) { - s = s + "Connection: close\r\n"; + builder.append ("Connection: close\r\n"); } - s = s + "\r\n" + text; + builder.append ("\r\n").append (text); + String s = builder.toString(); byte[] b = s.getBytes("ISO8859_1"); rawout.write (b); rawout.flush(); if (closeNow) { - connection.close(); + closeConnection(connection); } } catch (IOException e) { logger.log (Level.FINER, "ServerImpl.sendReply", e); - connection.close(); + closeConnection(connection); } } } void logReply (int code, String requestStr, String text) { + if (!logger.isLoggable(Level.FINE)) { + return; + } if (text == null) { text = ""; } - String message = requestStr + " [" + code + " " + + String r; + if (requestStr.length() > 80) { + r = requestStr.substring (0, 80) + ""; + } else { + r = requestStr; + } + String message = r + " [" + code + " " + Code.msg(code) + "] ("+text+")"; logger.fine (message); } @@ -667,6 +759,34 @@ class ServerImpl implements TimeSource { return wrapper; } + void requestStarted (HttpConnection c) { + c.creationTime = getTime(); + c.setState (State.REQUEST); + reqConnections.add (c); + } + + // called after a request has been completely read + // by the server. This stops the timer which would + // close the connection if the request doesn't arrive + // quickly enough. It then starts the timer + // that ensures the client reads the response in a timely + // fashion. + + void requestCompleted (HttpConnection c) { + assert c.getState() == State.REQUEST; + reqConnections.remove (c); + c.rspStartedTime = getTime(); + rspConnections.add (c); + c.setState (State.RESPONSE); + } + + // called after response has been sent + void responseCompleted (HttpConnection c) { + assert c.getState() == State.RESPONSE; + rspConnections.remove (c); + c.setState (State.IDLE); + } + /** * TimerTask run every CLOCK_TICK ms */ @@ -689,4 +809,62 @@ class ServerImpl implements TimeSource { } } } + + class ServerTimerTask1 extends TimerTask { + + // runs every TIMER_MILLIS + public void run () { + LinkedList toClose = new LinkedList(); + time = System.currentTimeMillis(); + synchronized (reqConnections) { + if (MAX_REQ_TIME != -1) { + for (HttpConnection c : reqConnections) { + if (c.creationTime + TIMER_MILLIS + MAX_REQ_TIME <= time) { + toClose.add (c); + } + } + for (HttpConnection c : toClose) { + logger.log (Level.FINE, "closing: no request: " + c); + reqConnections.remove (c); + allConnections.remove (c); + c.close(); + } + } + } + toClose = new LinkedList(); + synchronized (rspConnections) { + if (MAX_RSP_TIME != -1) { + for (HttpConnection c : rspConnections) { + if (c.rspStartedTime + TIMER_MILLIS +MAX_RSP_TIME <= time) { + toClose.add (c); + } + } + for (HttpConnection c : toClose) { + logger.log (Level.FINE, "closing: no response: " + c); + rspConnections.remove (c); + allConnections.remove (c); + c.close(); + } + } + } + } + } + + void logStackTrace (String s) { + logger.finest (s); + StringBuilder b = new StringBuilder (); + StackTraceElement[] e = Thread.currentThread().getStackTrace(); + for (int i=0; i Date: Wed, 17 Nov 2010 15:10:42 -0800 Subject: [PATCH 4/5] 6615506: (fmt spec) Date/Time conversion table missing column for 'Z' Added the column entry back in Reviewed-by: alanb --- jdk/src/share/classes/java/util/Formatter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index 55fd610d39d..6e115b5156b 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -1581,6 +1581,7 @@ import sun.misc.FormattedFloatingDecimal; * instance of the Java virtual machine. * * {@code 'Z'} + * '\u005a' * A string representing the abbreviation for the time zone. This * value will be adjusted as necessary for Daylight Saving Time. For * {@code long}, {@link Long}, and {@link Date} the time zone used is From 8aaa66c1f786d83307b8917a89ac5f1402dc8926 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Wed, 17 Nov 2010 21:33:16 -0800 Subject: [PATCH 5/5] 6217210: RFE: Support for Cp833 in 1.4.2 Forward port the Cp833 charset Reviewed-by: poonam --- jdk/make/sun/nio/cs/FILES_java.gmk | 3 + jdk/make/tools/CharsetMapping/IBM833.c2b | 94 ++++++++ jdk/make/tools/CharsetMapping/IBM833.map | 217 ++++++++++++++++++ jdk/make/tools/CharsetMapping/extsbcs | 1 + .../share/classes/sun/io/ByteToCharCp833.java | 42 ++++ .../share/classes/sun/io/CharToByteCp833.java | 46 ++++ .../classes/sun/io/CharacterEncoding.java | 7 +- .../sun/nio/cs/ext/ExtendedCharsets.java | 7 + jdk/test/sun/nio/cs/CheckHistoricalNames.java | 4 +- 9 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 jdk/make/tools/CharsetMapping/IBM833.c2b create mode 100644 jdk/make/tools/CharsetMapping/IBM833.map create mode 100644 jdk/src/share/classes/sun/io/ByteToCharCp833.java create mode 100644 jdk/src/share/classes/sun/io/CharToByteCp833.java diff --git a/jdk/make/sun/nio/cs/FILES_java.gmk b/jdk/make/sun/nio/cs/FILES_java.gmk index d930065d83f..b177d64b4c1 100644 --- a/jdk/make/sun/nio/cs/FILES_java.gmk +++ b/jdk/make/sun/nio/cs/FILES_java.gmk @@ -85,6 +85,7 @@ FILES_src = \ sun/io/ByteToCharCp500.java \ sun/io/ByteToCharCp737.java \ sun/io/ByteToCharCp775.java \ + sun/io/ByteToCharCp833.java \ sun/io/ByteToCharCp834.java \ sun/io/ByteToCharCp838.java \ sun/io/ByteToCharCp850.java \ @@ -214,6 +215,7 @@ FILES_src = \ sun/io/CharToByteCp500.java \ sun/io/CharToByteCp737.java \ sun/io/CharToByteCp775.java \ + sun/io/CharToByteCp833.java \ sun/io/CharToByteCp834.java \ sun/io/CharToByteCp838.java \ sun/io/CharToByteCp850.java \ @@ -331,6 +333,7 @@ FILES_gen_extcs = \ sun/nio/cs/ext/IBM420.java \ sun/nio/cs/ext/IBM424.java \ sun/nio/cs/ext/IBM500.java \ + sun/nio/cs/ext/IBM833.java \ sun/nio/cs/ext/IBM838.java \ sun/nio/cs/ext/IBM856.java \ sun/nio/cs/ext/IBM860.java \ diff --git a/jdk/make/tools/CharsetMapping/IBM833.c2b b/jdk/make/tools/CharsetMapping/IBM833.c2b new file mode 100644 index 00000000000..b751d80bc00 --- /dev/null +++ b/jdk/make/tools/CharsetMapping/IBM833.c2b @@ -0,0 +1,94 @@ +0x5A U+FF01 +0x7F U+FF02 +0x7B U+FF03 +0x5B U+FF04 +0x6C U+FF05 +0x50 U+FF06 +0x7D U+FF07 +0x4D U+FF08 +0x5D U+FF09 +0x5C U+FF0A +0x4E U+FF0B +0x6B U+FF0C +0x60 U+FF0D +0x4B U+FF0E +0x61 U+FF0F +0xF0 U+FF10 +0xF1 U+FF11 +0xF2 U+FF12 +0xF3 U+FF13 +0xF4 U+FF14 +0xF5 U+FF15 +0xF6 U+FF16 +0xF7 U+FF17 +0xF8 U+FF18 +0xF9 U+FF19 +0x7A U+FF1A +0x5E U+FF1B +0x4C U+FF1C +0x7E U+FF1D +0x6E U+FF1E +0x6F U+FF1F +0x7C U+FF20 +0xC1 U+FF21 +0xC2 U+FF22 +0xC3 U+FF23 +0xC4 U+FF24 +0xC5 U+FF25 +0xC6 U+FF26 +0xC7 U+FF27 +0xC8 U+FF28 +0xC9 U+FF29 +0xD1 U+FF2A +0xD2 U+FF2B +0xD3 U+FF2C +0xD4 U+FF2D +0xD5 U+FF2E +0xD6 U+FF2F +0xD7 U+FF30 +0xD8 U+FF31 +0xD9 U+FF32 +0xE2 U+FF33 +0xE3 U+FF34 +0xE4 U+FF35 +0xE5 U+FF36 +0xE6 U+FF37 +0xE7 U+FF38 +0xE8 U+FF39 +0xE9 U+FF3A +0x70 U+FF3B +0xB2 U+FF3C +0x80 U+FF3D +0xB0 U+FF3E +0x6D U+FF3F +0x79 U+FF40 +0x81 U+FF41 +0x82 U+FF42 +0x83 U+FF43 +0x84 U+FF44 +0x85 U+FF45 +0x86 U+FF46 +0x87 U+FF47 +0x88 U+FF48 +0x89 U+FF49 +0x91 U+FF4A +0x92 U+FF4B +0x93 U+FF4C +0x94 U+FF4D +0x95 U+FF4E +0x96 U+FF4F +0x97 U+FF50 +0x98 U+FF51 +0x99 U+FF52 +0xA2 U+FF53 +0xA3 U+FF54 +0xA4 U+FF55 +0xA5 U+FF56 +0xA6 U+FF57 +0xA7 U+FF58 +0xA8 U+FF59 +0xA9 U+FF5A +0xC0 U+FF5B +0x4F U+FF5C +0xD0 U+FF5D +0xA1 U+FF5E diff --git a/jdk/make/tools/CharsetMapping/IBM833.map b/jdk/make/tools/CharsetMapping/IBM833.map new file mode 100644 index 00000000000..b36860ae4e7 --- /dev/null +++ b/jdk/make/tools/CharsetMapping/IBM833.map @@ -0,0 +1,217 @@ +0x00 U+0000 +0x01 U+0001 +0x02 U+0002 +0x03 U+0003 +0x37 U+0004 +0x2D U+0005 +0x2E U+0006 +0x2F U+0007 +0x16 U+0008 +0x05 U+0009 +0x25 U+000A +0x0B U+000B +0x0C U+000C +0x0D U+000D +0x0E U+000E +0x0F U+000F +0x10 U+0010 +0x11 U+0011 +0x12 U+0012 +0x13 U+0013 +0x3C U+0014 +0x3D U+0015 +0x32 U+0016 +0x26 U+0017 +0x18 U+0018 +0x19 U+0019 +0x3F U+001A +0x27 U+001B +0x1C U+001C +0x1D U+001D +0x1E U+001E +0x1F U+001F +0x40 U+0020 +0x5A U+0021 +0x7F U+0022 +0x7B U+0023 +0x5B U+0024 +0x6C U+0025 +0x50 U+0026 +0x7D U+0027 +0x4D U+0028 +0x5D U+0029 +0x5C U+002A +0x4E U+002B +0x6B U+002C +0x60 U+002D +0x4B U+002E +0x61 U+002F +0xF0 U+0030 +0xF1 U+0031 +0xF2 U+0032 +0xF3 U+0033 +0xF4 U+0034 +0xF5 U+0035 +0xF6 U+0036 +0xF7 U+0037 +0xF8 U+0038 +0xF9 U+0039 +0x7A U+003A +0x5E U+003B +0x4C U+003C +0x7E U+003D +0x6E U+003E +0x6F U+003F +0x7C U+0040 +0xC1 U+0041 +0xC2 U+0042 +0xC3 U+0043 +0xC4 U+0044 +0xC5 U+0045 +0xC6 U+0046 +0xC7 U+0047 +0xC8 U+0048 +0xC9 U+0049 +0xD1 U+004A +0xD2 U+004B +0xD3 U+004C +0xD4 U+004D +0xD5 U+004E +0xD6 U+004F +0xD7 U+0050 +0xD8 U+0051 +0xD9 U+0052 +0xE2 U+0053 +0xE3 U+0054 +0xE4 U+0055 +0xE5 U+0056 +0xE6 U+0057 +0xE7 U+0058 +0xE8 U+0059 +0xE9 U+005A +0x70 U+005B +0xB2 U+005C +0x80 U+005D +0xB0 U+005E +0x6D U+005F +0x79 U+0060 +0x81 U+0061 +0x82 U+0062 +0x83 U+0063 +0x84 U+0064 +0x85 U+0065 +0x86 U+0066 +0x87 U+0067 +0x88 U+0068 +0x89 U+0069 +0x91 U+006A +0x92 U+006B +0x93 U+006C +0x94 U+006D +0x95 U+006E +0x96 U+006F +0x97 U+0070 +0x98 U+0071 +0x99 U+0072 +0xA2 U+0073 +0xA3 U+0074 +0xA4 U+0075 +0xA5 U+0076 +0xA6 U+0077 +0xA7 U+0078 +0xA8 U+0079 +0xA9 U+007A +0xC0 U+007B +0x4F U+007C +0xD0 U+007D +0xA1 U+007E +0x07 U+007F +0x20 U+0080 +0x21 U+0081 +0x22 U+0082 +0x23 U+0083 +0x24 U+0084 +0x15 U+0085 +0x06 U+0086 +0x17 U+0087 +0x28 U+0088 +0x29 U+0089 +0x2A U+008A +0x2B U+008B +0x2C U+008C +0x09 U+008D +0x0A U+008E +0x1B U+008F +0x30 U+0090 +0x31 U+0091 +0x1A U+0092 +0x33 U+0093 +0x34 U+0094 +0x35 U+0095 +0x36 U+0096 +0x08 U+0097 +0x38 U+0098 +0x39 U+0099 +0x3A U+009A +0x3B U+009B +0x04 U+009C +0x14 U+009D +0x3E U+009E +0xFF U+009F +0x4A U+00A2 +0x6A U+00A6 +0x5F U+00AC +0xA0 U+203E +0xE0 U+20A9 +0x42 U+FFA0 +0x43 U+FFA1 +0x44 U+FFA2 +0x45 U+FFA3 +0x46 U+FFA4 +0x47 U+FFA5 +0x48 U+FFA6 +0x49 U+FFA7 +0x52 U+FFA8 +0x53 U+FFA9 +0x54 U+FFAA +0x55 U+FFAB +0x56 U+FFAC +0x57 U+FFAD +0x58 U+FFAE +0x59 U+FFAF +0x62 U+FFB0 +0x63 U+FFB1 +0x64 U+FFB2 +0x65 U+FFB3 +0x66 U+FFB4 +0x67 U+FFB5 +0x68 U+FFB6 +0x69 U+FFB7 +0x72 U+FFB8 +0x73 U+FFB9 +0x74 U+FFBA +0x75 U+FFBB +0x76 U+FFBC +0x77 U+FFBD +0x78 U+FFBE +0x8A U+FFC2 +0x8B U+FFC3 +0x8C U+FFC4 +0x8D U+FFC5 +0x8E U+FFC6 +0x8F U+FFC7 +0x9A U+FFCA +0x9B U+FFCB +0x9C U+FFCC +0x9D U+FFCD +0x9E U+FFCE +0x9F U+FFCF +0xAA U+FFD2 +0xAB U+FFD3 +0xAC U+FFD4 +0xAD U+FFD5 +0xAE U+FFD6 +0xAF U+FFD7 +0xBA U+FFDA +0xBB U+FFDB +0xBC U+FFDC diff --git a/jdk/make/tools/CharsetMapping/extsbcs b/jdk/make/tools/CharsetMapping/extsbcs index 81a6acdf817..e66fe5bbb1c 100644 --- a/jdk/make/tools/CharsetMapping/extsbcs +++ b/jdk/make/tools/CharsetMapping/extsbcs @@ -32,6 +32,7 @@ IBM297 IBM297 Cp297 false sun.nio.cs.ext IBM420 IBM420 Cp420 false sun.nio.cs.ext IBM424 IBM424 Cp424 false sun.nio.cs.ext IBM500 IBM500 Cp500 false sun.nio.cs.ext +IBM833 IBM833 Cp833 false sun.nio.cs.ext IBM838 IBM-Thai Cp838 false sun.nio.cs.ext IBM856 x-IBM856 Cp856 false sun.nio.cs.ext IBM860 IBM860 Cp860 false sun.nio.cs.ext diff --git a/jdk/src/share/classes/sun/io/ByteToCharCp833.java b/jdk/src/share/classes/sun/io/ByteToCharCp833.java new file mode 100644 index 00000000000..a83a893d137 --- /dev/null +++ b/jdk/src/share/classes/sun/io/ByteToCharCp833.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.io; + +import sun.nio.cs.ext.IBM833; + +public class ByteToCharCp833 extends ByteToCharSingleByte { + + private final static IBM833 nioCoder = new IBM833(); + + public String getCharacterEncoding() { + return "Cp833"; + } + + public ByteToCharCp833() { + super.byteToCharTable = nioCoder.getDecoderSingleByteMappings(); + } +} + diff --git a/jdk/src/share/classes/sun/io/CharToByteCp833.java b/jdk/src/share/classes/sun/io/CharToByteCp833.java new file mode 100644 index 00000000000..2d531406c17 --- /dev/null +++ b/jdk/src/share/classes/sun/io/CharToByteCp833.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.io; + +import sun.nio.cs.ext.IBM833; + +public class CharToByteCp833 extends CharToByteSingleByte { + + private final static IBM833 nioCoder = new IBM833(); + + public String getCharacterEncoding() { + return "Cp833"; + } + + public CharToByteCp833() { + super.mask1 = 0xFF00; + super.mask2 = 0x00FF; + super.shift = 8; + super.index1 = nioCoder.getEncoderIndex1(); + super.index2 = nioCoder.getEncoderIndex2(); + } +} + diff --git a/jdk/src/share/classes/sun/io/CharacterEncoding.java b/jdk/src/share/classes/sun/io/CharacterEncoding.java index 94ce7040f5d..f577a9bc79b 100644 --- a/jdk/src/share/classes/sun/io/CharacterEncoding.java +++ b/jdk/src/share/classes/sun/io/CharacterEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -406,6 +406,11 @@ public class CharacterEncoding { aliasTable.put("cp775", "Cp775"); aliasTable.put("775", "Cp775"); + aliasTable.put("ibm833", "Cp833"); + aliasTable.put("ibm-833", "Cp833"); + aliasTable.put("cp833", "Cp833"); + aliasTable.put("833", "Cp833"); + aliasTable.put("ibm834", "Cp834"); aliasTable.put("ibm-834", "Cp834"); aliasTable.put("cp834", "Cp834"); diff --git a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java index ca6a49637c0..920e3372d42 100644 --- a/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java +++ b/jdk/src/share/classes/sun/nio/cs/ext/ExtendedCharsets.java @@ -778,6 +778,13 @@ public class ExtendedCharsets "csIBM500" }); + charset("x-IBM833", "IBM833", + new String[] { + "cp833", + "ibm833", + "ibm-833" + }); + //EBCDIC DBCS-only Korean charset("x-IBM834", "IBM834", new String[] { diff --git a/jdk/test/sun/nio/cs/CheckHistoricalNames.java b/jdk/test/sun/nio/cs/CheckHistoricalNames.java index fdab32d75ed..af04434bd82 100644 --- a/jdk/test/sun/nio/cs/CheckHistoricalNames.java +++ b/jdk/test/sun/nio/cs/CheckHistoricalNames.java @@ -22,7 +22,7 @@ */ /* @test - @bug 4513767 4961027 + @bug 4513767 4961027 6217210 @summary Checks canonical names match between old and (NIO) core charsets */ import java.io.InputStreamReader; @@ -154,6 +154,7 @@ public class CheckHistoricalNames { checkHistoricalName("Cp500"); checkHistoricalName("Cp737"); checkHistoricalName("Cp775"); + checkHistoricalName("Cp833"); checkHistoricalName("Cp838"); checkHistoricalName("Cp850"); checkHistoricalName("Cp852"); @@ -228,6 +229,7 @@ public class CheckHistoricalNames { checkMappedName("IBM856", "Cp856"); checkMappedName("IBM857", "Cp857"); checkMappedName("IBM00858", "Cp858"); + checkMappedName("IBM833", "Cp833"); checkMappedName("IBM860", "Cp860"); checkMappedName("IBM861", "Cp861"); checkMappedName("IBM862", "Cp862");