From 8f734f4dcff290797f5ffc99dc13ebc97bd7d813 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Tue, 23 Apr 2013 09:37:31 +0200 Subject: [PATCH 001/263] 8011081: Improve jhat Properly escape HTML output Reviewed-by: alanb, mschoene, sundar --- .../hat/internal/server/AllClassesQuery.java | 2 +- .../tools/hat/internal/server/ClassQuery.java | 10 +++++----- .../tools/hat/internal/server/HttpReader.java | 10 +++------- .../internal/server/InstancesCountQuery.java | 4 ++-- .../sun/tools/hat/internal/server/OQLHelp.java | 5 +---- .../sun/tools/hat/internal/server/OQLQuery.java | 15 +++------------ .../tools/hat/internal/server/QueryHandler.java | 17 +++++++++++++++-- .../hat/internal/server/RefsByTypeQuery.java | 6 +++--- 8 files changed, 33 insertions(+), 36 deletions(-) diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java index d44a8fc2ecf..bdf01b8d5c6 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/AllClassesQuery.java @@ -84,7 +84,7 @@ class AllClassesQuery extends QueryHandler { lastPackage = pkg; printClass(clazz); if (clazz.getId() != -1) { - out.print(" [" + clazz.getIdString() + "]"); + print(" [" + clazz.getIdString() + "]"); } out.println("
"); } diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java index 1d5782390ce..f13572a22cc 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/ClassQuery.java @@ -112,12 +112,12 @@ class ClassQuery extends QueryHandler { out.println("

Instances

"); printAnchorStart(); - out.print("instances/" + encodeForURL(clazz)); + print("instances/" + encodeForURL(clazz)); out.print("\">"); out.println("Exclude subclasses
"); printAnchorStart(); - out.print("allInstances/" + encodeForURL(clazz)); + print("allInstances/" + encodeForURL(clazz)); out.print("\">"); out.println("Include subclasses
"); @@ -126,19 +126,19 @@ class ClassQuery extends QueryHandler { out.println("

New Instances

"); printAnchorStart(); - out.print("newInstances/" + encodeForURL(clazz)); + print("newInstances/" + encodeForURL(clazz)); out.print("\">"); out.println("Exclude subclasses
"); printAnchorStart(); - out.print("allNewInstances/" + encodeForURL(clazz)); + print("allNewInstances/" + encodeForURL(clazz)); out.print("\">"); out.println("Include subclasses
"); } out.println("

References summary by Type

"); printAnchorStart(); - out.print("refsByType/" + encodeForURL(clazz)); + print("refsByType/" + encodeForURL(clazz)); out.print("\">"); out.println("References summary by type"); diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java index f86c8caa8e2..f08c9875c67 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/HttpReader.java @@ -41,21 +41,17 @@ package com.sun.tools.hat.internal.server; import java.net.Socket; -import java.net.ServerSocket; -import java.net.InetAddress; import java.io.InputStream; import java.io.BufferedInputStream; import java.io.IOException; -import java.io.Writer; import java.io.BufferedWriter; import java.io.PrintWriter; -import java.io.OutputStream; import java.io.OutputStreamWriter; -import java.io.BufferedOutputStream; import com.sun.tools.hat.internal.model.Snapshot; import com.sun.tools.hat.internal.oql.OQLEngine; +import com.sun.tools.hat.internal.util.Misc; public class HttpReader implements Runnable { @@ -87,7 +83,7 @@ public class HttpReader implements Runnable { outputError("Protocol error"); } int data; - StringBuffer queryBuf = new StringBuffer(); + StringBuilder queryBuf = new StringBuilder(); while ((data = in.read()) != -1 && data != ' ') { char ch = (char) data; queryBuf.append(ch); @@ -217,7 +213,7 @@ public class HttpReader implements Runnable { private void outputError(String msg) { out.println(); out.println(""); - out.println(msg); + out.println(Misc.encodeHtml(msg)); out.println(""); } diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java index 724b549ca4b..7e87543ef99 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/InstancesCountQuery.java @@ -102,7 +102,7 @@ class InstancesCountQuery extends QueryHandler { int count = clazz.getInstancesCount(false); print("" + count); printAnchorStart(); - out.print("instances/" + encodeForURL(classes[i])); + print("instances/" + encodeForURL(classes[i])); out.print("\"> "); if (count == 1) { print("instance"); @@ -121,7 +121,7 @@ class InstancesCountQuery extends QueryHandler { } print("("); printAnchorStart(); - out.print("newInstances/" + encodeForURL(classes[i])); + print("newInstances/" + encodeForURL(classes[i])); out.print("\">"); print("" + newInst + " new"); out.print(") "); diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java index 6aaa909109a..730d2b7672d 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLHelp.java @@ -54,10 +54,7 @@ class OQLHelp extends QueryHandler { out.print((char)ch); } } catch (Exception exp) { - out.println(exp.getMessage()); - out.println("
");
-            exp.printStackTrace(out);
-            out.println("
"); + printException(exp); } } } diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java index 8e5ec5e2894..3e99bbcbb74 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/OQLQuery.java @@ -32,10 +32,7 @@ package com.sun.tools.hat.internal.server; -import com.sun.tools.hat.internal.model.*; import com.sun.tools.hat.internal.oql.*; -import com.sun.tools.hat.internal.util.ArraySorter; -import com.sun.tools.hat.internal.util.Comparer; /** * This handles Object Query Language (OQL) queries. @@ -68,7 +65,7 @@ class OQLQuery extends QueryHandler { out.println("

"); out.println(""); out.println("

"); @@ -91,10 +88,7 @@ class OQLQuery extends QueryHandler { try { out.println(engine.toHtml(o)); } catch (Exception e) { - out.println(e.getMessage()); - out.println("
");
-                             e.printStackTrace(out);
-                             out.println("
"); + printException(e); } out.println(""); return false; @@ -102,10 +96,7 @@ class OQLQuery extends QueryHandler { }); out.println(""); } catch (OQLException exp) { - out.println(exp.getMessage()); - out.println("
");
-            exp.printStackTrace(out);
-            out.println("
"); + printException(exp); } } diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java index deda0f48058..9a6d93de06a 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/QueryHandler.java @@ -36,6 +36,7 @@ import java.io.PrintWriter; import com.sun.tools.hat.internal.model.*; import com.sun.tools.hat.internal.util.Misc; +import java.io.StringWriter; import java.net.URLEncoder; import java.io.UnsupportedEncodingException; @@ -96,7 +97,7 @@ abstract class QueryHandler { } protected void error(String msg) { - out.println(msg); + println(msg); } protected void printAnchorStart() { @@ -160,7 +161,6 @@ abstract class QueryHandler { out.println("null"); return; } - String name = clazz.getName(); printAnchorStart(); out.print("class/"); print(encodeForURL(clazz)); @@ -208,6 +208,15 @@ abstract class QueryHandler { } } + protected void printException(Throwable t) { + println(t.getMessage()); + out.println("
");
+        StringWriter sw = new StringWriter();
+        t.printStackTrace(new PrintWriter(sw));
+        print(sw.toString());
+        out.println("
"); + } + protected void printHex(long addr) { if (snapshot.getIdentifierSize() == 4) { out.print(Misc.toHex((int)addr)); @@ -223,4 +232,8 @@ abstract class QueryHandler { protected void print(String str) { out.print(Misc.encodeHtml(str)); } + + protected void println(String str) { + out.println(Misc.encodeHtml(str)); + } } diff --git a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java index 5e7de9a8866..3337b471590 100644 --- a/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java +++ b/jdk/src/share/classes/com/sun/tools/hat/internal/server/RefsByTypeQuery.java @@ -89,7 +89,7 @@ public class RefsByTypeQuery extends QueryHandler { out.println("

"); printClass(clazz); if (clazz.getId() != -1) { - out.println("[" + clazz.getIdString() + "]"); + println("[" + clazz.getIdString() + "]"); } out.println("

"); @@ -125,9 +125,9 @@ public class RefsByTypeQuery extends QueryHandler { JavaClass clazz = classes[i]; out.println(""); out.print(""); - out.print(clazz.getName()); + print(clazz.getName()); out.println(""); out.println(""); out.println(map.get(clazz)); From 7ca524c5cd9a36f350d8bb8ba5770df69427e706 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Tue, 7 May 2013 13:37:03 -0700 Subject: [PATCH 002/263] 8013506: Better Pack200 data handling Reviewed-by: jrose, kizune, mschoene --- jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp index 93bf3301546..f7b95b47368 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/zip.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, 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 @@ -340,6 +340,10 @@ uLong jar::get_dostime(int modtime) { struct tm sbuf; (void)memset((void*)&sbuf,0, sizeof(sbuf)); struct tm* s = gmtime_r(&t, &sbuf); + if (s == NULL) { + fprintf(u->errstrm, "Error: gmtime failure, invalid input archive\n"); + exit(2); + } modtime_cache = modtime; dostime_cache = dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec); @@ -384,7 +388,7 @@ bool jar::deflate_bytes(bytes& head, bytes& tail) { } deflated.empty(); - zs.next_out = (uchar*) deflated.grow(len + (len/2)); + zs.next_out = (uchar*) deflated.grow(add_size(len, (len/2))); zs.avail_out = (int)deflated.size(); zs.next_in = (uchar*)head.ptr; From e8457abad47c8c47beafcdbb394bbaf88b30753e Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Thu, 9 May 2013 09:52:55 -0700 Subject: [PATCH 003/263] 8013510: Augment image writing code Reviewed-by: bae, prr --- .../com/sun/imageio/plugins/jpeg/JPEGImageReader.java | 5 +++++ .../com/sun/imageio/plugins/jpeg/JPEGImageWriter.java | 4 ++-- jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index d69200c1408..0b7a865074a 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -1165,6 +1165,11 @@ public class JPEGImageReader extends ImageReader { target = imRas; } int [] bandSizes = target.getSampleModel().getSampleSize(); + for (int i = 0; i < bandSizes.length; i++) { + if (bandSizes[i] <= 0 || bandSizes[i] > 8) { + throw new IIOException("Illegal band size: should be 0 < size <= 8"); + } + } /* * If the process is sequential, and we have restart markers, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index b8564176df8..d9723e7ba20 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -495,8 +495,8 @@ public class JPEGImageWriter extends ImageWriter { // handle <= 8-bit samples. We now check the band sizes and throw // an exception for images, such as USHORT_GRAY, with > 8 bits // per sample. - if (bandSizes[i] > 8) { - throw new IIOException("Sample size must be <= 8"); + if (bandSizes[i] <= 0 || bandSizes[i] > 8) { + throw new IIOException("Illegal band size: should be 0 < size <= 8"); } // 4450894 part 2: We expand IndexColorModel images to full 24- // or 32-bit in grabPixels() for each scanline. For indexed diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index 7411c34bb83..4934c748f61 100644 --- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -2674,6 +2674,15 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_writeImage bandSize = (*env)->GetIntArrayElements(env, bandSizes, NULL); + for (i = 0; i < numBands; i++) { + if (bandSize[i] <= 0 || bandSize[i] > JPEG_BAND_SIZE) { + (*env)->ReleaseIntArrayElements(env, bandSizes, + bandSize, JNI_ABORT); + JNU_ThrowByName(env, "javax/imageio/IIOException", "Invalid Image"); + return JNI_FALSE;; + } + } + for (i = 0; i < numBands; i++) { if (bandSize[i] != JPEG_BAND_SIZE) { if (scale == NULL) { From 7dacefeca149e32a783e18398b5974d6c53bb867 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Tue, 14 May 2013 12:51:59 +0400 Subject: [PATCH 004/263] 8014093: Improve parsing of images Reviewed-by: prr, jgodinez --- .../native/sun/awt/image/awt_parseImage.c | 443 ++++++------------ .../native/sun/awt/image/awt_parseImage.h | 11 +- .../native/sun/awt/medialib/awt_ImagingLib.c | 114 +---- 3 files changed, 151 insertions(+), 417 deletions(-) diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.c b/jdk/src/share/native/sun/awt/image/awt_parseImage.c index e11a8dbee8c..8d6e9a3ed80 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.c +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.c @@ -873,363 +873,204 @@ setHints(JNIEnv *env, BufImageS_t *imageP) { return 1; } -/* - * This routine will fill in a buffer of data for either 1 band or all - * bands (if band == -1). - */ #define MAX_TO_GRAB (10240) -int awt_getPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned char *bufferP) { - int w = rasterP->width; - int h = rasterP->height; - int numBands = rasterP->numBands; +typedef union { + void *pv; + unsigned char *pb; + unsigned short *ps; +} PixelData_t; + + +int awt_getPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) { + const int w = rasterP->width; + const int h = rasterP->height; + const int numBands = rasterP->numBands; int y; int i; - int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); + int maxLines; jobject jsm; - int off; + int off = 0; jarray jdata = NULL; jobject jdatabuffer; int *dataP; - int maxBytes = w; + int maxSamples; + PixelData_t p; + + if (bufferP == NULL) { + return -1; + } + + if (rasterP->dataType != BYTE_DATA_TYPE && + rasterP->dataType != SHORT_DATA_TYPE) + { + return -1; + } + + p.pv = bufferP; + + if (!SAFE_TO_MULT(w, numBands)) { + return -1; + } + maxSamples = w * numBands; + + maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples); + if (maxLines > h) { + maxLines = h; + } + + if (!SAFE_TO_MULT(maxSamples, maxLines)) { + return -1; + } + + maxSamples *= maxLines; jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, g_RasterDataBufferID); - jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); + + jdata = (*env)->NewIntArray(env, maxSamples); if (JNU_IsNull(env, jdata)) { JNU_ThrowOutOfMemoryError(env, "Out of Memory"); return -1; } - /* Here is the generic code */ - if (band >= 0) { - int dOff; - if (band >= numBands) { + for (y = 0; y < h; y += maxLines) { + if (y + maxLines > h) { + maxLines = h - y; + maxSamples = w * numBands * maxLines; + } + + (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, + 0, y, w, + maxLines, jdata, jdatabuffer); + + if ((*env)->ExceptionOccurred(env)) { (*env)->DeleteLocalRef(env, jdata); - JNU_ThrowInternalError(env, "Band out of range."); return -1; } - off = 0; - for (y=0; y < h; ) { - (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - dOff = band; - for (i=0; i < maxBytes; i++, dOff += numBands) { - bufferP[off++] = (unsigned char) dataP[dOff]; - } - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - if (y+maxLines < h) { - y += maxLines; - } - else { - y++; - maxBytes = w; - } - } - } - else { - off = 0; - maxBytes *= numBands; - for (y=0; y < h; ) { - (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - for (i=0; i < maxBytes; i++) { - bufferP[off++] = (unsigned char) dataP[i]; - } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - if (y+maxLines < h) { - y += maxLines; - } - else { - y++; - maxBytes = w*numBands; - } - } - - } - (*env)->DeleteLocalRef(env, jdata); - - return 0; -} -int awt_setPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned char *bufferP) { - int w = rasterP->width; - int h = rasterP->height; - int numBands = rasterP->numBands; - int y; - int i; - int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); - jobject jsm; - int off; - jarray jdata = NULL; - jobject jdatabuffer; - int *dataP; - int maxBytes = w; - - jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); - jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, - g_RasterDataBufferID); - /* Here is the generic code */ - jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); - if (JNU_IsNull(env, jdata)) { - JNU_ThrowOutOfMemoryError(env, "Out of Memory"); - return -1; - } - if (band >= 0) { - int dOff; - if (band >= numBands) { + dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, + NULL); + if (dataP == NULL) { (*env)->DeleteLocalRef(env, jdata); - JNU_ThrowInternalError(env, "Band out of range."); return -1; } - off = 0; - for (y=0; y < h; y+=maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; - } - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - dOff = band; - for (i=0; i < maxBytes; i++, dOff += numBands) { - dataP[dOff] = bufferP[off++]; - } - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - } - } - else { - off = 0; - maxBytes *= numBands; - for (y=0; y < h; y+=maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; + switch (rasterP->dataType) { + case BYTE_DATA_TYPE: + for (i = 0; i < maxSamples; i ++) { + p.pb[off++] = (unsigned char) dataP[i]; } - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; + break; + case SHORT_DATA_TYPE: + for (i = 0; i < maxSamples; i ++) { + p.ps[off++] = (unsigned short) dataP[i]; } - for (i=0; i < maxBytes; i++) { - dataP[i] = bufferP[off++]; - } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); + break; } + (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, + JNI_ABORT); } - (*env)->DeleteLocalRef(env, jdata); - return 0; + return 1; } -int awt_getPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned short *bufferP) { - int w = rasterP->width; - int h = rasterP->height; - int numBands = rasterP->numBands; + +int awt_setPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP) { + const int w = rasterP->width; + const int h = rasterP->height; + const int numBands = rasterP->numBands; + int y; int i; - int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); + int maxLines; jobject jsm; - int off; + int off = 0; jarray jdata = NULL; jobject jdatabuffer; int *dataP; - int maxBytes = w*maxLines; + int maxSamples; + PixelData_t p; + + if (bufferP == NULL) { + return -1; + } + + if (rasterP->dataType != BYTE_DATA_TYPE && + rasterP->dataType != SHORT_DATA_TYPE) + { + return -1; + } + + p.pv = bufferP; + + if (!SAFE_TO_MULT(w, numBands)) { + return -1; + } + maxSamples = w * numBands; + + maxLines = maxSamples > MAX_TO_GRAB ? 1 : (MAX_TO_GRAB / maxSamples); + if (maxLines > h) { + maxLines = h; + } + + if (!SAFE_TO_MULT(maxSamples, maxLines)) { + return -1; + } + + maxSamples *= maxLines; jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, g_RasterDataBufferID); - jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); + + jdata = (*env)->NewIntArray(env, maxSamples); if (JNU_IsNull(env, jdata)) { JNU_ThrowOutOfMemoryError(env, "Out of Memory"); return -1; } - /* Here is the generic code */ - if (band >= 0) { - int dOff; - if (band >= numBands) { + + for (y = 0; y < h; y += maxLines) { + if (y + maxLines > h) { + maxLines = h - y; + maxSamples = w * numBands * maxLines; + } + dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, + NULL); + if (dataP == NULL) { (*env)->DeleteLocalRef(env, jdata); - JNU_ThrowInternalError(env, "Band out of range."); return -1; } - off = 0; - for (y=0; y < h; y += maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; - } - (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - dOff = band; - for (i=0; i < maxBytes; i++, dOff += numBands) { - bufferP[off++] = (unsigned short) dataP[dOff]; + switch (rasterP->dataType) { + case BYTE_DATA_TYPE: + for (i = 0; i < maxSamples; i ++) { + dataP[i] = p.pb[off++]; } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - } - } - else { - off = 0; - maxBytes *= numBands; - for (y=0; y < h; y+=maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; + break; + case SHORT_DATA_TYPE: + for (i = 0; i < maxSamples; i ++) { + dataP[i] = p.ps[off++]; } - (*env)->CallObjectMethod(env, jsm, g_SMGetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - for (i=0; i < maxBytes; i++) { - bufferP[off++] = (unsigned short) dataP[i]; - } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); + break; } + (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, + JNI_ABORT); + + (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, + 0, y, w, + maxLines, jdata, jdatabuffer); + + if ((*env)->ExceptionOccurred(env)) { + (*env)->DeleteLocalRef(env, jdata); + return -1; + } } (*env)->DeleteLocalRef(env, jdata); - return 0; -} -int awt_setPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned short *bufferP) { - int w = rasterP->width; - int h = rasterP->height; - int numBands = rasterP->numBands; - int y; - int i; - int maxLines = (h < MAX_TO_GRAB/w ? h : MAX_TO_GRAB/w); - jobject jsm; - int off; - jarray jdata = NULL; - jobject jdatabuffer; - int *dataP; - int maxBytes = w; - - jsm = (*env)->GetObjectField(env, rasterP->jraster, g_RasterSampleModelID); - jdatabuffer = (*env)->GetObjectField(env, rasterP->jraster, - g_RasterDataBufferID); - if (band >= numBands) { - JNU_ThrowInternalError(env, "Band out of range."); - return -1; - } - /* Here is the generic code */ - jdata = (*env)->NewIntArray(env, maxBytes*rasterP->numBands*maxLines); - if (JNU_IsNull(env, jdata)) { - JNU_ThrowOutOfMemoryError(env, "Out of Memory"); - return -1; - } - if (band >= 0) { - int dOff; - off = 0; - for (y=0; y < h; y+=maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; - } - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - dOff = band; - for (i=0; i < maxBytes; i++, dOff += numBands) { - dataP[dOff] = bufferP[off++]; - } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - } - } - else { - off = 0; - maxBytes *= numBands; - for (y=0; y < h; y+=maxLines) { - if (y+maxLines > h) { - maxBytes = w*numBands; - maxLines = h - y; - } - dataP = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, - NULL); - if (dataP == NULL) { - (*env)->DeleteLocalRef(env, jdata); - return -1; - } - for (i=0; i < maxBytes; i++) { - dataP[i] = bufferP[off++]; - } - - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dataP, - JNI_ABORT); - - (*env)->CallVoidMethod(env, jsm, g_SMSetPixelsMID, - 0, y, w, - maxLines, jdata, jdatabuffer); - } - - } - - (*env)->DeleteLocalRef(env, jdata); - return 0; + + return 1; } diff --git a/jdk/src/share/native/sun/awt/image/awt_parseImage.h b/jdk/src/share/native/sun/awt/image/awt_parseImage.h index b92bb0c2833..02dfd1a2154 100644 --- a/jdk/src/share/native/sun/awt/image/awt_parseImage.h +++ b/jdk/src/share/native/sun/awt/image/awt_parseImage.h @@ -188,13 +188,8 @@ void awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP); void awt_freeParsedImage(BufImageS_t *imageP, int freeImageP); -int awt_getPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned char *bufferP); -int awt_setPixelByte(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned char *bufferP); -int awt_getPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned short *bufferP); -int awt_setPixelShort(JNIEnv *env, int band, RasterS_t *rasterP, - unsigned short *bufferP); +int awt_getPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP); + +int awt_setPixels(JNIEnv *env, RasterS_t *rasterP, void *bufferP); #endif /* AWT_PARSE_IMAGE_H */ diff --git a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c index 25764213888..e3af348adda 100644 --- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c +++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c @@ -700,22 +700,7 @@ Java_sun_awt_image_ImagingLib_convolveRaster(JNIEnv *env, jobject this, /* Means that we couldn't write directly into the destination buffer */ if (ddata == NULL) { - unsigned char *bdataP; - unsigned short *sdataP; - - /* Punt for now */ - switch (dstRasterP->dataType) { - case BYTE_DATA_TYPE: - bdataP = (unsigned char *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ; - break; - case SHORT_DATA_TYPE: - sdataP = (unsigned short *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ; - break; - default: - retStatus = 0; - } + retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst)); } /* Release the pinned memory */ @@ -1119,24 +1104,9 @@ fprintf(stderr,"Flags : %d\n",dst->flags); /* Means that we couldn't write directly into the destination buffer */ if (ddata == NULL) { - unsigned char *bdataP; - unsigned short *sdataP; - /* Need to store it back into the array */ if (storeRasterArray(env, srcRasterP, dstRasterP, dst) < 0) { - /* Punt for now */ - switch (dst->type) { - case MLIB_BYTE: - bdataP = (unsigned char *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ; - break; - case MLIB_SHORT: - sdataP = (unsigned short *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ; - break; - default: - retStatus = 0; - } + retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst)); } } @@ -1704,21 +1674,7 @@ Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env, * the destination buffer */ if (ddata == NULL) { - unsigned char* bdataP; - unsigned short* sdataP; - - switch (dstRasterP->dataType) { - case BYTE_DATA_TYPE: - bdataP = (unsigned char *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelByte(env, -1, dstRasterP, bdataP) >= 0) ; - break; - case SHORT_DATA_TYPE: - sdataP = (unsigned short *) mlib_ImageGetData(dst); - retStatus = (awt_setPixelShort(env, -1, dstRasterP, sdataP) >= 0) ; - break; - default: - retStatus = 0; - } + retStatus = awt_setPixels(env, dstRasterP, mlib_ImageGetData(dst)); } /* Release the LUT */ @@ -2298,7 +2254,6 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, mlib_image **mlibImagePP, void **dataPP, int isSrc) { void *dataP; unsigned char *cDataP; - unsigned short *sdataP; int dataType = BYTE_DATA_TYPE; int width; int height; @@ -2484,8 +2439,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, return -1; } if (isSrc) { - cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); - if (awt_getPixelByte(env, -1, rasterP, cDataP) < 0) { + if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) { (*sMlibSysFns.deleteImageFP)(*mlibImagePP); return -1; } @@ -2499,8 +2453,7 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, return -1; } if (isSrc) { - sdataP = (unsigned short *) mlib_ImageGetData(*mlibImagePP); - if (awt_getPixelShort(env, -1, rasterP, sdataP) < 0) { + if (awt_getPixels(env, rasterP, mlib_ImageGetData(*mlibImagePP)) < 0) { (*sMlibSysFns.deleteImageFP)(*mlibImagePP); return -1; } @@ -2550,60 +2503,6 @@ freeDataArray(JNIEnv *env, jobject srcJdata, mlib_image *srcmlibImP, } } -static int -storeDstArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, - mlibHintS_t *hintP, mlib_image *mlibImP, void *ddata) { - RasterS_t *rasterP = &dstP->raster; - - /* Nothing to do since it is the same image type */ - if (srcP->imageType == dstP->imageType - && srcP->imageType != java_awt_image_BufferedImage_TYPE_CUSTOM - && srcP->imageType != java_awt_image_BufferedImage_TYPE_BYTE_INDEXED - && srcP->imageType != java_awt_image_BufferedImage_TYPE_BYTE_BINARY) { - /* REMIND: Should check the ICM LUTS to see if it is the same */ - return 0; - } - - /* These types are compatible with TYPE_INT_RGB */ - if (srcP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB - && (dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB || - dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE)){ - return 0; - } - - if (hintP->cvtSrcToDefault && - (srcP->cmodel.isAlphaPre == dstP->cmodel.isAlphaPre)) { - if (srcP->cmodel.isAlphaPre) { - if (dstP->imageType == - java_awt_image_BufferedImage_TYPE_INT_ARGB_PRE) - { - return 0; - } - if (!srcP->cmodel.supportsAlpha && - dstP->imageType == java_awt_image_BufferedImage_TYPE_INT_RGB){ - return 0; - } - } - else { - /* REMIND: */ - } - } - - if (dstP->cmodel.cmType == DIRECT_CM_TYPE) { - /* Just need to move bits */ - if (mlibImP->type == MLIB_BYTE) { - return awt_setPixelByte(env, -1, &dstP->raster, - (unsigned char *) mlibImP->data); - } - else if (mlibImP->type == MLIB_SHORT) { - return awt_setPixelByte(env, -1, &dstP->raster, - (unsigned char *) mlibImP->data); - } - } - - return 0; -} - #define ERR_BAD_IMAGE_LAYOUT (-2) #define CHECK_DST_ARRAY(start_offset, elements_per_pixel) \ @@ -2716,8 +2615,7 @@ storeImageArray(JNIEnv *env, BufImageS_t *srcP, BufImageS_t *dstP, } } else if (mlibImP->type == MLIB_SHORT) { - return awt_setPixelShort(env, -1, rasterP, - (unsigned short *) mlibImP->data); + return awt_setPixels(env, rasterP, mlibImP->data); } } else { From 38c8e922af160aeb9e4a054cd779d63011960bd4 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Mon, 20 May 2013 14:39:17 +0400 Subject: [PATCH 005/263] 8013744: Better tabling for AWT Reviewed-by: art, malenkov, skoivu --- jdk/src/share/classes/javax/swing/JTable.java | 18 +++++++++++------- .../share/classes/javax/swing/UIDefaults.java | 12 +++--------- .../javax/swing/text/DefaultFormatter.java | 8 ++++++-- .../javax/swing/text/NumberFormatter.java | 6 +++++- .../classes/sun/swing/SwingLazyValue.java | 3 ++- .../classes/sun/swing/SwingUtilities2.java | 13 +++++++++++++ 6 files changed, 40 insertions(+), 20 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/JTable.java b/jdk/src/share/classes/javax/swing/JTable.java index bed8e5ca93e..3bb97ddfd44 100644 --- a/jdk/src/share/classes/javax/swing/JTable.java +++ b/jdk/src/share/classes/javax/swing/JTable.java @@ -52,6 +52,7 @@ import java.text.MessageFormat; import javax.print.attribute.*; import javax.print.PrintService; +import sun.reflect.misc.ReflectUtil; import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2.Section; @@ -5462,14 +5463,15 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // they have the option to replace the value with // null or use escape to restore the original. // For Strings, return "" for backward compatibility. - if ("".equals(s)) { - if (constructor.getDeclaringClass() == String.class) { - value = s; - } - return super.stopCellEditing(); - } - try { + if ("".equals(s)) { + if (constructor.getDeclaringClass() == String.class) { + value = s; + } + return super.stopCellEditing(); + } + + SwingUtilities2.checkAccess(constructor.getModifiers()); value = constructor.newInstance(new Object[]{s}); } catch (Exception e) { @@ -5493,6 +5495,8 @@ public class JTable extends JComponent implements TableModelListener, Scrollable if (type == Object.class) { type = String.class; } + ReflectUtil.checkPackageAccess(type); + SwingUtilities2.checkAccess(type.getModifiers()); constructor = type.getConstructor(argTypes); } catch (Exception e) { diff --git a/jdk/src/share/classes/javax/swing/UIDefaults.java b/jdk/src/share/classes/javax/swing/UIDefaults.java index 9f304e742c7..3bd1297dd58 100644 --- a/jdk/src/share/classes/javax/swing/UIDefaults.java +++ b/jdk/src/share/classes/javax/swing/UIDefaults.java @@ -53,6 +53,7 @@ import java.security.PrivilegedAction; import sun.reflect.misc.MethodUtil; import sun.reflect.misc.ReflectUtil; +import sun.swing.SwingUtilities2; import sun.util.CoreResourceBundleControl; /** @@ -1101,7 +1102,7 @@ public class UIDefaults extends Hashtable } ReflectUtil.checkPackageAccess(className); c = Class.forName(className, true, (ClassLoader)cl); - checkAccess(c.getModifiers()); + SwingUtilities2.checkAccess(c.getModifiers()); if (methodName != null) { Class[] types = getClassArray(args); Method m = c.getMethod(methodName, types); @@ -1109,7 +1110,7 @@ public class UIDefaults extends Hashtable } else { Class[] types = getClassArray(args); Constructor constructor = c.getConstructor(types); - checkAccess(constructor.getModifiers()); + SwingUtilities2.checkAccess(constructor.getModifiers()); return constructor.newInstance(args); } } catch(Exception e) { @@ -1124,13 +1125,6 @@ public class UIDefaults extends Hashtable }, acc); } - private void checkAccess(int modifiers) { - if(System.getSecurityManager() != null && - !Modifier.isPublic(modifiers)) { - throw new SecurityException("Resource is not accessible"); - } - } - /* * Coerce the array of class types provided into one which * looks the way the Reflection APIs expect. This is done diff --git a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java index b67966ab70a..ac5bc72e76f 100644 --- a/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/DefaultFormatter.java @@ -24,7 +24,8 @@ */ package javax.swing.text; -import sun.reflect.misc.ConstructorUtil; +import sun.reflect.misc.ReflectUtil; +import sun.swing.SwingUtilities2; import java.io.Serializable; import java.lang.reflect.*; @@ -247,7 +248,9 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter Constructor cons; try { - cons = ConstructorUtil.getConstructor(vc, new Class[]{String.class}); + ReflectUtil.checkPackageAccess(vc); + SwingUtilities2.checkAccess(vc.getModifiers()); + cons = vc.getConstructor(new Class[]{String.class}); } catch (NoSuchMethodException nsme) { cons = null; @@ -255,6 +258,7 @@ public class DefaultFormatter extends JFormattedTextField.AbstractFormatter if (cons != null) { try { + SwingUtilities2.checkAccess(cons.getModifiers()); return cons.newInstance(new Object[] { string }); } catch (Throwable ex) { throw new ParseException("Error creating instance", 0); diff --git a/jdk/src/share/classes/javax/swing/text/NumberFormatter.java b/jdk/src/share/classes/javax/swing/text/NumberFormatter.java index 9500dcc03b7..672a92e5b63 100644 --- a/jdk/src/share/classes/javax/swing/text/NumberFormatter.java +++ b/jdk/src/share/classes/javax/swing/text/NumberFormatter.java @@ -27,6 +27,8 @@ package javax.swing.text; import java.lang.reflect.*; import java.text.*; import java.util.*; +import sun.reflect.misc.ReflectUtil; +import sun.swing.SwingUtilities2; /** * NumberFormatter subclasses InternationalFormatter @@ -427,10 +429,12 @@ public class NumberFormatter extends InternationalFormatter { valueClass = value.getClass(); } try { + ReflectUtil.checkPackageAccess(valueClass); + SwingUtilities2.checkAccess(valueClass.getModifiers()); Constructor cons = valueClass.getConstructor( new Class[] { String.class }); - if (cons != null) { + SwingUtilities2.checkAccess(cons.getModifiers()); return cons.newInstance(new Object[]{string}); } } catch (Throwable ex) { } diff --git a/jdk/src/share/classes/sun/swing/SwingLazyValue.java b/jdk/src/share/classes/sun/swing/SwingLazyValue.java index 2d1aa9cf847..a9e6f2c1bc8 100644 --- a/jdk/src/share/classes/sun/swing/SwingLazyValue.java +++ b/jdk/src/share/classes/sun/swing/SwingLazyValue.java @@ -30,6 +30,7 @@ import java.lang.reflect.AccessibleObject; import java.security.AccessController; import java.security.PrivilegedAction; import javax.swing.UIDefaults; +import sun.reflect.misc.ReflectUtil; /** * SwingLazyValue is a copy of ProxyLazyValue that does not snapshot the @@ -63,7 +64,7 @@ public class SwingLazyValue implements UIDefaults.LazyValue { public Object createValue(final UIDefaults table) { try { - Object cl; + ReflectUtil.checkPackageAccess(className); Class c = Class.forName(className, true, null); if (methodName != null) { Class[] types = getClassArray(args); diff --git a/jdk/src/share/classes/sun/swing/SwingUtilities2.java b/jdk/src/share/classes/sun/swing/SwingUtilities2.java index c6134885adf..57f7bb39cdc 100644 --- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java +++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java @@ -1311,6 +1311,19 @@ public class SwingUtilities2 { } } + /** + * Utility method that throws SecurityException if SecurityManager is set + * and modifiers are not public + * + * @param modifiers a set of modifiers + */ + public static void checkAccess(int modifiers) { + if (System.getSecurityManager() != null + && !Modifier.isPublic(modifiers)) { + throw new SecurityException("Resource is not accessible"); + } + } + /** * Returns true if EventQueue.getCurrentEvent() has the permissions to * access the system clipboard and if it is allowed gesture (if From 9a9e180fdd52a65f07849cdd40c72bacd150b99d Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Mon, 20 May 2013 15:26:42 +0400 Subject: [PATCH 006/263] 8014102: Improve image conversion Reviewed-by: mschoene, prr, jgodinez --- .../native/sun/awt/medialib/awt_ImagingLib.c | 94 +++++++++++++------ 1 file changed, 63 insertions(+), 31 deletions(-) diff --git a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c index e3af348adda..5b5f2acda71 100644 --- a/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c +++ b/jdk/src/share/native/sun/awt/medialib/awt_ImagingLib.c @@ -1985,21 +1985,25 @@ expandPacked(JNIEnv *env, BufImageS_t *img, ColorModelS_t *cmP, return 0; } +#define NUM_LINES 10 + static int cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component, unsigned char *dataP) { - ColorModelS_t *cmP = &imageP->cmodel; - RasterS_t *rasterP = &imageP->raster; + const RasterS_t *rasterP = &imageP->raster; + const int w = rasterP->width; + const int h = rasterP->height; + int y; - jobject jpixels = NULL; + jintArray jpixels = NULL; jint *pixels; unsigned char *dP = dataP; -#define NUM_LINES 10 - int numLines = NUM_LINES; + int numLines = h > NUM_LINES ? NUM_LINES : h; + /* it is safe to calculate the scan length, because width has been verified * on creation of the mlib image */ - int scanLength = rasterP->width * 4; + const int scanLength = w * 4; int nbytes = 0; if (!SAFE_TO_MULT(numLines, scanLength)) { @@ -2008,42 +2012,70 @@ cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component, nbytes = numLines * scanLength; - for (y=0; y < rasterP->height; y+=numLines) { - /* getData, one scanline at a time */ - if (y+numLines > rasterP->height) { - numLines = rasterP->height - y; + jpixels = (*env)->NewIntArray(env, nbytes); + if (JNU_IsNull(env, jpixels)) { + JNU_ThrowOutOfMemoryError(env, "Out of Memory"); + return -1; + } + + for (y = 0; y < h; y += numLines) { + if (y + numLines > h) { + numLines = h - y; nbytes = numLines * scanLength; } - jpixels = (*env)->CallObjectMethod(env, imageP->jimage, - g_BImgGetRGBMID, 0, y, - rasterP->width, numLines, - jpixels,0, rasterP->width); - if (jpixels == NULL) { - JNU_ThrowInternalError(env, "Can't retrieve pixels."); + + (*env)->CallObjectMethod(env, imageP->jimage, + g_BImgGetRGBMID, 0, y, + w, numLines, + jpixels, 0, w); + if ((*env)->ExceptionOccurred(env)) { + (*env)->DeleteLocalRef(env, jpixels); return -1; } pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL); + if (pixels == NULL) { + (*env)->DeleteLocalRef(env, jpixels); + return -1; + } + memcpy(dP, pixels, nbytes); dP += nbytes; + (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, JNI_ABORT); } + + /* Need to release the array */ + (*env)->DeleteLocalRef(env, jpixels); + return 0; } static int cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component, unsigned char *dataP) { - ColorModelS_t *cmP = &imageP->cmodel; - RasterS_t *rasterP = &imageP->raster; + const RasterS_t *rasterP = &imageP->raster; + const int w = rasterP->width; + const int h = rasterP->height; + int y; + jintArray jpixels = NULL; jint *pixels; unsigned char *dP = dataP; -#define NUM_LINES 10 - int numLines = NUM_LINES; - int nbytes = rasterP->width*4*NUM_LINES; - jintArray jpixels; + int numLines = h > NUM_LINES ? NUM_LINES : h; + + /* it is safe to calculate the scan length, because width has been verified + * on creation of the mlib image + */ + const int scanLength = w * 4; + + int nbytes = 0; + if (!SAFE_TO_MULT(numLines, scanLength)) { + return -1; + } + + nbytes = numLines * scanLength; jpixels = (*env)->NewIntArray(env, nbytes); if (JNU_IsNull(env, jpixels)) { @@ -2051,14 +2083,15 @@ cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component, return -1; } - for (y=0; y < rasterP->height; y+=NUM_LINES) { - if (y+numLines > rasterP->height) { - numLines = rasterP->height - y; - nbytes = rasterP->width*4*numLines; + for (y = 0; y < h; y += numLines) { + if (y + numLines > h) { + numLines = h - y; + nbytes = numLines * scanLength; } + pixels = (*env)->GetPrimitiveArrayCritical(env, jpixels, NULL); if (pixels == NULL) { - /* JNI error */ + (*env)->DeleteLocalRef(env, jpixels); return -1; } @@ -2067,12 +2100,11 @@ cvtDefaultToCustom(JNIEnv *env, BufImageS_t *imageP, int component, (*env)->ReleasePrimitiveArrayCritical(env, jpixels, pixels, 0); - /* setData, one scanline at a time */ - /* Fix 4223648, 4184283 */ (*env)->CallVoidMethod(env, imageP->jimage, g_BImgSetRGBMID, 0, y, - rasterP->width, numLines, jpixels, 0, - rasterP->width); + w, numLines, jpixels, + 0, w); if ((*env)->ExceptionOccurred(env)) { + (*env)->DeleteLocalRef(env, jpixels); return -1; } } From 5c6c0246ccc0e07d49ec855a939deb8b1ac42e54 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Mon, 20 May 2013 19:49:20 +0400 Subject: [PATCH 007/263] 8012071: Better Building of Beans Reviewed-by: art, skoivu --- jdk/src/share/classes/java/beans/Beans.java | 6 ++++++ .../beans/DefaultPersistenceDelegate.java | 3 +++ .../share/classes/java/beans/MetaData.java | 19 +++++++++++-------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/java/beans/Beans.java b/jdk/src/share/classes/java/beans/Beans.java index 2183d224167..a457fa41805 100644 --- a/jdk/src/share/classes/java/beans/Beans.java +++ b/jdk/src/share/classes/java/beans/Beans.java @@ -42,6 +42,8 @@ import java.io.ObjectInputStream; import java.io.ObjectStreamClass; import java.io.StreamCorruptedException; +import java.lang.reflect.Modifier; + import java.net.URL; import java.security.AccessController; @@ -222,6 +224,10 @@ public class Beans { throw ex; } + if (!Modifier.isPublic(cl.getModifiers())) { + throw new ClassNotFoundException("" + cl + " : no public access"); + } + /* * Try to instantiate the class. */ diff --git a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java index 3c6c7c2a3d3..6891692c30b 100644 --- a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java +++ b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java @@ -221,6 +221,9 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { // Write out the properties of this instance. private void initBean(Class type, Object oldInstance, Object newInstance, Encoder out) { for (Field field : type.getFields()) { + if (!ReflectUtil.isPackageAccessible(field.getDeclaringClass())) { + continue; + } int mod = field.getModifiers(); if (Modifier.isFinal(mod) || Modifier.isStatic(mod) || Modifier.isTransient(mod)) { continue; diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index 61f51d4bb3f..d733b6f1eab 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -42,6 +42,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.lang.reflect.InvocationTargetException; import java.security.AccessController; @@ -56,7 +57,7 @@ import javax.swing.plaf.ColorUIResource; import sun.swing.PrintColorUIResource; -import java.util.Objects; +import static sun.reflect.misc.ReflectUtil.isPackageAccessible; /* * Like the Intropector, the MetaData class @@ -850,13 +851,15 @@ static final class java_awt_AWTKeyStroke_PersistenceDelegate extends Persistence static class StaticFieldsPersistenceDelegate extends PersistenceDelegate { protected void installFields(Encoder out, Class cls) { - Field fields[] = cls.getFields(); - for(int i = 0; i < fields.length; i++) { - Field field = fields[i]; - // Don't install primitives, their identity will not be preserved - // by wrapping. - if (Object.class.isAssignableFrom(field.getType())) { - out.writeExpression(new Expression(field, "get", new Object[]{null})); + if (Modifier.isPublic(cls.getModifiers()) && isPackageAccessible(cls)) { + Field fields[] = cls.getFields(); + for(int i = 0; i < fields.length; i++) { + Field field = fields[i]; + // Don't install primitives, their identity will not be preserved + // by wrapping. + if (Object.class.isAssignableFrom(field.getType())) { + out.writeExpression(new Expression(field, "get", new Object[]{null})); + } } } } From d86660d21bbc69c1991b3d7ea3ce582e080cfcdb Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 31 May 2013 21:25:42 +0400 Subject: [PATCH 008/263] 8012277: Improve AWT DataFlavor Reviewed-by: art, skoivu --- .../java/awt/datatransfer/DataFlavor.java | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java index acbc0fe659d..3c1691545f4 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java +++ b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java @@ -30,6 +30,9 @@ import java.nio.*; import java.util.*; import sun.awt.datatransfer.DataTransferer; +import sun.reflect.misc.ReflectUtil; + +import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; /** * A {@code DataFlavor} provides meta information about data. {@code DataFlavor} @@ -116,26 +119,36 @@ public class DataFlavor implements Externalizable, Cloneable { ClassLoader fallback) throws ClassNotFoundException { - ClassLoader systemClassLoader = (ClassLoader) - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Object run() { - ClassLoader cl = Thread.currentThread(). - getContextClassLoader(); - return (cl != null) - ? cl - : ClassLoader.getSystemClassLoader(); - } - }); - + ReflectUtil.checkPackageAccess(className); try { - return Class.forName(className, true, systemClassLoader); - } catch (ClassNotFoundException e2) { - if (fallback != null) { - return Class.forName(className, true, fallback); - } else { - throw new ClassNotFoundException(className); + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(GET_CLASSLOADER_PERMISSION); } + ClassLoader loader = ClassLoader.getSystemClassLoader(); + try { + // bootstrap class loader and system class loader if present + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException exception) { + // thread context class loader if and only if present + loader = Thread.currentThread().getContextClassLoader(); + if (loader != null) { + try { + return Class.forName(className, true, loader); + } + catch (ClassNotFoundException e) { + // fallback to user's class loader + } + } + } + } catch (SecurityException exception) { + // ignore secured class loaders + } + if (fallback != null) { + return Class.forName(className, true, fallback); + } else { + throw new ClassNotFoundException(className); } } From 81621f63cad78c5a6ebf95d536a2e887bf253f08 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 8 May 2013 09:21:59 +0800 Subject: [PATCH 009/263] 8014341: Better service from Kerberos servers Read incoming data safely and take care of null return value Reviewed-by: valeriep, ahgross --- jdk/src/share/classes/sun/security/krb5/KdcComm.java | 12 ++++++++---- .../sun/security/krb5/internal/NetClient.java | 10 +++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/share/classes/sun/security/krb5/KdcComm.java index 80c0af48e00..c3048aaf64a 100644 --- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java @@ -246,11 +246,15 @@ public final class KdcComm { savedException = e; } } - if (ibuf == null && savedException != null) { - if (savedException instanceof IOException) { - throw (IOException) savedException; + if (ibuf == null) { + if (savedException != null) { + if (savedException instanceof IOException) { + throw (IOException) savedException; + } else { + throw (KrbException) savedException; + } } else { - throw (KrbException) savedException; + throw new IOException("Cannot get a KDC reply"); } } return ibuf; diff --git a/jdk/src/share/classes/sun/security/krb5/internal/NetClient.java b/jdk/src/share/classes/sun/security/krb5/internal/NetClient.java index 1f5b15bb7e6..7502cf00e9a 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/NetClient.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/NetClient.java @@ -31,6 +31,8 @@ package sun.security.krb5.internal; +import sun.misc.IOUtils; + import java.io.*; import java.net.*; @@ -100,17 +102,15 @@ class TCPClient extends NetClient { return null; } - byte data[] = new byte[len]; - count = readFully(data, len); - if (count != len) { + try { + return IOUtils.readFully(in, len, true); + } catch (IOException ioe) { if (Krb5.DEBUG) { System.out.println( ">>>DEBUG: TCPClient could not read complete packet (" + len + "/" + count + ")"); } return null; - } else { - return data; } } From c7d65c420780466e944fdf59f3a5140c73c2d8cf Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 13 Jun 2013 10:21:06 +0800 Subject: [PATCH 010/263] 8013739: Better LDAP resource management Reviewed-by: ahgross, mchung, xuelei --- .../com/sun/jndi/ldap/VersionHelper12.java | 15 ++++++++---- jdk/src/share/classes/java/lang/System.java | 4 ++++ jdk/src/share/classes/java/lang/Thread.java | 24 +++++++++++++++++-- .../classes/sun/misc/JavaLangAccess.java | 8 +++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java b/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java index 9e8854a460c..63e6bd280ba 100644 --- a/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java +++ b/jdk/src/share/classes/com/sun/jndi/ldap/VersionHelper12.java @@ -25,11 +25,12 @@ package com.sun.jndi.ldap; -import java.net.URL; import java.net.URLClassLoader; import java.net.MalformedURLException; +import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; +import sun.misc.SharedSecrets; final class VersionHelper12 extends VersionHelper { @@ -82,12 +83,16 @@ final class VersionHelper12 extends VersionHelper { } Thread createThread(final Runnable r) { + final AccessControlContext acc = AccessController.getContext(); + // 4290486: doPrivileged is needed to create a thread in + // an environment that restricts "modifyThreadGroup". return AccessController.doPrivileged( - new PrivilegedAction() { - public Thread run() { - return new Thread(r); + new PrivilegedAction() { + public Thread run() { + return SharedSecrets.getJavaLangAccess() + .newThreadWithAcc(r, acc); + } } - } ); } } diff --git a/jdk/src/share/classes/java/lang/System.java b/jdk/src/share/classes/java/lang/System.java index 52a5e0de823..445b4e1a959 100644 --- a/jdk/src/share/classes/java/lang/System.java +++ b/jdk/src/share/classes/java/lang/System.java @@ -26,6 +26,7 @@ package java.lang; import java.io.*; import java.lang.reflect.Executable; +import java.security.AccessControlContext; import java.util.Properties; import java.util.PropertyPermission; import java.util.StringTokenizer; @@ -1251,6 +1252,9 @@ public final class System { public String newStringUnsafe(char[] chars) { return new String(chars, true); } + public Thread newThreadWithAcc(Runnable target, AccessControlContext acc) { + return new Thread(target, acc); + } }); } } diff --git a/jdk/src/share/classes/java/lang/Thread.java b/jdk/src/share/classes/java/lang/Thread.java index bb175ff89ad..d97f03d4e24 100644 --- a/jdk/src/share/classes/java/lang/Thread.java +++ b/jdk/src/share/classes/java/lang/Thread.java @@ -340,6 +340,15 @@ class Thread implements Runnable { sleep(millis); } + /** + * Initializes a Thread with the current AccessControlContext. + * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext) + */ + private void init(ThreadGroup g, Runnable target, String name, + long stackSize) { + init(g, target, name, stackSize, null); + } + /** * Initializes a Thread. * @@ -348,9 +357,11 @@ class Thread implements Runnable { * @param name the name of the new Thread * @param stackSize the desired stack size for the new thread, or * zero to indicate that this parameter is to be ignored. + * @param acc the AccessControlContext to inherit, or + * AccessController.getContext() if null */ private void init(ThreadGroup g, Runnable target, String name, - long stackSize) { + long stackSize, AccessControlContext acc) { if (name == null) { throw new NullPointerException("name cannot be null"); } @@ -396,7 +407,8 @@ class Thread implements Runnable { this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; - this.inheritedAccessControlContext = AccessController.getContext(); + this.inheritedAccessControlContext = + acc != null ? acc : AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) @@ -448,6 +460,14 @@ class Thread implements Runnable { init(null, target, "Thread-" + nextThreadNum(), 0); } + /** + * Creates a new Thread that inherits the given AccessControlContext. + * This is not a public constructor. + */ + Thread(Runnable target, AccessControlContext acc) { + init(null, target, "Thread-" + nextThreadNum(), 0, acc); + } + /** * Allocates a new {@code Thread} object. This constructor has the same * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread} diff --git a/jdk/src/share/classes/sun/misc/JavaLangAccess.java b/jdk/src/share/classes/sun/misc/JavaLangAccess.java index 888d4ea8c46..45222f3652e 100644 --- a/jdk/src/share/classes/sun/misc/JavaLangAccess.java +++ b/jdk/src/share/classes/sun/misc/JavaLangAccess.java @@ -27,6 +27,8 @@ package sun.misc; import java.lang.annotation.Annotation; import java.lang.reflect.Executable; +import java.security.AccessControlContext; + import sun.reflect.ConstantPool; import sun.reflect.annotation.AnnotationType; import sun.nio.ch.Interruptible; @@ -107,4 +109,10 @@ public interface JavaLangAccess { * @return a newly created string whose content is the character array */ String newStringUnsafe(char[] chars); + + /** + * Returns a new Thread with the given Runnable and an + * inherited AccessControlContext. + */ + Thread newThreadWithAcc(Runnable target, AccessControlContext acc); } From 0be0627640342d268cad10b1aa1e47fc92312162 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 13 Jun 2013 10:31:21 +0800 Subject: [PATCH 011/263] 8015731: Subject java.security.auth.subject to improvements Reviewed-by: skoivu, mullan --- jdk/src/share/classes/javax/security/auth/Subject.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/javax/security/auth/Subject.java b/jdk/src/share/classes/javax/security/auth/Subject.java index 1caaad400e2..1128d8c1011 100644 --- a/jdk/src/share/classes/javax/security/auth/Subject.java +++ b/jdk/src/share/classes/javax/security/auth/Subject.java @@ -1297,8 +1297,14 @@ public final class Subject implements java.io.Serializable { { ObjectInputStream.GetField fields = ois.readFields(); subject = (Subject) fields.get("this$0", null); - elements = (LinkedList) fields.get("elements", null); which = fields.get("which", 0); + + LinkedList tmp = (LinkedList) fields.get("elements", null); + if (tmp.getClass() != LinkedList.class) { + elements = new LinkedList(tmp); + } else { + elements = tmp; + } } } From 73c5ae165c4ba53d8d168683c24af3241ccb5233 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Thu, 13 Jun 2013 12:14:37 -0700 Subject: [PATCH 012/263] 8014098: Better profile validation Reviewed-by: bae, mschoene, prr --- .../share/native/sun/java2d/cmm/lcms/cmsio0.c | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c index 5bad907e2d7..a18d75c3b5b 100644 --- a/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/cmsio0.c @@ -1074,6 +1074,27 @@ cmsHPROFILE CMSEXPORT cmsOpenProfileFromMem(const void* MemPtr, cmsUInt32Number } +static +cmsBool SanityCheck(_cmsICCPROFILE* profile) +{ + cmsIOHANDLER* io = profile->IOhandler; + if (!io) { + return FALSE; + } + + if (!io->Seek || + !(io->Seek==NULLSeek || io->Seek==MemorySeek || io->Seek==FileSeek)) + { + return FALSE; + } + if (!io->Read || + !(io->Read==NULLRead || io->Read==MemoryRead || io->Read==FileRead)) + { + return FALSE; + } + + return TRUE; +} // Dump tag contents. If the profile is being modified, untouched tags are copied from FileOrig static @@ -1087,6 +1108,7 @@ cmsBool SaveTags(_cmsICCPROFILE* Icc, _cmsICCPROFILE* FileOrig) cmsTagTypeSignature TypeBase; cmsTagTypeHandler* TypeHandler; + if (!SanityCheck(FileOrig)) return FALSE; for (i=0; i < Icc -> TagCount; i++) { @@ -1292,8 +1314,8 @@ cmsBool CMSEXPORT cmsSaveProfileToMem(cmsHPROFILE hProfile, void *MemPtr, cmsUIn // Should we just calculate the needed space? if (MemPtr == NULL) { - *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); - return TRUE; + *BytesNeeded = cmsSaveProfileToIOhandler(hProfile, NULL); + return (*BytesNeeded == 0 ? FALSE : TRUE); } // That is a real write operation From ae96f935a2cb24cf785ee38817c46fd42519bc69 Mon Sep 17 00:00:00 2001 From: Mark Sheppard Date: Fri, 14 Jun 2013 15:49:54 +0100 Subject: [PATCH 013/263] 8011157: Improve CORBA portablility Fix also reviewed by Alexander Fomin Reviewed-by: alanb, coffeys, skoivu --- jdk/make/com/sun/jmx/Makefile | 2 ++ .../modelmbean/RequiredModelMBean.java | 8 ++++++-- .../management/remote/rmi/RMIConnector.java | 18 +++++++++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/jdk/make/com/sun/jmx/Makefile b/jdk/make/com/sun/jmx/Makefile index 62435751673..02ef6b07998 100644 --- a/jdk/make/com/sun/jmx/Makefile +++ b/jdk/make/com/sun/jmx/Makefile @@ -130,11 +130,13 @@ $(CLASSDESTDIR)/%_Stub.class: $(CLASSDESTDIR)/%.class $(RMIC) -classpath "$(CLASSDESTDIR)" \ -d $(CLASSDESTDIR) \ -iiop -v1.2 \ + -emitPermissionCheck \ $(subst /,.,$(<:$(CLASSDESTDIR)/%.class=%)) $(RMIC) $(HOTSPOT_INTERPRETER_FLAG) -classpath "$(CLASSDESTDIR)" \ -d $(CLASSDESTDIR) \ -iiop -v1.2 \ -standardPackage \ + -emitPermissionCheck \ $(subst /,.,$(<:$(CLASSDESTDIR)/%.class=%)) @$(java-vm-cleanup) diff --git a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java index 6d28adaf0f7..0afd70f9423 100644 --- a/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java +++ b/jdk/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -298,11 +298,15 @@ public class RequiredModelMBean RequiredModelMBean.class.getName(), "setModelMBeanInfo(ModelMBeanInfo)", "Setting ModelMBeanInfo to " + printModelMBeanInfo(mbi)); + int noOfNotifications = 0; + if (mbi.getNotifications() != null) { + noOfNotifications = mbi.getNotifications().length; + } MODELMBEAN_LOGGER.logp(Level.FINER, RequiredModelMBean.class.getName(), "setModelMBeanInfo(ModelMBeanInfo)", "ModelMBeanInfo notifications has " + - (mbi.getNotifications()).length + " elements"); + noOfNotifications + " elements"); } modelMBeanInfo = (ModelMBeanInfo)mbi.clone(); diff --git a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java index 53e6754e6ed..4ddfb8fee38 100644 --- a/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java +++ b/jdk/src/share/classes/javax/management/remote/rmi/RMIConnector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, 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 @@ -61,6 +61,7 @@ import java.rmi.server.RemoteRef; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; +import java.security.PrivilegedActionException; import java.security.ProtectionDomain; import java.util.Arrays; import java.util.Collections; @@ -128,7 +129,6 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable Map environment) { if (rmiServer == null && address == null) throw new IllegalArgumentException("rmiServer and jmxServiceURL both null"); - initTransients(); this.rmiServer = rmiServer; @@ -2370,13 +2370,21 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable } } - private static RMIConnection shadowIiopStub(Object stub) + private static RMIConnection shadowIiopStub(Object stub) throws InstantiationException, IllegalAccessException { - Object proxyStub = proxyStubClass.newInstance(); + Object proxyStub = null; + try { + proxyStub = AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + return proxyStubClass.newInstance(); + } + }); + } catch (PrivilegedActionException e) { + throw new InternalError(); + } IIOPHelper.setDelegate(proxyStub, IIOPHelper.getDelegate(stub)); return (RMIConnection) proxyStub; } - private static RMIConnection getConnection(RMIServer server, Object credentials, boolean checkStub) From ccc1dc9103b704a619a638c35d93f689c6798d16 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Thu, 20 Jun 2013 08:51:47 +0200 Subject: [PATCH 014/263] 8014085: Better serialization support in JMX classes Reviewed-by: alanb, dfuchs, skoivu --- .../management/MBeanNotificationInfo.java | 22 ++++- .../javax/management/remote/JMXPrincipal.java | 23 ++++- .../management/remote/JMXServiceURL.java | 99 +++++++++++++------ .../management/remote/NotificationResult.java | 53 +++++++--- .../remote/TargetedNotification.java | 34 +++++-- 5 files changed, 176 insertions(+), 55 deletions(-) diff --git a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java index b4bbbe80292..dfa4ab1f8ff 100644 --- a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java @@ -25,6 +25,9 @@ package javax.management; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.util.Arrays; /** @@ -67,7 +70,7 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable /** * @serial The different types of the notification. */ - private final String[] types; + private String[] types; /** @see MBeanInfo#arrayGettersSafe */ private final transient boolean arrayGettersSafe; @@ -114,9 +117,8 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable notifType, though it doesn't explicitly allow it either. */ - if (notifTypes == null) - notifTypes = NO_TYPES; - this.types = notifTypes; + this.types = (notifTypes != null && notifTypes.length > 0) ? + notifTypes.clone() : NO_TYPES; this.arrayGettersSafe = MBeanInfo.arrayGettersSafe(this.getClass(), MBeanNotificationInfo.class); @@ -203,4 +205,16 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable hash ^= types[i].hashCode(); return hash; } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = ois.readFields(); + String[] t = (String[])gf.get("types", null); + + if (t == null) { + throw new InvalidObjectException("Trying to deserialize an invalid " + + "instance of " + MBeanNotificationInfo.class + + "[types=null]"); + } + types = t.length == 0 ? t : t.clone(); + } } diff --git a/jdk/src/share/classes/javax/management/remote/JMXPrincipal.java b/jdk/src/share/classes/javax/management/remote/JMXPrincipal.java index 258c537e277..5cb0c3739bc 100644 --- a/jdk/src/share/classes/javax/management/remote/JMXPrincipal.java +++ b/jdk/src/share/classes/javax/management/remote/JMXPrincipal.java @@ -26,6 +26,9 @@ package javax.management.remote; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.security.Principal; @@ -64,9 +67,7 @@ public class JMXPrincipal implements Principal, Serializable { * null. */ public JMXPrincipal(String name) { - if (name == null) - throw new NullPointerException("illegal null input"); - + validate(name); this.name = name; } @@ -130,4 +131,20 @@ public class JMXPrincipal implements Principal, Serializable { public int hashCode() { return name.hashCode(); } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = ois.readFields(); + String principalName = (String)gf.get("name", null); + try { + validate(principalName); + this.name = principalName; + } catch (NullPointerException e) { + throw new InvalidObjectException(e.getMessage()); + } + } + + private static void validate(String name) throws NullPointerException { + if (name == null) + throw new NullPointerException("illegal null input"); + } } diff --git a/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java b/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java index 143966bad68..4b1c376eda1 100644 --- a/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java +++ b/jdk/src/share/classes/javax/management/remote/JMXServiceURL.java @@ -29,6 +29,9 @@ package javax.management.remote; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.util.EnvHelp; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.io.Serializable; import java.net.InetAddress; @@ -297,7 +300,7 @@ public class JMXServiceURL implements Serializable { If we're given an explicit host name that is illegal we have to reject it. (Bug 5057532.) */ try { - validateHost(host); + validateHost(host, port); } catch (MalformedURLException e) { if (logger.fineOn()) { logger.fine("JMXServiceURL", @@ -336,36 +339,82 @@ public class JMXServiceURL implements Serializable { validate(); } - private void validate() throws MalformedURLException { + private static final String INVALID_INSTANCE_MSG = + "Trying to deserialize an invalid instance of JMXServiceURL"; + private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = inputStream.readFields(); + String h = (String)gf.get("host", null); + int p = (int)gf.get("port", -1); + String proto = (String)gf.get("protocol", null); + String url = (String)gf.get("urlPath", null); + if (proto == null || url == null || h == null) { + StringBuilder sb = new StringBuilder(INVALID_INSTANCE_MSG).append('['); + boolean empty = true; + if (proto == null) { + sb.append("protocol=null"); + empty = false; + } + if (h == null) { + sb.append(empty ? "" : ",").append("host=null"); + empty = false; + } + if (url == null) { + sb.append(empty ? "" : ",").append("urlPath=null"); + } + sb.append(']'); + throw new InvalidObjectException(sb.toString()); + } + + if (h.contains("[") || h.contains("]")) { + throw new InvalidObjectException("Invalid host name: " + h); + } + + try { + validate(proto, h, p, url); + this.protocol = proto; + this.host = h; + this.port = p; + this.urlPath = url; + } catch (MalformedURLException e) { + throw new InvalidObjectException(INVALID_INSTANCE_MSG + ": " + + e.getMessage()); + } + + } + + private void validate(String proto, String h, int p, String url) + throws MalformedURLException { // Check protocol - - final int protoEnd = indexOfFirstNotInSet(protocol, protocolBitSet, 0); - if (protoEnd == 0 || protoEnd < protocol.length() - || !alphaBitSet.get(protocol.charAt(0))) { + final int protoEnd = indexOfFirstNotInSet(proto, protocolBitSet, 0); + if (protoEnd == 0 || protoEnd < proto.length() + || !alphaBitSet.get(proto.charAt(0))) { throw new MalformedURLException("Missing or invalid protocol " + - "name: \"" + protocol + "\""); + "name: \"" + proto + "\""); } // Check host - - validateHost(); + validateHost(h, p); // Check port - - if (port < 0) - throw new MalformedURLException("Bad port: " + port); + if (p < 0) + throw new MalformedURLException("Bad port: " + p); // Check URL path - - if (urlPath.length() > 0) { - if (!urlPath.startsWith("/") && !urlPath.startsWith(";")) - throw new MalformedURLException("Bad URL path: " + urlPath); + if (url.length() > 0) { + if (!url.startsWith("/") && !url.startsWith(";")) + throw new MalformedURLException("Bad URL path: " + url); } } - private void validateHost() throws MalformedURLException { - if (host.length() == 0) { + private void validate() throws MalformedURLException { + validate(this.protocol, this.host, this.port, this.urlPath); + } + + private static void validateHost(String h, int port) + throws MalformedURLException { + + if (h.length() == 0) { if (port != 0) { throw new MalformedURLException("Cannot give port number " + "without host name"); @@ -373,12 +422,6 @@ public class JMXServiceURL implements Serializable { return; } - validateHost(host); - } - - private static void validateHost(String h) - throws MalformedURLException { - if (isNumericIPv6Address(h)) { /* We assume J2SE >= 1.4 here. Otherwise you can't use the address anyway. We can't call @@ -663,22 +706,22 @@ public class JMXServiceURL implements Serializable { /** * The value returned by {@link #getProtocol()}. */ - private final String protocol; + private String protocol; /** * The value returned by {@link #getHost()}. */ - private final String host; + private String host; /** * The value returned by {@link #getPort()}. */ - private final int port; + private int port; /** * The value returned by {@link #getURLPath()}. */ - private final String urlPath; + private String urlPath; /** * Cached result of {@link #toString()}. diff --git a/jdk/src/share/classes/javax/management/remote/NotificationResult.java b/jdk/src/share/classes/javax/management/remote/NotificationResult.java index cbc79755099..9e7cfaac31d 100644 --- a/jdk/src/share/classes/javax/management/remote/NotificationResult.java +++ b/jdk/src/share/classes/javax/management/remote/NotificationResult.java @@ -25,6 +25,9 @@ package javax.management.remote; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.io.Serializable; /** @@ -76,17 +79,7 @@ public class NotificationResult implements Serializable { public NotificationResult(long earliestSequenceNumber, long nextSequenceNumber, TargetedNotification[] targetedNotifications) { - if (targetedNotifications == null) { - final String msg = "Notifications null"; - throw new IllegalArgumentException(msg); - } - - if (earliestSequenceNumber < 0 || nextSequenceNumber < 0) - throw new IllegalArgumentException("Bad sequence numbers"); - /* We used to check nextSequenceNumber >= earliestSequenceNumber - here. But in fact the opposite can legitimately be true if - notifications have been lost. */ - + validate(targetedNotifications, earliestSequenceNumber, nextSequenceNumber); this.earliestSequenceNumber = earliestSequenceNumber; this.nextSequenceNumber = nextSequenceNumber; this.targetedNotifications = (targetedNotifications.length == 0 ? targetedNotifications : targetedNotifications.clone()); @@ -138,7 +131,39 @@ public class NotificationResult implements Serializable { getTargetedNotifications().length; } - private final long earliestSequenceNumber; - private final long nextSequenceNumber; - private final TargetedNotification[] targetedNotifications; + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = ois.readFields(); + TargetedNotification[] tNotifs = (TargetedNotification[])gf.get("targetedNotifications", null); + long snStart = gf.get("earliestSequenceNumber", -1L); + long snNext = gf.get("nextSequenceNumber", -1L); + try { + validate(tNotifs, snStart, snNext); + + this.targetedNotifications = tNotifs.length == 0 ? tNotifs : tNotifs.clone(); + this.earliestSequenceNumber = snStart; + this.nextSequenceNumber = snNext; + } catch (IllegalArgumentException e) { + throw new InvalidObjectException(e.getMessage()); + } + } + + private long earliestSequenceNumber; + private long nextSequenceNumber; + private TargetedNotification[] targetedNotifications; + + private static void validate(TargetedNotification[] targetedNotifications, + long earliestSequenceNumber, + long nextSequenceNumber) + throws IllegalArgumentException { + if (targetedNotifications == null) { + final String msg = "Notifications null"; + throw new IllegalArgumentException(msg); + } + + if (earliestSequenceNumber < 0 || nextSequenceNumber < 0) + throw new IllegalArgumentException("Bad sequence numbers"); + /* We used to check nextSequenceNumber >= earliestSequenceNumber + here. But in fact the opposite can legitimately be true if + notifications have been lost. */ + } } diff --git a/jdk/src/share/classes/javax/management/remote/TargetedNotification.java b/jdk/src/share/classes/javax/management/remote/TargetedNotification.java index c4b58dfba90..03aa0ca6235 100644 --- a/jdk/src/share/classes/javax/management/remote/TargetedNotification.java +++ b/jdk/src/share/classes/javax/management/remote/TargetedNotification.java @@ -26,6 +26,9 @@ package javax.management.remote; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.io.Serializable; import javax.management.Notification; @@ -73,12 +76,9 @@ public class TargetedNotification implements Serializable { */ public TargetedNotification(Notification notification, Integer listenerID) { + validate(notification, listenerID); // If we replace integer with int... // this(notification,intValue(listenerID)); - if (notification == null) throw new - IllegalArgumentException("Invalid notification: null"); - if (listenerID == null) throw new - IllegalArgumentException("Invalid listener ID: null"); this.notif = notification; this.id = listenerID; } @@ -115,13 +115,13 @@ public class TargetedNotification implements Serializable { * @serial A notification to transmit to the other side. * @see #getNotification() **/ - private final Notification notif; + private Notification notif; /** * @serial The ID of the listener to which the notification is * targeted. * @see #getListenerID() **/ - private final Integer id; + private Integer id; //private final int id; // Needed if we use int instead of Integer... @@ -130,4 +130,26 @@ public class TargetedNotification implements Serializable { // IllegalArgumentException("Invalid listener ID: null"); // return id.intValue(); // } + + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = ois.readFields(); + Notification notification = (Notification)gf.get("notif", null); + Integer listenerId = (Integer)gf.get("id", null); + try { + validate(notification, listenerId); + this.notif = notification; + this.id = listenerId; + } catch (IllegalArgumentException e) { + throw new InvalidObjectException(e.getMessage()); + } + } + + private static void validate(Notification notif, Integer id) throws IllegalArgumentException { + if (notif == null) { + throw new IllegalArgumentException("Invalid notification: null"); + } + if (id == null) { + throw new IllegalArgumentException("Invalid listener ID: null"); + } + } } From d0a47b3b30d11d264021b383ecfe09ebe62a3ecb Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Mon, 1 Jul 2013 15:17:24 +0400 Subject: [PATCH 015/263] 8017287: Better resource disposal Reviewed-by: prr, vadim, skoivu --- jdk/src/share/classes/sun/java2d/Disposer.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/sun/java2d/Disposer.java b/jdk/src/share/classes/sun/java2d/Disposer.java index dcedfe3846e..7be5c3acc92 100644 --- a/jdk/src/share/classes/sun/java2d/Disposer.java +++ b/jdk/src/share/classes/sun/java2d/Disposer.java @@ -155,8 +155,7 @@ public class Disposer implements Runnable { rec = null; clearDeferredRecords(); } catch (Exception e) { - System.out.println("Exception while removing reference: " + e); - e.printStackTrace(); + System.out.println("Exception while removing reference."); } } } @@ -182,7 +181,6 @@ public class Disposer implements Runnable { rec.dispose(); } catch (Exception e) { System.out.println("Exception while disposing deferred rec."); - e.printStackTrace(); } } deferredRecords.clear(); @@ -233,8 +231,7 @@ public class Disposer implements Runnable { } } } catch (Exception e) { - System.out.println("Exception while removing reference: " + e); - e.printStackTrace(); + System.out.println("Exception while removing reference."); } finally { pollingQueue = false; } From 2fc3e6741814a67fe89734348d091dea3f32e529 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Wed, 3 Jul 2013 10:14:02 +0200 Subject: [PATCH 016/263] 8012146: Improve tool support Reviewed-by: ksrini, dholmes, alanb, anthony --- jdk/makefiles/CompileLaunchers.gmk | 6 ++---- jdk/makefiles/Images.gmk | 5 +++++ jdk/test/Makefile | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index 90348b6360f..253fe0231c8 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -52,8 +52,7 @@ endif ifeq ($(OPENJDK_TARGET_OS), macosx) ORIGIN_ARG:=$(call SET_EXECUTABLE_ORIGIN) else - ORIGIN_ARG:=$(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli) \ - $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli) + ORIGIN_ARG:=$(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)/jli) endif # @@ -62,8 +61,7 @@ endif # devloper documentation of JAWT and what worked with OpenJDK6. # ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris),) - ORIGIN_ARG+=$(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)) \ - $(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/jre/lib$(OPENJDK_TARGET_CPU_LIBDIR)) + ORIGIN_ARG+=$(call SET_EXECUTABLE_ORIGIN,$(ORIGIN_ROOT)/lib$(OPENJDK_TARGET_CPU_LIBDIR)) endif define SetupLauncher diff --git a/jdk/makefiles/Images.gmk b/jdk/makefiles/Images.gmk index d265f4cd587..492cf544ab5 100644 --- a/jdk/makefiles/Images.gmk +++ b/jdk/makefiles/Images.gmk @@ -218,6 +218,11 @@ ifeq ($(OPENJDK_TARGET_OS), linux) JDK_LIB_FILES += jexec endif +ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris),) # If Linux or Solaris + JDK_LIB_FILES += $(LIBRARY_PREFIX)jli$(SHARED_LIBRARY_SUFFIX) \ + $(LIBRARY_PREFIX)jawt$(SHARED_LIBRARY_SUFFIX) +endif + # Find all files to copy from $(JDK_OUTPUTDIR)/lib # Jar files are not expected to be here ALL_JDKOUT_LIB_LIST := $(call not-containing,_the.,$(filter-out %.jar,\ diff --git a/jdk/test/Makefile b/jdk/test/Makefile index de6b4a783ff..aac9ef4227b 100644 --- a/jdk/test/Makefile +++ b/jdk/test/Makefile @@ -521,7 +521,8 @@ jdk_other: $(call TestDirs, \ com/sun/org/apache/xerces \ com/sun/corba \ com/sun/tracing \ - sun/usagetracker) + sun/usagetracker \ + misc) $(call RunAgentvmBatch) # Stable agentvm testruns (minus items from PROBLEM_LIST) From f0b7243841e85efcaeda0e7789f961b8201c4d9b Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Wed, 3 Jul 2013 15:10:11 -0700 Subject: [PATCH 017/263] 8011071: Better crypto provider handling Reviewed-by: hawtin, valeriep --- .../com/sun/crypto/provider/DHPrivateKey.java | 18 +------ .../sun/security/ec/ECPrivateKeyImpl.java | 10 +--- .../sun/security/jgss/GSSCredentialImpl.java | 4 +- .../classes/sun/security/pkcs/PKCS8Key.java | 13 +---- .../classes/sun/security/pkcs11/P11Key.java | 48 +------------------ .../sun/security/provider/DSAPrivateKey.java | 7 +-- .../security/rsa/RSAPrivateCrtKeyImpl.java | 27 +---------- .../sun/security/rsa/RSAPrivateKeyImpl.java | 9 +--- 8 files changed, 9 insertions(+), 127 deletions(-) diff --git a/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java b/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java index 1653a239960..cb50886f6eb 100644 --- a/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java +++ b/jdk/src/share/classes/com/sun/crypto/provider/DHPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, 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 @@ -279,22 +279,6 @@ javax.crypto.interfaces.DHPrivateKey, Serializable { return new DHParameterSpec(this.p, this.g); } - public String toString() { - String LINE_SEP = System.getProperty("line.separator"); - - StringBuffer strbuf - = new StringBuffer("SunJCE Diffie-Hellman Private Key:" - + LINE_SEP + "x:" + LINE_SEP - + Debug.toHexString(this.x) - + LINE_SEP + "p:" + LINE_SEP - + Debug.toHexString(this.p) - + LINE_SEP + "g:" + LINE_SEP - + Debug.toHexString(this.g)); - if (this.l != 0) - strbuf.append(LINE_SEP + "l:" + LINE_SEP + " " + this.l); - return strbuf.toString(); - } - private void parseKeyBits() throws InvalidKeyException { try { DerInputStream in = new DerInputStream(this.key); diff --git a/jdk/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java b/jdk/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java index 3bc90ce8071..b974c3ca86c 100644 --- a/jdk/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java +++ b/jdk/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, 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,12 +152,4 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey { throw new InvalidKeyException("Invalid EC private key", e); } } - - // return a string representation of this key for debugging - public String toString() { - return "Sun EC private key, " + params.getCurve().getField().getFieldSize() - + " bits\n private value: " - + s + "\n parameters: " + params; - } - } diff --git a/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java b/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java index 584e1784c8a..65f6847fd3e 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSCredentialImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, 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 @@ -651,7 +651,7 @@ public class GSSCredentialImpl implements ExtendedGSSCredential { buffer.append(element.isAcceptorCredential() ? " Accept" : ""); buffer.append(" ["); - buffer.append(element.toString()); + buffer.append(element.getClass()); buffer.append(']'); } catch (GSSException e) { // skip to next element diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java b/jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java index c53b421da66..59512f11b6e 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java +++ b/jdk/src/share/classes/sun/security/pkcs/PKCS8Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -304,17 +304,6 @@ public class PKCS8Key implements PrivateKey { return encodedKey.clone(); } - /* - * Returns a printable representation of the key - */ - public String toString () - { - HexDumpEncoder encoder = new HexDumpEncoder (); - - return "algorithm = " + algid.toString () - + ", unparsed keybits = \n" + encoder.encodeBuffer (key); - } - /** * Initialize an PKCS8Key object from an input stream. The data * on that input stream must be encoded using DER, obeying the diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java index dd0ec5f7ee1..e85d27efbb3 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -552,27 +552,6 @@ abstract class P11Key implements Key, Length { fetchValues(); return coeff; } - public String toString() { - fetchValues(); - StringBuilder sb = new StringBuilder(super.toString()); - sb.append("\n modulus: "); - sb.append(n); - sb.append("\n public exponent: "); - sb.append(e); - sb.append("\n private exponent: "); - sb.append(d); - sb.append("\n prime p: "); - sb.append(p); - sb.append("\n prime q: "); - sb.append(q); - sb.append("\n prime exponent p: "); - sb.append(pe); - sb.append("\n prime exponent q: "); - sb.append(qe); - sb.append("\n crt coefficient: "); - sb.append(coeff); - return sb.toString(); - } } // RSA non-CRT private key @@ -628,15 +607,6 @@ abstract class P11Key implements Key, Length { fetchValues(); return d; } - public String toString() { - fetchValues(); - StringBuilder sb = new StringBuilder(super.toString()); - sb.append("\n modulus: "); - sb.append(n); - sb.append("\n private exponent: "); - sb.append(d); - return sb.toString(); - } } private static final class P11RSAPublicKey extends P11Key @@ -812,11 +782,6 @@ abstract class P11Key implements Key, Length { fetchValues(); return params; } - public String toString() { - fetchValues(); - return super.toString() + "\n x: " + x + "\n p: " + params.getP() - + "\n q: " + params.getQ() + "\n g: " + params.getG(); - } } private static final class P11DHPrivateKey extends P11Key @@ -876,11 +841,6 @@ abstract class P11Key implements Key, Length { fetchValues(); return params; } - public String toString() { - fetchValues(); - return super.toString() + "\n x: " + x + "\n p: " + params.getP() - + "\n g: " + params.getG(); - } } private static final class P11DHPublicKey extends P11Key @@ -1001,12 +961,6 @@ abstract class P11Key implements Key, Length { fetchValues(); return params; } - public String toString() { - fetchValues(); - return super.toString() - + "\n private value: " + s - + "\n parameters: " + params; - } } private static final class P11ECPublicKey extends P11Key diff --git a/jdk/src/share/classes/sun/security/provider/DSAPrivateKey.java b/jdk/src/share/classes/sun/security/provider/DSAPrivateKey.java index b521e3d2fbd..97e7ef8d7da 100644 --- a/jdk/src/share/classes/sun/security/provider/DSAPrivateKey.java +++ b/jdk/src/share/classes/sun/security/provider/DSAPrivateKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -142,11 +142,6 @@ implements java.security.interfaces.DSAPrivateKey, Serializable { } } - public String toString() { - return "Sun DSA Private Key \nparameters:" + algid + "\nx: " + - Debug.toHexString(x) + "\n"; - } - protected void parseKeyBits() throws InvalidKeyException { try { DerInputStream in = new DerInputStream(key); diff --git a/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java index b289ef2efaa..7e68c427e52 100644 --- a/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java +++ b/jdk/src/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -225,29 +225,4 @@ public final class RSAPrivateCrtKeyImpl } return b; } - - // return a string representation of this key for debugging - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append("Sun RSA private CRT key, "); - sb.append(n.bitLength()); - sb.append(" bits\n modulus: "); - sb.append(n); - sb.append("\n public exponent: "); - sb.append(e); - sb.append("\n private exponent: "); - sb.append(d); - sb.append("\n prime p: "); - sb.append(p); - sb.append("\n prime q: "); - sb.append(q); - sb.append("\n prime exponent p: "); - sb.append(pe); - sb.append("\n prime exponent q: "); - sb.append(qe); - sb.append("\n crt coefficient: "); - sb.append(coeff); - return sb.toString(); - } - } diff --git a/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java b/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java index f9a7c340bf4..1a7df130463 100644 --- a/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java +++ b/jdk/src/share/classes/sun/security/rsa/RSAPrivateKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -98,11 +98,4 @@ public final class RSAPrivateKeyImpl extends PKCS8Key implements RSAPrivateKey { public BigInteger getPrivateExponent() { return d; } - - // return a string representation of this key for debugging - public String toString() { - return "Sun RSA private key, " + n.bitLength() + " bits\n modulus: " - + n + "\n private exponent: " + d; - } - } From 455cd24c9541114abe0a297a27be30c219fe399c Mon Sep 17 00:00:00 2001 From: Dmitry Samersoff Date: Mon, 8 Jul 2013 16:15:39 +0400 Subject: [PATCH 018/263] 8008589: Better MBean permission validation Better MBean permission validation Reviewed-by: skoivu, dfuchs, mchung, sjiang --- .../management/MBeanTrustPermission.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/jdk/src/share/classes/javax/management/MBeanTrustPermission.java b/jdk/src/share/classes/javax/management/MBeanTrustPermission.java index 040f0ddd653..605201a9f8d 100644 --- a/jdk/src/share/classes/javax/management/MBeanTrustPermission.java +++ b/jdk/src/share/classes/javax/management/MBeanTrustPermission.java @@ -26,6 +26,9 @@ package javax.management; import java.security.BasicPermission; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; /** * This permission represents "trust" in a signer or codebase. @@ -75,15 +78,31 @@ public class MBeanTrustPermission extends BasicPermission { */ public MBeanTrustPermission(String name, String actions) { super(name, actions); - /* Check that actions is a null empty string */ - if (actions != null && actions.length() > 0) - throw new IllegalArgumentException("MBeanTrustPermission " + - "actions must be null: " + - actions); + validate(name,actions); + } - if (!name.equals("register") && !name.equals("*")) - throw new IllegalArgumentException("MBeanTrustPermission: " + - "Unknown target name " + + private static void validate(String name, String actions) { + /* Check that actions is a null empty string */ + if (actions != null && actions.length() > 0) { + throw new IllegalArgumentException("MBeanTrustPermission actions must be null: " + + actions); + } + + if (!name.equals("register") && !name.equals("*")) { + throw new IllegalArgumentException("MBeanTrustPermission: Unknown target name " + "[" + name + "]"); + } + } + + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + + // Reading private fields of base class + in.defaultReadObject(); + try { + validate(super.getName(),super.getActions()); + } catch (IllegalArgumentException e) { + throw new InvalidObjectException(e.getMessage()); + } } } From c11a760a1b1481f5a2442c3d70d563fd25e8f6fc Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Thu, 26 Sep 2013 23:05:29 -0700 Subject: [PATCH 019/263] 8025720: Separate temporal interface layer Remove ZoneId and Chronology from TemporalField interface Reviewed-by: sherman --- .../classes/java/time/format/Parsed.java | 2 +- .../classes/java/time/temporal/IsoFields.java | 13 +++++++++-- .../java/time/temporal/JulianFields.java | 7 +++--- .../java/time/temporal/TemporalField.java | 23 +++++++++++-------- .../java/time/temporal/WeekFields.java | 9 ++++---- .../time/format/TCKDateTimeParseResolver.java | 12 ++++------ 6 files changed, 39 insertions(+), 27 deletions(-) diff --git a/jdk/src/share/classes/java/time/format/Parsed.java b/jdk/src/share/classes/java/time/format/Parsed.java index 908c7decaef..a86697a31f3 100644 --- a/jdk/src/share/classes/java/time/format/Parsed.java +++ b/jdk/src/share/classes/java/time/format/Parsed.java @@ -262,7 +262,7 @@ final class Parsed implements TemporalAccessor { while (changedCount < 50) { for (Map.Entry entry : fieldValues.entrySet()) { TemporalField targetField = entry.getKey(); - TemporalAccessor resolvedObject = targetField.resolve(fieldValues, chrono, zone, resolverStyle); + TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle); if (resolvedObject != null) { if (resolvedObject instanceof ChronoZonedDateTime) { ChronoZonedDateTime czdt = (ChronoZonedDateTime) resolvedObject; diff --git a/jdk/src/share/classes/java/time/temporal/IsoFields.java b/jdk/src/share/classes/java/time/temporal/IsoFields.java index bb19c299875..e8ccff15f60 100644 --- a/jdk/src/share/classes/java/time/temporal/IsoFields.java +++ b/jdk/src/share/classes/java/time/temporal/IsoFields.java @@ -69,6 +69,7 @@ import static java.time.temporal.ChronoUnit.MONTHS; import static java.time.temporal.ChronoUnit.WEEKS; import static java.time.temporal.ChronoUnit.YEARS; +import java.time.DateTimeException; import java.time.Duration; import java.time.LocalDate; import java.time.ZoneId; @@ -343,7 +344,7 @@ public final class IsoFields { } @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { Long yearLong = fieldValues.get(YEAR); Long qoyLong = fieldValues.get(QUARTER_OF_YEAR); if (yearLong == null || qoyLong == null) { @@ -351,6 +352,7 @@ public final class IsoFields { } int y = YEAR.checkValidIntValue(yearLong); // always validate long doq = fieldValues.get(DAY_OF_QUARTER); + ensureIso(partialTemporal); LocalDate date; if (resolverStyle == ResolverStyle.LENIENT) { date = LocalDate.of(y, 1, 1).plusMonths(Math.multiplyExact(Math.subtractExact(qoyLong, 1), 3)); @@ -464,7 +466,7 @@ public final class IsoFields { } @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { Long wbyLong = fieldValues.get(WEEK_BASED_YEAR); Long dowLong = fieldValues.get(DAY_OF_WEEK); if (wbyLong == null || dowLong == null) { @@ -472,6 +474,7 @@ public final class IsoFields { } int wby = WEEK_BASED_YEAR.range().checkValidIntValue(wbyLong, WEEK_BASED_YEAR); // always validate long wowby = fieldValues.get(WEEK_OF_WEEK_BASED_YEAR); + ensureIso(partialTemporal); LocalDate date = LocalDate.of(wby, 1, 4); if (resolverStyle == ResolverStyle.LENIENT) { long dow = dowLong; // unvalidated @@ -568,6 +571,12 @@ public final class IsoFields { return Chronology.from(temporal).equals(IsoChronology.INSTANCE); } + private static void ensureIso(TemporalAccessor temporal) { + if (isIso(temporal) == false) { + throw new DateTimeException("Resolve requires IsoChronology"); + } + } + private static ValueRange getWeekRange(LocalDate date) { int wby = getWeekBasedYear(date); date = date.withDayOfYear(1).withYear(wby); diff --git a/jdk/src/share/classes/java/time/temporal/JulianFields.java b/jdk/src/share/classes/java/time/temporal/JulianFields.java index 326f20d222f..f950d87201b 100644 --- a/jdk/src/share/classes/java/time/temporal/JulianFields.java +++ b/jdk/src/share/classes/java/time/temporal/JulianFields.java @@ -291,13 +291,14 @@ public final class JulianFields { //----------------------------------------------------------------------- @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { long value = fieldValues.remove(this); + Chronology chrono = Chronology.from(partialTemporal); if (resolverStyle == ResolverStyle.LENIENT) { - return chronology.dateEpochDay(Math.subtractExact(value, offset)); + return chrono.dateEpochDay(Math.subtractExact(value, offset)); } range().checkValidValue(value, this); - return chronology.dateEpochDay(value - offset); + return chrono.dateEpochDay(value - offset); } //----------------------------------------------------------------------- diff --git a/jdk/src/share/classes/java/time/temporal/TemporalField.java b/jdk/src/share/classes/java/time/temporal/TemporalField.java index e757734510c..51903ede30f 100644 --- a/jdk/src/share/classes/java/time/temporal/TemporalField.java +++ b/jdk/src/share/classes/java/time/temporal/TemporalField.java @@ -62,7 +62,6 @@ package java.time.temporal; import java.time.DateTimeException; -import java.time.ZoneId; import java.time.chrono.Chronology; import java.time.format.ResolverStyle; import java.util.Locale; @@ -338,6 +337,13 @@ public interface TemporalField { * complete {@code LocalDate}. The resolve method will remove all three * fields from the map before returning the {@code LocalDate}. *

+ * A partially complete temporal is used to allow the chronology and zone + * to be queried. In general, only the chronology will be needed. + * Querying items other than the zone or chronology is undefined and + * must not be relied on. + * The behavior of other methods such as {@code get}, {@code getLong}, + * {@code range} and {@code isSupported} is unpredictable and the results undefined. + *

* If resolution should be possible, but the data is invalid, the resolver * style should be used to determine an appropriate level of leniency, which * may require throwing a {@code DateTimeException} or {@code ArithmeticException}. @@ -350,16 +356,14 @@ public interface TemporalField { * instances that can produce a date, such as {@code EPOCH_DAY}. *

* Not all {@code TemporalAccessor} implementations are accepted as return values. - * Implementations must accept {@code ChronoLocalDate}, {@code ChronoLocalDateTime}, - * {@code ChronoZonedDateTime} and {@code LocalTime}. - *

- * The zone is not normally required for resolution, but is provided for completeness. + * Implementations that call this method must accept {@code ChronoLocalDate}, + * {@code ChronoLocalDateTime}, {@code ChronoZonedDateTime} and {@code LocalTime}. *

* The default implementation must return null. * * @param fieldValues the map of fields to values, which can be updated, not null - * @param chronology the effective chronology, not null - * @param zone the effective zone, not null + * @param partialTemporal the partially complete temporal to query for zone and + * chronology; querying for other things is undefined and not recommended, not null * @param resolverStyle the requested type of resolve, not null * @return the resolved temporal object; null if resolving only * changed the map, or no resolve occurred @@ -368,8 +372,9 @@ public interface TemporalField { * by querying a field on the temporal without first checking if it is supported */ default TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, + TemporalAccessor partialTemporal, + ResolverStyle resolverStyle) { return null; } diff --git a/jdk/src/share/classes/java/time/temporal/WeekFields.java b/jdk/src/share/classes/java/time/temporal/WeekFields.java index b3eb1383450..0edfa73e217 100644 --- a/jdk/src/share/classes/java/time/temporal/WeekFields.java +++ b/jdk/src/share/classes/java/time/temporal/WeekFields.java @@ -892,7 +892,7 @@ public final class WeekFields implements Serializable { @Override public ChronoLocalDate resolve( - Map fieldValues, Chronology chronology, ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { final long value = fieldValues.get(this); final int newValue = Math.toIntExact(value); // broad limit makes overflow checking lighter // first convert localized day-of-week to ISO day-of-week @@ -915,19 +915,20 @@ public final class WeekFields implements Serializable { int dow = localizedDayOfWeek(isoDow); // build date + Chronology chrono = Chronology.from(partialTemporal); if (fieldValues.containsKey(YEAR)) { int year = YEAR.checkValidIntValue(fieldValues.get(YEAR)); // validate if (rangeUnit == MONTHS && fieldValues.containsKey(MONTH_OF_YEAR)) { // week-of-month long month = fieldValues.get(MONTH_OF_YEAR); // not validated yet - return resolveWoM(fieldValues, chronology, year, month, newValue, dow, resolverStyle); + return resolveWoM(fieldValues, chrono, year, month, newValue, dow, resolverStyle); } if (rangeUnit == YEARS) { // week-of-year - return resolveWoY(fieldValues, chronology, year, newValue, dow, resolverStyle); + return resolveWoY(fieldValues, chrono, year, newValue, dow, resolverStyle); } } else if ((rangeUnit == WEEK_BASED_YEARS || rangeUnit == FOREVER) && fieldValues.containsKey(weekDef.weekBasedYear) && fieldValues.containsKey(weekDef.weekOfWeekBasedYear)) { // week-of-week-based-year and year-of-week-based-year - return resolveWBY(fieldValues, chronology, dow, resolverStyle); + return resolveWBY(fieldValues, chrono, dow, resolverStyle); } return null; } diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java index 4ef01317b2e..b99d9bb4730 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeParseResolver.java @@ -927,8 +927,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return LocalTime.MIDNIGHT.plusNanos(fieldValues.remove(this)); } }; @@ -979,8 +978,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { fieldValues.remove(this); return LocalDateTime.of(2010, 6, 30, 12, 30); } @@ -1032,8 +1030,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return ThaiBuddhistChronology.INSTANCE.dateNow(); } }; @@ -1082,8 +1079,7 @@ public class TCKDateTimeParseResolver { } @Override public TemporalAccessor resolve( - Map fieldValues, Chronology chronology, - ZoneId zone, ResolverStyle resolverStyle) { + Map fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) { return ZonedDateTime.of(2010, 6, 30, 12, 30, 0, 0, ZoneId.of("Europe/Paris")); } }; From f2ea6795a76bbbaf4c99158d772c946b1f0b0e1e Mon Sep 17 00:00:00 2001 From: Stephen Colebourne Date: Tue, 9 Jul 2013 21:35:04 +0100 Subject: [PATCH 020/263] 8025719: Change Chronology to an interface Split Chronology and add AbstractChronology Reviewed-by: darcy --- .../java/time/chrono/AbstractChronology.java | 783 ++++++++++++++++++ .../java/time/chrono/ChronoLocalDate.java | 2 +- .../java/time/chrono/ChronoLocalDateTime.java | 2 +- .../java/time/chrono/ChronoZonedDateTime.java | 2 +- .../classes/java/time/chrono/Chronology.java | 710 ++-------------- .../java/time/chrono/HijrahChronology.java | 8 +- .../java/time/chrono/IsoChronology.java | 2 +- .../java/time/chrono/JapaneseChronology.java | 2 +- .../java/time/chrono/MinguoChronology.java | 2 +- .../share/classes/java/time/chrono/Ser.java | 4 +- .../time/chrono/ThaiBuddhistChronology.java | 2 +- .../java/time/chrono/CopticChronology.java | 8 +- 12 files changed, 864 insertions(+), 663 deletions(-) create mode 100644 jdk/src/share/classes/java/time/chrono/AbstractChronology.java diff --git a/jdk/src/share/classes/java/time/chrono/AbstractChronology.java b/jdk/src/share/classes/java/time/chrono/AbstractChronology.java new file mode 100644 index 00000000000..89b728e88c9 --- /dev/null +++ b/jdk/src/share/classes/java/time/chrono/AbstractChronology.java @@ -0,0 +1,783 @@ +/* + * Copyright (c) 2012, 2013, 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of JSR-310 nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package java.time.chrono; + +import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; +import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR; +import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH; +import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; +import static java.time.temporal.ChronoField.DAY_OF_MONTH; +import static java.time.temporal.ChronoField.DAY_OF_WEEK; +import static java.time.temporal.ChronoField.DAY_OF_YEAR; +import static java.time.temporal.ChronoField.EPOCH_DAY; +import static java.time.temporal.ChronoField.ERA; +import static java.time.temporal.ChronoField.MONTH_OF_YEAR; +import static java.time.temporal.ChronoField.PROLEPTIC_MONTH; +import static java.time.temporal.ChronoField.YEAR; +import static java.time.temporal.ChronoField.YEAR_OF_ERA; +import static java.time.temporal.ChronoUnit.DAYS; +import static java.time.temporal.ChronoUnit.MONTHS; +import static java.time.temporal.ChronoUnit.WEEKS; +import static java.time.temporal.TemporalAdjuster.nextOrSame; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.io.InvalidObjectException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.time.DateTimeException; +import java.time.DayOfWeek; +import java.time.format.ResolverStyle; +import java.time.temporal.ChronoField; +import java.time.temporal.TemporalAdjuster; +import java.time.temporal.TemporalField; +import java.time.temporal.ValueRange; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import sun.util.logging.PlatformLogger; + +/** + * An abstract implementation of a calendar system, used to organize and identify dates. + *

+ * The main date and time API is built on the ISO calendar system. + * The chronology operates behind the scenes to represent the general concept of a calendar system. + *

+ * See {@link Chronology} for more details. + * + * @implSpec + * This class is separated from the {@code Chronology} interface so that the static methods + * are not inherited. While {@code Chronology} can be implemented directly, it is strongly + * recommended to extend this abstract class instead. + *

+ * This class must be implemented with care to ensure other classes operate correctly. + * All implementations that can be instantiated must be final, immutable and thread-safe. + * Subclasses should be Serializable wherever possible. + * + * @since 1.8 + */ +public abstract class AbstractChronology implements Chronology { + + /** + * ChronoLocalDate order constant. + */ + static final Comparator DATE_ORDER = + (Comparator & Serializable) (date1, date2) -> { + return Long.compare(date1.toEpochDay(), date2.toEpochDay()); + }; + /** + * ChronoLocalDateTime order constant. + */ + static final Comparator> DATE_TIME_ORDER = + (Comparator> & Serializable) (dateTime1, dateTime2) -> { + int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay()); + if (cmp == 0) { + cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay()); + } + return cmp; + }; + /** + * ChronoZonedDateTime order constant. + */ + static final Comparator> INSTANT_ORDER = + (Comparator> & Serializable) (dateTime1, dateTime2) -> { + int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond()); + if (cmp == 0) { + cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano()); + } + return cmp; + }; + + /** + * Map of available calendars by ID. + */ + private static final ConcurrentHashMap CHRONOS_BY_ID = new ConcurrentHashMap<>(); + /** + * Map of available calendars by calendar type. + */ + private static final ConcurrentHashMap CHRONOS_BY_TYPE = new ConcurrentHashMap<>(); + + /** + * Register a Chronology by its ID and type for lookup by {@link #of(String)}. + * Chronologies must not be registered until they are completely constructed. + * Specifically, not in the constructor of Chronology. + * + * @param chrono the chronology to register; not null + * @return the already registered Chronology if any, may be null + */ + static Chronology registerChrono(Chronology chrono) { + return registerChrono(chrono, chrono.getId()); + } + + /** + * Register a Chronology by ID and type for lookup by {@link #of(String)}. + * Chronos must not be registered until they are completely constructed. + * Specifically, not in the constructor of Chronology. + * + * @param chrono the chronology to register; not null + * @param id the ID to register the chronology; not null + * @return the already registered Chronology if any, may be null + */ + static Chronology registerChrono(Chronology chrono, String id) { + Chronology prev = CHRONOS_BY_ID.putIfAbsent(id, chrono); + if (prev == null) { + String type = chrono.getCalendarType(); + if (type != null) { + CHRONOS_BY_TYPE.putIfAbsent(type, chrono); + } + } + return prev; + } + + /** + * Initialization of the maps from id and type to Chronology. + * The ServiceLoader is used to find and register any implementations + * of {@link java.time.chrono.AbstractChronology} found in the bootclass loader. + * The built-in chronologies are registered explicitly. + * Calendars configured via the Thread's context classloader are local + * to that thread and are ignored. + *

+ * The initialization is done only once using the registration + * of the IsoChronology as the test and the final step. + * Multiple threads may perform the initialization concurrently. + * Only the first registration of each Chronology is retained by the + * ConcurrentHashMap. + * @return true if the cache was initialized + */ + private static boolean initCache() { + if (CHRONOS_BY_ID.get("ISO") == null) { + // Initialization is incomplete + + // Register built-in Chronologies + registerChrono(HijrahChronology.INSTANCE); + registerChrono(JapaneseChronology.INSTANCE); + registerChrono(MinguoChronology.INSTANCE); + registerChrono(ThaiBuddhistChronology.INSTANCE); + + // Register Chronologies from the ServiceLoader + @SuppressWarnings("rawtypes") + ServiceLoader loader = ServiceLoader.load(AbstractChronology.class, null); + for (AbstractChronology chrono : loader) { + String id = chrono.getId(); + if (id.equals("ISO") || registerChrono(chrono) != null) { + // Log the attempt to replace an existing Chronology + PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); + logger.warning("Ignoring duplicate Chronology, from ServiceLoader configuration " + id); + } + } + + // finally, register IsoChronology to mark initialization is complete + registerChrono(IsoChronology.INSTANCE); + return true; + } + return false; + } + + //----------------------------------------------------------------------- + /** + * Obtains an instance of {@code Chronology} from a locale. + *

+ * See {@link Chronology#ofLocale(Locale)}. + * + * @param locale the locale to use to obtain the calendar system, not null + * @return the calendar system associated with the locale, not null + * @throws java.time.DateTimeException if the locale-specified calendar cannot be found + */ + static Chronology ofLocale(Locale locale) { + Objects.requireNonNull(locale, "locale"); + String type = locale.getUnicodeLocaleType("ca"); + if (type == null || "iso".equals(type) || "iso8601".equals(type)) { + return IsoChronology.INSTANCE; + } + // Not pre-defined; lookup by the type + do { + Chronology chrono = CHRONOS_BY_TYPE.get(type); + if (chrono != null) { + return chrono; + } + // If not found, do the initialization (once) and repeat the lookup + } while (initCache()); + + // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader + // Application provided Chronologies must not be cached + @SuppressWarnings("rawtypes") + ServiceLoader loader = ServiceLoader.load(Chronology.class); + for (Chronology chrono : loader) { + if (type.equals(chrono.getCalendarType())) { + return chrono; + } + } + throw new DateTimeException("Unknown calendar system: " + type); + } + + //----------------------------------------------------------------------- + /** + * Obtains an instance of {@code Chronology} from a chronology ID or + * calendar system type. + *

+ * See {@link Chronology#of(String)}. + * + * @param id the chronology ID or calendar system type, not null + * @return the chronology with the identifier requested, not null + * @throws java.time.DateTimeException if the chronology cannot be found + */ + static Chronology of(String id) { + Objects.requireNonNull(id, "id"); + do { + Chronology chrono = of0(id); + if (chrono != null) { + return chrono; + } + // If not found, do the initialization (once) and repeat the lookup + } while (initCache()); + + // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader + // Application provided Chronologies must not be cached + @SuppressWarnings("rawtypes") + ServiceLoader loader = ServiceLoader.load(Chronology.class); + for (Chronology chrono : loader) { + if (id.equals(chrono.getId()) || id.equals(chrono.getCalendarType())) { + return chrono; + } + } + throw new DateTimeException("Unknown chronology: " + id); + } + + /** + * Obtains an instance of {@code Chronology} from a chronology ID or + * calendar system type. + * + * @param id the chronology ID or calendar system type, not null + * @return the chronology with the identifier requested, or {@code null} if not found + */ + private static Chronology of0(String id) { + Chronology chrono = CHRONOS_BY_ID.get(id); + if (chrono == null) { + chrono = CHRONOS_BY_TYPE.get(id); + } + return chrono; + } + + /** + * Returns the available chronologies. + *

+ * Each returned {@code Chronology} is available for use in the system. + * The set of chronologies includes the system chronologies and + * any chronologies provided by the application via ServiceLoader + * configuration. + * + * @return the independent, modifiable set of the available chronology IDs, not null + */ + static Set getAvailableChronologies() { + initCache(); // force initialization + HashSet chronos = new HashSet<>(CHRONOS_BY_ID.values()); + + /// Add in Chronologies from the ServiceLoader configuration + @SuppressWarnings("rawtypes") + ServiceLoader loader = ServiceLoader.load(Chronology.class); + for (Chronology chrono : loader) { + chronos.add(chrono); + } + return chronos; + } + + //----------------------------------------------------------------------- + /** + * Creates an instance. + */ + protected AbstractChronology() { + } + + //----------------------------------------------------------------------- + /** + * Resolves parsed {@code ChronoField} values into a date during parsing. + *

+ * Most {@code TemporalField} implementations are resolved using the + * resolve method on the field. By contrast, the {@code ChronoField} class + * defines fields that only have meaning relative to the chronology. + * As such, {@code ChronoField} date fields are resolved here in the + * context of a specific chronology. + *

+ * {@code ChronoField} instances are resolved by this method, which may + * be overridden in subclasses. + *

    + *
  • {@code EPOCH_DAY} - If present, this is converted to a date and + * all other date fields are then cross-checked against the date. + *
  • {@code PROLEPTIC_MONTH} - If present, then it is split into the + * {@code YEAR} and {@code MONTH_OF_YEAR}. If the mode is strict or smart + * then the field is validated. + *
  • {@code YEAR_OF_ERA} and {@code ERA} - If both are present, then they + * are combined to form a {@code YEAR}. In lenient mode, the {@code YEAR_OF_ERA} + * range is not validated, in smart and strict mode it is. The {@code ERA} is + * validated for range in all three modes. If only the {@code YEAR_OF_ERA} is + * present, and the mode is smart or lenient, then the last available era + * is assumed. In strict mode, no era is assumed and the {@code YEAR_OF_ERA} is + * left untouched. If only the {@code ERA} is present, then it is left untouched. + *
  • {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} - + * If all three are present, then they are combined to form a date. + * In all three modes, the {@code YEAR} is validated. + * If the mode is smart or strict, then the month and day are validated. + * If the mode is lenient, then the date is combined in a manner equivalent to + * creating a date on the first day of the first month in the requested year, + * then adding the difference in months, then the difference in days. + * If the mode is smart, and the day-of-month is greater than the maximum for + * the year-month, then the day-of-month is adjusted to the last day-of-month. + * If the mode is strict, then the three fields must form a valid date. + *
  • {@code YEAR} and {@code DAY_OF_YEAR} - + * If both are present, then they are combined to form a date. + * In all three modes, the {@code YEAR} is validated. + * If the mode is lenient, then the date is combined in a manner equivalent to + * creating a date on the first day of the requested year, then adding + * the difference in days. + * If the mode is smart or strict, then the two fields must form a valid date. + *
  • {@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and + * {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} - + * If all four are present, then they are combined to form a date. + * In all three modes, the {@code YEAR} is validated. + * If the mode is lenient, then the date is combined in a manner equivalent to + * creating a date on the first day of the first month in the requested year, then adding + * the difference in months, then the difference in weeks, then in days. + * If the mode is smart or strict, then the all four fields are validated to + * their outer ranges. The date is then combined in a manner equivalent to + * creating a date on the first day of the requested year and month, then adding + * the amount in weeks and days to reach their values. If the mode is strict, + * the date is additionally validated to check that the day and week adjustment + * did not change the month. + *
  • {@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and + * {@code DAY_OF_WEEK} - If all four are present, then they are combined to + * form a date. The approach is the same as described above for + * years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}. + * The day-of-week is adjusted as the next or same matching day-of-week once + * the years, months and weeks have been handled. + *
  • {@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code ALIGNED_DAY_OF_WEEK_IN_YEAR} - + * If all three are present, then they are combined to form a date. + * In all three modes, the {@code YEAR} is validated. + * If the mode is lenient, then the date is combined in a manner equivalent to + * creating a date on the first day of the requested year, then adding + * the difference in weeks, then in days. + * If the mode is smart or strict, then the all three fields are validated to + * their outer ranges. The date is then combined in a manner equivalent to + * creating a date on the first day of the requested year, then adding + * the amount in weeks and days to reach their values. If the mode is strict, + * the date is additionally validated to check that the day and week adjustment + * did not change the year. + *
  • {@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} - + * If all three are present, then they are combined to form a date. + * The approach is the same as described above for years and weeks in + * {@code ALIGNED_DAY_OF_WEEK_IN_YEAR}. The day-of-week is adjusted as the + * next or same matching day-of-week once the years and weeks have been handled. + *
+ *

+ * The default implementation is suitable for most calendar systems. + * If {@link java.time.temporal.ChronoField#YEAR_OF_ERA} is found without an {@link java.time.temporal.ChronoField#ERA} + * then the last era in {@link #eras()} is used. + * The implementation assumes a 7 day week, that the first day-of-month + * has the value 1, that first day-of-year has the value 1, and that the + * first of the month and year always exists. + * + * @param fieldValues the map of fields to values, which can be updated, not null + * @param resolverStyle the requested type of resolve, not null + * @return the resolved date, null if insufficient information to create a date + * @throws java.time.DateTimeException if the date cannot be resolved, typically + * because of a conflict in the input data + */ + @Override + public ChronoLocalDate resolveDate(Map fieldValues, ResolverStyle resolverStyle) { + // check epoch-day before inventing era + if (fieldValues.containsKey(EPOCH_DAY)) { + return dateEpochDay(fieldValues.remove(EPOCH_DAY)); + } + + // fix proleptic month before inventing era + resolveProlepticMonth(fieldValues, resolverStyle); + + // invent era if necessary to resolve year-of-era + ChronoLocalDate resolved = resolveYearOfEra(fieldValues, resolverStyle); + if (resolved != null) { + return resolved; + } + + // build date + if (fieldValues.containsKey(YEAR)) { + if (fieldValues.containsKey(MONTH_OF_YEAR)) { + if (fieldValues.containsKey(DAY_OF_MONTH)) { + return resolveYMD(fieldValues, resolverStyle); + } + if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) { + if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) { + return resolveYMAA(fieldValues, resolverStyle); + } + if (fieldValues.containsKey(DAY_OF_WEEK)) { + return resolveYMAD(fieldValues, resolverStyle); + } + } + } + if (fieldValues.containsKey(DAY_OF_YEAR)) { + return resolveYD(fieldValues, resolverStyle); + } + if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) { + if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) { + return resolveYAA(fieldValues, resolverStyle); + } + if (fieldValues.containsKey(DAY_OF_WEEK)) { + return resolveYAD(fieldValues, resolverStyle); + } + } + } + return null; + } + + void resolveProlepticMonth(Map fieldValues, ResolverStyle resolverStyle) { + Long pMonth = fieldValues.remove(PROLEPTIC_MONTH); + if (pMonth != null) { + if (resolverStyle != ResolverStyle.LENIENT) { + PROLEPTIC_MONTH.checkValidValue(pMonth); + } + // first day-of-month is likely to be safest for setting proleptic-month + // cannot add to year zero, as not all chronologies have a year zero + ChronoLocalDate chronoDate = dateNow() + .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth); + addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR)); + addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR)); + } + } + + ChronoLocalDate resolveYearOfEra(Map fieldValues, ResolverStyle resolverStyle) { + Long yoeLong = fieldValues.remove(YEAR_OF_ERA); + if (yoeLong != null) { + Long eraLong = fieldValues.remove(ERA); + int yoe; + if (resolverStyle != ResolverStyle.LENIENT) { + yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA); + } else { + yoe = Math.toIntExact(yoeLong); + } + if (eraLong != null) { + Era eraObj = eraOf(range(ERA).checkValidIntValue(eraLong, ERA)); + addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe)); + } else { + if (fieldValues.containsKey(YEAR)) { + int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR); + ChronoLocalDate chronoDate = dateYearDay(year, 1); + addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe)); + } else if (resolverStyle == ResolverStyle.STRICT) { + // do not invent era if strict + // reinstate the field removed earlier, no cross-check issues + fieldValues.put(YEAR_OF_ERA, yoeLong); + } else { + List eras = eras(); + if (eras.isEmpty()) { + addFieldValue(fieldValues, YEAR, yoe); + } else { + Era eraObj = eras.get(eras.size() - 1); + addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe)); + } + } + } + } else if (fieldValues.containsKey(ERA)) { + range(ERA).checkValidValue(fieldValues.get(ERA), ERA); // always validated + } + return null; + } + + ChronoLocalDate resolveYMD(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); + long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1); + return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS); + } + int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); + ValueRange domRange = range(DAY_OF_MONTH); + int dom = domRange.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH); + if (resolverStyle == ResolverStyle.SMART) { // previous valid + try { + return date(y, moy, dom); + } catch (DateTimeException ex) { + return date(y, moy, 1).with(TemporalAdjuster.lastDayOfMonth()); + } + } + return date(y, moy, dom); + } + + ChronoLocalDate resolveYD(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1); + return dateYearDay(y, 1).plus(days, DAYS); + } + int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR); + return dateYearDay(y, doy); // smart is same as strict + } + + ChronoLocalDate resolveYMAA(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); + long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1); + return date(y, 1, 1).plus(months, MONTHS).plus(weeks, WEEKS).plus(days, DAYS); + } + int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); + int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH); + int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH); + ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7 + (ad - 1), DAYS); + if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { + throw new DateTimeException("Strict mode rejected resolved date as it is in a different month"); + } + return date; + } + + ChronoLocalDate resolveYMAD(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); + long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); + return resolveAligned(date(y, 1, 1), months, weeks, dow); + } + int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); + int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH); + int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK); + ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow))); + if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { + throw new DateTimeException("Strict mode rejected resolved date as it is in a different month"); + } + return date; + } + + ChronoLocalDate resolveYAA(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); + long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1); + return dateYearDay(y, 1).plus(weeks, WEEKS).plus(days, DAYS); + } + int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR); + int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR); + ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7 + (ad - 1), DAYS); + if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { + throw new DateTimeException("Strict mode rejected resolved date as it is in a different year"); + } + return date; + } + + ChronoLocalDate resolveYAD(Map fieldValues, ResolverStyle resolverStyle) { + int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); + if (resolverStyle == ResolverStyle.LENIENT) { + long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); + long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); + return resolveAligned(dateYearDay(y, 1), 0, weeks, dow); + } + int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR); + int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK); + ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow))); + if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { + throw new DateTimeException("Strict mode rejected resolved date as it is in a different year"); + } + return date; + } + + ChronoLocalDate resolveAligned(ChronoLocalDate base, long months, long weeks, long dow) { + ChronoLocalDate date = base.plus(months, MONTHS).plus(weeks, WEEKS); + if (dow > 7) { + date = date.plus((dow - 1) / 7, WEEKS); + dow = ((dow - 1) % 7) + 1; + } else if (dow < 1) { + date = date.plus(Math.subtractExact(dow, 7) / 7, WEEKS); + dow = ((dow + 6) % 7) + 1; + } + return date.with(nextOrSame(DayOfWeek.of((int) dow))); + } + + /** + * Adds a field-value pair to the map, checking for conflicts. + *

+ * If the field is not already present, then the field-value pair is added to the map. + * If the field is already present and it has the same value as that specified, no action occurs. + * If the field is already present and it has a different value to that specified, then + * an exception is thrown. + * + * @param field the field to add, not null + * @param value the value to add, not null + * @throws java.time.DateTimeException if the field is already present with a different value + */ + void addFieldValue(Map fieldValues, ChronoField field, long value) { + Long old = fieldValues.get(field); // check first for better error message + if (old != null && old.longValue() != value) { + throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value); + } + fieldValues.put(field, value); + } + + //----------------------------------------------------------------------- + /** + * Compares this chronology to another chronology. + *

+ * The comparison order first by the chronology ID string, then by any + * additional information specific to the subclass. + * It is "consistent with equals", as defined by {@link Comparable}. + * + * @implSpec + * This implementation compares the chronology ID. + * Subclasses must compare any additional state that they store. + * + * @param other the other chronology to compare to, not null + * @return the comparator value, negative if less, positive if greater + */ + @Override + public int compareTo(Chronology other) { + return getId().compareTo(other.getId()); + } + + /** + * Checks if this chronology is equal to another chronology. + *

+ * The comparison is based on the entire state of the object. + * + * @implSpec + * This implementation checks the type and calls + * {@link #compareTo(java.time.chrono.Chronology)}. + * + * @param obj the object to check, null returns false + * @return true if this is equal to the other chronology + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof AbstractChronology) { + return compareTo((AbstractChronology) obj) == 0; + } + return false; + } + + /** + * A hash code for this chronology. + *

+ * The hash code should be based on the entire state of the object. + * + * @implSpec + * This implementation is based on the chronology ID and class. + * Subclasses should add any additional state that they store. + * + * @return a suitable hash code + */ + @Override + public int hashCode() { + return getClass().hashCode() ^ getId().hashCode(); + } + + //----------------------------------------------------------------------- + /** + * Outputs this chronology as a {@code String}, using the chronology ID. + * + * @return a string representation of this chronology, not null + */ + @Override + public String toString() { + return getId(); + } + + //----------------------------------------------------------------------- + /** + * Writes the Chronology using a + * dedicated serialized form. + *

+     *  out.writeByte(1);  // identifies this as a Chronology
+     *  out.writeUTF(getId());
+     * 
+ * + * @return the instance of {@code Ser}, not null + */ + Object writeReplace() { + return new Ser(Ser.CHRONO_TYPE, this); + } + + /** + * Defend against malicious streams. + * @return never + * @throws java.io.InvalidObjectException always + */ + private Object readResolve() throws ObjectStreamException { + throw new InvalidObjectException("Deserialization via serialization delegate"); + } + + void writeExternal(DataOutput out) throws IOException { + out.writeUTF(getId()); + } + + static Chronology readExternal(DataInput in) throws IOException { + String id = in.readUTF(); + return Chronology.of(id); + } + +} diff --git a/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java b/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java index 58e4f5d5250..da5f0e719ce 100644 --- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java +++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDate.java @@ -262,7 +262,7 @@ public interface ChronoLocalDate * @see #isEqual */ static Comparator timeLineOrder() { - return Chronology.DATE_ORDER; + return AbstractChronology.DATE_ORDER; } //----------------------------------------------------------------------- diff --git a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java index 4c2ddfd31a7..353673c9dcd 100644 --- a/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java +++ b/jdk/src/share/classes/java/time/chrono/ChronoLocalDateTime.java @@ -136,7 +136,7 @@ public interface ChronoLocalDateTime * @see #isEqual */ static Comparator> timeLineOrder() { - return Chronology.DATE_TIME_ORDER; + return AbstractChronology.DATE_TIME_ORDER; } //----------------------------------------------------------------------- diff --git a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java index 033ab997fdd..caec8558e6e 100644 --- a/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java +++ b/jdk/src/share/classes/java/time/chrono/ChronoZonedDateTime.java @@ -137,7 +137,7 @@ public interface ChronoZonedDateTime * @see #isEqual */ static Comparator> timeLineOrder() { - return Chronology.INSTANT_ORDER; + return AbstractChronology.INSTANT_ORDER; } //----------------------------------------------------------------------- diff --git a/jdk/src/share/classes/java/time/chrono/Chronology.java b/jdk/src/share/classes/java/time/chrono/Chronology.java index ed40f4138f0..22a7e69ae25 100644 --- a/jdk/src/share/classes/java/time/chrono/Chronology.java +++ b/jdk/src/share/classes/java/time/chrono/Chronology.java @@ -61,33 +61,8 @@ */ package java.time.chrono; -import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH; -import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR; -import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH; -import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; -import static java.time.temporal.ChronoField.DAY_OF_MONTH; -import static java.time.temporal.ChronoField.DAY_OF_WEEK; -import static java.time.temporal.ChronoField.DAY_OF_YEAR; -import static java.time.temporal.ChronoField.EPOCH_DAY; -import static java.time.temporal.ChronoField.ERA; -import static java.time.temporal.ChronoField.MONTH_OF_YEAR; -import static java.time.temporal.ChronoField.PROLEPTIC_MONTH; -import static java.time.temporal.ChronoField.YEAR; -import static java.time.temporal.ChronoField.YEAR_OF_ERA; -import static java.time.temporal.ChronoUnit.DAYS; -import static java.time.temporal.ChronoUnit.MONTHS; -import static java.time.temporal.ChronoUnit.WEEKS; -import static java.time.temporal.TemporalAdjuster.nextOrSame; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.io.InvalidObjectException; -import java.io.ObjectStreamException; -import java.io.Serializable; import java.time.Clock; import java.time.DateTimeException; -import java.time.DayOfWeek; import java.time.Instant; import java.time.LocalDate; import java.time.LocalTime; @@ -97,28 +72,21 @@ import java.time.format.ResolverStyle; import java.time.format.TextStyle; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; -import java.time.temporal.TemporalAdjuster; import java.time.temporal.TemporalField; import java.time.temporal.TemporalQuery; import java.time.temporal.UnsupportedTemporalTypeException; import java.time.temporal.ValueRange; -import java.util.Comparator; -import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.ServiceLoader; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import sun.util.logging.PlatformLogger; /** * A calendar system, used to organize and identify dates. *

* The main date and time API is built on the ISO calendar system. - * This class operates behind the scenes to represent the general concept of a calendar system. + * The chronology operates behind the scenes to represent the general concept of a calendar system. * For example, the Japanese, Minguo, Thai Buddhist and others. *

* Most other calendar systems also operate on the shared concepts of year, month and day, @@ -179,130 +147,14 @@ import sun.util.logging.PlatformLogger; * CLDR type and, if applicable, the CLDR variant, * * @implSpec - * This class must be implemented with care to ensure other classes operate correctly. + * This interface must be implemented with care to ensure other classes operate correctly. * All implementations that can be instantiated must be final, immutable and thread-safe. * Subclasses should be Serializable wherever possible. * * @since 1.8 */ -public abstract class Chronology implements Comparable { +public interface Chronology extends Comparable { - /** - * ChronoLocalDate order constant. - */ - static final Comparator DATE_ORDER = - (Comparator & Serializable) (date1, date2) -> { - return Long.compare(date1.toEpochDay(), date2.toEpochDay()); - }; - /** - * ChronoLocalDateTime order constant. - */ - static final Comparator> DATE_TIME_ORDER = - (Comparator> & Serializable) (dateTime1, dateTime2) -> { - int cmp = Long.compare(dateTime1.toLocalDate().toEpochDay(), dateTime2.toLocalDate().toEpochDay()); - if (cmp == 0) { - cmp = Long.compare(dateTime1.toLocalTime().toNanoOfDay(), dateTime2.toLocalTime().toNanoOfDay()); - } - return cmp; - }; - /** - * ChronoZonedDateTime order constant. - */ - static final Comparator> INSTANT_ORDER = - (Comparator> & Serializable) (dateTime1, dateTime2) -> { - int cmp = Long.compare(dateTime1.toEpochSecond(), dateTime2.toEpochSecond()); - if (cmp == 0) { - cmp = Long.compare(dateTime1.toLocalTime().getNano(), dateTime2.toLocalTime().getNano()); - } - return cmp; - }; - - /** - * Map of available calendars by ID. - */ - private static final ConcurrentHashMap CHRONOS_BY_ID = new ConcurrentHashMap<>(); - /** - * Map of available calendars by calendar type. - */ - private static final ConcurrentHashMap CHRONOS_BY_TYPE = new ConcurrentHashMap<>(); - - /** - * Register a Chronology by its ID and type for lookup by {@link #of(java.lang.String)}. - * Chronologies must not be registered until they are completely constructed. - * Specifically, not in the constructor of Chronology. - * - * @param chrono the chronology to register; not null - * @return the already registered Chronology if any, may be null - */ - static Chronology registerChrono(Chronology chrono) { - return registerChrono(chrono, chrono.getId()); - } - - /** - * Register a Chronology by ID and type for lookup by {@link #of(java.lang.String)}. - * Chronos must not be registered until they are completely constructed. - * Specifically, not in the constructor of Chronology. - * - * @param chrono the chronology to register; not null - * @param id the ID to register the chronology; not null - * @return the already registered Chronology if any, may be null - */ - static Chronology registerChrono(Chronology chrono, String id) { - Chronology prev = CHRONOS_BY_ID.putIfAbsent(id, chrono); - if (prev == null) { - String type = chrono.getCalendarType(); - if (type != null) { - CHRONOS_BY_TYPE.putIfAbsent(type, chrono); - } - } - return prev; - } - - /** - * Initialization of the maps from id and type to Chronology. - * The ServiceLoader is used to find and register any implementations - * of {@link java.time.chrono.Chronology} found in the bootclass loader. - * The built-in chronologies are registered explicitly. - * Calendars configured via the Thread's context classloader are local - * to that thread and are ignored. - *

- * The initialization is done only once using the registration - * of the IsoChronology as the test and the final step. - * Multiple threads may perform the initialization concurrently. - * Only the first registration of each Chronology is retained by the - * ConcurrentHashMap. - * @return true if the cache was initialized - */ - private static boolean initCache() { - if (CHRONOS_BY_ID.get("ISO") == null) { - // Initialization is incomplete - - // Register built-in Chronologies - registerChrono(HijrahChronology.INSTANCE); - registerChrono(JapaneseChronology.INSTANCE); - registerChrono(MinguoChronology.INSTANCE); - registerChrono(ThaiBuddhistChronology.INSTANCE); - - // Register Chronologies from the ServiceLoader - @SuppressWarnings("rawtypes") - ServiceLoader loader = ServiceLoader.load(Chronology.class, null); - for (Chronology chrono : loader) { - String id = chrono.getId(); - if (id.equals("ISO") || registerChrono(chrono) != null) { - // Log the attempt to replace an existing Chronology - PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); - logger.warning("Ignoring duplicate Chronology, from ServiceLoader configuration " + id); - } - } - - // finally, register IsoChronology to mark initialization is complete - registerChrono(IsoChronology.INSTANCE); - return true; - } - return false; - } - - //----------------------------------------------------------------------- /** * Obtains an instance of {@code Chronology} from a temporal object. *

@@ -320,7 +172,7 @@ public abstract class Chronology implements Comparable { * @return the chronology, not null * @throws DateTimeException if unable to convert to an {@code Chronology} */ - public static Chronology from(TemporalAccessor temporal) { + static Chronology from(TemporalAccessor temporal) { Objects.requireNonNull(temporal, "temporal"); Chronology obj = temporal.query(TemporalQuery.chronology()); return (obj != null ? obj : IsoChronology.INSTANCE); @@ -367,31 +219,8 @@ public abstract class Chronology implements Comparable { * @return the calendar system associated with the locale, not null * @throws DateTimeException if the locale-specified calendar cannot be found */ - public static Chronology ofLocale(Locale locale) { - Objects.requireNonNull(locale, "locale"); - String type = locale.getUnicodeLocaleType("ca"); - if (type == null || "iso".equals(type) || "iso8601".equals(type)) { - return IsoChronology.INSTANCE; - } - // Not pre-defined; lookup by the type - do { - Chronology chrono = CHRONOS_BY_TYPE.get(type); - if (chrono != null) { - return chrono; - } - // If not found, do the initialization (once) and repeat the lookup - } while (initCache()); - - // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader - // Application provided Chronologies must not be cached - @SuppressWarnings("rawtypes") - ServiceLoader loader = ServiceLoader.load(Chronology.class); - for (Chronology chrono : loader) { - if (type.equals(chrono.getCalendarType())) { - return chrono; - } - } - throw new DateTimeException("Unknown calendar system: " + type); + static Chronology ofLocale(Locale locale) { + return AbstractChronology.ofLocale(locale); } //----------------------------------------------------------------------- @@ -415,41 +244,8 @@ public abstract class Chronology implements Comparable { * @return the chronology with the identifier requested, not null * @throws DateTimeException if the chronology cannot be found */ - public static Chronology of(String id) { - Objects.requireNonNull(id, "id"); - do { - Chronology chrono = of0(id); - if (chrono != null) { - return chrono; - } - // If not found, do the initialization (once) and repeat the lookup - } while (initCache()); - - // Look for a Chronology using ServiceLoader of the Thread's ContextClassLoader - // Application provided Chronologies must not be cached - @SuppressWarnings("rawtypes") - ServiceLoader loader = ServiceLoader.load(Chronology.class); - for (Chronology chrono : loader) { - if (id.equals(chrono.getId()) || id.equals(chrono.getCalendarType())) { - return chrono; - } - } - throw new DateTimeException("Unknown chronology: " + id); - } - - /** - * Obtains an instance of {@code Chronology} from a chronology ID or - * calendar system type. - * - * @param id the chronology ID or calendar system type, not null - * @return the chronology with the identifier requested, or {@code null} if not found - */ - private static Chronology of0(String id) { - Chronology chrono = CHRONOS_BY_ID.get(id); - if (chrono == null) { - chrono = CHRONOS_BY_TYPE.get(id); - } - return chrono; + static Chronology of(String id) { + return AbstractChronology.of(id); } /** @@ -462,24 +258,8 @@ public abstract class Chronology implements Comparable { * * @return the independent, modifiable set of the available chronology IDs, not null */ - public static Set getAvailableChronologies() { - initCache(); // force initialization - HashSet chronos = new HashSet<>(CHRONOS_BY_ID.values()); - - /// Add in Chronologies from the ServiceLoader configuration - @SuppressWarnings("rawtypes") - ServiceLoader loader = ServiceLoader.load(Chronology.class); - for (Chronology chrono : loader) { - chronos.add(chrono); - } - return chronos; - } - - //----------------------------------------------------------------------- - /** - * Creates an instance. - */ - protected Chronology() { + static Set getAvailableChronologies() { + return AbstractChronology.getAvailableChronologies(); } //----------------------------------------------------------------------- @@ -492,7 +272,7 @@ public abstract class Chronology implements Comparable { * @return the chronology ID, not null * @see #getCalendarType() */ - public abstract String getId(); + String getId(); /** * Gets the calendar type of the calendar system. @@ -507,13 +287,17 @@ public abstract class Chronology implements Comparable { * @return the calendar system type, null if the calendar is not defined by CLDR/LDML * @see #getId() */ - public abstract String getCalendarType(); + String getCalendarType(); //----------------------------------------------------------------------- /** * Obtains a local date in this chronology from the era, year-of-era, * month-of-year and day-of-month fields. * + * @implSpec + * The default implementation combines the era and year-of-era into a proleptic + * year before calling {@link #date(int, int, int)}. + * * @param era the era of the correct type for the chronology, not null * @param yearOfEra the chronology year-of-era * @param month the chronology month-of-year @@ -522,7 +306,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if unable to create the date * @throws ClassCastException if the {@code era} is not of the correct type for the chronology */ - public ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) { + default ChronoLocalDate date(Era era, int yearOfEra, int month, int dayOfMonth) { return date(prolepticYear(era, yearOfEra), month, dayOfMonth); } @@ -536,12 +320,16 @@ public abstract class Chronology implements Comparable { * @return the local date in this chronology, not null * @throws DateTimeException if unable to create the date */ - public abstract ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth); + ChronoLocalDate date(int prolepticYear, int month, int dayOfMonth); /** * Obtains a local date in this chronology from the era, year-of-era and * day-of-year fields. * + * @implSpec + * The default implementation combines the era and year-of-era into a proleptic + * year before calling {@link #dateYearDay(int, int)}. + * * @param era the era of the correct type for the chronology, not null * @param yearOfEra the chronology year-of-era * @param dayOfYear the chronology day-of-year @@ -549,7 +337,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if unable to create the date * @throws ClassCastException if the {@code era} is not of the correct type for the chronology */ - public ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) { + default ChronoLocalDate dateYearDay(Era era, int yearOfEra, int dayOfYear) { return dateYearDay(prolepticYear(era, yearOfEra), dayOfYear); } @@ -562,7 +350,7 @@ public abstract class Chronology implements Comparable { * @return the local date in this chronology, not null * @throws DateTimeException if unable to create the date */ - public abstract ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear); + ChronoLocalDate dateYearDay(int prolepticYear, int dayOfYear); /** * Obtains a local date in this chronology from the epoch-day. @@ -574,7 +362,7 @@ public abstract class Chronology implements Comparable { * @return the local date in this chronology, not null * @throws DateTimeException if unable to create the date */ - public abstract ChronoLocalDate dateEpochDay(long epochDay); + ChronoLocalDate dateEpochDay(long epochDay); //----------------------------------------------------------------------- /** @@ -585,13 +373,14 @@ public abstract class Chronology implements Comparable { *

* Using this method will prevent the ability to use an alternate clock for testing * because the clock is hard-coded. - *

- * This implementation uses {@link #dateNow(Clock)}. + * + * @implSpec + * The default implementation invokes {@link #dateNow(Clock)}. * * @return the current local date using the system clock and default time-zone, not null * @throws DateTimeException if unable to create the date */ - public ChronoLocalDate dateNow() { + default ChronoLocalDate dateNow() { return dateNow(Clock.systemDefaultZone()); } @@ -604,11 +393,14 @@ public abstract class Chronology implements Comparable { * Using this method will prevent the ability to use an alternate clock for testing * because the clock is hard-coded. * + * @implSpec + * The default implementation invokes {@link #dateNow(Clock)}. + * * @param zone the zone ID to use, not null * @return the current local date using the system clock, not null * @throws DateTimeException if unable to create the date */ - public ChronoLocalDate dateNow(ZoneId zone) { + default ChronoLocalDate dateNow(ZoneId zone) { return dateNow(Clock.system(zone)); } @@ -619,11 +411,14 @@ public abstract class Chronology implements Comparable { * Using this method allows the use of an alternate clock for testing. * The alternate clock may be introduced using {@link Clock dependency injection}. * + * @implSpec + * The default implementation invokes {@link #date(TemporalAccessor)} )}. + * * @param clock the clock to use, not null * @return the current local date, not null * @throws DateTimeException if unable to create the date */ - public ChronoLocalDate dateNow(Clock clock) { + default ChronoLocalDate dateNow(Clock clock) { Objects.requireNonNull(clock, "clock"); return date(LocalDate.now(clock)); } @@ -647,7 +442,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if unable to create the date * @see ChronoLocalDate#from(TemporalAccessor) */ - public abstract ChronoLocalDate date(TemporalAccessor temporal); + ChronoLocalDate date(TemporalAccessor temporal); /** * Obtains a local date-time in this chronology from another temporal object. @@ -670,7 +465,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if unable to create the date-time * @see ChronoLocalDateTime#from(TemporalAccessor) */ - public ChronoLocalDateTime localDateTime(TemporalAccessor temporal) { + default ChronoLocalDateTime localDateTime(TemporalAccessor temporal) { try { return date(temporal).atTime(LocalTime.from(temporal)); } catch (DateTimeException ex) { @@ -702,7 +497,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if unable to create the date-time * @see ChronoZonedDateTime#from(TemporalAccessor) */ - public ChronoZonedDateTime zonedDateTime(TemporalAccessor temporal) { + default ChronoZonedDateTime zonedDateTime(TemporalAccessor temporal) { try { ZoneId zone = ZoneId.from(temporal); try { @@ -728,7 +523,7 @@ public abstract class Chronology implements Comparable { * @return the zoned date-time, not null * @throws DateTimeException if the result exceeds the supported range */ - public ChronoZonedDateTime zonedDateTime(Instant instant, ZoneId zone) { + default ChronoZonedDateTime zonedDateTime(Instant instant, ZoneId zone) { return ChronoZonedDateTimeImpl.ofInstant(this, instant, zone); } @@ -746,7 +541,7 @@ public abstract class Chronology implements Comparable { * @param prolepticYear the proleptic-year to check, not validated for range * @return true if the year is a leap year */ - public abstract boolean isLeapYear(long prolepticYear); + boolean isLeapYear(long prolepticYear); /** * Calculates the proleptic-year given the era and year-of-era. @@ -764,7 +559,7 @@ public abstract class Chronology implements Comparable { * such as if the year is invalid for the era * @throws ClassCastException if the {@code era} is not of the correct type for the chronology */ - public abstract int prolepticYear(Era era, int yearOfEra); + int prolepticYear(Era era, int yearOfEra); /** * Creates the chronology era object from the numeric value. @@ -785,7 +580,7 @@ public abstract class Chronology implements Comparable { * @return the calendar system era, not null * @throws DateTimeException if unable to create the era */ - public abstract Era eraOf(int eraValue); + Era eraOf(int eraValue); /** * Gets the list of eras for the chronology. @@ -796,7 +591,7 @@ public abstract class Chronology implements Comparable { * * @return the list of eras for the chronology, may be immutable, not null */ - public abstract List eras(); + List eras(); //----------------------------------------------------------------------- /** @@ -815,7 +610,7 @@ public abstract class Chronology implements Comparable { * @return the range of valid values for the field, not null * @throws DateTimeException if the range for the field cannot be obtained */ - public abstract ValueRange range(ChronoField field); + ValueRange range(ChronoField field); //----------------------------------------------------------------------- /** @@ -825,28 +620,16 @@ public abstract class Chronology implements Comparable { * suitable for presentation to the user. * The parameters control the style of the returned text and the locale. * + * @implSpec + * The default implementation behaves as the the formatter was used to + * format the chronology textual name. + * * @param style the style of the text required, not null * @param locale the locale to use, not null * @return the text value of the chronology, not null */ - public String getDisplayName(TextStyle style, Locale locale) { - return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(toTemporal()); - } - - /** - * Converts this chronology to a {@code TemporalAccessor}. - *

- * A {@code Chronology} can be fully represented as a {@code TemporalAccessor}. - * However, the interface is not implemented by this class as most of the - * methods on the interface have no meaning to {@code Chronology}. - *

- * The returned temporal has no supported fields, with the query method - * supporting the return of the chronology using {@link TemporalQuery#chronology()}. - * - * @return a temporal equivalent to this chronology, not null - */ - private TemporalAccessor toTemporal() { - return new TemporalAccessor() { + default String getDisplayName(TextStyle style, Locale locale) { + TemporalAccessor temporal = new TemporalAccessor() { @Override public boolean isSupported(TemporalField field) { return false; @@ -864,6 +647,7 @@ public abstract class Chronology implements Comparable { return TemporalAccessor.super.query(query); } }; + return new DateTimeFormatterBuilder().appendChronologyText(style).toFormatter(locale).format(temporal); } //----------------------------------------------------------------------- @@ -876,82 +660,8 @@ public abstract class Chronology implements Comparable { * As such, {@code ChronoField} date fields are resolved here in the * context of a specific chronology. *

- * {@code ChronoField} instances are resolved by this method, which may - * be overridden in subclasses. - *

    - *
  • {@code EPOCH_DAY} - If present, this is converted to a date and - * all other date fields are then cross-checked against the date. - *
  • {@code PROLEPTIC_MONTH} - If present, then it is split into the - * {@code YEAR} and {@code MONTH_OF_YEAR}. If the mode is strict or smart - * then the field is validated. - *
  • {@code YEAR_OF_ERA} and {@code ERA} - If both are present, then they - * are combined to form a {@code YEAR}. In lenient mode, the {@code YEAR_OF_ERA} - * range is not validated, in smart and strict mode it is. The {@code ERA} is - * validated for range in all three modes. If only the {@code YEAR_OF_ERA} is - * present, and the mode is smart or lenient, then the last available era - * is assumed. In strict mode, no era is assumed and the {@code YEAR_OF_ERA} is - * left untouched. If only the {@code ERA} is present, then it is left untouched. - *
  • {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} - - * If all three are present, then they are combined to form a date. - * In all three modes, the {@code YEAR} is validated. - * If the mode is smart or strict, then the month and day are validated. - * If the mode is lenient, then the date is combined in a manner equivalent to - * creating a date on the first day of the first month in the requested year, - * then adding the difference in months, then the difference in days. - * If the mode is smart, and the day-of-month is greater than the maximum for - * the year-month, then the day-of-month is adjusted to the last day-of-month. - * If the mode is strict, then the three fields must form a valid date. - *
  • {@code YEAR} and {@code DAY_OF_YEAR} - - * If both are present, then they are combined to form a date. - * In all three modes, the {@code YEAR} is validated. - * If the mode is lenient, then the date is combined in a manner equivalent to - * creating a date on the first day of the requested year, then adding - * the difference in days. - * If the mode is smart or strict, then the two fields must form a valid date. - *
  • {@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and - * {@code ALIGNED_DAY_OF_WEEK_IN_MONTH} - - * If all four are present, then they are combined to form a date. - * In all three modes, the {@code YEAR} is validated. - * If the mode is lenient, then the date is combined in a manner equivalent to - * creating a date on the first day of the first month in the requested year, then adding - * the difference in months, then the difference in weeks, then in days. - * If the mode is smart or strict, then the all four fields are validated to - * their outer ranges. The date is then combined in a manner equivalent to - * creating a date on the first day of the requested year and month, then adding - * the amount in weeks and days to reach their values. If the mode is strict, - * the date is additionally validated to check that the day and week adjustment - * did not change the month. - *
  • {@code YEAR}, {@code MONTH_OF_YEAR}, {@code ALIGNED_WEEK_OF_MONTH} and - * {@code DAY_OF_WEEK} - If all four are present, then they are combined to - * form a date. The approach is the same as described above for - * years, months and weeks in {@code ALIGNED_DAY_OF_WEEK_IN_MONTH}. - * The day-of-week is adjusted as the next or same matching day-of-week once - * the years, months and weeks have been handled. - *
  • {@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code ALIGNED_DAY_OF_WEEK_IN_YEAR} - - * If all three are present, then they are combined to form a date. - * In all three modes, the {@code YEAR} is validated. - * If the mode is lenient, then the date is combined in a manner equivalent to - * creating a date on the first day of the requested year, then adding - * the difference in weeks, then in days. - * If the mode is smart or strict, then the all three fields are validated to - * their outer ranges. The date is then combined in a manner equivalent to - * creating a date on the first day of the requested year, then adding - * the amount in weeks and days to reach their values. If the mode is strict, - * the date is additionally validated to check that the day and week adjustment - * did not change the year. - *
  • {@code YEAR}, {@code ALIGNED_WEEK_OF_YEAR} and {@code DAY_OF_WEEK} - - * If all three are present, then they are combined to form a date. - * The approach is the same as described above for years and weeks in - * {@code ALIGNED_DAY_OF_WEEK_IN_YEAR}. The day-of-week is adjusted as the - * next or same matching day-of-week once the years and weeks have been handled. - *
- *

- * The default implementation is suitable for most calendar systems. - * If {@link ChronoField#YEAR_OF_ERA} is found without an {@link ChronoField#ERA} - * then the last era in {@link #eras()} is used. - * The implementation assumes a 7 day week, that the first day-of-month - * has the value 1, that first day-of-year has the value 1, and that the - * first of the month and year always exists. + * The default implementation, which explains typical resolve behaviour, + * is provided in {@link AbstractChronology}. * * @param fieldValues the map of fields to values, which can be updated, not null * @param resolverStyle the requested type of resolve, not null @@ -959,233 +669,7 @@ public abstract class Chronology implements Comparable { * @throws DateTimeException if the date cannot be resolved, typically * because of a conflict in the input data */ - public ChronoLocalDate resolveDate(Map fieldValues, ResolverStyle resolverStyle) { - // check epoch-day before inventing era - if (fieldValues.containsKey(EPOCH_DAY)) { - return dateEpochDay(fieldValues.remove(EPOCH_DAY)); - } - - // fix proleptic month before inventing era - resolveProlepticMonth(fieldValues, resolverStyle); - - // invent era if necessary to resolve year-of-era - ChronoLocalDate resolved = resolveYearOfEra(fieldValues, resolverStyle); - if (resolved != null) { - return resolved; - } - - // build date - if (fieldValues.containsKey(YEAR)) { - if (fieldValues.containsKey(MONTH_OF_YEAR)) { - if (fieldValues.containsKey(DAY_OF_MONTH)) { - return resolveYMD(fieldValues, resolverStyle); - } - if (fieldValues.containsKey(ALIGNED_WEEK_OF_MONTH)) { - if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_MONTH)) { - return resolveYMAA(fieldValues, resolverStyle); - } - if (fieldValues.containsKey(DAY_OF_WEEK)) { - return resolveYMAD(fieldValues, resolverStyle); - } - } - } - if (fieldValues.containsKey(DAY_OF_YEAR)) { - return resolveYD(fieldValues, resolverStyle); - } - if (fieldValues.containsKey(ALIGNED_WEEK_OF_YEAR)) { - if (fieldValues.containsKey(ALIGNED_DAY_OF_WEEK_IN_YEAR)) { - return resolveYAA(fieldValues, resolverStyle); - } - if (fieldValues.containsKey(DAY_OF_WEEK)) { - return resolveYAD(fieldValues, resolverStyle); - } - } - } - return null; - } - - void resolveProlepticMonth(Map fieldValues, ResolverStyle resolverStyle) { - Long pMonth = fieldValues.remove(PROLEPTIC_MONTH); - if (pMonth != null) { - if (resolverStyle != ResolverStyle.LENIENT) { - PROLEPTIC_MONTH.checkValidValue(pMonth); - } - // first day-of-month is likely to be safest for setting proleptic-month - // cannot add to year zero, as not all chronologies have a year zero - ChronoLocalDate chronoDate = dateNow() - .with(DAY_OF_MONTH, 1).with(PROLEPTIC_MONTH, pMonth); - addFieldValue(fieldValues, MONTH_OF_YEAR, chronoDate.get(MONTH_OF_YEAR)); - addFieldValue(fieldValues, YEAR, chronoDate.get(YEAR)); - } - } - - ChronoLocalDate resolveYearOfEra(Map fieldValues, ResolverStyle resolverStyle) { - Long yoeLong = fieldValues.remove(YEAR_OF_ERA); - if (yoeLong != null) { - Long eraLong = fieldValues.remove(ERA); - int yoe; - if (resolverStyle != ResolverStyle.LENIENT) { - yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA); - } else { - yoe = Math.toIntExact(yoeLong); - } - if (eraLong != null) { - Era eraObj = eraOf(range(ERA).checkValidIntValue(eraLong, ERA)); - addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe)); - } else { - if (fieldValues.containsKey(YEAR)) { - int year = range(YEAR).checkValidIntValue(fieldValues.get(YEAR), YEAR); - ChronoLocalDate chronoDate = dateYearDay(year, 1); - addFieldValue(fieldValues, YEAR, prolepticYear(chronoDate.getEra(), yoe)); - } else if (resolverStyle == ResolverStyle.STRICT) { - // do not invent era if strict - // reinstate the field removed earlier, no cross-check issues - fieldValues.put(YEAR_OF_ERA, yoeLong); - } else { - List eras = eras(); - if (eras.isEmpty()) { - addFieldValue(fieldValues, YEAR, yoe); - } else { - Era eraObj = eras.get(eras.size() - 1); - addFieldValue(fieldValues, YEAR, prolepticYear(eraObj, yoe)); - } - } - } - } else if (fieldValues.containsKey(ERA)) { - range(ERA).checkValidValue(fieldValues.get(ERA), ERA); // always validated - } - return null; - } - - ChronoLocalDate resolveYMD(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); - long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1); - return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS); - } - int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); - ValueRange domRange = range(DAY_OF_MONTH); - int dom = domRange.checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH); - if (resolverStyle == ResolverStyle.SMART) { // previous valid - try { - return date(y, moy, dom); - } catch (DateTimeException ex) { - return date(y, moy, 1).with(TemporalAdjuster.lastDayOfMonth()); - } - } - return date(y, moy, dom); - } - - ChronoLocalDate resolveYD(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1); - return dateYearDay(y, 1).plus(days, DAYS); - } - int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR); - return dateYearDay(y, doy); // smart is same as strict - } - - ChronoLocalDate resolveYMAA(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); - long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), 1); - return date(y, 1, 1).plus(months, MONTHS).plus(weeks, WEEKS).plus(days, DAYS); - } - int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); - int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH); - int ad = range(ALIGNED_DAY_OF_WEEK_IN_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_MONTH), ALIGNED_DAY_OF_WEEK_IN_MONTH); - ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7 + (ad - 1), DAYS); - if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { - throw new DateTimeException("Strict mode rejected resolved date as it is in a different month"); - } - return date; - } - - ChronoLocalDate resolveYMAD(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), 1); - long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); - return resolveAligned(date(y, 1, 1), months, weeks, dow); - } - int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); - int aw = range(ALIGNED_WEEK_OF_MONTH).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_MONTH), ALIGNED_WEEK_OF_MONTH); - int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK); - ChronoLocalDate date = date(y, moy, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow))); - if (resolverStyle == ResolverStyle.STRICT && date.get(MONTH_OF_YEAR) != moy) { - throw new DateTimeException("Strict mode rejected resolved date as it is in a different month"); - } - return date; - } - - ChronoLocalDate resolveYAA(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); - long days = Math.subtractExact(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), 1); - return dateYearDay(y, 1).plus(weeks, WEEKS).plus(days, DAYS); - } - int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR); - int ad = range(ALIGNED_DAY_OF_WEEK_IN_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_DAY_OF_WEEK_IN_YEAR), ALIGNED_DAY_OF_WEEK_IN_YEAR); - ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7 + (ad - 1), DAYS); - if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { - throw new DateTimeException("Strict mode rejected resolved date as it is in a different year"); - } - return date; - } - - ChronoLocalDate resolveYAD(Map fieldValues, ResolverStyle resolverStyle) { - int y = range(YEAR).checkValidIntValue(fieldValues.remove(YEAR), YEAR); - if (resolverStyle == ResolverStyle.LENIENT) { - long weeks = Math.subtractExact(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), 1); - long dow = Math.subtractExact(fieldValues.remove(DAY_OF_WEEK), 1); - return resolveAligned(dateYearDay(y, 1), 0, weeks, dow); - } - int aw = range(ALIGNED_WEEK_OF_YEAR).checkValidIntValue(fieldValues.remove(ALIGNED_WEEK_OF_YEAR), ALIGNED_WEEK_OF_YEAR); - int dow = range(DAY_OF_WEEK).checkValidIntValue(fieldValues.remove(DAY_OF_WEEK), DAY_OF_WEEK); - ChronoLocalDate date = dateYearDay(y, 1).plus((aw - 1) * 7, DAYS).with(nextOrSame(DayOfWeek.of(dow))); - if (resolverStyle == ResolverStyle.STRICT && date.get(YEAR) != y) { - throw new DateTimeException("Strict mode rejected resolved date as it is in a different year"); - } - return date; - } - - ChronoLocalDate resolveAligned(ChronoLocalDate base, long months, long weeks, long dow) { - ChronoLocalDate date = base.plus(months, MONTHS).plus(weeks, WEEKS); - if (dow > 7) { - date = date.plus((dow - 1) / 7, WEEKS); - dow = ((dow - 1) % 7) + 1; - } else if (dow < 1) { - date = date.plus(Math.subtractExact(dow, 7) / 7, WEEKS); - dow = ((dow + 6) % 7) + 1; - } - return date.with(nextOrSame(DayOfWeek.of((int) dow))); - } - - /** - * Adds a field-value pair to the map, checking for conflicts. - *

- * If the field is not already present, then the field-value pair is added to the map. - * If the field is already present and it has the same value as that specified, no action occurs. - * If the field is already present and it has a different value to that specified, then - * an exception is thrown. - * - * @param field the field to add, not null - * @param value the value to add, not null - * @throws DateTimeException if the field is already present with a different value - */ - void addFieldValue(Map fieldValues, ChronoField field, long value) { - Long old = fieldValues.get(field); // check first for better error message - if (old != null && old.longValue() != value) { - throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value); - } - fieldValues.put(field, value); - } + ChronoLocalDate resolveDate(Map fieldValues, ResolverStyle resolverStyle); //----------------------------------------------------------------------- /** @@ -1215,7 +699,7 @@ public abstract class Chronology implements Comparable { * @param days the number of years, may be negative * @return the period in terms of this chronology, not null */ - public ChronoPeriod period(int years, int months, int days) { + default ChronoPeriod period(int years, int months, int days) { return new ChronoPeriodImpl(this, years, months, days); } @@ -1226,107 +710,43 @@ public abstract class Chronology implements Comparable { * The comparison order first by the chronology ID string, then by any * additional information specific to the subclass. * It is "consistent with equals", as defined by {@link Comparable}. - *

- * The default implementation compares the chronology ID. - * Subclasses must compare any additional state that they store. * * @param other the other chronology to compare to, not null * @return the comparator value, negative if less, positive if greater */ @Override - public int compareTo(Chronology other) { - return getId().compareTo(other.getId()); - } + int compareTo(Chronology other); /** * Checks if this chronology is equal to another chronology. *

* The comparison is based on the entire state of the object. - *

- * The default implementation checks the type and calls {@link #compareTo(Chronology)}. * * @param obj the object to check, null returns false * @return true if this is equal to the other chronology */ @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof Chronology) { - return compareTo((Chronology) obj) == 0; - } - return false; - } + boolean equals(Object obj); /** * A hash code for this chronology. *

- * The default implementation is based on the ID and class. - * Subclasses should add any additional state that they store. + * The hash code should be based on the entire state of the object. * * @return a suitable hash code */ @Override - public int hashCode() { - return getClass().hashCode() ^ getId().hashCode(); - } + int hashCode(); //----------------------------------------------------------------------- /** - * Outputs this chronology as a {@code String}, using the ID. + * Outputs this chronology as a {@code String}. + *

+ * The format should include the entire state of the object. * * @return a string representation of this chronology, not null */ @Override - public String toString() { - return getId(); - } - - //----------------------------------------------------------------------- - /** - * Writes the Chronology using a - * dedicated serialized form. - * @serialData - *

-     *  out.writeByte(1);  // identifies a Chronology
-     *  out.writeUTF(getId());
-     * 
- * - * @return the instance of {@code Ser}, not null - */ - Object writeReplace() { - return new Ser(Ser.CHRONO_TYPE, this); - } - - /** - * Defend against malicious streams. - * @return never - * @throws InvalidObjectException always - */ - private Object readResolve() throws InvalidObjectException { - throw new InvalidObjectException("Deserialization via serialization delegate"); - } - - /** - * Write the Chronology id to the stream. - * @param out the output stream - * @throws IOException on any error during the write - */ - void writeExternal(DataOutput out) throws IOException { - out.writeUTF(getId()); - } - - /** - * Reads the Chronology id and creates the Chronology. - * @param in the input stream - * @return the Chronology - * @throws IOException on errors during the read - * @throws DateTimeException if the Chronology cannot be returned - */ - static Chronology readExternal(DataInput in) throws IOException { - String id = in.readUTF(); - return Chronology.of(id); - } + String toString(); } diff --git a/jdk/src/share/classes/java/time/chrono/HijrahChronology.java b/jdk/src/share/classes/java/time/chrono/HijrahChronology.java index 7d4485809c9..277b1010fe4 100644 --- a/jdk/src/share/classes/java/time/chrono/HijrahChronology.java +++ b/jdk/src/share/classes/java/time/chrono/HijrahChronology.java @@ -214,7 +214,7 @@ import sun.util.logging.PlatformLogger; * * @since 1.8 */ -public final class HijrahChronology extends Chronology implements Serializable { +public final class HijrahChronology extends AbstractChronology implements Serializable { /** * The Hijrah Calendar id. @@ -308,8 +308,8 @@ public final class HijrahChronology extends Chronology implements Serializable { try { INSTANCE = new HijrahChronology("Hijrah-umalqura"); // Register it by its aliases - Chronology.registerChrono(INSTANCE, "Hijrah"); - Chronology.registerChrono(INSTANCE, "islamic"); + AbstractChronology.registerChrono(INSTANCE, "Hijrah"); + AbstractChronology.registerChrono(INSTANCE, "islamic"); } catch (DateTimeException ex) { // Absence of Hijrah calendar is fatal to initializing this class. PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); @@ -336,7 +336,7 @@ public final class HijrahChronology extends Chronology implements Serializable { try { // Create and register the variant HijrahChronology chrono = new HijrahChronology(id); - Chronology.registerChrono(chrono); + AbstractChronology.registerChrono(chrono); } catch (DateTimeException ex) { // Log error and continue PlatformLogger logger = PlatformLogger.getLogger("java.time.chrono"); diff --git a/jdk/src/share/classes/java/time/chrono/IsoChronology.java b/jdk/src/share/classes/java/time/chrono/IsoChronology.java index 9638f6eea4f..eb71a1fe65c 100644 --- a/jdk/src/share/classes/java/time/chrono/IsoChronology.java +++ b/jdk/src/share/classes/java/time/chrono/IsoChronology.java @@ -120,7 +120,7 @@ import java.util.Objects; * * @since 1.8 */ -public final class IsoChronology extends Chronology implements Serializable { +public final class IsoChronology extends AbstractChronology implements Serializable { /** * Singleton instance of the ISO chronology. diff --git a/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java b/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java index b01707e63ab..09e5b692ef2 100644 --- a/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java +++ b/jdk/src/share/classes/java/time/chrono/JapaneseChronology.java @@ -120,7 +120,7 @@ import sun.util.calendar.LocalGregorianCalendar; * * @since 1.8 */ -public final class JapaneseChronology extends Chronology implements Serializable { +public final class JapaneseChronology extends AbstractChronology implements Serializable { static final LocalGregorianCalendar JCAL = (LocalGregorianCalendar) CalendarSystem.forName("japanese"); diff --git a/jdk/src/share/classes/java/time/chrono/MinguoChronology.java b/jdk/src/share/classes/java/time/chrono/MinguoChronology.java index db75a8645d6..af0be986c93 100644 --- a/jdk/src/share/classes/java/time/chrono/MinguoChronology.java +++ b/jdk/src/share/classes/java/time/chrono/MinguoChronology.java @@ -105,7 +105,7 @@ import java.util.Map; * * @since 1.8 */ -public final class MinguoChronology extends Chronology implements Serializable { +public final class MinguoChronology extends AbstractChronology implements Serializable { /** * Singleton instance for the Minguo chronology. diff --git a/jdk/src/share/classes/java/time/chrono/Ser.java b/jdk/src/share/classes/java/time/chrono/Ser.java index 5a4e3c12623..317a7696497 100644 --- a/jdk/src/share/classes/java/time/chrono/Ser.java +++ b/jdk/src/share/classes/java/time/chrono/Ser.java @@ -161,7 +161,7 @@ final class Ser implements Externalizable { out.writeByte(type); switch (type) { case CHRONO_TYPE: - ((Chronology) object).writeExternal(out); + ((AbstractChronology) object).writeExternal(out); break; case CHRONO_LOCAL_DATE_TIME_TYPE: ((ChronoLocalDateTimeImpl) object).writeExternal(out); @@ -231,7 +231,7 @@ final class Ser implements Externalizable { private static Object readInternal(byte type, ObjectInput in) throws IOException, ClassNotFoundException { switch (type) { - case CHRONO_TYPE: return Chronology.readExternal(in); + case CHRONO_TYPE: return AbstractChronology.readExternal(in); case CHRONO_LOCAL_DATE_TIME_TYPE: return ChronoLocalDateTimeImpl.readExternal(in); case CHRONO_ZONE_DATE_TIME_TYPE: return ChronoZonedDateTimeImpl.readExternal(in); case JAPANESE_DATE_TYPE: return JapaneseDate.readExternal(in); diff --git a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java index 4ffd15bfcc6..c41aa34c0f1 100644 --- a/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java +++ b/jdk/src/share/classes/java/time/chrono/ThaiBuddhistChronology.java @@ -106,7 +106,7 @@ import java.util.Map; * * @since 1.8 */ -public final class ThaiBuddhistChronology extends Chronology implements Serializable { +public final class ThaiBuddhistChronology extends AbstractChronology implements Serializable { /** * Singleton instance of the Buddhist chronology. diff --git a/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java b/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java index c111eed3658..c72b7370de8 100644 --- a/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java +++ b/jdk/test/java/time/tck/java/time/chrono/CopticChronology.java @@ -59,13 +59,11 @@ package tck.java.time.chrono; import static java.time.temporal.ChronoField.EPOCH_DAY; import java.io.Serializable; - +import java.time.chrono.AbstractChronology; +import java.time.chrono.Era; import java.time.temporal.ChronoField; import java.time.temporal.TemporalAccessor; import java.time.temporal.ValueRange; -import java.time.chrono.Chronology; -import java.time.chrono.Era; - import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -95,7 +93,7 @@ import java.util.Locale; *

Implementation notes

* This class is immutable and thread-safe. */ -public final class CopticChronology extends Chronology implements Serializable { +public final class CopticChronology extends AbstractChronology implements Serializable { /** * Singleton instance of the Coptic chronology. From be5469fc716a7868f4ae4b705502dbb1bee0bc03 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Thu, 11 Jul 2013 13:32:36 -0700 Subject: [PATCH 021/263] 8014987: Augment serialization handling Reviewed-by: alanb, coffeys, skoivu --- .../classes/java/io/ObjectInputStream.java | 15 +++++++------- .../classes/java/io/ObjectOutputStream.java | 20 ++++++++++++------- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java index ca0400539f9..0e41b08dc3e 100644 --- a/jdk/src/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java @@ -490,11 +490,12 @@ public class ObjectInputStream public void defaultReadObject() throws IOException, ClassNotFoundException { - if (curContext == null) { + SerialCallbackContext ctx = curContext; + if (ctx == null) { throw new NotActiveException("not in call to readObject"); } - Object curObj = curContext.getObj(); - ObjectStreamClass curDesc = curContext.getDesc(); + Object curObj = ctx.getObj(); + ObjectStreamClass curDesc = ctx.getDesc(); bin.setBlockDataMode(false); defaultReadFields(curObj, curDesc); bin.setBlockDataMode(true); @@ -528,11 +529,12 @@ public class ObjectInputStream public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException { - if (curContext == null) { + SerialCallbackContext ctx = curContext; + if (ctx == null) { throw new NotActiveException("not in call to readObject"); } - Object curObj = curContext.getObj(); - ObjectStreamClass curDesc = curContext.getDesc(); + Object curObj = ctx.getObj(); + ObjectStreamClass curDesc = ctx.getDesc(); bin.setBlockDataMode(false); GetFieldImpl getField = new GetFieldImpl(curDesc); getField.readFields(); @@ -1967,7 +1969,6 @@ public class ObjectInputStream private void defaultReadFields(Object obj, ObjectStreamClass desc) throws IOException { - // REMIND: is isInstance check necessary? Class cl = desc.forClass(); if (cl != null && obj != null && !cl.isInstance(obj)) { throw new ClassCastException(); diff --git a/jdk/src/share/classes/java/io/ObjectOutputStream.java b/jdk/src/share/classes/java/io/ObjectOutputStream.java index f7a94bb0342..c99aeb9cd67 100644 --- a/jdk/src/share/classes/java/io/ObjectOutputStream.java +++ b/jdk/src/share/classes/java/io/ObjectOutputStream.java @@ -430,11 +430,12 @@ public class ObjectOutputStream * OutputStream */ public void defaultWriteObject() throws IOException { - if ( curContext == null ) { + SerialCallbackContext ctx = curContext; + if (ctx == null) { throw new NotActiveException("not in call to writeObject"); } - Object curObj = curContext.getObj(); - ObjectStreamClass curDesc = curContext.getDesc(); + Object curObj = ctx.getObj(); + ObjectStreamClass curDesc = ctx.getDesc(); bout.setBlockDataMode(false); defaultWriteFields(curObj, curDesc); bout.setBlockDataMode(true); @@ -452,11 +453,12 @@ public class ObjectOutputStream */ public ObjectOutputStream.PutField putFields() throws IOException { if (curPut == null) { - if (curContext == null) { + SerialCallbackContext ctx = curContext; + if (ctx == null) { throw new NotActiveException("not in call to writeObject"); } - Object curObj = curContext.getObj(); - ObjectStreamClass curDesc = curContext.getDesc(); + Object curObj = ctx.getObj(); + ObjectStreamClass curDesc = ctx.getDesc(); curPut = new PutFieldImpl(curDesc); } return curPut; @@ -1516,7 +1518,11 @@ public class ObjectOutputStream private void defaultWriteFields(Object obj, ObjectStreamClass desc) throws IOException { - // REMIND: perform conservative isInstance check here? + Class cl = desc.forClass(); + if (cl != null && obj != null && !cl.isInstance(obj)) { + throw new ClassCastException(); + } + desc.checkDefaultSerialize(); int primDataSize = desc.getPrimDataSize(); From 79bda234fe58acb682b3be6ee3fa064d6fdcec43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Borggr=C3=A9n-Franck?= Date: Mon, 15 Jul 2013 14:44:50 +0200 Subject: [PATCH 022/263] 8014349: (cl) Class.getDeclaredClass problematic in some class loader configurations Reviewed-by: mchung, ahgross, darcy --- jdk/src/share/classes/java/lang/Class.java | 18 +++++++++++++++++- jdk/src/share/native/java/lang/Class.c | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index df4d457367d..eb11681ac00 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -1221,9 +1221,25 @@ public final class Class implements java.io.Serializable, * type, or void,then this method returns null. * * @return the declaring class for this class + * @throws SecurityException + * If a security manager, s, is present and the caller's + * class loader is not the same as or an ancestor of the class + * loader for the declaring class and invocation of {@link + * SecurityManager#checkPackageAccess s.checkPackageAccess()} + * denies access to the package of the declaring class * @since JDK1.1 */ - public native Class getDeclaringClass(); + @CallerSensitive + public Class getDeclaringClass() throws SecurityException { + final Class candidate = getDeclaringClass0(); + + if (candidate != null) + candidate.checkPackageAccess( + ClassLoader.getClassLoader(Reflection.getCallerClass()), true); + return candidate; + } + + private native Class getDeclaringClass0(); /** diff --git a/jdk/src/share/native/java/lang/Class.c b/jdk/src/share/native/java/lang/Class.c index e53d3f73b79..b0ba34349d8 100644 --- a/jdk/src/share/native/java/lang/Class.c +++ b/jdk/src/share/native/java/lang/Class.c @@ -69,7 +69,7 @@ static JNINativeMethod methods[] = { {"getDeclaredConstructors0","(Z)[" CTR, (void *)&JVM_GetClassDeclaredConstructors}, {"getProtectionDomain0", "()" PD, (void *)&JVM_GetProtectionDomain}, {"getDeclaredClasses0", "()[" CLS, (void *)&JVM_GetDeclaredClasses}, - {"getDeclaringClass", "()" CLS, (void *)&JVM_GetDeclaringClass}, + {"getDeclaringClass0", "()" CLS, (void *)&JVM_GetDeclaringClass}, {"getGenericSignature0", "()" STR, (void *)&JVM_GetClassSignature}, {"getRawAnnotations", "()" BA, (void *)&JVM_GetClassAnnotations}, {"getConstantPool", "()" CPL, (void *)&JVM_GetClassConstantPool}, From 1f1524301201ef37f3180a9b9659eb45d598afa0 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 15 Jul 2013 20:24:39 -0700 Subject: [PATCH 023/263] 8017291: Cast Proxies Aside Reviewed-by: alanb, ahgross --- jdk/src/share/classes/java/lang/ClassLoader.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/jdk/src/share/classes/java/lang/ClassLoader.java b/jdk/src/share/classes/java/lang/ClassLoader.java index f26eafd980a..3735cd3a782 100644 --- a/jdk/src/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/share/classes/java/lang/ClassLoader.java @@ -57,6 +57,7 @@ import sun.misc.URLClassPath; import sun.misc.VM; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; +import sun.reflect.misc.ReflectUtil; import sun.security.util.SecurityConstants; /** @@ -486,6 +487,13 @@ public abstract class ClassLoader { private void checkPackageAccess(Class cls, ProtectionDomain pd) { final SecurityManager sm = System.getSecurityManager(); if (sm != null) { + if (ReflectUtil.isNonPublicProxyClass(cls)) { + for (Class intf: cls.getInterfaces()) { + checkPackageAccess(intf, pd); + } + return; + } + final String name = cls.getName(); final int i = name.lastIndexOf('.'); if (i != -1) { From fb90cdbe873ae541008c71cbc04107b6b893a660 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 16 Jul 2013 21:11:54 +0400 Subject: [PATCH 024/263] 8019617: Better view of objects Reviewed-by: art, skoivu --- .../javax/swing/text/html/ObjectView.java | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/text/html/ObjectView.java b/jdk/src/share/classes/javax/swing/text/html/ObjectView.java index 4e43cfb6d70..00d3a42c3a6 100644 --- a/jdk/src/share/classes/javax/swing/text/html/ObjectView.java +++ b/jdk/src/share/classes/javax/swing/text/html/ObjectView.java @@ -31,6 +31,9 @@ import javax.swing.text.*; import java.beans.*; import java.lang.reflect.*; +import sun.reflect.misc.MethodUtil; +import sun.reflect.misc.ReflectUtil; + /** * Component decorator that implements the view interface * for <object> elements. @@ -87,6 +90,7 @@ public class ObjectView extends ComponentView { AttributeSet attr = getElement().getAttributes(); String classname = (String) attr.getAttribute(HTML.Attribute.CLASSID); try { + ReflectUtil.checkPackageAccess(classname); Class c = Class.forName(classname, true,Thread.currentThread(). getContextClassLoader()); Object o = c.newInstance(); @@ -115,28 +119,6 @@ public class ObjectView extends ComponentView { return comp; } - /** - * Get a Class object to use for loading the - * classid. If possible, the Classloader - * used to load the associated Document is used. - * This would typically be the same as the ClassLoader - * used to load the EditorKit. If the documents - * ClassLoader is null, - * Class.forName is used. - */ - private Class getClass(String classname) throws ClassNotFoundException { - Class klass; - - Class docClass = getDocument().getClass(); - ClassLoader loader = docClass.getClassLoader(); - if (loader != null) { - klass = loader.loadClass(classname); - } else { - klass = Class.forName(classname); - } - return klass; - } - /** * Initialize this component according the KEY/VALUEs passed in * via the <param> elements in the corresponding @@ -170,7 +152,7 @@ public class ObjectView extends ComponentView { } Object [] args = { value }; try { - writer.invoke(comp, args); + MethodUtil.invoke(writer, comp, args); } catch (Exception ex) { System.err.println("Invocation failed"); // invocation code From a775b1ae8d7146b5e0ac513000884a4ecf680a58 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 18 Jul 2013 18:52:14 +0100 Subject: [PATCH 025/263] 8015743: Address internet addresses Reviewed-by: alanb, khazra, skoivu --- .../share/classes/java/net/Inet6Address.java | 496 +++++++++++------- .../share/classes/java/net/InetAddress.java | 9 +- jdk/src/share/native/java/net/Inet6Address.c | 15 +- jdk/src/share/native/java/net/net_util.c | 105 +++- jdk/src/share/native/java/net/net_util.h | 15 +- .../native/java/net/Inet6AddressImpl.c | 15 +- .../native/java/net/NetworkInterface.c | 18 +- .../native/java/net/PlainDatagramSocketImpl.c | 3 +- jdk/src/solaris/native/java/net/net_util_md.c | 8 +- .../native/java/net/Inet6AddressImpl.c | 16 +- .../native/java/net/NetworkInterface.c | 16 +- .../native/java/net/NetworkInterface_winXP.c | 12 +- .../java/net/TwoStacksPlainSocketImpl.c | 11 +- jdk/src/windows/native/java/net/net_util_md.c | 6 +- .../net/Inet6Address/serialize/Serialize.java | 181 ++++++- 15 files changed, 657 insertions(+), 269 deletions(-) diff --git a/jdk/src/share/classes/java/net/Inet6Address.java b/jdk/src/share/classes/java/net/Inet6Address.java index 4a2d4e22473..8892631bb30 100644 --- a/jdk/src/share/classes/java/net/Inet6Address.java +++ b/jdk/src/share/classes/java/net/Inet6Address.java @@ -28,7 +28,10 @@ package java.net; import java.io.IOException; import java.io.InvalidObjectException; import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; import java.util.Enumeration; +import java.util.Arrays; /** * This class represents an Internet Protocol version 6 (IPv6) address. @@ -177,37 +180,192 @@ class Inet6Address extends InetAddress { */ private transient int cached_scope_id; // 0 - /** - * Holds a 128-bit (16 bytes) IPv6 address. - * - * @serial - */ - byte[] ipaddress; + private class Inet6AddressHolder { - /** - * scope_id. The scope specified when the object is created. If the object - * is created with an interface name, then the scope_id is not determined - * until the time it is needed. - */ - private int scope_id; // 0 + private Inet6AddressHolder() { + ipaddress = new byte[INADDRSZ]; + } - /** - * This will be set to true when the scope_id field contains a valid - * integer scope_id. - */ - private boolean scope_id_set; // false + private Inet6AddressHolder( + byte[] ipaddress, int scope_id, boolean scope_id_set, + NetworkInterface ifname, boolean scope_ifname_set) + { + this.ipaddress = ipaddress; + this.scope_id = scope_id; + this.scope_id_set = scope_id_set; + this.scope_ifname_set = scope_ifname_set; + this.scope_ifname = ifname; + } - /** - * scoped interface. scope_id is derived from this as the scope_id of the first - * address whose scope is the same as this address for the named interface. - */ - private transient NetworkInterface scope_ifname; // null + /** + * Holds a 128-bit (16 bytes) IPv6 address. + */ + byte[] ipaddress; - /** - * set if the object is constructed with a scoped - * interface instead of a numeric scope id. - */ - private boolean scope_ifname_set; // false; + /** + * scope_id. The scope specified when the object is created. If the object + * is created with an interface name, then the scope_id is not determined + * until the time it is needed. + */ + int scope_id; // 0 + + /** + * This will be set to true when the scope_id field contains a valid + * integer scope_id. + */ + boolean scope_id_set; // false + + /** + * scoped interface. scope_id is derived from this as the scope_id of the first + * address whose scope is the same as this address for the named interface. + */ + NetworkInterface scope_ifname; // null + + /** + * set if the object is constructed with a scoped + * interface instead of a numeric scope id. + */ + boolean scope_ifname_set; // false; + + void setAddr(byte addr[]) { + if (addr.length == INADDRSZ) { // normal IPv6 address + System.arraycopy(addr, 0, ipaddress, 0, INADDRSZ); + } + } + + void init(byte addr[], int scope_id) { + setAddr(addr); + + if (scope_id >= 0) { + this.scope_id = scope_id; + this.scope_id_set = true; + } + } + + void init(byte addr[], NetworkInterface nif) + throws UnknownHostException + { + setAddr(addr); + + if (nif != null) { + this.scope_id = deriveNumericScope(ipaddress, nif); + this.scope_id_set = true; + this.scope_ifname = nif; + this.scope_ifname_set = true; + } + } + + String getHostAddress() { + String s = numericToTextFormat(ipaddress); + if (scope_ifname != null) { /* must check this first */ + s = s + "%" + scope_ifname.getName(); + } else if (scope_id_set) { + s = s + "%" + scope_id; + } + return s; + } + + public boolean equals(Object o) { + if (! (o instanceof Inet6AddressHolder)) { + return false; + } + Inet6AddressHolder that = (Inet6AddressHolder)o; + + return Arrays.equals(this.ipaddress, that.ipaddress); + } + + public int hashCode() { + if (ipaddress != null) { + + int hash = 0; + int i=0; + while (i= 0, or -1 to indicate not being set */ Inet6Address(String hostName, byte addr[], int scope_id) { - holder().hostName = hostName; - if (addr.length == INADDRSZ) { // normal IPv6 address - holder().family = IPv6; - ipaddress = addr.clone(); - } - if (scope_id >= 0) { - this.scope_id = scope_id; - scope_id_set = true; - } + holder.init(hostName, IPv6); + holder6 = new Inet6AddressHolder(); + holder6.init(addr, scope_id); } Inet6Address(String hostName, byte addr[]) { + holder6 = new Inet6AddressHolder(); try { initif (hostName, addr, null); } catch (UnknownHostException e) {} /* cant happen if ifname is null */ @@ -245,12 +397,14 @@ class Inet6Address extends InetAddress { Inet6Address (String hostName, byte addr[], NetworkInterface nif) throws UnknownHostException { + holder6 = new Inet6AddressHolder(); initif (hostName, addr, nif); } Inet6Address (String hostName, byte addr[], String ifname) throws UnknownHostException { + holder6 = new Inet6AddressHolder(); initstr (hostName, addr, ifname); } @@ -341,17 +495,13 @@ class Inet6Address extends InetAddress { private void initif(String hostName, byte addr[], NetworkInterface nif) throws UnknownHostException { - holder().hostName = hostName; + int family = -1; + holder6.init(addr, nif); + if (addr.length == INADDRSZ) { // normal IPv6 address - holder().family = IPv6; - ipaddress = addr.clone(); - } - if (nif != null) { - scope_ifname = nif; - scope_id = deriveNumericScope(nif); - scope_id_set = true; - scope_ifname_set = true; // for consistency + family = IPv6; } + holder.init(hostName, family); } /* check the two Ipv6 addresses and return false if they are both @@ -359,17 +509,22 @@ class Inet6Address extends InetAddress { * (ie. one is sitelocal and the other linklocal) * return true otherwise. */ - private boolean differentLocalAddressTypes(Inet6Address other) { - if (isLinkLocalAddress() && !other.isLinkLocalAddress()) + + private static boolean isDifferentLocalAddressType( + byte[] thisAddr, byte[] otherAddr) { + + if (Inet6Address.isLinkLocalAddress(thisAddr) && + !Inet6Address.isLinkLocalAddress(otherAddr)) { return false; - if (isSiteLocalAddress() && !other.isSiteLocalAddress()) + } + if (Inet6Address.isSiteLocalAddress(thisAddr) && + !Inet6Address.isSiteLocalAddress(otherAddr)) { return false; + } return true; } - private int deriveNumericScope(NetworkInterface ifc) - throws UnknownHostException - { + private static int deriveNumericScope (byte[] thisAddr, NetworkInterface ifc) throws UnknownHostException { Enumeration addresses = ifc.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress addr = addresses.nextElement(); @@ -378,46 +533,60 @@ class Inet6Address extends InetAddress { } Inet6Address ia6_addr = (Inet6Address)addr; /* check if site or link local prefixes match */ - if (!differentLocalAddressTypes(ia6_addr)){ + if (!isDifferentLocalAddressType(thisAddr, ia6_addr.getAddress())){ /* type not the same, so carry on searching */ continue; } /* found a matching address - return its scope_id */ - return ia6_addr.scope_id; + return ia6_addr.getScopeId(); } throw new UnknownHostException ("no scope_id found"); } - private int deriveNumericScope(String ifname) throws UnknownHostException { + private int deriveNumericScope (String ifname) throws UnknownHostException { Enumeration en; try { en = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { - throw new UnknownHostException( - "could not enumerate local network interfaces"); + throw new UnknownHostException ("could not enumerate local network interfaces"); } while (en.hasMoreElements()) { NetworkInterface ifc = en.nextElement(); - if (ifc.getName().equals(ifname)) { - Enumeration addresses = ifc.getInetAddresses(); - while (addresses.hasMoreElements()) { - InetAddress addr = addresses.nextElement(); - if (!(addr instanceof Inet6Address)) { - continue; - } - Inet6Address ia6_addr = (Inet6Address)addr; - /* check if site or link local prefixes match */ - if (!differentLocalAddressTypes(ia6_addr)){ - /* type not the same, so carry on searching */ - continue; - } - /* found a matching address - return its scope_id */ - return ia6_addr.scope_id; - } + if (ifc.getName().equals (ifname)) { + return deriveNumericScope(holder6.ipaddress, ifc); } } - throw new UnknownHostException( - "No matching address found for interface : " +ifname); + throw new UnknownHostException ("No matching address found for interface : " +ifname); + } + + /** + * @serialField ipaddress byte[] + * @serialField scope_id int + * @serialField scope_id_set boolean + * @serialField scope_ifname_set boolean + * @serialField ifname String + */ + + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("ipaddress", byte[].class), + new ObjectStreamField("scope_id", int.class), + new ObjectStreamField("scope_id_set", boolean.class), + new ObjectStreamField("scope_ifname_set", boolean.class), + new ObjectStreamField("ifname", String.class) + }; + + private static final long FIELDS_OFFSET; + private static final sun.misc.Unsafe UNSAFE; + + static { + try { + sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); + FIELDS_OFFSET = unsafe.objectFieldOffset( + Inet6Address.class.getDeclaredField("holder6")); + UNSAFE = unsafe; + } catch (ReflectiveOperationException e) { + throw new Error(e); + } } /** @@ -427,35 +596,41 @@ class Inet6Address extends InetAddress { */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { + NetworkInterface scope_ifname = null; if (getClass().getClassLoader() != null) { throw new SecurityException ("invalid address type"); } - s.defaultReadObject(); + ObjectInputStream.GetField gf = s.readFields(); + byte[] ipaddress = (byte[])gf.get("ipaddress", null); + int scope_id = (int)gf.get("scope_id", -1); + boolean scope_id_set = (boolean)gf.get("scope_id_set", false); + boolean scope_ifname_set = (boolean)gf.get("scope_ifname_set", false); + String ifname = (String)gf.get("ifname", null); - if (ifname != null && !ifname.equals("")) { + if (ifname != null && !"".equals (ifname)) { try { scope_ifname = NetworkInterface.getByName(ifname); - if (scope_ifname != null) { - scope_ifname_set = true; - try { - scope_id = deriveNumericScope(scope_ifname); - } catch (UnknownHostException e) { - // typically should not happen, but it may be that - // the machine being used for deserialization has - // the same interface name but without IPv6 configured. - } - } else { + if (scope_ifname == null) { /* the interface does not exist on this system, so we clear * the scope information completely */ scope_id_set = false; scope_ifname_set = false; scope_id = 0; + } else { + scope_ifname_set = true; + try { + scope_id = deriveNumericScope (ipaddress, scope_ifname); + } catch (UnknownHostException e) { + // typically should not happen, but it may be that + // the machine being used for deserialization has + // the same interface name but without IPv6 configured. + } } } catch (SocketException e) {} - } + /* if ifname was not supplied, then the numeric info is used */ ipaddress = ipaddress.clone(); @@ -466,9 +641,38 @@ class Inet6Address extends InetAddress { ipaddress.length); } - if (holder().getFamily() != IPv6) { + if (holder.getFamily() != IPv6) { throw new InvalidObjectException("invalid address family type"); } + + Inet6AddressHolder h = new Inet6AddressHolder( + ipaddress, scope_id, scope_id_set, scope_ifname, scope_ifname_set + ); + + UNSAFE.putObject(this, FIELDS_OFFSET, h); + } + + /** + * default behavior is overridden in order to write the + * scope_ifname field as a String, rather than a NetworkInterface + * which is not serializable + */ + private synchronized void writeObject(ObjectOutputStream s) + throws IOException + { + String ifname = null; + + if (holder6.scope_ifname != null) { + ifname = holder6.scope_ifname.getName(); + holder6.scope_ifname_set = true; + } + ObjectOutputStream.PutField pfields = s.putFields(); + pfields.put("ipaddress", holder6.ipaddress); + pfields.put("scope_id", holder6.scope_id); + pfields.put("scope_id_set", holder6.scope_id_set); + pfields.put("scope_ifname_set", holder6.scope_ifname_set); + pfields.put("ifname", ifname); + s.writeFields(); } /** @@ -483,7 +687,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMulticastAddress() { - return ((ipaddress[0] & 0xff) == 0xff); + return holder6.isMulticastAddress(); } /** @@ -496,11 +700,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isAnyLocalAddress() { - byte test = 0x00; - for (int i = 0; i < INADDRSZ; i++) { - test |= ipaddress[i]; - } - return (test == 0x00); + return holder6.isAnyLocalAddress(); } /** @@ -513,11 +713,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isLoopbackAddress() { - byte test = 0x00; - for (int i = 0; i < 15; i++) { - test |= ipaddress[i]; - } - return (test == 0x00) && (ipaddress[15] == 0x01); + return holder6.isLoopbackAddress(); } /** @@ -530,6 +726,11 @@ class Inet6Address extends InetAddress { */ @Override public boolean isLinkLocalAddress() { + return holder6.isLinkLocalAddress(); + } + + /* static version of above */ + static boolean isLinkLocalAddress(byte[] ipaddress) { return ((ipaddress[0] & 0xff) == 0xfe && (ipaddress[1] & 0xc0) == 0x80); } @@ -544,6 +745,11 @@ class Inet6Address extends InetAddress { */ @Override public boolean isSiteLocalAddress() { + return holder6.isSiteLocalAddress(); + } + + /* static version of above */ + static boolean isSiteLocalAddress(byte[] ipaddress) { return ((ipaddress[0] & 0xff) == 0xfe && (ipaddress[1] & 0xc0) == 0xc0); } @@ -559,8 +765,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMCGlobal() { - return ((ipaddress[0] & 0xff) == 0xff - && (ipaddress[1] & 0x0f) == 0x0e); + return holder6.isMCGlobal(); } /** @@ -574,8 +779,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMCNodeLocal() { - return ((ipaddress[0] & 0xff) == 0xff - && (ipaddress[1] & 0x0f) == 0x01); + return holder6.isMCNodeLocal(); } /** @@ -589,8 +793,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMCLinkLocal() { - return ((ipaddress[0] & 0xff) == 0xff - && (ipaddress[1] & 0x0f) == 0x02); + return holder6.isMCLinkLocal(); } /** @@ -604,8 +807,7 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMCSiteLocal() { - return ((ipaddress[0] & 0xff) == 0xff - && (ipaddress[1] & 0x0f) == 0x05); + return holder6.isMCSiteLocal(); } /** @@ -619,10 +821,8 @@ class Inet6Address extends InetAddress { */ @Override public boolean isMCOrgLocal() { - return ((ipaddress[0] & 0xff) == 0xff - && (ipaddress[1] & 0x0f) == 0x08); + return holder6.isMCOrgLocal(); } - /** * Returns the raw IP address of this {@code InetAddress} object. The result * is in network byte order: the highest order byte of the address is in @@ -632,7 +832,7 @@ class Inet6Address extends InetAddress { */ @Override public byte[] getAddress() { - return ipaddress.clone(); + return holder6.ipaddress.clone(); } /** @@ -644,7 +844,7 @@ class Inet6Address extends InetAddress { * @since 1.5 */ public int getScopeId() { - return scope_id; + return holder6.scope_id; } /** @@ -655,7 +855,7 @@ class Inet6Address extends InetAddress { * @since 1.5 */ public NetworkInterface getScopedInterface() { - return scope_ifname; + return holder6.scope_ifname; } /** @@ -669,13 +869,7 @@ class Inet6Address extends InetAddress { */ @Override public String getHostAddress() { - String s = numericToTextFormat(ipaddress); - if (scope_ifname != null) { /* must check this first */ - s = s + "%" + scope_ifname.getName(); - } else if (scope_id_set) { - s = s + "%" + scope_id; - } - return s; + return holder6.getHostAddress(); } /** @@ -685,25 +879,7 @@ class Inet6Address extends InetAddress { */ @Override public int hashCode() { - if (ipaddress != null) { - - int hash = 0; - int i=0; - while (iFindClass(env, "java/net/Inet6Address"); CHECK_NULL(c); ia6_class = (*env)->NewGlobalRef(env, c); CHECK_NULL(ia6_class); - ia6_ipaddressID = (*env)->GetFieldID(env, ia6_class, "ipaddress", "[B"); + ia6h_class = (*env)->FindClass(env, "java/net/Inet6Address$Inet6AddressHolder"); + CHECK_NULL(ia6h_class); + ia6_holder6ID = (*env)->GetFieldID(env, ia6_class, "holder6", "Ljava/net/Inet6Address$Inet6AddressHolder;"); + CHECK_NULL(ia6_holder6ID); + ia6_ipaddressID = (*env)->GetFieldID(env, ia6h_class, "ipaddress", "[B"); CHECK_NULL(ia6_ipaddressID); - ia6_scopeidID = (*env)->GetFieldID(env, ia6_class, "scope_id", "I"); + ia6_scopeidID = (*env)->GetFieldID(env, ia6h_class, "scope_id", "I"); CHECK_NULL(ia6_scopeidID); ia6_cachedscopeidID = (*env)->GetFieldID(env, ia6_class, "cached_scope_id", "I"); CHECK_NULL(ia6_cachedscopeidID); - ia6_scopeidsetID = (*env)->GetFieldID(env, ia6_class, "scope_id_set", "Z"); + ia6_scopeidsetID = (*env)->GetFieldID(env, ia6h_class, "scope_id_set", "Z"); CHECK_NULL(ia6_scopeidID); - ia6_scopeifnameID = (*env)->GetFieldID(env, ia6_class, "scope_ifname", "Ljava/net/NetworkInterface;"); + ia6_scopeifnameID = (*env)->GetFieldID(env, ia6h_class, "scope_ifname", "Ljava/net/NetworkInterface;"); CHECK_NULL(ia6_scopeifnameID); ia6_ctrID = (*env)->GetMethodID(env, ia6_class, "", "()V"); CHECK_NULL(ia6_ctrID); diff --git a/jdk/src/share/native/java/net/net_util.c b/jdk/src/share/native/java/net/net_util.c index 5d15f9d9b0e..d52577ce25b 100644 --- a/jdk/src/share/native/java/net/net_util.c +++ b/jdk/src/share/native/java/net/net_util.c @@ -94,6 +94,92 @@ extern jfieldID ia_holderID; extern jfieldID iac_addressID; extern jfieldID iac_familyID; +/** + * set_ methods return JNI_TRUE on success JNI_FALSE on error + * get_ methods that return +ve int return -1 on error + * get_ methods that return objects return NULL on error. + */ +jobject getInet6Address_scopeifname(JNIEnv *env, jobject iaObj) { + jobject holder; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, NULL); + return (*env)->GetObjectField(env, holder, ia6_scopeifnameID); +} + +int setInet6Address_scopeifname(JNIEnv *env, jobject iaObj, jobject scopeifname) { + jobject holder; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, JNI_FALSE); + (*env)->SetObjectField(env, holder, ia6_scopeifnameID, scopeifname); + return JNI_TRUE; +} + +int getInet6Address_scopeid_set(JNIEnv *env, jobject iaObj) { + jobject holder; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, -1); + return (*env)->GetBooleanField(env, holder, ia6_scopeidsetID); +} + +int getInet6Address_scopeid(JNIEnv *env, jobject iaObj) { + jobject holder; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, -1); + return (*env)->GetIntField(env, holder, ia6_scopeidID); +} + +int setInet6Address_scopeid(JNIEnv *env, jobject iaObj, int scopeid) { + jobject holder; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, JNI_FALSE); + (*env)->SetIntField(env, holder, ia6_scopeidID, scopeid); + if (scopeid > 0) { + (*env)->SetBooleanField(env, holder, ia6_scopeidsetID, JNI_TRUE); + } + return JNI_TRUE; +} + + +int getInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *dest) { + jobject holder, addr; + jbyteArray barr; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, JNI_FALSE); + addr = (*env)->GetObjectField(env, holder, ia6_ipaddressID); + CHECK_NULL_RETURN(addr, JNI_FALSE); + (*env)->GetByteArrayRegion(env, addr, 0, 16, (jbyte *)dest); + return JNI_TRUE; +} + +int setInet6Address_ipaddress(JNIEnv *env, jobject iaObj, char *address) { + jobject holder; + jbyteArray addr; + + init(env); + holder = (*env)->GetObjectField(env, iaObj, ia6_holder6ID); + CHECK_NULL_RETURN(holder, JNI_FALSE); + addr = (jbyteArray)(*env)->GetObjectField(env, holder, ia6_ipaddressID); + if (addr == NULL) { + addr = (*env)->NewByteArray(env, 16); + CHECK_NULL_RETURN(addr, JNI_FALSE); + (*env)->SetObjectField(env, holder, ia6_ipaddressID, addr); + } + (*env)->SetByteArrayRegion(env, addr, 0, 16, (jbyte *)address); + return JNI_TRUE; +} + void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) { jobject holder; init(env); @@ -167,6 +253,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { } else { static jclass inet6Cls = 0; jint scope; + int ret; if (inet6Cls == 0) { jclass c = (*env)->FindClass(env, "java/net/Inet6Address"); CHECK_NULL_RETURN(c, NULL); @@ -176,18 +263,11 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { } iaObj = (*env)->NewObject(env, inet6Cls, ia6_ctrID); CHECK_NULL_RETURN(iaObj, NULL); - ipaddress = (*env)->NewByteArray(env, 16); - CHECK_NULL_RETURN(ipaddress, NULL); - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(him6->sin6_addr)); - - (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress); - + ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr)); + CHECK_NULL_RETURN(ret, NULL); setInetAddress_family(env, iaObj, IPv6); scope = getScopeID(him); - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - if (scope > 0) - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); + setInet6Address_scopeid(env, iaObj, scope); } *port = ntohs(him6->sin6_port); } else @@ -247,9 +327,8 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) if (family == AF_INET) { return JNI_FALSE; } - ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); - scope = (*env)->GetIntField(env, iaObj, ia6_scopeidID); - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddrCur); + scope = getInet6Address_scopeid(env, iaObj); + getInet6Address_ipaddress(env, iaObj, (char *)caddrCur); if (NET_IsEqual(caddrNew, caddrCur) && cmpScopeID(scope, him)) { return JNI_TRUE; } else { diff --git a/jdk/src/share/native/java/net/net_util.h b/jdk/src/share/native/java/net/net_util.h index 0fd5b6c427f..d38a5f52fcf 100644 --- a/jdk/src/share/native/java/net/net_util.h +++ b/jdk/src/share/native/java/net/net_util.h @@ -58,6 +58,19 @@ extern jfieldID iac_familyID; extern jfieldID iac_hostNameID; extern jfieldID ia_preferIPv6AddressID; +/** (Inet6Address accessors) + * set_ methods return JNI_TRUE on success JNI_FALSE on error + * get_ methods that return int/boolean, return -1 on error + * get_ methods that return objects return NULL on error. + */ +extern jobject getInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj); +extern int setInet6Address_scopeifname(JNIEnv *env, jobject ia6Obj, jobject scopeifname); +extern int getInet6Address_scopeid_set(JNIEnv *env, jobject ia6Obj); +extern int getInet6Address_scopeid(JNIEnv *env, jobject ia6Obj); +extern int setInet6Address_scopeid(JNIEnv *env, jobject ia6Obj, int scopeid); +extern int getInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *dest); +extern int setInet6Address_ipaddress(JNIEnv *env, jobject ia6Obj, char *address); + extern void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address); extern void setInetAddress_family(JNIEnv *env, jobject iaObj, int family); extern void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject h); @@ -93,12 +106,12 @@ extern jfieldID dp_bufLengthID; /* Inet6Address fields */ extern jclass ia6_class; +extern jfieldID ia6_holder6ID; extern jfieldID ia6_ipaddressID; extern jfieldID ia6_scopeidID; extern jfieldID ia6_cachedscopeidID; extern jfieldID ia6_scopeidsetID; extern jfieldID ia6_scopeifnameID; -extern jfieldID ia6_scopeifnamesetID; extern jmethodID ia6_ctrID; /************************************************************************ diff --git a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c index 4fc64867f8b..694826f3aba 100644 --- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c +++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c @@ -120,7 +120,6 @@ static jclass ni_ia4cls; static jclass ni_ia6cls; static jmethodID ni_ia4ctrID; static jmethodID ni_ia6ctrID; -static jfieldID ni_ia6ipaddressID; static int initialized = 0; /* @@ -156,7 +155,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "", "()V"); ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "", "()V"); - ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); initialized = 1; } @@ -303,6 +301,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, } while (iterator != NULL) { + int ret1; if (iterator->ai_family == AF_INET) { jobject iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); if (IS_NULL(iaObj)) { @@ -315,26 +314,22 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, inetIndex++; } else if (iterator->ai_family == AF_INET6) { jint scope = 0; - jbyteArray ipaddress; jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (IS_NULL(iaObj)) { ret = NULL; goto cleanupAndReturn; } - ipaddress = (*env)->NewByteArray(env, 16); - if (IS_NULL(ipaddress)) { + ret1 = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); + if (!ret1) { ret = NULL; goto cleanupAndReturn; } - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); + scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); + setInet6Address_scopeid(env, iaObj, scope); } - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); setInetAddress_hostName(env, iaObj, host); (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); inet6Index++; diff --git a/jdk/src/solaris/native/java/net/NetworkInterface.c b/jdk/src/solaris/native/java/net/NetworkInterface.c index 68633db5a18..1c999442168 100644 --- a/jdk/src/solaris/native/java/net/NetworkInterface.c +++ b/jdk/src/solaris/native/java/net/NetworkInterface.c @@ -118,7 +118,6 @@ static jclass ni_ibcls; static jmethodID ni_ia4ctrID; static jmethodID ni_ia6ctrID; static jmethodID ni_ibctrID; -static jfieldID ni_ia6ipaddressID; static jfieldID ni_ibaddressID; static jfieldID ni_ib4broadcastID; static jfieldID ni_ib4maskID; @@ -193,7 +192,6 @@ Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) { ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "", "()V"); ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "", "()V"); ni_ibctrID = (*env)->GetMethodID(env, ni_ibcls, "", "()V"); - ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); ni_ibaddressID = (*env)->GetFieldID(env, ni_ibcls, "address", "Ljava/net/InetAddress;"); ni_ib4broadcastID = (*env)->GetFieldID(env, ni_ibcls, "broadcast", "Ljava/net/Inet4Address;"); ni_ib4maskID = (*env)->GetFieldID(env, ni_ibcls, "maskLength", "S"); @@ -332,11 +330,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0 #ifdef AF_INET6 if (family == AF_INET6) { jbyte *bytes = (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr); - jbyteArray ipaddress = (*env)->GetObjectField(env, iaObj, ni_ia6ipaddressID); jbyte caddr[16]; int i; - - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); + getInet6Address_ipaddress(env, iaObj, (char *)caddr); i = 0; while (i < 16) { if (caddr[i] != bytes[i]) { @@ -670,21 +666,17 @@ jobject createNetworkInterface(JNIEnv *env, netif *ifs) { int scope=0; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (iaObj) { - jbyteArray ipaddress = (*env)->NewByteArray(env, 16); - if (ipaddress == NULL) { + int ret = setInet6Address_ipaddress(env, iaObj, (char *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); + if (ret == JNI_FALSE) { return NULL; } - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); - (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); + setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeifname(env, iaObj, netifObj); } - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj) { diff --git a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c index 981bf534a66..09f8e5d0c61 100644 --- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c +++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c @@ -2148,8 +2148,7 @@ static void mcast_join_leave(JNIEnv *env, jobject this, caddr[14] = ((address >> 8) & 0xff); caddr[15] = (address & 0xff); } else { - ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); + getInet6Address_ipaddress(env, iaObj, caddr); } memcpy((void *)&(mname6.ipv6mr_multiaddr), caddr, sizeof(struct in6_addr)); diff --git a/jdk/src/solaris/native/java/net/net_util_md.c b/jdk/src/solaris/native/java/net/net_util_md.c index 004b6aa5d92..d7ebbd5a7c9 100644 --- a/jdk/src/solaris/native/java/net/net_util_md.c +++ b/jdk/src/solaris/native/java/net/net_util_md.c @@ -782,7 +782,6 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr /* needs work. 1. family 2. clean up him6 etc deallocate memory */ if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) { struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him; - jbyteArray ipaddress; jbyte caddr[16]; jint address; @@ -803,8 +802,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr caddr[15] = (address & 0xff); } } else { - ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); + getInet6Address_ipaddress(env, iaObj, (char *)caddr); } memset((char *)him6, 0, sizeof(struct sockaddr_in6)); him6->sin6_port = htons(port); @@ -840,7 +838,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr */ if (!cached_scope_id) { if (ia6_scopeidID) { - scope_id = (int)(*env)->GetIntField(env,iaObj,ia6_scopeidID); + scope_id = getInet6Address_scopeid(env, iaObj); } if (scope_id != 0) { /* check user-specified value for loopback case @@ -884,7 +882,7 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr if (family != IPv4) { if (ia6_scopeidID) { - him6->sin6_scope_id = (int)(*env)->GetIntField(env, iaObj, ia6_scopeidID); + him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj); } } #endif diff --git a/jdk/src/windows/native/java/net/Inet6AddressImpl.c b/jdk/src/windows/native/java/net/Inet6AddressImpl.c index 6f46d7eb642..c124f91f4d5 100644 --- a/jdk/src/windows/native/java/net/Inet6AddressImpl.c +++ b/jdk/src/windows/native/java/net/Inet6AddressImpl.c @@ -77,7 +77,6 @@ static jclass ni_ia4cls; static jclass ni_ia6cls; static jmethodID ni_ia4ctrID; static jmethodID ni_ia6ctrID; -static jfieldID ni_ia6ipaddressID; static int initialized = 0; JNIEXPORT jobjectArray JNICALL @@ -101,7 +100,6 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); ni_ia4ctrID = (*env)->GetMethodID(env, ni_ia4cls, "", "()V"); ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "", "()V"); - ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); initialized = 1; } if (IS_NULL(host)) { @@ -242,26 +240,22 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, (*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj); inetIndex ++; } else if (iterator->ai_family == AF_INET6) { - jint scope = 0; - jbyteArray ipaddress; + jint scope = 0, ret1; jobject iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (IS_NULL(iaObj)) { ret = NULL; goto cleanupAndReturn; } - ipaddress = (*env)->NewByteArray(env, 16); - if (IS_NULL(ipaddress)) { + ret1 = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); + + if (ret1 == JNI_FALSE) { ret = NULL; goto cleanupAndReturn; } - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(((struct sockaddr_in6*)iterator->ai_addr)->sin6_addr)); scope = ((struct sockaddr_in6*)iterator->ai_addr)->sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); + setInet6Address_scopeid(env, iaObj, scope); } - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); setInetAddress_hostName(env, iaObj, host); (*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj); inet6Index ++; diff --git a/jdk/src/windows/native/java/net/NetworkInterface.c b/jdk/src/windows/native/java/net/NetworkInterface.c index c548930a913..edcccd4ae4c 100644 --- a/jdk/src/windows/native/java/net/NetworkInterface.c +++ b/jdk/src/windows/native/java/net/NetworkInterface.c @@ -72,8 +72,6 @@ jmethodID ni_ia4Ctor; /* Inet4Address() */ jclass ni_ia6cls; /* Inet6Address */ jmethodID ni_ia6ctrID; /* Inet6Address() */ -jfieldID ni_ia6ipaddressID; -jfieldID ni_ia6ipaddressID; jclass ni_ibcls; /* InterfaceAddress */ jmethodID ni_ibctrID; /* InterfaceAddress() */ @@ -520,7 +518,6 @@ Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls) ni_ia6cls = (*env)->FindClass(env, "java/net/Inet6Address"); ni_ia6cls = (*env)->NewGlobalRef(env, ni_ia6cls); ni_ia6ctrID = (*env)->GetMethodID(env, ni_ia6cls, "", "()V"); - ni_ia6ipaddressID = (*env)->GetFieldID(env, ni_ia6cls, "ipaddress", "[B"); ni_ibcls = (*env)->FindClass(env, "java/net/InterfaceAddress"); ni_ibcls = (*env)->NewGlobalRef(env, ni_ibcls); @@ -621,19 +618,16 @@ jobject createNetworkInterface int scope; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (iaObj) { - jbyteArray ipaddress = (*env)->NewByteArray(env, 16); - if (ipaddress == NULL) { + int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); + if (ret == JNI_FALSE) { return NULL; } - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); + scope = addrs->addr.him6.sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); - (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); + setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeifname(env, iaObj, netifObj); } - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { free_netaddr(netaddrP); diff --git a/jdk/src/windows/native/java/net/NetworkInterface_winXP.c b/jdk/src/windows/native/java/net/NetworkInterface_winXP.c index 1078d826afa..67374a02583 100644 --- a/jdk/src/windows/native/java/net/NetworkInterface_winXP.c +++ b/jdk/src/windows/native/java/net/NetworkInterface_winXP.c @@ -544,19 +544,15 @@ static jobject createNetworkInterfaceXP(JNIEnv *env, netif *ifs) int scope; iaObj = (*env)->NewObject(env, ni_ia6cls, ni_ia6ctrID); if (iaObj) { - jbyteArray ipaddress = (*env)->NewByteArray(env, 16); - if (ipaddress == NULL) { + int ret = setInet6Address_ipaddress(env, iaObj, (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); + if (ret == JNI_FALSE) { return NULL; } - (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(addrs->addr.him6.sin6_addr.s6_addr)); scope = addrs->addr.him6.sin6_scope_id; if (scope != 0) { /* zero is default value, no need to set */ - (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); - (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); - (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); + setInet6Address_scopeid(env, iaObj, scope); + setInet6Address_scopeifname(env, iaObj, netifObj); } - (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj == NULL) { free_netaddr(netaddrP); diff --git a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c index 6823ddc7c7c..f535073df38 100644 --- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c +++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c @@ -728,7 +728,6 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, setInetAddress_family(env, socketAddressObj, IPv4); (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj); } else { - jbyteArray addr; /* AF_INET6 -> Inet6Address */ if (inet6Cls == 0) { jclass c = (*env)->FindClass(env, "java/net/Inet6Address"); @@ -751,14 +750,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this, NET_SocketClose(fd); return; } - addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID); - (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr); + setInet6Address_ipaddress(env, socketAddressObj, (const char *)&him.him6.sin6_addr); setInetAddress_family(env, socketAddressObj, IPv6); - scope = him.him6.sin6_scope_id; - (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, scope); - if(scope>0) { - (*env)->SetBooleanField(env, socketAddressObj, ia6_scopeidsetID, JNI_TRUE); - } + setInet6Address_scopeid(env, socketAddressObj, him.him6.sin6_scope_id); + } /* fields common to AF_INET and AF_INET6 */ diff --git a/jdk/src/windows/native/java/net/net_util_md.c b/jdk/src/windows/native/java/net/net_util_md.c index 4e5cb50b0bc..6ddb2bcfd78 100644 --- a/jdk/src/windows/native/java/net/net_util_md.c +++ b/jdk/src/windows/native/java/net/net_util_md.c @@ -851,7 +851,6 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr family = (iafam == IPv4)? AF_INET : AF_INET6; if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) { struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; - jbyteArray ipaddress; jbyte caddr[16]; jint address, scopeid = 0; jint cached_scope_id = 0; @@ -872,10 +871,9 @@ NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr caddr[15] = (address & 0xff); } } else { - ipaddress = (*env)->GetObjectField(env, iaObj, ia6_ipaddressID); - scopeid = (jint)(*env)->GetIntField(env, iaObj, ia6_scopeidID); + getInet6Address_ipaddress(env, iaObj, (char *)caddr); + scopeid = getInet6Address_scopeid(env, iaObj); cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID); - (*env)->GetByteArrayRegion(env, ipaddress, 0, 16, caddr); } memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6)); diff --git a/jdk/test/java/net/Inet6Address/serialize/Serialize.java b/jdk/test/java/net/Inet6Address/serialize/Serialize.java index c563c8b115a..f7c6fe735fb 100644 --- a/jdk/test/java/net/Inet6Address/serialize/Serialize.java +++ b/jdk/test/java/net/Inet6Address/serialize/Serialize.java @@ -94,7 +94,26 @@ public class Serialize { } finally { ois.close(); } - System.out.println(nobj); + + nobj = (Inet6Address)InetAddress.getByAddress("foo.com", new byte[] { + (byte)0xfe,(byte)0x80,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0, + (byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)1 + }); + if (!test1(nobj, addr1)) { + throw new RuntimeException("failed with " + nobj.toString()); + } + nobj = (Inet6Address)InetAddress.getByAddress("x.bar.com", new byte[] { + (byte)0xfe,(byte)0xC0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0, + (byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)1 + }); + if (!test1(nobj, addr2)) { + throw new RuntimeException("failed with " + nobj.toString()); + } + nobj = (Inet6Address)InetAddress.getByName("::1"); + if (!test1(nobj, addr3)) { + throw new RuntimeException("failed with " + nobj.toString()); + } + System.out.println("All tests passed"); } @@ -113,4 +132,162 @@ public class Serialize { return false; } } - } + + static boolean test1 (Inet6Address obj, byte[] buf) throws Exception { + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buf)); + Inet6Address nobj = (Inet6Address) ois.readObject(); + ois.close(); + + if (nobj.equals(obj)) { + return true; + } else { + return false; + } + } + + // Inet6Address instances serialized with JDK 6 + + static byte[] addr1 = { + (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72, + (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49, + (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64, + (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f, + (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80, + (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00, + (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65, + (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c, + (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f, + (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74, + (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f, + (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e, + (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65, + (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66, + (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00, + (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f, + (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67, + (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70, + (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73, + (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42, + (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61, + (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74, + (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41, + (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73, + (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3, + (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49, + (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72, + (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06, + (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79, + (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73, + (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71, + (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x02,(byte)0x74,(byte)0x00,(byte)0x07,(byte)0x66, + (byte)0x6f,(byte)0x6f,(byte)0x2e,(byte)0x63,(byte)0x6f,(byte)0x6d, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x70,(byte)0x75,(byte)0x72,(byte)0x00,(byte)0x02,(byte)0x5b, + (byte)0x42,(byte)0xac,(byte)0xf3,(byte)0x17,(byte)0xf8,(byte)0x06, + (byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02,(byte)0x00,(byte)0x00, + (byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x10, + (byte)0xfe,(byte)0x80,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01,(byte)0x78 + }; + + static byte[] addr2 = { + (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72, + (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49, + (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64, + (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f, + (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80, + (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00, + (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65, + (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c, + (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f, + (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74, + (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f, + (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e, + (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65, + (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66, + (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00, + (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f, + (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67, + (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70, + (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73, + (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42, + (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61, + (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74, + (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41, + (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73, + (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3, + (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49, + (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72, + (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06, + (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79, + (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73, + (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71, + (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x02,(byte)0x74,(byte)0x00,(byte)0x09,(byte)0x78, + (byte)0x2e,(byte)0x62,(byte)0x61,(byte)0x72,(byte)0x2e,(byte)0x63, + (byte)0x6f,(byte)0x6d,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x70,(byte)0x75,(byte)0x72,(byte)0x00, + (byte)0x02,(byte)0x5b,(byte)0x42,(byte)0xac,(byte)0xf3,(byte)0x17, + (byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0,(byte)0x02, + (byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x10,(byte)0xfe,(byte)0xc0,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x01, + (byte)0x78 + }; + + static byte[] addr3 = { + (byte)0xac,(byte)0xed,(byte)0x00,(byte)0x05,(byte)0x73,(byte)0x72, + (byte)0x00,(byte)0x15,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x2e,(byte)0x49, + (byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x36,(byte)0x41,(byte)0x64, + (byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73,(byte)0x5f, + (byte)0x7c,(byte)0x20,(byte)0x81,(byte)0x52,(byte)0x2c,(byte)0x80, + (byte)0x21,(byte)0x03,(byte)0x00,(byte)0x05,(byte)0x49,(byte)0x00, + (byte)0x08,(byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65, + (byte)0x5f,(byte)0x69,(byte)0x64,(byte)0x5a,(byte)0x00,(byte)0x0c, + (byte)0x73,(byte)0x63,(byte)0x6f,(byte)0x70,(byte)0x65,(byte)0x5f, + (byte)0x69,(byte)0x64,(byte)0x5f,(byte)0x73,(byte)0x65,(byte)0x74, + (byte)0x5a,(byte)0x00,(byte)0x10,(byte)0x73,(byte)0x63,(byte)0x6f, + (byte)0x70,(byte)0x65,(byte)0x5f,(byte)0x69,(byte)0x66,(byte)0x6e, + (byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x5f,(byte)0x73,(byte)0x65, + (byte)0x74,(byte)0x4c,(byte)0x00,(byte)0x06,(byte)0x69,(byte)0x66, + (byte)0x6e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x74,(byte)0x00, + (byte)0x12,(byte)0x4c,(byte)0x6a,(byte)0x61,(byte)0x76,(byte)0x61, + (byte)0x2f,(byte)0x6c,(byte)0x61,(byte)0x6e,(byte)0x67,(byte)0x2f, + (byte)0x53,(byte)0x74,(byte)0x72,(byte)0x69,(byte)0x6e,(byte)0x67, + (byte)0x3b,(byte)0x5b,(byte)0x00,(byte)0x09,(byte)0x69,(byte)0x70, + (byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73, + (byte)0x73,(byte)0x74,(byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42, + (byte)0x78,(byte)0x72,(byte)0x00,(byte)0x14,(byte)0x6a,(byte)0x61, + (byte)0x76,(byte)0x61,(byte)0x2e,(byte)0x6e,(byte)0x65,(byte)0x74, + (byte)0x2e,(byte)0x49,(byte)0x6e,(byte)0x65,(byte)0x74,(byte)0x41, + (byte)0x64,(byte)0x64,(byte)0x72,(byte)0x65,(byte)0x73,(byte)0x73, + (byte)0x2d,(byte)0x9b,(byte)0x57,(byte)0xaf,(byte)0x9f,(byte)0xe3, + (byte)0xeb,(byte)0xdb,(byte)0x02,(byte)0x00,(byte)0x03,(byte)0x49, + (byte)0x00,(byte)0x07,(byte)0x61,(byte)0x64,(byte)0x64,(byte)0x72, + (byte)0x65,(byte)0x73,(byte)0x73,(byte)0x49,(byte)0x00,(byte)0x06, + (byte)0x66,(byte)0x61,(byte)0x6d,(byte)0x69,(byte)0x6c,(byte)0x79, + (byte)0x4c,(byte)0x00,(byte)0x08,(byte)0x68,(byte)0x6f,(byte)0x73, + (byte)0x74,(byte)0x4e,(byte)0x61,(byte)0x6d,(byte)0x65,(byte)0x71, + (byte)0x00,(byte)0x7e,(byte)0x00,(byte)0x01,(byte)0x78,(byte)0x70, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x02,(byte)0x70,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x70,(byte)0x75,(byte)0x72, + (byte)0x00,(byte)0x02,(byte)0x5b,(byte)0x42,(byte)0xac,(byte)0xf3, + (byte)0x17,(byte)0xf8,(byte)0x06,(byte)0x08,(byte)0x54,(byte)0xe0, + (byte)0x02,(byte)0x00,(byte)0x00,(byte)0x78,(byte)0x70,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x10,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x01,(byte)0x78 + }; +} From 3d9f33759d5c2e1d6e6d8438d8ae78416bfac086 Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Fri, 19 Jul 2013 12:14:34 +0900 Subject: [PATCH 026/263] 8001029: Add new date/time capability Reviewed-by: mchung, hawtin --- jdk/src/share/classes/java/util/TimeZone.java | 140 +++++------------- .../util/TimeZone/SetDefaultSecurityTest.java | 67 +++++++++ 2 files changed, 107 insertions(+), 100 deletions(-) create mode 100644 jdk/test/java/util/TimeZone/SetDefaultSecurityTest.java diff --git a/jdk/src/share/classes/java/util/TimeZone.java b/jdk/src/share/classes/java/util/TimeZone.java index ba4abb91f2c..3075bff157a 100644 --- a/jdk/src/share/classes/java/util/TimeZone.java +++ b/jdk/src/share/classes/java/util/TimeZone.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2013, 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 @@ -39,13 +39,9 @@ package java.util; import java.io.Serializable; -import java.lang.ref.SoftReference; import java.security.AccessController; import java.security.PrivilegedAction; import java.time.ZoneId; -import java.util.concurrent.ConcurrentHashMap; -import sun.misc.JavaAWTAccess; -import sun.misc.SharedSecrets; import sun.security.action.GetPropertyAction; import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfoFile; @@ -596,11 +592,26 @@ abstract public class TimeZone implements Serializable, Cloneable { private static native String getSystemGMTOffsetID(); /** - * Gets the default TimeZone for this host. - * The source of the default TimeZone - * may vary with implementation. - * @return a default TimeZone. - * @see #setDefault + * Gets the default {@code TimeZone} of the Java virtual machine. If the + * cached default {@code TimeZone} is available, its clone is returned. + * Otherwise, the method takes the following steps to determine the default + * time zone. + * + *

    + *
  • Use the {@code user.timezone} property value as the default + * time zone ID if it's available.
  • + *
  • Detect the platform time zone ID. The source of the + * platform time zone and ID mapping may vary with implementation.
  • + *
  • Use {@code GMT} as the last resort if the given or detected + * time zone ID is unknown.
  • + *
+ * + *

The default {@code TimeZone} created from the ID is cached, + * and its clone is returned. The {@code user.timezone} property + * value is set to the ID upon return. + * + * @return the default {@code TimeZone} + * @see #setDefault(TimeZone) */ public static TimeZone getDefault() { return (TimeZone) getDefaultRef().clone(); @@ -611,14 +622,11 @@ abstract public class TimeZone implements Serializable, Cloneable { * method doesn't create a clone. */ static TimeZone getDefaultRef() { - TimeZone defaultZone = getDefaultInAppContext(); + TimeZone defaultZone = defaultTimeZone; if (defaultZone == null) { - defaultZone = defaultTimeZone; - if (defaultZone == null) { - // Need to initialize the default time zone. - defaultZone = setDefaultZone(); - assert defaultZone != null; - } + // Need to initialize the default time zone. + defaultZone = setDefaultZone(); + assert defaultZone != null; } // Don't clone here. return defaultZone; @@ -676,95 +684,27 @@ abstract public class TimeZone implements Serializable, Cloneable { return tz; } - private static boolean hasPermission() { - boolean hasPermission = true; - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - try { - sm.checkPermission(new PropertyPermission - ("user.timezone", "write")); - } catch (SecurityException e) { - hasPermission = false; - } - } - return hasPermission; - } - /** - * Sets the TimeZone that is - * returned by the getDefault method. If zone - * is null, reset the default to the value it had originally when the - * VM first started. - * @param zone the new default time zone + * Sets the {@code TimeZone} that is returned by the {@code getDefault} + * method. {@code zone} is cached. If {@code zone} is null, the cached + * default {@code TimeZone} is cleared. This method doesn't change the value + * of the {@code user.timezone} property. + * + * @param zone the new default {@code TimeZone}, or null + * @throws SecurityException if the security manager's {@code checkPermission} + * denies {@code PropertyPermission("user.timezone", + * "write")} * @see #getDefault + * @see PropertyPermission */ public static void setDefault(TimeZone zone) { - if (hasPermission()) { - synchronized (TimeZone.class) { - defaultTimeZone = zone; - setDefaultInAppContext(null); - } - } else { - setDefaultInAppContext(zone); - } - } - - /** - * Returns the default TimeZone in an AppContext if any AppContext - * has ever used. null is returned if any AppContext hasn't been - * used or if the AppContext doesn't have the default TimeZone. - * - * Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't - * been loaded. If so, it implies that AWTSecurityManager is not our - * SecurityManager and we can use a local static variable. - * This works around a build time issue. - */ - private static TimeZone getDefaultInAppContext() { - // JavaAWTAccess provides access implementation-private methods without using reflection. - JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess(); - - if (javaAWTAccess == null) { - return mainAppContextDefault; - } else { - if (!javaAWTAccess.isDisposed()) { - TimeZone tz = (TimeZone) - javaAWTAccess.get(TimeZone.class); - if (tz == null && javaAWTAccess.isMainAppContext()) { - return mainAppContextDefault; - } else { - return tz; - } - } - } - return null; - } - - /** - * Sets the default TimeZone in the AppContext to the given - * tz. null is handled special: do nothing if any AppContext - * hasn't been used, remove the default TimeZone in the - * AppContext otherwise. - * - * Note that javaAWTAccess may be null if sun.awt.AppContext class hasn't - * been loaded. If so, it implies that AWTSecurityManager is not our - * SecurityManager and we can use a local static variable. - * This works around a build time issue. - */ - private static void setDefaultInAppContext(TimeZone tz) { - // JavaAWTAccess provides access implementation-private methods without using reflection. - JavaAWTAccess javaAWTAccess = SharedSecrets.getJavaAWTAccess(); - - if (javaAWTAccess == null) { - mainAppContextDefault = tz; - } else { - if (!javaAWTAccess.isDisposed()) { - javaAWTAccess.put(TimeZone.class, tz); - if (javaAWTAccess.isMainAppContext()) { - mainAppContextDefault = null; - } - } + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(new PropertyPermission + ("user.timezone", "write")); } + defaultTimeZone = zone; } /** diff --git a/jdk/test/java/util/TimeZone/SetDefaultSecurityTest.java b/jdk/test/java/util/TimeZone/SetDefaultSecurityTest.java new file mode 100644 index 00000000000..e749ffe9420 --- /dev/null +++ b/jdk/test/java/util/TimeZone/SetDefaultSecurityTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 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. + */ + +/* + * @test + * @bug 8001029 + * @summary Make sure that TimeZone.setDefault throws a SecurityException if the + * security manager doesn't permit. + * @run main/othervm SetDefaultSecurityTest + */ + +import java.util.SimpleTimeZone; +import java.util.TimeZone; + +public class SetDefaultSecurityTest { + static final TimeZone NOWHERE = new SimpleTimeZone(Integer.MAX_VALUE, "Nowhere"); + + public static void main(String[] args) { + TimeZone defaultZone = TimeZone.getDefault(); + + // Make sure that TimeZone.setDefault works for trusted code + TimeZone.setDefault(NOWHERE); + if (!NOWHERE.equals(TimeZone.getDefault())) { + new RuntimeException("TimeZone.setDefault doesn't work for trusted code."); + } + // Restore defaultZone + TimeZone.setDefault(defaultZone); + if (!defaultZone.equals(TimeZone.getDefault())) { + new RuntimeException("TimeZone.setDefault doesn't restore defaultZone."); + } + + // Install a SecurityManager. + System.setSecurityManager(new SecurityManager()); + try { + TimeZone.setDefault(NOWHERE); + throw new RuntimeException("TimeZone.setDefault doesn't throw a SecurityException."); + } catch (SecurityException se) { + // OK + } + TimeZone tz = TimeZone.getDefault(); + if (!defaultZone.equals(tz)) { + throw new RuntimeException("Default TimeZone changed: " + tz); + } + } +} From 20511649934fed3e8094b69b5375107b965c62a9 Mon Sep 17 00:00:00 2001 From: Shanliang Jiang Date: Fri, 19 Jul 2013 13:35:01 +0200 Subject: [PATCH 027/263] 8014534: Better profiling support Validation of parameters Reviewed-by: sspitsyn, skoivu, mchung --- .../com/sun/demo/jvmti/hprof/Tracker.java | 26 ++++++++++++++++-- jdk/src/share/demo/jvmti/hprof/hprof_class.c | 14 ++++++++-- jdk/src/share/demo/jvmti/hprof/hprof_event.c | 27 ++++++++++++++----- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/jdk/src/share/classes/com/sun/demo/jvmti/hprof/Tracker.java b/jdk/src/share/classes/com/sun/demo/jvmti/hprof/Tracker.java index f2e33d72454..96950870be2 100644 --- a/jdk/src/share/classes/com/sun/demo/jvmti/hprof/Tracker.java +++ b/jdk/src/share/classes/com/sun/demo/jvmti/hprof/Tracker.java @@ -53,7 +53,10 @@ public class Tracker { public static void ObjectInit(Object obj) { - if ( engaged != 0 ) { + if ( engaged != 0) { + if (obj == null) { + throw new IllegalArgumentException("Null object."); + } nativeObjectInit(Thread.currentThread(), obj); } } @@ -66,7 +69,10 @@ public class Tracker { public static void NewArray(Object obj) { - if ( engaged != 0 ) { + if ( engaged != 0) { + if (obj == null) { + throw new IllegalArgumentException("Null object."); + } nativeNewArray(Thread.currentThread(), obj); } } @@ -82,6 +88,14 @@ public class Tracker { public static void CallSite(int cnum, int mnum) { if ( engaged != 0 ) { + if (cnum < 0) { + throw new IllegalArgumentException("Negative class index"); + } + + if (mnum < 0) { + throw new IllegalArgumentException("Negative method index"); + } + nativeCallSite(Thread.currentThread(), cnum, mnum); } } @@ -95,6 +109,14 @@ public class Tracker { public static void ReturnSite(int cnum, int mnum) { if ( engaged != 0 ) { + if (cnum < 0) { + throw new IllegalArgumentException("Negative class index"); + } + + if (mnum < 0) { + throw new IllegalArgumentException("Negative method index"); + } + nativeReturnSite(Thread.currentThread(), cnum, mnum); } } diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_class.c b/jdk/src/share/demo/jvmti/hprof/hprof_class.c index f25f53ad934..fb16784476f 100644 --- a/jdk/src/share/demo/jvmti/hprof/hprof_class.c +++ b/jdk/src/share/demo/jvmti/hprof/hprof_class.c @@ -527,7 +527,12 @@ class_get_methodID(JNIEnv *env, ClassIndex index, MethodIndex mnum) jmethodID method; info = get_info(index); - HPROF_ASSERT(mnum < info->method_count); + if (mnum >= info->method_count) { + jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); + (*env)->ThrowNew(env, newExcCls, "Illegal mnum"); + + return NULL; + } method = info->method[mnum].method_id; if ( method == NULL ) { char * name; @@ -535,7 +540,12 @@ class_get_methodID(JNIEnv *env, ClassIndex index, MethodIndex mnum) jclass clazz; name = (char *)string_get(info->method[mnum].name_index); - HPROF_ASSERT(name!=NULL); + if (name==NULL) { + jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); + (*env)->ThrowNew(env, newExcCls, "Name not found"); + + return NULL; + } sig = (char *)string_get(info->method[mnum].sig_index); HPROF_ASSERT(sig!=NULL); clazz = class_get_class(env, index); diff --git a/jdk/src/share/demo/jvmti/hprof/hprof_event.c b/jdk/src/share/demo/jvmti/hprof/hprof_event.c index 15dd4ddaa76..7892457d3f8 100644 --- a/jdk/src/share/demo/jvmti/hprof/hprof_event.c +++ b/jdk/src/share/demo/jvmti/hprof/hprof_event.c @@ -195,7 +195,12 @@ event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(cnum!=0 && cnum!=gdata->tracker_cnum); + if (cnum == 0 || cnum == gdata->tracker_cnum) { + jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); + (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); + + return; + } /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, @@ -204,8 +209,10 @@ event_call(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) (*pstatus) = 1; method = class_get_methodID(env, cnum, mnum); - HPROF_ASSERT(method!=NULL); - tls_push_method(tls_index, method); + if (method != NULL) { + tls_push_method(tls_index, method); + } + (*pstatus) = 0; } } @@ -248,7 +255,13 @@ event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) HPROF_ASSERT(env!=NULL); HPROF_ASSERT(thread!=NULL); - HPROF_ASSERT(cnum!=0 && cnum!=gdata->tracker_cnum); + + if (cnum == 0 || cnum == gdata->tracker_cnum) { + jclass newExcCls = (*env)->FindClass(env, "java/lang/IllegalArgumentException"); + (*env)->ThrowNew(env, newExcCls, "Illegal cnum."); + + return; + } /* Prevent recursion into any BCI function for this thread (pstatus). */ if ( tls_get_tracker_status(env, thread, JNI_FALSE, @@ -257,8 +270,10 @@ event_return(JNIEnv *env, jthread thread, ClassIndex cnum, MethodIndex mnum) (*pstatus) = 1; method = class_get_methodID(env, cnum, mnum); - HPROF_ASSERT(method!=NULL); - tls_pop_method(tls_index, thread, method); + if (method != NULL) { + tls_pop_method(tls_index, thread, method); + } + (*pstatus) = 0; } } From bd41c425d2a88e9e78897a43a5e3ea811d453ba4 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Mon, 22 Jul 2013 19:41:07 -0700 Subject: [PATCH 028/263] 8017196: Ensure Proxies are handled appropriately Reviewed-by: dfuchs, jrose, jdn, ahgross, chegar --- .../java/lang/invoke/MethodHandles.java | 15 ++++-- .../classes/java/lang/reflect/Proxy.java | 38 +++++++++++---- .../classes/sun/reflect/misc/ReflectUtil.java | 48 +++++++++++++++++++ 3 files changed, 88 insertions(+), 13 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index 3bf24bc8503..1c9a068ed92 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -433,7 +433,7 @@ public class MethodHandles { Lookup(Class lookupClass) { this(lookupClass, ALL_MODES); // make sure we haven't accidentally picked up a privileged class: - checkUnprivilegedlookupClass(lookupClass); + checkUnprivilegedlookupClass(lookupClass, ALL_MODES); } private Lookup(Class lookupClass, int allowedModes) { @@ -487,7 +487,7 @@ public class MethodHandles { // No permissions. newModes = 0; } - checkUnprivilegedlookupClass(requestedLookupClass); + checkUnprivilegedlookupClass(requestedLookupClass, newModes); return new Lookup(requestedLookupClass, newModes); } @@ -503,10 +503,19 @@ public class MethodHandles { /** Package-private version of lookup which is trusted. */ static final Lookup IMPL_LOOKUP = new Lookup(Object.class, TRUSTED); - private static void checkUnprivilegedlookupClass(Class lookupClass) { + private static void checkUnprivilegedlookupClass(Class lookupClass, int allowedModes) { String name = lookupClass.getName(); if (name.startsWith("java.lang.invoke.")) throw newIllegalArgumentException("illegal lookupClass: "+lookupClass); + + // For caller-sensitive MethodHandles.lookup() + // disallow lookup more restricted packages + if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) { + if (name.startsWith("java.") || + (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) { + throw newIllegalArgumentException("illegal lookupClass: " + lookupClass); + } + } } /** diff --git a/jdk/src/share/classes/java/lang/reflect/Proxy.java b/jdk/src/share/classes/java/lang/reflect/Proxy.java index dd5c2ad4336..f2e4eda4e62 100644 --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java @@ -347,11 +347,11 @@ public class Proxy implements java.io.Serializable { * s.checkPermission} with * {@code RuntimePermission("getClassLoader")} permission * denies access. - *

  • the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and + *
  • for each proxy interface, {@code intf}, + * the caller's class loader is not the same as or an + * ancestor of the class loader for {@code intf} and * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to any one of the - * given proxy interfaces.
  • + * s.checkPackageAccess()} denies access to {@code intf}. * * @throws NullPointerException if the {@code interfaces} array @@ -680,11 +680,11 @@ public class Proxy implements java.io.Serializable { * s.checkPermission} with * {@code RuntimePermission("getClassLoader")} permission * denies access; - *
  • the caller's class loader is not the same as or an - * ancestor of the class loader for the current class and + *
  • for each proxy interface, {@code intf}, + * the caller's class loader is not the same as or an + * ancestor of the class loader for {@code intf} and * invocation of {@link SecurityManager#checkPackageAccess - * s.checkPackageAccess()} denies access to any one of the - * given proxy interfaces.
  • + * s.checkPackageAccess()} denies access to {@code intf}; *
  • any of the given proxy interfaces is non-public and the * caller class is not in the same {@linkplain Package runtime package} * as the non-public interface and the invocation of @@ -795,7 +795,14 @@ public class Proxy implements java.io.Serializable { * @return the invocation handler for the proxy instance * @throws IllegalArgumentException if the argument is not a * proxy instance + * @throws SecurityException if a security manager, s, is present + * and the caller's class loader is not the same as or an + * ancestor of the class loader for the invocation handler + * and invocation of {@link SecurityManager#checkPackageAccess + * s.checkPackageAccess()} denies access to the invocation + * handler's class. */ + @CallerSensitive public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException { @@ -806,8 +813,19 @@ public class Proxy implements java.io.Serializable { throw new IllegalArgumentException("not a proxy instance"); } - Proxy p = (Proxy) proxy; - return p.h; + final Proxy p = (Proxy) proxy; + final InvocationHandler ih = p.h; + if (System.getSecurityManager() != null) { + Class ihClass = ih.getClass(); + Class caller = Reflection.getCallerClass(); + if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), + ihClass.getClassLoader())) + { + ReflectUtil.checkPackageAccess(ihClass); + } + } + + return ih; } private static native Class defineClass0(ClassLoader loader, String name, diff --git a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java index efd85fca9cb..1f871e8de02 100644 --- a/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java +++ b/jdk/src/share/classes/sun/reflect/misc/ReflectUtil.java @@ -26,8 +26,10 @@ package sun.reflect.misc; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; +import java.util.Arrays; import sun.reflect.Reflection; public final class ReflectUtil { @@ -250,4 +252,50 @@ public final class ReflectUtil { String pkg = (i != -1) ? name.substring(0, i) : ""; return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE); } + + /** + * Check if the given method is a method declared in the proxy interface + * implemented by the given proxy instance. + * + * @param proxy a proxy instance + * @param method an interface method dispatched to a InvocationHandler + * + * @throws IllegalArgumentException if the given proxy or method is invalid. + */ + public static void checkProxyMethod(Object proxy, Method method) { + // check if it is a valid proxy instance + if (proxy == null || !Proxy.isProxyClass(proxy.getClass())) { + throw new IllegalArgumentException("Not a Proxy instance"); +} + if (Modifier.isStatic(method.getModifiers())) { + throw new IllegalArgumentException("Can't handle static method"); + } + + Class c = method.getDeclaringClass(); + if (c == Object.class) { + String name = method.getName(); + if (name.equals("hashCode") || name.equals("equals") || name.equals("toString")) { + return; + } + } + + if (isSuperInterface(proxy.getClass(), c)) { + return; + } + + // disallow any method not declared in one of the proxy intefaces + throw new IllegalArgumentException("Can't handle: " + method); + } + + private static boolean isSuperInterface(Class c, Class intf) { + for (Class i : c.getInterfaces()) { + if (i == intf) { + return true; + } + if (isSuperInterface(i, intf)) { + return true; + } + } + return false; + } } From ff1d4ae90507ecf250df4852ffab15b037670f13 Mon Sep 17 00:00:00 2001 From: Sergey Gabdurakhmanov Date: Tue, 23 Jul 2013 09:30:58 +0400 Subject: [PATCH 029/263] 8016357: Update hotspot diagnostic class Add security check to HotSpotDiagnostic.dumpHeap Reviewed-by: fparain, sla, ahgross --- jdk/make/java/management/mapfile-vers | 2 +- jdk/makefiles/mapfiles/libmanagement/mapfile-vers | 2 +- .../com/sun/management/HotSpotDiagnosticMXBean.java | 5 +++++ .../classes/sun/management/HotSpotDiagnostic.java | 12 +++++++++++- .../share/native/sun/management/HotSpotDiagnostic.c | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/jdk/make/java/management/mapfile-vers b/jdk/make/java/management/mapfile-vers index 63c4fbf03cc..0ea2ab4eb06 100644 --- a/jdk/make/java/management/mapfile-vers +++ b/jdk/make/java/management/mapfile-vers @@ -57,7 +57,7 @@ SUNWprivate_1.1 { Java_sun_management_GcInfoBuilder_fillGcAttributeInfo; Java_sun_management_GcInfoBuilder_getLastGcInfo0; Java_sun_management_GcInfoBuilder_getNumGcExtAttributes; - Java_sun_management_HotSpotDiagnostic_dumpHeap; + Java_sun_management_HotSpotDiagnostic_dumpHeap0; Java_sun_management_HotspotThread_getInternalThreadCount; Java_sun_management_HotspotThread_getInternalThreadTimes0; Java_sun_management_MemoryImpl_getMemoryManagers0; diff --git a/jdk/makefiles/mapfiles/libmanagement/mapfile-vers b/jdk/makefiles/mapfiles/libmanagement/mapfile-vers index b934fe8b748..724f7bb7100 100644 --- a/jdk/makefiles/mapfiles/libmanagement/mapfile-vers +++ b/jdk/makefiles/mapfiles/libmanagement/mapfile-vers @@ -57,7 +57,7 @@ SUNWprivate_1.1 { Java_sun_management_GcInfoBuilder_fillGcAttributeInfo; Java_sun_management_GcInfoBuilder_getLastGcInfo0; Java_sun_management_GcInfoBuilder_getNumGcExtAttributes; - Java_sun_management_HotSpotDiagnostic_dumpHeap; + Java_sun_management_HotSpotDiagnostic_dumpHeap0; Java_sun_management_HotspotThread_getInternalThreadCount; Java_sun_management_HotspotThread_getInternalThreadTimes0; Java_sun_management_MemoryImpl_getMemoryManagers0; diff --git a/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index 2fe8835259f..eaf5447b430 100644 --- a/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/jdk/src/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -66,6 +66,11 @@ public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { * cannot be created, opened, or written to. * @throws UnsupportedOperationException if this operation is not supported. * @throws NullPointerException if outputFile is null. + * @throws SecurityException + * If a security manager exists and its {@link + * java.lang.SecurityManager#checkWrite(java.lang.String)} + * method denies write access to the named file + * or the caller does not have ManagmentPermission("control"). */ public void dumpHeap(String outputFile, boolean live) throws java.io.IOException; diff --git a/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java b/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java index a6d3be1640f..7a4bd99f274 100644 --- a/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java +++ b/jdk/src/share/classes/sun/management/HotSpotDiagnostic.java @@ -40,7 +40,17 @@ public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean { public HotSpotDiagnostic() { } - public native void dumpHeap(String outputFile, boolean live) throws IOException; + public void dumpHeap(String outputFile, boolean live) throws IOException { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkWrite(outputFile); + Util.checkControlAccess(); + } + + dumpHeap0(outputFile, live); + } + + private native void dumpHeap0(String outputFile, boolean live) throws IOException; public List getDiagnosticOptions() { List allFlags = Flag.getAllFlags(); diff --git a/jdk/src/share/native/sun/management/HotSpotDiagnostic.c b/jdk/src/share/native/sun/management/HotSpotDiagnostic.c index 8d48b201109..cfa9e9ab8fa 100644 --- a/jdk/src/share/native/sun/management/HotSpotDiagnostic.c +++ b/jdk/src/share/native/sun/management/HotSpotDiagnostic.c @@ -29,7 +29,7 @@ #include "sun_management_HotSpotDiagnostic.h" JNIEXPORT void JNICALL -Java_sun_management_HotSpotDiagnostic_dumpHeap +Java_sun_management_HotSpotDiagnostic_dumpHeap0 (JNIEnv *env, jobject dummy, jstring outputfile, jboolean live) { jmm_interface->DumpHeap0(env, outputfile, live); From 2fac55ced5c5e37112d3d2ab6ed0f7f88a725838 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 17 Jul 2013 18:46:00 +0800 Subject: [PATCH 030/263] 8020696: Merge problem for KdcComm.java Reviewed-by: chegar --- jdk/src/share/classes/sun/security/krb5/KdcComm.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/sun/security/krb5/KdcComm.java b/jdk/src/share/classes/sun/security/krb5/KdcComm.java index ae3b0f098b7..3d50f9569d3 100644 --- a/jdk/src/share/classes/sun/security/krb5/KdcComm.java +++ b/jdk/src/share/classes/sun/security/krb5/KdcComm.java @@ -227,15 +227,15 @@ public final class KdcComm { try { ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP); } catch(Exception first) { + boolean ok = false; while(tempKdc.hasNext()) { try { ibuf = sendIfPossible(obuf, tempKdc.next(), useTCP); - if (ibuf != null) { - return ibuf; - } + ok = true; + break; } catch(Exception ignore) {} } - throw first; + if (!ok) throw first; } if (ibuf == null) { throw new IOException("Cannot get a KDC reply"); From eef8299094596d609d610228ba0775a04f6b6108 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Fri, 19 Jul 2013 16:29:26 +0200 Subject: [PATCH 031/263] 8019584: javax/management/remote/mandatory/loading/MissingClassTest.java failed in nightly against jdk7u45: java.io.InvalidObjectException: Invalid notification: null Reviewed-by: mchung, sjiang, dfuchs, ahgross --- .../management/remote/NotificationResult.java | 17 +++++++++-------- .../management/remote/TargetedNotification.java | 8 ++------ .../mandatory/loading/MissingClassTest.java | 2 +- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/jdk/src/share/classes/javax/management/remote/NotificationResult.java b/jdk/src/share/classes/javax/management/remote/NotificationResult.java index 9e7cfaac31d..ff3978d99eb 100644 --- a/jdk/src/share/classes/javax/management/remote/NotificationResult.java +++ b/jdk/src/share/classes/javax/management/remote/NotificationResult.java @@ -132,16 +132,17 @@ public class NotificationResult implements Serializable { } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - ObjectInputStream.GetField gf = ois.readFields(); - TargetedNotification[] tNotifs = (TargetedNotification[])gf.get("targetedNotifications", null); - long snStart = gf.get("earliestSequenceNumber", -1L); - long snNext = gf.get("nextSequenceNumber", -1L); + ois.defaultReadObject(); try { - validate(tNotifs, snStart, snNext); + validate( + this.targetedNotifications, + this.earliestSequenceNumber, + this.nextSequenceNumber + ); - this.targetedNotifications = tNotifs.length == 0 ? tNotifs : tNotifs.clone(); - this.earliestSequenceNumber = snStart; - this.nextSequenceNumber = snNext; + this.targetedNotifications = this.targetedNotifications.length == 0 ? + this.targetedNotifications : + this.targetedNotifications.clone(); } catch (IllegalArgumentException e) { throw new InvalidObjectException(e.getMessage()); } diff --git a/jdk/src/share/classes/javax/management/remote/TargetedNotification.java b/jdk/src/share/classes/javax/management/remote/TargetedNotification.java index 03aa0ca6235..cc3d0dcc664 100644 --- a/jdk/src/share/classes/javax/management/remote/TargetedNotification.java +++ b/jdk/src/share/classes/javax/management/remote/TargetedNotification.java @@ -132,13 +132,9 @@ public class TargetedNotification implements Serializable { // } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { - ObjectInputStream.GetField gf = ois.readFields(); - Notification notification = (Notification)gf.get("notif", null); - Integer listenerId = (Integer)gf.get("id", null); + ois.defaultReadObject(); try { - validate(notification, listenerId); - this.notif = notification; - this.id = listenerId; + validate(this.notif, this.id); } catch (IllegalArgumentException e) { throw new InvalidObjectException(e.getMessage()); } diff --git a/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java b/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java index e70d0adfe6e..98eead895bf 100644 --- a/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java +++ b/jdk/test/javax/management/remote/mandatory/loading/MissingClassTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4915825 4921009 4934965 4977469 + * @bug 4915825 4921009 4934965 4977469 8019584 * @summary Tests behavior when client or server gets object of unknown class * @author Eamonn McManus * @run clean MissingClassTest SingleClassLoader From 99860de3cd08c11752b465c31a4257118d70ac28 Mon Sep 17 00:00:00 2001 From: Johnny Chen Date: Wed, 24 Jul 2013 12:03:57 -0700 Subject: [PATCH 032/263] 8020293: JVM crash Reviewed-by: prr, jgodinez --- jdk/src/share/classes/sun/font/GlyphLayout.java | 7 ++++--- jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/sun/font/GlyphLayout.java b/jdk/src/share/classes/sun/font/GlyphLayout.java index d29ecf34cb2..f2fc484caa0 100644 --- a/jdk/src/share/classes/sun/font/GlyphLayout.java +++ b/jdk/src/share/classes/sun/font/GlyphLayout.java @@ -468,9 +468,10 @@ public final class GlyphLayout { _gvdata.grow(); } } - if (_gvdata._count < 0) { - break; - } + } + // Break out of the outer for loop if layout fails. + if (_gvdata._count < 0) { + break; } } diff --git a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp index b32f2601b4d..858e3636038 100644 --- a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp +++ b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp @@ -104,6 +104,10 @@ Java_sun_font_SunLayoutEngine_initGVIDs int putGV(JNIEnv* env, jint gmask, jint baseIndex, jobject gvdata, const LayoutEngine* engine, int glyphCount) { int count = env->GetIntField(gvdata, gvdCountFID); + if (count < 0) { + JNU_ThrowInternalError(env, "count negative"); + return 0; + } jarray glyphArray = (jarray)env->GetObjectField(gvdata, gvdGlyphsFID); if (IS_NULL(glyphArray)) { From 7abc885152c1d3036c9aaae323a2b7aff39f282b Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Mon, 29 Jul 2013 04:43:41 -0700 Subject: [PATCH 033/263] 8021577: JCK test api/javax_management/jmx_serial/modelmbean/ModelMBeanNotificationInfo/serial/index.html#Input has failed since jdk 7u45 b01 Reviewed-by: alanb, dfuchs, ahgross --- .../classes/javax/management/MBeanNotificationInfo.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java index dfa4ab1f8ff..e3b4aba1252 100644 --- a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java @@ -210,11 +210,6 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable ObjectInputStream.GetField gf = ois.readFields(); String[] t = (String[])gf.get("types", null); - if (t == null) { - throw new InvalidObjectException("Trying to deserialize an invalid " + - "instance of " + MBeanNotificationInfo.class + - "[types=null]"); - } - types = t.length == 0 ? t : t.clone(); + types = (t != null && t.length != 0) ? t.clone() : NO_TYPES; } } From adf52d0164028f9a7ceedeb0afc633f4f0bcd0fb Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 1 Aug 2013 14:09:39 -0700 Subject: [PATCH 034/263] 8021286: Improve MacOS resourcing Reviewed-by: okutsu --- jdk/make/sun/awt/FILES_c_macosx.gmk | 28 ----- jdk/make/sun/awt/FILES_export_macosx.gmk | 29 ----- jdk/make/sun/awt/Makefile | 2 - jdk/makefiles/CompileNativeLibraries.gmk | 4 - .../com/apple/laf/AquaLookAndFeel.java | 4 +- .../apple/resources/MacOSXResourceBundle.java | 110 ------------------ .../apple/resources/MacOSXResourceBundle.m | 110 ------------------ 7 files changed, 1 insertion(+), 286 deletions(-) delete mode 100644 jdk/make/sun/awt/FILES_c_macosx.gmk delete mode 100644 jdk/make/sun/awt/FILES_export_macosx.gmk delete mode 100644 jdk/src/macosx/classes/com/apple/resources/MacOSXResourceBundle.java delete mode 100644 jdk/src/macosx/native/com/apple/resources/MacOSXResourceBundle.m diff --git a/jdk/make/sun/awt/FILES_c_macosx.gmk b/jdk/make/sun/awt/FILES_c_macosx.gmk deleted file mode 100644 index d6bef30bb2a..00000000000 --- a/jdk/make/sun/awt/FILES_c_macosx.gmk +++ /dev/null @@ -1,28 +0,0 @@ -# -# Copyright (c) 1995, 2012, 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. -# - -FILES_AWT_objc = \ - $(TARGDIR)MacOSXResourceBundle.m - diff --git a/jdk/make/sun/awt/FILES_export_macosx.gmk b/jdk/make/sun/awt/FILES_export_macosx.gmk deleted file mode 100644 index c7f0e003cb9..00000000000 --- a/jdk/make/sun/awt/FILES_export_macosx.gmk +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 1995, 2012, 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. -# - -# FILES_export definitions for Mac OS X - -FILES_export += \ - com/apple/resources/MacOSXResourceBundle.java diff --git a/jdk/make/sun/awt/Makefile b/jdk/make/sun/awt/Makefile index dc4c250cf74..c45ecb9fe45 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -145,8 +145,6 @@ ifeq ($(PLATFORM), macosx) # # Files # -include FILES_c_macosx.gmk -include FILES_export_macosx.gmk FILES_objc = $(FILES_AWT_objc) OTHER_LDLIBS = -lmlib_image $(JVMLIB) $(LIBM) \ diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index 02bf3be808c..fa416032473 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -558,11 +558,7 @@ endif ifeq ($(OPENJDK_TARGET_OS),macosx) LIBAWT_FILES += awt_LoadLibrary.c img_colors.c - LIBAWT_DIRS += $(JDK_TOPDIR)/src/macosx/native/com/apple/resources - LIBAWT_FILES += awt_LoadLibrary.c MacOSXResourceBundle.m LIBAWT_CFLAGS += -F/System/Library/Frameworks/JavaVM.framework/Frameworks - - LIBAWT_MacOSXResourceBundle.m_CFLAGS:=-O0 endif ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc) diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java index 457b82d36a3..046d693e329 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaLookAndFeel.java @@ -37,8 +37,6 @@ import javax.swing.plaf.basic.BasicLookAndFeel; import sun.swing.*; import apple.laf.*; -import com.apple.resources.MacOSXResourceBundle; - public class AquaLookAndFeel extends BasicLookAndFeel { static final String sOldPropertyPrefix = "com.apple.macos."; // old prefix for things like 'useScreenMenuBar' static final String sPropertyPrefix = "apple.laf."; // new prefix for things like 'useScreenMenuBar' @@ -252,7 +250,7 @@ public class AquaLookAndFeel extends BasicLookAndFeel { table.setDefaultLocale(Locale.getDefault()); table.addResourceBundle(PKG_PREFIX + "resources.aqua"); try { - final ResourceBundle aquaProperties = MacOSXResourceBundle.getMacResourceBundle(PKG_PREFIX + "resources.aqua"); + final ResourceBundle aquaProperties = ResourceBundle.getBundle(PKG_PREFIX + "resources.aqua"); final Enumeration propertyKeys = aquaProperties.getKeys(); while (propertyKeys.hasMoreElements()) { diff --git a/jdk/src/macosx/classes/com/apple/resources/MacOSXResourceBundle.java b/jdk/src/macosx/classes/com/apple/resources/MacOSXResourceBundle.java deleted file mode 100644 index 143584b0b87..00000000000 --- a/jdk/src/macosx/classes/com/apple/resources/MacOSXResourceBundle.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2011, 2012, 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 com.apple.resources; - -import java.security.*; -import java.util.PropertyResourceBundle; -import java.util.ResourceBundle; -import java.io.*; - -public class MacOSXResourceBundle extends PropertyResourceBundle { - MacOSXResourceBundle(InputStream stream) throws IOException { - super(stream); - } - - void setItsParent(ResourceBundle rb) { - setParent(rb); - } - - public static ResourceBundle getMacResourceBundle(String baseJavaBundle) throws Exception { - return getMacResourceBundle(baseJavaBundle, null); - } - - public static ResourceBundle getMacResourceBundle(String baseJavaBundle, String filename) throws Exception { - LoadNativeBundleAction lnba = new LoadNativeBundleAction(baseJavaBundle, filename); - return (ResourceBundle)java.security.AccessController.doPrivileged(lnba); - } -} - -class LoadNativeBundleAction implements PrivilegedExceptionAction { - String mBaseJavaBundle; - String mFilenameOverride; - - LoadNativeBundleAction(String baseJavaBundle, String filenameOverride) { - mBaseJavaBundle = baseJavaBundle; - mFilenameOverride = filenameOverride; - } - - public Object run() { - java.util.ResourceBundle returnValue = null; - MacOSXResourceBundle macOSrb = null; - - // Load the Mac OS X resources. - // Use a base filename if we were given one. Otherwise, we will look for the last piece of the bundle path - // with '.properties' appended. Either way, the native method will take care of the extension. - String filename = mFilenameOverride; - - if (filename == null) { - filename = mBaseJavaBundle.substring(mBaseJavaBundle.lastIndexOf('.') + 1); - } - - File propsFile = null; - String propertyFileName = getPathToBundleFile(filename); - InputStream stream = null; - - try { - propsFile = new File(propertyFileName); - stream = new FileInputStream(propsFile); - stream = new java.io.BufferedInputStream(stream); - macOSrb = new MacOSXResourceBundle(stream); - } catch (Exception e) { - //e.printStackTrace(); - //System.out.println("Failed to create resources from application bundle. Using Java-based resources."); - } finally { - try { - if (stream != null) stream.close(); - stream = null; - } catch (Exception e) { - e.printStackTrace(); - } - } - - returnValue = ResourceBundle.getBundle(mBaseJavaBundle); - - // If we have a platform-specific bundle, make it the parent of the generic bundle, so failures propagate up to the parent. - if (returnValue != null) { - if (macOSrb != null) { - macOSrb.setItsParent(returnValue); - returnValue = macOSrb; - } - } - - return returnValue; - } - - private static native String getPathToBundleFile(String filename); -} - diff --git a/jdk/src/macosx/native/com/apple/resources/MacOSXResourceBundle.m b/jdk/src/macosx/native/com/apple/resources/MacOSXResourceBundle.m deleted file mode 100644 index 0b98d2b0588..00000000000 --- a/jdk/src/macosx/native/com/apple/resources/MacOSXResourceBundle.m +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2011, 2012, 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. - */ - -#import -#import -#import - -#ifndef MAXPATHLEN -#define MAXPATHLEN PATH_MAX -#endif - -static jboolean -GetPathFromCurrentBinary(char *buf, jint bufsize) -{ - Dl_info dlinfo; - dladdr((void *)GetPathFromCurrentBinary, &dlinfo); - if (realpath(dlinfo.dli_fname, buf) == NULL) { -// fprintf(stderr, "Error: realpath(`%s') failed.\n", dlinfo.dli_fname); - return JNI_FALSE; - } - - const char *libawt = "lib/libawt.dylib"; - int strLen, libawtLen; - - strLen = strlen(buf); - libawtLen = strlen(libawt); - - if (strLen < libawtLen || - strcmp(buf + strLen - libawtLen, libawt) != 0) { - return JNI_FALSE; - } - - buf[strLen - libawtLen] = '\0'; - - return JNI_TRUE; -} - -#define JAVA_DLL "libjava.dylib" - -static jboolean -GetJREPath(char *buf, jint bufsize) -{ - /* try to get the path from the current binary, if not, bail to the framework */ - if (GetPathFromCurrentBinary(buf, bufsize) == JNI_TRUE) { - /* does the rest of the JRE exist? */ - char libjava[MAXPATHLEN]; - snprintf(libjava, MAXPATHLEN, "%s/lib/" JAVA_DLL, buf); - if (access(libjava, F_OK) == 0) { - return JNI_TRUE; - } - } - - return JNI_FALSE; -} - -static NSString *getRunningJavaBundle() -{ - char path[MAXPATHLEN]; - GetJREPath(path, MAXPATHLEN); - return [[NSString alloc] initWithFormat:@"%@/bundle", [NSString stringWithUTF8String:path]]; -} - -/* - * Class: com_apple_resources_LoadNativeBundleAction - * Method: getPathToBundleFile - * Signature: (Ljava/lang/String)Ljava/lang/String; - */ -JNIEXPORT jstring JNICALL -Java_com_apple_resources_LoadNativeBundleAction_getPathToBundleFile - (JNIEnv *env, jclass klass, jstring filename) -{ - jstring returnVal = NULL; - if (filename == NULL) { - return NULL; - } - -JNF_COCOA_ENTER(env); - NSBundle *javaBundle = [NSBundle bundleWithPath:getRunningJavaBundle()]; - NSString *baseFilename = JNFJavaToNSString(env, filename); - NSString *propertyFilePath = [javaBundle pathForResource:baseFilename ofType:@"properties"]; - - if (propertyFilePath != nil) { - returnVal = JNFNSToJavaString(env, propertyFilePath); - } -JNF_COCOA_EXIT(env); - - return returnVal; -} From 10738dc29803a286a22c0973f85ffaac94ef6b5a Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sun, 4 Aug 2013 02:50:02 +0400 Subject: [PATCH 035/263] 8021282: Better recycling of object instances Reviewed-by: art --- .../classes/com/apple/laf/AquaUtils.java | 193 ++++++++++-------- 1 file changed, 104 insertions(+), 89 deletions(-) diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java b/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java index 0592da714a2..a5f5501cb35 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, 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 @@ -29,6 +29,7 @@ import java.awt.*; import java.awt.image.*; import java.lang.ref.SoftReference; import java.lang.reflect.Method; +import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; @@ -41,56 +42,68 @@ import sun.awt.AppContext; import sun.lwawt.macosx.CImage; import sun.lwawt.macosx.CImage.Creator; import sun.lwawt.macosx.CPlatformWindow; +import sun.misc.Launcher; +import sun.reflect.misc.ReflectUtil; +import sun.security.action.GetPropertyAction; import sun.swing.SwingUtilities2; import com.apple.laf.AquaImageFactory.SlicedImageControl; -public class AquaUtils { - final static String ANIMATIONS_SYSTEM_PROPERTY = "swing.enableAnimations"; +final class AquaUtils { - /* + private static final String ANIMATIONS_PROPERTY = "swing.enableAnimations"; + + /** + * Suppresses default constructor, ensuring non-instantiability. + */ + private AquaUtils() { + } + + /** * Convenience function for determining ComponentOrientation. Helps us * avoid having Munge directives throughout the code. */ - public static boolean isLeftToRight(final Component c) { + static boolean isLeftToRight(final Component c) { return c.getComponentOrientation().isLeftToRight(); } - public static void enforceComponentOrientation(Component c, ComponentOrientation orientation) { + static void enforceComponentOrientation(final Component c, final ComponentOrientation orientation) { c.setComponentOrientation(orientation); if (c instanceof Container) { - for (Component child : ((Container)c).getComponents()) { + for (final Component child : ((Container)c).getComponents()) { enforceComponentOrientation(child, orientation); } } } - private static CImage.Creator getCImageCreatorInternal() { - return java.security.AccessController.doPrivileged(new PrivilegedAction() { + private static Creator getCImageCreatorInternal() { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override public Creator run() { try { final Method getCreatorMethod = CImage.class.getDeclaredMethod("getCreator", new Class[] {}); getCreatorMethod.setAccessible(true); - return (CImage.Creator)getCreatorMethod.invoke(null, new Object[] {}); - } catch (final Exception e) { + return (Creator)getCreatorMethod.invoke(null, new Object[] {}); + } catch (final Exception ignored) { return null; } } }); } - private static final RecyclableSingleton cImageCreator = new RecyclableSingleton() { + private static final RecyclableSingleton cImageCreator = new RecyclableSingleton() { @Override protected Creator getInstance() { return getCImageCreatorInternal(); } }; - static CImage.Creator getCImageCreator() { + static Creator getCImageCreator() { return cImageCreator.get(); } - protected static Image generateSelectedDarkImage(final Image image) { + static Image generateSelectedDarkImage(final Image image) { final ImageProducer prod = new FilteredImageSource(image.getSource(), new IconImageFilter() { + @Override int getGreyFor(final int gray) { return gray * 75 / 100; } @@ -98,8 +111,9 @@ public class AquaUtils { return Toolkit.getDefaultToolkit().createImage(prod); } - protected static Image generateDisabledImage(final Image image) { + static Image generateDisabledImage(final Image image) { final ImageProducer prod = new FilteredImageSource(image.getSource(), new IconImageFilter() { + @Override int getGreyFor(final int gray) { return 255 - ((255 - gray) * 65 / 100); } @@ -107,19 +121,20 @@ public class AquaUtils { return Toolkit.getDefaultToolkit().createImage(prod); } - protected static Image generateLightenedImage(final Image image, final int percent) { + static Image generateLightenedImage(final Image image, final int percent) { final GrayFilter filter = new GrayFilter(true, percent); final ImageProducer prod = new FilteredImageSource(image.getSource(), filter); return Toolkit.getDefaultToolkit().createImage(prod); } - static abstract class IconImageFilter extends RGBImageFilter { - public IconImageFilter() { + private abstract static class IconImageFilter extends RGBImageFilter { + IconImageFilter() { super(); canFilterIndexColorModel = true; } - public int filterRGB(final int x, final int y, final int rgb) { + @Override + public final int filterRGB(final int x, final int y, final int rgb) { final int red = (rgb >> 16) & 0xff; final int green = (rgb >> 8) & 0xff; final int blue = rgb & 0xff; @@ -135,14 +150,14 @@ public class AquaUtils { return result; } - abstract int getGreyFor(final int gray); + abstract int getGreyFor(int gray); } - public abstract static class RecyclableObject { - protected SoftReference objectRef = null; + abstract static class RecyclableObject { + private SoftReference objectRef; - public T get() { - T referent = null; + T get() { + T referent; if (objectRef != null && (referent = objectRef.get()) != null) return referent; referent = create(); objectRef = new SoftReference(referent); @@ -152,8 +167,8 @@ public class AquaUtils { protected abstract T create(); } - public abstract static class RecyclableSingleton { - public T get() { + abstract static class RecyclableSingleton { + final T get() { final AppContext appContext = AppContext.getAppContext(); SoftReference ref = (SoftReference) appContext.get(this); if (ref != null) { @@ -166,38 +181,36 @@ public class AquaUtils { return object; } - public void reset() { - AppContext appContext = AppContext.getAppContext(); - appContext.remove(this); + void reset() { + AppContext.getAppContext().remove(this); } - protected abstract T getInstance(); + abstract T getInstance(); } - public static class RecyclableSingletonFromDefaultConstructor extends RecyclableSingleton { - protected final Class clazz; + static class RecyclableSingletonFromDefaultConstructor extends RecyclableSingleton { + private final Class clazz; - public RecyclableSingletonFromDefaultConstructor(final Class clazz) { + RecyclableSingletonFromDefaultConstructor(final Class clazz) { this.clazz = clazz; } - protected T getInstance() { + @Override + T getInstance() { try { + ReflectUtil.checkPackageAccess(clazz); return clazz.newInstance(); - } catch (final InstantiationException e) { - e.printStackTrace(); - } catch (final IllegalAccessException e) { - e.printStackTrace(); + } catch (InstantiationException | IllegalAccessException ignored) { } return null; } } - public abstract static class LazyKeyedSingleton { - protected Map refs; + abstract static class LazyKeyedSingleton { + private Map refs; - public V get(final K key) { - if (refs == null) refs = new HashMap(); + V get(final K key) { + if (refs == null) refs = new HashMap<>(); final V cachedValue = refs.get(key); if (cachedValue != null) return cachedValue; @@ -207,44 +220,45 @@ public class AquaUtils { return value; } - protected abstract V getInstance(final K key); + protected abstract V getInstance(K key); } - static final RecyclableSingleton enableAnimations = new RecyclableSingleton() { + private static final RecyclableSingleton enableAnimations = new RecyclableSingleton() { @Override protected Boolean getInstance() { - final String sizeProperty = (String)java.security.AccessController.doPrivileged((PrivilegedAction)new sun.security.action.GetPropertyAction(ANIMATIONS_SYSTEM_PROPERTY)); - return new Boolean(!"false".equals(sizeProperty)); // should be true by default + final String sizeProperty = (String) AccessController.doPrivileged((PrivilegedAction)new GetPropertyAction( + ANIMATIONS_PROPERTY)); + return !"false".equals(sizeProperty); // should be true by default } }; - static boolean animationsEnabled() { + private static boolean animationsEnabled() { return enableAnimations.get(); } - static final int MENU_BLINK_DELAY = 50; // 50ms == 3/60 sec, according to the spec - protected static void blinkMenu(final Selectable selectable) { + private static final int MENU_BLINK_DELAY = 50; // 50ms == 3/60 sec, according to the spec + static void blinkMenu(final Selectable selectable) { if (!animationsEnabled()) return; try { selectable.paintSelected(false); Thread.sleep(MENU_BLINK_DELAY); selectable.paintSelected(true); Thread.sleep(MENU_BLINK_DELAY); - } catch (final InterruptedException e) { } + } catch (final InterruptedException ignored) { } } interface Selectable { - void paintSelected(final boolean selected); + void paintSelected(boolean selected); } interface JComponentPainter { - public void paint(JComponent c, Graphics g, int x, int y, int w, int h); + void paint(JComponent c, Graphics g, int x, int y, int w, int h); } interface Painter { - public void paint(final Graphics g, int x, int y, int w, int h); + void paint(Graphics g, int x, int y, int w, int h); } - public static void paintDropShadowText(final Graphics g, final JComponent c, final Font font, final FontMetrics metrics, final int x, final int y, final int offsetX, final int offsetY, final Color textColor, final Color shadowColor, final String text) { + static void paintDropShadowText(final Graphics g, final JComponent c, final Font font, final FontMetrics metrics, final int x, final int y, final int offsetX, final int offsetY, final Color textColor, final Color shadowColor, final String text) { g.setFont(font); g.setColor(shadowColor); SwingUtilities2.drawString(c, g, text, x + offsetX, y + offsetY + metrics.getAscent()); @@ -252,22 +266,22 @@ public class AquaUtils { SwingUtilities2.drawString(c, g, text, x, y + metrics.getAscent()); } - public static class ShadowBorder implements Border { - final Painter prePainter; - final Painter postPainter; + static class ShadowBorder implements Border { + private final Painter prePainter; + private final Painter postPainter; - final int offsetX; - final int offsetY; - final float distance; - final int blur; - final Insets insets; - final ConvolveOp blurOp; + private final int offsetX; + private final int offsetY; + private final float distance; + private final int blur; + private final Insets insets; + private final ConvolveOp blurOp; - public ShadowBorder(final Painter prePainter, final Painter postPainter, final int offsetX, final int offsetY, final float distance, final float intensity, final int blur) { + ShadowBorder(final Painter prePainter, final Painter postPainter, final int offsetX, final int offsetY, final float distance, final float intensity, final int blur) { this.prePainter = prePainter; this.postPainter = postPainter; this.offsetX = offsetX; this.offsetY = offsetY; this.distance = distance; this.blur = blur; final int halfBlur = blur / 2; - this.insets = new Insets(halfBlur - offsetY, halfBlur - offsetX, halfBlur + offsetY, halfBlur + offsetX); + insets = new Insets(halfBlur - offsetY, halfBlur - offsetX, halfBlur + offsetY, halfBlur + offsetX); final float blurry = intensity / (blur * blur); final float[] blurKernel = new float[blur * blur]; @@ -275,14 +289,17 @@ public class AquaUtils { blurOp = new ConvolveOp(new Kernel(blur, blur, blurKernel)); } - public boolean isBorderOpaque() { + @Override + public final boolean isBorderOpaque() { return false; } - public Insets getBorderInsets(final Component c) { + @Override + public final Insets getBorderInsets(final Component c) { return insets; } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { final BufferedImage img = new BufferedImage(width + blur * 2, height + blur * 2, BufferedImage.TYPE_INT_ARGB_PRE); paintToImage(img, x, y, width, height); @@ -290,7 +307,7 @@ public class AquaUtils { g.drawImage(img, -blur, -blur, null); } - protected void paintToImage(final BufferedImage img, final int x, final int y, final int width, final int height) { + private void paintToImage(final BufferedImage img, final int x, final int y, final int width, final int height) { // clear the prior image Graphics2D imgG = (Graphics2D)img.getGraphics(); imgG.setComposite(AlphaComposite.Clear); @@ -319,10 +336,10 @@ public class AquaUtils { } } - public static class SlicedShadowBorder extends ShadowBorder { - final SlicedImageControl slices; + static class SlicedShadowBorder extends ShadowBorder { + private final SlicedImageControl slices; - public SlicedShadowBorder(final Painter prePainter, final Painter postPainter, final int offsetX, final int offsetY, final float distance, final float intensity, final int blur, final int templateWidth, final int templateHeight, final int leftCut, final int topCut, final int rightCut, final int bottomCut) { + SlicedShadowBorder(final Painter prePainter, final Painter postPainter, final int offsetX, final int offsetY, final float distance, final float intensity, final int blur, final int templateWidth, final int templateHeight, final int leftCut, final int topCut, final int rightCut, final int bottomCut) { super(prePainter, postPainter, offsetX, offsetY, distance, intensity, blur); final BufferedImage i = new BufferedImage(templateWidth, templateHeight, BufferedImage.TYPE_INT_ARGB_PRE); @@ -331,15 +348,12 @@ public class AquaUtils { slices = new SlicedImageControl(i, leftCut, topCut, rightCut, bottomCut, false); } + @Override public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width, final int height) { slices.paint(g, x, y, width, height); } } - public interface NineSliceMetricsProvider { - - } - // static void debugFrame(String name, Image image) { // JFrame f = new JFrame(name); // f.setContentPane(new JLabel(new ImageIcon(image))); @@ -350,28 +364,30 @@ public class AquaUtils { // special casing naughty applications, like InstallAnywhere // REGR: JButton: Myst IV: the buttons of 1.0.3 updater have redraw issue static boolean shouldUseOpaqueButtons() { - final ClassLoader launcherClassLoader = sun.misc.Launcher.getLauncher().getClassLoader(); + final ClassLoader launcherClassLoader = Launcher.getLauncher().getClassLoader(); if (classExists(launcherClassLoader, "com.installshield.wizard.platform.macosx.MacOSXUtils")) return true; return false; } - static boolean classExists(final ClassLoader classLoader, final String clazzName) { + private static boolean classExists(final ClassLoader classLoader, final String clazzName) { try { return Class.forName(clazzName, false, classLoader) != null; - } catch (final Throwable e) { } + } catch (final Throwable ignored) { } return false; } - private static RecyclableSingleton getJComponentGetFlagMethod = new RecyclableSingleton() { + private static final RecyclableSingleton getJComponentGetFlagMethod = new RecyclableSingleton() { + @Override protected Method getInstance() { - return java.security.AccessController.doPrivileged( + return AccessController.doPrivileged( new PrivilegedAction() { + @Override public Method run() { try { final Method method = JComponent.class.getDeclaredMethod("getFlag", new Class[] { int.class }); method.setAccessible(true); return method; - } catch (final Throwable e) { + } catch (final Throwable ignored) { return null; } } @@ -380,18 +396,18 @@ public class AquaUtils { } }; - private static final Integer OPAQUE_SET_FLAG = new Integer(24); // private int JComponent.OPAQUE_SET - protected static boolean hasOpaqueBeenExplicitlySet(final JComponent c) { + private static final Integer OPAQUE_SET_FLAG = 24; // private int JComponent.OPAQUE_SET + static boolean hasOpaqueBeenExplicitlySet(final JComponent c) { final Method method = getJComponentGetFlagMethod.get(); if (method == null) return false; try { return Boolean.TRUE.equals(method.invoke(c, OPAQUE_SET_FLAG)); - } catch (final Throwable e) { + } catch (final Throwable ignored) { return false; } } - protected static boolean isWindowTextured(final Component c) { + private static boolean isWindowTextured(final Component c) { if (!(c instanceof JComponent)) { return false; } @@ -412,13 +428,12 @@ public class AquaUtils { return new Color(color.getRed(), color.getGreen(), color.getBlue(), 0); } - protected static void fillRect(final Graphics g, final Component c) { + static void fillRect(final Graphics g, final Component c) { fillRect(g, c, c.getBackground(), 0, 0, c.getWidth(), c.getHeight()); } - protected static void fillRect(final Graphics g, final Component c, - final Color color, final int x, final int y, - final int w, final int h) { + static void fillRect(final Graphics g, final Component c, final Color color, + final int x, final int y, final int w, final int h) { if (!(g instanceof Graphics2D)) { return; } From a3b45465c6003b542aafe8969f5a5f13d3b2ca48 Mon Sep 17 00:00:00 2001 From: Shanliang Jiang Date: Tue, 6 Aug 2013 10:33:42 +0200 Subject: [PATCH 036/263] 8019292: Better Attribute Value Exceptions Reviewed-by: dfuchs, dholmes, ahgross --- .../BadAttributeValueExpException.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/jdk/src/share/classes/javax/management/BadAttributeValueExpException.java b/jdk/src/share/classes/javax/management/BadAttributeValueExpException.java index 9ed27e91fa3..2eda233d24a 100644 --- a/jdk/src/share/classes/javax/management/BadAttributeValueExpException.java +++ b/jdk/src/share/classes/javax/management/BadAttributeValueExpException.java @@ -25,6 +25,9 @@ package javax.management; +import java.io.IOException; +import java.io.ObjectInputStream; + /** * Thrown when an invalid MBean attribute is passed to a query @@ -41,17 +44,19 @@ public class BadAttributeValueExpException extends Exception { private static final long serialVersionUID = -3105272988410493376L; /** - * @serial The attribute value that originated this exception + * @serial A string representation of the attribute that originated this exception. + * for example, the string value can be the return of {@code attribute.toString()} */ private Object val; /** - * Constructs an BadAttributeValueExpException with the specified Object. + * Constructs a BadAttributeValueExpException using the specified Object to + * create the toString() value. * * @param val the inappropriate value. */ public BadAttributeValueExpException (Object val) { - this.val = val; + this.val = val == null ? null : val.toString(); } @@ -62,4 +67,25 @@ public class BadAttributeValueExpException extends Exception { return "BadAttributeValueException: " + val; } + private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gf = ois.readFields(); + Object valObj = gf.get("val", null); + + if (valObj == null) { + val = null; + } else if (valObj instanceof String) { + val= valObj; + } else if (System.getSecurityManager() == null + || valObj instanceof Long + || valObj instanceof Integer + || valObj instanceof Float + || valObj instanceof Double + || valObj instanceof Byte + || valObj instanceof Short + || valObj instanceof Boolean) { + val = valObj.toString(); + } else { // the serialized object is from a version without JDK-8019292 fix + val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName(); + } + } } From 68d1aae1be91153f3df0736e8a96ed99d36945a6 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 7 Aug 2013 14:37:22 +0400 Subject: [PATCH 037/263] 8021969: The index_AccessAllowed jnlp can not load successfully with exception thrown in the log Reviewed-by: art, skoivu --- jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java index 3c1691545f4..400553dd854 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java +++ b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java @@ -145,11 +145,7 @@ public class DataFlavor implements Externalizable, Cloneable { } catch (SecurityException exception) { // ignore secured class loaders } - if (fallback != null) { - return Class.forName(className, true, fallback); - } else { - throw new ClassNotFoundException(className); - } + return Class.forName(className, true, fallback); } /* From 046a6fa8e2263dc23bc39d97294922c71cf893b7 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Thu, 8 Aug 2013 19:16:27 +0200 Subject: [PATCH 038/263] 8021360: object not exported" on start of JMXConnectorServer for RMI-IIOP protocol with security manager Reviewed-by: alanb, ahgross, smarks, coffeys --- .../remote/protocol/iiop/IIOPProxyImpl.java | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java b/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java index d4171b24282..b0fe91bf728 100644 --- a/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java +++ b/jdk/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009,2013, 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 @@ -36,13 +36,34 @@ import java.rmi.RemoteException; import java.rmi.NoSuchObjectException; import com.sun.jmx.remote.internal.IIOPProxy; +import java.io.SerializablePermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permissions; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.security.ProtectionDomain; /** - * An implementatin of IIOPProxy that simply delegates to the appropriate + * An implementation of IIOPProxy that simply delegates to the appropriate * RMI-IIOP and CORBA APIs. */ public class IIOPProxyImpl implements IIOPProxy { + // special ACC used to initialize the IIOP stub + // the only allowed privilege is SerializablePermission("enableSubclassImplementation") + private static final AccessControlContext STUB_ACC; + + static { + Permissions p = new Permissions(); + p.add(new SerializablePermission("enableSubclassImplementation")); + STUB_ACC = new AccessControlContext( + new ProtectionDomain[]{ + new ProtectionDomain(null, p) + } + ); + } + public IIOPProxyImpl() { } @Override @@ -113,7 +134,24 @@ public class IIOPProxyImpl implements IIOPProxy { } @Override - public Remote toStub(Remote obj) throws NoSuchObjectException { - return PortableRemoteObject.toStub(obj); + public Remote toStub(final Remote obj) throws NoSuchObjectException { + if (System.getSecurityManager() == null) { + return PortableRemoteObject.toStub(obj); + } else { + try { + return AccessController.doPrivileged(new PrivilegedExceptionAction() { + + @Override + public Remote run() throws Exception { + return PortableRemoteObject.toStub(obj); + } + }, STUB_ACC); + } catch (PrivilegedActionException e) { + if (e.getException() instanceof NoSuchObjectException) { + throw (NoSuchObjectException)e.getException(); + } + throw new RuntimeException("Unexpected exception type", e.getException()); + } + } } } From ac42104fef46f3d20133383985fea56247768156 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 12 Aug 2013 19:57:21 +0400 Subject: [PATCH 039/263] 8021275: Better screening for ScreenMenu Reviewed-by: art --- .../classes/com/apple/laf/ScreenMenu.java | 144 +++++++++--------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java b/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java index 5f78ff6e061..87393408487 100644 --- a/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java +++ b/jdk/src/macosx/classes/com/apple/laf/ScreenMenu.java @@ -36,7 +36,10 @@ import sun.awt.SunToolkit; import sun.lwawt.LWToolkit; import sun.lwawt.macosx.*; -class ScreenMenu extends Menu implements ContainerListener, ComponentListener, ScreenMenuPropertyHandler { +final class ScreenMenu extends Menu + implements ContainerListener, ComponentListener, + ScreenMenuPropertyHandler { + static { java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -48,20 +51,22 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S } // screen menu stuff - public static native long addMenuListeners(ScreenMenu listener, long nativeMenu); - public static native void removeMenuListeners(long modelPtr); + private static native long addMenuListeners(ScreenMenu listener, long nativeMenu); + private static native void removeMenuListeners(long modelPtr); - long fModelPtr = 0; + private transient long fModelPtr; - Hashtable fItems; - JMenu fInvoker; + private final Hashtable fItems; + private final JMenu fInvoker; - Component fLastMouseEventTarget; - Rectangle fLastTargetRect; + private Component fLastMouseEventTarget; + private Rectangle fLastTargetRect; private volatile Rectangle[] fItemBounds; + private ScreenMenuPropertyListener fPropertyListener; + // Array of child hashes used to see if we need to recreate the Menu. - int childHashArray[]; + private int childHashArray[]; ScreenMenu(final JMenu invoker) { super(invoker.getText()); @@ -74,25 +79,12 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S updateItems(); } - // I'm always 'visible', but never on screen - static class ScreenMenuComponent extends Container { - public boolean isVisible() { return true; } - public boolean isShowing() { return true; } - public void setVisible(final boolean b) {} - public void show() {} - } - - ScreenMenuComponent makeScreenMenuComponent() { - return new ScreenMenuComponent(); - } - - /** * Determine if we need to tear down the Menu and re-create it, since the contents may have changed in the Menu opened listener and * we do not get notified of it, because EDT is busy in our code. We only need to update if the menu contents have changed in some * way, such as the number of menu items, the text of the menuitems, icon, shortcut etc. */ - static boolean needsUpdate(final Component items[], final int childHashArray[]) { + private static boolean needsUpdate(final Component items[], final int childHashArray[]) { if (items == null || childHashArray == null) { return true; } @@ -112,7 +104,7 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S * Used to recreate the AWT based Menu structure that implements the Screen Menu. * Also computes hashcode and stores them so that we can compare them later in needsUpdate. */ - void updateItems() { + private void updateItems() { final int count = fInvoker.getMenuComponentCount(); final Component[] items = fInvoker.getMenuComponents(); if (needsUpdate(items, childHashArray)) { @@ -163,16 +155,14 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S LWCToolkit.invokeAndWait(new Runnable() { public void run() { invoker.setSelected(false); - - // Null out the tracking rectangles and the array. + // Null out the tracking rectangles and the array. if (fItemBounds != null) { - for (int i = 0; i < fItemBounds.length; i++) { - fItemBounds[i] = null; - } + for (int i = 0; i < fItemBounds.length; i++) { + fItemBounds[i] = null; + } } - - fItemBounds = null; - } + fItemBounds = null; + } }, invoker); } catch (final Exception e) { e.printStackTrace(); @@ -237,49 +227,56 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S }); } - ScreenMenuPropertyListener fPropertyListener; + @Override public void addNotify() { - super.addNotify(); - if (fModelPtr == 0) { - fInvoker.addContainerListener(this); - fInvoker.addComponentListener(this); - fPropertyListener = new ScreenMenuPropertyListener(this); - fInvoker.addPropertyChangeListener(fPropertyListener); + synchronized (getTreeLock()) { + super.addNotify(); + if (fModelPtr == 0) { + fInvoker.addContainerListener(this); + fInvoker.addComponentListener(this); + fPropertyListener = new ScreenMenuPropertyListener(this); + fInvoker.addPropertyChangeListener(fPropertyListener); - final Icon icon = fInvoker.getIcon(); - if (icon != null) { - this.setIcon(icon); - } + final Icon icon = fInvoker.getIcon(); + if (icon != null) { + setIcon(icon); + } - final String tooltipText = fInvoker.getToolTipText(); - if (tooltipText != null) { - this.setToolTipText(tooltipText); - } - final MenuComponentPeer peer = getPeer(); - if (peer instanceof CMenu) { - final CMenu menu = (CMenu)peer; - final long nativeMenu = menu.getNativeMenu(); - fModelPtr = addMenuListeners(this, nativeMenu); + final String tooltipText = fInvoker.getToolTipText(); + if (tooltipText != null) { + setToolTipText(tooltipText); + } + final MenuComponentPeer peer = getPeer(); + if (peer instanceof CMenu) { + final CMenu menu = (CMenu) peer; + final long nativeMenu = menu.getNativeMenu(); + fModelPtr = addMenuListeners(this, nativeMenu); + } } } } + @Override public void removeNotify() { - // Call super so that the NSMenu has been removed, before we release the delegate in removeMenuListeners - super.removeNotify(); - fItems.clear(); - if (fModelPtr != 0) { - removeMenuListeners(fModelPtr); - fModelPtr = 0; - fInvoker.removeContainerListener(this); - fInvoker.removeComponentListener(this); - fInvoker.removePropertyChangeListener(fPropertyListener); + synchronized (getTreeLock()) { + // Call super so that the NSMenu has been removed, before we release + // the delegate in removeMenuListeners + super.removeNotify(); + fItems.clear(); + if (fModelPtr != 0) { + removeMenuListeners(fModelPtr); + fModelPtr = 0; + fInvoker.removeContainerListener(this); + fInvoker.removeComponentListener(this); + fInvoker.removePropertyChangeListener(fPropertyListener); + } } } /** * Invoked when a component has been added to the container. */ + @Override public void componentAdded(final ContainerEvent e) { addItem(e.getChild()); } @@ -287,23 +284,26 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S /** * Invoked when a component has been removed from the container. */ + @Override public void componentRemoved(final ContainerEvent e) { final Component child = e.getChild(); final MenuItem sm = fItems.get(child); if (sm == null) return; - remove(sm); - fItems.remove(sm); - } + remove(sm); + fItems.remove(sm); + } /** * Invoked when the component's size changes. */ + @Override public void componentResized(final ComponentEvent e) {} /** * Invoked when the component's position changes. */ + @Override public void componentMoved(final ComponentEvent e) {} /** @@ -311,6 +311,7 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S * See componentHidden - we should still have a MenuItem * it just isn't inserted */ + @Override public void componentShown(final ComponentEvent e) { setVisible(true); } @@ -321,11 +322,12 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S * so we remove the ScreenMenuItem from the ScreenMenu * but leave it in fItems */ + @Override public void componentHidden(final ComponentEvent e) { setVisible(false); } - public void setVisible(final boolean b) { + private void setVisible(final boolean b) { // Tell our parent to add/remove us final MenuContainer parent = getParent(); @@ -333,20 +335,24 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S if (parent instanceof ScreenMenu) { final ScreenMenu sm = (ScreenMenu)parent; sm.setChildVisible(fInvoker, b); - } + } } } + @Override public void setChildVisible(final JMenuItem child, final boolean b) { fItems.remove(child); updateItems(); } + @Override public void setAccelerator(final KeyStroke ks) {} // only check and radio items can be indeterminate + @Override public void setIndeterminate(boolean indeterminate) { } + @Override public void setToolTipText(final String text) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -355,6 +361,7 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S cmi.setToolTipText(text); } + @Override public void setIcon(final Icon i) { final MenuComponentPeer peer = getPeer(); if (!(peer instanceof CMenuItem)) return; @@ -374,9 +381,8 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S /** * Gets a hashCode for a JMenu or JMenuItem or subclass so that we can compare for * changes in the Menu. - * */ - static int getHashCode(final Component m) { + private static int getHashCode(final Component m) { int hashCode = m.hashCode(); if (m instanceof JMenuItem) { @@ -408,7 +414,7 @@ class ScreenMenu extends Menu implements ContainerListener, ComponentListener, S return hashCode; } - void addItem(final Component m) { + private void addItem(final Component m) { if (!m.isVisible()) return; MenuItem sm = fItems.get(m); From 53b5f75095fbfdc11d0816de508bdde491844095 Mon Sep 17 00:00:00 2001 From: Christian Thalinger Date: Mon, 12 Aug 2013 13:47:21 -0700 Subject: [PATCH 040/263] 8022066: Evaluation of method reference to signature polymorphic method crashes VM Reviewed-by: jrose --- .../java/lang/invoke/MethodHandles.java | 4 + .../lang/invoke/MethodHandleConstants.java | 188 ++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 jdk/test/java/lang/invoke/MethodHandleConstants.java diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java index 8a435d06fca..2ee21d667c0 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java @@ -1289,6 +1289,10 @@ return mh1; : resolveOrFail(refKind, defc, name, (Class) type); return getDirectField(refKind, defc, field); } else if (MethodHandleNatives.refKindIsMethod(refKind)) { + if (defc == MethodHandle.class && refKind == REF_invokeVirtual) { + MethodHandle mh = findVirtualForMH(name, (MethodType) type); + if (mh != null) return mh; + } MemberName method = (resolved != null) ? resolved : resolveOrFail(refKind, defc, name, (MethodType) type); return getDirectMethod(refKind, defc, method, lookupClass); diff --git a/jdk/test/java/lang/invoke/MethodHandleConstants.java b/jdk/test/java/lang/invoke/MethodHandleConstants.java new file mode 100644 index 00000000000..57e041ba7bb --- /dev/null +++ b/jdk/test/java/lang/invoke/MethodHandleConstants.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2010, 2013, 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 8022066 + * @summary smoke test for method handle constants + * @build indify.Indify + * @compile MethodHandleConstants.java + * @run main/othervm + * indify.Indify + * --verify-specifier-count=0 + * --expand-properties --classpath ${test.classes} + * --java test.java.lang.invoke.MethodHandleConstants --check-output + * @run main/othervm + * indify.Indify + * --expand-properties --classpath ${test.classes} + * --java test.java.lang.invoke.MethodHandleConstants --security-manager + */ + +package test.java.lang.invoke; + +import java.util.*; +import java.io.*; +import java.lang.invoke.*; +import java.security.*; + +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; + +public class MethodHandleConstants { + public static void main(String... av) throws Throwable { + if (av.length > 0 && av[0].equals("--check-output")) openBuf(); + if (av.length > 0 && av[0].equals("--security-manager")) setSM(); + System.out.println("Obtaining method handle constants:"); + testCase(MH_String_replace_C2(), String.class, "replace", String.class, String.class, char.class, char.class); + testCase(MH_MethodHandle_invokeExact_SC2(), MethodHandle.class, "invokeExact", String.class, MethodHandle.class, String.class, char.class, char.class); + testCase(MH_MethodHandle_invoke_SC2(), MethodHandle.class, "invoke", String.class, MethodHandle.class, String.class, char.class, char.class); + testCase(MH_Class_forName_S(), Class.class, "forName", Class.class, String.class); + testCase(MH_Class_forName_SbCL(), Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class); + System.out.println("Done."); + closeBuf(); + } + + private static void testCase(MethodHandle mh, Class defc, String name, Class rtype, Class... ptypes) throws Throwable { + System.out.println(mh); + // we include defc, because we assume it is a non-static MH: + MethodType mt = methodType(rtype, ptypes); + assertEquals(mh.type(), mt); + // FIXME: Use revealDirect to find out more + } + private static void assertEquals(Object exp, Object act) { + if (exp == act || (exp != null && exp.equals(act))) return; + throw new AssertionError("not equal: "+exp+", "+act); + } + + private static void setSM() { + Policy.setPolicy(new TestPolicy()); + System.setSecurityManager(new SecurityManager()); + } + + private static PrintStream oldOut; + private static ByteArrayOutputStream buf; + private static void openBuf() { + oldOut = System.out; + buf = new ByteArrayOutputStream(); + System.setOut(new PrintStream(buf)); + } + private static void closeBuf() { + if (buf == null) return; + System.out.flush(); + System.setOut(oldOut); + String[] haveLines = new String(buf.toByteArray()).split("[\n\r]+"); + for (String line : haveLines) System.out.println(line); + Iterator iter = Arrays.asList(haveLines).iterator(); + for (String want : EXPECT_OUTPUT) { + String have = iter.hasNext() ? iter.next() : "[EOF]"; + if (want.equals(have)) continue; + System.err.println("want line: "+want); + System.err.println("have line: "+have); + throw new AssertionError("unexpected output: "+have); + } + if (iter.hasNext()) + throw new AssertionError("unexpected output: "+iter.next()); + } + private static final String[] EXPECT_OUTPUT = { + "Obtaining method handle constants:", + "MethodHandle(String,char,char)String", + "MethodHandle(MethodHandle,String,char,char)String", + "MethodHandle(MethodHandle,String,char,char)String", + "MethodHandle(String)Class", + "MethodHandle(String,boolean,ClassLoader)Class", + "Done." + }; + + // String.replace(String, char, char) + private static MethodType MT_String_replace_C2() { + shouldNotCallThis(); + return methodType(String.class, char.class, char.class); + } + private static MethodHandle MH_String_replace_C2() throws ReflectiveOperationException { + shouldNotCallThis(); + return lookup().findVirtual(String.class, "replace", MT_String_replace_C2()); + } + + // MethodHandle.invokeExact(...) + private static MethodType MT_MethodHandle_invokeExact_SC2() { + shouldNotCallThis(); + return methodType(String.class, String.class, char.class, char.class); + } + private static MethodHandle MH_MethodHandle_invokeExact_SC2() throws ReflectiveOperationException { + shouldNotCallThis(); + return lookup().findVirtual(MethodHandle.class, "invokeExact", MT_MethodHandle_invokeExact_SC2()); + } + + // MethodHandle.invoke(...) + private static MethodType MT_MethodHandle_invoke_SC2() { + shouldNotCallThis(); + return methodType(String.class, String.class, char.class, char.class); + } + private static MethodHandle MH_MethodHandle_invoke_SC2() throws ReflectiveOperationException { + shouldNotCallThis(); + return lookup().findVirtual(MethodHandle.class, "invoke", MT_MethodHandle_invoke_SC2()); + } + + // Class.forName(String) + private static MethodType MT_Class_forName_S() { + shouldNotCallThis(); + return methodType(Class.class, String.class); + } + private static MethodHandle MH_Class_forName_S() throws ReflectiveOperationException { + shouldNotCallThis(); + return lookup().findStatic(Class.class, "forName", MT_Class_forName_S()); + } + + // Class.forName(String, boolean, ClassLoader) + private static MethodType MT_Class_forName_SbCL() { + shouldNotCallThis(); + return methodType(Class.class, String.class, boolean.class, ClassLoader.class); + } + private static MethodHandle MH_Class_forName_SbCL() throws ReflectiveOperationException { + shouldNotCallThis(); + return lookup().findStatic(Class.class, "forName", MT_Class_forName_SbCL()); + } + + private static void shouldNotCallThis() { + // if this gets called, the transformation has not taken place + if (System.getProperty("MethodHandleConstants.allow-untransformed") != null) return; + throw new AssertionError("this code should be statically transformed away by Indify"); + } + + static class TestPolicy extends Policy { + final PermissionCollection permissions = new Permissions(); + TestPolicy() { + permissions.add(new java.io.FilePermission("<>", "read")); + } + public PermissionCollection getPermissions(ProtectionDomain domain) { + return permissions; + } + + public PermissionCollection getPermissions(CodeSource codesource) { + return permissions; + } + + public boolean implies(ProtectionDomain domain, Permission perm) { + return permissions.implies(perm); + } + } +} From 73aa07b6c5c56bc747c0ff14ac13ff3fdea70b39 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Wed, 14 Aug 2013 10:17:57 -0700 Subject: [PATCH 041/263] 8021355: REGRESSION: Five closed/java/awt/SplashScreen tests fail since 7u45 b01 on Linux, Solaris Reviewed-by: dholmes, anthony, ahgross, erikj --- jdk/src/solaris/bin/java_md_solinux.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/jdk/src/solaris/bin/java_md_solinux.c b/jdk/src/solaris/bin/java_md_solinux.c index b0028bde78d..05a5b3e34d8 100644 --- a/jdk/src/solaris/bin/java_md_solinux.c +++ b/jdk/src/solaris/bin/java_md_solinux.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, 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 @@ -958,9 +958,27 @@ static void* hSplashLib = NULL; void* SplashProcAddress(const char* name) { if (!hSplashLib) { - const char * splashLibPath; - splashLibPath = SPLASHSCREEN_SO; - hSplashLib = dlopen(splashLibPath, RTLD_LAZY | RTLD_GLOBAL); + int ret; + char jrePath[MAXPATHLEN]; + char splashPath[MAXPATHLEN]; + + if (!GetJREPath(jrePath, sizeof(jrePath), GetArch(), JNI_FALSE)) { + JLI_ReportErrorMessage(JRE_ERROR1); + return NULL; + } + ret = JLI_Snprintf(splashPath, sizeof(splashPath), "%s/lib/%s/%s", + jrePath, GetArch(), SPLASHSCREEN_SO); + + if (ret >= (int) sizeof(splashPath)) { + JLI_ReportErrorMessage(JRE_ERROR11); + return NULL; + } + if (ret < 0) { + JLI_ReportErrorMessage(JRE_ERROR13); + return NULL; + } + hSplashLib = dlopen(splashPath, RTLD_LAZY | RTLD_GLOBAL); + JLI_TraceLauncher("Info: loaded %s\n", splashPath); } if (hSplashLib) { void* sym = dlsym(hSplashLib, name); From 9b8991f944b3a1e10a073ab4b26ef3dd32511191 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Wed, 14 Aug 2013 15:25:16 +0800 Subject: [PATCH 042/263] 8022931: Enhance Kerberos exceptions Reviewed-by: xuelei, ahgross --- .../javax/security/auth/kerberos/KeyTab.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java b/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java index 631b7d02275..db815395e3a 100644 --- a/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java +++ b/jdk/src/share/classes/javax/security/auth/kerberos/KeyTab.java @@ -26,6 +26,7 @@ package javax.security.auth.kerberos; import java.io.File; +import java.security.AccessControlException; import java.util.Objects; import sun.security.krb5.EncryptionKey; import sun.security.krb5.KerberosSecrets; @@ -214,9 +215,22 @@ public final class KeyTab { return new KeyTab(princ, null, true); } - //Takes a snapshot of the keytab content + // Takes a snapshot of the keytab content. This method is called by + // JavaxSecurityAuthKerberosAccessImpl so no more private sun.security.krb5.internal.ktab.KeyTab takeSnapshot() { - return sun.security.krb5.internal.ktab.KeyTab.getInstance(file); + try { + return sun.security.krb5.internal.ktab.KeyTab.getInstance(file); + } catch (AccessControlException ace) { + if (file != null) { + // It's OK to show the name if caller specified it + throw ace; + } else { + AccessControlException ace2 = new AccessControlException( + "Access to default keytab denied (modified exception)"); + ace2.setStackTrace(ace.getStackTrace()); + throw ace2; + } + } } /** From 73ddb82395f11287b3e46abef29c720d1c98b958 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 19 Aug 2013 12:30:48 +0200 Subject: [PATCH 043/263] 8022719: tools/launcher/RunpathTest.java fails after 8012146 Reviewed-by: chegar --- jdk/test/tools/launcher/RunpathTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/jdk/test/tools/launcher/RunpathTest.java b/jdk/test/tools/launcher/RunpathTest.java index 631be16d975..675d7630dbe 100644 --- a/jdk/test/tools/launcher/RunpathTest.java +++ b/jdk/test/tools/launcher/RunpathTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7190813 + * @bug 7190813, 8022719 * @summary Check for extended RPATHs on *nixes * @compile -XDignore.symbol.file RunpathTest.java * @run main RunpathTest @@ -65,12 +65,10 @@ public class RunpathTest extends TestHelper { void testRpath() { if (isDualMode && is64Bit) { - String expectedRpath = ".*RPATH.*\\$ORIGIN/../../lib/" + getJreArch() - + ":\\$ORIGIN/../../jre/lib/" + getJreArch() + ".*"; + String expectedRpath = ".*RPATH.*\\$ORIGIN/../../lib/" + getJreArch() + ".*"; elfCheck(java64Cmd, expectedRpath); } else { - String expectedRpath = ".*RPATH.*\\$ORIGIN/../lib/" + getJreArch() - + ":\\$ORIGIN/../jre/lib/" + getJreArch() + ".*"; + String expectedRpath = ".*RPATH.*\\$ORIGIN/../lib/" + getJreArch() + ".*"; elfCheck(javaCmd, expectedRpath); } } From c130ed36602208230609811e52c78c5fe58a784c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 19 Aug 2013 14:48:08 +0200 Subject: [PATCH 044/263] 8023231: Remove comma from jtreg bug line Reviewed-by: alanb, chegar --- jdk/test/tools/launcher/RunpathTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/tools/launcher/RunpathTest.java b/jdk/test/tools/launcher/RunpathTest.java index 675d7630dbe..79b8b0ecca7 100644 --- a/jdk/test/tools/launcher/RunpathTest.java +++ b/jdk/test/tools/launcher/RunpathTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7190813, 8022719 + * @bug 7190813 8022719 * @summary Check for extended RPATHs on *nixes * @compile -XDignore.symbol.file RunpathTest.java * @run main RunpathTest From 3fceb1f27791e046d3e756927492ff4b5ba300a8 Mon Sep 17 00:00:00 2001 From: William Harnois Date: Wed, 25 Sep 2013 10:50:37 -0400 Subject: [PATCH 045/263] 8025262: new64jre/new64jdk wrappers should be removed, build 32-bit AU during windows-amd64 builds instead Reviewed-by: amenkov, jqzuo --- make/install-rules.gmk | 1 - 1 file changed, 1 deletion(-) diff --git a/make/install-rules.gmk b/make/install-rules.gmk index 2bde487b5ad..2ba4a66fa31 100644 --- a/make/install-rules.gmk +++ b/make/install-rules.gmk @@ -96,7 +96,6 @@ endif combo_build: @$(ECHO) $@ installer combo build started: `$(DATE) '+%y-%m-%d %H:%M'` $(CD) $(INSTALL_TOPDIR)/make/installer/bundles/windows/ishield/wrapper/wrapper.jreboth ; $(MAKE) all - $(CD) $(INSTALL_TOPDIR)/make/installer/bundles/windows/ishield/wrapper/wrapper.new64jre ; $(MAKE) all $(CD) $(INSTALL_TOPDIR)/make/installer/bundles/windows/ishield/jre ; $(MAKE) au_combo $(CD) $(INSTALL_TOPDIR)/make/installer/bundles/windows/xmlinffile ; $(MAKE) all From 7569765f7e21c1b4ce2d4223bdde1dd1ae70b53e Mon Sep 17 00:00:00 2001 From: Taras Ledkov Date: Fri, 27 Sep 2013 12:35:43 +0400 Subject: [PATCH 046/263] 8025249: [javadoc] fix some javadoc errors in javax/swing/ Reviewed-by: alexsch, yan --- .../javax/swing/border/CompoundBorder.java | 4 +- .../AbstractColorChooserPanel.java | 6 +- .../classes/javax/swing/event/CaretEvent.java | 4 +- .../javax/swing/event/DocumentEvent.java | 6 +- .../javax/swing/event/EventListenerList.java | 2 +- .../javax/swing/event/ListDataEvent.java | 4 +- .../javax/swing/event/TreeModelEvent.java | 8 +- .../javax/swing/filechooser/FileView.java | 6 +- .../swing/table/DefaultTableCellRenderer.java | 2 +- .../javax/swing/table/DefaultTableModel.java | 5 +- .../javax/swing/table/JTableHeader.java | 10 +- .../javax/swing/table/TableCellRenderer.java | 8 +- .../javax/swing/text/AbstractDocument.java | 106 +++++++++--------- .../javax/swing/text/AbstractWriter.java | 4 +- .../javax/swing/text/AsyncBoxView.java | 50 ++++----- .../javax/swing/text/AttributeSet.java | 2 +- .../classes/javax/swing/text/Document.java | 22 ++-- .../classes/javax/swing/text/Element.java | 14 +-- .../share/classes/javax/swing/text/View.java | 62 +++++----- 19 files changed, 162 insertions(+), 163 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/border/CompoundBorder.java b/jdk/src/share/classes/javax/swing/border/CompoundBorder.java index 56371a47a6d..a0143670ec2 100644 --- a/jdk/src/share/classes/javax/swing/border/CompoundBorder.java +++ b/jdk/src/share/classes/javax/swing/border/CompoundBorder.java @@ -37,11 +37,11 @@ import java.beans.ConstructorProperties; * For example, this class may be used to add blank margin space * to a component with an existing decorative border: *

    - *

    + * 
      *    Border border = comp.getBorder();
      *    Border margin = new EmptyBorder(10,10,10,10);
      *    comp.setBorder(new CompoundBorder(border, margin));
    - * 
    + *
    *

    * Warning: * Serialized objects of this class will not be compatible with diff --git a/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java b/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java index 99a20e38ffd..2a3b0c0c4c1 100644 --- a/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java +++ b/jdk/src/share/classes/javax/swing/colorchooser/AbstractColorChooserPanel.java @@ -85,7 +85,7 @@ public abstract class AbstractColorChooserPanel extends JPanel { /** * Provides a hint to the look and feel as to the * KeyEvent.VK constant that can be used as a mnemonic to - * access the panel. A return value <= 0 indicates there is no mnemonic. + * access the panel. A return value <= 0 indicates there is no mnemonic. *

    * The return value here is a hint, it is ultimately up to the look * and feel to honor the return value in some meaningful way. @@ -94,7 +94,7 @@ public abstract class AbstractColorChooserPanel extends JPanel { * AbstractColorChooserPanel does not support a mnemonic, * subclasses wishing a mnemonic will need to override this. * - * @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no + * @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no * mnemonic * @see #getDisplayedMnemonicIndex * @since 1.4 @@ -107,7 +107,7 @@ public abstract class AbstractColorChooserPanel extends JPanel { * Provides a hint to the look and feel as to the index of the character in * getDisplayName that should be visually identified as the * mnemonic. The look and feel should only use this if - * getMnemonic returns a value > 0. + * getMnemonic returns a value > 0. *

    * The return value here is a hint, it is ultimately up to the look * and feel to honor the return value in some meaningful way. For example, diff --git a/jdk/src/share/classes/javax/swing/event/CaretEvent.java b/jdk/src/share/classes/javax/swing/event/CaretEvent.java index 7b47eb3f714..6cb3164b6b0 100644 --- a/jdk/src/share/classes/javax/swing/event/CaretEvent.java +++ b/jdk/src/share/classes/javax/swing/event/CaretEvent.java @@ -56,7 +56,7 @@ public abstract class CaretEvent extends EventObject { /** * Fetches the location of the caret. * - * @return the dot >= 0 + * @return the dot >= 0 */ public abstract int getDot(); @@ -65,7 +65,7 @@ public abstract class CaretEvent extends EventObject { * selection. If there is no selection, this * will be the same as dot. * - * @return the mark >= 0 + * @return the mark >= 0 */ public abstract int getMark(); } diff --git a/jdk/src/share/classes/javax/swing/event/DocumentEvent.java b/jdk/src/share/classes/javax/swing/event/DocumentEvent.java index 707e698b63c..9c9c796f8ec 100644 --- a/jdk/src/share/classes/javax/swing/event/DocumentEvent.java +++ b/jdk/src/share/classes/javax/swing/event/DocumentEvent.java @@ -45,14 +45,14 @@ public interface DocumentEvent { * Returns the offset within the document of the start * of the change. * - * @return the offset >= 0 + * @return the offset >= 0 */ public int getOffset(); /** * Returns the length of the change. * - * @return the length >= 0 + * @return the length >= 0 */ public int getLength(); @@ -155,7 +155,7 @@ public interface DocumentEvent { * This is the location that children were added * and/or removed. * - * @return the index >= 0 + * @return the index >= 0 */ public int getIndex(); diff --git a/jdk/src/share/classes/javax/swing/event/EventListenerList.java b/jdk/src/share/classes/javax/swing/event/EventListenerList.java index 237bf2067b2..004659ad24e 100644 --- a/jdk/src/share/classes/javax/swing/event/EventListenerList.java +++ b/jdk/src/share/classes/javax/swing/event/EventListenerList.java @@ -69,7 +69,7 @@ import java.lang.reflect.Array; * Object[] listeners = listenerList.getListenerList(); * // Process the listeners last to first, notifying * // those that are interested in this event - * for (int i = listeners.length-2; i>=0; i-=2) { + * for (int i = listeners.length-2; i>=0; i-=2) { * if (listeners[i]==FooListener.class) { * // Lazily create the event: * if (fooEvent == null) diff --git a/jdk/src/share/classes/javax/swing/event/ListDataEvent.java b/jdk/src/share/classes/javax/swing/event/ListDataEvent.java index 3ccf01e1a45..8862e724eac 100644 --- a/jdk/src/share/classes/javax/swing/event/ListDataEvent.java +++ b/jdk/src/share/classes/javax/swing/event/ListDataEvent.java @@ -85,9 +85,9 @@ public class ListDataEvent extends EventObject public int getIndex1() { return index1; } /** - * Constructs a ListDataEvent object. If index0 is > + * Constructs a ListDataEvent object. If index0 is > * index1, index0 and index1 will be swapped such that - * index0 will always be <= index1. + * index0 will always be <= index1. * * @param source the source Object (typically this) * @param type an int specifying {@link #CONTENTS_CHANGED}, diff --git a/jdk/src/share/classes/javax/swing/event/TreeModelEvent.java b/jdk/src/share/classes/javax/swing/event/TreeModelEvent.java index 3c92dc16377..6c6d7cef4cd 100644 --- a/jdk/src/share/classes/javax/swing/event/TreeModelEvent.java +++ b/jdk/src/share/classes/javax/swing/event/TreeModelEvent.java @@ -101,14 +101,14 @@ public class TreeModelEvent extends EventObject { * of initial-positions, you then need to convert the Vector of Integer * objects to an array of int to create the event. *

    - * Notes: