# HG changeset patch # User lana # Date 1316821889 25200 # Node ID 5e57ab6c83a31bdfb47b18d0deb539aec8cbc225 # Parent 244113d67cf06951e4a89b8ba9f4432cde5f673d# Parent 429da7734bf491bccde2a752fae97e9f225896dc Merge diff -r 244113d67cf0 -r 5e57ab6c83a3 .hgtags --- a/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ de9223c94f9c710b3eebb599cd3586f36c8b94a9 jdk8-b01 1b9d19620eb4606a25b1e28f86d66c8bfa867e06 jdk8-b02 6815e85bf96d6d3875954f9777660372cd70d065 jdk8-b03 +31f5c34d78081572ad9a2401c0bb0c6b9711dd65 jdk8-b04 +c4f9ea1ecb55ff44e0dd21d2888ead308c86a3aa jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 .hgtags-top-repo --- a/.hgtags-top-repo Wed Sep 21 17:08:02 2011 +0400 +++ b/.hgtags-top-repo Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ f42e3d9394b40a423d345b8da22687b5462e5f25 jdk8-b01 69f592185747226a9c765a9fe139c1d34d616f9c jdk8-b02 587bb549dff83131b65f40aa51864f69562f34a7 jdk8-b03 +0b66a233bfb9ba2ebda1e5cdfdb0373d6c1e3c69 jdk8-b04 +b910aac18c772b823b1f7da03e2c6528725cc6de jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 corba/.hgtags --- a/corba/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/corba/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ 949fb60ca830364571e7c4c9964e6b351ca929ec jdk8-b01 ed8d94519a87b4adac270c3eec9134ff1f62bff5 jdk8-b02 cd0da00694fbce642db9be936d3e4909a71d911d jdk8-b03 +60a68d688e24473cf84dedd1e60901a61ab82555 jdk8-b04 +cc1b599b986a37cb57de4584c5e58169766ca535 jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 hotspot/.hgtags --- a/hotspot/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/hotspot/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -177,3 +177,5 @@ 0cc8a70952c368e06de2adab1f2649a408f5e577 jdk8-b01 31e253c1da429124bb87570ab095d9bc89850d0a jdk8-b02 3a2fb61165dfc72e398179a2796d740c8da5b8c0 jdk8-b03 +0fa3ace511fe98fe948e751531f3e2b7c60c8376 jdk8-b04 +dce7d24674f4d0bed00de24f00119057fdce7cfb jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 jaxp/.hgtags --- a/jaxp/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/jaxp/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ 4f0fcb812767594fe9de509f946b56942db5a2f0 jdk8-b01 ca4d6ad55a660f0469882e85b4dacf7822d50abf jdk8-b02 7a74371ce0c64108b857c497ae130dfe9514532c jdk8-b03 +acbcadef0b21582abf406f07f1b74d2b8f80dc01 jdk8-b04 +ff0a3d78e7a22743eabbaa71e9d17b2f094ddf62 jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 jaxws/.hgtags --- a/jaxws/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/jaxws/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ 64df57a1edeca74388bd62f0a87d056db981fbdf jdk8-b01 1034127ed402e9d0f1ed1477238ef594e9cc8da6 jdk8-b02 7dcb0307508f408507d878cd7c2048c102b15158 jdk8-b03 +3f6f08163331ed75b30a6de1246670ce655645c8 jdk8-b04 +7d5d91fddbceb1fc3ae7ff409e732ae4a0391b34 jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/.hgtags --- a/jdk/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -126,3 +126,4 @@ 13e70aa1398eb959c54bc68b783ca0eef1286ad2 jdk8-b02 7989ee9fe673a87f4db3917fa6a005732a6a9b85 jdk8-b03 fc569517f3cf242f90ce3503b743eb5553938946 jdk8-b04 +0b32369b83d81c226a2e79e730f3a8c0d2595e92 jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/make/com/sun/servicetag/Makefile --- a/jdk/make/com/sun/servicetag/Makefile Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/make/com/sun/servicetag/Makefile Fri Sep 23 16:51:29 2011 -0700 @@ -47,7 +47,7 @@ # Add all properties files to the FILES_copy list SWORDFISH_properties := $(shell \ $(CD) $(SHARE_SRC)/classes/com/sun/servicetag/resources; \ - $(FIND) . -name 'javase_*_swordfish.properties' -print ; \ + $(FIND) . -name 'javase_*.properties' -print ; \ ) FILES_copy += $(shell \ for f in $(SWORDFISH_properties) ; do \ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/make/jprt.properties --- a/jdk/make/jprt.properties Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/make/jprt.properties Fri Sep 23 16:51:29 2011 -0700 @@ -258,6 +258,15 @@ windows_i586_5.1-product-c1-jdk_security3, \ windows_x64_5.2-product-c2-jdk_security3, \ \ + solaris_sparc_5.10-product-c1-jdk_sound, \ + solaris_sparcv9_5.10-product-c2-jdk_sound, \ + solaris_i586_5.10-product-c1-jdk_sound, \ + solaris_x64_5.10-product-c2-jdk_sound, \ + linux_i586_2.6-product-{c1|c2}-jdk_sound, \ + linux_x64_2.6-product-c2-jdk_sound, \ + windows_i586_5.1-product-c1-jdk_sound, \ + windows_x64_5.2-product-c2-jdk_sound, \ + \ solaris_sparc_5.10-product-c1-jdk_swing, \ solaris_sparcv9_5.10-product-c2-jdk_swing, \ solaris_i586_5.10-product-c1-jdk_swing, \ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JFIFMarkerSegment.java Fri Sep 23 16:51:29 2011 -0700 @@ -763,7 +763,7 @@ } } catch (IllegalThumbException e) { // Should never happen - throw new InternalError("Illegal thumb in setThumbnail!"); + throw new InternalError("Illegal thumb in setThumbnail!", e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/jmx/snmp/SnmpCounter64.java --- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpCounter64.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpCounter64.java Fri Sep 23 16:51:29 2011 -0700 @@ -186,7 +186,7 @@ newclone = (SnmpCounter64) super.clone() ; newclone.value = value ; } catch (CloneNotSupportedException e) { - throw new InternalError() ; // vm bug. + throw new InternalError(e) ; // vm bug. } return newclone ; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/jmx/snmp/SnmpInt.java --- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpInt.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpInt.java Fri Sep 23 16:51:29 2011 -0700 @@ -232,7 +232,7 @@ newclone = (SnmpInt) super.clone() ; newclone.value = value ; } catch (CloneNotSupportedException e) { - throw new InternalError() ; // vm bug. + throw new InternalError(e) ; // vm bug. } return newclone ; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/jmx/snmp/SnmpNull.java --- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpNull.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpNull.java Fri Sep 23 16:51:29 2011 -0700 @@ -129,7 +129,7 @@ newclone = (SnmpNull) super.clone() ; newclone.tag = tag ; } catch (CloneNotSupportedException e) { - throw new InternalError() ; // vm bug. + throw new InternalError(e) ; // vm bug. } return newclone ; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/jmx/snmp/SnmpString.java --- a/jdk/src/share/classes/com/sun/jmx/snmp/SnmpString.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/jmx/snmp/SnmpString.java Fri Sep 23 16:51:29 2011 -0700 @@ -250,7 +250,7 @@ newclone.value = new byte[value.length] ; System.arraycopy(value, 0, newclone.value, 0, value.length) ; } catch (CloneNotSupportedException e) { - throw new InternalError() ; // vm bug. + throw new InternalError(e) ; // vm bug. } return newclone ; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java --- a/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/jmx/snmp/daemon/SnmpRequestHandler.java Fri Sep 23 16:51:29 2011 -0700 @@ -921,7 +921,7 @@ SNMP_ADAPTOR_LOGGER.logp(Level.FINEST, dbgTag, "newTooBigMessage", "Internal error", x); } - throw new InternalError() ; + throw new InternalError(x) ; } return result ; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java --- a/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/security/auth/module/NTSystem.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ public class NTSystem { private native void getCurrent(boolean debug); + private native long getImpersonationToken0(); private String userName; private String domain; @@ -132,10 +133,14 @@ * * @return an impersonation token for the current NT user. */ - public long getImpersonationToken() { + public synchronized long getImpersonationToken() { + if (impersonationToken == 0) { + impersonationToken = getImpersonationToken0(); + } return impersonationToken; } + private void loadNative() { System.loadLibrary("jaas_nt"); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/servicetag/BrowserSupport.java --- a/jdk/src/share/classes/com/sun/servicetag/BrowserSupport.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/servicetag/BrowserSupport.java Fri Sep 23 16:51:29 2011 -0700 @@ -77,9 +77,7 @@ result = (Boolean) isDesktopSupportedMethod.invoke(null); } catch (IllegalAccessException e) { // should never reach here - InternalError x = - new InternalError("Desktop.getDesktop() method not found"); - x.initCause(e); + throw new InternalError("Desktop.getDesktop() method not found", e); } catch (InvocationTargetException e) { // browser not supported if (Util.isVerbose()) { @@ -101,28 +99,10 @@ result = (Boolean) isSupportedMethod.invoke(desktopObj, browseField.get(null)); supported = result.booleanValue(); } - } catch (ClassNotFoundException e) { - // browser not supported - if (Util.isVerbose()) { - e.printStackTrace(); - } - } catch (NoSuchMethodException e) { - // browser not supported - if (Util.isVerbose()) { - e.printStackTrace(); - } - } catch (NoSuchFieldException e) { - // browser not supported - if (Util.isVerbose()) { - e.printStackTrace(); - } } catch (IllegalAccessException e) { // should never reach here - InternalError x = - new InternalError("Desktop.getDesktop() method not found"); - x.initCause(e); - throw x; - } catch (InvocationTargetException e) { + throw new InternalError("Desktop.getDesktop() method not found", e); + } catch (ReflectiveOperationException e) { // browser not supported if (Util.isVerbose()) { e.printStackTrace(); @@ -175,10 +155,7 @@ browseMethod.invoke(desktop, uri); } catch (IllegalAccessException e) { // should never reach here - InternalError x = - new InternalError("Desktop.getDesktop() method not found"); - x.initCause(e); - throw x; + throw new InternalError("Desktop.getDesktop() method not found", e); } catch (InvocationTargetException e) { Throwable x = e.getCause(); if (x != null) { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/servicetag/Installer.java --- a/jdk/src/share/classes/com/sun/servicetag/Installer.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/servicetag/Installer.java Fri Sep 23 16:51:29 2011 -0700 @@ -61,8 +61,8 @@ private static RegistrationData registration; private static boolean supportRegistration; private static String registerHtmlParent; - private static Set supportedLocales = new HashSet(); - private static Properties swordfishProps = null; + private static Set supportedLocales = new HashSet<>(); + private static Properties svcTagProps = null; private static String[] jreArchs = null; static { String dir = System.getProperty(SVCTAG_DIR_PATH); @@ -94,7 +94,7 @@ boolean cleanup = false; try { // Check if we have the swordfish entries for this JRE version - if (loadSwordfishEntries() == null) { + if (loadServiceTagProps() == null) { return null; } @@ -144,18 +144,14 @@ return registration; } if (regXmlFile.exists()) { - BufferedInputStream in = null; - try { - in = new BufferedInputStream(new FileInputStream(regXmlFile)); + try (BufferedInputStream in = + new BufferedInputStream(new FileInputStream(regXmlFile))) + { registration = RegistrationData.loadFromXML(in); } catch (IllegalArgumentException ex) { System.err.println("Error: Bad registration data \"" + regXmlFile + "\":" + ex.getMessage()); throw ex; - } finally { - if (in != null) { - in.close(); - } } } else { registration = new RegistrationData(); @@ -186,18 +182,14 @@ deleteRegistrationHtmlPage(); getRegistrationHtmlPage(); - BufferedOutputStream out = null; - try { - out = new BufferedOutputStream(new FileOutputStream(regXmlFile)); + try (BufferedOutputStream out = + new BufferedOutputStream(new FileOutputStream(regXmlFile))) + { getRegistrationData().storeToXML(out); } catch (IllegalArgumentException ex) { System.err.println("Error: Bad registration data \"" + regXmlFile + "\":" + ex.getMessage()); throw ex; - } finally { - if (out != null) { - out.close(); - } } } @@ -206,11 +198,9 @@ * or empty set if file not exists. */ private static Set getInstalledURNs() throws IOException { - Set urnSet = new HashSet(); + Set urnSet = new HashSet<>(); if (serviceTagFile.exists()) { - BufferedReader in = null; - try { - in = new BufferedReader(new FileReader(serviceTagFile)); + try (BufferedReader in = new BufferedReader(new FileReader(serviceTagFile))) { String urn; while ((urn = in.readLine()) != null) { urn = urn.trim(); @@ -218,10 +208,6 @@ urnSet.add(urn); } } - } finally { - if (in != null) { - in.close(); - } } } return urnSet; @@ -237,9 +223,9 @@ private static ServiceTag[] getJavaServiceTagArray() throws IOException { RegistrationData regData = getRegistrationData(); Set svcTags = regData.getServiceTags(); - Set result = new HashSet(); + Set result = new HashSet<>(); - Properties props = loadSwordfishEntries(); + Properties props = loadServiceTagProps(); String jdkUrn = props.getProperty("servicetag.jdk.urn"); String jreUrn = props.getProperty("servicetag.jre.urn"); for (ServiceTag st : svcTags) { @@ -343,8 +329,7 @@ } private static ServiceTag newServiceTag(String svcTagSource) throws IOException { - // Load the swoRDFish information for the service tag creation - Properties props = loadSwordfishEntries(); + Properties props = loadServiceTagProps(); // Determine the product URN and name String productURN; @@ -442,52 +427,35 @@ return; } - PrintWriter out = null; - try { - out = new PrintWriter(serviceTagFile); - + try (PrintWriter out = new PrintWriter(serviceTagFile)) { ServiceTag[] javaSvcTags = getJavaServiceTagArray(); for (ServiceTag st : javaSvcTags) { // Write the instance_run to the servicetag file String instanceURN = st.getInstanceURN(); out.println(instanceURN); } - } finally { - if (out != null) { - out.close(); - } } } /** - * Load the values associated with the swoRDFish metadata entries - * for Java SE. The swoRDFish metadata entries are different for - * different release. + * Load the properties for generating Java SE service tags. * * @param version Version of Java SE */ - private static synchronized Properties loadSwordfishEntries() throws IOException { - if (swordfishProps != null) { - return swordfishProps; + private static synchronized Properties loadServiceTagProps() throws IOException { + if (svcTagProps != null) { + return svcTagProps; } - // The version string for Java SE 6 is 1.6.0 - // We just need the minor number in the version string - int version = Util.getJdkVersion(); - - String filename = "/com/sun/servicetag/resources/javase_" + - version + "_swordfish.properties"; - InputStream in = Installer.class.getResourceAsStream(filename); - if (in == null) { - return null; + // For Java SE 8 and later releases, JDK and JRE both use + // the same product number. The sworRDFish metadata were + // for legacy Sun part number. + String filename = "/com/sun/servicetag/resources/javase_servicetag.properties"; + try (InputStream in = Installer.class.getResourceAsStream(filename)) { + svcTagProps = new Properties(); + svcTagProps.load(in); } - swordfishProps = new Properties(); - try { - swordfishProps.load(in); - } finally { - in.close(); - } - return swordfishProps; + return svcTagProps; } /** @@ -546,7 +514,7 @@ return jreArchs; } - Set archs = new HashSet(); + Set archs = new HashSet<>(); String os = System.getProperty("os.name"); if (os.equals("SunOS") || os.equals("Linux")) { @@ -681,16 +649,16 @@ String country = locale.getCountry(); String variant = locale.getVariant(); - List locales = new ArrayList(3); + List locales = new ArrayList<>(3); if (variant.length() > 0) { locales.add(locale); } if (country.length() > 0) { - locales.add((locales.size() == 0) ? + locales.add((locales.isEmpty()) ? locale : new Locale(language, country, "")); } if (language.length() > 0) { - locales.add((locales.size() == 0) ? + locales.add((locales.isEmpty()) ? locale : new Locale(language, "", "")); } return locales; @@ -788,14 +756,11 @@ // Format the registration data in one single line StringBuilder payload = new StringBuilder(); String xml = regData.toString().replaceAll("\"", "%22"); - BufferedReader reader = new BufferedReader(new StringReader(xml)); - try { + try (BufferedReader reader = new BufferedReader(new StringReader(xml))) { String line = null; while ((line = reader.readLine()) != null) { payload.append(line.trim()); } - } finally { - reader.close(); } String resourceFilename = "/com/sun/servicetag/resources/register"; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/servicetag/RegistrationDocument.java --- a/jdk/src/share/classes/com/sun/servicetag/RegistrationDocument.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/com/sun/servicetag/RegistrationDocument.java Fri Sep 23 16:51:29 2011 -0700 @@ -150,9 +150,7 @@ } catch (ParserConfigurationException pce) { // Parser with specific options can't be built // should not reach here - InternalError x = new InternalError("Error in creating the new document"); - x.initCause(pce); - throw x; + throw new InternalError("Error in creating the new document", pce); } } @@ -172,9 +170,7 @@ } catch (ParserConfigurationException pce) { // Parser with specified options can't be built // should not reach here - InternalError x = new InternalError("Error in creating the new document"); - x.initCause(pce); - throw x; + throw new InternalError("Error in creating the new document", pce); } } @@ -195,20 +191,14 @@ new StreamResult(new BufferedWriter(new OutputStreamWriter(os, "UTF-8")))); } catch (UnsupportedEncodingException ue) { // Should not reach here - InternalError x = new InternalError("Error generated during transformation"); - x.initCause(ue); - throw x; + throw new InternalError("Error generated during transformation", ue); } catch (TransformerConfigurationException tce) { // Error generated by the parser // Should not reach here - InternalError x = new InternalError("Error in creating the new document"); - x.initCause(tce); - throw x; + throw new InternalError("Error in creating the new document", tce); } catch (TransformerException te) { // Error generated by the transformer - InternalError x = new InternalError("Error generated during transformation"); - x.initCause(te); - throw x; + throw new InternalError("Error generated during transformation", te); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/com/sun/servicetag/resources/javase_servicetag.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/com/sun/servicetag/resources/javase_servicetag.properties Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,29 @@ +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. + +servicetag.jdk.urn = Q8549 +servicetag.jdk.name = Java Development Kit +servicetag.jre.urn = Q8549 +servicetag.jre.name = Java Runtime Environment +servicetag.parent.urn = Q8549 +servicetag.parent.name = Java Platform, Standard Edition diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/BufferCapabilities.java --- a/jdk/src/share/classes/java/awt/BufferCapabilities.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/BufferCapabilities.java Fri Sep 23 16:51:29 2011 -0700 @@ -137,7 +137,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // Since we implement Cloneable, this should never happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/Component.java --- a/jdk/src/share/classes/java/awt/Component.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/Component.java Fri Sep 23 16:51:29 2011 -0700 @@ -3776,11 +3776,10 @@ createBufferStrategy(numBuffers, bufferCaps); return; // Success } catch (AWTException e) { - // Failed - } - // Code should never reach here (an unaccelerated blitting - // strategy should always work) - throw new InternalError("Could not create a buffer strategy"); + // Code should never reach here (an unaccelerated blitting + // strategy should always work) + throw new InternalError("Could not create a buffer strategy", e); + } } /** diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/GridBagConstraints.java --- a/jdk/src/share/classes/java/awt/GridBagConstraints.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/GridBagConstraints.java Fri Sep 23 16:51:29 2011 -0700 @@ -653,7 +653,7 @@ return c; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/ImageCapabilities.java --- a/jdk/src/share/classes/java/awt/ImageCapabilities.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/ImageCapabilities.java Fri Sep 23 16:51:29 2011 -0700 @@ -74,7 +74,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // Since we implement Cloneable, this should never happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/Insets.java --- a/jdk/src/share/classes/java/awt/Insets.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/Insets.java Fri Sep 23 16:51:29 2011 -0700 @@ -177,7 +177,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } /** diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/JobAttributes.java --- a/jdk/src/share/classes/java/awt/JobAttributes.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/JobAttributes.java Fri Sep 23 16:51:29 2011 -0700 @@ -361,7 +361,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // Since we implement Cloneable, this should never happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/PageAttributes.java --- a/jdk/src/share/classes/java/awt/PageAttributes.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/PageAttributes.java Fri Sep 23 16:51:29 2011 -0700 @@ -969,7 +969,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // Since we implement Cloneable, this should never happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/RenderingHints.java --- a/jdk/src/share/classes/java/awt/RenderingHints.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/RenderingHints.java Fri Sep 23 16:51:29 2011 -0700 @@ -1276,7 +1276,7 @@ } } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } return rh; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/font/TextLayout.java --- a/jdk/src/share/classes/java/awt/font/TextLayout.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/font/TextLayout.java Fri Sep 23 16:51:29 2011 -0700 @@ -753,7 +753,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/AffineTransform.java --- a/jdk/src/share/classes/java/awt/geom/AffineTransform.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/AffineTransform.java Fri Sep 23 16:51:29 2011 -0700 @@ -3856,7 +3856,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/CubicCurve2D.java --- a/jdk/src/share/classes/java/awt/geom/CubicCurve2D.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/CubicCurve2D.java Fri Sep 23 16:51:29 2011 -0700 @@ -1569,7 +1569,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/Dimension2D.java --- a/jdk/src/share/classes/java/awt/geom/Dimension2D.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/Dimension2D.java Fri Sep 23 16:51:29 2011 -0700 @@ -108,7 +108,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/Line2D.java --- a/jdk/src/share/classes/java/awt/geom/Line2D.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/Line2D.java Fri Sep 23 16:51:29 2011 -0700 @@ -1122,7 +1122,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/Point2D.java --- a/jdk/src/share/classes/java/awt/geom/Point2D.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/Point2D.java Fri Sep 23 16:51:29 2011 -0700 @@ -393,7 +393,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/QuadCurve2D.java --- a/jdk/src/share/classes/java/awt/geom/QuadCurve2D.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/QuadCurve2D.java Fri Sep 23 16:51:29 2011 -0700 @@ -1395,7 +1395,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/geom/RectangularShape.java --- a/jdk/src/share/classes/java/awt/geom/RectangularShape.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/geom/RectangularShape.java Fri Sep 23 16:51:29 2011 -0700 @@ -391,7 +391,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/image/ImageFilter.java --- a/jdk/src/share/classes/java/awt/image/ImageFilter.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/image/ImageFilter.java Fri Sep 23 16:51:29 2011 -0700 @@ -252,7 +252,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/awt/image/Kernel.java --- a/jdk/src/share/classes/java/awt/image/Kernel.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/awt/image/Kernel.java Fri Sep 23 16:51:29 2011 -0700 @@ -147,7 +147,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/io/ObjectStreamClass.java --- a/jdk/src/share/classes/java/io/ObjectStreamClass.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/io/ObjectStreamClass.java Fri Sep 23 16:51:29 2011 -0700 @@ -478,7 +478,7 @@ fieldRefl = getReflector(fields, this); } catch (InvalidClassException ex) { // field mismatches impossible when matching local fields vs. self - throw new InternalError(); + throw new InternalError(ex); } if (deserializeEx == null) { @@ -941,7 +941,7 @@ return cons.newInstance(); } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -969,7 +969,7 @@ } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -1000,7 +1000,7 @@ } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -1028,7 +1028,7 @@ } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -1053,11 +1053,11 @@ throw (ObjectStreamException) th; } else { throwMiscException(th); - throw new InternalError(); // never reached + throw new InternalError(th); // never reached } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -1082,11 +1082,11 @@ throw (ObjectStreamException) th; } else { throwMiscException(th); - throw new InternalError(); // never reached + throw new InternalError(th); // never reached } } catch (IllegalAccessException ex) { // should not occur, as access checks have been suppressed - throw new InternalError(); + throw new InternalError(ex); } } else { throw new UnsupportedOperationException(); @@ -1774,7 +1774,7 @@ } return hash; } catch (IOException ex) { - throw new InternalError(); + throw new InternalError(ex); } catch (NoSuchAlgorithmException ex) { throw new SecurityException(ex.getMessage()); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/CharacterName.java --- a/jdk/src/share/classes/java/lang/CharacterName.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/CharacterName.java Fri Sep 23 16:51:29 2011 -0700 @@ -83,7 +83,7 @@ dis.readFully(strPool); refStrPool = new SoftReference<>(strPool); } catch (Exception x) { - throw new InternalError(x.getMessage()); + throw new InternalError(x.getMessage(), x); } finally { try { if (dis != null) diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/Class.java --- a/jdk/src/share/classes/java/lang/Class.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/Class.java Fri Sep 23 16:51:29 2011 -0700 @@ -974,8 +974,7 @@ descriptor = (String) enclosingInfo[2]; assert((name != null && descriptor != null) || name == descriptor); } catch (ClassCastException cce) { - throw (InternalError) - new InternalError("Invalid type in enclosing method information").initCause(cce); + throw new InternalError("Invalid type in enclosing method information", cce); } } @@ -1241,8 +1240,7 @@ try { return getName().substring(enclosingClass.getName().length()); } catch (IndexOutOfBoundsException ex) { - throw (InternalError) - new InternalError("Malformed class name").initCause(ex); + throw new InternalError("Malformed class name", ex); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/VirtualMachineError.java --- a/jdk/src/share/classes/java/lang/VirtualMachineError.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/VirtualMachineError.java Fri Sep 23 16:51:29 2011 -0700 @@ -3,7 +3,7 @@ * 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, asP + * 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. diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/invoke/CallSite.java --- a/jdk/src/share/classes/java/lang/invoke/CallSite.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/invoke/CallSite.java Fri Sep 23 16:51:29 2011 -0700 @@ -27,7 +27,6 @@ import sun.invoke.empty.Empty; import sun.misc.Unsafe; -import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; /** @@ -244,8 +243,8 @@ try { GET_TARGET = IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); - } catch (ReflectiveOperationException ignore) { - throw new InternalError(); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/invoke/Invokers.java --- a/jdk/src/share/classes/java/lang/invoke/Invokers.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/invoke/Invokers.java Fri Sep 23 16:51:29 2011 -0700 @@ -88,7 +88,7 @@ try { invoker = IMPL_LOOKUP.findVirtual(MethodHandle.class, name, targetType); } catch (ReflectiveOperationException ex) { - throw new InternalError("JVM cannot find invoker for "+targetType); + throw new InternalError("JVM cannot find invoker for "+targetType, ex); } assert(invokerType(targetType) == invoker.type()); assert(!invoker.isVarargsCollector()); diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/invoke/MemberName.java --- a/jdk/src/share/classes/java/lang/invoke/MemberName.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/invoke/MemberName.java Fri Sep 23 16:51:29 2011 -0700 @@ -382,7 +382,7 @@ try { return (MemberName) super.clone(); } catch (CloneNotSupportedException ex) { - throw new InternalError(); + throw new InternalError(ex); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleStatics.java Fri Sep 23 16:51:29 2011 -0700 @@ -108,9 +108,7 @@ return new IllegalArgumentException(message(message, obj, obj2)); } /*non-public*/ static Error uncaughtException(Exception ex) { - Error err = new InternalError("uncaught exception"); - err.initCause(ex); - return err; + throw new InternalError("uncaught exception", ex); } private static String message(String message, Object obj) { if (obj != null) message = message + ": " + obj; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java --- a/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/invoke/MethodTypeForm.java Fri Sep 23 16:51:29 2011 -0700 @@ -461,7 +461,7 @@ // Trigger adapter creation. genericInvoker = InvokeGeneric.generalInvokerOf(erasedType); } catch (Exception ex) { - Error err = new InternalError("Exception while resolving inexact invoke"); + Error err = new InternalError("Exception while resolving inexact invoke", ex); err.initCause(ex); throw err; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/reflect/Proxy.java --- a/jdk/src/share/classes/java/lang/reflect/Proxy.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/reflect/Proxy.java Fri Sep 23 16:51:29 2011 -0700 @@ -610,7 +610,7 @@ IllegalAccessException | InstantiationException | InvocationTargetException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/lang/reflect/TypeVariable.java --- a/jdk/src/share/classes/java/lang/reflect/TypeVariable.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/lang/reflect/TypeVariable.java Fri Sep 23 16:51:29 2011 -0700 @@ -48,7 +48,7 @@ * * @since 1.5 */ -public interface TypeVariable extends Type { +public interface TypeVariable extends Type, AnnotatedElement { /** * Returns an array of {@code Type} objects representing the * upper bound(s) of this type variable. Note that if no upper bound is diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/math/BigDecimal.java --- a/jdk/src/share/classes/java/math/BigDecimal.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/math/BigDecimal.java Fri Sep 23 16:51:29 2011 -0700 @@ -215,6 +215,7 @@ * @author Josh Bloch * @author Mike Cowlishaw * @author Joseph D. Darcy + * @author Sergey V. Kuksenko */ public class BigDecimal extends Number implements Comparable { /** @@ -224,7 +225,7 @@ * @serial * @see #unscaledValue */ - private volatile BigInteger intVal; + private final BigInteger intVal; /** * The scale of this BigDecimal, as returned by {@link #scale}. @@ -232,8 +233,9 @@ * @serial * @see #scale */ - private int scale; // Note: this may have any value, so - // calculations must be done in longs + private final int scale; // Note: this may have any value, so + // calculations must be done in longs + /** * The number of decimal digits in this BigDecimal, or 0 if the * number of digits are not known (lookaside information). If @@ -256,19 +258,19 @@ */ static final long INFLATED = Long.MIN_VALUE; + private static final BigInteger INFLATED_BIGINT = BigInteger.valueOf(INFLATED); + /** * If the absolute value of the significand of this BigDecimal is * less than or equal to {@code Long.MAX_VALUE}, the value can be * compactly stored in this field and used in computations. */ - private transient long intCompact; + private final transient long intCompact; // All 18-digit base ten strings fit into a long; not all 19-digit // strings will private static final int MAX_COMPACT_DIGITS = 18; - private static final int MAX_BIGINT_BITS = 62; - /* Appease the serialization gods */ private static final long serialVersionUID = 6108874887143696463L; @@ -282,17 +284,17 @@ // Cache of common small BigDecimal values. private static final BigDecimal zeroThroughTen[] = { - new BigDecimal(BigInteger.ZERO, 0, 0, 1), - new BigDecimal(BigInteger.ONE, 1, 0, 1), - new BigDecimal(BigInteger.valueOf(2), 2, 0, 1), - new BigDecimal(BigInteger.valueOf(3), 3, 0, 1), - new BigDecimal(BigInteger.valueOf(4), 4, 0, 1), - new BigDecimal(BigInteger.valueOf(5), 5, 0, 1), - new BigDecimal(BigInteger.valueOf(6), 6, 0, 1), - new BigDecimal(BigInteger.valueOf(7), 7, 0, 1), - new BigDecimal(BigInteger.valueOf(8), 8, 0, 1), - new BigDecimal(BigInteger.valueOf(9), 9, 0, 1), - new BigDecimal(BigInteger.TEN, 10, 0, 2), + new BigDecimal(BigInteger.ZERO, 0, 0, 1), + new BigDecimal(BigInteger.ONE, 1, 0, 1), + new BigDecimal(BigInteger.valueOf(2), 2, 0, 1), + new BigDecimal(BigInteger.valueOf(3), 3, 0, 1), + new BigDecimal(BigInteger.valueOf(4), 4, 0, 1), + new BigDecimal(BigInteger.valueOf(5), 5, 0, 1), + new BigDecimal(BigInteger.valueOf(6), 6, 0, 1), + new BigDecimal(BigInteger.valueOf(7), 7, 0, 1), + new BigDecimal(BigInteger.valueOf(8), 8, 0, 1), + new BigDecimal(BigInteger.valueOf(9), 9, 0, 1), + new BigDecimal(BigInteger.TEN, 10, 0, 2), }; // Cache of zero scaled by 0 - 15 @@ -378,178 +380,7 @@ * @since 1.5 */ public BigDecimal(char[] in, int offset, int len) { - // protect against huge length. - if (offset+len > in.length || offset < 0) - throw new NumberFormatException(); - // This is the primary string to BigDecimal constructor; all - // incoming strings end up here; it uses explicit (inline) - // parsing for speed and generates at most one intermediate - // (temporary) object (a char[] array) for non-compact case. - - // Use locals for all fields values until completion - int prec = 0; // record precision value - int scl = 0; // record scale value - long rs = 0; // the compact value in long - BigInteger rb = null; // the inflated value in BigInteger - - // use array bounds checking to handle too-long, len == 0, - // bad offset, etc. - try { - // handle the sign - boolean isneg = false; // assume positive - if (in[offset] == '-') { - isneg = true; // leading minus means negative - offset++; - len--; - } else if (in[offset] == '+') { // leading + allowed - offset++; - len--; - } - - // should now be at numeric part of the significand - boolean dot = false; // true when there is a '.' - int cfirst = offset; // record start of integer - long exp = 0; // exponent - char c; // current character - - boolean isCompact = (len <= MAX_COMPACT_DIGITS); - // integer significand array & idx is the index to it. The array - // is ONLY used when we can't use a compact representation. - char coeff[] = isCompact ? null : new char[len]; - int idx = 0; - - for (; len > 0; offset++, len--) { - c = in[offset]; - // have digit - if ((c >= '0' && c <= '9') || Character.isDigit(c)) { - // First compact case, we need not to preserve the character - // and we can just compute the value in place. - if (isCompact) { - int digit = Character.digit(c, 10); - if (digit == 0) { - if (prec == 0) - prec = 1; - else if (rs != 0) { - rs *= 10; - ++prec; - } // else digit is a redundant leading zero - } else { - if (prec != 1 || rs != 0) - ++prec; // prec unchanged if preceded by 0s - rs = rs * 10 + digit; - } - } else { // the unscaled value is likely a BigInteger object. - if (c == '0' || Character.digit(c, 10) == 0) { - if (prec == 0) { - coeff[idx] = c; - prec = 1; - } else if (idx != 0) { - coeff[idx++] = c; - ++prec; - } // else c must be a redundant leading zero - } else { - if (prec != 1 || idx != 0) - ++prec; // prec unchanged if preceded by 0s - coeff[idx++] = c; - } - } - if (dot) - ++scl; - continue; - } - // have dot - if (c == '.') { - // have dot - if (dot) // two dots - throw new NumberFormatException(); - dot = true; - continue; - } - // exponent expected - if ((c != 'e') && (c != 'E')) - throw new NumberFormatException(); - offset++; - c = in[offset]; - len--; - boolean negexp = (c == '-'); - // optional sign - if (negexp || c == '+') { - offset++; - c = in[offset]; - len--; - } - if (len <= 0) // no exponent digits - throw new NumberFormatException(); - // skip leading zeros in the exponent - while (len > 10 && Character.digit(c, 10) == 0) { - offset++; - c = in[offset]; - len--; - } - if (len > 10) // too many nonzero exponent digits - throw new NumberFormatException(); - // c now holds first digit of exponent - for (;; len--) { - int v; - if (c >= '0' && c <= '9') { - v = c - '0'; - } else { - v = Character.digit(c, 10); - if (v < 0) // not a digit - throw new NumberFormatException(); - } - exp = exp * 10 + v; - if (len == 1) - break; // that was final character - offset++; - c = in[offset]; - } - if (negexp) // apply sign - exp = -exp; - // Next test is required for backwards compatibility - if ((int)exp != exp) // overflow - throw new NumberFormatException(); - break; // [saves a test] - } - // here when no characters left - if (prec == 0) // no digits found - throw new NumberFormatException(); - - // Adjust scale if exp is not zero. - if (exp != 0) { // had significant exponent - // Can't call checkScale which relies on proper fields value - long adjustedScale = scl - exp; - if (adjustedScale > Integer.MAX_VALUE || - adjustedScale < Integer.MIN_VALUE) - throw new NumberFormatException("Scale out of range."); - scl = (int)adjustedScale; - } - - // Remove leading zeros from precision (digits count) - if (isCompact) { - rs = isneg ? -rs : rs; - } else { - char quick[]; - if (!isneg) { - quick = (coeff.length != prec) ? - Arrays.copyOf(coeff, prec) : coeff; - } else { - quick = new char[prec + 1]; - quick[0] = '-'; - System.arraycopy(coeff, 0, quick, 1, prec); - } - rb = new BigInteger(quick); - rs = compactValFor(rb); - } - } catch (ArrayIndexOutOfBoundsException e) { - throw new NumberFormatException(); - } catch (NegativeArraySizeException e) { - throw new NumberFormatException(); - } - this.scale = scl; - this.precision = prec; - this.intCompact = rs; - this.intVal = (rs != INFLATED) ? null : rb; + this(in,offset,len,MathContext.UNLIMITED); } /** @@ -576,9 +407,254 @@ * @since 1.5 */ public BigDecimal(char[] in, int offset, int len, MathContext mc) { - this(in, offset, len); - if (mc.precision > 0) - roundThis(mc); + // protect against huge length. + if (offset + len > in.length || offset < 0) + throw new NumberFormatException("Bad offset or len arguments for char[] input."); + // This is the primary string to BigDecimal constructor; all + // incoming strings end up here; it uses explicit (inline) + // parsing for speed and generates at most one intermediate + // (temporary) object (a char[] array) for non-compact case. + + // Use locals for all fields values until completion + int prec = 0; // record precision value + int scl = 0; // record scale value + long rs = 0; // the compact value in long + BigInteger rb = null; // the inflated value in BigInteger + // use array bounds checking to handle too-long, len == 0, + // bad offset, etc. + try { + // handle the sign + boolean isneg = false; // assume positive + if (in[offset] == '-') { + isneg = true; // leading minus means negative + offset++; + len--; + } else if (in[offset] == '+') { // leading + allowed + offset++; + len--; + } + + // should now be at numeric part of the significand + boolean dot = false; // true when there is a '.' + long exp = 0; // exponent + char c; // current character + boolean isCompact = (len <= MAX_COMPACT_DIGITS); + // integer significand array & idx is the index to it. The array + // is ONLY used when we can't use a compact representation. + int idx = 0; + if (isCompact) { + // First compact case, we need not to preserve the character + // and we can just compute the value in place. + for (; len > 0; offset++, len--) { + c = in[offset]; + if ((c == '0')) { // have zero + if (prec == 0) + prec = 1; + else if (rs != 0) { + rs *= 10; + ++prec; + } // else digit is a redundant leading zero + if (dot) + ++scl; + } else if ((c >= '1' && c <= '9')) { // have digit + int digit = c - '0'; + if (prec != 1 || rs != 0) + ++prec; // prec unchanged if preceded by 0s + rs = rs * 10 + digit; + if (dot) + ++scl; + } else if (c == '.') { // have dot + // have dot + if (dot) // two dots + throw new NumberFormatException(); + dot = true; + } else if (Character.isDigit(c)) { // slow path + int digit = Character.digit(c, 10); + if (digit == 0) { + if (prec == 0) + prec = 1; + else if (rs != 0) { + rs *= 10; + ++prec; + } // else digit is a redundant leading zero + } else { + if (prec != 1 || rs != 0) + ++prec; // prec unchanged if preceded by 0s + rs = rs * 10 + digit; + } + if (dot) + ++scl; + } else if ((c == 'e') || (c == 'E')) { + exp = parseExp(in, offset, len); + // Next test is required for backwards compatibility + if ((int) exp != exp) // overflow + throw new NumberFormatException(); + break; // [saves a test] + } else { + throw new NumberFormatException(); + } + } + if (prec == 0) // no digits found + throw new NumberFormatException(); + // Adjust scale if exp is not zero. + if (exp != 0) { // had significant exponent + scl = adjustScale(scl, exp); + } + rs = isneg ? -rs : rs; + int mcp = mc.precision; + int drop = prec - mcp; // prec has range [1, MAX_INT], mcp has range [0, MAX_INT]; + // therefore, this subtract cannot overflow + if (mcp > 0 && drop > 0) { // do rounding + while (drop > 0) { + scl = checkScaleNonZero((long) scl - drop); + rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(rs); + drop = prec - mcp; + } + } + } else { + char coeff[] = new char[len]; + for (; len > 0; offset++, len--) { + c = in[offset]; + // have digit + if ((c >= '0' && c <= '9') || Character.isDigit(c)) { + // First compact case, we need not to preserve the character + // and we can just compute the value in place. + if (c == '0' || Character.digit(c, 10) == 0) { + if (prec == 0) { + coeff[idx] = c; + prec = 1; + } else if (idx != 0) { + coeff[idx++] = c; + ++prec; + } // else c must be a redundant leading zero + } else { + if (prec != 1 || idx != 0) + ++prec; // prec unchanged if preceded by 0s + coeff[idx++] = c; + } + if (dot) + ++scl; + continue; + } + // have dot + if (c == '.') { + // have dot + if (dot) // two dots + throw new NumberFormatException(); + dot = true; + continue; + } + // exponent expected + if ((c != 'e') && (c != 'E')) + throw new NumberFormatException(); + exp = parseExp(in, offset, len); + // Next test is required for backwards compatibility + if ((int) exp != exp) // overflow + throw new NumberFormatException(); + break; // [saves a test] + } + // here when no characters left + if (prec == 0) // no digits found + throw new NumberFormatException(); + // Adjust scale if exp is not zero. + if (exp != 0) { // had significant exponent + scl = adjustScale(scl, exp); + } + // Remove leading zeros from precision (digits count) + rb = new BigInteger(coeff, isneg ? -1 : 1, prec); + rs = compactValFor(rb); + int mcp = mc.precision; + if (mcp > 0 && (prec > mcp)) { + if (rs == INFLATED) { + int drop = prec - mcp; + while (drop > 0) { + scl = checkScaleNonZero((long) scl - drop); + rb = divideAndRoundByTenPow(rb, drop, mc.roundingMode.oldMode); + rs = compactValFor(rb); + if (rs != INFLATED) { + prec = longDigitLength(rs); + break; + } + prec = bigDigitLength(rb); + drop = prec - mcp; + } + } + if (rs != INFLATED) { + int drop = prec - mcp; + while (drop > 0) { + scl = checkScaleNonZero((long) scl - drop); + rs = divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(rs); + drop = prec - mcp; + } + rb = null; + } + } + } + } catch (ArrayIndexOutOfBoundsException e) { + throw new NumberFormatException(); + } catch (NegativeArraySizeException e) { + throw new NumberFormatException(); + } + this.scale = scl; + this.precision = prec; + this.intCompact = rs; + this.intVal = rb; + } + + private int adjustScale(int scl, long exp) { + long adjustedScale = scl - exp; + if (adjustedScale > Integer.MAX_VALUE || adjustedScale < Integer.MIN_VALUE) + throw new NumberFormatException("Scale out of range."); + scl = (int) adjustedScale; + return scl; + } + + /* + * parse exponent + */ + private static long parseExp(char[] in, int offset, int len){ + long exp = 0; + offset++; + char c = in[offset]; + len--; + boolean negexp = (c == '-'); + // optional sign + if (negexp || c == '+') { + offset++; + c = in[offset]; + len--; + } + if (len <= 0) // no exponent digits + throw new NumberFormatException(); + // skip leading zeros in the exponent + while (len > 10 && (c=='0' || (Character.digit(c, 10) == 0))) { + offset++; + c = in[offset]; + len--; + } + if (len > 10) // too many nonzero exponent digits + throw new NumberFormatException(); + // c now holds first digit of exponent + for (;; len--) { + int v; + if (c >= '0' && c <= '9') { + v = c - '0'; + } else { + v = Character.digit(c, 10); + if (v < 0) // not a digit + throw new NumberFormatException(); + } + exp = exp * 10 + v; + if (len == 1) + break; // that was final character + offset++; + c = in[offset]; + } + if (negexp) // apply sign + exp = -exp; + return exp; } /** @@ -754,9 +830,7 @@ * @since 1.5 */ public BigDecimal(String val, MathContext mc) { - this(val.toCharArray(), 0, val.length()); - if (mc.precision > 0) - roundThis(mc); + this(val.toCharArray(), 0, val.length(), mc); } /** @@ -804,49 +878,7 @@ * @throws NumberFormatException if {@code val} is infinite or NaN. */ public BigDecimal(double val) { - if (Double.isInfinite(val) || Double.isNaN(val)) - throw new NumberFormatException("Infinite or NaN"); - - // Translate the double into sign, exponent and significand, according - // to the formulae in JLS, Section 20.10.22. - long valBits = Double.doubleToLongBits(val); - int sign = ((valBits >> 63)==0 ? 1 : -1); - int exponent = (int) ((valBits >> 52) & 0x7ffL); - long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1 - : (valBits & ((1L<<52) - 1)) | (1L<<52)); - exponent -= 1075; - // At this point, val == sign * significand * 2**exponent. - - /* - * Special case zero to supress nonterminating normalization - * and bogus scale calculation. - */ - if (significand == 0) { - intVal = BigInteger.ZERO; - intCompact = 0; - precision = 1; - return; - } - - // Normalize - while((significand & 1) == 0) { // i.e., significand is even - significand >>= 1; - exponent++; - } - - // Calculate intVal and scale - long s = sign * significand; - BigInteger b; - if (exponent < 0) { - b = BigInteger.valueOf(5).pow(-exponent).multiply(s); - scale = -exponent; - } else if (exponent > 0) { - b = BigInteger.valueOf(2).pow(exponent).multiply(s); - } else { - b = BigInteger.valueOf(s); - } - intCompact = compactValFor(b); - intVal = (intCompact != INFLATED) ? null : b; + this(val,MathContext.UNLIMITED); } /** @@ -868,9 +900,85 @@ * @since 1.5 */ public BigDecimal(double val, MathContext mc) { - this(val); - if (mc.precision > 0) - roundThis(mc); + if (Double.isInfinite(val) || Double.isNaN(val)) + throw new NumberFormatException("Infinite or NaN"); + // Translate the double into sign, exponent and significand, according + // to the formulae in JLS, Section 20.10.22. + long valBits = Double.doubleToLongBits(val); + int sign = ((valBits >> 63) == 0 ? 1 : -1); + int exponent = (int) ((valBits >> 52) & 0x7ffL); + long significand = (exponent == 0 + ? (valBits & ((1L << 52) - 1)) << 1 + : (valBits & ((1L << 52) - 1)) | (1L << 52)); + exponent -= 1075; + // At this point, val == sign * significand * 2**exponent. + + /* + * Special case zero to supress nonterminating normalization and bogus + * scale calculation. + */ + if (significand == 0) { + this.intVal = BigInteger.ZERO; + this.scale = 0; + this.intCompact = 0; + this.precision = 1; + return; + } + // Normalize + while ((significand & 1) == 0) { // i.e., significand is even + significand >>= 1; + exponent++; + } + int scale = 0; + // Calculate intVal and scale + BigInteger intVal; + long compactVal = sign * significand; + if (exponent == 0) { + intVal = (compactVal == INFLATED) ? INFLATED_BIGINT : null; + } else { + if (exponent < 0) { + intVal = BigInteger.valueOf(5).pow(-exponent).multiply(compactVal); + scale = -exponent; + } else { // (exponent > 0) + intVal = BigInteger.valueOf(2).pow(exponent).multiply(compactVal); + } + compactVal = compactValFor(intVal); + } + int prec = 0; + int mcp = mc.precision; + if (mcp > 0) { // do rounding + int mode = mc.roundingMode.oldMode; + int drop; + if (compactVal == INFLATED) { + prec = bigDigitLength(intVal); + drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + intVal = divideAndRoundByTenPow(intVal, drop, mode); + compactVal = compactValFor(intVal); + if (compactVal != INFLATED) { + break; + } + prec = bigDigitLength(intVal); + drop = prec - mcp; + } + } + if (compactVal != INFLATED) { + prec = longDigitLength(compactVal); + drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(compactVal); + drop = prec - mcp; + } + intVal = null; + } + } + this.intVal = intVal; + this.intCompact = compactVal; + this.scale = scale; + this.precision = prec; } /** @@ -881,8 +989,9 @@ * {@code BigDecimal}. */ public BigDecimal(BigInteger val) { + scale = 0; + intVal = val; intCompact = compactValFor(val); - intVal = (intCompact != INFLATED) ? null : val; } /** @@ -898,9 +1007,7 @@ * @since 1.5 */ public BigDecimal(BigInteger val, MathContext mc) { - this(val); - if (mc.precision > 0) - roundThis(mc); + this(val,0,mc); } /** @@ -914,7 +1021,8 @@ */ public BigDecimal(BigInteger unscaledVal, int scale) { // Negative scales are now allowed - this(unscaledVal); + this.intVal = unscaledVal; + this.intCompact = compactValFor(unscaledVal); this.scale = scale; } @@ -934,10 +1042,41 @@ * @since 1.5 */ public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) { - this(unscaledVal); + long compactVal = compactValFor(unscaledVal); + int mcp = mc.precision; + int prec = 0; + if (mcp > 0) { // do rounding + int mode = mc.roundingMode.oldMode; + if (compactVal == INFLATED) { + prec = bigDigitLength(unscaledVal); + int drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + unscaledVal = divideAndRoundByTenPow(unscaledVal, drop, mode); + compactVal = compactValFor(unscaledVal); + if (compactVal != INFLATED) { + break; + } + prec = bigDigitLength(unscaledVal); + drop = prec - mcp; + } + } + if (compactVal != INFLATED) { + prec = longDigitLength(compactVal); + int drop = prec - mcp; // drop can't be more than 18 + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mode); + prec = longDigitLength(compactVal); + drop = prec - mcp; + } + unscaledVal = null; + } + } + this.intVal = unscaledVal; + this.intCompact = compactVal; this.scale = scale; - if (mc.precision > 0) - roundThis(mc); + this.precision = prec; } /** @@ -949,7 +1088,9 @@ * @since 1.5 */ public BigDecimal(int val) { - intCompact = val; + this.intCompact = val; + this.scale = 0; + this.intVal = null; } /** @@ -964,9 +1105,24 @@ * @since 1.5 */ public BigDecimal(int val, MathContext mc) { - intCompact = val; - if (mc.precision > 0) - roundThis(mc); + int mcp = mc.precision; + long compactVal = val; + int scale = 0; + int prec = 0; + if (mcp > 0) { // do rounding + prec = longDigitLength(compactVal); + int drop = prec - mcp; // drop can't be more than 18 + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(compactVal); + drop = prec - mcp; + } + } + this.intVal = null; + this.intCompact = compactVal; + this.scale = scale; + this.precision = prec; } /** @@ -978,7 +1134,8 @@ */ public BigDecimal(long val) { this.intCompact = val; - this.intVal = (val == INFLATED) ? BigInteger.valueOf(val) : null; + this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null; + this.scale = 0; } /** @@ -993,9 +1150,42 @@ * @since 1.5 */ public BigDecimal(long val, MathContext mc) { - this(val); - if (mc.precision > 0) - roundThis(mc); + int mcp = mc.precision; + int mode = mc.roundingMode.oldMode; + int prec = 0; + int scale = 0; + BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null; + if (mcp > 0) { // do rounding + if (val == INFLATED) { + prec = 19; + int drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + intVal = divideAndRoundByTenPow(intVal, drop, mode); + val = compactValFor(intVal); + if (val != INFLATED) { + break; + } + prec = bigDigitLength(intVal); + drop = prec - mcp; + } + } + if (val != INFLATED) { + prec = longDigitLength(val); + int drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(val); + drop = prec - mcp; + } + intVal = null; + } + } + this.intVal = intVal; + this.intCompact = val; + this.scale = scale; + this.precision = prec; } // Static Factory Methods @@ -1016,13 +1206,10 @@ if (scale == 0) return valueOf(unscaledVal); else if (unscaledVal == 0) { - if (scale > 0 && scale < ZERO_SCALED_BY.length) - return ZERO_SCALED_BY[scale]; - else - return new BigDecimal(BigInteger.ZERO, 0, scale, 1); + return zeroValueOf(scale); } return new BigDecimal(unscaledVal == INFLATED ? - BigInteger.valueOf(unscaledVal) : null, + INFLATED_BIGINT : null, unscaledVal, scale, 0); } @@ -1041,7 +1228,34 @@ return zeroThroughTen[(int)val]; else if (val != INFLATED) return new BigDecimal(null, val, 0, 0); - return new BigDecimal(BigInteger.valueOf(val), val, 0, 0); + return new BigDecimal(INFLATED_BIGINT, val, 0, 0); + } + + static BigDecimal valueOf(long unscaledVal, int scale, int prec) { + if (scale == 0 && unscaledVal >= 0 && unscaledVal < zeroThroughTen.length) { + return zeroThroughTen[(int) unscaledVal]; + } else if (unscaledVal == 0) { + return zeroValueOf(scale); + } + return new BigDecimal(unscaledVal == INFLATED ? INFLATED_BIGINT : null, + unscaledVal, scale, prec); + } + + static BigDecimal valueOf(BigInteger intVal, int scale, int prec) { + long val = compactValFor(intVal); + if (val == 0) { + return zeroValueOf(scale); + } else if (scale == 0 && val >= 0 && val < zeroThroughTen.length) { + return zeroThroughTen[(int) val]; + } + return new BigDecimal(intVal, val, scale, prec); + } + + static BigDecimal zeroValueOf(int scale) { + if (scale >= 0 && scale < ZERO_SCALED_BY.length) + return ZERO_SCALED_BY[scale]; + else + return new BigDecimal(BigInteger.ZERO, 0, scale, 1); } /** @@ -1079,42 +1293,19 @@ * @return {@code this + augend} */ public BigDecimal add(BigDecimal augend) { - long xs = this.intCompact; - long ys = augend.intCompact; - BigInteger fst = (xs != INFLATED) ? null : this.intVal; - BigInteger snd = (ys != INFLATED) ? null : augend.intVal; - int rscale = this.scale; - - long sdiff = (long)rscale - augend.scale; - if (sdiff != 0) { - if (sdiff < 0) { - int raise = checkScale(-sdiff); - rscale = augend.scale; - if (xs == INFLATED || - (xs = longMultiplyPowerTen(xs, raise)) == INFLATED) - fst = bigMultiplyPowerTen(raise); + if (this.intCompact != INFLATED) { + if ((augend.intCompact != INFLATED)) { + return add(this.intCompact, this.scale, augend.intCompact, augend.scale); } else { - int raise = augend.checkScale(sdiff); - if (ys == INFLATED || - (ys = longMultiplyPowerTen(ys, raise)) == INFLATED) - snd = augend.bigMultiplyPowerTen(raise); + return add(this.intCompact, this.scale, augend.intVal, augend.scale); + } + } else { + if ((augend.intCompact != INFLATED)) { + return add(augend.intCompact, augend.scale, this.intVal, this.scale); + } else { + return add(this.intVal, this.scale, augend.intVal, augend.scale); } } - if (xs != INFLATED && ys != INFLATED) { - long sum = xs + ys; - // See "Hacker's Delight" section 2-12 for explanation of - // the overflow test. - if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) // not overflowed - return BigDecimal.valueOf(sum, rscale); - } - if (fst == null) - fst = BigInteger.valueOf(xs); - if (snd == null) - snd = BigInteger.valueOf(ys); - BigInteger sum = fst.add(snd); - return (fst.signum == snd.signum) ? - new BigDecimal(sum, INFLATED, rscale, 0) : - new BigDecimal(sum, rscale); } /** @@ -1136,10 +1327,6 @@ return add(augend); BigDecimal lhs = this; - // Could optimize if values are compact - this.inflate(); - augend.inflate(); - // If either number is zero then the other number, rounded and // scaled if necessary, is used as the result. { @@ -1150,20 +1337,14 @@ int preferredScale = Math.max(lhs.scale(), augend.scale()); BigDecimal result; - // Could use a factory for zero instead of a new object if (lhsIsZero && augendIsZero) - return new BigDecimal(BigInteger.ZERO, 0, preferredScale, 0); - + return zeroValueOf(preferredScale); result = lhsIsZero ? doRound(augend, mc) : doRound(lhs, mc); if (result.scale() == preferredScale) return result; else if (result.scale() > preferredScale) { - BigDecimal scaledResult = - new BigDecimal(result.intVal, result.intCompact, - result.scale, 0); - scaledResult.stripZerosToMatchScale(preferredScale); - return scaledResult; + return stripZerosToMatchScale(result.intVal, result.intCompact, result.scale, preferredScale); } else { // result.scale < preferredScale int precisionDiff = mc.precision - result.precision(); int scaleDiff = preferredScale - result.scale(); @@ -1176,17 +1357,14 @@ } } - long padding = (long)lhs.scale - augend.scale; - if (padding != 0) { // scales differ; alignment needed + long padding = (long) lhs.scale - augend.scale; + if (padding != 0) { // scales differ; alignment needed BigDecimal arg[] = preAlign(lhs, augend, padding, mc); matchScale(arg); - lhs = arg[0]; + lhs = arg[0]; augend = arg[1]; } - - BigDecimal d = new BigDecimal(lhs.inflate().add(augend.inflate()), - lhs.scale); - return doRound(d, mc); + return doRound(lhs.inflated().add(augend.inflated()), lhs.scale, mc); } /** @@ -1211,27 +1389,26 @@ * that the number of digits of the smaller operand could be * reduced even though the significands partially overlapped. */ - private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend, - long padding, MathContext mc) { + private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend, long padding, MathContext mc) { assert padding != 0; BigDecimal big; BigDecimal small; - if (padding < 0) { // lhs is big; augend is small - big = lhs; + if (padding < 0) { // lhs is big; augend is small + big = lhs; small = augend; - } else { // lhs is small; augend is big - big = augend; + } else { // lhs is small; augend is big + big = augend; small = lhs; } /* - * This is the estimated scale of an ulp of the result; it - * assumes that the result doesn't have a carry-out on a true - * add (e.g. 999 + 1 => 1000) or any subtractive cancellation - * on borrowing (e.g. 100 - 1.2 => 98.8) + * This is the estimated scale of an ulp of the result; it assumes that + * the result doesn't have a carry-out on a true add (e.g. 999 + 1 => + * 1000) or any subtractive cancellation on borrowing (e.g. 100 - 1.2 => + * 98.8) */ - long estResultUlpScale = (long)big.scale - big.precision() + mc.precision; + long estResultUlpScale = (long) big.scale - big.precision() + mc.precision; /* * The low-order digit position of big is big.scale(). This @@ -1242,11 +1419,10 @@ * disjoint *and* the digit positions of small should not be * directly visible in the result. */ - long smallHighDigitPos = (long)small.scale - small.precision() + 1; - if (smallHighDigitPos > big.scale + 2 && // big and small disjoint + long smallHighDigitPos = (long) small.scale - small.precision() + 1; + if (smallHighDigitPos > big.scale + 2 && // big and small disjoint smallHighDigitPos > estResultUlpScale + 2) { // small digits not visible - small = BigDecimal.valueOf(small.signum(), - this.checkScale(Math.max(big.scale, estResultUlpScale) + 3)); + small = BigDecimal.valueOf(small.signum(), this.checkScale(Math.max(big.scale, estResultUlpScale) + 3)); } // Since addition is symmetric, preserving input order in @@ -1264,7 +1440,22 @@ * @return {@code this - subtrahend} */ public BigDecimal subtract(BigDecimal subtrahend) { - return add(subtrahend.negate()); + if (this.intCompact != INFLATED) { + if ((subtrahend.intCompact != INFLATED)) { + return add(this.intCompact, this.scale, -subtrahend.intCompact, subtrahend.scale); + } else { + return add(this.intCompact, this.scale, subtrahend.intVal.negate(), subtrahend.scale); + } + } else { + if ((subtrahend.intCompact != INFLATED)) { + // Pair of subtrahend values given before pair of + // values from this BigDecimal to avoid need for + // method overloading on the specialized add method + return add(-subtrahend.intCompact, subtrahend.scale, this.intVal, this.scale); + } else { + return add(this.intVal, this.scale, subtrahend.intVal.negate(), subtrahend.scale); + } + } } /** @@ -1282,11 +1473,10 @@ * @since 1.5 */ public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) { - BigDecimal nsubtrahend = subtrahend.negate(); if (mc.precision == 0) - return add(nsubtrahend); + return subtract(subtrahend); // share the special rounding code in add() - return add(nsubtrahend, mc); + return add(subtrahend.negate(), mc); } /** @@ -1298,37 +1488,20 @@ * @return {@code this * multiplicand} */ public BigDecimal multiply(BigDecimal multiplicand) { - long x = this.intCompact; - long y = multiplicand.intCompact; - int productScale = checkScale((long)scale + multiplicand.scale); - - // Might be able to do a more clever check incorporating the - // inflated check into the overflow computation. - if (x != INFLATED && y != INFLATED) { - /* - * If the product is not an overflowed value, continue - * to use the compact representation. if either of x or y - * is INFLATED, the product should also be regarded as - * an overflow. Before using the overflow test suggested in - * "Hacker's Delight" section 2-12, we perform quick checks - * using the precision information to see whether the overflow - * would occur since division is expensive on most CPUs. - */ - long product = x * y; - long prec = this.precision() + multiplicand.precision(); - if (prec < 19 || (prec < 21 && (y == 0 || product / y == x))) - return BigDecimal.valueOf(product, productScale); - return new BigDecimal(BigInteger.valueOf(x).multiply(y), INFLATED, - productScale, 0); + int productScale = checkScale((long) scale + multiplicand.scale); + if (this.intCompact != INFLATED) { + if ((multiplicand.intCompact != INFLATED)) { + return multiply(this.intCompact, multiplicand.intCompact, productScale); + } else { + return multiply(this.intCompact, multiplicand.intVal, productScale); + } + } else { + if ((multiplicand.intCompact != INFLATED)) { + return multiply(multiplicand.intCompact, this.intVal, productScale); + } else { + return multiply(this.intVal, multiplicand.intVal, productScale); + } } - BigInteger rb; - if (x == INFLATED && y == INFLATED) - rb = this.intVal.multiply(multiplicand.intVal); - else if (x != INFLATED) - rb = multiplicand.intVal.multiply(x); - else - rb = this.intVal.multiply(y); - return new BigDecimal(rb, INFLATED, productScale, 0); } /** @@ -1345,7 +1518,20 @@ public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) { if (mc.precision == 0) return multiply(multiplicand); - return doRound(this.multiply(multiplicand), mc); + int productScale = checkScale((long) scale + multiplicand.scale); + if (this.intCompact != INFLATED) { + if ((multiplicand.intCompact != INFLATED)) { + return multiplyAndRound(this.intCompact, multiplicand.intCompact, productScale, mc); + } else { + return multiplyAndRound(this.intCompact, multiplicand.intVal, productScale, mc); + } + } else { + if ((multiplicand.intCompact != INFLATED)) { + return multiplyAndRound(multiplicand.intCompact, this.intVal, productScale, mc); + } else { + return multiplyAndRound(this.intVal, multiplicand.intVal, productScale, mc); + } + } } /** @@ -1377,120 +1563,21 @@ * @see #ROUND_UNNECESSARY */ public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) { - /* - * IMPLEMENTATION NOTE: This method *must* return a new object - * since divideAndRound uses divide to generate a value whose - * scale is then modified. - */ if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); - /* - * Rescale dividend or divisor (whichever can be "upscaled" to - * produce correctly scaled quotient). - * Take care to detect out-of-range scales - */ - BigDecimal dividend = this; - if (checkScale((long)scale + divisor.scale) > this.scale) - dividend = this.setScale(scale + divisor.scale, ROUND_UNNECESSARY); - else - divisor = divisor.setScale(checkScale((long)this.scale - scale), - ROUND_UNNECESSARY); - return divideAndRound(dividend.intCompact, dividend.intVal, - divisor.intCompact, divisor.intVal, - scale, roundingMode, scale); - } - - /** - * Internally used for division operation. The dividend and divisor are - * passed both in {@code long} format and {@code BigInteger} format. The - * returned {@code BigDecimal} object is the quotient whose scale is set to - * the passed in scale. If the remainder is not zero, it will be rounded - * based on the passed in roundingMode. Also, if the remainder is zero and - * the last parameter, i.e. preferredScale is NOT equal to scale, the - * trailing zeros of the result is stripped to match the preferredScale. - */ - private static BigDecimal divideAndRound(long ldividend, BigInteger bdividend, - long ldivisor, BigInteger bdivisor, - int scale, int roundingMode, - int preferredScale) { - boolean isRemainderZero; // record remainder is zero or not - int qsign; // quotient sign - long q = 0, r = 0; // store quotient & remainder in long - MutableBigInteger mq = null; // store quotient - MutableBigInteger mr = null; // store remainder - MutableBigInteger mdivisor = null; - boolean isLongDivision = (ldividend != INFLATED && ldivisor != INFLATED); - if (isLongDivision) { - q = ldividend / ldivisor; - if (roundingMode == ROUND_DOWN && scale == preferredScale) - return new BigDecimal(null, q, scale, 0); - r = ldividend % ldivisor; - isRemainderZero = (r == 0); - qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1; + if (this.intCompact != INFLATED) { + if ((divisor.intCompact != INFLATED)) { + return divide(this.intCompact, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode); + } else { + return divide(this.intCompact, this.scale, divisor.intVal, divisor.scale, scale, roundingMode); + } } else { - if (bdividend == null) - bdividend = BigInteger.valueOf(ldividend); - // Descend into mutables for faster remainder checks - MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); - mq = new MutableBigInteger(); - if (ldivisor != INFLATED) { - r = mdividend.divide(ldivisor, mq); - isRemainderZero = (r == 0); - qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; + if ((divisor.intCompact != INFLATED)) { + return divide(this.intVal, this.scale, divisor.intCompact, divisor.scale, scale, roundingMode); } else { - mdivisor = new MutableBigInteger(bdivisor.mag); - mr = mdividend.divide(mdivisor, mq); - isRemainderZero = mr.isZero(); - qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1; + return divide(this.intVal, this.scale, divisor.intVal, divisor.scale, scale, roundingMode); } } - boolean increment = false; - if (!isRemainderZero) { - int cmpFracHalf; - /* Round as appropriate */ - if (roundingMode == ROUND_UNNECESSARY) { // Rounding prohibited - throw new ArithmeticException("Rounding necessary"); - } else if (roundingMode == ROUND_UP) { // Away from zero - increment = true; - } else if (roundingMode == ROUND_DOWN) { // Towards zero - increment = false; - } else if (roundingMode == ROUND_CEILING) { // Towards +infinity - increment = (qsign > 0); - } else if (roundingMode == ROUND_FLOOR) { // Towards -infinity - increment = (qsign < 0); - } else { - if (isLongDivision || ldivisor != INFLATED) { - if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) { - cmpFracHalf = 1; // 2 * r can't fit into long - } else { - cmpFracHalf = longCompareMagnitude(2 * r, ldivisor); - } - } else { - cmpFracHalf = mr.compareHalf(mdivisor); - } - if (cmpFracHalf < 0) - increment = false; // We're closer to higher digit - else if (cmpFracHalf > 0) // We're closer to lower digit - increment = true; - else if (roundingMode == ROUND_HALF_UP) - increment = true; - else if (roundingMode == ROUND_HALF_DOWN) - increment = false; - else // roundingMode == ROUND_HALF_EVEN, true iff quotient is odd - increment = isLongDivision ? (q & 1L) != 0L : mq.isOdd(); - } - } - BigDecimal res; - if (isLongDivision) - res = new BigDecimal(null, (increment ? q + qsign : q), scale, 0); - else { - if (increment) - mq.add(MutableBigInteger.ONE); - res = mq.toBigDecimal(qsign, scale); - } - if (isRemainderZero && preferredScale != scale) - res.stripZerosToMatchScale(preferredScale); - return res; } /** @@ -1541,7 +1628,7 @@ * @see #ROUND_UNNECESSARY */ public BigDecimal divide(BigDecimal divisor, int roundingMode) { - return this.divide(divisor, scale, roundingMode); + return this.divide(divisor, scale, roundingMode); } /** @@ -1588,15 +1675,11 @@ } // Calculate preferred scale - int preferredScale = saturateLong((long)this.scale - divisor.scale); - if (this.signum() == 0) // 0/y - return (preferredScale >= 0 && - preferredScale < ZERO_SCALED_BY.length) ? - ZERO_SCALED_BY[preferredScale] : - BigDecimal.valueOf(0, preferredScale); + int preferredScale = saturateLong((long) this.scale - divisor.scale); + + if (this.signum() == 0) // 0/y + return zeroValueOf(preferredScale); else { - this.inflate(); - divisor.inflate(); /* * If the quotient this/divisor has a terminating decimal * expansion, the expansion can have no more than @@ -1623,7 +1706,6 @@ // the desired one by removing trailing zeros; since the // exact divide method does not have an explicit digit // limit, we can add zeros too. - if (preferredScale > quotientScale) return quotient.setScale(preferredScale, ROUND_UNNECESSARY); @@ -1668,38 +1750,23 @@ throw new ArithmeticException("Division undefined"); // NaN throw new ArithmeticException("Division by zero"); } - if (dividend.signum() == 0) // 0/y - return new BigDecimal(BigInteger.ZERO, 0, - saturateLong(preferredScale), 1); - - // Normalize dividend & divisor so that both fall into [0.1, 0.999...] + if (dividend.signum() == 0) // 0/y + return zeroValueOf(saturateLong(preferredScale)); int xscale = dividend.precision(); int yscale = divisor.precision(); - dividend = new BigDecimal(dividend.intVal, dividend.intCompact, - xscale, xscale); - divisor = new BigDecimal(divisor.intVal, divisor.intCompact, - yscale, yscale); - if (dividend.compareMagnitude(divisor) > 0) // satisfy constraint (b) - yscale = divisor.scale -= 1; // [that is, divisor *= 10] - - // In order to find out whether the divide generates the exact result, - // we avoid calling the above divide method. 'quotient' holds the - // return BigDecimal object whose scale will be set to 'scl'. - BigDecimal quotient; - int scl = checkScale(preferredScale + yscale - xscale + mcp); - if (checkScale((long)mcp + yscale) > xscale) - dividend = dividend.setScale(mcp + yscale, ROUND_UNNECESSARY); - else - divisor = divisor.setScale(checkScale((long)xscale - mcp), - ROUND_UNNECESSARY); - quotient = divideAndRound(dividend.intCompact, dividend.intVal, - divisor.intCompact, divisor.intVal, - scl, mc.roundingMode.oldMode, - checkScale(preferredScale)); - // doRound, here, only affects 1000000000 case. - quotient = doRound(quotient, mc); - - return quotient; + if(dividend.intCompact!=INFLATED) { + if(divisor.intCompact!=INFLATED) { + return divide(dividend.intCompact, xscale, divisor.intCompact, yscale, preferredScale, mc); + } else { + return divide(dividend.intCompact, xscale, divisor.intVal, yscale, preferredScale, mc); + } + } else { + if(divisor.intCompact!=INFLATED) { + return divide(dividend.intVal, xscale, divisor.intCompact, yscale, preferredScale, mc); + } else { + return divide(dividend.intVal, xscale, divisor.intVal, yscale, preferredScale, mc); + } + } } /** @@ -1715,13 +1782,13 @@ */ public BigDecimal divideToIntegralValue(BigDecimal divisor) { // Calculate preferred scale - int preferredScale = saturateLong((long)this.scale - divisor.scale); + int preferredScale = saturateLong((long) this.scale - divisor.scale); if (this.compareMagnitude(divisor) < 0) { // much faster when this << divisor - return BigDecimal.valueOf(0, preferredScale); + return zeroValueOf(preferredScale); } - if(this.signum() == 0 && divisor.signum() != 0) + if (this.signum() == 0 && divisor.signum() != 0) return this.setScale(preferredScale, ROUND_UNNECESSARY); // Perform a divide with enough digits to round to a correct @@ -1735,13 +1802,14 @@ RoundingMode.DOWN)); if (quotient.scale > 0) { quotient = quotient.setScale(0, RoundingMode.DOWN); - quotient.stripZerosToMatchScale(preferredScale); + quotient = stripZerosToMatchScale(quotient.intVal, quotient.intCompact, quotient.scale, preferredScale); } if (quotient.scale < preferredScale) { // pad with zeros if necessary quotient = quotient.setScale(preferredScale, ROUND_UNNECESSARY); } + return quotient; } @@ -1766,8 +1834,8 @@ * @author Joseph D. Darcy */ public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) { - if (mc.precision == 0 || // exact result - (this.compareMagnitude(divisor) < 0) ) // zero result + if (mc.precision == 0 || // exact result + (this.compareMagnitude(divisor) < 0)) // zero result return divideToIntegralValue(divisor); // Calculate preferred scale @@ -1780,8 +1848,7 @@ * digits. Next, remove any fractional digits from the * quotient and adjust the scale to the preferred value. */ - BigDecimal result = this. - divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN)); + BigDecimal result = this.divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN)); if (result.scale() < 0) { /* @@ -1811,8 +1878,7 @@ return result.setScale(result.scale() + Math.min(precisionDiff, preferredScale - result.scale) ); } else { - result.stripZerosToMatchScale(preferredScale); - return result; + return stripZerosToMatchScale(result.intVal,result.intCompact,result.scale,preferredScale); } } @@ -1954,8 +2020,7 @@ // No need to calculate pow(n) if result will over/underflow. // Don't attempt to support "supernormal" numbers. int newScale = checkScale((long)scale * n); - this.inflate(); - return new BigDecimal(intVal.pow(n), newScale); + return new BigDecimal(this.inflated().pow(n), newScale); } @@ -2016,12 +2081,10 @@ throw new ArithmeticException("Invalid operation"); if (n == 0) return ONE; // x**0 == 1 in X3.274 - this.inflate(); BigDecimal lhs = this; MathContext workmc = mc; // working settings int mag = Math.abs(n); // magnitude of n if (mc.precision > 0) { - int elength = longDigitLength(mag); // length of n in digits if (elength > mc.precision) // X3.274 rule throw new ArithmeticException("Invalid operation"); @@ -2044,7 +2107,7 @@ // else (!seenbit) no point in squaring ONE } // if negative n, calculate the reciprocal using working precision - if (n<0) // [hence mc.precision>0] + if (n < 0) // [hence mc.precision>0] acc=ONE.divide(acc, workmc); // round to final precision and strip zeros return doRound(acc, mc); @@ -2083,14 +2146,11 @@ * @return {@code -this}. */ public BigDecimal negate() { - BigDecimal result; - if (intCompact != INFLATED) - result = BigDecimal.valueOf(-intCompact, scale); - else { - result = new BigDecimal(intVal.negate(), scale); - result.precision = precision; + if (intCompact == INFLATED) { + return new BigDecimal(intVal.negate(), INFLATED, scale, precision); + } else { + return valueOf(-intCompact, scale, precision); } - return result; } /** @@ -2186,7 +2246,7 @@ if (s != INFLATED) result = longDigitLength(s); else - result = bigDigitLength(inflate()); + result = bigDigitLength(intVal); precision = result; } return result; @@ -2202,7 +2262,7 @@ * @since 1.2 */ public BigInteger unscaledValue() { - return this.inflate(); + return this.inflated(); } // Rounding Modes @@ -2383,29 +2443,41 @@ if (newScale == oldScale) // easy case return this; if (this.signum() == 0) // zero can have any scale - return BigDecimal.valueOf(0, newScale); - - long rs = this.intCompact; - if (newScale > oldScale) { - int raise = checkScale((long)newScale - oldScale); - BigInteger rb = null; - if (rs == INFLATED || - (rs = longMultiplyPowerTen(rs, raise)) == INFLATED) - rb = bigMultiplyPowerTen(raise); - return new BigDecimal(rb, rs, newScale, - (precision > 0) ? precision + raise : 0); + return zeroValueOf(newScale); + if(this.intCompact!=INFLATED) { + long rs = this.intCompact; + if (newScale > oldScale) { + int raise = checkScale((long) newScale - oldScale); + if ((rs = longMultiplyPowerTen(rs, raise)) != INFLATED) { + return valueOf(rs,newScale); + } + BigInteger rb = bigMultiplyPowerTen(raise); + return new BigDecimal(rb, INFLATED, newScale, (precision > 0) ? precision + raise : 0); + } else { + // newScale < oldScale -- drop some digits + // Can't predict the precision due to the effect of rounding. + int drop = checkScale((long) oldScale - newScale); + if (drop < LONG_TEN_POWERS_TABLE.length) { + return divideAndRound(rs, LONG_TEN_POWERS_TABLE[drop], newScale, roundingMode, newScale); + } else { + return divideAndRound(this.inflated(), bigTenToThe(drop), newScale, roundingMode, newScale); + } + } } else { - // newScale < oldScale -- drop some digits - // Can't predict the precision due to the effect of rounding. - int drop = checkScale((long)oldScale - newScale); - if (drop < LONG_TEN_POWERS_TABLE.length) - return divideAndRound(rs, this.intVal, - LONG_TEN_POWERS_TABLE[drop], null, - newScale, roundingMode, newScale); - else - return divideAndRound(rs, this.intVal, - INFLATED, bigTenToThe(drop), - newScale, roundingMode, newScale); + if (newScale > oldScale) { + int raise = checkScale((long) newScale - oldScale); + BigInteger rb = bigMultiplyPowerTen(this.intVal,raise); + return new BigDecimal(rb, INFLATED, newScale, (precision > 0) ? precision + raise : 0); + } else { + // newScale < oldScale -- drop some digits + // Can't predict the precision due to the effect of rounding. + int drop = checkScale((long) oldScale - newScale); + if (drop < LONG_TEN_POWERS_TABLE.length) + return divideAndRound(this.intVal, LONG_TEN_POWERS_TABLE[drop], newScale, roundingMode, + newScale); + else + return divideAndRound(this.intVal, bigTenToThe(drop), newScale, roundingMode, newScale); + } } } @@ -2524,10 +2596,11 @@ * @since 1.5 */ public BigDecimal stripTrailingZeros() { - this.inflate(); - BigDecimal result = new BigDecimal(intVal, scale); - result.stripZerosToMatchScale(Long.MIN_VALUE); - return result; + if(intCompact!=INFLATED) { + return createAndStripZerosToMatchScale(intCompact, scale, Long.MIN_VALUE); + } else { + return createAndStripZerosToMatchScale(intVal, scale, Long.MIN_VALUE); + } } // Comparison Operations @@ -2647,7 +2720,7 @@ } else if (xs != INFLATED) return xs == compactValFor(this.intVal); - return this.inflate().equals(xDec.inflate()); + return this.inflated().equals(xDec.inflated()); } /** @@ -2872,13 +2945,38 @@ * @see #toEngineeringString() */ public String toPlainString() { - BigDecimal bd = this; - if (bd.scale < 0) - bd = bd.setScale(0); - bd.inflate(); - if (bd.scale == 0) // No decimal point - return bd.intVal.toString(); - return bd.getValueString(bd.signum(), bd.intVal.abs().toString(), bd.scale); + if(scale==0) { + if(intCompact!=INFLATED) { + return Long.toString(intCompact); + } else { + return intVal.toString(); + } + } + if(this.scale<0) { // No decimal point + if(signum()==0) { + return "0"; + } + int tailingZeros = checkScaleNonZero((-(long)scale)); + StringBuilder buf; + if(intCompact!=INFLATED) { + buf = new StringBuilder(20+tailingZeros); + buf.append(intCompact); + } else { + String str = intVal.toString(); + buf = new StringBuilder(str.length()+tailingZeros); + buf.append(str); + } + for (int i = 0; i < tailingZeros; i++) + buf.append('0'); + return buf.toString(); + } + String str ; + if(intCompact!=INFLATED) { + str = Long.toString(Math.abs(intCompact)); + } else { + str = intVal.abs().toString(); + } + return getValueString(signum(), str, scale); } /* Returns a digit.digit string */ @@ -2922,7 +3020,7 @@ */ public BigInteger toBigInteger() { // force to an integer, quietly - return this.setScale(0, ROUND_DOWN).inflate(); + return this.setScale(0, ROUND_DOWN).inflated(); } /** @@ -2937,7 +3035,7 @@ */ public BigInteger toBigIntegerExact() { // round to an integer, with Exception if decimal part non-0 - return this.setScale(0, ROUND_UNNECESSARY).inflate(); + return this.setScale(0, ROUND_UNNECESSARY).inflated(); } /** @@ -2990,7 +3088,7 @@ BigDecimal num = this.setScale(0, ROUND_UNNECESSARY); if (num.precision() >= 19) // need to check carefully LongOverflow.check(num); - return num.inflate().longValue(); + return num.inflated().longValue(); } private static class LongOverflow { @@ -3001,9 +3099,9 @@ private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE); public static void check(BigDecimal num) { - num.inflate(); - if ((num.intVal.compareTo(LONGMIN) < 0) || - (num.intVal.compareTo(LONGMAX) > 0)) + BigInteger intVal = num.inflated(); + if (intVal.compareTo(LONGMIN) < 0 || + intVal.compareTo(LONGMAX) > 0) throw new java.lang.ArithmeticException("Overflow"); } } @@ -3107,8 +3205,28 @@ * @return this {@code BigDecimal} converted to a {@code float}. */ public float floatValue(){ - if (scale == 0 && intCompact != INFLATED) + if(intCompact != INFLATED) { + if (scale == 0) { return (float)intCompact; + } else { + /* + * If both intCompact and the scale can be exactly + * represented as float values, perform a single float + * multiply or divide to compute the (properly + * rounded) result. + */ + if (Math.abs(intCompact) < 1L<<22 ) { + // Don't have too guard against + // Math.abs(MIN_VALUE) because of outer check + // against INFLATED. + if (scale > 0 && scale < float10pow.length) { + return (float)intCompact / float10pow[scale]; + } else if (scale < 0 && scale > -float10pow.length) { + return (float)intCompact * float10pow[-scale]; + } + } + } + } // Somewhat inefficient, but guaranteed to work. return Float.parseFloat(this.toString()); } @@ -3130,13 +3248,53 @@ * @return this {@code BigDecimal} converted to a {@code double}. */ public double doubleValue(){ - if (scale == 0 && intCompact != INFLATED) - return (double)intCompact; + if(intCompact != INFLATED) { + if (scale == 0) { + return (double)intCompact; + } else { + /* + * If both intCompact and the scale can be exactly + * represented as double values, perform a single + * double multiply or divide to compute the (properly + * rounded) result. + */ + if (Math.abs(intCompact) < 1L<<52 ) { + // Don't have too guard against + // Math.abs(MIN_VALUE) because of outer check + // against INFLATED. + if (scale > 0 && scale < double10pow.length) { + return (double)intCompact / double10pow[scale]; + } else if (scale < 0 && scale > -double10pow.length) { + return (double)intCompact * double10pow[-scale]; + } + } + } + } // Somewhat inefficient, but guaranteed to work. return Double.parseDouble(this.toString()); } /** + * Powers of 10 which can be represented exactly in {@code + * double}. + */ + private static final double double10pow[] = { + 1.0e0, 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, + 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, 1.0e11, + 1.0e12, 1.0e13, 1.0e14, 1.0e15, 1.0e16, 1.0e17, + 1.0e18, 1.0e19, 1.0e20, 1.0e21, 1.0e22 + }; + + /** + * Powers of 10 which can be represented exactly in {@code + * float}. + */ + private static final float float10pow[] = { + 1.0e0f, 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, + 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f + }; + + /** * Returns the size of an ulp, a unit in the last place, of this * {@code BigDecimal}. An ulp of a nonzero {@code BigDecimal} * value is the positive distance between this value and the @@ -3151,10 +3309,9 @@ * @since 1.5 */ public BigDecimal ulp() { - return BigDecimal.valueOf(1, this.scale()); + return BigDecimal.valueOf(1, this.scale(), 1); } - // Private class to build a string representation for BigDecimal object. // "StringBuilderHelper" is constructed as a thread local variable so it is // thread safe. The StringBuilder field acts as a buffer to hold the temporary @@ -3268,6 +3425,15 @@ return (intCompact != INFLATED) ? Long.toString(intCompact): intVal.toString(); + if (scale == 2 && + intCompact >= 0 && intCompact < Integer.MAX_VALUE) { + // currency fast path + int lowInt = (int)intCompact % 100; + int highInt = (int)intCompact / 100; + return (Integer.toString(highInt) + '.' + + StringBuilderHelper.DIGIT_TENS[lowInt] + + StringBuilderHelper.DIGIT_ONES[lowInt]) ; + } StringBuilderHelper sbHelper = threadLocalStringBuilderHelper.get(); char[] coeff; @@ -3377,7 +3543,7 @@ tenpow[0] = '1'; for (int i = 1; i <= n; i++) tenpow[i] = '0'; - return new BigInteger(tenpow); + return new BigInteger(tenpow,1, tenpow.length); } /** @@ -3433,11 +3599,16 @@ 1000000000000000000L // 18 / 10^18 }; - private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {BigInteger.ONE, - BigInteger.valueOf(10), BigInteger.valueOf(100), - BigInteger.valueOf(1000), BigInteger.valueOf(10000), - BigInteger.valueOf(100000), BigInteger.valueOf(1000000), - BigInteger.valueOf(10000000), BigInteger.valueOf(100000000), + private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = { + BigInteger.ONE, + BigInteger.valueOf(10), + BigInteger.valueOf(100), + BigInteger.valueOf(1000), + BigInteger.valueOf(10000), + BigInteger.valueOf(100000), + BigInteger.valueOf(1000000), + BigInteger.valueOf(10000000), + BigInteger.valueOf(100000000), BigInteger.valueOf(1000000000), BigInteger.valueOf(10000000000L), BigInteger.valueOf(100000000000L), @@ -3502,7 +3673,7 @@ */ private BigInteger bigMultiplyPowerTen(int n) { if (n <= 0) - return this.inflate(); + return this.inflated(); if (intCompact != INFLATED) return bigTenToThe(n).multiply(intCompact); @@ -3511,12 +3682,13 @@ } /** - * Assign appropriate BigInteger to intVal field if intVal is + * Returns appropriate BigInteger from intVal field if intVal is * null, i.e. the compact representation is in use. */ - private BigInteger inflate() { - if (intVal == null) - intVal = BigInteger.valueOf(intCompact); + private BigInteger inflated() { + if (intVal == null) { + return BigInteger.valueOf(intCompact); + } return intVal; } @@ -3543,6 +3715,30 @@ } } + private static class UnsafeHolder { + private static final sun.misc.Unsafe unsafe; + private static final long intCompactOffset; + private static final long intValOffset; + static { + try { + unsafe = sun.misc.Unsafe.getUnsafe(); + intCompactOffset = unsafe.objectFieldOffset + (BigDecimal.class.getDeclaredField("intCompact")); + intValOffset = unsafe.objectFieldOffset + (BigDecimal.class.getDeclaredField("intVal")); + } catch (Exception ex) { + throw new ExceptionInInitializerError(ex); + } + } + static void setIntCompactVolatile(BigDecimal bd, long val) { + unsafe.putLongVolatile(bd, intCompactOffset, val); + } + + static void setIntValVolatile(BigDecimal bd, BigInteger val) { + unsafe.putObjectVolatile(bd, intValOffset, val); + } + } + /** * Reconstitute the {@code BigDecimal} instance from a stream (that is, * deserialize it). @@ -3559,7 +3755,7 @@ throw new java.io.StreamCorruptedException(message); // [all values of scale are now allowed] } - intCompact = compactValFor(intVal); + UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal)); } /** @@ -3570,13 +3766,12 @@ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Must inflate to maintain compatible serial form. - this.inflate(); - - // Write proper fields + if (this.intVal == null) + UnsafeHolder.setIntValVolatile(this, BigInteger.valueOf(this.intCompact)); + // Could reset intVal back to null if it has to be set. s.defaultWriteObject(); } - /** * Returns the length of the absolute value of a {@code long}, in decimal * digits. @@ -3584,36 +3779,29 @@ * @param x the {@code long} * @return the length of the unscaled value, in deciaml digits. */ - private static int longDigitLength(long x) { + static int longDigitLength(long x) { /* * As described in "Bit Twiddling Hacks" by Sean Anderson, * (http://graphics.stanford.edu/~seander/bithacks.html) - * integer log 10 of x is within 1 of - * (1233/4096)* (1 + integer log 2 of x). - * The fraction 1233/4096 approximates log10(2). So we first - * do a version of log2 (a variant of Long class with - * pre-checks and opposite directionality) and then scale and - * check against powers table. This is a little simpler in - * present context than the version in Hacker's Delight sec - * 11-4. Adding one to bit length allows comparing downward - * from the LONG_TEN_POWERS_TABLE that we need anyway. + * integer log 10 of x is within 1 of (1233/4096)* (1 + + * integer log 2 of x). The fraction 1233/4096 approximates + * log10(2). So we first do a version of log2 (a variant of + * Long class with pre-checks and opposite directionality) and + * then scale and check against powers table. This is a little + * simpler in present context than the version in Hacker's + * Delight sec 11-4. Adding one to bit length allows comparing + * downward from the LONG_TEN_POWERS_TABLE that we need + * anyway. */ - assert x != INFLATED; + assert x != BigDecimal.INFLATED; if (x < 0) x = -x; if (x < 10) // must screen for 0, might as well 10 return 1; - int n = 64; // not 63, to avoid needing to add 1 later - int y = (int)(x >>> 32); - if (y == 0) { n -= 32; y = (int)x; } - if (y >>> 16 == 0) { n -= 16; y <<= 16; } - if (y >>> 24 == 0) { n -= 8; y <<= 8; } - if (y >>> 28 == 0) { n -= 4; y <<= 4; } - if (y >>> 30 == 0) { n -= 2; y <<= 2; } - int r = (((y >>> 31) + n) * 1233) >>> 12; + int r = ((64 - Long.numberOfLeadingZeros(x) + 1) * 1233) >>> 12; long[] tab = LONG_TEN_POWERS_TABLE; // if r >= length, must have max possible digits for long - return (r >= tab.length || x < tab[r])? r : r+1; + return (r >= tab.length || x < tab[r]) ? r : r + 1; } /** @@ -3635,41 +3823,6 @@ return b.compareMagnitude(bigTenToThe(r)) < 0? r : r+1; } - - /** - * Remove insignificant trailing zeros from this - * {@code BigDecimal} until the preferred scale is reached or no - * more zeros can be removed. If the preferred scale is less than - * Integer.MIN_VALUE, all the trailing zeros will be removed. - * - * {@code BigInteger} assistance could help, here? - * - *

WARNING: This method should only be called on new objects as - * it mutates the value fields. - * - * @return this {@code BigDecimal} with a scale possibly reduced - * to be closed to the preferred scale. - */ - private BigDecimal stripZerosToMatchScale(long preferredScale) { - this.inflate(); - BigInteger qr[]; // quotient-remainder pair - while ( intVal.compareMagnitude(BigInteger.TEN) >= 0 && - scale > preferredScale) { - if (intVal.testBit(0)) - break; // odd number cannot end in 0 - qr = intVal.divideAndRemainder(BigInteger.TEN); - if (qr[1].signum() != 0) - break; // non-0 remainder - intVal=qr[0]; - scale = checkScale((long)scale-1); // could Overflow - if (precision > 0) // adjust precision if known - precision--; - } - if (intVal != null) - intCompact = compactValFor(intVal); - return this; - } - /** * Check a scale for Underflow or Overflow. If this BigDecimal is * nonzero, throw an exception if the scale is outof range. If this @@ -3693,74 +3846,7 @@ return asInt; } - /** - * Round an operand; used only if digits > 0. Does not change - * {@code this}; if rounding is needed a new {@code BigDecimal} - * is created and returned. - * - * @param mc the context to use. - * @throws ArithmeticException if the result is inexact but the - * rounding mode is {@code UNNECESSARY}. - */ - private BigDecimal roundOp(MathContext mc) { - BigDecimal rounded = doRound(this, mc); - return rounded; - } - - /** Round this BigDecimal according to the MathContext settings; - * used only if precision {@literal >} 0. - * - *

WARNING: This method should only be called on new objects as - * it mutates the value fields. - * - * @param mc the context to use. - * @throws ArithmeticException if the rounding mode is - * {@code RoundingMode.UNNECESSARY} and the - * {@code BigDecimal} operation would require rounding. - */ - private void roundThis(MathContext mc) { - BigDecimal rounded = doRound(this, mc); - if (rounded == this) // wasn't rounded - return; - this.intVal = rounded.intVal; - this.intCompact = rounded.intCompact; - this.scale = rounded.scale; - this.precision = rounded.precision; - } - - /** - * Returns a {@code BigDecimal} rounded according to the - * MathContext settings; used only if {@code mc.precision > 0}. - * Does not change {@code this}; if rounding is needed a new - * {@code BigDecimal} is created and returned. - * - * @param mc the context to use. - * @return a {@code BigDecimal} rounded according to the MathContext - * settings. May return this, if no rounding needed. - * @throws ArithmeticException if the rounding mode is - * {@code RoundingMode.UNNECESSARY} and the - * result is inexact. - */ - private static BigDecimal doRound(BigDecimal d, MathContext mc) { - int mcp = mc.precision; - int drop; - // This might (rarely) iterate to cover the 999=>1000 case - while ((drop = d.precision() - mcp) > 0) { - int newScale = d.checkScale((long)d.scale - drop); - int mode = mc.roundingMode.oldMode; - if (drop < LONG_TEN_POWERS_TABLE.length) - d = divideAndRound(d.intCompact, d.intVal, - LONG_TEN_POWERS_TABLE[drop], null, - newScale, mode, newScale); - else - d = divideAndRound(d.intCompact, d.intVal, - INFLATED, bigTenToThe(drop), - newScale, mode, newScale); - } - return d; - } - - /** + /** * Returns the compact value for given {@code BigInteger}, or * INFLATED if too big. Relies on internal representation of * {@code BigInteger}. @@ -3852,4 +3938,1290 @@ } return this; } + + /* the same as checkScale where value!=0 */ + private static int checkScaleNonZero(long val) { + int asInt = (int)val; + if (asInt != val) { + throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow"); + } + return asInt; + } + + private static int checkScale(long intCompact, long val) { + int asInt = (int)val; + if (asInt != val) { + asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE; + if (intCompact != 0) + throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow"); + } + return asInt; + } + + private static int checkScale(BigInteger intVal, long val) { + int asInt = (int)val; + if (asInt != val) { + asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE; + if (intVal.signum() != 0) + throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow"); + } + return asInt; + } + + /** + * Returns a {@code BigDecimal} rounded according to the MathContext + * settings; + * If rounding is needed a new {@code BigDecimal} is created and returned. + * + * @param val the value to be rounded + * @param mc the context to use. + * @return a {@code BigDecimal} rounded according to the MathContext + * settings. May return {@code value}, if no rounding needed. + * @throws ArithmeticException if the rounding mode is + * {@code RoundingMode.UNNECESSARY} and the + * result is inexact. + */ + private static BigDecimal doRound(BigDecimal val, MathContext mc) { + int mcp = mc.precision; + boolean wasDivided = false; + if (mcp > 0) { + BigInteger intVal = val.intVal; + long compactVal = val.intCompact; + int scale = val.scale; + int prec = val.precision(); + int mode = mc.roundingMode.oldMode; + int drop; + if (compactVal == INFLATED) { + drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + intVal = divideAndRoundByTenPow(intVal, drop, mode); + wasDivided = true; + compactVal = compactValFor(intVal); + if (compactVal != INFLATED) { + prec = longDigitLength(compactVal); + break; + } + prec = bigDigitLength(intVal); + drop = prec - mcp; + } + } + if (compactVal != INFLATED) { + drop = prec - mcp; // drop can't be more than 18 + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + wasDivided = true; + prec = longDigitLength(compactVal); + drop = prec - mcp; + intVal = null; + } + } + return wasDivided ? new BigDecimal(intVal,compactVal,scale,prec) : val; + } + return val; + } + + /* + * Returns a {@code BigDecimal} created from {@code long} value with + * given scale rounded according to the MathContext settings + */ + private static BigDecimal doRound(long compactVal, int scale, MathContext mc) { + int mcp = mc.precision; + if (mcp > 0 && mcp < 19) { + int prec = longDigitLength(compactVal); + int drop = prec - mcp; // drop can't be more than 18 + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(compactVal); + drop = prec - mcp; + } + return valueOf(compactVal, scale, prec); + } + return valueOf(compactVal, scale); + } + + /* + * Returns a {@code BigDecimal} created from {@code BigInteger} value with + * given scale rounded according to the MathContext settings + */ + private static BigDecimal doRound(BigInteger intVal, int scale, MathContext mc) { + int mcp = mc.precision; + int prec = 0; + if (mcp > 0) { + long compactVal = compactValFor(intVal); + int mode = mc.roundingMode.oldMode; + int drop; + if (compactVal == INFLATED) { + prec = bigDigitLength(intVal); + drop = prec - mcp; + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + intVal = divideAndRoundByTenPow(intVal, drop, mode); + compactVal = compactValFor(intVal); + if (compactVal != INFLATED) { + break; + } + prec = bigDigitLength(intVal); + drop = prec - mcp; + } + } + if (compactVal != INFLATED) { + prec = longDigitLength(compactVal); + drop = prec - mcp; // drop can't be more than 18 + while (drop > 0) { + scale = checkScaleNonZero((long) scale - drop); + compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode); + prec = longDigitLength(compactVal); + drop = prec - mcp; + } + return valueOf(compactVal,scale,prec); + } + } + return new BigDecimal(intVal,INFLATED,scale,prec); + } + + /* + * Divides {@code BigInteger} value by ten power. + */ + private static BigInteger divideAndRoundByTenPow(BigInteger intVal, int tenPow, int roundingMode) { + if (tenPow < LONG_TEN_POWERS_TABLE.length) + intVal = divideAndRound(intVal, LONG_TEN_POWERS_TABLE[tenPow], roundingMode); + else + intVal = divideAndRound(intVal, bigTenToThe(tenPow), roundingMode); + return intVal; + } + + /** + * Internally used for division operation for division {@code long} by + * {@code long}. + * The returned {@code BigDecimal} object is the quotient whose scale is set + * to the passed in scale. If the remainder is not zero, it will be rounded + * based on the passed in roundingMode. Also, if the remainder is zero and + * the last parameter, i.e. preferredScale is NOT equal to scale, the + * trailing zeros of the result is stripped to match the preferredScale. + */ + private static BigDecimal divideAndRound(long ldividend, long ldivisor, int scale, int roundingMode, + int preferredScale) { + + int qsign; // quotient sign + long q = ldividend / ldivisor; // store quotient in long + if (roundingMode == ROUND_DOWN && scale == preferredScale) + return valueOf(q, scale); + long r = ldividend % ldivisor; // store remainder in long + qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1; + if (r != 0) { + boolean increment = needIncrement(ldivisor, roundingMode, qsign, q, r); + return valueOf((increment ? q + qsign : q), scale); + } else { + if (preferredScale != scale) + return createAndStripZerosToMatchScale(q, scale, preferredScale); + else + return valueOf(q, scale); + } + } + + /** + * Divides {@code long} by {@code long} and do rounding based on the + * passed in roundingMode. + */ + private static long divideAndRound(long ldividend, long ldivisor, int roundingMode) { + int qsign; // quotient sign + long q = ldividend / ldivisor; // store quotient in long + if (roundingMode == ROUND_DOWN) + return q; + long r = ldividend % ldivisor; // store remainder in long + qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1; + if (r != 0) { + boolean increment = needIncrement(ldivisor, roundingMode, qsign, q, r); + return increment ? q + qsign : q; + } else { + return q; + } + } + + /** + * Shared logic of need increment computation. + */ + private static boolean commonNeedIncrement(int roundingMode, int qsign, + int cmpFracHalf, boolean oddQuot) { + switch(roundingMode) { + case ROUND_UNNECESSARY: + throw new ArithmeticException("Rounding necessary"); + + case ROUND_UP: // Away from zero + return true; + + case ROUND_DOWN: // Towards zero + return false; + + case ROUND_CEILING: // Towards +infinity + return qsign > 0; + + case ROUND_FLOOR: // Towards -infinity + return qsign < 0; + + default: // Some kind of half-way rounding + assert roundingMode >= ROUND_HALF_UP && + roundingMode <= ROUND_HALF_EVEN: "Unexpected rounding mode" + RoundingMode.valueOf(roundingMode); + + if (cmpFracHalf < 0 ) // We're closer to higher digit + return false; + else if (cmpFracHalf > 0 ) // We're closer to lower digit + return true; + else { // half-way + assert cmpFracHalf == 0; + + switch(roundingMode) { + case ROUND_HALF_DOWN: + return false; + + case ROUND_HALF_UP: + return true; + + case ROUND_HALF_EVEN: + return oddQuot; + + default: + throw new AssertionError("Unexpected rounding mode" + roundingMode); + } + } + } + } + + /** + * Tests if quotient has to be incremented according the roundingMode + */ + private static boolean needIncrement(long ldivisor, int roundingMode, + int qsign, long q, long r) { + assert r != 0L; + + int cmpFracHalf; + if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) { + cmpFracHalf = 1; // 2 * r can't fit into long + } else { + cmpFracHalf = longCompareMagnitude(2 * r, ldivisor); + } + + return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, (q & 1L) != 0L); + } + + /** + * Divides {@code BigInteger} value by {@code long} value and + * do rounding based on the passed in roundingMode. + */ + private static BigInteger divideAndRound(BigInteger bdividend, long ldivisor, int roundingMode) { + boolean isRemainderZero; // record remainder is zero or not + int qsign; // quotient sign + long r = 0; // store quotient & remainder in long + MutableBigInteger mq = null; // store quotient + // Descend into mutables for faster remainder checks + MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); + mq = new MutableBigInteger(); + r = mdividend.divide(ldivisor, mq); + isRemainderZero = (r == 0); + qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; + if (!isRemainderZero) { + if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) { + mq.add(MutableBigInteger.ONE); + } + } + return mq.toBigInteger(qsign); + } + + /** + * Internally used for division operation for division {@code BigInteger} + * by {@code long}. + * The returned {@code BigDecimal} object is the quotient whose scale is set + * to the passed in scale. If the remainder is not zero, it will be rounded + * based on the passed in roundingMode. Also, if the remainder is zero and + * the last parameter, i.e. preferredScale is NOT equal to scale, the + * trailing zeros of the result is stripped to match the preferredScale. + */ + private static BigDecimal divideAndRound(BigInteger bdividend, + long ldivisor, int scale, int roundingMode, int preferredScale) { + boolean isRemainderZero; // record remainder is zero or not + int qsign; // quotient sign + long r = 0; // store quotient & remainder in long + MutableBigInteger mq = null; // store quotient + // Descend into mutables for faster remainder checks + MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); + mq = new MutableBigInteger(); + r = mdividend.divide(ldivisor, mq); + isRemainderZero = (r == 0); + qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum; + if (!isRemainderZero) { + if(needIncrement(ldivisor, roundingMode, qsign, mq, r)) { + mq.add(MutableBigInteger.ONE); + } + return mq.toBigDecimal(qsign, scale); + } else { + if (preferredScale != scale) { + long compactVal = mq.toCompactValue(qsign); + if(compactVal!=INFLATED) { + return createAndStripZerosToMatchScale(compactVal, scale, preferredScale); + } + BigInteger intVal = mq.toBigInteger(qsign); + return createAndStripZerosToMatchScale(intVal,scale, preferredScale); + } else { + return mq.toBigDecimal(qsign, scale); + } + } + } + + /** + * Tests if quotient has to be incremented according the roundingMode + */ + private static boolean needIncrement(long ldivisor, int roundingMode, + int qsign, MutableBigInteger mq, long r) { + assert r != 0L; + + int cmpFracHalf; + if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) { + cmpFracHalf = 1; // 2 * r can't fit into long + } else { + cmpFracHalf = longCompareMagnitude(2 * r, ldivisor); + } + + return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, mq.isOdd()); + } + + /** + * Divides {@code BigInteger} value by {@code BigInteger} value and + * do rounding based on the passed in roundingMode. + */ + private static BigInteger divideAndRound(BigInteger bdividend, BigInteger bdivisor, int roundingMode) { + boolean isRemainderZero; // record remainder is zero or not + int qsign; // quotient sign + // Descend into mutables for faster remainder checks + MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); + MutableBigInteger mq = new MutableBigInteger(); + MutableBigInteger mdivisor = new MutableBigInteger(bdivisor.mag); + MutableBigInteger mr = mdividend.divide(mdivisor, mq); + isRemainderZero = mr.isZero(); + qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1; + if (!isRemainderZero) { + if (needIncrement(mdivisor, roundingMode, qsign, mq, mr)) { + mq.add(MutableBigInteger.ONE); + } + } + return mq.toBigInteger(qsign); + } + + /** + * Internally used for division operation for division {@code BigInteger} + * by {@code BigInteger}. + * The returned {@code BigDecimal} object is the quotient whose scale is set + * to the passed in scale. If the remainder is not zero, it will be rounded + * based on the passed in roundingMode. Also, if the remainder is zero and + * the last parameter, i.e. preferredScale is NOT equal to scale, the + * trailing zeros of the result is stripped to match the preferredScale. + */ + private static BigDecimal divideAndRound(BigInteger bdividend, BigInteger bdivisor, int scale, int roundingMode, + int preferredScale) { + boolean isRemainderZero; // record remainder is zero or not + int qsign; // quotient sign + // Descend into mutables for faster remainder checks + MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag); + MutableBigInteger mq = new MutableBigInteger(); + MutableBigInteger mdivisor = new MutableBigInteger(bdivisor.mag); + MutableBigInteger mr = mdividend.divide(mdivisor, mq); + isRemainderZero = mr.isZero(); + qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1; + if (!isRemainderZero) { + if (needIncrement(mdivisor, roundingMode, qsign, mq, mr)) { + mq.add(MutableBigInteger.ONE); + } + return mq.toBigDecimal(qsign, scale); + } else { + if (preferredScale != scale) { + long compactVal = mq.toCompactValue(qsign); + if (compactVal != INFLATED) { + return createAndStripZerosToMatchScale(compactVal, scale, preferredScale); + } + BigInteger intVal = mq.toBigInteger(qsign); + return createAndStripZerosToMatchScale(intVal, scale, preferredScale); + } else { + return mq.toBigDecimal(qsign, scale); + } + } + } + + /** + * Tests if quotient has to be incremented according the roundingMode + */ + private static boolean needIncrement(MutableBigInteger mdivisor, int roundingMode, + int qsign, MutableBigInteger mq, MutableBigInteger mr) { + assert !mr.isZero(); + int cmpFracHalf = mr.compareHalf(mdivisor); + return commonNeedIncrement(roundingMode, qsign, cmpFracHalf, mq.isOdd()); + } + + /** + * Remove insignificant trailing zeros from this + * {@code BigInteger} value until the preferred scale is reached or no + * more zeros can be removed. If the preferred scale is less than + * Integer.MIN_VALUE, all the trailing zeros will be removed. + * + * @return new {@code BigDecimal} with a scale possibly reduced + * to be closed to the preferred scale. + */ + private static BigDecimal createAndStripZerosToMatchScale(BigInteger intVal, int scale, long preferredScale) { + BigInteger qr[]; // quotient-remainder pair + while (intVal.compareMagnitude(BigInteger.TEN) >= 0 + && scale > preferredScale) { + if (intVal.testBit(0)) + break; // odd number cannot end in 0 + qr = intVal.divideAndRemainder(BigInteger.TEN); + if (qr[1].signum() != 0) + break; // non-0 remainder + intVal = qr[0]; + scale = checkScale(intVal,(long) scale - 1); // could Overflow + } + return valueOf(intVal, scale, 0); + } + + /** + * Remove insignificant trailing zeros from this + * {@code long} value until the preferred scale is reached or no + * more zeros can be removed. If the preferred scale is less than + * Integer.MIN_VALUE, all the trailing zeros will be removed. + * + * @return new {@code BigDecimal} with a scale possibly reduced + * to be closed to the preferred scale. + */ + private static BigDecimal createAndStripZerosToMatchScale(long compactVal, int scale, long preferredScale) { + while (Math.abs(compactVal) >= 10L && scale > preferredScale) { + if ((compactVal & 1L) != 0L) + break; // odd number cannot end in 0 + long r = compactVal % 10L; + if (r != 0L) + break; // non-0 remainder + compactVal /= 10; + scale = checkScale(compactVal, (long) scale - 1); // could Overflow + } + return valueOf(compactVal, scale); + } + + private static BigDecimal stripZerosToMatchScale(BigInteger intVal, long intCompact, int scale, int preferredScale) { + if(intCompact!=INFLATED) { + return createAndStripZerosToMatchScale(intCompact, scale, preferredScale); + } else { + return createAndStripZerosToMatchScale(intVal==null ? INFLATED_BIGINT : intVal, + scale, preferredScale); + } + } + + /* + * returns INFLATED if oveflow + */ + private static long add(long xs, long ys){ + long sum = xs + ys; + // See "Hacker's Delight" section 2-12 for explanation of + // the overflow test. + if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) { // not overflowed + return sum; + } + return INFLATED; + } + + private static BigDecimal add(long xs, long ys, int scale){ + long sum = add(xs, ys); + if (sum!=INFLATED) + return BigDecimal.valueOf(sum, scale); + return new BigDecimal(BigInteger.valueOf(xs).add(ys), scale); + } + + private static BigDecimal add(final long xs, int scale1, final long ys, int scale2) { + long sdiff = (long) scale1 - scale2; + if (sdiff == 0) { + return add(xs, ys, scale1); + } else if (sdiff < 0) { + int raise = checkScale(xs,-sdiff); + long scaledX = longMultiplyPowerTen(xs, raise); + if (scaledX != INFLATED) { + return add(scaledX, ys, scale2); + } else { + BigInteger bigsum = bigMultiplyPowerTen(xs,raise).add(ys); + return ((xs^ys)>=0) ? // same sign test + new BigDecimal(bigsum, INFLATED, scale2, 0) + : valueOf(bigsum, scale2, 0); + } + } else { + int raise = checkScale(ys,sdiff); + long scaledY = longMultiplyPowerTen(ys, raise); + if (scaledY != INFLATED) { + return add(xs, scaledY, scale1); + } else { + BigInteger bigsum = bigMultiplyPowerTen(ys,raise).add(xs); + return ((xs^ys)>=0) ? + new BigDecimal(bigsum, INFLATED, scale1, 0) + : valueOf(bigsum, scale1, 0); + } + } + } + + private static BigDecimal add(final long xs, int scale1, BigInteger snd, int scale2) { + int rscale = scale1; + long sdiff = (long)rscale - scale2; + boolean sameSigns = (Long.signum(xs) == snd.signum); + BigInteger sum; + if (sdiff < 0) { + int raise = checkScale(xs,-sdiff); + rscale = scale2; + long scaledX = longMultiplyPowerTen(xs, raise); + if (scaledX == INFLATED) { + sum = snd.add(bigMultiplyPowerTen(xs,raise)); + } else { + sum = snd.add(scaledX); + } + } else { //if (sdiff > 0) { + int raise = checkScale(snd,sdiff); + snd = bigMultiplyPowerTen(snd,raise); + sum = snd.add(xs); + } + return (sameSigns) ? + new BigDecimal(sum, INFLATED, rscale, 0) : + valueOf(sum, rscale, 0); + } + + private static BigDecimal add(BigInteger fst, int scale1, BigInteger snd, int scale2) { + int rscale = scale1; + long sdiff = (long)rscale - scale2; + if (sdiff != 0) { + if (sdiff < 0) { + int raise = checkScale(fst,-sdiff); + rscale = scale2; + fst = bigMultiplyPowerTen(fst,raise); + } else { + int raise = checkScale(snd,sdiff); + snd = bigMultiplyPowerTen(snd,raise); + } + } + BigInteger sum = fst.add(snd); + return (fst.signum == snd.signum) ? + new BigDecimal(sum, INFLATED, rscale, 0) : + valueOf(sum, rscale, 0); + } + + private static BigInteger bigMultiplyPowerTen(long value, int n) { + if (n <= 0) + return BigInteger.valueOf(value); + return bigTenToThe(n).multiply(value); + } + + private static BigInteger bigMultiplyPowerTen(BigInteger value, int n) { + if (n <= 0) + return value; + if(n=0 + long scaledX = (xraise==0) ? xs : + longMultiplyPowerTen(xs, xraise); // can't overflow here! + BigDecimal quotient; + + int cmp = longCompareMagnitude(scaledX, ys); + if(cmp > 0) { // satisfy constraint (b) + yscale -= 1; // [that is, divisor *= 10] + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + if (checkScaleNonZero((long) mcp + yscale) > xscale) { + // assert newScale >= xscale + int raise = checkScaleNonZero((long) mcp + yscale - xscale); + long scaledXs; + if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) { + quotient = null; + if((mcp-1) >=0 && (mcp-1)= yscale + if (newScale == yscale) { // easy case + quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + int raise = checkScaleNonZero((long) newScale - yscale); + long scaledYs; + if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) { + BigInteger rb = bigMultiplyPowerTen(ys,raise); + quotient = divideAndRound(BigInteger.valueOf(xs), + rb, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale)); + } + } + } + } else { + // abs(scaledX) <= abs(ys) + // result is "scaledX * 10^msp / ys" + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + if(cmp==0) { + // abs(scaleX)== abs(ys) => result will be scaled 10^mcp + correct sign + quotient = roundedTenPower(((scaledX < 0) == (ys < 0)) ? 1 : -1, mcp, scl, checkScaleNonZero(preferredScale)); + } else { + // abs(scaledX) < abs(ys) + long scaledXs; + if ((scaledXs = longMultiplyPowerTen(scaledX, mcp)) == INFLATED) { + quotient = null; + if(mcp 0) {// satisfy constraint (b) + yscale -= 1; // [that is, divisor *= 10] + } + int roundingMode = mc.roundingMode.oldMode; + // In order to find out whether the divide generates the exact result, + // we avoid calling the above divide method. 'quotient' holds the + // return BigDecimal object whose scale will be set to 'scl'. + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + BigDecimal quotient; + if (checkScaleNonZero((long) mcp + yscale) > xscale) { + int raise = checkScaleNonZero((long) mcp + yscale - xscale); + long scaledXs; + if ((scaledXs = longMultiplyPowerTen(xs, raise)) == INFLATED) { + BigInteger rb = bigMultiplyPowerTen(xs,raise); + quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); + } else { + quotient = divideAndRound(scaledXs, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); + } + } else { + int newScale = checkScaleNonZero((long) xscale - mcp); + // assert newScale >= yscale + if (newScale == yscale) { // easy case + quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + int raise = checkScaleNonZero((long) newScale - yscale); + long scaledYs; + if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) { + BigInteger rb = bigMultiplyPowerTen(ys,raise); + quotient = divideAndRound(BigInteger.valueOf(xs), + rb, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale)); + } + } + } + // doRound, here, only affects 1000000000 case. + return doRound(quotient,mc); + } + + /** + * Returns a {@code BigDecimal} whose value is {@code (xs / + * ys)}, with rounding according to the context settings. + */ + private static BigDecimal divide(BigInteger xs, int xscale, long ys, int yscale, long preferredScale, MathContext mc) { + // Normalize dividend & divisor so that both fall into [0.1, 0.999...] + if ((-compareMagnitudeNormalized(ys, yscale, xs, xscale)) > 0) {// satisfy constraint (b) + yscale -= 1; // [that is, divisor *= 10] + } + int mcp = mc.precision; + int roundingMode = mc.roundingMode.oldMode; + + // In order to find out whether the divide generates the exact result, + // we avoid calling the above divide method. 'quotient' holds the + // return BigDecimal object whose scale will be set to 'scl'. + BigDecimal quotient; + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + if (checkScaleNonZero((long) mcp + yscale) > xscale) { + int raise = checkScaleNonZero((long) mcp + yscale - xscale); + BigInteger rb = bigMultiplyPowerTen(xs,raise); + quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); + } else { + int newScale = checkScaleNonZero((long) xscale - mcp); + // assert newScale >= yscale + if (newScale == yscale) { // easy case + quotient = divideAndRound(xs, ys, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + int raise = checkScaleNonZero((long) newScale - yscale); + long scaledYs; + if ((scaledYs = longMultiplyPowerTen(ys, raise)) == INFLATED) { + BigInteger rb = bigMultiplyPowerTen(ys,raise); + quotient = divideAndRound(xs, rb, scl, roundingMode,checkScaleNonZero(preferredScale)); + } else { + quotient = divideAndRound(xs, scaledYs, scl, roundingMode,checkScaleNonZero(preferredScale)); + } + } + } + // doRound, here, only affects 1000000000 case. + return doRound(quotient, mc); + } + + /** + * Returns a {@code BigDecimal} whose value is {@code (xs / + * ys)}, with rounding according to the context settings. + */ + private static BigDecimal divide(long xs, int xscale, BigInteger ys, int yscale, long preferredScale, MathContext mc) { + // Normalize dividend & divisor so that both fall into [0.1, 0.999...] + if (compareMagnitudeNormalized(xs, xscale, ys, yscale) > 0) {// satisfy constraint (b) + yscale -= 1; // [that is, divisor *= 10] + } + int mcp = mc.precision; + int roundingMode = mc.roundingMode.oldMode; + + // In order to find out whether the divide generates the exact result, + // we avoid calling the above divide method. 'quotient' holds the + // return BigDecimal object whose scale will be set to 'scl'. + BigDecimal quotient; + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + if (checkScaleNonZero((long) mcp + yscale) > xscale) { + int raise = checkScaleNonZero((long) mcp + yscale - xscale); + BigInteger rb = bigMultiplyPowerTen(xs,raise); + quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); + } else { + int newScale = checkScaleNonZero((long) xscale - mcp); + int raise = checkScaleNonZero((long) newScale - yscale); + BigInteger rb = bigMultiplyPowerTen(ys,raise); + quotient = divideAndRound(BigInteger.valueOf(xs), rb, scl, roundingMode,checkScaleNonZero(preferredScale)); + } + // doRound, here, only affects 1000000000 case. + return doRound(quotient, mc); + } + + /** + * Returns a {@code BigDecimal} whose value is {@code (xs / + * ys)}, with rounding according to the context settings. + */ + private static BigDecimal divide(BigInteger xs, int xscale, BigInteger ys, int yscale, long preferredScale, MathContext mc) { + // Normalize dividend & divisor so that both fall into [0.1, 0.999...] + if (compareMagnitudeNormalized(xs, xscale, ys, yscale) > 0) {// satisfy constraint (b) + yscale -= 1; // [that is, divisor *= 10] + } + int mcp = mc.precision; + int roundingMode = mc.roundingMode.oldMode; + + // In order to find out whether the divide generates the exact result, + // we avoid calling the above divide method. 'quotient' holds the + // return BigDecimal object whose scale will be set to 'scl'. + BigDecimal quotient; + int scl = checkScaleNonZero(preferredScale + yscale - xscale + mcp); + if (checkScaleNonZero((long) mcp + yscale) > xscale) { + int raise = checkScaleNonZero((long) mcp + yscale - xscale); + BigInteger rb = bigMultiplyPowerTen(xs,raise); + quotient = divideAndRound(rb, ys, scl, roundingMode, checkScaleNonZero(preferredScale)); + } else { + int newScale = checkScaleNonZero((long) xscale - mcp); + int raise = checkScaleNonZero((long) newScale - yscale); + BigInteger rb = bigMultiplyPowerTen(ys,raise); + quotient = divideAndRound(xs, rb, scl, roundingMode,checkScaleNonZero(preferredScale)); + } + // doRound, here, only affects 1000000000 case. + return doRound(quotient, mc); + } + + /* + * performs divideAndRound for (dividend0*dividend1, divisor) + * returns null if quotient can't fit into long value; + */ + private static BigDecimal multiplyDivideAndRound(long dividend0, long dividend1, long divisor, int scale, int roundingMode, + int preferredScale) { + int qsign = Long.signum(dividend0)*Long.signum(dividend1)*Long.signum(divisor); + dividend0 = Math.abs(dividend0); + dividend1 = Math.abs(dividend1); + divisor = Math.abs(divisor); + // multiply dividend0 * dividend1 + long d0_hi = dividend0 >>> 32; + long d0_lo = dividend0 & LONG_MASK; + long d1_hi = dividend1 >>> 32; + long d1_lo = dividend1 & LONG_MASK; + long product = d0_lo * d1_lo; + long d0 = product & LONG_MASK; + long d1 = product >>> 32; + product = d0_hi * d1_lo + d1; + d1 = product & LONG_MASK; + long d2 = product >>> 32; + product = d0_lo * d1_hi + d1; + d1 = product & LONG_MASK; + d2 += product >>> 32; + long d3 = d2>>>32; + d2 &= LONG_MASK; + product = d0_hi*d1_hi + d2; + d2 = product & LONG_MASK; + d3 = ((product>>>32) + d3) & LONG_MASK; + final long dividendHi = make64(d3,d2); + final long dividendLo = make64(d1,d0); + // divide + return divideAndRound128(dividendHi, dividendLo, divisor, qsign, scale, roundingMode, preferredScale); + } + + private static final long DIV_NUM_BASE = (1L<<32); // Number base (32 bits). + + /* + * divideAndRound 128-bit value by long divisor. + * returns null if quotient can't fit into long value; + * Specialized version of Knuth's division + */ + private static BigDecimal divideAndRound128(final long dividendHi, final long dividendLo, long divisor, int sign, + int scale, int roundingMode, int preferredScale) { + if (dividendHi >= divisor) { + return null; + } + final int shift = Long.numberOfLeadingZeros(divisor); + divisor <<= shift; + + final long v1 = divisor >>> 32; + final long v0 = divisor & LONG_MASK; + + long q1, q0; + long r_tmp; + + long tmp = dividendLo << shift; + long u1 = tmp >>> 32; + long u0 = tmp & LONG_MASK; + + tmp = (dividendHi << shift) | (dividendLo >>> 64 - shift); + long u2 = tmp & LONG_MASK; + tmp = divWord(tmp,v1); + q1 = tmp & LONG_MASK; + r_tmp = tmp >>> 32; + while(q1 >= DIV_NUM_BASE || unsignedLongCompare(q1*v0, make64(r_tmp, u1))) { + q1--; + r_tmp += v1; + if (r_tmp >= DIV_NUM_BASE) + break; + } + tmp = mulsub(u2,u1,v1,v0,q1); + u1 = tmp & LONG_MASK; + tmp = divWord(tmp,v1); + q0 = tmp & LONG_MASK; + r_tmp = tmp >>> 32; + while(q0 >= DIV_NUM_BASE || unsignedLongCompare(q0*v0,make64(r_tmp,u0))) { + q0--; + r_tmp += v1; + if (r_tmp >= DIV_NUM_BASE) + break; + } + if((int)q1 < 0) { + // result (which is positive and unsigned here) + // can't fit into long due to sign bit is used for value + MutableBigInteger mq = new MutableBigInteger(new int[]{(int)q1, (int)q0}); + if (roundingMode == ROUND_DOWN && scale == preferredScale) { + return mq.toBigDecimal(sign, scale); + } + long r = mulsub(u1, u0, v1, v0, q0) >>> shift; + if (r != 0) { + if(needIncrement(divisor >>> shift, roundingMode, sign, mq, r)){ + mq.add(MutableBigInteger.ONE); + } + return mq.toBigDecimal(sign, scale); + } else { + if (preferredScale != scale) { + BigInteger intVal = mq.toBigInteger(sign); + return createAndStripZerosToMatchScale(intVal,scale, preferredScale); + } else { + return mq.toBigDecimal(sign, scale); + } + } + } + long q = make64(q1,q0); + q*=sign; + if (roundingMode == ROUND_DOWN && scale == preferredScale) + return valueOf(q, scale); + long r = mulsub(u1, u0, v1, v0, q0) >>> shift; + if (r != 0) { + boolean increment = needIncrement(divisor >>> shift, roundingMode, sign, q, r); + return valueOf((increment ? q + sign : q), scale); + } else { + if (preferredScale != scale) { + return createAndStripZerosToMatchScale(q, scale, preferredScale); + } else { + return valueOf(q, scale); + } + } + } + + /* + * calculate divideAndRound for ldividend*10^raise / divisor + * when abs(dividend)==abs(divisor); + */ + private static BigDecimal roundedTenPower(int qsign, int raise, int scale, int preferredScale) { + if (scale > preferredScale) { + int diff = scale - preferredScale; + if(diff < raise) { + return scaledTenPow(raise - diff, qsign, preferredScale); + } else { + return valueOf(qsign,scale-raise); + } + } else { + return scaledTenPow(raise, qsign, scale); + } + } + + static BigDecimal scaledTenPow(int n, int sign, int scale) { + if (n < LONG_TEN_POWERS_TABLE.length) + return valueOf(sign*LONG_TEN_POWERS_TABLE[n],scale); + else { + BigInteger unscaledVal = bigTenToThe(n); + if(sign==-1) { + unscaledVal = unscaledVal.negate(); + } + return new BigDecimal(unscaledVal, INFLATED, scale, n+1); + } + } + + private static long divWord(long n, long dLong) { + long r; + long q; + if (dLong == 1) { + q = (int)n; + return (q & LONG_MASK); + } + // Approximate the quotient and remainder + q = (n >>> 1) / (dLong >>> 1); + r = n - q*dLong; + + // Correct the approximation + while (r < 0) { + r += dLong; + q--; + } + while (r >= dLong) { + r -= dLong; + q++; + } + // n - q*dlong == r && 0 <= r >>32) - q0*v1,tmp & LONG_MASK); + } + + private static boolean unsignedLongCompare(long one, long two) { + return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE); + } + + private static boolean unsignedLongCompareEq(long one, long two) { + return (one+Long.MIN_VALUE) >= (two+Long.MIN_VALUE); + } + + + // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...] + private static int compareMagnitudeNormalized(long xs, int xscale, long ys, int yscale) { + // assert xs!=0 && ys!=0 + int sdiff = xscale - yscale; + if (sdiff != 0) { + if (sdiff < 0) { + xs = longMultiplyPowerTen(xs, -sdiff); + } else { // sdiff > 0 + ys = longMultiplyPowerTen(ys, sdiff); + } + } + if (xs != INFLATED) + return (ys != INFLATED) ? longCompareMagnitude(xs, ys) : -1; + else + return 1; + } + + // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...] + private static int compareMagnitudeNormalized(long xs, int xscale, BigInteger ys, int yscale) { + // assert "ys can't be represented as long" + if (xs == 0) + return -1; + int sdiff = xscale - yscale; + if (sdiff < 0) { + if (longMultiplyPowerTen(xs, -sdiff) == INFLATED ) { + return bigMultiplyPowerTen(xs, -sdiff).compareMagnitude(ys); + } + } + return -1; + } + + // Compare Normalize dividend & divisor so that both fall into [0.1, 0.999...] + private static int compareMagnitudeNormalized(BigInteger xs, int xscale, BigInteger ys, int yscale) { + int sdiff = xscale - yscale; + if (sdiff < 0) { + return bigMultiplyPowerTen(xs, -sdiff).compareMagnitude(ys); + } else { // sdiff >= 0 + return xs.compareMagnitude(bigMultiplyPowerTen(ys, sdiff)); + } + } + + private static long multiply(long x, long y){ + long product = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + if (((ax | ay) >>> 31 == 0) || (y == 0) || (product / y == x)){ + return product; + } + return INFLATED; + } + + private static BigDecimal multiply(long x, long y, int scale) { + long product = multiply(x, y); + if(product!=INFLATED) { + return valueOf(product,scale); + } + return new BigDecimal(BigInteger.valueOf(x).multiply(y),INFLATED,scale,0); + } + + private static BigDecimal multiply(long x, BigInteger y, int scale) { + if(x==0) { + return zeroValueOf(scale); + } + return new BigDecimal(y.multiply(x),INFLATED,scale,0); + } + + private static BigDecimal multiply(BigInteger x, BigInteger y, int scale) { + return new BigDecimal(x.multiply(y),INFLATED,scale,0); + } + + /** + * Multiplies two long values and rounds according {@code MathContext} + */ + private static BigDecimal multiplyAndRound(long x, long y, int scale, MathContext mc) { + long product = multiply(x, y); + if(product!=INFLATED) { + return doRound(product, scale, mc); + } + // attempt to do it in 128 bits + int rsign = 1; + if(x < 0) { + x = -x; + rsign = -1; + } + if(y < 0) { + y = -y; + rsign *= -1; + } + // multiply dividend0 * dividend1 + long m0_hi = x >>> 32; + long m0_lo = x & LONG_MASK; + long m1_hi = y >>> 32; + long m1_lo = y & LONG_MASK; + product = m0_lo * m1_lo; + long m0 = product & LONG_MASK; + long m1 = product >>> 32; + product = m0_hi * m1_lo + m1; + m1 = product & LONG_MASK; + long m2 = product >>> 32; + product = m0_lo * m1_hi + m1; + m1 = product & LONG_MASK; + m2 += product >>> 32; + long m3 = m2>>>32; + m2 &= LONG_MASK; + product = m0_hi*m1_hi + m2; + m2 = product & LONG_MASK; + m3 = ((product>>>32) + m3) & LONG_MASK; + final long mHi = make64(m3,m2); + final long mLo = make64(m1,m0); + BigDecimal res = doRound128(mHi, mLo, rsign, scale, mc); + if(res!=null) { + return res; + } + res = new BigDecimal(BigInteger.valueOf(x).multiply(y*rsign), INFLATED, scale, 0); + return doRound(res,mc); + } + + private static BigDecimal multiplyAndRound(long x, BigInteger y, int scale, MathContext mc) { + if(x==0) { + return zeroValueOf(scale); + } + return doRound(y.multiply(x), scale, mc); + } + + private static BigDecimal multiplyAndRound(BigInteger x, BigInteger y, int scale, MathContext mc) { + return doRound(x.multiply(y), scale, mc); + } + + /** + * rounds 128-bit value according {@code MathContext} + * returns null if result can't be repsented as compact BigDecimal. + */ + private static BigDecimal doRound128(long hi, long lo, int sign, int scale, MathContext mc) { + int mcp = mc.precision; + int drop; + BigDecimal res = null; + if(((drop = precision(hi, lo) - mcp) > 0)&&(drop=0) { + return longDigitLength(lo); + } + return (unsignedLongCompareEq(lo, LONGLONG_TEN_POWERS_TABLE[0][1])) ? 20 : 19; + // 0x8AC7230489E80000L = unsigned 2^19 + } + int r = ((128 - Long.numberOfLeadingZeros(hi) + 1) * 1233) >>> 12; + int idx = r-19; + return (idx >= LONGLONG_TEN_POWERS_TABLE.length || longLongCompareMagnitude(hi, lo, + LONGLONG_TEN_POWERS_TABLE[idx][0], LONGLONG_TEN_POWERS_TABLE[idx][1])) ? r : r + 1; + } + + /* + * returns true if 128 bit number is less then + * hi0 & hi1 should be non-negative + */ + private static boolean longLongCompareMagnitude(long hi0, long lo0, long hi1, long lo1) { + if(hi0!=hi1) { + return hi0 dividendScale) { + int newScale = scale + divisorScale; + int raise = newScale - dividendScale; + if(raise dividendScale) { + int newScale = scale + divisorScale; + int raise = newScale - dividendScale; + BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise); + return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale); + } else { + int newScale = checkScale(divisor,(long)dividendScale - scale); + int raise = newScale - divisorScale; + if(raise dividendScale) { + int newScale = scale + divisorScale; + int raise = newScale - dividendScale; + BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise); + return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale); + } else { + int newScale = checkScale(divisor,(long)dividendScale - scale); + int raise = newScale - divisorScale; + BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise); + return divideAndRound(BigInteger.valueOf(dividend), scaledDivisor, scale, roundingMode, scale); + } + } + + private static BigDecimal divide(BigInteger dividend, int dividendScale, BigInteger divisor, int divisorScale, int scale, int roundingMode) { + if (checkScale(dividend,(long)scale + divisorScale) > dividendScale) { + int newScale = scale + divisorScale; + int raise = newScale - dividendScale; + BigInteger scaledDividend = bigMultiplyPowerTen(dividend, raise); + return divideAndRound(scaledDividend, divisor, scale, roundingMode, scale); + } else { + int newScale = checkScale(divisor,(long)dividendScale - scale); + int raise = newScale - divisorScale; + BigInteger scaledDivisor = bigMultiplyPowerTen(divisor, raise); + return divideAndRound(dividend, scaledDivisor, scale, roundingMode, scale); + } + } + } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/math/BigInteger.java --- a/jdk/src/share/classes/java/math/BigInteger.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/math/BigInteger.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.Random; import java.io.*; +import java.util.Arrays; /** * Immutable arbitrary-precision integers. All operations behave as if @@ -353,27 +354,17 @@ mag = trustedStripLeadingZeroInts(magnitude); } - // Constructs a new BigInteger using a char array with radix=10 - BigInteger(char[] val) { + /* + * Constructs a new BigInteger using a char array with radix=10. + * Sign is precalculated outside and not allowed in the val. + */ + BigInteger(char[] val, int sign, int len) { int cursor = 0, numDigits; - int len = val.length; - - // Check for leading minus sign - int sign = 1; - if (val[0] == '-') { - if (len == 1) - throw new NumberFormatException("Zero length BigInteger"); - sign = -1; - cursor = 1; - } else if (val[0] == '+') { - if (len == 1) - throw new NumberFormatException("Zero length BigInteger"); - cursor = 1; - } // Skip leading zeros and compute number of digits in magnitude - while (cursor < len && Character.digit(val[cursor], 10) == 0) + while (cursor < len && Character.digit(val[cursor], 10) == 0) { cursor++; + } if (cursor == len) { signum = 0; mag = ZERO.mag; @@ -382,7 +373,6 @@ numDigits = len - cursor; signum = sign; - // Pre-allocate array of expected size int numWords; if (len < 10) { @@ -1058,6 +1048,73 @@ } /** + * Package private methods used by BigDecimal code to add a BigInteger + * with a long. Assumes val is not equal to INFLATED. + */ + BigInteger add(long val) { + if (val == 0) + return this; + if (signum == 0) + return valueOf(val); + if (Long.signum(val) == signum) + return new BigInteger(add(mag, Math.abs(val)), signum); + int cmp = compareMagnitude(val); + if (cmp == 0) + return ZERO; + int[] resultMag = (cmp > 0 ? subtract(mag, Math.abs(val)) : subtract(Math.abs(val), mag)); + resultMag = trustedStripLeadingZeroInts(resultMag); + return new BigInteger(resultMag, cmp == signum ? 1 : -1); + } + + /** + * Adds the contents of the int array x and long value val. This + * method allocates a new int array to hold the answer and returns + * a reference to that array. Assumes x.length > 0 and val is + * non-negative + */ + private static int[] add(int[] x, long val) { + int[] y; + long sum = 0; + int xIndex = x.length; + int[] result; + int highWord = (int)(val >>> 32); + if (highWord==0) { + result = new int[xIndex]; + sum = (x[--xIndex] & LONG_MASK) + val; + result[xIndex] = (int)sum; + } else { + if (xIndex == 1) { + result = new int[2]; + sum = val + (x[0] & LONG_MASK); + result[1] = (int)sum; + result[0] = (int)(sum >>> 32); + return result; + } else { + result = new int[xIndex]; + sum = (x[--xIndex] & LONG_MASK) + (val & LONG_MASK); + result[xIndex] = (int)sum; + sum = (x[--xIndex] & LONG_MASK) + (highWord & LONG_MASK) + (sum >>> 32); + result[xIndex] = (int)sum; + } + } + // Copy remainder of longer number while carry propagation is required + boolean carry = (sum >>> 32 != 0); + while (xIndex > 0 && carry) + carry = ((result[--xIndex] = x[xIndex] + 1) == 0); + // Copy remainder of longer number + while (xIndex > 0) + result[--xIndex] = x[xIndex]; + // Grow result if necessary + if (carry) { + int bigger[] = new int[result.length + 1]; + System.arraycopy(result, 0, bigger, 1, result.length); + bigger[0] = 0x01; + return bigger; + } + return result; + } + + /** * Adds the contents of the int arrays x and y. This method allocates * a new int array to hold the answer and returns a reference to that * array. @@ -1074,14 +1131,17 @@ int yIndex = y.length; int result[] = new int[xIndex]; long sum = 0; - - // Add common parts of both numbers - while(yIndex > 0) { - sum = (x[--xIndex] & LONG_MASK) + - (y[--yIndex] & LONG_MASK) + (sum >>> 32); + if(yIndex==1) { + sum = (x[--xIndex] & LONG_MASK) + (y[0] & LONG_MASK) ; result[xIndex] = (int)sum; + } else { + // Add common parts of both numbers + while(yIndex > 0) { + sum = (x[--xIndex] & LONG_MASK) + + (y[--yIndex] & LONG_MASK) + (sum >>> 32); + result[xIndex] = (int)sum; + } } - // Copy remainder of longer number while carry propagation is required boolean carry = (sum >>> 32 != 0); while (xIndex > 0 && carry) @@ -1101,6 +1161,71 @@ return result; } + private static int[] subtract(long val, int[] little) { + int highWord = (int)(val >>> 32); + if (highWord==0) { + int result[] = new int[1]; + result[0] = (int)(val - (little[0] & LONG_MASK)); + return result; + } else { + int result[] = new int[2]; + if(little.length==1) { + long difference = ((int)val & LONG_MASK) - (little[0] & LONG_MASK); + result[1] = (int)difference; + // Subtract remainder of longer number while borrow propagates + boolean borrow = (difference >> 32 != 0); + if(borrow) { + result[0] = highWord - 1; + } else { // Copy remainder of longer number + result[0] = highWord; + } + return result; + } else { // little.length==2 + long difference = ((int)val & LONG_MASK) - (little[1] & LONG_MASK); + result[1] = (int)difference; + difference = (highWord & LONG_MASK) - (little[0] & LONG_MASK) + (difference >> 32); + result[0] = (int)difference; + return result; + } + } + } + + /** + * Subtracts the contents of the second argument (val) from the + * first (big). The first int array (big) must represent a larger number + * than the second. This method allocates the space necessary to hold the + * answer. + * assumes val >= 0 + */ + private static int[] subtract(int[] big, long val) { + int highWord = (int)(val >>> 32); + int bigIndex = big.length; + int result[] = new int[bigIndex]; + long difference = 0; + + if (highWord==0) { + difference = (big[--bigIndex] & LONG_MASK) - val; + result[bigIndex] = (int)difference; + } else { + difference = (big[--bigIndex] & LONG_MASK) - (val & LONG_MASK); + result[bigIndex] = (int)difference; + difference = (big[--bigIndex] & LONG_MASK) - (highWord & LONG_MASK) + (difference >> 32); + result[bigIndex] = (int)difference; + } + + + // Subtract remainder of longer number while borrow propagates + boolean borrow = (difference >> 32 != 0); + while (bigIndex > 0 && borrow) + borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1); + + // Copy remainder of longer number + while (bigIndex > 0) + result[--bigIndex] = big[bigIndex]; + + return result; + } + /** * Returns a BigInteger whose value is {@code (this - val)}. * @@ -1165,11 +1290,39 @@ public BigInteger multiply(BigInteger val) { if (val.signum == 0 || signum == 0) return ZERO; - + int resultSign = signum == val.signum ? 1 : -1; + if (val.mag.length == 1) { + return multiplyByInt(mag,val.mag[0], resultSign); + } + if(mag.length == 1) { + return multiplyByInt(val.mag,mag[0], resultSign); + } int[] result = multiplyToLen(mag, mag.length, val.mag, val.mag.length, null); result = trustedStripLeadingZeroInts(result); - return new BigInteger(result, signum == val.signum ? 1 : -1); + return new BigInteger(result, resultSign); + } + + private static BigInteger multiplyByInt(int[] x, int y, int sign) { + if(Integer.bitCount(y)==1) { + return new BigInteger(shiftLeft(x,Integer.numberOfTrailingZeros(y)), sign); + } + int xlen = x.length; + int[] rmag = new int[xlen + 1]; + long carry = 0; + long yl = y & LONG_MASK; + int rstart = rmag.length - 1; + for (int i = xlen - 1; i >= 0; i--) { + long product = (x[i] & LONG_MASK) * yl + carry; + rmag[rstart--] = (int)product; + carry = product >>> 32; + } + if (carry == 0L) { + rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length); + } else { + rmag[rstart] = (int)carry; + } + return new BigInteger(rmag, sign); } /** @@ -1339,8 +1492,8 @@ a = new MutableBigInteger(this.mag), b = new MutableBigInteger(val.mag); - a.divide(b, q); - return q.toBigInteger(this.signum == val.signum ? 1 : -1); + a.divide(b, q, false); + return q.toBigInteger(this.signum * val.signum); } /** @@ -1460,14 +1613,12 @@ } else { // Array must be resized if (nBits <= (32-bitsInHighWord)) { int result[] = new int[nInts+len]; - for (int i=0; i>> 5; int[] mag = new int[numInts]; - for (int i=0; i>> 5; int nBits = n & 0x1f; int magLen = mag.length; @@ -2077,8 +2227,7 @@ if (nBits == 0) { newMag = new int[magLen + nInts]; - for (int i=0; i>> nBits2; newMag[i] = mag[j] << nBits; } - - return new BigInteger(newMag, signum); + return newMag; } /** @@ -2132,9 +2280,7 @@ if (nBits == 0) { int newMagLen = magLen - nInts; - newMag = new int[newMagLen]; - for (int i=0; i>> nBits; @@ -2405,7 +2551,7 @@ if (signum < 0) { // Check if magnitude is a power of two boolean pow2 = (Integer.bitCount(mag[0]) == 1); - for(int i=1; i< len && pow2; i++) + for (int i=1; i< len && pow2; i++) pow2 = (mag[i] == 0); n = (pow2 ? magBitLength -1 : magBitLength); @@ -2530,6 +2676,49 @@ } /** + * Version of compareMagnitude that compares magnitude with long value. + * val can't be Long.MIN_VALUE. + */ + final int compareMagnitude(long val) { + assert val != Long.MIN_VALUE; + int[] m1 = mag; + int len = m1.length; + if(len > 2) { + return 1; + } + if (val < 0) { + val = -val; + } + int highWord = (int)(val >>> 32); + if (highWord==0) { + if (len < 1) + return -1; + if (len > 1) + return 1; + int a = m1[0]; + int b = (int)val; + if (a != b) { + return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1; + } + return 0; + } else { + if (len < 2) + return -1; + int a = m1[0]; + int b = highWord; + if (a != b) { + return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1; + } + a = m1[1]; + b = (int)val; + if (a != b) { + return ((a & LONG_MASK) < (b & LONG_MASK))? -1 : 1; + } + return 0; + } + } + + /** * Compares this BigInteger with the specified Object for equality. * * @param x Object to which this BigInteger is to be compared. @@ -3114,25 +3303,35 @@ } // Commit final fields via Unsafe - unsafe.putIntVolatile(this, signumOffset, sign); + UnsafeHolder.putSign(this, sign); // Calculate mag field from magnitude and discard magnitude - unsafe.putObjectVolatile(this, magOffset, - stripLeadingZeroBytes(magnitude)); + UnsafeHolder.putMag(this, stripLeadingZeroBytes(magnitude)); } // Support for resetting final fields while deserializing - private static final sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe(); - private static final long signumOffset; - private static final long magOffset; - static { - try { - signumOffset = unsafe.objectFieldOffset - (BigInteger.class.getDeclaredField("signum")); - magOffset = unsafe.objectFieldOffset - (BigInteger.class.getDeclaredField("mag")); - } catch (Exception ex) { - throw new Error(ex); + private static class UnsafeHolder { + private static final sun.misc.Unsafe unsafe; + private static final long signumOffset; + private static final long magOffset; + static { + try { + unsafe = sun.misc.Unsafe.getUnsafe(); + signumOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("signum")); + magOffset = unsafe.objectFieldOffset + (BigInteger.class.getDeclaredField("mag")); + } catch (Exception ex) { + throw new ExceptionInInitializerError(ex); + } + } + + static void putSign(BigInteger bi, int sign) { + unsafe.putIntVolatile(bi, signumOffset, sign); + } + + static void putMag(BigInteger bi, int[] magnitude) { + unsafe.putObjectVolatile(bi, magOffset, magnitude); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/math/MutableBigInteger.java --- a/jdk/src/share/classes/java/math/MutableBigInteger.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/math/MutableBigInteger.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -160,7 +160,7 @@ */ BigDecimal toBigDecimal(int sign, int scale) { if (intLen == 0 || sign == 0) - return BigDecimal.valueOf(0, scale); + return BigDecimal.zeroValueOf(scale); int[] mag = getMagnitudeArray(); int len = mag.length; int d = mag[0]; @@ -171,7 +171,28 @@ long v = (len == 2) ? ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) : d & LONG_MASK; - return new BigDecimal(null, sign == -1 ? -v : v, scale, 0); + return BigDecimal.valueOf(sign == -1 ? -v : v, scale); + } + + /** + * This is for internal use in converting from a MutableBigInteger + * object into a long value given a specified sign. + * returns INFLATED if value is not fit into long + */ + long toCompactValue(int sign) { + if (intLen == 0 || sign == 0) + return 0L; + int[] mag = getMagnitudeArray(); + int len = mag.length; + int d = mag[0]; + // If this MutableBigInteger can not be fitted into long, we need to + // make a BigInteger object for the resultant BigDecimal object. + if (len > 2 || (d < 0 && len == 2)) + return INFLATED; + long v = (len == 2) ? + ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) : + d & LONG_MASK; + return sign == -1 ? -v : v; } /** @@ -544,6 +565,24 @@ } /** + * The method is the same as mulsun, except the fact that q array is not + * updated, the only result of the method is borrow flag. + */ + private int mulsubBorrow(int[] q, int[] a, int x, int len, int offset) { + long xLong = x & LONG_MASK; + long carry = 0; + offset += len; + for (int j=len-1; j >= 0; j--) { + long product = (a[j] & LONG_MASK) * xLong + carry; + long difference = q[offset--] - product; + carry = (product >>> 32) + + (((difference & LONG_MASK) > + (((~(int)product) & LONG_MASK))) ? 1:0); + } + return (int)carry; + } + + /** * Right shift this MutableBigInteger n bits, where n is * less than 32. * Assumes that intLen > 0, n > 0 for speed @@ -842,20 +881,20 @@ rem = (int) (remLong - (quotient.value[0] * divisorLong)); remLong = rem & LONG_MASK; } - int xlen = intLen; - int[] qWord = new int[2]; while (--xlen > 0) { - long dividendEstimate = (remLong<<32) | - (value[offset + intLen - xlen] & LONG_MASK); + long dividendEstimate = (remLong << 32) | + (value[offset + intLen - xlen] & LONG_MASK); + int q; if (dividendEstimate >= 0) { - qWord[0] = (int) (dividendEstimate / divisorLong); - qWord[1] = (int) (dividendEstimate - qWord[0] * divisorLong); + q = (int) (dividendEstimate / divisorLong); + rem = (int) (dividendEstimate - q * divisorLong); } else { - divWord(qWord, dividendEstimate, divisor); + long tmp = divWord(dividendEstimate, divisor); + q = (int) (tmp & LONG_MASK); + rem = (int) (tmp >>> 32); } - quotient.value[intLen - xlen] = qWord[0]; - rem = qWord[1]; + quotient.value[intLen - xlen] = q; remLong = rem & LONG_MASK; } @@ -879,40 +918,45 @@ * */ MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) { + return divide(b,quotient,true); + } + + MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient, boolean needReminder) { if (b.intLen == 0) throw new ArithmeticException("BigInteger divide by zero"); // Dividend is zero if (intLen == 0) { quotient.intLen = quotient.offset; - return new MutableBigInteger(); + return needReminder ? new MutableBigInteger() : null; } int cmp = compare(b); // Dividend less than divisor if (cmp < 0) { quotient.intLen = quotient.offset = 0; - return new MutableBigInteger(this); + return needReminder ? new MutableBigInteger(this) : null; } // Dividend equal to divisor if (cmp == 0) { quotient.value[0] = quotient.intLen = 1; quotient.offset = 0; - return new MutableBigInteger(); + return needReminder ? new MutableBigInteger() : null; } quotient.clear(); // Special case one word divisor if (b.intLen == 1) { int r = divideOneWord(b.value[b.offset], quotient); - if (r == 0) - return new MutableBigInteger(); - return new MutableBigInteger(r); + if(needReminder) { + if (r == 0) + return new MutableBigInteger(); + return new MutableBigInteger(r); + } else { + return null; + } } - - // Copy divisor value to protect divisor - int[] div = Arrays.copyOfRange(b.value, b.offset, b.offset + b.intLen); - return divideMagnitude(div, quotient); + return divideMagnitude(b, quotient, needReminder); } /** @@ -940,30 +984,72 @@ if (d == 0) return divideOneWord((int)v, quotient) & LONG_MASK; else { - int[] div = new int[]{ d, (int)(v & LONG_MASK) }; - return divideMagnitude(div, quotient).toLong(); + return divideLongMagnitude(v, quotient).toLong(); } } + private static void copyAndShift(int[] src, int srcFrom, int srcLen, int[] dst, int dstFrom, int shift) { + int n2 = 32 - shift; + int c=src[srcFrom]; + for (int i=0; i < srcLen-1; i++) { + int b = c; + c = src[++srcFrom]; + dst[dstFrom+i] = (b << shift) | (c >>> n2); + } + dst[dstFrom+srcLen-1] = c << shift; + } + /** - * Divide this MutableBigInteger by the divisor represented by its magnitude - * array. The quotient will be placed into the provided quotient object & + * Divide this MutableBigInteger by the divisor. + * The quotient will be placed into the provided quotient object & * the remainder object is returned. */ - private MutableBigInteger divideMagnitude(int[] divisor, - MutableBigInteger quotient) { - - // Remainder starts as dividend with space for a leading zero - MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]); - System.arraycopy(value, offset, rem.value, 1, intLen); - rem.intLen = intLen; - rem.offset = 1; + private MutableBigInteger divideMagnitude(MutableBigInteger div, + MutableBigInteger quotient, + boolean needReminder ) { + // assert div.intLen > 1 + // D1 normalize the divisor + int shift = Integer.numberOfLeadingZeros(div.value[div.offset]); + // Copy divisor value to protect divisor + final int dlen = div.intLen; + int[] divisor; + MutableBigInteger rem; // Remainder starts as dividend with space for a leading zero + if (shift > 0) { + divisor = new int[dlen]; + copyAndShift(div.value,div.offset,dlen,divisor,0,shift); + if(Integer.numberOfLeadingZeros(value[offset])>=shift) { + int[] remarr = new int[intLen + 1]; + rem = new MutableBigInteger(remarr); + rem.intLen = intLen; + rem.offset = 1; + copyAndShift(value,offset,intLen,remarr,1,shift); + } else { + int[] remarr = new int[intLen + 2]; + rem = new MutableBigInteger(remarr); + rem.intLen = intLen+1; + rem.offset = 1; + int rFrom = offset; + int c=0; + int n2 = 32 - shift; + for (int i=1; i < intLen+1; i++,rFrom++) { + int b = c; + c = value[rFrom]; + remarr[i] = (b << shift) | (c >>> n2); + } + remarr[intLen+1] = c << shift; + } + } else { + divisor = Arrays.copyOfRange(div.value, div.offset, div.offset + div.intLen); + rem = new MutableBigInteger(new int[intLen + 1]); + System.arraycopy(value, offset, rem.value, 1, intLen); + rem.intLen = intLen; + rem.offset = 1; + } int nlen = rem.intLen; // Set the quotient size - int dlen = divisor.length; - int limit = nlen - dlen + 1; + final int limit = nlen - dlen + 1; if (quotient.value.length < limit) { quotient.value = new int[limit]; quotient.offset = 0; @@ -971,14 +1057,6 @@ quotient.intLen = limit; int[] q = quotient.value; - // D1 normalize the divisor - int shift = Integer.numberOfLeadingZeros(divisor[0]); - if (shift > 0) { - // First shift will not grow array - BigInteger.primitiveLeftShift(divisor, dlen, shift); - // But this one might - rem.leftShift(shift); - } // Must insert leading 0 in rem if its length did not change if (rem.intLen == nlen) { @@ -990,10 +1068,9 @@ int dh = divisor[0]; long dhLong = dh & LONG_MASK; int dl = divisor[1]; - int[] qWord = new int[2]; // D2 Initialize j - for(int j=0; j>> 32); } } @@ -1053,6 +1130,181 @@ // Store the quotient digit q[j] = qhat; } // D7 loop on j + // D3 Calculate qhat + // estimate qhat + int qhat = 0; + int qrem = 0; + boolean skipCorrection = false; + int nh = rem.value[limit - 1 + rem.offset]; + int nh2 = nh + 0x80000000; + int nm = rem.value[limit + rem.offset]; + + if (nh == dh) { + qhat = ~0; + qrem = nh + nm; + skipCorrection = qrem + 0x80000000 < nh2; + } else { + long nChunk = (((long) nh) << 32) | (nm & LONG_MASK); + if (nChunk >= 0) { + qhat = (int) (nChunk / dhLong); + qrem = (int) (nChunk - (qhat * dhLong)); + } else { + long tmp = divWord(nChunk, dh); + qhat = (int) (tmp & LONG_MASK); + qrem = (int) (tmp >>> 32); + } + } + if (qhat != 0) { + if (!skipCorrection) { // Correct qhat + long nl = rem.value[limit + 1 + rem.offset] & LONG_MASK; + long rs = ((qrem & LONG_MASK) << 32) | nl; + long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK); + + if (unsignedLongCompare(estProduct, rs)) { + qhat--; + qrem = (int) ((qrem & LONG_MASK) + dhLong); + if ((qrem & LONG_MASK) >= dhLong) { + estProduct -= (dl & LONG_MASK); + rs = ((qrem & LONG_MASK) << 32) | nl; + if (unsignedLongCompare(estProduct, rs)) + qhat--; + } + } + } + + + // D4 Multiply and subtract + int borrow; + rem.value[limit - 1 + rem.offset] = 0; + if(needReminder) + borrow = mulsub(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset); + else + borrow = mulsubBorrow(rem.value, divisor, qhat, dlen, limit - 1 + rem.offset); + + // D5 Test remainder + if (borrow + 0x80000000 > nh2) { + // D6 Add back + if(needReminder) + divadd(divisor, rem.value, limit - 1 + 1 + rem.offset); + qhat--; + } + + // Store the quotient digit + q[(limit - 1)] = qhat; + } + + + if(needReminder) { + // D8 Unnormalize + if (shift > 0) + rem.rightShift(shift); + rem.normalize(); + } + quotient.normalize(); + return needReminder ? rem : null; + } + + /** + * Divide this MutableBigInteger by the divisor represented by positive long + * value. The quotient will be placed into the provided quotient object & + * the remainder object is returned. + */ + private MutableBigInteger divideLongMagnitude(long ldivisor, MutableBigInteger quotient) { + // Remainder starts as dividend with space for a leading zero + MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]); + System.arraycopy(value, offset, rem.value, 1, intLen); + rem.intLen = intLen; + rem.offset = 1; + + int nlen = rem.intLen; + + int limit = nlen - 2 + 1; + if (quotient.value.length < limit) { + quotient.value = new int[limit]; + quotient.offset = 0; + } + quotient.intLen = limit; + int[] q = quotient.value; + + // D1 normalize the divisor + int shift = Long.numberOfLeadingZeros(ldivisor); + if (shift > 0) { + ldivisor<<=shift; + rem.leftShift(shift); + } + + // Must insert leading 0 in rem if its length did not change + if (rem.intLen == nlen) { + rem.offset = 0; + rem.value[0] = 0; + rem.intLen++; + } + + int dh = (int)(ldivisor >>> 32); + long dhLong = dh & LONG_MASK; + int dl = (int)(ldivisor & LONG_MASK); + + // D2 Initialize j + for (int j = 0; j < limit; j++) { + // D3 Calculate qhat + // estimate qhat + int qhat = 0; + int qrem = 0; + boolean skipCorrection = false; + int nh = rem.value[j + rem.offset]; + int nh2 = nh + 0x80000000; + int nm = rem.value[j + 1 + rem.offset]; + + if (nh == dh) { + qhat = ~0; + qrem = nh + nm; + skipCorrection = qrem + 0x80000000 < nh2; + } else { + long nChunk = (((long) nh) << 32) | (nm & LONG_MASK); + if (nChunk >= 0) { + qhat = (int) (nChunk / dhLong); + qrem = (int) (nChunk - (qhat * dhLong)); + } else { + long tmp = divWord(nChunk, dh); + qhat =(int)(tmp & LONG_MASK); + qrem = (int)(tmp>>>32); + } + } + + if (qhat == 0) + continue; + + if (!skipCorrection) { // Correct qhat + long nl = rem.value[j + 2 + rem.offset] & LONG_MASK; + long rs = ((qrem & LONG_MASK) << 32) | nl; + long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK); + + if (unsignedLongCompare(estProduct, rs)) { + qhat--; + qrem = (int) ((qrem & LONG_MASK) + dhLong); + if ((qrem & LONG_MASK) >= dhLong) { + estProduct -= (dl & LONG_MASK); + rs = ((qrem & LONG_MASK) << 32) | nl; + if (unsignedLongCompare(estProduct, rs)) + qhat--; + } + } + } + + // D4 Multiply and subtract + rem.value[j + rem.offset] = 0; + int borrow = mulsubLong(rem.value, dh, dl, qhat, j + rem.offset); + + // D5 Test remainder + if (borrow + 0x80000000 > nh2) { + // D6 Add back + divaddLong(dh,dl, rem.value, j + 1 + rem.offset); + qhat--; + } + + // Store the quotient digit + q[j] = qhat; + } // D7 loop on j // D8 Unnormalize if (shift > 0) @@ -1064,6 +1316,46 @@ } /** + * A primitive used for division by long. + * Specialized version of the method divadd. + * dh is a high part of the divisor, dl is a low part + */ + private int divaddLong(int dh, int dl, int[] result, int offset) { + long carry = 0; + + long sum = (dl & LONG_MASK) + (result[1+offset] & LONG_MASK); + result[1+offset] = (int)sum; + + sum = (dh & LONG_MASK) + (result[offset] & LONG_MASK) + carry; + result[offset] = (int)sum; + carry = sum >>> 32; + return (int)carry; + } + + /** + * This method is used for division by long. + * Specialized version of the method sulsub. + * dh is a high part of the divisor, dl is a low part + */ + private int mulsubLong(int[] q, int dh, int dl, int x, int offset) { + long xLong = x & LONG_MASK; + offset += 2; + long product = (dl & LONG_MASK) * xLong; + long difference = q[offset] - product; + q[offset--] = (int)difference; + long carry = (product >>> 32) + + (((difference & LONG_MASK) > + (((~(int)product) & LONG_MASK))) ? 1:0); + product = (dh & LONG_MASK) * xLong + carry; + difference = q[offset] - product; + q[offset--] = (int)difference; + carry = (product >>> 32) + + (((difference & LONG_MASK) > + (((~(int)product) & LONG_MASK))) ? 1:0); + return (int)carry; + } + + /** * Compare two longs as if they were unsigned. * Returns true iff one is bigger than two. */ @@ -1075,19 +1367,22 @@ * This method divides a long quantity by an int to estimate * qhat for two multi precision numbers. It is used when * the signed value of n is less than zero. + * Returns long value where high 32 bits contain reminder value and + * low 32 bits contain quotient value. */ - private void divWord(int[] result, long n, int d) { + static long divWord(long n, int d) { long dLong = d & LONG_MASK; - + long r; + long q; if (dLong == 1) { - result[0] = (int)n; - result[1] = 0; - return; + q = (int)n; + r = 0; + return (r << 32) | (q & LONG_MASK); } // Approximate the quotient and remainder - long q = (n >>> 1) / (dLong >>> 1); - long r = n - q*dLong; + q = (n >>> 1) / (dLong >>> 1); + r = n - q*dLong; // Correct the approximation while (r < 0) { @@ -1098,10 +1393,8 @@ r -= dLong; q++; } - // n - q*dlong == r && 0 <= r - * If you read from a socket input stream after invoking - * shutdownInput() on the socket, the stream will return EOF. + * If you read from a socket input stream after invoking this method on the + * socket, the stream's {@code available} method will return 0, and its + * {@code read} methods will return {@code -1} (end of stream). * * @exception IOException if an I/O error occurs when shutting down this * socket. diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/net/SocketImpl.java --- a/jdk/src/share/classes/java/net/SocketImpl.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/net/SocketImpl.java Fri Sep 23 16:51:29 2011 -0700 @@ -181,8 +181,9 @@ * Any data sent to this socket is acknowledged and then * silently discarded. * - * If you read from a socket input stream after invoking - * shutdownInput() on the socket, the stream will return EOF. + * If you read from a socket input stream after invoking this method on the + * socket, the stream's {@code available} method will return 0, and its + * {@code read} methods will return {@code -1} (end of stream). * * @exception IOException if an I/O error occurs when shutting down this * socket. diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/net/URI.java --- a/jdk/src/share/classes/java/net/URI.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/net/URI.java Fri Sep 23 16:51:29 2011 -0700 @@ -1711,6 +1711,8 @@ i++; continue; } + if (d != '%') + return false; i++; if (toLower(s.charAt(i)) != toLower(t.charAt(i))) return false; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/rmi/dgc/VMID.java --- a/jdk/src/share/classes/java/rmi/dgc/VMID.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/rmi/dgc/VMID.java Fri Sep 23 16:51:29 2011 -0700 @@ -170,7 +170,7 @@ /* can't happen, but be deterministic anyway. */ addrHash = new byte[0]; } catch (NoSuchAlgorithmException complain) { - throw new InternalError(complain.toString()); + throw new InternalError(complain.toString(), complain); } return addrHash; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java --- a/jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/CollectionCertStoreParameters.java Fri Sep 23 16:51:29 2011 -0700 @@ -122,7 +122,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java --- a/jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/LDAPCertStoreParameters.java Fri Sep 23 16:51:29 2011 -0700 @@ -128,7 +128,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java --- a/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java Fri Sep 23 16:51:29 2011 -0700 @@ -175,7 +175,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java --- a/jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathValidatorResult.java Fri Sep 23 16:51:29 2011 -0700 @@ -136,7 +136,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/PKIXParameters.java --- a/jdk/src/share/classes/java/security/cert/PKIXParameters.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/PKIXParameters.java Fri Sep 23 16:51:29 2011 -0700 @@ -683,7 +683,7 @@ return copy; } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/X509CRLSelector.java --- a/jdk/src/share/classes/java/security/cert/X509CRLSelector.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/X509CRLSelector.java Fri Sep 23 16:51:29 2011 -0700 @@ -708,7 +708,7 @@ return copy; } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/security/cert/X509CertSelector.java --- a/jdk/src/share/classes/java/security/cert/X509CertSelector.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/security/cert/X509CertSelector.java Fri Sep 23 16:51:29 2011 -0700 @@ -2615,7 +2615,7 @@ return copy; } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/AttributedString.java --- a/jdk/src/share/classes/java/text/AttributedString.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/AttributedString.java Fri Sep 23 16:51:29 2011 -0700 @@ -794,7 +794,7 @@ return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/BreakDictionary.java --- a/jdk/src/share/classes/java/text/BreakDictionary.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/BreakDictionary.java Fri Sep 23 16:51:29 2011 -0700 @@ -154,7 +154,7 @@ ); } catch (PrivilegedActionException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } byte[] buf = new byte[8]; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/BreakIterator.java --- a/jdk/src/share/classes/java/text/BreakIterator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/BreakIterator.java Fri Sep 23 16:51:29 2011 -0700 @@ -254,7 +254,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } @@ -617,7 +617,7 @@ } } catch (Exception e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/Collator.java --- a/jdk/src/share/classes/java/text/Collator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/Collator.java Fri Sep 23 16:51:29 2011 -0700 @@ -461,7 +461,7 @@ try { return (Collator)super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/DateFormatSymbols.java --- a/jdk/src/share/classes/java/text/DateFormatSymbols.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/DateFormatSymbols.java Fri Sep 23 16:51:29 2011 -0700 @@ -597,7 +597,7 @@ copyMembers(this, other); return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/DecimalFormat.java --- a/jdk/src/share/classes/java/text/DecimalFormat.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/DecimalFormat.java Fri Sep 23 16:51:29 2011 -0700 @@ -1891,14 +1891,10 @@ * Standard override; no change in semantics. */ public Object clone() { - try { - DecimalFormat other = (DecimalFormat) super.clone(); - other.symbols = (DecimalFormatSymbols) symbols.clone(); - other.digitList = (DigitList) digitList.clone(); - return other; - } catch (Exception e) { - throw new InternalError(); - } + DecimalFormat other = (DecimalFormat) super.clone(); + other.symbols = (DecimalFormatSymbols) symbols.clone(); + other.digitList = (DigitList) digitList.clone(); + return other; } /** diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/DecimalFormatSymbols.java --- a/jdk/src/share/classes/java/text/DecimalFormatSymbols.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/DecimalFormatSymbols.java Fri Sep 23 16:51:29 2011 -0700 @@ -479,7 +479,7 @@ return (DecimalFormatSymbols)super.clone(); // other fields are bit-copied } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/DigitList.java --- a/jdk/src/share/classes/java/text/DigitList.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/DigitList.java Fri Sep 23 16:51:29 2011 -0700 @@ -632,7 +632,7 @@ other.tempBuffer = null; return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/Format.java --- a/jdk/src/share/classes/java/text/Format.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/Format.java Fri Sep 23 16:51:29 2011 -0700 @@ -258,7 +258,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // will never happen - return null; + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/RuleBasedBreakIterator.java --- a/jdk/src/share/classes/java/text/RuleBasedBreakIterator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/RuleBasedBreakIterator.java Fri Sep 23 16:51:29 2011 -0700 @@ -453,7 +453,7 @@ ); } catch (PrivilegedActionException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } int offset = 0; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/text/StringCharacterIterator.java --- a/jdk/src/share/classes/java/text/StringCharacterIterator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/text/StringCharacterIterator.java Fri Sep 23 16:51:29 2011 -0700 @@ -272,7 +272,7 @@ return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/ArrayList.java --- a/jdk/src/share/classes/java/util/ArrayList.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/ArrayList.java Fri Sep 23 16:51:29 2011 -0700 @@ -307,7 +307,7 @@ return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/BitSet.java --- a/jdk/src/share/classes/java/util/BitSet.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/BitSet.java Fri Sep 23 16:51:29 2011 -0700 @@ -1092,7 +1092,7 @@ result.checkInvariants(); return result; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/Calendar.java --- a/jdk/src/share/classes/java/util/Calendar.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/Calendar.java Fri Sep 23 16:51:29 2011 -0700 @@ -2512,7 +2512,7 @@ } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/Currency.java --- a/jdk/src/share/classes/java/util/Currency.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/Currency.java Fri Sep 23 16:51:29 2011 -0700 @@ -221,9 +221,7 @@ otherCurrenciesNumericCode = readIntArray(dis, ocCount); dis.close(); } catch (IOException e) { - InternalError ie = new InternalError(); - ie.initCause(e); - throw ie; + throw new InternalError(e); } // look for the properties file for overrides diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/HashSet.java --- a/jdk/src/share/classes/java/util/HashSet.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/HashSet.java Fri Sep 23 16:51:29 2011 -0700 @@ -253,7 +253,7 @@ newSet.map = (HashMap) map.clone(); return newSet; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/Hashtable.java --- a/jdk/src/share/classes/java/util/Hashtable.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/Hashtable.java Fri Sep 23 16:51:29 2011 -0700 @@ -537,7 +537,7 @@ return t; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/IdentityHashMap.java --- a/jdk/src/share/classes/java/util/IdentityHashMap.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/IdentityHashMap.java Fri Sep 23 16:51:29 2011 -0700 @@ -703,7 +703,7 @@ m.table = table.clone(); return m; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/LinkedList.java --- a/jdk/src/share/classes/java/util/LinkedList.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/LinkedList.java Fri Sep 23 16:51:29 2011 -0700 @@ -994,7 +994,7 @@ try { return (LinkedList) super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/Locale.java --- a/jdk/src/share/classes/java/util/Locale.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/Locale.java Fri Sep 23 16:51:29 2011 -0700 @@ -1859,7 +1859,7 @@ Locale that = (Locale)super.clone(); return that; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/ResourceBundle.java --- a/jdk/src/share/classes/java/util/ResourceBundle.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/ResourceBundle.java Fri Sep 23 16:51:29 2011 -0700 @@ -614,7 +614,7 @@ return clone; } catch (CloneNotSupportedException e) { //this should never happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/TimeZone.java --- a/jdk/src/share/classes/java/util/TimeZone.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/TimeZone.java Fri Sep 23 16:51:29 2011 -0700 @@ -739,7 +739,7 @@ other.ID = ID; return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/TreeMap.java --- a/jdk/src/share/classes/java/util/TreeMap.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/TreeMap.java Fri Sep 23 16:51:29 2011 -0700 @@ -622,7 +622,7 @@ try { clone = (TreeMap) super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } // Put clone into "virgin" state (except for comparator) diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/TreeSet.java --- a/jdk/src/share/classes/java/util/TreeSet.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/TreeSet.java Fri Sep 23 16:51:29 2011 -0700 @@ -474,7 +474,7 @@ try { clone = (TreeSet) super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } clone.m = new TreeMap<>(m); diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/UUID.java --- a/jdk/src/share/classes/java/util/UUID.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/UUID.java Fri Sep 23 16:51:29 2011 -0700 @@ -165,7 +165,7 @@ try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException nsae) { - throw new InternalError("MD5 not supported"); + throw new InternalError("MD5 not supported", nsae); } byte[] md5Bytes = md.digest(name); md5Bytes[6] &= 0x0f; /* clear version */ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/Vector.java --- a/jdk/src/share/classes/java/util/Vector.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/Vector.java Fri Sep 23 16:51:29 2011 -0700 @@ -673,7 +673,7 @@ return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/java/util/zip/ZipEntry.java --- a/jdk/src/share/classes/java/util/zip/ZipEntry.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java Fri Sep 23 16:51:29 2011 -0700 @@ -321,7 +321,7 @@ return e; } catch (CloneNotSupportedException e) { // This should never happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java --- a/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/javax/management/openmbean/TabularDataSupport.java Fri Sep 23 16:51:29 2011 -0700 @@ -671,7 +671,7 @@ return c; } catch (CloneNotSupportedException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/javax/swing/text/ElementIterator.java --- a/jdk/src/share/classes/javax/swing/text/ElementIterator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/javax/swing/text/ElementIterator.java Fri Sep 23 16:51:29 2011 -0700 @@ -157,7 +157,7 @@ } return it; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java --- a/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/javax/swing/text/rtf/RTFReader.java Fri Sep 23 16:51:29 2011 -0700 @@ -528,7 +528,7 @@ try { translationTable = (char[])getCharacterSet("ansi"); } catch (IOException e) { - throw new InternalError("RTFReader: Unable to find character set resources (" + e + ")"); + throw new InternalError("RTFReader: Unable to find character set resources (" + e + ")", e); } } } @@ -1614,7 +1614,7 @@ } catch (BadLocationException ble) { /* This shouldn't be able to happen, of course */ /* TODO is InternalError the correct error to throw? */ - throw new InternalError(ble.getMessage()); + throw new InternalError(ble.getMessage(), ble); } } @@ -1628,7 +1628,7 @@ } catch (BadLocationException ble) { /* This shouldn't be able to happen, of course */ /* TODO is InternalError the correct error to throw? */ - throw new InternalError(ble.getMessage()); + throw new InternalError(ble.getMessage(), ble); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/awt/FontConfiguration.java --- a/jdk/src/share/classes/sun/awt/FontConfiguration.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/awt/FontConfiguration.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,11 +266,20 @@ private File findFontConfigFile(String javaLib) { String baseName = javaLib + File.separator + "fontconfig"; File configFile; + String osMajorVersion = null; if (osVersion != null && osName != null) { configFile = findImpl(baseName + "." + osName + "." + osVersion); if (configFile != null) { return configFile; } + int decimalPointIndex = osVersion.indexOf("."); + if (decimalPointIndex != -1) { + osMajorVersion = osVersion.substring(0, osVersion.indexOf(".")); + configFile = findImpl(baseName + "." + osName + "." + osMajorVersion); + if (configFile != null) { + return configFile; + } + } } if (osName != null) { configFile = findImpl(baseName + "." + osName); @@ -283,6 +292,12 @@ if (configFile != null) { return configFile; } + if (osMajorVersion != null) { + configFile = findImpl(baseName + "." + osMajorVersion); + if (configFile != null) { + return configFile; + } + } } foundOsSpecificFile = false; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java --- a/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/dc/DuctusRenderingEngine.java Fri Sep 23 16:51:29 2011 -0700 @@ -158,7 +158,7 @@ feedConsumer(pi, consumer, normalize, 0.25f); } catch (PathException e) { throw new InternalError("Unable to Stroke shape ("+ - e.getMessage()+")"); + e.getMessage()+")", e); } finally { while (consumer != null && consumer != sr) { PathConsumer next = consumer.getConsumer(); @@ -763,7 +763,7 @@ consumer.endPath(); } catch (PathException e) { throw new InternalError("Unable to Stroke shape ("+ - e.getMessage()+")"); + e.getMessage()+")", e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/font/FontLineMetrics.java --- a/jdk/src/share/classes/sun/font/FontLineMetrics.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/font/FontLineMetrics.java Fri Sep 23 16:51:29 2011 -0700 @@ -113,7 +113,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/font/GlyphLayout.java --- a/jdk/src/share/classes/sun/font/GlyphLayout.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/font/GlyphLayout.java Fri Sep 23 16:51:29 2011 -0700 @@ -233,7 +233,7 @@ invdtx = dtx.createInverse(); } catch (NoninvertibleTransformException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/invoke/util/ValueConversions.java --- a/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/invoke/util/ValueConversions.java Fri Sep 23 16:51:29 2011 -0700 @@ -677,9 +677,7 @@ EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); NEW_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "newArray", MethodType.methodType(Object[].class, int.class)); } catch (NoSuchMethodException | IllegalAccessException ex) { - Error err = new InternalError("uncaught exception"); - err.initCause(ex); - throw err; + throw new InternalError("uncaught exception", ex); } } @@ -693,9 +691,7 @@ COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class)); MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class)); } catch (ReflectiveOperationException ex) { - Error err = new InternalError("uncaught exception"); - err.initCause(ex); - throw err; + throw new InternalError("uncaught exception", ex); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java --- a/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/java2d/pipe/LoopPipe.java Fri Sep 23 16:51:29 2011 -0700 @@ -281,9 +281,8 @@ } catch (Throwable t) { sr.dispose(); sr = null; - t.printStackTrace(); throw new InternalError("Unable to Stroke shape ("+ - t.getMessage()+")"); + t.getMessage()+")", t); } return sr; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java --- a/jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/management/counter/perf/PerfDataEntry.java Fri Sep 23 16:51:29 2011 -0700 @@ -133,7 +133,7 @@ catch (UnsupportedEncodingException e) { // should not reach here // "UTF-8" is always a known encoding - throw new InternalError(e.getMessage()); + throw new InternalError(e.getMessage(), e); } if (variability == Variability.INVALID) { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java --- a/jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/management/counter/perf/PerfDataType.java Fri Sep 23 16:51:29 2011 -0700 @@ -93,7 +93,7 @@ this.value = b[0]; } catch (UnsupportedEncodingException e) { // ignore, "UTF-8" is always a known encoding - throw new InternalError("Unknown encoding"); + throw new InternalError("Unknown encoding", e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/misc/Launcher.java --- a/jdk/src/share/classes/sun/misc/Launcher.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/misc/Launcher.java Fri Sep 23 16:51:29 2011 -0700 @@ -71,7 +71,7 @@ extcl = ExtClassLoader.getExtClassLoader(); } catch (IOException e) { throw new InternalError( - "Could not create extension class loader"); + "Could not create extension class loader", e); } // Now create the class loader to use to launch the application @@ -79,7 +79,7 @@ loader = AppClassLoader.getAppClassLoader(extcl); } catch (IOException e) { throw new InternalError( - "Could not create application class loader"); + "Could not create application class loader", e); } // Also set the context class loader for the primordial thread. @@ -460,7 +460,7 @@ return ParseUtil.fileToEncodedURL(file); } catch (MalformedURLException e) { // Should never happen since we specify the protocol... - throw new InternalError(); + throw new InternalError(e); } } @@ -475,15 +475,10 @@ try { Class c = Class.forName(name); return (URLStreamHandler)c.newInstance(); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); + } catch (ReflectiveOperationException e) { + throw new InternalError("could not load " + protocol + + "system protocol handler", e); } - throw new InternalError("could not load " + protocol + - "system protocol handler"); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/misc/ProxyGenerator.java --- a/jdk/src/share/classes/sun/misc/ProxyGenerator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/misc/ProxyGenerator.java Fri Sep 23 16:51:29 2011 -0700 @@ -460,7 +460,7 @@ methods.add(generateStaticInitializer()); } catch (IOException e) { - throw new InternalError("unexpected I/O Exception"); + throw new InternalError("unexpected I/O Exception", e); } if (methods.size() > 65535) { @@ -540,7 +540,7 @@ dout.writeShort(0); // (no ClassFile attributes for proxy classes) } catch (IOException e) { - throw new InternalError("unexpected I/O Exception"); + throw new InternalError("unexpected I/O Exception", e); } return bout.toByteArray(); diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/NetworkClient.java --- a/jdk/src/share/classes/sun/net/NetworkClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/NetworkClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -139,7 +139,7 @@ serverSocket.getOutputStream()), true, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding +"encoding not found"); + throw new InternalError(encoding +"encoding not found", e); } serverInput = new BufferedInputStream(serverSocket.getInputStream()); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/NetworkServer.java --- a/jdk/src/share/classes/sun/net/NetworkServer.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/NetworkServer.java Fri Sep 23 16:51:29 2011 -0700 @@ -142,7 +142,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java --- a/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/ftp/impl/FtpClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -905,7 +905,7 @@ out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), true, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding + "encoding not found"); + throw new InternalError(encoding + "encoding not found", e); } in = new BufferedInputStream(server.getInputStream()); } @@ -1621,7 +1621,7 @@ out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), true, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding + "encoding not found"); + throw new InternalError(encoding + "encoding not found", e); } in = new BufferedInputStream(server.getInputStream()); } @@ -2056,7 +2056,7 @@ out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), true, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding + "encoding not found"); + throw new InternalError(encoding + "encoding not found", e); } in = new BufferedInputStream(server.getInputStream()); @@ -2090,7 +2090,7 @@ out = new PrintStream(new BufferedOutputStream(server.getOutputStream()), true, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding + "encoding not found"); + throw new InternalError(encoding + "encoding not found", e); } in = new BufferedInputStream(server.getInputStream()); diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/smtp/SmtpClient.java --- a/jdk/src/share/classes/sun/net/smtp/SmtpClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/smtp/SmtpClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -134,7 +134,7 @@ try { message = new SmtpPrintStream(serverOutput, this); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+" encoding not found"); + throw new InternalError(encoding+" encoding not found", e); } return message; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java --- a/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/www/http/ChunkedOutputStream.java Fri Sep 23 16:51:29 2011 -0700 @@ -79,7 +79,7 @@ return header; } catch (java.io.UnsupportedEncodingException e) { /* This should never happen */ - throw new InternalError(e.getMessage()); + throw new InternalError(e.getMessage(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/www/http/HttpClient.java --- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -395,7 +395,7 @@ new BufferedOutputStream(out), false, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+" encoding not found"); + throw new InternalError(encoding+" encoding not found", e); } serverSocket.setTcpNoDelay(true); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java --- a/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/www/protocol/gopher/GopherClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -324,7 +324,7 @@ } } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+ " encoding not found"); + throw new InternalError(encoding+ " encoding not found", e); } catch (IOException e) { } finally { try { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java --- a/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri Sep 23 16:51:29 2011 -0700 @@ -529,7 +529,7 @@ new BufferedOutputStream(serverSocket.getOutputStream()), false, encoding); } catch (UnsupportedEncodingException e) { - throw new InternalError(encoding+" encoding not found"); + throw new InternalError(encoding+" encoding not found", e); } // check URL spoofing if it has not been checked under handshaking diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/nio/ch/Util.java --- a/jdk/src/share/classes/sun/nio/ch/Util.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/nio/ch/Util.java Fri Sep 23 16:51:29 2011 -0700 @@ -373,7 +373,7 @@ NoSuchMethodException | IllegalArgumentException | ClassCastException x) { - throw new InternalError(); + throw new InternalError(x); } return null; }}); @@ -395,7 +395,7 @@ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new InternalError(); + throw new InternalError(e); } return dbb; } @@ -418,7 +418,7 @@ NoSuchMethodException | IllegalArgumentException | ClassCastException x) { - throw new InternalError(); + throw new InternalError(x); } return null; }}); @@ -440,7 +440,7 @@ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new InternalError(); + throw new InternalError(e); } return dbb; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java --- a/jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/nio/cs/AbstractCharsetProvider.java Fri Sep 23 16:51:29 2011 -0700 @@ -179,7 +179,9 @@ public Charset next() { String csn = i.next(); - return lookup(csn); + synchronized (AbstractCharsetProvider.this) { + return lookup(csn); + } } public void remove() { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/reflect/UTF8.java --- a/jdk/src/share/classes/sun/reflect/UTF8.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/reflect/UTF8.java Fri Sep 23 16:51:29 2011 -0700 @@ -52,7 +52,7 @@ } } catch (ArrayIndexOutOfBoundsException e) { throw new InternalError - ("Bug in sun.reflect bootstrap UTF-8 encoder"); + ("Bug in sun.reflect bootstrap UTF-8 encoder", e); } return res; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java --- a/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/reflect/generics/reflectiveObjects/TypeVariableImpl.java Fri Sep 23 16:51:29 2011 -0700 @@ -25,9 +25,11 @@ package sun.reflect.generics.reflectiveObjects; +import java.lang.annotation.Annotation; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; +import java.util.Objects; import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.tree.FieldTypeSignature; @@ -178,4 +180,27 @@ public int hashCode() { return genericDeclaration.hashCode() ^ name.hashCode(); } + + // Currently vacuous implementations of AnnotatedElement methods. + public boolean isAnnotationPresent(Class annotationClass) { + Objects.requireNonNull(annotationClass); + return false; + } + + public T getAnnotation(Class annotationClass) { + Objects.requireNonNull(annotationClass); + return null; + } + + public Annotation[] getAnnotations() { + // Since zero-length, don't need defensive clone + return EMPTY_ANNOTATION_ARRAY; + } + + public Annotation[] getDeclaredAnnotations() { + // Since zero-length, don't need defensive clone + return EMPTY_ANNOTATION_ARRAY; + } + + private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/reflect/misc/MethodUtil.java --- a/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/reflect/misc/MethodUtil.java Fri Sep 23 16:51:29 2011 -0700 @@ -292,7 +292,7 @@ } }); } catch (Exception e) { - throw new InternalError("bouncer cannot be found"); + throw new InternalError("bouncer cannot be found", e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/rmi/transport/LiveRef.java --- a/jdk/src/share/classes/sun/rmi/transport/LiveRef.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/rmi/transport/LiveRef.java Fri Sep 23 16:51:29 2011 -0700 @@ -111,7 +111,7 @@ LiveRef newRef = (LiveRef) super.clone(); return newRef; } catch (CloneNotSupportedException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/krb5/EncryptionKey.java --- a/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/krb5/EncryptionKey.java Fri Sep 23 16:51:29 2011 -0700 @@ -151,11 +151,36 @@ } /** + * Obtains a key for a given etype of a principal with possible new salt + * and s2kparams + * @param cname NOT null + * @param password NOT null + * @param etype + * @param snp can be NULL + * @returns never null + */ + public static EncryptionKey acquireSecretKey(PrincipalName cname, + char[] password, int etype, PAData.SaltAndParams snp) + throws KrbException { + String salt; + byte[] s2kparams; + if (snp != null) { + salt = snp.salt != null ? snp.salt : cname.getSalt(); + s2kparams = snp.params; + } else { + salt = cname.getSalt(); + s2kparams = null; + } + return acquireSecretKey(password, salt, etype, s2kparams); + } + + /** * Obtains a key for a given etype with salt and optional s2kparams * @param password NOT null * @param salt NOT null * @param etype * @param s2kparams can be NULL + * @returns never null */ public static EncryptionKey acquireSecretKey(char[] password, String salt, int etype, byte[] s2kparams) diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/krb5/KrbAsRep.java --- a/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Fri Sep 23 16:51:29 2011 -0700 @@ -131,13 +131,11 @@ KrbAsReq asReq, PrincipalName cname) throws KrbException, Asn1Exception, IOException { int encPartKeyType = rep.encPart.getEType(); - PAData.SaltAndParams snp = - PAData.getSaltAndParams(encPartKeyType, rep.pAData); - EncryptionKey dkey = null; - dkey = EncryptionKey.acquireSecretKey(password, - snp.salt == null ? cname.getSalt() : snp.salt, + EncryptionKey dkey = EncryptionKey.acquireSecretKey( + cname, + password, encPartKeyType, - snp.params); + PAData.getSaltAndParams(encPartKeyType, rep.pAData)); decrypt(dkey, asReq); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java --- a/jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/krb5/KrbAsReqBuilder.java Fri Sep 23 16:51:29 2011 -0700 @@ -169,34 +169,44 @@ * from a keytab on acceptor, but unfortunately (?) Java supports * acceptor using password. In this case, if the service ticket is * encrypted using an etype which we don't have PA-DATA new salt, - * using the default salt is normally wrong (say, case-insensitive + * using the default salt might be wrong (say, case-insensitive * user name). Instead, we would use the new salt of another etype. */ String salt = null; // the saved new salt - for (int i=0; i>>Pre-Authentication Data:"); - System.out.println("\t PA-DATA type = " + pa_type); - } - - switch(pa_type) { - case Krb5.PA_ENC_TIMESTAMP: - if (DEBUG) { - System.out.println("\t PA-ENC-TIMESTAMP"); - } - break; - case Krb5.PA_ETYPE_INFO: - if (pa_value != null) { - DerValue der = new DerValue(pa_value); - while (der.data.available() > 0) { - DerValue value = der.data.getDerValue(); - ETypeInfo info = new ETypeInfo(value); - if (pa_eType == 0) pa_eType = info.getEType(); - if (DEBUG) { - System.out.println("\t PA-ETYPE-INFO etype = " + info.getEType()); - System.out.println("\t PA-ETYPE-INFO salt = " + info.getSalt()); - } - } - } - break; - case Krb5.PA_ETYPE_INFO2: - if (pa_value != null) { - DerValue der = new DerValue(pa_value); - while (der.data.available() > 0) { - DerValue value = der.data.getDerValue(); - ETypeInfo2 info2 = new ETypeInfo2(value); - if (pa_eType == 0) pa_eType = info2.getEType(); - if (DEBUG) { - System.out.println("\t PA-ETYPE-INFO2 etype = " + info2.getEType()); - System.out.println("\t PA-ETYPE-INFO2 salt = " + info2.getSalt()); - } - } - } - break; - default: - // Unknown Pre-auth type - break; + System.out.println(pa_data); } } pa = paList.toArray(new PAData[paList.size()]); @@ -340,10 +297,6 @@ return pa; } - public final int getEType() { - return pa_eType; - } - public final String getErrorString() { return eText; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/krb5/internal/PAData.java --- a/jdk/src/share/classes/sun/security/krb5/internal/PAData.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/krb5/internal/PAData.java Fri Sep 23 16:51:29 2011 -0700 @@ -139,9 +139,56 @@ } /** + * Gets the preferred etype from the PAData array. + * 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored + * 2. ETYPE-INFO2 preferred to ETYPE-INFO + * 3. multiple entries for same etype in one PA-DATA, use the first one. + * 4. Multiple PA-DATA with same type, choose the last one + * (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined). + * @return the etype, or defaultEType if not enough info + * @throws Asn1Exception|IOException if there is an encoding error + */ + public static int getPreferredEType(PAData[] pas, int defaultEType) + throws IOException, Asn1Exception { + + if (pas == null) return defaultEType; + + DerValue d = null, d2 = null; + for (PAData p: pas) { + if (p.getValue() == null) continue; + switch (p.getType()) { + case Krb5.PA_ETYPE_INFO: + d = new DerValue(p.getValue()); + break; + case Krb5.PA_ETYPE_INFO2: + d2 = new DerValue(p.getValue()); + break; + } + } + if (d2 != null) { + while (d2.data.available() > 0) { + DerValue value = d2.data.getDerValue(); + ETypeInfo2 tmp = new ETypeInfo2(value); + if (tmp.getParams() == null) { + // we don't support non-null s2kparams + return tmp.getEType(); + } + } + } + if (d != null) { + while (d.data.available() > 0) { + DerValue value = d.data.getDerValue(); + ETypeInfo tmp = new ETypeInfo(value); + return tmp.getEType(); + } + } + return defaultEType; + } + + /** * A place to store a pair of salt and s2kparams. - * An empty salt is changed to null, to be interopable - * with Windows 2000 server. + * An empty salt is changed to null, to be interoperable + * with Windows 2000 server. This is in fact not correct. */ public static class SaltAndParams { public final String salt; @@ -155,57 +202,120 @@ /** * Fetches salt and s2kparams value for eType in a series of PA-DATAs. - * The preference order is PA-ETYPE-INFO2 > PA-ETYPE-INFO > PA-PW-SALT. - * If multiple PA-DATA for the same etype appears, use the last one. + * 1. ETYPE-INFO2-ENTRY with unknown s2kparams ignored + * 2. PA-ETYPE-INFO2 preferred to PA-ETYPE-INFO preferred to PA-PW-SALT. + * 3. multiple entries for same etype in one PA-DATA, use the first one. + * 4. Multiple PA-DATA with same type, choose the last one * (This is useful when PA-DATAs from KRB-ERROR and AS-REP are combined). - * @return salt and s2kparams. never null, its field might be null. + * @return salt and s2kparams. can be null if not found */ public static SaltAndParams getSaltAndParams(int eType, PAData[] pas) - throws Asn1Exception, KrbException { + throws Asn1Exception, IOException { - if (pas == null || pas.length == 0) { - return new SaltAndParams(null, null); - } + if (pas == null) return null; + DerValue d = null, d2 = null; String paPwSalt = null; - ETypeInfo2 info2 = null; - ETypeInfo info = null; for (PAData p: pas) { - if (p.getValue() != null) { - try { - switch (p.getType()) { - case Krb5.PA_PW_SALT: - paPwSalt = new String(p.getValue(), - KerberosString.MSNAME?"UTF8":"8859_1"); - break; - case Krb5.PA_ETYPE_INFO: - DerValue der = new DerValue(p.getValue()); - while (der.data.available() > 0) { - DerValue value = der.data.getDerValue(); - ETypeInfo tmp = new ETypeInfo(value); - if (tmp.getEType() == eType) info = tmp; - } - break; - case Krb5.PA_ETYPE_INFO2: - der = new DerValue(p.getValue()); - while (der.data.available() > 0) { - DerValue value = der.data.getDerValue(); - ETypeInfo2 tmp = new ETypeInfo2(value); - if (tmp.getEType() == eType) info2 = tmp; - } - break; - } - } catch (IOException ioe) { - // Ignored + if (p.getValue() == null) continue; + switch (p.getType()) { + case Krb5.PA_PW_SALT: + paPwSalt = new String(p.getValue(), + KerberosString.MSNAME?"UTF8":"8859_1"); + break; + case Krb5.PA_ETYPE_INFO: + d = new DerValue(p.getValue()); + break; + case Krb5.PA_ETYPE_INFO2: + d2 = new DerValue(p.getValue()); + break; + } + } + if (d2 != null) { + while (d2.data.available() > 0) { + DerValue value = d2.data.getDerValue(); + ETypeInfo2 tmp = new ETypeInfo2(value); + if (tmp.getParams() == null && tmp.getEType() == eType) { + // we don't support non-null s2kparams + return new SaltAndParams(tmp.getSalt(), tmp.getParams()); + } + } + } + if (d != null) { + while (d.data.available() > 0) { + DerValue value = d.data.getDerValue(); + ETypeInfo tmp = new ETypeInfo(value); + if (tmp.getEType() == eType) { + return new SaltAndParams(tmp.getSalt(), null); } } } - if (info2 != null) { - return new SaltAndParams(info2.getSalt(), info2.getParams()); - } else if (info != null) { - return new SaltAndParams(info.getSalt(), null); + if (paPwSalt != null) { + return new SaltAndParams(paPwSalt, null); } - return new SaltAndParams(paPwSalt, null); + return null; + } + + @Override + public String toString(){ + StringBuilder sb = new StringBuilder(); + sb.append(">>>Pre-Authentication Data:\n\t PA-DATA type = ") + .append(pADataType).append('\n'); + + switch(pADataType) { + case Krb5.PA_ENC_TIMESTAMP: + sb.append("\t PA-ENC-TIMESTAMP"); + break; + case Krb5.PA_ETYPE_INFO: + if (pADataValue != null) { + try { + DerValue der = new DerValue(pADataValue); + while (der.data.available() > 0) { + DerValue value = der.data.getDerValue(); + ETypeInfo info = new ETypeInfo(value); + sb.append("\t PA-ETYPE-INFO etype = ") + .append(info.getEType()) + .append(", salt = ") + .append(info.getSalt()) + .append('\n'); + } + } catch (IOException|Asn1Exception e) { + sb.append("\t \n"); + } + } + break; + case Krb5.PA_ETYPE_INFO2: + if (pADataValue != null) { + try { + DerValue der = new DerValue(pADataValue); + while (der.data.available() > 0) { + DerValue value = der.data.getDerValue(); + ETypeInfo2 info2 = new ETypeInfo2(value); + sb.append("\t PA-ETYPE-INFO2 etype = ") + .append(info2.getEType()) + .append(", salt = ") + .append(info2.getSalt()) + .append(", s2kparams = "); + byte[] s2kparams = info2.getParams(); + if (s2kparams == null) { + sb.append("null\n"); + } else if (s2kparams.length == 0) { + sb.append("empty\n"); + } else { + sb.append(new sun.misc.HexDumpEncoder() + .encodeBuffer(s2kparams)); + } + } + } catch (IOException|Asn1Exception e) { + sb.append("\t \n"); + } + } + break; + default: + // Unknown Pre-auth type + break; + } + return sb.toString(); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/provider/SecureRandom.java --- a/jdk/src/share/classes/sun/security/provider/SecureRandom.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/provider/SecureRandom.java Fri Sep 23 16:51:29 2011 -0700 @@ -249,7 +249,7 @@ try { digest = MessageDigest.getInstance ("SHA"); } catch (NoSuchAlgorithmException e) { - throw new InternalError("internal error: SHA-1 not available."); + throw new InternalError("internal error: SHA-1 not available.", e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/provider/SeedGenerator.java --- a/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/provider/SeedGenerator.java Fri Sep 23 16:51:29 2011 -0700 @@ -151,7 +151,8 @@ try { md = MessageDigest.getInstance("SHA"); } catch (NoSuchAlgorithmException nsae) { - throw new InternalError("internal error: SHA-1 not available."); + throw new InternalError("internal error: SHA-1 not available." + , nsae); } // The current time in millis @@ -258,7 +259,8 @@ try { digest = MessageDigest.getInstance("SHA"); } catch (NoSuchAlgorithmException e) { - throw new InternalError("internal error: SHA-1 not available."); + throw new InternalError("internal error: SHA-1 not available." + , e); } final ThreadGroup[] finalsg = new ThreadGroup[1]; @@ -311,7 +313,8 @@ t.start(); } catch (Exception e) { throw new InternalError("internal error: " + - "SeedGenerator thread creation error."); + "SeedGenerator thread creation error." + , e); } // We wait 250milli quanta, so the minimum wait time @@ -344,7 +347,8 @@ } } catch (Exception e) { throw new InternalError("internal error: " + - "SeedGenerator thread generated an exception."); + "SeedGenerator thread generated an exception." + , e); } } @@ -367,7 +371,8 @@ } catch (Exception e) { if (count <= 0) throw new InternalError("internal error: " + - "SeedGenerator thread generated an exception."); + "SeedGenerator thread generated an exception." + ,e); } synchronized(this) { @@ -533,7 +538,7 @@ } catch (IOException ioe) { throw new InternalError("URLSeedGenerator " + deviceName + " generated exception: " + - ioe.getMessage()); + ioe.getMessage(), ioe); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java Fri Sep 23 16:51:29 2011 -0700 @@ -262,7 +262,7 @@ = (HashSet)subjectNamesTraversed.clone(); return clonedState; } catch (CloneNotSupportedException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java --- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java Fri Sep 23 16:51:29 2011 -0700 @@ -394,7 +394,7 @@ return clonedState; } catch (CloneNotSupportedException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java Fri Sep 23 16:51:29 2011 -0700 @@ -494,7 +494,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { /* Cannot happen */ - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/tools/JarSigner.java --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java Fri Sep 23 16:51:29 2011 -0700 @@ -1506,6 +1506,9 @@ CertPath cp = certificateFactory.generateCertPath(certs); validator.validate(cp, pkixParameters); } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } chainNotValidated = true; s.append(tab + rb.getString(".CertPath.not.validated.") + e.getLocalizedMessage() + "]\n"); // TODO @@ -1562,6 +1565,27 @@ } try { + + certificateFactory = CertificateFactory.getInstance("X.509"); + validator = CertPathValidator.getInstance("PKIX"); + Set tas = new HashSet<>(); + try { + KeyStore caks = KeyTool.getCacertsKeyStore(); + if (caks != null) { + Enumeration aliases = caks.aliases(); + while (aliases.hasMoreElements()) { + String a = aliases.nextElement(); + try { + tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null)); + } catch (Exception e2) { + // ignore, when a SecretkeyEntry does not include a cert + } + } + } + } catch (Exception e) { + // Ignore, if cacerts cannot be loaded + } + if (providerName == null) { store = KeyStore.getInstance(storetype); } else { @@ -1580,45 +1604,28 @@ (rb.getString("Enter.Passphrase.for.keystore.")); } - if (nullStream) { - store.load(null, storepass); - } else { - keyStoreName = keyStoreName.replace(File.separatorChar, '/'); - URL url = null; - try { - url = new URL(keyStoreName); - } catch (java.net.MalformedURLException e) { - // try as file - url = new File(keyStoreName).toURI().toURL(); - } - InputStream is = null; - try { - is = url.openStream(); - store.load(is, storepass); - } finally { - if (is != null) { - is.close(); + try { + if (nullStream) { + store.load(null, storepass); + } else { + keyStoreName = keyStoreName.replace(File.separatorChar, '/'); + URL url = null; + try { + url = new URL(keyStoreName); + } catch (java.net.MalformedURLException e) { + // try as file + url = new File(keyStoreName).toURI().toURL(); } - } - } - Set tas = new HashSet<>(); - try { - KeyStore caks = KeyTool.getCacertsKeyStore(); - if (caks != null) { - Enumeration aliases = caks.aliases(); - while (aliases.hasMoreElements()) { - String a = aliases.nextElement(); - try { - tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null)); - } catch (Exception e2) { - // ignore, when a SecretkeyEntry does not include a cert + InputStream is = null; + try { + is = url.openStream(); + store.load(is, storepass); + } finally { + if (is != null) { + is.close(); } } } - } catch (Exception e) { - // Ignore, if cacerts cannot be loaded - } - if (store != null) { Enumeration aliases = store.aliases(); while (aliases.hasMoreElements()) { String a = aliases.nextElement(); @@ -1634,14 +1641,13 @@ // ignore, when a SecretkeyEntry does not include a cert } } - } - certificateFactory = CertificateFactory.getInstance("X.509"); - validator = CertPathValidator.getInstance("PKIX"); - try { - pkixParameters = new PKIXParameters(tas); - pkixParameters.setRevocationEnabled(false); - } catch (InvalidAlgorithmParameterException ex) { - // Only if tas is empty + } finally { + try { + pkixParameters = new PKIXParameters(tas); + pkixParameters.setRevocationEnabled(false); + } catch (InvalidAlgorithmParameterException ex) { + // Only if tas is empty + } } } catch (IOException ioe) { throw new RuntimeException(rb.getString("keystore.load.") + @@ -1805,6 +1811,9 @@ CertPath cp = certificateFactory.generateCertPath(Arrays.asList(certChain)); validator.validate(cp, pkixParameters); } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } chainNotValidated = true; } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/tools/KeyTool.java --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java Fri Sep 23 16:51:29 2011 -0700 @@ -1141,17 +1141,14 @@ if (token) { keyStore.store(null, null); } else { - FileOutputStream fout = null; - try { - fout = (nullStream ? - (FileOutputStream)null : - new FileOutputStream(ksfname)); - keyStore.store - (fout, - (storePassNew!=null) ? storePassNew : storePass); - } finally { - if (fout != null) { - fout.close(); + char[] pass = (storePassNew!=null) ? storePassNew : storePass; + if (nullStream) { + keyStore.store(null, pass); + } else { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + keyStore.store(bout, pass); + try (FileOutputStream fout = new FileOutputStream(ksfname)) { + fout.write(bout.toByteArray()); } } } @@ -1399,7 +1396,7 @@ private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{ if (P12KEYSTORE.equalsIgnoreCase(storetype)) { return origPass; - } else if (!token) { + } else if (!token && !protectedPath) { // Prompt for key password int count; for (count = 0; count < 3; count++) { @@ -1446,7 +1443,7 @@ } } } - return null; // PKCS11 + return null; // PKCS11, MSCAPI, or -protected } /** * Creates a new secret key. diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/security/util/SecurityConstants.java --- a/jdk/src/share/classes/sun/security/util/SecurityConstants.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/security/util/SecurityConstants.java Fri Sep 23 16:51:29 2011 -0700 @@ -127,10 +127,8 @@ // AWT present try { return (PermissionFactory)c.newInstance(); - } catch (InstantiationException x) { - throw new InternalError(x.getMessage()); - } catch (IllegalAccessException x) { - throw new InternalError(x.getMessage()); + } catch (ReflectiveOperationException x) { + throw new InternalError(x.getMessage(), x); } } else { // AWT not present diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/text/CompactByteArray.java --- a/jdk/src/share/classes/sun/text/CompactByteArray.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/text/CompactByteArray.java Fri Sep 23 16:51:29 2011 -0700 @@ -269,7 +269,7 @@ if (hashes != null) other.hashes = (int[])hashes.clone(); return other; } catch (CloneNotSupportedException e) { - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java --- a/jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/text/normalizer/NormalizerBase.java Fri Sep 23 16:51:29 2011 -0700 @@ -636,7 +636,7 @@ return copy; } catch (CloneNotSupportedException e) { - throw new InternalError(e.toString()); + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/tools/attach/HotSpotAttachProvider.java --- a/jdk/src/share/classes/sun/tools/attach/HotSpotAttachProvider.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/tools/attach/HotSpotAttachProvider.java Fri Sep 23 16:51:29 2011 -0700 @@ -89,7 +89,7 @@ if (t instanceof SecurityException) { return result; } - throw new InternalError(); // shouldn't happen + throw new InternalError(t); // shouldn't happen } for (Object vmid: vms) { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java --- a/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/tools/attach/HotSpotVirtualMachine.java Fri Sep 23 16:51:29 2011 -0700 @@ -102,7 +102,7 @@ try { loadAgentLibrary("instrument", args); } catch (AgentLoadException x) { - throw new InternalError("instrument library is missing in target VM"); + throw new InternalError("instrument library is missing in target VM", x); } catch (AgentInitializationException x) { /* * Translate interesting errors into the right exception and @@ -212,7 +212,7 @@ try { return execute(cmd, args); } catch (AgentLoadException x) { - throw new InternalError("Should not get here"); + throw new InternalError("Should not get here", x); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java --- a/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/tools/jconsole/LocalVirtualMachine.java Fri Sep 23 16:51:29 2011 -0700 @@ -135,10 +135,8 @@ try { host = MonitoredHost.getMonitoredHost(new HostIdentifier((String)null)); vms = host.activeVms(); - } catch (java.net.URISyntaxException sx) { - throw new InternalError(sx.getMessage()); - } catch (MonitorException mx) { - throw new InternalError(mx.getMessage()); + } catch (java.net.URISyntaxException | MonitorException x) { + throw new InternalError(x.getMessage(), x); } for (Object vmid: vms) { if (vmid instanceof Integer) { diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/tools/tree/Node.java --- a/jdk/src/share/classes/sun/tools/tree/Node.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/tools/tree/Node.java Fri Sep 23 16:51:29 2011 -0700 @@ -108,7 +108,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java --- a/jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/tracing/dtrace/DTraceProvider.java Fri Sep 23 16:51:29 2011 -0700 @@ -26,18 +26,15 @@ package sun.tracing.dtrace; import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.annotation.Annotation; -import java.util.HashMap; import sun.tracing.ProviderSkeleton; import sun.tracing.ProbeSkeleton; import com.sun.tracing.Provider; -import com.sun.tracing.ProviderName; import com.sun.tracing.ProbeName; import com.sun.tracing.dtrace.Attributes; import com.sun.tracing.dtrace.ModuleName; @@ -140,14 +137,8 @@ try { Constructor cons = proxyClass.getConstructor(constructorParams); return (T)cons.newInstance(new Object[] { this }); - } catch (NoSuchMethodException e) { - throw new InternalError(e.toString()); - } catch (IllegalAccessException e) { - throw new InternalError(e.toString()); - } catch (InstantiationException e) { - throw new InternalError(e.toString()); - } catch (InvocationTargetException e) { - throw new InternalError(e.toString()); + } catch (ReflectiveOperationException e) { + throw new InternalError(e.toString(), e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/share/classes/sun/util/calendar/CalendarDate.java --- a/jdk/src/share/classes/sun/util/calendar/CalendarDate.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/share/classes/sun/util/calendar/CalendarDate.java Fri Sep 23 16:51:29 2011 -0700 @@ -435,7 +435,7 @@ return super.clone(); } catch (CloneNotSupportedException e) { // this shouldn't happen - throw new InternalError(); + throw new InternalError(e); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/solaris/classes/sun/awt/X11/XBaseMenuWindow.java --- a/jdk/src/solaris/classes/sun/awt/X11/XBaseMenuWindow.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/solaris/classes/sun/awt/X11/XBaseMenuWindow.java Fri Sep 23 16:51:29 2011 -0700 @@ -157,7 +157,7 @@ try { return super.clone(); } catch (CloneNotSupportedException ex) { - throw new InternalError(); + throw new InternalError(ex); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java --- a/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/solaris/classes/sun/awt/X11/XMenuItemPeer.java Fri Sep 23 16:51:29 2011 -0700 @@ -131,7 +131,7 @@ try { return super.clone(); } catch (CloneNotSupportedException ex) { - throw new InternalError(); + throw new InternalError(ex); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java --- a/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/solaris/classes/sun/nio/ch/InheritedChannel.java Fri Sep 23 16:51:29 2011 -0700 @@ -64,7 +64,7 @@ dup2(devnull, 2); } catch (IOException ioe) { // this shouldn't happen - throw new InternalError(); + throw new InternalError(ioe); } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java --- a/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java Fri Sep 23 16:51:29 2011 -0700 @@ -304,7 +304,7 @@ try { b = s.getBytes("UTF-8"); } catch (java.io.UnsupportedEncodingException x) { - throw new InternalError(); + throw new InternalError(x); } LinuxVirtualMachine.write(fd, b, 0, b.length); } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/solaris/native/sun/awt/fontpath.c --- a/jdk/src/solaris/native/sun/awt/fontpath.c Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/solaris/native/sun/awt/fontpath.c Fri Sep 23 16:51:29 2011 -0700 @@ -1191,8 +1191,16 @@ fontformat = NULL; (*FcPatternGetString)(fontPattern, FC_FONTFORMAT, 0, &fontformat); - if (fontformat != NULL && strcmp((char*)fontformat, "TrueType") - != 0) { + /* We only want TrueType fonts but some Linuxes still depend + * on Type 1 fonts for some Locale support, so we'll allow + * them there. + */ + if (fontformat != NULL + && (strcmp((char*)fontformat, "TrueType") != 0) +#ifdef __linux__ + && (strcmp((char*)fontformat, "Type 1") != 0) +#endif + ) { continue; } result = (*FcPatternGetCharSet)(fontPattern, diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/windows/native/com/sun/security/auth/module/nt.c --- a/jdk/src/windows/native/com/sun/security/auth/module/nt.c Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/windows/native/com/sun/security/auth/module/nt.c Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,19 @@ BOOL getTextualSid(PSID pSid, LPTSTR TextualSid, LPDWORD lpdwBufferLen); void DisplayErrorText(DWORD dwLastError); +JNIEXPORT jlong JNICALL +Java_com_sun_security_auth_module_NTSystem_getImpersonationToken0 + (JNIEnv *env, jobject obj) { + HANDLE impersonationToken = 0; // impersonation token + if (debug) { + printf("getting impersonation token\n"); + } + if (getImpersonationToken(&impersonationToken) == FALSE) { + return 0; + } + return (jlong)impersonationToken; +} + JNIEXPORT void JNICALL Java_com_sun_security_auth_module_NTSystem_getCurrent (JNIEnv *env, jobject obj, jboolean debugNative) { @@ -59,7 +72,6 @@ DWORD numGroups = 0; // num groups LPTSTR *groups = NULL; // groups array long pIndex = -1; // index of primaryGroup in groups array - HANDLE impersonationToken = 0; // impersonation token jfieldID fid; jstring jstr; @@ -100,13 +112,6 @@ return; } - if (debug) { - printf("getting impersonation token\n"); - } - if (getImpersonationToken(&impersonationToken) == FALSE) { - return; - } - // then set values into NTSystem fid = (*env)->GetFieldID(env, cls, "userName", "Ljava/lang/String;"); @@ -233,18 +238,6 @@ (*env)->SetObjectField(env, obj, fid, jgroups); } - fid = (*env)->GetFieldID(env, cls, "impersonationToken", "J"); - if (fid == 0) { - jclass newExcCls = - (*env)->FindClass(env, "java/lang/IllegalArgumentException"); - if (newExcCls == 0) { - systemError = TRUE; - goto out; - } - (*env)->ThrowNew(env, newExcCls, "invalid field: impersonationToken"); - } - (*env)->SetLongField(env, obj, fid, (jlong)impersonationToken); - out: if (userName != NULL) { HeapFree(GetProcessHeap(), 0, userName); @@ -269,6 +262,7 @@ } HeapFree(GetProcessHeap(), 0, groups); } + CloseHandle(tokenHandle); if (systemError && debug) { printf(" [getCurrent] System Error: "); @@ -592,6 +586,7 @@ } return FALSE; } + CloseHandle(dupToken); if (debug) { printf(" [getImpersonationToken] token = %d\n", *impersonationToken); @@ -802,6 +797,8 @@ } HeapFree(GetProcessHeap(), 0, groups); } + CloseHandle(impersonationToken); + CloseHandle(tokenHandle); } */ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/windows/native/java/net/NetworkInterface.c --- a/jdk/src/windows/native/java/net/NetworkInterface.c Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/windows/native/java/net/NetworkInterface.c Fri Sep 23 16:51:29 2011 -0700 @@ -504,8 +504,7 @@ */ if (netaddrCount < 0) { netaddrCount = enumAddresses_win(env, ifs, &netaddrP); - if ((*env)->ExceptionOccurred(env)) { - free_netaddr(netaddrP); + if (netaddrCount == -1) { return NULL; } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/windows/native/java/net/NetworkInterface_winXP.c --- a/jdk/src/windows/native/java/net/NetworkInterface_winXP.c Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/windows/native/java/net/NetworkInterface_winXP.c Fri Sep 23 16:51:29 2011 -0700 @@ -194,8 +194,7 @@ while (curr != NULL) { netaddr *netaddrP; ret = enumAddresses_win(env, curr, &netaddrP); - if ((*env)->ExceptionOccurred(env)) { - free_netaddr(netaddrP); + if (ret == -1) { return -1; } curr->addrs = netaddrP; @@ -449,8 +448,7 @@ */ if (netaddrCount < 0) { netaddrCount = enumAddresses_win(env, ifs, &netaddrP); - if ((*env)->ExceptionOccurred(env)) { - free_netaddr(netaddrP); + if (netaddrCount == -1) { return NULL; } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c --- a/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/src/windows/native/java/net/TwoStacksPlainSocketImpl.c Fri Sep 23 16:51:29 2011 -0700 @@ -576,6 +576,7 @@ { /* fields on this */ jint port; + jint scope; jint timeout = (*env)->GetIntField(env, this, psi_timeoutID); jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID); jobject fd1Obj = (*env)->GetObjectField(env, this, psi_fd1ID); @@ -755,7 +756,11 @@ addr = (*env)->GetObjectField (env, socketAddressObj, ia6_ipaddressID); (*env)->SetByteArrayRegion (env, addr, 0, 16, (const char *)&him.him6.sin6_addr); (*env)->SetIntField(env, socketAddressObj, ia_familyID, IPv6); - (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, him.him6.sin6_scope_id); + scope = him.him6.sin6_scope_id; + (*env)->SetIntField(env, socketAddressObj, ia6_scopeidID, scope); + if(scope>0) { + (*env)->SetBooleanField(env, socketAddressObj, ia6_scopeidsetID, JNI_TRUE); + } } /* fields common to AF_INET and AF_INET6 */ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/Makefile --- a/jdk/test/Makefile Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/Makefile Fri Sep 23 16:51:29 2011 -0700 @@ -423,7 +423,8 @@ # Stable othervm testruns (minus items from PROBLEM_LIST) # Using samevm has problems, and doesn't help performance as much as others. JDK_ALL_TARGETS += jdk_awt -jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt) +jdk_awt: $(call TestDirs, com/sun/awt java/awt sun/awt \ + javax/imageio javax/print sun/pisces) $(call RunOthervmBatch) # Stable samevm testruns (minus items from PROBLEM_LIST) @@ -486,9 +487,8 @@ # Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_misc jdk_misc: $(call TestDirs, \ - demo javax/imageio javax/naming javax/print javax/script \ - javax/smartcardio javax/sound com/sun/java com/sun/jndi \ - com/sun/org com/sun/xml sun/misc sun/pisces) + demo/jvmti demo/zipfs javax/naming javax/script \ + javax/smartcardio com/sun/jndi com/sun/xml sun/misc) $(call RunSamevmBatch) # Stable samevm testruns (minus items from PROBLEM_LIST) @@ -532,17 +532,15 @@ jdk_security1: $(call TestDirs, java/security) $(call RunSamevmBatch) -# Stable othervm testruns (minus items from PROBLEM_LIST) -# Using samevm has serious problems with these tests +# Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_security2 -jdk_security2: $(call TestDirs, javax/crypto com/sun/crypto) +jdk_security2: $(call TestDirs, javax/crypto javax/xml/crypto com/sun/crypto) $(call RunSamevmBatch) -# Stable othervm testruns (minus items from PROBLEM_LIST) -# Using samevm has serious problems with these tests +# Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_security3 -jdk_security3: $(call TestDirs, com/sun/security lib/security \ - javax/security sun/security) +jdk_security3: $(call TestDirs, com/sun/security lib/security javax/security \ + sun/security com/sun/org/apache/xml/internal/security) $(call SharedLibraryPermissions,sun/security) $(call RunSamevmBatch) @@ -550,10 +548,16 @@ jdk_security: jdk_security1 jdk_security2 jdk_security3 @$(SummaryInfo) +# Stable samevm testruns (minus items from PROBLEM_LIST) +JDK_ALL_TARGETS += jdk_sound +jdk_sound: $(call TestDirs, javax/sound) + $(call RunSamevmBatch) + # Stable othervm testruns (minus items from PROBLEM_LIST) # Using samevm has problems, and doesn't help performance as much as others. JDK_ALL_TARGETS += jdk_swing -jdk_swing: $(call TestDirs, javax/swing sun/java2d) +jdk_swing: $(call TestDirs, javax/swing sun/java2d \ + demo/jfc com/sun/java/swing) $(call RunOthervmBatch) # Stable samevm testruns (minus items from PROBLEM_LIST) @@ -802,17 +806,17 @@ # The jtjck.jar utility to use to run the tests JTJCK_JAR = $(JCK_HOME)/lib/jtjck.jar JTJCK_JAVA_ARGS = -XX:MaxPermSize=256m -Xmx512m -JTJCK_OPTIONS = -headless -v +JTJCK_OPTIONS = -headless -v # Default tests to run ifndef JCK_COMPILER_TESTS - JCK_COMPILER_TESTS = + JCK_COMPILER_TESTS = endif ifndef JCK_RUNTIME_TESTS - JCK_RUNTIME_TESTS = + JCK_RUNTIME_TESTS = endif ifndef JCK_DEVTOOLS_TESTS - JCK_DEVTOOLS_TESTS = + JCK_DEVTOOLS_TESTS = endif # Generic rule used to run jck tests @@ -838,14 +842,14 @@ _generic_jck_tests # JCK7 runtime tests -jck7runtime: +jck7runtime: $(MAKE) UNIQUE_DIR=$@ \ JCK_HOME=$(JCK7RUNTIME_HOME) \ TESTDIRS="$(JCK_RUNTIME_TESTS)" \ _generic_jck_tests # JCK7 devtools tests -jck7devtools: +jck7devtools: $(MAKE) UNIQUE_DIR=$@ \ JCK_HOME=$(JCK7DEVTOOLS_HOME) \ TESTDIRS="$(JCK_DEVTOOLS_TESTS)" \ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/ProblemList.txt --- a/jdk/test/ProblemList.txt Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/ProblemList.txt Fri Sep 23 16:51:29 2011 -0700 @@ -526,6 +526,16 @@ # 7081817 sun/security/provider/certpath/X509CertPath/IllegalCertiticates.java generic-all +# 7041639, Solaris DSA keypair generation bug (Note: jdk_util also affected) +java/security/KeyPairGenerator/SolarisShortDSA.java solaris-all +sun/security/tools/jarsigner/onlymanifest.sh solaris-all +sun/security/tools/jarsigner/ts.sh solaris-all +sun/security/tools/keytool/emptysubject.sh solaris-all +sun/security/tools/keytool/importreadall.sh solaris-all +sun/security/tools/keytool/readjar.sh solaris-all +sun/security/tools/keytool/selfissued.sh solaris-all +sun/security/tools/keytool/standard.sh solaris-all + ############################################################################ # jdk_swing (not using samevm) @@ -586,5 +596,8 @@ # Filed 6772009 java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all +# 7041639, Solaris DSA keypair generation bug +java/util/TimeZone/TimeZoneDatePermissionCheck.sh solaris-all + ############################################################################ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/com/sun/servicetag/JavaServiceTagTest.java --- a/jdk/test/com/sun/servicetag/JavaServiceTagTest.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest.java Fri Sep 23 16:51:29 2011 -0700 @@ -25,7 +25,7 @@ /* * @test - * @bug 6622366 + * @bug 6622366 7078024 * @summary Basic Test for ServiceTag.getJavaServiceTag() * Disable creating the service tag in the system registry. * Verify the existence of registration.xml file and the @@ -86,23 +86,42 @@ } } + /** + * Tests if the running platform is a JDK. + */ + static boolean isJDK() { + // Determine the JRE path by checking the existence of + // /jre/lib and /lib. + String javaHome = System.getProperty("java.home"); + String jrepath = javaHome + File.separator + "jre"; + File f = new File(jrepath, "lib"); + if (!f.exists()) { + // java.home usually points to the JRE path + jrepath = javaHome; + } + + return jrepath.endsWith(File.separator + "jre"); + } + private static void checkServiceTag(ServiceTag st) throws IOException { - Properties props = loadSwordfishEntries(); - if (st.getProductURN(). - equals(props.getProperty("servicetag.jdk.urn"))) { - if (!st.getProductName(). - equals(props.getProperty("servicetag.jdk.name"))) { - throw new RuntimeException("Product URN and name don't match."); - } - } else if (st.getProductURN(). - equals(props.getProperty("servicetag.jre.urn"))) { - if (!st.getProductName(). - equals(props.getProperty("servicetag.jre.name"))) { + Properties props = loadServiceTagProps(); + // jdk 8 and later, JDK and JRE have the same product URN. + String jdkUrn = props.getProperty("servicetag.jdk.urn"); + String jreUrn = props.getProperty("servicetag.jre.urn"); + boolean isJdk = isJDK(); + + if (isJdk) { + if (!st.getProductURN().equals(jdkUrn) || + !st.getProductName().equals( + props.getProperty("servicetag.jdk.name"))) { throw new RuntimeException("Product URN and name don't match."); } } else { - throw new RuntimeException("Unexpected product_urn: " + - st.getProductURN()); + if (!st.getProductURN().equals(jreUrn) || + !st.getProductName().equals( + props.getProperty("servicetag.jre.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } } if (!st.getProductVersion(). equals(System.getProperty("java.version"))) { @@ -160,18 +179,13 @@ } } - private static Properties loadSwordfishEntries() + private static Properties loadServiceTagProps() throws IOException { - int version = sun.misc.Version.jdkMinorVersion(); - String filename = "/com/sun/servicetag/resources/javase_" + - version + "_swordfish.properties"; - InputStream in = Installer.class.getClass().getResourceAsStream(filename); - Properties props = new Properties(); - try { + String filename = "/com/sun/servicetag/resources/javase_servicetag.properties"; + try (InputStream in = Installer.class.getClass().getResourceAsStream(filename)) { + Properties props = new Properties(); props.load(in); - } finally { - in.close(); + return props; } - return props; } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/com/sun/servicetag/JavaServiceTagTest1.java --- a/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/com/sun/servicetag/JavaServiceTagTest1.java Fri Sep 23 16:51:29 2011 -0700 @@ -25,7 +25,7 @@ /* * @test - * @bug 6622366 + * @bug 6622366 7078024 * @summary Basic Test for ServiceTag.getJavaServiceTag(String) * to verify that the registration.xml and servicetag files * are both created correctly. @@ -157,25 +157,45 @@ return svctag; } + /** + * Tests if the running platform is a JDK. + */ + static boolean isJDK() { + // Determine the JRE path by checking the existence of + // /jre/lib and /lib. + String javaHome = System.getProperty("java.home"); + String jrepath = javaHome + File.separator + "jre"; + File f = new File(jrepath, "lib"); + if (!f.exists()) { + // java.home usually points to the JRE path + jrepath = javaHome; + } + + return jrepath.endsWith(File.separator + "jre"); + } + private static void checkServiceTag(ServiceTag st, String source) throws IOException { - Properties props = loadSwordfishEntries(); - if (st.getProductURN(). - equals(props.getProperty("servicetag.jdk.urn"))) { - if (!st.getProductName(). - equals(props.getProperty("servicetag.jdk.name"))) { - throw new RuntimeException("Product URN and name don't match."); - } - } else if (st.getProductURN(). - equals(props.getProperty("servicetag.jre.urn"))) { - if (!st.getProductName(). - equals(props.getProperty("servicetag.jre.name"))) { + Properties props = loadServiceTagProps(); + // jdk 8 and later, JDK and JRE have the same product URN. + String jdkUrn = props.getProperty("servicetag.jdk.urn"); + String jreUrn = props.getProperty("servicetag.jre.urn"); + boolean isJdk = isJDK(); + + if (isJdk) { + if (!st.getProductURN().equals(jdkUrn) || + !st.getProductName().equals( + props.getProperty("servicetag.jdk.name"))) { throw new RuntimeException("Product URN and name don't match."); } } else { - throw new RuntimeException("Unexpected product_urn: " + - st.getProductURN()); + if (!st.getProductURN().equals(jreUrn) || + !st.getProductName().equals( + props.getProperty("servicetag.jre.name"))) { + throw new RuntimeException("Product URN and name don't match."); + } } + if (!st.getProductVersion(). equals(System.getProperty("java.version"))) { throw new RuntimeException("Unexpected product_version: " + @@ -233,18 +253,13 @@ } } - private static Properties loadSwordfishEntries() + private static Properties loadServiceTagProps() throws IOException { - int version = sun.misc.Version.jdkMinorVersion(); - String filename = "/com/sun/servicetag/resources/javase_" + - version + "_swordfish.properties"; - InputStream in = Installer.class.getClass().getResourceAsStream(filename); - Properties props = new Properties(); - try { + String filename = "/com/sun/servicetag/resources/javase_servicetag.properties"; + try (InputStream in = Installer.class.getClass().getResourceAsStream(filename)) { + Properties props = new Properties(); props.load(in); - } finally { - in.close(); + return props; } - return props; } } diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/lang/invoke/InvokeGenericTest.java --- a/jdk/test/java/lang/invoke/InvokeGenericTest.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/lang/invoke/InvokeGenericTest.java Fri Sep 23 16:51:29 2011 -0700 @@ -25,7 +25,7 @@ /* @test * @summary unit tests for java.lang.invoke.MethodHandle.invoke - * @compile -target 7 InvokeGenericTest.java + * @compile InvokeGenericTest.java * @run junit/othervm test.java.lang.invoke.InvokeGenericTest */ diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/lang/reflect/TypeVariable/TestAnnotatedElement.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/lang/reflect/TypeVariable/TestAnnotatedElement.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7086192 + * @summary Verify functionality of AnnotatedElement methods on type variables + * @author Joseph D. Darcy + */ + +import java.lang.reflect.*; +import java.lang.annotation.*; + +public class TestAnnotatedElement { + // Type variable on a method + private static B m(B b) {return null;} + + // Type variable on a construtor + private TestAnnotatedElement(){super();} + + public static void main(String... argv) throws ReflectiveOperationException { + int errors = 0; + + Class clazz = TestAnnotatedElement.class; + errors += testTypeVariable(clazz.getTypeParameters()); + errors += testTypeVariable(clazz.getDeclaredConstructor().getTypeParameters()); + errors += testTypeVariable(clazz.getDeclaredMethod("m", Object.class).getTypeParameters()); + + if (errors > 0) + throw new RuntimeException(errors + " failures"); + } + + + private static int testTypeVariable(TypeVariable[] typeVars) { + int errors = 0; + if (typeVars.length == 0) + return ++errors; + + for(TypeVariable typeVar : typeVars) { + try { + typeVar.getAnnotation(null); + errors++; + } catch(NullPointerException npe) { + ; // Expected + } + + if (typeVar.getAnnotation(SuppressWarnings.class) != null) + errors++; + + try { + typeVar.isAnnotationPresent(null); + errors++; + } catch(NullPointerException npe) { + ; // Expected + } + + if (typeVar.isAnnotationPresent(SuppressWarnings.class)) + errors++; + + if(typeVar.getAnnotations().length != 0) + errors++; + + if(typeVar.getDeclaredAnnotations().length != 0) + errors++; + } + return errors; + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/math/BigDecimal/DivideMcTests.java --- a/jdk/test/java/math/BigDecimal/DivideMcTests.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/math/BigDecimal/DivideMcTests.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java --- a/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/math/BigDecimal/FloatDoubleValueTests.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6274390 + * @bug 6274390 7082971 * @summary Verify {float, double}Value methods work with condensed representation * @run main FloatDoubleValueTests * @run main/othervm -XX:+AggressiveOpts FloatDoubleValueTests @@ -79,6 +79,7 @@ // and double. static void testFloatDoubleValue() { long longValues[] = { + Long.MIN_VALUE, // -2^63 0, 1, 2, diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/math/BigDecimal/RangeTests.java --- a/jdk/test/java/math/BigDecimal/RangeTests.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/math/BigDecimal/RangeTests.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/math/BigDecimal/StrippingZerosTest.java --- a/jdk/test/java/math/BigDecimal/StrippingZerosTest.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/math/BigDecimal/StrippingZerosTest.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2011 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/math/BigDecimal/ToPlainStringTests.java --- a/jdk/test/java/math/BigDecimal/ToPlainStringTests.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/math/BigDecimal/ToPlainStringTests.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/net/Socket/ShutdownInput.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/Socket/ShutdownInput.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7014860 + * @summary Socket.getInputStream().available() not clear for + * case that connection is shutdown for reading + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.nio.channels.ServerSocketChannel; +import java.nio.channels.SocketChannel; + +public class ShutdownInput { + static boolean failed = false; + + public static void main(String args[]) throws Exception { + InetAddress iaddr = InetAddress.getLocalHost(); + + try ( ServerSocket ss = new ServerSocket(0); + Socket s1 = new Socket(iaddr, ss.getLocalPort()); + Socket s2 = ss.accept() ) { + + test(s1, s2, "Testing NET"); + } + + // check the NIO socket adapter + try (ServerSocketChannel sc = ServerSocketChannel.open().bind(null); + SocketChannel s1 = SocketChannel.open( + new InetSocketAddress(iaddr, sc.socket().getLocalPort())); + SocketChannel s2 = sc.accept() ) { + + test(s1.socket(), s2.socket(), "Testing NIO"); + } + + if (failed) { + throw new RuntimeException("Failed: check output"); + } + } + + public static void test(Socket s1, Socket s2, String mesg) throws Exception { + OutputStream os = s1.getOutputStream(); + os.write("This is a message".getBytes("US-ASCII")); + + InputStream in = s2.getInputStream(); + s2.shutdownInput(); + + if (in.available() != 0) { + failed = true; + System.out.println(mesg + ":" + s2 + " in.available() should be 0, " + + "but returns "+ in.available()); + } + + byte[] ba = new byte[2]; + if (in.read() != -1 || + in.read(ba) != -1 || + in.read(ba, 0, ba.length) != -1) { + + failed = true; + System.out.append(mesg + ":" + s2 + " in.read() should be -1"); + } + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/net/URI/Test.java --- a/jdk/test/java/net/URI/Test.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/java/net/URI/Test.java Fri Sep 23 16:51:29 2011 -0700 @@ -23,7 +23,7 @@ /* @test * @summary Unit test for java.net.URI - * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 + * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 * @author Mark Reinhold */ @@ -1428,6 +1428,8 @@ gt(s, new URI("http://jag:CafeBabe@java.sun.com:94/b/c/d?q#f")); lt(s, new URI("http://jag:cafebabe@java.sun.com:94/b/c/d?r#f")); lt(s, new URI("http://jag:cafebabe@java.sun.com:94/b/c/d?q#g")); + eq(new URI("http://host/a%00bcd"), new URI("http://host/a%00bcd")); + ne(new URI("http://host/a%00bcd"), new URI("http://host/aZ00bcd")); lt("p", "s:p"); lt("s:p", "T:p"); diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/java/security/KeyPairGenerator/SolarisShortDSA.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/KeyPairGenerator/SolarisShortDSA.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7081411 + * @summary DSA keypair generation affected by Solaris bug + */ + +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.Signature; +import sun.security.provider.DSAPrivateKey; + +public class SolarisShortDSA { + static byte[] data = new byte[0]; + public static void main(String args[]) throws Exception { + for (int i=0; i<10000; i++) { + KeyPairGenerator kpg = KeyPairGenerator.getInstance("DSA"); + KeyPair kp = kpg.generateKeyPair(); + DSAPrivateKey dpk = (DSAPrivateKey)kp.getPrivate(); + int len = dpk.getX().bitLength(); + if (len <= 152) { + if (!use(kp)) { + String os = System.getProperty("os.name"); + // Solaris bug, update the following line once it's fixed + if (os.equals("SunOS")) { + throw new IllegalStateException( + "Don't panic. This is a Solaris bug"); + } else { + throw new RuntimeException("Real test failure"); + } + } + break; + } + } + } + + static boolean use(KeyPair kp) throws Exception { + Signature sig = Signature.getInstance("SHA1withDSA"); + sig.initSign(kp.getPrivate()); + sig.update(data); + byte[] signed = sig.sign(); + Signature sig2 = Signature.getInstance("SHA1withDSA"); + sig2.initVerify(kp.getPublic()); + sig2.update(data); + return sig2.verify(signed); + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java --- a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Fri Sep 23 16:51:29 2011 -0700 @@ -26,6 +26,7 @@ * @bug 6436919 6460930 * @summary check that XML Signatures can be generated and validated with * SecurityManager enabled and default policy + * @run main/othervm XMLDSigWithSecMgr * @author Sean Mullan */ import java.io.*; diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/lib/security/java.policy/Ext_AllPolicy.sh --- a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh Fri Sep 23 16:51:29 2011 -0700 @@ -54,19 +54,16 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; CYGWIN* ) NULL=/dev/null PS=";" FS="/" - TMP=/tmp ;; Windows_95 | Windows_98 | Windows_NT ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/krb5/auto/DupEtypes.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/krb5/auto/DupEtypes.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7067974 + * @summary multiple ETYPE-INFO-ENTRY with same etype and different salt + * @compile -XDignore.symbol.file DupEtypes.java + * @run main/othervm DupEtypes 1 + * @run main/othervm DupEtypes 2 + * @run main/othervm/fail DupEtypes 3 + * @run main/othervm DupEtypes 4 + * @run main/othervm DupEtypes 5 + */ + +import sun.security.jgss.GSSUtil; + +public class DupEtypes { + + public static void main(String[] args) throws Exception { + + OneKDC kdc = new OneKDC(null); + kdc.writeJAASConf(); + + // Different test cases, read KDC.processAsReq for details + kdc.setOption(KDC.Option.DUP_ETYPE, Integer.parseInt(args[0])); + + Context c, s; + c = Context.fromJAAS("client"); + s = Context.fromJAAS("server"); + + c.startAsClient(OneKDC.SERVER, GSSUtil.GSS_KRB5_MECH_OID); + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID); + + Context.handshake(c, s); + + Context.transmit("i say high --", c, s); + Context.transmit(" you say low", s, c); + + s.dispose(); + c.dispose(); + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/krb5/auto/KDC.java --- a/jdk/test/sun/security/krb5/auto/KDC.java Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/krb5/auto/KDC.java Fri Sep 23 16:51:29 2011 -0700 @@ -174,6 +174,10 @@ * Set all name-type to a value in response */ RESP_NT, + /** + * Multiple ETYPE-INFO-ENTRY with same etype but different salt + */ + DUP_ETYPE, }; static { @@ -881,48 +885,104 @@ bFlags[Krb5.TKT_OPTS_INITIAL] = true; // Creating PA-DATA - int[] epas = eTypes; - if (options.containsKey(KDC.Option.RC4_FIRST_PREAUTH)) { - for (int i=1; i ${TMP}${FS}temp_file_40875602475 2> ${NULL} -grep MissingResourceException ${TMP}${FS}temp_file_40875602475 +${TESTJAVA}${FS}bin${FS}keytool > temp_file_40875602475 2> ${NULL} +grep MissingResourceException temp_file_40875602475 if [ $? -eq 0 ]; then - rm ${TMP}${FS}temp_file_40875602475 exit 1 fi -rm ${TMP}${FS}temp_file_40875602475 exit 0 diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/keytool/trystore.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/security/tools/keytool/trystore.sh Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,65 @@ +# +# Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 7047200 +# @summary keytool can try save to a byte array before overwrite the file + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* ) + FS="\\" + ;; + * ) + FS="/" + ;; +esac + +rm trystore.jks 2> /dev/null + +KEYTOOL="${TESTJAVA}${FS}bin${FS}keytool -storetype jks -keystore trystore.jks" +$KEYTOOL -genkeypair -alias a -dname CN=A -storepass changeit -keypass changeit +$KEYTOOL -genkeypair -alias b -dname CN=B -storepass changeit -keypass changeit + +# We use -protected for JKS keystore. This is illegal so the command should +# fail. Then we can check if the keystore is damaged. + +$KEYTOOL -genkeypair -protected -alias b -delete -debug + +if [ $? = 0 ]; then + echo "What? -protected works for JKS?" + exit 1 +fi + +$KEYTOOL -list -storepass changeit + +if [ $? != 0 ]; then + echo "Keystore file damaged" + exit 2 +fi diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/Alias.sh --- a/jdk/test/sun/security/tools/policytool/Alias.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/Alias.sh Fri Sep 23 16:51:29 2011 -0700 @@ -51,13 +51,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/ChangeUI.sh --- a/jdk/test/sun/security/tools/policytool/ChangeUI.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/ChangeUI.sh Fri Sep 23 16:51:29 2011 -0700 @@ -50,13 +50,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/OpenPolicy.sh --- a/jdk/test/sun/security/tools/policytool/OpenPolicy.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/OpenPolicy.sh Fri Sep 23 16:51:29 2011 -0700 @@ -50,13 +50,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/SaveAs.sh --- a/jdk/test/sun/security/tools/policytool/SaveAs.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/SaveAs.sh Fri Sep 23 16:51:29 2011 -0700 @@ -51,13 +51,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/UpdatePermissions.sh --- a/jdk/test/sun/security/tools/policytool/UpdatePermissions.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/UpdatePermissions.sh Fri Sep 23 16:51:29 2011 -0700 @@ -50,13 +50,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/UsePolicy.sh --- a/jdk/test/sun/security/tools/policytool/UsePolicy.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/UsePolicy.sh Fri Sep 23 16:51:29 2011 -0700 @@ -50,13 +50,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 jdk/test/sun/security/tools/policytool/i18n.sh --- a/jdk/test/sun/security/tools/policytool/i18n.sh Wed Sep 21 17:08:02 2011 +0400 +++ b/jdk/test/sun/security/tools/policytool/i18n.sh Fri Sep 23 16:51:29 2011 -0700 @@ -50,13 +50,11 @@ NULL=/dev/null PS=":" FS="/" - TMP=/tmp ;; Windows* ) NULL=NUL PS=";" FS="\\" - TMP="c:/temp" ;; * ) echo "Unrecognized system!" diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/.hgtags --- a/langtools/.hgtags Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/.hgtags Fri Sep 23 16:51:29 2011 -0700 @@ -125,3 +125,5 @@ e9f118c2bd3c4690d8d2e6b108b5bad7e226634c jdk8-b01 b3c059de2a61fc122c99d555cdd8b85f112393c1 jdk8-b02 f497fac86cf9ada4801ecaf49eb0d2307a2b61c8 jdk8-b03 +5df63fd8fa64741e829281ee6febe9954932841b jdk8-b04 +5304c2a17d4b001e365a8f0163082dc375f1abab jdk8-b05 diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java --- a/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Fri Sep 23 16:51:29 2011 -0700 @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -51,6 +52,7 @@ import com.sun.source.util.TaskListener; import com.sun.tools.javac.util.ClientCodeException; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -146,7 +148,7 @@ return fo; } - DiagnosticListener wrap(DiagnosticListener dl) { + DiagnosticListener wrap(DiagnosticListener dl) { if (isTrusted(dl)) return dl; return new WrappedDiagnosticListener(dl); @@ -158,6 +160,16 @@ return new WrappedTaskListener(tl); } + @SuppressWarnings("unchecked") + private Diagnostic unwrap(final Diagnostic diagnostic) { + if (diagnostic instanceof JCDiagnostic) { + JCDiagnostic d = (JCDiagnostic) diagnostic; + return (Diagnostic) new DiagnosticSourceUnwrapper(d); + } else { + return diagnostic; + } + } + protected boolean isTrusted(Object o) { Class c = o.getClass(); Boolean trusted = trustedClasses.get(c); @@ -534,7 +546,7 @@ } } - protected class WrappedDiagnosticListener implements DiagnosticListener { + protected class WrappedDiagnosticListener implements DiagnosticListener { protected DiagnosticListener clientDiagnosticListener; WrappedDiagnosticListener(DiagnosticListener clientDiagnosticListener) { clientDiagnosticListener.getClass(); // null check @@ -544,7 +556,7 @@ @Override public void report(Diagnostic diagnostic) { try { - clientDiagnosticListener.report(diagnostic); + clientDiagnosticListener.report(unwrap(diagnostic)); } catch (ClientCodeException e) { throw e; } catch (RuntimeException e) { @@ -555,6 +567,54 @@ } } + public class DiagnosticSourceUnwrapper implements Diagnostic { + public final JCDiagnostic d; + + DiagnosticSourceUnwrapper(JCDiagnostic d) { + this.d = d; + } + + public Diagnostic.Kind getKind() { + return d.getKind(); + } + + public JavaFileObject getSource() { + return unwrap(d.getSource()); + } + + public long getPosition() { + return d.getPosition(); + } + + public long getStartPosition() { + return d.getStartPosition(); + } + + public long getEndPosition() { + return d.getEndPosition(); + } + + public long getLineNumber() { + return d.getLineNumber(); + } + + public long getColumnNumber() { + return d.getColumnNumber(); + } + + public String getCode() { + return d.getCode(); + } + + public String getMessage(Locale locale) { + return d.getMessage(locale); + } + + public String toString() { + return d.toString(); + } + } + protected class WrappedTaskListener implements TaskListener { protected TaskListener clientTaskListener; WrappedTaskListener(TaskListener clientTaskListener) { diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/code/Types.java --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Sep 23 16:51:29 2011 -0700 @@ -269,10 +269,12 @@ // /** - * Is t a subtype of or convertiable via boxing/unboxing - * convertions to s? + * Is t a subtype of or convertible via boxing/unboxing + * conversion to s? */ public boolean isConvertible(Type t, Type s, Warner warn) { + if (t.tag == ERROR) + return true; boolean tPrimitive = t.isPrimitive(); boolean sPrimitive = s.isPrimitive(); if (tPrimitive == sPrimitive) { @@ -2117,6 +2119,8 @@ } } + List seenTypes = List.nil(); + /** members closure visitor methods **/ public CompoundScope visitType(Type t, Boolean skipInterface) { @@ -2125,21 +2129,33 @@ @Override public CompoundScope visitClassType(ClassType t, Boolean skipInterface) { - ClassSymbol csym = (ClassSymbol)t.tsym; - Entry e = _map.get(csym); - if (e == null || !e.matches(skipInterface)) { - CompoundScope membersClosure = new CompoundScope(csym); - if (!skipInterface) { - for (Type i : interfaces(t)) { - membersClosure.addSubScope(visit(i, skipInterface)); + if (seenTypes.contains(t.tsym)) { + //this is possible when an interface is implemented in multiple + //superclasses, or when a classs hierarchy is circular - in such + //cases we don't need to recurse (empty scope is returned) + return new CompoundScope(t.tsym); + } + try { + seenTypes = seenTypes.prepend(t.tsym); + ClassSymbol csym = (ClassSymbol)t.tsym; + Entry e = _map.get(csym); + if (e == null || !e.matches(skipInterface)) { + CompoundScope membersClosure = new CompoundScope(csym); + if (!skipInterface) { + for (Type i : interfaces(t)) { + membersClosure.addSubScope(visit(i, skipInterface)); + } } + membersClosure.addSubScope(visit(supertype(t), skipInterface)); + membersClosure.addSubScope(csym.members()); + e = new Entry(skipInterface, membersClosure); + _map.put(csym, e); } - membersClosure.addSubScope(visit(supertype(t), skipInterface)); - membersClosure.addSubScope(csym.members()); - e = new Entry(skipInterface, membersClosure); - _map.put(csym, e); + return e.compoundScope; } - return e.compoundScope; + finally { + seenTypes = seenTypes.tail; + } } @Override diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Sep 23 16:51:29 2011 -0700 @@ -594,7 +594,15 @@ lintEnv = lintEnv.next; // Having found the enclosing lint value, we can initialize the lint value for this class - env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.attributes_field, env.info.enclVar.flags()); + // ... but ... + // There's a problem with evaluating annotations in the right order, such that + // env.info.enclVar.attributes_field might not yet have been evaluated, and so might be + // null. In that case, calling augment will throw an NPE. To avoid this, for now we + // revert to the jdk 6 behavior and ignore the (unevaluated) attributes. + if (env.info.enclVar.attributes_field == null) + env.info.lint = lintEnv.info.lint; + else + env.info.lint = lintEnv.info.lint.augment(env.info.enclVar.attributes_field, env.info.enclVar.flags()); Lint prevLint = chk.setLint(env.info.lint); JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java --- a/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,6 +98,7 @@ @Override public OutputStream openOutputStream() throws IOException { + fileManager.flushCache(this); ensureParentDirectoriesExist(); return new FileOutputStream(file); } @@ -128,6 +129,7 @@ @Override public Writer openWriter() throws IOException { + fileManager.flushCache(this); ensureParentDirectoriesExist(); return new OutputStreamWriter(new FileOutputStream(file), fileManager.getEncodingName()); } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Sep 23 16:51:29 2011 -0700 @@ -1689,6 +1689,8 @@ // outer instance of a super(...) call appears as first parameter). genArgs(tree.args, TreeInfo.symbol(tree.meth).externalType(types).getParameterTypes()); + code.statBegin(tree.pos); + code.markStatBegin(); result = m.invoke(); } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java --- a/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/nio/PathFileObject.java Fri Sep 23 16:51:29 2011 -0700 @@ -205,6 +205,7 @@ @Override public OutputStream openOutputStream() throws IOException { + fileManager.flushCache(this); ensureParentDirectoriesExist(); return Files.newOutputStream(path); } @@ -241,6 +242,7 @@ @Override public Writer openWriter() throws IOException { + fileManager.flushCache(this); ensureParentDirectoriesExist(); return new OutputStreamWriter(Files.newOutputStream(path), fileManager.getEncodingName()); } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Sep 23 16:51:29 2011 -0700 @@ -27,15 +27,15 @@ import java.util.*; +import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; -import com.sun.tools.javac.code.*; +import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; -import static com.sun.tools.javac.util.ListBuffer.lb; -import com.sun.tools.javac.tree.JCTree.*; - +import static com.sun.tools.javac.util.ListBuffer.lb; import static com.sun.tools.javac.parser.Token.*; /** The parser maps a token sequence into an abstract syntax @@ -254,26 +254,44 @@ } private JCErroneous syntaxError(int pos, String key, Token... args) { - return syntaxError(pos, null, key, args); + return syntaxError(pos, List.nil(), key, args); } private JCErroneous syntaxError(int pos, List errs, String key, Token... args) { setErrorEndPos(pos); - reportSyntaxError(pos, key, (Object[])args); - return toP(F.at(pos).Erroneous(errs)); + JCErroneous err = F.at(pos).Erroneous(errs); + reportSyntaxError(err, key, (Object[])args); + if (errs != null) { + JCTree last = errs.last(); + if (last != null) + storeEnd(last, pos); + } + return toP(err); } private int errorPos = Position.NOPOS; + /** - * Report a syntax error at given position using the given - * argument unless one was already reported at the same position. + * Report a syntax using the given the position parameter and arguments, + * unless one was already reported at the same position. */ private void reportSyntaxError(int pos, String key, Object... args) { + JCDiagnostic.DiagnosticPosition diag = new JCDiagnostic.SimpleDiagnosticPosition(pos); + reportSyntaxError(diag, key, args); + } + + /** + * Report a syntax error using the given DiagnosticPosition object and + * arguments, unless one was already reported at the same position. + */ + private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) { + int pos = diagPos.getPreferredPosition(); if (pos > S.errPos() || pos == Position.NOPOS) { - if (S.token() == EOF) - error(pos, "premature.eof"); - else - error(pos, key, args); + if (S.token() == EOF) { + error(diagPos, "premature.eof"); + } else { + error(diagPos, key, args); + } } S.errPos(pos); if (S.pos() == errorPos) @@ -311,7 +329,7 @@ /** Report an illegal start of expression/type error at given position. */ JCExpression illegal(int pos) { - setErrorEndPos(S.pos()); + setErrorEndPos(pos); if ((mode & EXPR) != 0) return syntaxError(pos, "illegal.start.of.expr"); else @@ -340,7 +358,7 @@ * indexed by the tree nodes they refer to. * defined only if option flag keepDocComment is set. */ - Map docComments; + private final Map docComments; /** Make an entry into docComments hashtable, * provided flag keepDocComments is set and given doc comment is non-null. @@ -462,6 +480,10 @@ return t; } + JCExpression literal(Name prefix) { + return literal(prefix, S.pos()); + } + /** * Literal = * INTLITERAL @@ -474,8 +496,7 @@ * | FALSE * | NULL */ - JCExpression literal(Name prefix) { - int pos = S.pos(); + JCExpression literal(Name prefix, int pos) { JCExpression t = errorTree; switch (S.token()) { case INTLITERAL: @@ -869,7 +890,7 @@ (S.token() == INTLITERAL || S.token() == LONGLITERAL) && S.radix() == 10) { mode = EXPR; - t = literal(names.hyphen); + t = literal(names.hyphen, pos); } else { t = term3(); return F.at(pos).Unary(unoptag(token), t); @@ -1267,15 +1288,17 @@ case GTGT: S.token(GT); break; + case GT: + S.nextToken(); + break; default: - accept(GT); + args.append(syntaxError(S.pos(), "expected", GT)); break; } return args.toList(); } } else { - syntaxError(S.pos(), "expected", LT); - return List.nil(); + return List.of(syntaxError(S.pos(), "expected", LT)); } } @@ -1300,12 +1323,12 @@ return F.at(pos).Wildcard(t, bound); } else if (S.token() == IDENTIFIER) { //error recovery - reportSyntaxError(S.prevEndPos(), "expected3", - GT, EXTENDS, SUPER); TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); JCExpression wc = toP(F.at(pos).Wildcard(t, null)); JCIdent id = toP(F.at(S.pos()).Ident(ident())); - return F.at(pos).Erroneous(List.of(wc, id)); + JCErroneous err = F.at(pos).Erroneous(List.of(wc, id)); + reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); + return err; } else { TypeBoundKind t = toP(F.at(pos).TypeBoundKind(BoundKind.UNBOUND)); return toP(F.at(pos).Wildcard(t, null)); @@ -1391,7 +1414,7 @@ while (S.token() == DOT) { if (diamondFound) { //cannot select after a diamond - illegal(S.pos()); + illegal(); } int pos = S.pos(); S.nextToken(); @@ -1419,15 +1442,16 @@ pos = typeArgs.head.pos; } setErrorEndPos(S.prevEndPos()); - reportSyntaxError(pos, "cannot.create.array.with.type.arguments"); - return toP(F.at(newpos).Erroneous(typeArgs.prepend(e))); + JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e)); + reportSyntaxError(err, "cannot.create.array.with.type.arguments"); + return toP(err); } return e; } else if (S.token() == LPAREN) { return classCreatorRest(newpos, null, typeArgs, t); } else { - reportSyntaxError(S.pos(), "expected2", - LPAREN, LBRACKET); + setErrorEndPos(S.pos()); + reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET); t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.nil(), null)); return toP(F.at(newpos).Erroneous(List.of(t))); } @@ -1457,7 +1481,8 @@ if (S.token() == LBRACE) { return arrayInitializer(newpos, elemtype); } else { - return syntaxError(S.pos(), "array.dimension.missing"); + JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null)); + return syntaxError(S.pos(), List.of(t), "array.dimension.missing"); } } else { ListBuffer dims = new ListBuffer(); @@ -1843,7 +1868,7 @@ /** CatchClause = CATCH "(" FormalParameter ")" Block */ - JCCatch catchClause() { + protected JCCatch catchClause() { int pos = S.pos(); accept(CATCH); accept(LPAREN); @@ -1973,7 +1998,7 @@ JCModifiers modifiersOpt() { return modifiersOpt(null); } - JCModifiers modifiersOpt(JCModifiers partial) { + protected JCModifiers modifiersOpt(JCModifiers partial) { long flags; ListBuffer annotations = new ListBuffer(); int pos; @@ -2006,6 +2031,7 @@ case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; case STRICTFP : flag = Flags.STRICTFP; break; case MONKEYS_AT : flag = Flags.ANNOTATION; break; + case ERROR : flag = 0; S.nextToken(); break; default: break loop; } if ((flags & flag) != 0) error(S.pos(), "repeated.modifier"); @@ -2219,9 +2245,12 @@ /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression */ - JCTree resource() { - return variableDeclaratorRest(S.pos(), optFinal(Flags.FINAL), - parseType(), ident(), true, null); + protected JCTree resource() { + JCModifiers optFinal = optFinal(Flags.FINAL); + JCExpression type = parseType(); + int pos = S.pos(); + Name ident = ident(); + return variableDeclaratorRest(pos, optFinal, type, ident, true, null); } /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} @@ -2568,7 +2597,7 @@ * | ModifiersOpt Type Ident * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) */ - List classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { + protected List classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { if (S.token() == SEMI) { S.nextToken(); return List.nil(); @@ -2770,7 +2799,7 @@ /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter */ - JCVariableDecl formalParameter() { + protected JCVariableDecl formalParameter() { JCModifiers mods = optFinal(Flags.PARAMETER); JCExpression type = parseType(); if (S.token() == ELLIPSIS) { @@ -2788,6 +2817,10 @@ log.error(DiagnosticFlag.SYNTAX, pos, key, args); } + void error(DiagnosticPosition pos, String key, Object ... args) { + log.error(DiagnosticFlag.SYNTAX, pos, key, args); + } + void warning(int pos, String key, Object ... args) { log.warning(pos, key, args); } @@ -2807,8 +2840,9 @@ case JCTree.ERRONEOUS: return t; default: - error(t.pos, "not.stmt"); - return F.at(t.pos).Erroneous(List.of(t)); + JCExpression ret = F.at(t.pos).Erroneous(List.of(t)); + error(ret, "not.stmt"); + return ret; } } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java Fri Sep 23 16:51:29 2011 -0700 @@ -982,8 +982,16 @@ } /** Sets the current token. + * This method is primarily used to update the token stream when the + * parser is handling the end of nested type arguments such as + * {@code List>} and needs to disambiguate between + * repeated use of ">" and relation operators such as ">>" and ">>>". Noting + * that this does not handle arbitrary tokens containing Unicode escape + * sequences. */ public void token(Token token) { + pos += this.token.name.length() - token.name.length(); + prevEndPos = pos; this.token = token; } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java --- a/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/AbstractLog.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,6 +96,19 @@ /** Report an error, unless another error was already reported at same * source position. + * @param flag A flag to set on the diagnostic + * @param pos The source position at which to report the error. + * @param key The key for the localized error message. + * @param args Fields of the error message. + */ + public void error(DiagnosticFlag flag, DiagnosticPosition pos, String key, Object ... args) { + JCDiagnostic d = diags.error(source, pos, key, args); + d.setFlag(flag); + report(d); + } + + /** Report an error, unless another error was already reported at same + * source position. * @param pos The source position at which to report the error. * @param key The key for the localized error message. * @param args Fields of the error message. diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java --- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -322,16 +322,46 @@ // public CharBuffer getCachedContent(JavaFileObject file) { - SoftReference r = contentCache.get(file); - return (r == null ? null : r.get()); + ContentCacheEntry e = contentCache.get(file); + if (e == null) + return null; + + if (!e.isValid(file)) { + contentCache.remove(file); + return null; + } + + return e.getValue(); } public void cache(JavaFileObject file, CharBuffer cb) { - contentCache.put(file, new SoftReference(cb)); + contentCache.put(file, new ContentCacheEntry(file, cb)); + } + + public void flushCache(JavaFileObject file) { + contentCache.remove(file); } - protected final Map> contentCache - = new HashMap>(); + protected final Map contentCache + = new HashMap(); + + protected static class ContentCacheEntry { + final long timestamp; + final SoftReference ref; + + ContentCacheEntry(JavaFileObject file, CharBuffer cb) { + this.timestamp = file.getLastModified(); + this.ref = new SoftReference(cb); + } + + boolean isValid(JavaFileObject file) { + return timestamp == file.getLastModified(); + } + + CharBuffer getValue() { + return ref.get(); + } + } // public static Kind getKind(String name) { diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/src/share/classes/javax/tools/JavaCompiler.java --- a/langtools/src/share/classes/javax/tools/JavaCompiler.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/src/share/classes/javax/tools/JavaCompiler.java Fri Sep 23 16:51:29 2011 -0700 @@ -26,10 +26,8 @@ package javax.tools; import java.io.File; -import java.io.InputStream; import java.io.Writer; import java.nio.charset.Charset; -import java.util.List; import java.util.Locale; import java.util.concurrent.Callable; import javax.annotation.processing.Processor; diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/7079713/TestCircularClassfile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7079713/TestCircularClassfile.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7079713 + * @summary javac hangs when compiling a class that references a cyclically inherited class + * @run main TestCircularClassfile + */ + +import java.io.*; +import java.net.URI; +import java.util.Arrays; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; + +public class TestCircularClassfile { + + enum SourceKind { + A_EXTENDS_B("class B {} class A extends B { void m() {} }"), + B_EXTENDS_A("class A { void m() {} } class B extends A {}"); + + String sourceStr; + + private SourceKind(String sourceStr) { + this.sourceStr = sourceStr; + } + + SimpleJavaFileObject getSource() { + return new SimpleJavaFileObject(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return sourceStr; + } + }; + } + } + + enum TestKind { + REPLACE_A("A.class"), + REPLACE_B("B.class"); + + String targetClass; + + private TestKind(String targetClass) { + this.targetClass = targetClass; + } + } + + enum ClientKind { + METHOD_CALL1("A a = null; a.m();"), + METHOD_CALL2("B b = null; b.m();"), + CONSTR_CALL1("new A();"), + CONSTR_CALL2("new B();"), + ASSIGN1("A a = null; B b = a;"), + ASSIGN2("B b = null; A a = b;"); + + String mainMethod; + + private ClientKind(String mainMethod) { + this.mainMethod = mainMethod; + } + + SimpleJavaFileObject getSource() { + return new SimpleJavaFileObject(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE) { + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return "class Test { public static void main(String[] args) { #M } }" + .replace("#M", mainMethod); + } + }; + } + } + + public static void main(String... args) throws Exception { + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + int count = 0; + for (SourceKind sk1 : SourceKind.values()) { + for (SourceKind sk2 : SourceKind.values()) { + for (TestKind tk : TestKind.values()) { + for (ClientKind ck : ClientKind.values()) { + new TestCircularClassfile("sub_"+count++, sk1, sk2, tk, ck).check(comp, fm); + } + } + } + } + } + + static String workDir = System.getProperty("user.dir"); + + String destPath; + SourceKind sk1; + SourceKind sk2; + TestKind tk; + ClientKind ck; + + TestCircularClassfile(String destPath, SourceKind sk1, SourceKind sk2, TestKind tk, ClientKind ck) { + this.destPath = destPath; + this.sk1 = sk1; + this.sk2 = sk2; + this.tk = tk; + this.ck = ck; + } + + void check(JavaCompiler comp, StandardJavaFileManager fm) throws Exception { + //step 1: compile first source code in the test subfolder + File destDir = new File(workDir, destPath); destDir.mkdir(); + //output dir must be set explicitly as we are sharing the fm (see bug 7026941) + fm.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); + JavacTask ct = (JavacTask)comp.getTask(null, fm, null, + null, null, Arrays.asList(sk1.getSource())); + ct.generate(); + + //step 2: compile second source code in a temp folder + File tmpDir = new File(destDir, "tmp"); tmpDir.mkdir(); + //output dir must be set explicitly as we are sharing the fm (see bug 7026941) + fm.setLocation(javax.tools.StandardLocation.CLASS_OUTPUT, Arrays.asList(tmpDir)); + ct = (JavacTask)comp.getTask(null, fm, null, + null, null, Arrays.asList(sk2.getSource())); + ct.generate(); + + //step 3: move a classfile from the temp folder to the test subfolder + File fileToMove = new File(tmpDir, tk.targetClass); + File target = new File(destDir, tk.targetClass); + target.delete(); + boolean success = fileToMove.renameTo(target); + + if (!success) { + throw new AssertionError("error when moving file " + tk.targetClass); + } + + //step 4: compile the client class against the classes in the test subfolder + //input/output dir must be set explicitly as we are sharing the fm (see bug 7026941) + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); + fm.setLocation(StandardLocation.CLASS_PATH, Arrays.asList(destDir)); + ct = (JavacTask)comp.getTask(null, fm, null, + null, null, Arrays.asList(ck.getSource())); + + ct.generate(); + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/7085024/T7085024.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7085024/T7085024.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7085024 + * @summary internal error; cannot instantiate Foo + * @compile/fail/ref=T7085024.out -XDrawDiagnostics T7085024.java + */ + +class T7085024 { + T7085024 (boolean ret) { } //internal error goes away if constructor accepts a reference type + + T7085024 f = new T7085024((NonExistentClass) null ); +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/7085024/T7085024.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/7085024/T7085024.out Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,2 @@ +T7085024.java:11:32: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, T7085024, null) +1 error diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/BadTwr.out --- a/langtools/test/tools/javac/TryWithResources/BadTwr.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/BadTwr.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ -BadTwr.java:13:39: compiler.err.already.defined: r1, main(java.lang.String...) -BadTwr.java:18:13: compiler.err.already.defined: args, main(java.lang.String...) +BadTwr.java:13:46: compiler.err.already.defined: r1, main(java.lang.String...) +BadTwr.java:18:20: compiler.err.already.defined: args, main(java.lang.String...) BadTwr.java:21:13: compiler.err.cant.assign.val.to.final.var: thatsIt -BadTwr.java:26:17: compiler.err.already.defined: name, main(java.lang.String...) +BadTwr.java:26:24: compiler.err.already.defined: name, main(java.lang.String...) 4 errors diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out --- a/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/DuplicateResourceDecl.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,2 +1,2 @@ -DuplicateResourceDecl.java:12:45: compiler.err.already.defined: c, main(java.lang.String[]) +DuplicateResourceDecl.java:12:56: compiler.err.already.defined: c, main(java.lang.String[]) 1 error diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/ResourceInterface.out --- a/langtools/test/tools/javac/TryWithResources/ResourceInterface.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/ResourceInterface.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,2 +1,2 @@ -ResourceInterface.java:38:13: compiler.err.unreported.exception.implicit.close: ResourceInterface.E1, r2 +ResourceInterface.java:38:23: compiler.err.unreported.exception.implicit.close: ResourceInterface.E1, r2 1 error diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/TwrFlow.out --- a/langtools/test/tools/javac/TryWithResources/TwrFlow.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/TwrFlow.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,3 +1,3 @@ TwrFlow.java:14:11: compiler.err.except.never.thrown.in.try: java.io.IOException -TwrFlow.java:12:13: compiler.err.unreported.exception.implicit.close: CustomCloseException, twrFlow +TwrFlow.java:12:21: compiler.err.unreported.exception.implicit.close: CustomCloseException, twrFlow 2 errors diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/TwrLint.out --- a/langtools/test/tools/javac/TryWithResources/TwrLint.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/TwrLint.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,3 +1,3 @@ TwrLint.java:14:15: compiler.warn.try.explicit.close.call -TwrLint.java:13:13: compiler.warn.try.resource.not.referenced: r3 +TwrLint.java:13:21: compiler.warn.try.resource.not.referenced: r3 2 warnings diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out --- a/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/TwrOnNonResource.out Fri Sep 23 16:51:29 2011 -0700 @@ -1,4 +1,4 @@ -TwrOnNonResource.java:12:13: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable -TwrOnNonResource.java:15:13: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable -TwrOnNonResource.java:18:13: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:12:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:15:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable +TwrOnNonResource.java:18:30: compiler.err.prob.found.req: (compiler.misc.try.not.applicable.to.type), TwrOnNonResource, java.lang.AutoCloseable 3 errors diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/TryWithResources/UnusedResourcesTest.java --- a/langtools/test/tools/javac/TryWithResources/UnusedResourcesTest.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/TryWithResources/UnusedResourcesTest.java Fri Sep 23 16:51:29 2011 -0700 @@ -28,6 +28,7 @@ */ import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.ClientCodeWrapper; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.util.JCDiagnostic; import java.net.URI; @@ -236,7 +237,7 @@ public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.WARNING && diagnostic.getCode().contains("try.resource.not.referenced")) { - String varName = ((JCDiagnostic)diagnostic).getArgs()[0].toString(); + String varName = unwrap(diagnostic).getArgs()[0].toString(); if (varName.equals(TwrStmt.TWR1.resourceName)) { unused_r1 = true; } else if (varName.equals(TwrStmt.TWR2.resourceName)) { @@ -246,5 +247,13 @@ } } } + + private JCDiagnostic unwrap(Diagnostic diagnostic) { + if (diagnostic instanceof JCDiagnostic) + return (JCDiagnostic) diagnostic; + if (diagnostic instanceof ClientCodeWrapper.DiagnosticSourceUnwrapper) + return ((ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic).d; + throw new IllegalArgumentException(); + } } } diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/annotations/T7043371.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/T7043371.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7043371 + * @summary javac7 fails with NPE during compilation + * @compile T7043371.java + */ + +@interface Anno { + String value(); +} + +class B { + @Anno(value=A.a) + public static final int b = 0; +} + +class A { + @Deprecated + public static final String a = "a"; +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/annotations/T7073477.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/annotations/T7073477.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7073477 + * @summary NPE in com.sun.tools.javac.code.Symbol$VarSymbol.getConstValue + * @compile T7073477.java + */ + +@SuppressWarnings(T7073477A.S) +class T7073477 { +} + +class T7073477A { + @SuppressWarnings("") + static final String S = ""; +} + diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/api/7086261/T7086261.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/api/7086261/T7086261.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 20011, 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 7086261 + * @summary javac doesn't report error as expected, it only reports ClientCodeWrapper$DiagnosticSourceUnwrapper + */ + +import javax.tools.*; + +import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper; +import com.sun.tools.javac.util.JCDiagnostic; + +import java.net.URI; +import java.util.Arrays; + +import static javax.tools.StandardLocation.*; +import static javax.tools.JavaFileObject.Kind.*; + + +public class T7086261 { + + static class ErroneousSource extends SimpleJavaFileObject { + public ErroneousSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + } + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return "class Test { NonexistentClass c = null; }"; + } + } + + static class DiagnosticChecker implements DiagnosticListener { + public void report(Diagnostic message) { + if (!(message instanceof DiagnosticSourceUnwrapper)) { + throw new AssertionError("Wrapped diagnostic expected!"); + } + String actual = message.toString(); + JCDiagnostic jd = (JCDiagnostic)((DiagnosticSourceUnwrapper)message).d; + String expected = jd.toString(); + if (!actual.equals(expected)) { + throw new AssertionError("expected = " + expected + "\nfound = " + actual); + } + } + }; + + void test() throws Throwable { + JavaCompiler javac = ToolProvider.getSystemJavaCompiler(); + JavaFileManager jfm = javac.getStandardFileManager(null, null, null); + JavaCompiler.CompilationTask task = + javac.getTask(null, jfm, new DiagnosticChecker(), null, null, Arrays.asList(new ErroneousSource())); + task.call(); + } + + public static void main(String[] args) throws Throwable { + new T7086261().test(); + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/diags/Example.java --- a/langtools/test/tools/javac/diags/Example.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/diags/Example.java Fri Sep 23 16:51:29 2011 -0700 @@ -21,10 +21,12 @@ * questions. */ -import com.sun.tools.javac.file.JavacFileManager; import java.io.*; +import java.net.URL; +import java.net.URLClassLoader; import java.util.*; import java.util.regex.*; +import javax.annotation.processing.Processor; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler; @@ -37,12 +39,11 @@ // import com.sun.tools.javac.Main // import com.sun.tools.javac.main.Main +import com.sun.tools.javac.api.ClientCodeWrapper; +import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.JCDiagnostic; -import java.net.URL; -import java.net.URLClassLoader; -import javax.annotation.processing.Processor; /** * Class to handle example code designed to illustrate javac diagnostic messages. @@ -397,7 +398,7 @@ if (keys != null) { for (Diagnostic d: dc.getDiagnostics()) { - scanForKeys((JCDiagnostic) d, keys); + scanForKeys(unwrap(d), keys); } } @@ -418,6 +419,14 @@ for (JCDiagnostic sd: d.getSubdiagnostics()) scanForKeys(sd, keys); } + + private JCDiagnostic unwrap(Diagnostic diagnostic) { + if (diagnostic instanceof JCDiagnostic) + return (JCDiagnostic) diagnostic; + if (diagnostic instanceof ClientCodeWrapper.DiagnosticSourceUnwrapper) + return ((ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic).d; + throw new IllegalArgumentException(); + } } /** diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java --- a/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ // key: compiler.err.empty.char.lit // key: compiler.err.unclosed.char.lit -// key: compiler.err.expected // key: compiler.err.premature.eof class X { diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/file/T7068451.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/file/T7068451.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7068451 + * @summary Regression: javac compiles fixed sources against previous, + * not current, version of generated sources + */ + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.Filer; +import javax.annotation.processing.Messager; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +public class T7068451 { + public static void main(String[] args) throws Exception { + new T7068451().run(); + } + + void run() throws Exception { + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + System.err.println("using " + compiler.getClass() + " from " + compiler.getClass().getProtectionDomain().getCodeSource()); + + File tmp = new File("tmp"); + tmp.mkdir(); + for (File f: tmp.listFiles()) + f.delete(); + + File input = writeFile(tmp, "X.java", "package p; class X { { p.C.first(); } }"); + + List opts = Arrays.asList( + "-s", tmp.getPath(), + "-d", tmp.getPath(), + "-XprintRounds"); + + System.err.println(); + System.err.println("FIRST compilation"); + System.err.println(); + + CompilationTask task = compiler.getTask(null, null, null, opts, null, + compiler.getStandardFileManager(null, null, null).getJavaFileObjects(input)); + task.setProcessors(Collections.singleton(new Proc("first"))); + check("compilation", task.call()); + + writeFile(tmp, "X.java", "package p; class X { { p.C.second(); } }"); + + //Thread.sleep(2000); + + System.err.println(); + System.err.println("SECOND compilation"); + System.err.println(); + + task = compiler.getTask(null, null, null, opts, null, + compiler.getStandardFileManager(null, null, null).getJavaFileObjects(input)); + task.setProcessors(Collections.singleton(new Proc("second"))); + check("compilation", task.call()); + + //Thread.sleep(2000); + + System.err.println(); + System.err.println("SECOND compilation, REPEATED"); + System.err.println(); + + task = compiler.getTask(null, null, null, opts, null, + compiler.getStandardFileManager(null, null, null).getJavaFileObjects(input)); + task.setProcessors(Collections.singleton(new Proc("second"))); + check("compilation", task.call()); + } + + void check(String msg, boolean ok) { + System.err.println(msg + ": " + (ok ? "ok" : "failed")); + if (!ok) + throw new AssertionError(msg); + } + + static File writeFile(File base, String path, String body) throws IOException { + File f = new File(base, path); + FileWriter out = new FileWriter(f); + out.write(body); + out.close(); + System.err.println("wrote " + path + ": " + body); + return f; + } + + @SupportedAnnotationTypes("*") + private static class Proc extends AbstractProcessor { + final String m; + Proc(String m) { + this.m = m; + } + + int count; + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver() || count++ > 0) { + return false; + } + + Filer filer = processingEnv.getFiler(); + Messager messager = processingEnv.getMessager(); + + System.err.println("running Proc"); + try { + int len = filer.getResource(StandardLocation.SOURCE_OUTPUT, "p", "C.java").getCharContent(false).length(); + messager.printMessage(Kind.NOTE, "C.java: found previous content of length " + len); + } catch (FileNotFoundException x) { + messager.printMessage(Kind.NOTE, "C.java: not previously there"); + } catch (IOException x) { + messager.printMessage(Kind.ERROR, "while reading: " + x); + } + + try { + String body = "package p; public class C { public static void " + m + "() {} }"; + Writer w = filer.createSourceFile("p.C").openWriter(); + w.write(body); + w.close(); + messager.printMessage(Kind.NOTE, "C.java: wrote new content: " + body); + } catch (IOException x) { + messager.printMessage(Kind.ERROR, "while writing: " + x); + } + + return true; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + } +} + diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/jvm/T7024096.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/jvm/T7024096.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,31 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7024096 + * @summary Stack trace has invalid line numbers + * @author Bruce Chapman + * @compile T7024096.java + * @run main T7024096 + */ + +public class T7024096 { + private static final int START = 14; // starting line number for the test + public static void main(String[] args) { + T7024096 m = new T7024096(); + m.nest(START); + m.nest(START + 1, m.nest(START + 1), m.nest(START + 1), + m.nest(START + 2), + m.nest(START + 3, m.nest(START + 3))); + } + + public T7024096 nest(int expectedline, T7024096... args) { + Exception e = new Exception("expected line#: " + expectedline); + int myline = e.getStackTrace()[1].getLineNumber(); + if( myline != expectedline) { + throw new RuntimeException("Incorrect line number " + + "expected: " + expectedline + + ", got: " + myline, e); + } + System.out.format("Got expected line number %d correct %n", myline); + return null; + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/parser/netbeans/JavacParserTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/test/tools/javac/parser/netbeans/JavacParserTest.java Fri Sep 23 16:51:29 2011 -0700 @@ -0,0 +1,716 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7073631 + * @summary tests error and diagnostics positions + * @author jan.lahoda@oracle.com + */ + +import com.sun.source.tree.BinaryTree; +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionStatementTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.ModifiersTree; +import com.sun.source.tree.StatementTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.tree.VariableTree; +import com.sun.source.tree.WhileLoopTree; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.tree.JCTree; +import java.io.IOException; +import java.net.URI; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.DiagnosticListener; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.ToolProvider; + +public class JavacParserTest extends TestCase { + final JavaCompiler tool; + public JavacParserTest(String testName) { + tool = ToolProvider.getSystemJavaCompiler(); + System.out.println("java.home=" + System.getProperty("java.home")); + } + + static class MyFileObject extends SimpleJavaFileObject { + + private String text; + + public MyFileObject(String text) { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + this.text = text; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return text; + } + } + + public void testPositionForSuperConstructorCalls() throws IOException { + assert tool != null; + + String code = "package test; public class Test {public Test() {super();}}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + MethodTree method = + (MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0); + ExpressionStatementTree es = + (ExpressionStatementTree) method.getBody().getStatements().get(0); + + assertEquals("testPositionForSuperConstructorCalls", + 72 - 24, pos.getStartPosition(cut, es)); + assertEquals("testPositionForSuperConstructorCalls", + 80 - 24, pos.getEndPosition(cut, es)); + + MethodInvocationTree mit = (MethodInvocationTree) es.getExpression(); + + assertEquals("testPositionForSuperConstructorCalls", + 72 - 24, pos.getStartPosition(cut, mit)); + assertEquals("testPositionForSuperConstructorCalls", + 79 - 24, pos.getEndPosition(cut, mit)); + + assertEquals("testPositionForSuperConstructorCalls", + 72 - 24, pos.getStartPosition(cut, mit.getMethodSelect())); + assertEquals("testPositionForSuperConstructorCalls", + 77 - 24, pos.getEndPosition(cut, mit.getMethodSelect())); + + } + + public void testPositionForEnumModifiers() throws IOException { + + String code = "package test; public enum Test {A;}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + ModifiersTree mt = clazz.getModifiers(); + + assertEquals("testPositionForEnumModifiers", + 38 - 24, pos.getStartPosition(cut, mt)); + assertEquals("testPositionForEnumModifiers", + 44 - 24, pos.getEndPosition(cut, mt)); + } + + public void testNewClassWithEnclosing() throws IOException { + + + String code = "package test; class Test { " + + "class d {} private void method() { " + + "Object o = Test.this.new d(); } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + SourcePositions pos = Trees.instance(ct).getSourcePositions(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + ExpressionTree est = + ((VariableTree) ((MethodTree) clazz.getMembers().get(1)).getBody().getStatements().get(0)).getInitializer(); + + assertEquals("testNewClassWithEnclosing", + 97 - 24, pos.getStartPosition(cut, est)); + assertEquals("testNewClassWithEnclosing", + 114 - 24, pos.getEndPosition(cut, est)); + } + + public void testPreferredPositionForBinaryOp() throws IOException { + + String code = "package test; public class Test {" + + "private void test() {" + + "Object o = null; boolean b = o != null && o instanceof String;" + + "} private Test() {}}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree method = (MethodTree) clazz.getMembers().get(0); + VariableTree condSt = (VariableTree) method.getBody().getStatements().get(1); + BinaryTree cond = (BinaryTree) condSt.getInitializer(); + + JCTree condJC = (JCTree) cond; + + assertEquals("testNewClassWithEnclosing", + 117 - 24, condJC.pos); + } + + public void testPositionBrokenSource126732a() throws IOException { + String[] commands = new String[]{ + "return Runnable()", + "do { } while (true)", + "throw UnsupportedOperationException()", + "assert true", + "1 + 1",}; + + for (String command : commands) { + + String code = "package test;\n" + + "public class Test {\n" + + " public static void test() {\n" + + " " + command + " {\n" + + " new Runnable() {\n" + + " };\n" + + " }\n" + + "}"; + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, + null, null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree method = (MethodTree) clazz.getMembers().get(0); + List statements = + method.getBody().getStatements(); + + StatementTree ret = statements.get(0); + StatementTree block = statements.get(1); + + Trees t = Trees.instance(ct); + int len = code.indexOf(command + " {") + (command + " ").length(); + assertEquals(command, len, + t.getSourcePositions().getEndPosition(cut, ret)); + assertEquals(command, len, + t.getSourcePositions().getStartPosition(cut, block)); + } + } + + public void testPositionBrokenSource126732b() throws IOException { + String[] commands = new String[]{ + "break", + "break A", + "continue ", + "continue A",}; + + for (String command : commands) { + + String code = "package test;\n" + + "public class Test {\n" + + " public static void test() {\n" + + " while (true) {\n" + + " " + command + " {\n" + + " new Runnable() {\n" + + " };\n" + + " }\n" + + " }\n" + + "}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, + null, null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree method = (MethodTree) clazz.getMembers().get(0); + List statements = + ((BlockTree) ((WhileLoopTree) method.getBody().getStatements().get(0)).getStatement()).getStatements(); + + StatementTree ret = statements.get(0); + StatementTree block = statements.get(1); + + Trees t = Trees.instance(ct); + int len = code.indexOf(command + " {") + (command + " ").length(); + assertEquals(command, len, + t.getSourcePositions().getEndPosition(cut, ret)); + assertEquals(command, len, + t.getSourcePositions().getStartPosition(cut, block)); + } + } + + public void testErrorRecoveryForEnhancedForLoop142381() throws IOException { + + String code = "package test; class Test { " + + "private void method() { " + + "java.util.Set s = null; for (a : s) {} } }"; + + final List> errors = + new LinkedList>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener() { + public void report(Diagnostic diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + CompilationUnitTree cut = ct.parse().iterator().next(); + + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + StatementTree forStatement = + ((MethodTree) clazz.getMembers().get(0)).getBody().getStatements().get(1); + + assertEquals("testErrorRecoveryForEnhancedForLoop142381", + Kind.ENHANCED_FOR_LOOP, forStatement.getKind()); + assertFalse("testErrorRecoveryForEnhancedForLoop142381", errors.isEmpty()); + } + + public void testPositionAnnotationNoPackage187551() throws IOException { + + String code = "\n@interface Test {}"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + Trees t = Trees.instance(ct); + + assertEquals("testPositionAnnotationNoPackage187551", + 1, t.getSourcePositions().getStartPosition(cut, clazz)); + } + + public void testPositionsSane() throws IOException { + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List> l; " + + "} }"); + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List> l; " + + "} }"); + performPositionsSanityTest("package test; class Test { " + + "private void method() { " + + "java.util.List> l; } }"); + } + + private void performPositionsSanityTest(String code) throws IOException { + + final List> errors = + new LinkedList>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener() { + + public void report(Diagnostic diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + final CompilationUnitTree cut = ct.parse().iterator().next(); + final Trees trees = Trees.instance(ct); + + new TreeScanner() { + + private long parentStart = 0; + private long parentEnd = Integer.MAX_VALUE; + + @Override + public Void scan(Tree node, Void p) { + if (node == null) { + return null; + } + + long start = trees.getSourcePositions().getStartPosition(cut, node); + + if (start == (-1)) { + return null; //synthetic tree + } + assertTrue(node.toString() + ":" + start + "/" + parentStart, + parentStart <= start); + + long prevParentStart = parentStart; + + parentStart = start; + + long end = trees.getSourcePositions().getEndPosition(cut, node); + + assertTrue(node.toString() + ":" + end + "/" + parentEnd, + end <= parentEnd); + + long prevParentEnd = parentEnd; + + parentEnd = end; + + super.scan(node, p); + + parentStart = prevParentStart; + parentEnd = prevParentEnd; + + return null; + } + + private void assertTrue(String message, boolean b) { + if (!b) fail(message); + } + }.scan(cut, null); + } + + public void testCorrectWilcardPositions() throws IOException { + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List> l; } }", + + Arrays.asList("List> l;", + "List>", + "List", + "? extends List", + "List", + "List", + "? extends String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List> l; } }", + + Arrays.asList("List> l;", + "List>", + "List", + "? super List", + "List", + "List", + "? super String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { List> l; } }", + + Arrays.asList("List> l;", + "List>", + "List", + "? super List", + "List", + "List", + "?")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { " + + "List>> l; } }", + + Arrays.asList("List>> l;", + "List>>", + "List", + "? extends List>", + "List>", + "List", + "? extends List", + "List", + "List", + "? extends String", + "String")); + performWildcardPositionsTest("package test; import java.util.List; " + + "class Test { private void method() { " + + "List>> l; } }", + Arrays.asList("List>> l;", + "List>>", + "List", + "? extends List>", + "List>", + "List", + "? extends List", + "List", + "List", + "? extends String", + "String")); + } + + public void performWildcardPositionsTest(final String code, + List golden) throws IOException { + + final List> errors = + new LinkedList>(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, + new DiagnosticListener() { + public void report(Diagnostic diagnostic) { + errors.add(diagnostic); + } + }, null, null, Arrays.asList(new MyFileObject(code))); + + final CompilationUnitTree cut = ct.parse().iterator().next(); + final List content = new LinkedList(); + final Trees trees = Trees.instance(ct); + + new TreeScanner() { + @Override + public Void scan(Tree node, Void p) { + if (node == null) { + return null; + } + long start = trees.getSourcePositions().getStartPosition(cut, node); + + if (start == (-1)) { + return null; //synthetic tree + } + long end = trees.getSourcePositions().getEndPosition(cut, node); + String s = code.substring((int) start, (int) end); + content.add(s); + + return super.scan(node, p); + } + }.scan(((MethodTree) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0)).getBody().getStatements().get(0), null); + + assertEquals("performWildcardPositionsTest",golden.toString(), + content.toString()); + } + + public void testStartPositionForMethodWithoutModifiers() throws IOException { + + String code = "package t; class Test { void t() {} }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + MethodTree mt = (MethodTree) clazz.getMembers().get(0); + Trees t = Trees.instance(ct); + int start = (int) t.getSourcePositions().getStartPosition(cut, mt); + int end = (int) t.getSourcePositions().getEndPosition(cut, mt); + + assertEquals("testStartPositionForMethodWithoutModifiers", + " void t() {}", code.substring(start, end)); + } + + public void testStartPositionEnumConstantInit() throws IOException { + + String code = "package t; enum Test { AAA; }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + ClassTree clazz = (ClassTree) cut.getTypeDecls().get(0); + VariableTree enumAAA = (VariableTree) clazz.getMembers().get(0); + Trees t = Trees.instance(ct); + int start = (int) t.getSourcePositions().getStartPosition(cut, + enumAAA.getInitializer()); + + assertEquals("testStartPositionEnumConstantInit", -1, start); + } + + public void testVariableInIfThen1() throws IOException { + + String code = "package t; class Test { " + + "private static void t(String name) { " + + "if (name != null) String nn = name.trim(); } }"; + + DiagnosticCollector coll = + new DiagnosticCollector(); + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List codes = new LinkedList(); + + for (Diagnostic d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen1", + Arrays.asList("compiler.err.variable.not.allowed"), + codes); + } + + public void testVariableInIfThen2() throws IOException { + + String code = "package t; class Test { " + + "private static void t(String name) { " + + "if (name != null) class X {} } }"; + DiagnosticCollector coll = + new DiagnosticCollector(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List codes = new LinkedList(); + + for (Diagnostic d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen2", + Arrays.asList("compiler.err.class.not.allowed"), codes); + } + + public void testVariableInIfThen3() throws IOException { + + String code = "package t; class Test { "+ + "private static void t(String name) { " + + "if (name != null) abstract } }"; + DiagnosticCollector coll = + new DiagnosticCollector(); + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, coll, null, + null, Arrays.asList(new MyFileObject(code))); + + ct.parse(); + + List codes = new LinkedList(); + + for (Diagnostic d : coll.getDiagnostics()) { + codes.add(d.getCode()); + } + + assertEquals("testVariableInIfThen3", + Arrays.asList("compiler.err.illegal.start.of.expr"), + codes); + } + + //see javac bug #6882235, NB bug #98234: + public void testMissingExponent() throws IOException { + + String code = "\nclass Test { { System.err.println(0e); } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + + assertNotNull(ct.parse().iterator().next()); + } + + public void testTryResourcePos() throws IOException { + + final String code = "package t; class Test { " + + "{ try (java.io.InputStream in = null) { } } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + new TreeScanner() { + @Override + public Void visitVariable(VariableTree node, Void p) { + if ("in".contentEquals(node.getName())) { + JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; + System.out.println(node.getName() + "," + var.pos); + assertEquals("testTryResourcePos", "in = null) { } } }", + code.substring(var.pos)); + } + return super.visitVariable(node, p); + } + }.scan(cut, null); + } + + public void testVarPos() throws IOException { + + final String code = "package t; class Test { " + + "{ java.io.InputStream in = null; } }"; + + JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, null, null, null, + null, Arrays.asList(new MyFileObject(code))); + CompilationUnitTree cut = ct.parse().iterator().next(); + + new TreeScanner() { + + @Override + public Void visitVariable(VariableTree node, Void p) { + if ("in".contentEquals(node.getName())) { + JCTree.JCVariableDecl var = (JCTree.JCVariableDecl) node; + assertEquals("testVarPos","in = null; } }", + code.substring(var.pos)); + } + return super.visitVariable(node, p); + } + }.scan(cut, null); + } + + void testsNotWorking() throws IOException { + + // Fails with nb-javac, needs further investigation + testPositionBrokenSource126732a(); + testPositionBrokenSource126732b(); + + // Fails, these tests yet to be addressed + testVariableInIfThen1(); + testVariableInIfThen2(); + testPositionForEnumModifiers(); + testStartPositionEnumConstantInit(); + } + void testPositions() throws IOException { + testPositionsSane(); + testCorrectWilcardPositions(); + testPositionAnnotationNoPackage187551(); + testPositionForSuperConstructorCalls(); + testPreferredPositionForBinaryOp(); + testStartPositionForMethodWithoutModifiers(); + testVarPos(); + testVariableInIfThen3(); + testTryResourcePos(); + } + + public static void main(String... args) throws IOException { + JavacParserTest jpt = new JavacParserTest("JavacParserTest"); + jpt.testPositions(); + System.out.println("PASS"); + } +} + +abstract class TestCase { + + void assertEquals(String message, int i, int pos) { + if (i != pos) { + fail(message); + } + } + + void assertFalse(String message, boolean empty) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + void assertEquals(String message, int i, long l) { + if (i != l) { + fail(message + ":" + i + ":" + l); + } + } + + void assertEquals(String message, Object o1, Object o2) { + System.out.println(o1); + System.out.println(o2); + if (o1 != null && o2 != null && !o1.equals(o2)) { + fail(message); + } + if (o1 == null && o2 != null) { + fail(message); + } + } + + void assertNotNull(Object o) { + if (o == null) { + fail(); + } + } + + void fail() { + fail("test failed"); + } + + void fail(String message) { + throw new RuntimeException(message); + } +} diff -r 244113d67cf0 -r 5e57ab6c83a3 langtools/test/tools/javac/processing/errors/TestSuppression.java --- a/langtools/test/tools/javac/processing/errors/TestSuppression.java Wed Sep 21 17:08:02 2011 +0400 +++ b/langtools/test/tools/javac/processing/errors/TestSuppression.java Fri Sep 23 16:51:29 2011 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import javax.tools.*; import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.ClientCodeWrapper; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.util.JCDiagnostic; @@ -171,7 +172,7 @@ public void report(Diagnostic diagnostic) { System.err.println((++total) + ": " - + "resolveError:" + isResolveError((JCDiagnostic) diagnostic) + "\n" + + "resolveError:" + isResolveError(unwrap(diagnostic)) + "\n" + diagnostic); Diagnostic.Kind dk = diagnostic.getKind(); Integer c = counts.get(dk); @@ -181,6 +182,14 @@ private static boolean isResolveError(JCDiagnostic d) { return d.isFlagSet(RESOLVE_ERROR); } + + private JCDiagnostic unwrap(Diagnostic diagnostic) { + if (diagnostic instanceof JCDiagnostic) + return (JCDiagnostic) diagnostic; + if (diagnostic instanceof ClientCodeWrapper.DiagnosticSourceUnwrapper) + return ((ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic).d; + throw new IllegalArgumentException(); + } } @SupportedAnnotationTypes("*")