From e6e820c6474e3608abe4e08698097d06dda2900e Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Thu, 13 Oct 2011 12:00:51 +0100 Subject: [PATCH 01/41] 7099228: Use a PKCS11 config attribute to control encoding of an EC point Reviewed-by: valeriep, mullan --- .../classes/sun/security/pkcs11/Config.java | 11 +++++++++ .../sun/security/pkcs11/P11ECKeyFactory.java | 20 ++++++++++------ .../classes/sun/security/pkcs11/P11Key.java | 23 +++++++------------ .../share/lib/security/sunpkcs11-solaris.cfg | 3 +++ jdk/test/ProblemList.txt | 3 --- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs11/Config.java b/jdk/src/share/classes/sun/security/pkcs11/Config.java index dbed2cf8f4c..08cb6de40c9 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/Config.java +++ b/jdk/src/share/classes/sun/security/pkcs11/Config.java @@ -192,6 +192,11 @@ final class Config { // works only for NSS providers created via the Secmod API private boolean nssUseSecmodTrust = false; + // Flag to indicate whether the X9.63 encoding for EC points shall be used + // (true) or whether that encoding shall be wrapped in an ASN.1 OctetString + // (false). + private boolean useEcX963Encoding = false; + private Config(String filename, InputStream in) throws IOException { if (in == null) { if (filename.startsWith("--")) { @@ -320,6 +325,10 @@ final class Config { return nssUseSecmodTrust; } + boolean getUseEcX963Encoding() { + return useEcX963Encoding; + } + private static String expand(final String s) throws IOException { try { return PropertyExpander.expand(s); @@ -440,6 +449,8 @@ final class Config { parseNSSArgs(word); } else if (word.equals("nssUseSecmodTrust")) { nssUseSecmodTrust = parseBooleanEntry(word); + } else if (word.equals("useEcX963Encoding")) { + useEcX963Encoding = parseBooleanEntry(word); } else { throw new ConfigurationException ("Unknown keyword '" + word + "', line " + st.lineno()); diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java b/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java index d44231a6bf2..ef6cf3a1ef5 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java @@ -203,14 +203,20 @@ final class P11ECKeyFactory extends P11KeyFactory { private PublicKey generatePublic(ECPoint point, ECParameterSpec params) throws PKCS11Exception { byte[] encodedParams = ECParameters.encodeParameters(params); - byte[] encodedPoint = null; - DerValue pkECPoint = new DerValue(DerValue.tag_OctetString, - ECParameters.encodePoint(point, params.getCurve())); + byte[] encodedPoint = + ECParameters.encodePoint(point, params.getCurve()); - try { - encodedPoint = pkECPoint.toByteArray(); - } catch (IOException e) { - throw new IllegalArgumentException("Could not DER encode point", e); + // Check whether the X9.63 encoding of an EC point shall be wrapped + // in an ASN.1 OCTET STRING + if (!token.config.getUseEcX963Encoding()) { + try { + encodedPoint = + new DerValue(DerValue.tag_OctetString, encodedPoint) + .toByteArray(); + } catch (IOException e) { + throw new + IllegalArgumentException("Could not DER encode point", e); + } } CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] { diff --git a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java index 54ccd3213c2..bbce8982e90 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/P11Key.java +++ b/jdk/src/share/classes/sun/security/pkcs11/P11Key.java @@ -1028,28 +1028,21 @@ abstract class P11Key implements Key { try { params = P11ECKeyFactory.decodeParameters (attributes[1].getByteArray()); - - /* - * An uncompressed EC point may be in either of two formats. - * First try the OCTET STRING encoding: - * 04 04 - * - * Otherwise try the raw encoding: - * 04 - */ byte[] ecKey = attributes[0].getByteArray(); - try { + // Check whether the X9.63 encoding of an EC point is wrapped + // in an ASN.1 OCTET STRING + if (!token.config.getUseEcX963Encoding()) { DerValue wECPoint = new DerValue(ecKey); - if (wECPoint.getTag() != DerValue.tag_OctetString) - throw new IOException("Unexpected tag: " + - wECPoint.getTag()); + if (wECPoint.getTag() != DerValue.tag_OctetString) { + throw new IOException("Could not DER decode EC point." + + " Unexpected tag: " + wECPoint.getTag()); + } w = P11ECKeyFactory.decodePoint (wECPoint.getDataBytes(), params.getCurve()); - } catch (IOException e) { - // Failover + } else { w = P11ECKeyFactory.decodePoint(ecKey, params.getCurve()); } diff --git a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg index daf03a447a3..3b3f7fa82f9 100644 --- a/jdk/src/share/lib/security/sunpkcs11-solaris.cfg +++ b/jdk/src/share/lib/security/sunpkcs11-solaris.cfg @@ -11,6 +11,9 @@ library = /usr/lib/$ISA/libpkcs11.so handleStartupErrors = ignoreAll +# Use the X9.63 encoding for EC points (do not wrap in an ASN.1 OctetString). +useEcX963Encoding = true + attributes = compatibility disabledMechanisms = { diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index c2fd9fc0cfc..6097bcf7b97 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -517,9 +517,6 @@ sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java generic-all # 7079203 sun/security/tools/keytool/printssl.sh fails on solaris with timeout sun/security/tools/keytool/printssl.sh solaris-all -# 7054637 -sun/security/tools/jarsigner/ec.sh solaris-all - # 7081817 sun/security/provider/certpath/X509CertPath/IllegalCertiticates.java generic-all From 4bc227715b2c484b23eec40ae2d70dca6b02c257 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Thu, 13 Oct 2011 13:50:17 -0400 Subject: [PATCH 02/41] 6953295: Move few sun.security.{util, x509, pkcs} classes used by keytool/jarsigner to another package Reviewed-by: mchung --- jdk/make/sun/security/other/Makefile | 1 + .../sun/security/pkcs/EncodingException.java | 45 ---- .../sun/security/{pkcs => pkcs10}/PKCS10.java | 2 +- .../{pkcs => pkcs10}/PKCS10Attribute.java | 5 +- .../{pkcs => pkcs10}/PKCS10Attributes.java | 4 +- .../provider/certpath/CertStoreHelper.java | 68 +++++- .../provider/certpath/URICertStore.java | 163 +++++-------- .../provider/certpath/ldap/LDAPCertStore.java | 2 +- .../certpath/ldap/LDAPCertStoreHelper.java | 8 +- .../certpath/ssl/SSLServerCertStore.java | 153 ++++++++++++ .../ssl/SSLServerCertStoreHelper.java | 69 ++++++ .../{x509 => tools}/CertAndKeyGen.java | 16 +- .../classes/sun/security/tools/KeyTool.java | 223 ++++++------------ .../security/{util => tools}/PathList.java | 4 +- .../classes/sun/security/util/BigInt.java | 198 ---------------- .../util/BigInt/BigIntEqualsHashCode.java | 46 ---- 16 files changed, 439 insertions(+), 568 deletions(-) delete mode 100644 jdk/src/share/classes/sun/security/pkcs/EncodingException.java rename jdk/src/share/classes/sun/security/{pkcs => pkcs10}/PKCS10.java (99%) rename jdk/src/share/classes/sun/security/{pkcs => pkcs10}/PKCS10Attribute.java (97%) rename jdk/src/share/classes/sun/security/{pkcs => pkcs10}/PKCS10Attributes.java (98%) create mode 100644 jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java create mode 100644 jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java rename jdk/src/share/classes/sun/security/{x509 => tools}/CertAndKeyGen.java (95%) rename jdk/src/share/classes/sun/security/{util => tools}/PathList.java (97%) delete mode 100644 jdk/src/share/classes/sun/security/util/BigInt.java delete mode 100644 jdk/test/sun/security/util/BigInt/BigIntEqualsHashCode.java diff --git a/jdk/make/sun/security/other/Makefile b/jdk/make/sun/security/other/Makefile index 78893730edd..cc869aec2e3 100644 --- a/jdk/make/sun/security/other/Makefile +++ b/jdk/make/sun/security/other/Makefile @@ -38,6 +38,7 @@ AUTO_FILES_JAVA_DIRS = \ sun/security/acl \ sun/security/jca \ sun/security/pkcs \ + sun/security/pkcs10 \ sun/security/pkcs12 \ sun/security/provider \ sun/security/rsa \ diff --git a/jdk/src/share/classes/sun/security/pkcs/EncodingException.java b/jdk/src/share/classes/sun/security/pkcs/EncodingException.java deleted file mode 100644 index 81650cd89f5..00000000000 --- a/jdk/src/share/classes/sun/security/pkcs/EncodingException.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 1996, 2003, 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. - */ - -/** - * Generic PKCS Encoding exception. - * - * @author Benjamin Renaud - */ - -package sun.security.pkcs; - -public class EncodingException extends Exception { - - private static final long serialVersionUID = 4060198374240668325L; - - public EncodingException() { - super(); - } - - public EncodingException(String s) { - super(s); - } -} diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS10.java b/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java similarity index 99% rename from jdk/src/share/classes/sun/security/pkcs/PKCS10.java rename to jdk/src/share/classes/sun/security/pkcs10/PKCS10.java index 6303c8b9adf..c5418c67d07 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS10.java +++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10.java @@ -24,7 +24,7 @@ */ -package sun.security.pkcs; +package sun.security.pkcs10; import java.io.PrintStream; import java.io.IOException; diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attribute.java b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attribute.java similarity index 97% rename from jdk/src/share/classes/sun/security/pkcs/PKCS10Attribute.java rename to jdk/src/share/classes/sun/security/pkcs10/PKCS10Attribute.java index a83813157b0..c7cac3baa25 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attribute.java +++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attribute.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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,11 +23,12 @@ * questions. */ -package sun.security.pkcs; +package sun.security.pkcs10; import java.io.OutputStream; import java.io.IOException; +import sun.security.pkcs.PKCS9Attribute; import sun.security.util.*; /** diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attributes.java b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attributes.java similarity index 98% rename from jdk/src/share/classes/sun/security/pkcs/PKCS10Attributes.java rename to jdk/src/share/classes/sun/security/pkcs10/PKCS10Attributes.java index 8279ae237eb..d35f3a7fe29 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS10Attributes.java +++ b/jdk/src/share/classes/sun/security/pkcs10/PKCS10Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ * questions. */ -package sun.security.pkcs; +package sun.security.pkcs10; import java.io.IOException; import java.io.OutputStream; diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java index 891919a4bb1..e325239d114 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 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 @@ -27,32 +27,86 @@ package sun.security.provider.certpath; import java.net.URI; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.security.AccessController; import java.security.NoSuchAlgorithmException; import java.security.InvalidAlgorithmParameterException; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.security.cert.CertStore; import java.security.cert.X509CertSelector; import java.security.cert.X509CRLSelector; import javax.security.auth.x500.X500Principal; import java.io.IOException; +import sun.security.util.Cache; + /** - * Helper used by URICertStore when delegating to another CertStore to - * fetch certs and CRLs. + * Helper used by URICertStore and others when delegating to another CertStore + * to fetch certs and CRLs. */ -public interface CertStoreHelper { +public abstract class CertStoreHelper { + + private static final int NUM_TYPES = 2; + private final static Map classMap = new HashMap<>(NUM_TYPES); + static { + classMap.put( + "LDAP", + "sun.security.provider.certpath.ldap.LDAPCertStoreHelper"); + classMap.put( + "SSLServer", + "sun.security.provider.certpath.ssl.SSLServerCertStoreHelper"); + }; + private static Cache cache = Cache.newSoftMemoryCache(NUM_TYPES); + + public static CertStoreHelper getInstance(final String type) + throws NoSuchAlgorithmException + { + CertStoreHelper helper = (CertStoreHelper)cache.get(type); + if (helper != null) { + return helper; + } + final String cl = classMap.get(type); + if (cl == null) { + throw new NoSuchAlgorithmException(type + " not available"); + } + try { + helper = AccessController.doPrivileged( + new PrivilegedExceptionAction() { + public CertStoreHelper run() throws ClassNotFoundException { + try { + Class c = Class.forName(cl, true, null); + CertStoreHelper csh + = (CertStoreHelper)c.newInstance(); + cache.put(type, csh); + return csh; + } catch (InstantiationException e) { + throw new AssertionError(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + } + }); + return helper; + } catch (PrivilegedActionException e) { + throw new NoSuchAlgorithmException(type + " not available", + e.getException()); + } + } /** * Returns a CertStore using the given URI as parameters. */ - CertStore getCertStore(URI uri) + public abstract CertStore getCertStore(URI uri) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException; /** * Wraps an existing X509CertSelector when needing to avoid DN matching * issues. */ - X509CertSelector wrap(X509CertSelector selector, + public abstract X509CertSelector wrap(X509CertSelector selector, X500Principal certSubject, String dn) throws IOException; @@ -61,7 +115,7 @@ public interface CertStoreHelper { * Wraps an existing X509CRLSelector when needing to avoid DN matching * issues. */ - X509CRLSelector wrap(X509CRLSelector selector, + public abstract X509CRLSelector wrap(X509CRLSelector selector, Collection certIssuers, String dn) throws IOException; diff --git a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java index 321f9153ec3..da607724437 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java @@ -30,8 +30,6 @@ import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URLConnection; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.security.InvalidAlgorithmParameterException; import java.security.NoSuchAlgorithmException; import java.security.Provider; @@ -120,35 +118,10 @@ class URICertStore extends CertStoreSpi { // true if URI is ldap private boolean ldap = false; + private CertStoreHelper ldapHelper; private CertStore ldapCertStore; private String ldapPath; - /** - * Holder class to lazily load LDAPCertStoreHelper if present. - */ - private static class LDAP { - private static final String CERT_STORE_HELPER = - "sun.security.provider.certpath.ldap.LDAPCertStoreHelper"; - private static final CertStoreHelper helper = - AccessController.doPrivileged( - new PrivilegedAction() { - public CertStoreHelper run() { - try { - Class c = Class.forName(CERT_STORE_HELPER, true, null); - return (CertStoreHelper)c.newInstance(); - } catch (ClassNotFoundException cnf) { - return null; - } catch (InstantiationException e) { - throw new AssertionError(e); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } - }}); - static CertStoreHelper helper() { - return helper; - } - } - /** * Creates a URICertStore. * @@ -164,10 +137,9 @@ class URICertStore extends CertStoreSpi { this.uri = ((URICertStoreParameters) params).uri; // if ldap URI, use an LDAPCertStore to fetch certs and CRLs if (uri.getScheme().toLowerCase(Locale.ENGLISH).equals("ldap")) { - if (LDAP.helper() == null) - throw new NoSuchAlgorithmException("LDAP not present"); ldap = true; - ldapCertStore = LDAP.helper().getCertStore(uri); + ldapHelper = CertStoreHelper.getInstance("LDAP"); + ldapCertStore = ldapHelper.getCertStore(uri); ldapPath = uri.getPath(); // strip off leading '/' if (ldapPath.charAt(0) == '/') { @@ -251,7 +223,7 @@ class URICertStore extends CertStoreSpi { if (ldap) { X509CertSelector xsel = (X509CertSelector) selector; try { - xsel = LDAP.helper().wrap(xsel, xsel.getSubject(), ldapPath); + xsel = ldapHelper.wrap(xsel, xsel.getSubject(), ldapPath); } catch (IOException ioe) { throw new CertStoreException(ioe); } @@ -273,57 +245,44 @@ class URICertStore extends CertStoreSpi { return getMatchingCerts(certs, selector); } lastChecked = time; - InputStream in = null; try { URLConnection connection = uri.toURL().openConnection(); if (lastModified != 0) { connection.setIfModifiedSince(lastModified); } - in = connection.getInputStream(); long oldLastModified = lastModified; - lastModified = connection.getLastModified(); - if (oldLastModified != 0) { - if (oldLastModified == lastModified) { - if (debug != null) { - debug.println("Not modified, using cached copy"); - } - return getMatchingCerts(certs, selector); - } else if (connection instanceof HttpURLConnection) { - // some proxy servers omit last modified - HttpURLConnection hconn = (HttpURLConnection) connection; - if (hconn.getResponseCode() - == HttpURLConnection.HTTP_NOT_MODIFIED) { + try (InputStream in = connection.getInputStream()) { + lastModified = connection.getLastModified(); + if (oldLastModified != 0) { + if (oldLastModified == lastModified) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCerts(certs, selector); + } else if (connection instanceof HttpURLConnection) { + // some proxy servers omit last modified + HttpURLConnection hconn = (HttpURLConnection)connection; + if (hconn.getResponseCode() + == HttpURLConnection.HTTP_NOT_MODIFIED) { + if (debug != null) { + debug.println("Not modified, using cached copy"); + } + return getMatchingCerts(certs, selector); + } } } - } - if (debug != null) { - debug.println("Downloading new certificates..."); - } - // Safe cast since factory is an X.509 certificate factory - certs = (Collection) - factory.generateCertificates(in); - return getMatchingCerts(certs, selector); - } catch (IOException e) { - if (debug != null) { - debug.println("Exception fetching certificates:"); - e.printStackTrace(); - } - } catch (CertificateException e) { - if (debug != null) { - debug.println("Exception fetching certificates:"); - e.printStackTrace(); - } - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // ignore + if (debug != null) { + debug.println("Downloading new certificates..."); } + // Safe cast since factory is an X.509 certificate factory + certs = (Collection) + factory.generateCertificates(in); + } + return getMatchingCerts(certs, selector); + } catch (IOException | CertificateException e) { + if (debug != null) { + debug.println("Exception fetching certificates:"); + e.printStackTrace(); } } // exception, forget previous values @@ -343,8 +302,7 @@ class URICertStore extends CertStoreSpi { if (selector == null) { return certs; } - List matchedCerts = - new ArrayList(certs.size()); + List matchedCerts = new ArrayList<>(certs.size()); for (X509Certificate cert : certs) { if (selector.match(cert)) { matchedCerts.add(cert); @@ -374,7 +332,7 @@ class URICertStore extends CertStoreSpi { if (ldap) { X509CRLSelector xsel = (X509CRLSelector) selector; try { - xsel = LDAP.helper().wrap(xsel, null, ldapPath); + xsel = ldapHelper.wrap(xsel, null, ldapPath); } catch (IOException ioe) { throw new CertStoreException(ioe); } @@ -395,55 +353,42 @@ class URICertStore extends CertStoreSpi { return getMatchingCRLs(crl, selector); } lastChecked = time; - InputStream in = null; try { URLConnection connection = uri.toURL().openConnection(); if (lastModified != 0) { connection.setIfModifiedSince(lastModified); } - in = connection.getInputStream(); long oldLastModified = lastModified; - lastModified = connection.getLastModified(); - if (oldLastModified != 0) { - if (oldLastModified == lastModified) { - if (debug != null) { - debug.println("Not modified, using cached copy"); - } - return getMatchingCRLs(crl, selector); - } else if (connection instanceof HttpURLConnection) { - // some proxy servers omit last modified - HttpURLConnection hconn = (HttpURLConnection) connection; - if (hconn.getResponseCode() - == HttpURLConnection.HTTP_NOT_MODIFIED) { + try (InputStream in = connection.getInputStream()) { + lastModified = connection.getLastModified(); + if (oldLastModified != 0) { + if (oldLastModified == lastModified) { if (debug != null) { debug.println("Not modified, using cached copy"); } return getMatchingCRLs(crl, selector); + } else if (connection instanceof HttpURLConnection) { + // some proxy servers omit last modified + HttpURLConnection hconn = (HttpURLConnection)connection; + if (hconn.getResponseCode() + == HttpURLConnection.HTTP_NOT_MODIFIED) { + if (debug != null) { + debug.println("Not modified, using cached copy"); + } + return getMatchingCRLs(crl, selector); + } } } - } - if (debug != null) { - debug.println("Downloading new CRL..."); - } - crl = (X509CRL) factory.generateCRL(in); - return getMatchingCRLs(crl, selector); - } catch (IOException e) { - if (debug != null) { - debug.println("Exception fetching CRL:"); - e.printStackTrace(); - } - } catch (CRLException e) { - if (debug != null) { - debug.println("Exception fetching CRL:"); - e.printStackTrace(); - } - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException e) { - // ignore + if (debug != null) { + debug.println("Downloading new CRL..."); } + crl = (X509CRL) factory.generateCRL(in); + } + return getMatchingCRLs(crl, selector); + } catch (IOException | CRLException e) { + if (debug != null) { + debug.println("Exception fetching CRL:"); + e.printStackTrace(); } } // exception, forget previous values diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java index d86404d0802..3eea0b25fff 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java @@ -103,7 +103,7 @@ import sun.security.action.GetPropertyAction; * @author Steve Hanna * @author Andreas Sterbenz */ -public class LDAPCertStore extends CertStoreSpi { +public final class LDAPCertStore extends CertStoreSpi { private static final Debug debug = Debug.getInstance("certpath"); diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java index 7eb65d5a7a8..5ec100c6a1d 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 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 @@ -41,11 +41,9 @@ import sun.security.provider.certpath.CertStoreHelper; * LDAP implementation of CertStoreHelper. */ -public class LDAPCertStoreHelper - implements CertStoreHelper +public final class LDAPCertStoreHelper + extends CertStoreHelper { - public LDAPCertStoreHelper() { } - @Override public CertStore getCertStore(URI uri) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java new file mode 100644 index 00000000000..5109e132d22 --- /dev/null +++ b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStore.java @@ -0,0 +1,153 @@ +/* + * 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. + */ + +package sun.security.provider.certpath.ssl; + +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.security.GeneralSecurityException; +import java.security.InvalidAlgorithmParameterException; +import java.security.Provider; +import java.security.cert.CertificateException; +import java.security.cert.CertSelector; +import java.security.cert.CertStore; +import java.security.cert.CertStoreException; +import java.security.cert.CertStoreParameters; +import java.security.cert.CertStoreSpi; +import java.security.cert.CRLSelector; +import java.security.cert.X509Certificate; +import java.security.cert.X509CRL; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +/** + * A CertStore that retrieves an SSL server's certificate chain. + */ +public final class SSLServerCertStore extends CertStoreSpi { + + private final URI uri; + + SSLServerCertStore(URI uri) throws InvalidAlgorithmParameterException { + super(null); + this.uri = uri; + } + + public synchronized Collection engineGetCertificates + (CertSelector selector) throws CertStoreException + { + try { + SSLContext sc = SSLContext.getInstance("SSL"); + GetChainTrustManager xtm = new GetChainTrustManager(); + sc.init(null, new TrustManager[] { xtm }, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + HttpsURLConnection.setDefaultHostnameVerifier( + new HostnameVerifier() { + public boolean verify(String hostname, SSLSession session) { + return true; + } + }); + uri.toURL().openConnection().connect(); + return getMatchingCerts(xtm.serverChain, selector); + } catch (GeneralSecurityException | IOException e) { + throw new CertStoreException(e); + } + } + + private static List getMatchingCerts + (List certs, CertSelector selector) + { + // if selector not specified, all certs match + if (selector == null) { + return certs; + } + List matchedCerts = new ArrayList<>(certs.size()); + for (X509Certificate cert : certs) { + if (selector.match(cert)) { + matchedCerts.add(cert); + } + } + return matchedCerts; + } + + public Collection engineGetCRLs(CRLSelector selector) + throws CertStoreException + { + throw new UnsupportedOperationException(); + } + + static synchronized CertStore getInstance(URI uri) + throws InvalidAlgorithmParameterException + { + return new CS(new SSLServerCertStore(uri), null, "SSLServer", null); + } + + /* + * An X509TrustManager that simply stores a reference to the server's + * certificate chain. + */ + private static class GetChainTrustManager implements X509TrustManager { + private List serverChain; + + public X509Certificate[] getAcceptedIssuers() { + throw new UnsupportedOperationException(); + } + + public void checkClientTrusted(X509Certificate[] chain, + String authType) + throws CertificateException + { + throw new UnsupportedOperationException(); + } + + public void checkServerTrusted(X509Certificate[] chain, + String authType) + throws CertificateException + { + this.serverChain = (chain == null) + ? Collections.emptyList() + : Arrays.asList(chain); + } + } + + /** + * This class allows the SSLServerCertStore to be accessed as a CertStore. + */ + private static class CS extends CertStore { + protected CS(CertStoreSpi spi, Provider p, String type, + CertStoreParameters params) + { + super(spi, p, type, params); + } + } +} diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java new file mode 100644 index 00000000000..fd36adfbad1 --- /dev/null +++ b/jdk/src/share/classes/sun/security/provider/certpath/ssl/SSLServerCertStoreHelper.java @@ -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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.security.provider.certpath.ssl; + +import java.net.URI; +import java.util.Collection; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidAlgorithmParameterException; +import java.security.cert.CertStore; +import java.security.cert.X509CertSelector; +import java.security.cert.X509CRLSelector; +import javax.security.auth.x500.X500Principal; +import java.io.IOException; + +import sun.security.provider.certpath.CertStoreHelper; + +/** + * SSL implementation of CertStoreHelper. + */ +public final class SSLServerCertStoreHelper extends CertStoreHelper { + + @Override + public CertStore getCertStore(URI uri) + throws NoSuchAlgorithmException, InvalidAlgorithmParameterException + { + return SSLServerCertStore.getInstance(uri); + } + + @Override + public X509CertSelector wrap(X509CertSelector selector, + X500Principal certSubject, + String ldapDN) + throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public X509CRLSelector wrap(X509CRLSelector selector, + Collection certIssuers, + String ldapDN) + throws IOException + { + throw new UnsupportedOperationException(); + } +} diff --git a/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java b/jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java similarity index 95% rename from jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java rename to jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java index f1560c716ad..4c32a33b4f7 100644 --- a/jdk/src/share/classes/sun/security/x509/CertAndKeyGen.java +++ b/jdk/src/share/classes/sun/security/tools/CertAndKeyGen.java @@ -23,7 +23,7 @@ * questions. */ -package sun.security.x509; +package sun.security.tools; import java.io.IOException; import java.security.cert.X509Certificate; @@ -32,7 +32,19 @@ import java.security.cert.CertificateEncodingException; import java.security.*; import java.util.Date; -import sun.security.pkcs.PKCS10; +import sun.security.pkcs10.PKCS10; +import sun.security.x509.AlgorithmId; +import sun.security.x509.CertificateAlgorithmId; +import sun.security.x509.CertificateIssuerName; +import sun.security.x509.CertificateSerialNumber; +import sun.security.x509.CertificateSubjectName; +import sun.security.x509.CertificateValidity; +import sun.security.x509.CertificateVersion; +import sun.security.x509.CertificateX509Key; +import sun.security.x509.X500Name; +import sun.security.x509.X509CertImpl; +import sun.security.x509.X509CertInfo; +import sun.security.x509.X509Key; /** diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 2e67bcea23b..0d928209807 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -38,10 +38,12 @@ import java.security.Signature; import java.security.Timestamp; import java.security.UnrecoverableEntryException; import java.security.UnrecoverableKeyException; +import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.Provider; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.security.cert.CertStoreException; import java.security.cert.CRL; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; @@ -63,23 +65,16 @@ import java.security.cert.X509CRLSelector; import javax.security.auth.x500.X500Principal; import sun.misc.BASE64Encoder; import sun.security.util.ObjectIdentifier; -import sun.security.pkcs.PKCS10; +import sun.security.pkcs10.PKCS10; +import sun.security.pkcs10.PKCS10Attribute; import sun.security.provider.X509Factory; +import sun.security.provider.certpath.CertStoreHelper; import sun.security.util.Password; -import sun.security.util.PathList; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; import sun.misc.BASE64Decoder; -import sun.security.pkcs.PKCS10Attribute; import sun.security.pkcs.PKCS9Attribute; -import sun.security.provider.certpath.ldap.LDAPCertStoreHelper; import sun.security.util.DerValue; import sun.security.x509.*; @@ -917,18 +912,13 @@ public final class KeyTool { // Perform the specified command if (command == CERTREQ) { - PrintStream ps = null; if (filename != null) { - ps = new PrintStream(new FileOutputStream - (filename)); - out = ps; - } - try { - doCertReq(alias, sigAlgName, out); - } finally { - if (ps != null) { - ps.close(); + try (PrintStream ps = new PrintStream(new FileOutputStream + (filename))) { + doCertReq(alias, sigAlgName, ps); } + } else { + doCertReq(alias, sigAlgName, out); } if (verbose && filename != null) { MessageFormat form = new MessageFormat(rb.getString @@ -941,18 +931,13 @@ public final class KeyTool { doDeleteEntry(alias); kssave = true; } else if (command == EXPORTCERT) { - PrintStream ps = null; if (filename != null) { - ps = new PrintStream(new FileOutputStream - (filename)); - out = ps; - } - try { - doExportCert(alias, out); - } finally { - if (ps != null) { - ps.close(); + try (PrintStream ps = new PrintStream(new FileOutputStream + (filename))) { + doExportCert(alias, ps); } + } else { + doExportCert(alias, out); } if (filename != null) { MessageFormat form = new MessageFormat(rb.getString @@ -973,16 +958,12 @@ public final class KeyTool { doGenSecretKey(alias, keyAlgName, keysize); kssave = true; } else if (command == IDENTITYDB) { - InputStream inStream = System.in; if (filename != null) { - inStream = new FileInputStream(filename); - } - try { - doImportIdentityDatabase(inStream); - } finally { - if (inStream != System.in) { - inStream.close(); + try (InputStream inStream = new FileInputStream(filename)) { + doImportIdentityDatabase(inStream); } + } else { + doImportIdentityDatabase(System.in); } } else if (command == IMPORTCERT) { InputStream inStream = System.in; @@ -1101,29 +1082,21 @@ public final class KeyTool { if (alias == null) { alias = keyAlias; } - PrintStream ps = null; if (filename != null) { - ps = new PrintStream(new FileOutputStream(filename)); - out = ps; - } - try { - doGenCRL(out); - } finally { - if (ps != null) { - ps.close(); + try (PrintStream ps = + new PrintStream(new FileOutputStream(filename))) { + doGenCRL(ps); } + } else { + doGenCRL(out); } } else if (command == PRINTCERTREQ) { - InputStream inStream = System.in; if (filename != null) { - inStream = new FileInputStream(filename); - } - try { - doPrintCertReq(inStream, out); - } finally { - if (inStream != System.in) { - inStream.close(); + try (InputStream inStream = new FileInputStream(filename)) { + doPrintCertReq(inStream, out); } + } else { + doPrintCertReq(System.in, out); } } else if (command == PRINTCRL) { doPrintCRL(filename, out); @@ -2070,12 +2043,13 @@ public final class KeyTool { } } } else { // must be LDAP, and uri is not null + // Lazily load LDAPCertStoreHelper if present + CertStoreHelper helper = CertStoreHelper.getInstance("LDAP"); String path = uri.getPath(); if (path.charAt(0) == '/') path = path.substring(1); - LDAPCertStoreHelper h = new LDAPCertStoreHelper(); - CertStore s = h.getCertStore(uri); + CertStore s = helper.getCertStore(uri); X509CRLSelector sel = - h.wrap(new X509CRLSelector(), null, path); + helper.wrap(new X509CRLSelector(), null, path); return s.getCRLs(sel); } } @@ -2259,18 +2233,12 @@ public final class KeyTool { int pos = 0; while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); - InputStream is = null; - try { - is = jf.getInputStream(je); + try (InputStream is = jf.getInputStream(je)) { while (is.read(buffer) != -1) { // we just read. this will throw a SecurityException // if a signature/digest check fails. This also // populate the signers } - } finally { - if (is != null) { - is.close(); - } } CodeSigner[] signers = je.getCodeSigners(); if (signers != null) { @@ -2316,85 +2284,52 @@ public final class KeyTool { out.println(rb.getString("Not.a.signed.jar.file")); } } else if (sslserver != null) { - SSLContext sc = SSLContext.getInstance("SSL"); - final boolean[] certPrinted = new boolean[1]; - sc.init(null, new TrustManager[] { - new X509TrustManager() { - - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return null; - } - - public void checkClientTrusted( - java.security.cert.X509Certificate[] certs, String authType) { - } - - public void checkServerTrusted( - java.security.cert.X509Certificate[] certs, String authType) { - for (int i=0; i 0) { - certPrinted[0] = true; - } - } - } - }, null); - HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); - HttpsURLConnection.setDefaultHostnameVerifier( - new HostnameVerifier() { - public boolean verify(String hostname, SSLSession session) { - return true; - } - }); - // HTTPS instead of raw SSL, so that -Dhttps.proxyHost and - // -Dhttps.proxyPort can be used. Since we only go through - // the handshake process, an HTTPS server is not needed. - // This program should be able to deal with any SSL-based - // network service. - Exception ex = null; + // Lazily load SSLCertStoreHelper if present + CertStoreHelper helper = CertStoreHelper.getInstance("SSLServer"); + CertStore cs = helper.getCertStore(new URI("https://" + sslserver)); + Collection chain; try { - new URL("https://" + sslserver).openConnection().connect(); - } catch (Exception e) { - ex = e; - } - // If the certs are not printed out, we consider it an error even - // if the URL connection is successful. - if (!certPrinted[0]) { - Exception e = new Exception( - rb.getString("No.certificate.from.the.SSL.server")); - if (ex != null) { - e.initCause(ex); + chain = cs.getCertificates(null); + if (chain.isEmpty()) { + // If the certs are not retrieved, we consider it an error + // even if the URL connection is successful. + throw new Exception(rb.getString( + "No.certificate.from.the.SSL.server")); + } + } catch (CertStoreException cse) { + if (cse.getCause() instanceof IOException) { + throw new Exception(rb.getString( + "No.certificate.from.the.SSL.server"), + cse.getCause()); + } else { + throw cse; + } + } + + int i = 0; + for (Certificate cert : chain) { + try { + if (rfc) { + dumpCert(cert, out); + } else { + out.println("Certificate #" + i++); + out.println("===================================="); + printX509Cert((X509Certificate)cert, out); + out.println(); + } + } catch (Exception e) { + if (debug) { + e.printStackTrace(); + } } - throw e; } } else { - InputStream inStream = System.in; if (filename != null) { - inStream = new FileInputStream(filename); - } - try { - printCertFromStream(inStream, out); - } finally { - if (inStream != System.in) { - inStream.close(); + try (FileInputStream inStream = new FileInputStream(filename)) { + printCertFromStream(inStream, out); } + } else { + printCertFromStream(System.in, out); } } } @@ -2590,9 +2525,7 @@ public final class KeyTool { X509Certificate cert = null; try { cert = (X509Certificate)cf.generateCertificate(in); - } catch (ClassCastException cce) { - throw new Exception(rb.getString("Input.not.an.X.509.certificate")); - } catch (CertificateException ce) { + } catch (ClassCastException | CertificateException ce) { throw new Exception(rb.getString("Input.not.an.X.509.certificate")); } @@ -3441,16 +3374,10 @@ public final class KeyTool { if (!file.exists()) { return null; } - FileInputStream fis = null; KeyStore caks = null; - try { - fis = new FileInputStream(file); + try (FileInputStream fis = new FileInputStream(file)) { caks = KeyStore.getInstance(JKS); caks.load(fis, null); - } finally { - if (fis != null) { - fis.close(); - } } return caks; } diff --git a/jdk/src/share/classes/sun/security/util/PathList.java b/jdk/src/share/classes/sun/security/tools/PathList.java similarity index 97% rename from jdk/src/share/classes/sun/security/util/PathList.java rename to jdk/src/share/classes/sun/security/tools/PathList.java index 4d1fa71d704..f059a5ea1aa 100644 --- a/jdk/src/share/classes/sun/security/util/PathList.java +++ b/jdk/src/share/classes/sun/security/tools/PathList.java @@ -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 @@ -23,7 +23,7 @@ * questions. */ -package sun.security.util; +package sun.security.tools; import java.io.File; import java.io.IOException; diff --git a/jdk/src/share/classes/sun/security/util/BigInt.java b/jdk/src/share/classes/sun/security/util/BigInt.java deleted file mode 100644 index 4713cc4d9fb..00000000000 --- a/jdk/src/share/classes/sun/security/util/BigInt.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.security.util; - -import java.math.BigInteger; - - -/** - * A low-overhead arbitrary-precision unsigned integer. - * This is intended for use with ASN.1 parsing, and printing of - * such parsed values. Convert to "BigInteger" if you need to do - * arbitrary precision arithmetic, rather than just represent - * the number as a wrapped array of bytes. - * - *

NOTE: This class may eventually disappear, to - * be supplanted by big-endian byte arrays which hold both signed - * and unsigned arbitrary-precision integers. - * - * @author David Brownell - */ -public final class BigInt { - - // Big endian -- MSB first. - private byte[] places; - - /** - * Constructs a "Big" integer from a set of (big-endian) bytes. - * Leading zeroes should be stripped off. - * - * @param data a sequence of bytes, most significant bytes/digits - * first. CONSUMED. - */ - public BigInt(byte[] data) { places = data.clone(); } - - /** - * Constructs a "Big" integer from a "BigInteger", which must be - * positive (or zero) in value. - */ - public BigInt(BigInteger i) { - byte[] temp = i.toByteArray(); - - if ((temp[0] & 0x80) != 0) - throw new IllegalArgumentException("negative BigInteger"); - - // XXX we assume exactly _one_ sign byte is used... - - if (temp[0] != 0) - places = temp; - else { - places = new byte[temp.length - 1]; - for (int j = 1; j < temp.length; j++) - places[j - 1] = temp[j]; - } - } - - /** - * Constructs a "Big" integer from a normal Java integer. - * - * @param i the java primitive integer - */ - public BigInt(int i) { - if (i < (1 << 8)) { - places = new byte[1]; - places[0] = (byte) i; - } else if (i < (1 << 16)) { - places = new byte[2]; - places[0] = (byte) (i >> 8); - places[1] = (byte) i; - } else if (i < (1 << 24)) { - places = new byte[3]; - places[0] = (byte) (i >> 16); - places[1] = (byte) (i >> 8); - places[2] = (byte) i; - } else { - places = new byte[4]; - places[0] = (byte) (i >> 24); - places[1] = (byte) (i >> 16); - places[2] = (byte) (i >> 8); - places[3] = (byte) i; - } - } - - /** - * Converts the "big" integer to a java primitive integer. - * - * @excpet NumberFormatException if 32 bits is insufficient. - */ - public int toInt() { - if (places.length > 4) - throw new NumberFormatException("BigInt.toLong, too big"); - int retval = 0, i = 0; - for (; i < places.length; i++) - retval = (retval << 8) + ((int)places[i] & 0xff); - return retval; - } - - /** - * Returns a hexadecimal printed representation. The value is - * formatted to fit on lines of at least 75 characters, with - * embedded newlines. Words are separated for readability, - * with eight words (32 bytes) per line. - */ - public String toString() { return hexify(); } - - /** - * Returns a BigInteger value which supports many arithmetic - * operations. Assumes negative values will never occur. - */ - public BigInteger toBigInteger() - { return new BigInteger(1, places); } - - /** - * Returns the data as a byte array. The most significant bit - * of the array is bit zero (as in java.math.BigInteger). - */ - public byte[] toByteArray() { return places.clone(); } - - private static final String digits = "0123456789abcdef"; - private String hexify() { - if (places.length == 0) - return " 0 "; - - StringBuffer buf = new StringBuffer(places.length * 2); - buf.append(" "); // four spaces - for (int i = 0; i < places.length; i++) { - buf.append(digits.charAt((places[i] >> 4) & 0x0f)); - buf.append(digits.charAt(places[i] & 0x0f)); - if (((i + 1) % 32) == 0) { - if ((i + 1) != places.length) - buf.append("\n "); // line after four words - } else if (((i + 1) % 4) == 0) - buf.append(' '); // space between words - } - return buf.toString(); - } - - /** - * Returns true iff the parameter is a numerically equivalent - * BigInt. - * - * @param other the object being compared with this one. - */ - public boolean equals(Object other) { - if (other instanceof BigInt) - return equals((BigInt) other); - return false; - } - - /** - * Returns true iff the parameter is numerically equivalent. - * - * @param other the BigInt being compared with this one. - */ - public boolean equals(BigInt other) { - if (this == other) - return true; - - byte[] otherPlaces = other.toByteArray(); - if (places.length != otherPlaces.length) - return false; - for (int i = 0; i < places.length; i++) - if (places[i] != otherPlaces[i]) - return false; - return true; - } - - /** - * Returns a hashcode for this BigInt. - * - * @return a hashcode for this BigInt. - */ - public int hashCode() { - return hexify().hashCode(); - } -} diff --git a/jdk/test/sun/security/util/BigInt/BigIntEqualsHashCode.java b/jdk/test/sun/security/util/BigInt/BigIntEqualsHashCode.java deleted file mode 100644 index 5da5752e1e6..00000000000 --- a/jdk/test/sun/security/util/BigInt/BigIntEqualsHashCode.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 1999, 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 - * @author Gary Ellison - * @bug 4170635 - * @summary Verify equals()/hashCode() contract honored - */ - -import java.io.*; -import sun.security.util.*; - - -public class BigIntEqualsHashCode { - public static void main(String[] args) throws Exception { - BigInt bi1 = new BigInt(12345678); - BigInt bi2 = new BigInt(12345678); - - if ( (bi1.equals(bi2)) == (bi1.hashCode()==bi2.hashCode()) ) - System.out.println("PASSED"); - else - throw new Exception ("FAILED equals()/hashCode() contract"); - - } -} From ab1010388dba92bfa00545e06d01be8e34eae7ae Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 17 Oct 2011 17:11:26 +0800 Subject: [PATCH 03/41] 7099399: cannot deal with CRL file larger than 16MB Reviewed-by: xuelei, mullan --- .../sun/security/provider/X509Factory.java | 17 ++++ .../security/provider/X509Factory/BigCRL.java | 87 +++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 jdk/test/sun/security/provider/X509Factory/BigCRL.java diff --git a/jdk/src/share/classes/sun/security/provider/X509Factory.java b/jdk/src/share/classes/sun/security/provider/X509Factory.java index 0260ff5c7bf..15122a0eafc 100644 --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java @@ -669,6 +669,23 @@ public class X509Factory extends CertificateFactorySpi { bout.write(midByte); bout.write(lowByte); length = (highByte << 16) | (midByte << 8) | lowByte; + } else if (n == 0x84) { + int highByte = is.read(); + int nextByte = is.read(); + int midByte = is.read(); + int lowByte = is.read(); + if (lowByte == -1) { + throw new IOException("Incomplete BER/DER length info"); + } + if (highByte > 127) { + throw new IOException("Invalid BER/DER data (a little huge?)"); + } + bout.write(highByte); + bout.write(nextByte); + bout.write(midByte); + bout.write(lowByte); + length = (highByte << 24 ) | (nextByte << 16) | + (midByte << 8) | lowByte; } else { // ignore longer length forms throw new IOException("Invalid BER/DER data (too huge?)"); } diff --git a/jdk/test/sun/security/provider/X509Factory/BigCRL.java b/jdk/test/sun/security/provider/X509Factory/BigCRL.java new file mode 100644 index 00000000000..acee51a1434 --- /dev/null +++ b/jdk/test/sun/security/provider/X509Factory/BigCRL.java @@ -0,0 +1,87 @@ +/* + * 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 7099399 + * @summary cannot deal with CRL file larger than 16MB + * @run main/othervm -Xmx1024m BigCRL + */ + +import java.io.FileInputStream; +import java.math.BigInteger; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.PrivateKey; +import java.security.cert.X509CRLEntry; +import java.util.Arrays; +import java.util.Date; +import sun.security.x509.*; +import java.security.cert.CertificateFactory; +import java.io.ByteArrayInputStream; + +public class BigCRL { + + public static void main(String[] args) throws Exception { + int n = 500000; + String ks = System.getProperty("test.src", ".") + + "/../../ssl/etc/keystore"; + String pass = "passphrase"; + String alias = "dummy"; + + KeyStore keyStore = KeyStore.getInstance("JKS"); + keyStore.load(new FileInputStream(ks), pass.toCharArray()); + Certificate signerCert = keyStore.getCertificate(alias); + byte[] encoded = signerCert.getEncoded(); + X509CertImpl signerCertImpl = new X509CertImpl(encoded); + X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." + + CertificateSubjectName.DN_NAME); + + Date date = new Date(); + PrivateKey privateKey = (PrivateKey) + keyStore.getKey(alias, pass.toCharArray()); + String sigAlgName = signerCertImpl.getSigAlgOID(); + + X509CRLEntry[] badCerts = new X509CRLEntry[n]; + CRLExtensions ext = new CRLExtensions(); + ext.set("Reason", new CRLReasonCodeExtension(1)); + for (int i = 0; i < n; i++) { + badCerts[i] = new X509CRLEntryImpl( + BigInteger.valueOf(i), date, ext); + } + X509CRLImpl crl = new X509CRLImpl(owner, date, date, badCerts); + crl.sign(privateKey, sigAlgName); + byte[] data = crl.getEncodedInternal(); + + // Make sure the CRL is big enough + if ((data[1]&0xff) != 0x84) { + throw new Exception("The file should be big enough?"); + } + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + cf.generateCRL(new ByteArrayInputStream(data)); + } +} + From 9852219b7e071395c8cf2c04da0e8d71128439ad Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 18 Oct 2011 10:12:14 -0400 Subject: [PATCH 04/41] 7092897: sun.security.util.Cache should be generified Reviewed-by: xuelei --- .../classes/sun/security/pkcs11/KeyCache.java | 10 +- .../sun/security/provider/X509Factory.java | 23 +-- .../provider/certpath/CertStoreHelper.java | 5 +- .../provider/certpath/URICertStore.java | 17 +- .../certpath/X509CertificatePair.java | 9 +- .../provider/certpath/ldap/LDAPCertStore.java | 45 +++--- .../security/ssl/SSLSessionContextImpl.java | 31 ++-- .../classes/sun/security/util/Cache.java | 146 ++++++++++-------- 8 files changed, 149 insertions(+), 137 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java b/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java index 359156f7dc9..1687649e10e 100644 --- a/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java +++ b/jdk/src/share/classes/sun/security/pkcs11/KeyCache.java @@ -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 @@ -48,7 +48,7 @@ import sun.security.util.Cache; */ final class KeyCache { - private final Cache strongCache; + private final Cache strongCache; private WeakReference> cacheReference; @@ -77,7 +77,7 @@ final class KeyCache { } synchronized P11Key get(Key key) { - P11Key p11Key = (P11Key)strongCache.get(new IdentityWrapper(key)); + P11Key p11Key = strongCache.get(new IdentityWrapper(key)); if (p11Key != null) { return p11Key; } @@ -94,8 +94,8 @@ final class KeyCache { Map map = (cacheReference == null) ? null : cacheReference.get(); if (map == null) { - map = new IdentityHashMap(); - cacheReference = new WeakReference>(map); + map = new IdentityHashMap<>(); + cacheReference = new WeakReference<>(map); } map.put(key, p11Key); } diff --git a/jdk/src/share/classes/sun/security/provider/X509Factory.java b/jdk/src/share/classes/sun/security/provider/X509Factory.java index 0260ff5c7bf..b3d738fb856 100644 --- a/jdk/src/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/share/classes/sun/security/provider/X509Factory.java @@ -64,8 +64,10 @@ public class X509Factory extends CertificateFactorySpi { private static final int ENC_MAX_LENGTH = 4096 * 1024; // 4 MB MAX - private static final Cache certCache = Cache.newSoftMemoryCache(750); - private static final Cache crlCache = Cache.newSoftMemoryCache(750); + private static final Cache certCache + = Cache.newSoftMemoryCache(750); + private static final Cache crlCache + = Cache.newSoftMemoryCache(750); /** * Generates an X.509 certificate object and initializes it with @@ -90,7 +92,7 @@ public class X509Factory extends CertificateFactorySpi { try { byte[] encoding = readOneBlock(is); if (encoding != null) { - X509CertImpl cert = (X509CertImpl)getFromCache(certCache, encoding); + X509CertImpl cert = getFromCache(certCache, encoding); if (cert != null) { return cert; } @@ -151,7 +153,7 @@ public class X509Factory extends CertificateFactorySpi { } else { encoding = c.getEncoded(); } - X509CertImpl newC = (X509CertImpl)getFromCache(certCache, encoding); + X509CertImpl newC = getFromCache(certCache, encoding); if (newC != null) { return newC; } @@ -181,7 +183,7 @@ public class X509Factory extends CertificateFactorySpi { } else { encoding = c.getEncoded(); } - X509CRLImpl newC = (X509CRLImpl)getFromCache(crlCache, encoding); + X509CRLImpl newC = getFromCache(crlCache, encoding); if (newC != null) { return newC; } @@ -198,18 +200,17 @@ public class X509Factory extends CertificateFactorySpi { /** * Get the X509CertImpl or X509CRLImpl from the cache. */ - private static synchronized Object getFromCache(Cache cache, + private static synchronized V getFromCache(Cache cache, byte[] encoding) { Object key = new Cache.EqualByteArray(encoding); - Object value = cache.get(key); - return value; + return cache.get(key); } /** * Add the X509CertImpl or X509CRLImpl to the cache. */ - private static synchronized void addToCache(Cache cache, byte[] encoding, - Object value) { + private static synchronized void addToCache(Cache cache, + byte[] encoding, V value) { if (encoding.length > ENC_MAX_LENGTH) { return; } @@ -361,7 +362,7 @@ public class X509Factory extends CertificateFactorySpi { try { byte[] encoding = readOneBlock(is); if (encoding != null) { - X509CRLImpl crl = (X509CRLImpl)getFromCache(crlCache, encoding); + X509CRLImpl crl = getFromCache(crlCache, encoding); if (crl != null) { return crl; } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java index e325239d114..8670778ee7e 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java @@ -59,12 +59,13 @@ public abstract class CertStoreHelper { "SSLServer", "sun.security.provider.certpath.ssl.SSLServerCertStoreHelper"); }; - private static Cache cache = Cache.newSoftMemoryCache(NUM_TYPES); + private static Cache cache + = Cache.newSoftMemoryCache(NUM_TYPES); public static CertStoreHelper getInstance(final String type) throws NoSuchAlgorithmException { - CertStoreHelper helper = (CertStoreHelper)cache.get(type); + CertStoreHelper helper = cache.get(type); if (helper != null) { return helper; } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java index da607724437..6fb7bc72af3 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java @@ -100,8 +100,7 @@ class URICertStore extends CertStoreSpi { private final CertificateFactory factory; // cached Collection of X509Certificates (may be empty, never null) - private Collection certs = - Collections.emptySet(); + private Collection certs = Collections.emptySet(); // cached X509CRL (may be null) private X509CRL crl; @@ -157,14 +156,14 @@ class URICertStore extends CertStoreSpi { * Returns a URI CertStore. This method consults a cache of * CertStores (shared per JVM) using the URI as a key. */ - private static final Cache certStoreCache = - Cache.newSoftMemoryCache(CACHE_SIZE); + private static final Cache + certStoreCache = Cache.newSoftMemoryCache(CACHE_SIZE); static synchronized CertStore getInstance(URICertStoreParameters params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { if (debug != null) { debug.println("CertStore URI:" + params.uri); } - CertStore ucs = (CertStore) certStoreCache.get(params); + CertStore ucs = certStoreCache.get(params); if (ucs == null) { ucs = new UCS(new URICertStore(params), null, "URI", params); certStoreCache.put(params, ucs); @@ -287,7 +286,7 @@ class URICertStore extends CertStoreSpi { } // exception, forget previous values lastModified = 0; - certs = Collections.emptySet(); + certs = Collections.emptySet(); return certs; } @@ -394,7 +393,7 @@ class URICertStore extends CertStoreSpi { // exception, forget previous values lastModified = 0; crl = null; - return Collections.emptyList(); + return Collections.emptyList(); } /** @@ -404,9 +403,9 @@ class URICertStore extends CertStoreSpi { private static Collection getMatchingCRLs (X509CRL crl, CRLSelector selector) { if (selector == null || (crl != null && selector.match(crl))) { - return Collections.singletonList(crl); + return Collections.singletonList(crl); } else { - return Collections.emptyList(); + return Collections.emptyList(); } } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java index 20d05f71be8..3228b7ed62e 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, 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 @@ -79,7 +79,8 @@ public class X509CertificatePair { private X509Certificate reverse; private byte[] encoded; - private static final Cache cache = Cache.newSoftMemoryCache(750); + private static final Cache cache + = Cache.newSoftMemoryCache(750); /** * Creates an empty instance of X509CertificatePair. @@ -114,7 +115,7 @@ public class X509CertificatePair { * * For internal use only, external code should use generateCertificatePair. */ - private X509CertificatePair(byte[] encoded)throws CertificateException { + private X509CertificatePair(byte[] encoded) throws CertificateException { try { parse(new DerValue(encoded)); this.encoded = encoded; @@ -138,7 +139,7 @@ public class X509CertificatePair { public static synchronized X509CertificatePair generateCertificatePair (byte[] encoded) throws CertificateException { Object key = new Cache.EqualByteArray(encoded); - X509CertificatePair pair = (X509CertificatePair)cache.get(key); + X509CertificatePair pair = cache.get(key); if (pair != null) { return pair; } diff --git a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java index 3eea0b25fff..eb20b3f704d 100644 --- a/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java +++ b/jdk/src/share/classes/sun/security/provider/certpath/ldap/LDAPCertStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, 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 @@ -160,7 +160,7 @@ public final class LDAPCertStore extends CertStoreSpi { */ private boolean prefetchCRLs = false; - private final Cache valueCache; + private final Cache valueCache; private int cacheHits = 0; private int cacheMisses = 0; @@ -207,10 +207,11 @@ public final class LDAPCertStore extends CertStoreSpi { * Returns an LDAP CertStore. This method consults a cache of * CertStores (shared per JVM) using the LDAP server/port as a key. */ - private static final Cache certStoreCache = Cache.newSoftMemoryCache(185); + private static final Cache + certStoreCache = Cache.newSoftMemoryCache(185); static synchronized CertStore getInstance(LDAPCertStoreParameters params) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { - CertStore lcs = (CertStore) certStoreCache.get(params); + CertStore lcs = certStoreCache.get(params); if (lcs == null) { lcs = CertStore.getInstance("LDAP", params); certStoreCache.put(params, lcs); @@ -232,7 +233,7 @@ public final class LDAPCertStore extends CertStoreSpi { private void createInitialDirContext(String server, int port) throws InvalidAlgorithmParameterException { String url = "ldap://" + server + ":" + port; - Hashtable env = new Hashtable(); + Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, url); @@ -283,7 +284,7 @@ public final class LDAPCertStore extends CertStoreSpi { LDAPRequest(String name) { this.name = name; - requestedAttributes = new ArrayList(5); + requestedAttributes = new ArrayList<>(5); } String getName() { @@ -311,7 +312,7 @@ public final class LDAPCertStore extends CertStoreSpi { + cacheMisses); } String cacheKey = name + "|" + attrId; - byte[][] values = (byte[][])valueCache.get(cacheKey); + byte[][] values = valueCache.get(cacheKey); if (values != null) { cacheHits++; return values; @@ -347,7 +348,7 @@ public final class LDAPCertStore extends CertStoreSpi { System.out.println("LDAP requests: " + requests); } } - valueMap = new HashMap(8); + valueMap = new HashMap<>(8); String[] attrIds = requestedAttributes.toArray(STRING0); Attributes attrs; try { @@ -429,10 +430,10 @@ public final class LDAPCertStore extends CertStoreSpi { int n = encodedCert.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List certs = new ArrayList(n); + List certs = new ArrayList<>(n); /* decode certs and check if they satisfy selector */ for (int i = 0; i < n; i++) { ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]); @@ -477,11 +478,10 @@ public final class LDAPCertStore extends CertStoreSpi { int n = encodedCertPair.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List certPairs = - new ArrayList(n); + List certPairs = new ArrayList<>(n); /* decode each cert pair and add it to the Collection */ for (int i = 0; i < n; i++) { try { @@ -528,8 +528,7 @@ public final class LDAPCertStore extends CertStoreSpi { getCertPairs(request, CROSS_CERT); // Find Certificates that match and put them in a list - ArrayList matchingCerts = - new ArrayList(); + ArrayList matchingCerts = new ArrayList<>(); for (X509CertificatePair certPair : certPairs) { X509Certificate cert; if (forward != null) { @@ -587,7 +586,7 @@ public final class LDAPCertStore extends CertStoreSpi { int basicConstraints = xsel.getBasicConstraints(); String subject = xsel.getSubjectAsString(); String issuer = xsel.getIssuerAsString(); - HashSet certs = new HashSet(); + HashSet certs = new HashSet<>(); if (debug != null) { debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: " + basicConstraints); @@ -706,10 +705,10 @@ public final class LDAPCertStore extends CertStoreSpi { int n = encodedCRL.length; if (n == 0) { - return Collections.emptySet(); + return Collections.emptySet(); } - List crls = new ArrayList(n); + List crls = new ArrayList<>(n); /* decode each crl and check if it matches selector */ for (int i = 0; i < n; i++) { try { @@ -765,13 +764,13 @@ public final class LDAPCertStore extends CertStoreSpi { throw new CertStoreException("need X509CRLSelector to find CRLs"); } X509CRLSelector xsel = (X509CRLSelector) selector; - HashSet crls = new HashSet(); + HashSet crls = new HashSet<>(); // Look in directory entry for issuer of cert we're checking. Collection issuerNames; X509Certificate certChecking = xsel.getCertificateChecking(); if (certChecking != null) { - issuerNames = new HashSet(); + issuerNames = new HashSet<>(); X500Principal issuer = certChecking.getIssuerX500Principal(); issuerNames.add(issuer.getName(X500Principal.RFC2253)); } else { @@ -796,7 +795,7 @@ public final class LDAPCertStore extends CertStoreSpi { issuerName = (String)nameObject; } // If all we want is CA certs, try to get the (probably shorter) ARL - Collection entryCRLs = Collections.emptySet(); + Collection entryCRLs = Collections.emptySet(); if (certChecking == null || certChecking.getBasicConstraints() != -1) { LDAPRequest request = new LDAPRequest(issuerName); request.addRequestedAttribute(CROSS_CERT); @@ -1028,9 +1027,9 @@ public final class LDAPCertStore extends CertStoreSpi { throws IOException { this.selector = selector == null ? new X509CRLSelector() : selector; this.certIssuers = certIssuers; - issuerNames = new HashSet(); + issuerNames = new HashSet<>(); issuerNames.add(ldapDN); - issuers = new HashSet(); + issuers = new HashSet<>(); issuers.add(new X500Name(ldapDN).asX500Principal()); } // we only override the get (accessor methods) since the set methods diff --git a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java index ce1336bf122..7d0ea3faf97 100644 --- a/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java +++ b/jdk/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2009, 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 @@ -43,11 +43,14 @@ import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import sun.security.util.Cache; +import sun.security.util.Cache.CacheVisitor; final class SSLSessionContextImpl implements SSLSessionContext { - private Cache sessionCache; // session cache, session id as key - private Cache sessionHostPortCache; // session cache, "host:port" as key + private Cache sessionCache; + // session cache, session id as key + private Cache sessionHostPortCache; + // session cache, "host:port" as key private int cacheLimit; // the max cache size private int timeout; // timeout in seconds @@ -71,8 +74,7 @@ final class SSLSessionContextImpl implements SSLSessionContext { throw new NullPointerException("session id cannot be null"); } - SSLSessionImpl sess = - (SSLSessionImpl)sessionCache.get(new SessionId(sessionId)); + SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId)); if (!isTimedout(sess)) { return sess; } @@ -157,8 +159,7 @@ final class SSLSessionContextImpl implements SSLSessionContext { return null; } - SSLSessionImpl sess = - (SSLSessionImpl)sessionHostPortCache.get(getKey(hostname, port)); + SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port)); if (!isTimedout(sess)) { return sess; } @@ -193,7 +194,7 @@ final class SSLSessionContextImpl implements SSLSessionContext { // package-private method, remove a cached SSLSession void remove(SessionId key) { - SSLSessionImpl s = (SSLSessionImpl)sessionCache.get(key); + SSLSessionImpl s = sessionCache.get(key); if (s != null) { sessionCache.remove(key); sessionHostPortCache.remove( @@ -233,17 +234,17 @@ final class SSLSessionContextImpl implements SSLSessionContext { } final class SessionCacheVisitor - implements sun.security.util.Cache.CacheVisitor { + implements Cache.CacheVisitor { Vector ids = null; - // public void visit(java.util.Map map) {} - public void visit(java.util.Map map) { - ids = new Vector(map.size()); + // public void visit(java.util.Map map) {} + public void visit(java.util.Map map) { + ids = new Vector<>(map.size()); - for (Object key : map.keySet()) { - SSLSessionImpl value = (SSLSessionImpl)map.get(key); + for (SessionId key : map.keySet()) { + SSLSessionImpl value = map.get(key); if (!isTimedout(value)) { - ids.addElement(((SessionId)key).getId()); + ids.addElement(key.getId()); } } } diff --git a/jdk/src/share/classes/sun/security/util/Cache.java b/jdk/src/share/classes/sun/security/util/Cache.java index 7c7f072b5de..8037324928a 100644 --- a/jdk/src/share/classes/sun/security/util/Cache.java +++ b/jdk/src/share/classes/sun/security/util/Cache.java @@ -43,7 +43,7 @@ import java.lang.ref.*; * * . optional lifetime, specified in seconds. * - * . save for concurrent use by multiple threads + * . safe for concurrent use by multiple threads * * . values are held by either standard references or via SoftReferences. * SoftReferences have the advantage that they are automatically cleared @@ -69,7 +69,7 @@ import java.lang.ref.*; * * @author Andreas Sterbenz */ -public abstract class Cache { +public abstract class Cache { protected Cache() { // empty @@ -88,12 +88,12 @@ public abstract class Cache { /** * Add an entry to the cache. */ - public abstract void put(Object key, Object value); + public abstract void put(K key, V value); /** * Get a value from the cache. */ - public abstract Object get(Object key); + public abstract V get(Object key); /** * Remove an entry from the cache. @@ -113,14 +113,14 @@ public abstract class Cache { /** * accept a visitor */ - public abstract void accept(CacheVisitor visitor); + public abstract void accept(CacheVisitor visitor); /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by SoftReferences. */ - public static Cache newSoftMemoryCache(int size) { - return new MemoryCache(true, size); + public static Cache newSoftMemoryCache(int size) { + return new MemoryCache<>(true, size); } /** @@ -128,23 +128,24 @@ public abstract class Cache { * specified maximum lifetime (in seconds), with the values held * by SoftReferences. */ - public static Cache newSoftMemoryCache(int size, int timeout) { - return new MemoryCache(true, size, timeout); + public static Cache newSoftMemoryCache(int size, int timeout) { + return new MemoryCache<>(true, size, timeout); } /** * Return a new memory cache with the specified maximum size, unlimited * lifetime for entries, with the values held by standard references. */ - public static Cache newHardMemoryCache(int size) { - return new MemoryCache(false, size); + public static Cache newHardMemoryCache(int size) { + return new MemoryCache<>(false, size); } /** * Return a dummy cache that does nothing. */ - public static Cache newNullCache() { - return NullCache.INSTANCE; + @SuppressWarnings("unchecked") + public static Cache newNullCache() { + return (Cache) NullCache.INSTANCE; } /** @@ -152,8 +153,8 @@ public abstract class Cache { * specified maximum lifetime (in seconds), with the values held * by standard references. */ - public static Cache newHardMemoryCache(int size, int timeout) { - return new MemoryCache(false, size, timeout); + public static Cache newHardMemoryCache(int size, int timeout) { + return new MemoryCache<>(false, size, timeout); } /** @@ -193,15 +194,15 @@ public abstract class Cache { } } - public interface CacheVisitor { - public void visit(Map map); + public interface CacheVisitor { + public void visit(Map map); } } -class NullCache extends Cache { +class NullCache extends Cache { - final static Cache INSTANCE = new NullCache(); + final static Cache INSTANCE = new NullCache<>(); private NullCache() { // empty @@ -215,11 +216,11 @@ class NullCache extends Cache { // empty } - public void put(Object key, Object value) { + public void put(K key, V value) { // empty } - public Object get(Object key) { + public V get(Object key) { return null; } @@ -235,23 +236,26 @@ class NullCache extends Cache { // empty } - public void accept(CacheVisitor visitor) { + public void accept(CacheVisitor visitor) { // empty } } -class MemoryCache extends Cache { +class MemoryCache extends Cache { private final static float LOAD_FACTOR = 0.75f; // XXXX private final static boolean DEBUG = false; - private final Map cacheMap; + private final Map> cacheMap; private int maxSize; private long lifetime; - private final ReferenceQueue queue; + + // ReferenceQueue is of type V instead of Cache + // to allow SoftCacheEntry to extend SoftReference + private final ReferenceQueue queue; public MemoryCache(boolean soft, int maxSize) { this(soft, maxSize, 0); @@ -260,10 +264,13 @@ class MemoryCache extends Cache { public MemoryCache(boolean soft, int maxSize, int lifetime) { this.maxSize = maxSize; this.lifetime = lifetime * 1000; - this.queue = soft ? new ReferenceQueue() : null; + if (soft) + this.queue = new ReferenceQueue<>(); + else + this.queue = null; + int buckets = (int)(maxSize / LOAD_FACTOR) + 1; - cacheMap = new LinkedHashMap(buckets, - LOAD_FACTOR, true); + cacheMap = new LinkedHashMap<>(buckets, LOAD_FACTOR, true); } /** @@ -279,16 +286,17 @@ class MemoryCache extends Cache { } int startSize = cacheMap.size(); while (true) { - CacheEntry entry = (CacheEntry)queue.poll(); + @SuppressWarnings("unchecked") + CacheEntry entry = (CacheEntry)queue.poll(); if (entry == null) { break; } - Object key = entry.getKey(); + K key = entry.getKey(); if (key == null) { // key is null, entry has already been removed continue; } - CacheEntry currentEntry = cacheMap.remove(key); + CacheEntry currentEntry = cacheMap.remove(key); // check if the entry in the map corresponds to the expired // entry. If not, readd the entry if ((currentEntry != null) && (entry != currentEntry)) { @@ -314,9 +322,9 @@ class MemoryCache extends Cache { } int cnt = 0; long time = System.currentTimeMillis(); - for (Iterator t = cacheMap.values().iterator(); + for (Iterator> t = cacheMap.values().iterator(); t.hasNext(); ) { - CacheEntry entry = t.next(); + CacheEntry entry = t.next(); if (entry.isValid(time) == false) { t.remove(); cnt++; @@ -339,7 +347,7 @@ class MemoryCache extends Cache { if (queue != null) { // if this is a SoftReference cache, first invalidate() all // entries so that GC does not have to enqueue them - for (CacheEntry entry : cacheMap.values()) { + for (CacheEntry entry : cacheMap.values()) { entry.invalidate(); } while (queue.poll() != null) { @@ -349,12 +357,12 @@ class MemoryCache extends Cache { cacheMap.clear(); } - public synchronized void put(Object key, Object value) { + public synchronized void put(K key, V value) { emptyQueue(); long expirationTime = (lifetime == 0) ? 0 : System.currentTimeMillis() + lifetime; - CacheEntry newEntry = newEntry(key, value, expirationTime, queue); - CacheEntry oldEntry = cacheMap.put(key, newEntry); + CacheEntry newEntry = newEntry(key, value, expirationTime, queue); + CacheEntry oldEntry = cacheMap.put(key, newEntry); if (oldEntry != null) { oldEntry.invalidate(); return; @@ -362,8 +370,8 @@ class MemoryCache extends Cache { if (maxSize > 0 && cacheMap.size() > maxSize) { expungeExpiredEntries(); if (cacheMap.size() > maxSize) { // still too large? - Iterator t = cacheMap.values().iterator(); - CacheEntry lruEntry = t.next(); + Iterator> t = cacheMap.values().iterator(); + CacheEntry lruEntry = t.next(); if (DEBUG) { System.out.println("** Overflow removal " + lruEntry.getKey() + " | " + lruEntry.getValue()); @@ -374,9 +382,9 @@ class MemoryCache extends Cache { } } - public synchronized Object get(Object key) { + public synchronized V get(Object key) { emptyQueue(); - CacheEntry entry = cacheMap.get(key); + CacheEntry entry = cacheMap.get(key); if (entry == null) { return null; } @@ -393,7 +401,7 @@ class MemoryCache extends Cache { public synchronized void remove(Object key) { emptyQueue(); - CacheEntry entry = cacheMap.remove(key); + CacheEntry entry = cacheMap.remove(key); if (entry != null) { entry.invalidate(); } @@ -402,9 +410,9 @@ class MemoryCache extends Cache { public synchronized void setCapacity(int size) { expungeExpiredEntries(); if (size > 0 && cacheMap.size() > size) { - Iterator t = cacheMap.values().iterator(); + Iterator> t = cacheMap.values().iterator(); for (int i = cacheMap.size() - size; i > 0; i--) { - CacheEntry lruEntry = t.next(); + CacheEntry lruEntry = t.next(); if (DEBUG) { System.out.println("** capacity reset removal " + lruEntry.getKey() + " | " + lruEntry.getValue()); @@ -431,60 +439,61 @@ class MemoryCache extends Cache { } // it is a heavyweight method. - public synchronized void accept(CacheVisitor visitor) { + public synchronized void accept(CacheVisitor visitor) { expungeExpiredEntries(); - Map cached = getCachedEntries(); + Map cached = getCachedEntries(); visitor.visit(cached); } - private Map getCachedEntries() { - Map kvmap = new HashMap(cacheMap.size()); + private Map getCachedEntries() { + Map kvmap = new HashMap<>(cacheMap.size()); - for (CacheEntry entry : cacheMap.values()) { + for (CacheEntry entry : cacheMap.values()) { kvmap.put(entry.getKey(), entry.getValue()); } return kvmap; } - protected CacheEntry newEntry(Object key, Object value, - long expirationTime, ReferenceQueue queue) { + protected CacheEntry newEntry(K key, V value, + long expirationTime, ReferenceQueue queue) { if (queue != null) { - return new SoftCacheEntry(key, value, expirationTime, queue); + return new SoftCacheEntry<>(key, value, expirationTime, queue); } else { - return new HardCacheEntry(key, value, expirationTime); + return new HardCacheEntry<>(key, value, expirationTime); } } - private static interface CacheEntry { + private static interface CacheEntry { boolean isValid(long currentTime); void invalidate(); - Object getKey(); + K getKey(); - Object getValue(); + V getValue(); } - private static class HardCacheEntry implements CacheEntry { + private static class HardCacheEntry implements CacheEntry { - private Object key, value; + private K key; + private V value; private long expirationTime; - HardCacheEntry(Object key, Object value, long expirationTime) { + HardCacheEntry(K key, V value, long expirationTime) { this.key = key; this.value = value; this.expirationTime = expirationTime; } - public Object getKey() { + public K getKey() { return key; } - public Object getValue() { + public V getValue() { return value; } @@ -503,24 +512,25 @@ class MemoryCache extends Cache { } } - private static class SoftCacheEntry - extends SoftReference implements CacheEntry { + private static class SoftCacheEntry + extends SoftReference + implements CacheEntry { - private Object key; + private K key; private long expirationTime; - SoftCacheEntry(Object key, Object value, long expirationTime, - ReferenceQueue queue) { + SoftCacheEntry(K key, V value, long expirationTime, + ReferenceQueue queue) { super(value, queue); this.key = key; this.expirationTime = expirationTime; } - public Object getKey() { + public K getKey() { return key; } - public Object getValue() { + public V getValue() { return get(); } From d25a9c128ff99b8eb95b0fd3b1eed2d13b594b8a Mon Sep 17 00:00:00 2001 From: Bradford Wetmore Date: Tue, 18 Oct 2011 11:58:57 -0700 Subject: [PATCH 05/41] 7031830: bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine Reviewed-by: xuelei, weijun, asaha --- .../classes/sun/security/ssl/CipherBox.java | 13 +- .../SSLEngineBadBufferArrayAccess.java | 479 ++++++++++++++++++ 2 files changed, 487 insertions(+), 5 deletions(-) create mode 100644 jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java diff --git a/jdk/src/share/classes/sun/security/ssl/CipherBox.java b/jdk/src/share/classes/sun/security/ssl/CipherBox.java index 91f9f36198d..16f0643a7c5 100644 --- a/jdk/src/share/classes/sun/security/ssl/CipherBox.java +++ b/jdk/src/share/classes/sun/security/ssl/CipherBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 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 @@ -305,9 +305,11 @@ final class CipherBox { byte[] buf = null; int limit = bb.limit(); if (bb.hasArray()) { + int arrayOffset = bb.arrayOffset(); buf = bb.array(); - System.arraycopy(buf, pos, - buf, pos + prefix.length, limit - pos); + System.arraycopy(buf, arrayOffset + pos, + buf, arrayOffset + pos + prefix.length, + limit - pos); bb.limit(limit + prefix.length); } else { buf = new byte[limit - pos]; @@ -491,9 +493,10 @@ final class CipherBox { byte[] buf = null; int limit = bb.limit(); if (bb.hasArray()) { + int arrayOffset = bb.arrayOffset(); buf = bb.array(); - System.arraycopy(buf, pos + blockSize, - buf, pos, limit - pos - blockSize); + System.arraycopy(buf, arrayOffset + pos + blockSize, + buf, arrayOffset + pos, limit - pos - blockSize); bb.limit(limit - blockSize); } else { buf = new byte[limit - pos - blockSize]; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java new file mode 100644 index 00000000000..f9cd5185b33 --- /dev/null +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/SSLEngineBadBufferArrayAccess.java @@ -0,0 +1,479 @@ +/* + * 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 7031830 + * @summary bad_record_mac failure on TLSv1.2 enabled connection with SSLEngine + * @run main/othervm SSLEngineBadBufferArrayAccess + * + * SunJSSE does not support dynamic system properties, no way to re-use + * system properties in samevm/agentvm mode. + */ + +/** + * A SSLSocket/SSLEngine interop test case. This is not the way to + * code SSLEngine-based servers, but works for what we need to do here, + * which is to make sure that SSLEngine/SSLSockets can talk to each other. + * SSLEngines can use direct or indirect buffers, and different code + * is used to get at the buffer contents internally, so we test that here. + * + * The test creates one SSLSocket (client) and one SSLEngine (server). + * The SSLSocket talks to a raw ServerSocket, and the server code + * does the translation between byte [] and ByteBuffers that the SSLEngine + * can use. The "transport" layer consists of a Socket Input/OutputStream + * and two byte buffers for the SSLEngines: think of them + * as directly connected pipes. + * + * Again, this is a *very* simple example: real code will be much more + * involved. For example, different threading and I/O models could be + * used, transport mechanisms could close unexpectedly, and so on. + * + * When this application runs, notice that several messages + * (wrap/unwrap) pass before any application data is consumed or + * produced. (For more information, please see the SSL/TLS + * specifications.) There may several steps for a successful handshake, + * so it's typical to see the following series of operations: + * + * client server message + * ====== ====== ======= + * write() ... ClientHello + * ... unwrap() ClientHello + * ... wrap() ServerHello/Certificate + * read() ... ServerHello/Certificate + * write() ... ClientKeyExchange + * write() ... ChangeCipherSpec + * write() ... Finished + * ... unwrap() ClientKeyExchange + * ... unwrap() ChangeCipherSpec + * ... unwrap() Finished + * ... wrap() ChangeCipherSpec + * ... wrap() Finished + * read() ... ChangeCipherSpec + * read() ... Finished + * + * This particular bug had a problem where byte buffers backed by an + * array didn't offset correctly, and we got bad MAC errors. + */ +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.net.*; +import java.security.*; +import java.nio.*; + +public class SSLEngineBadBufferArrayAccess { + + /* + * Enables logging of the SSL/TLS operations. + */ + private static boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static boolean debug = false; + private SSLContext sslc; + private SSLEngine serverEngine; // server-side SSLEngine + private SSLSocket sslSocket; // client-side socket + private ServerSocket serverSocket; // server-side Socket, generates the... + private Socket socket; // server-side socket that will read + + private final byte[] serverMsg = "Hi there Client, I'm a Server".getBytes(); + private final byte[] clientMsg = "Hello Server, I'm a Client".getBytes(); + + private ByteBuffer serverOut; // write side of serverEngine + private ByteBuffer serverIn; // read side of serverEngine + + private volatile Exception clientException; + private volatile Exception serverException; + + /* + * For data transport, this example uses local ByteBuffers. + */ + private ByteBuffer cTOs; // "reliable" transport client->server + private ByteBuffer sTOc; // "reliable" transport server->client + + /* + * The following is to set up the keystores/trust material. + */ + private static final String pathToStores = "../../../../../../../etc/"; + private static final String keyStoreFile = "keystore"; + private static final String trustStoreFile = "truststore"; + private static final String passwd = "passphrase"; + private static String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + private static String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + String [] protocols = new String [] { + "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }; + + for (String protocol : protocols) { + log("Testing " + protocol); + /* + * Run the tests with direct and indirect buffers. + */ + SSLEngineBadBufferArrayAccess test = + new SSLEngineBadBufferArrayAccess(protocol); + test.runTest(true); + test.runTest(false); + } + + System.out.println("Test Passed."); + } + + /* + * Create an initialized SSLContext to use for these tests. + */ + public SSLEngineBadBufferArrayAccess(String protocol) throws Exception { + + KeyStore ks = KeyStore.getInstance("JKS"); + KeyStore ts = KeyStore.getInstance("JKS"); + + char[] passphrase = "passphrase".toCharArray(); + + ks.load(new FileInputStream(keyFilename), passphrase); + ts.load(new FileInputStream(trustFilename), passphrase); + + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ts); + + SSLContext sslCtx = SSLContext.getInstance(protocol); + + sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + + sslc = sslCtx; + } + + /* + * Run the test. + * + * Sit in a tight loop, with the server engine calling wrap/unwrap + * regardless of whether data is available or not. We do this until + * we get the application data. Then we shutdown and go to the next one. + * + * The main loop handles all of the I/O phases of the SSLEngine's + * lifetime: + * + * initial handshaking + * application data transfer + * engine closing + * + * One could easily separate these phases into separate + * sections of code. + */ + private void runTest(boolean direct) throws Exception { + boolean serverClose = direct; + + serverSocket = new ServerSocket(0); + int port = serverSocket.getLocalPort(); + Thread thread = createClientThread(port, serverClose); + + socket = serverSocket.accept(); + socket.setSoTimeout(500); + serverSocket.close(); + + createSSLEngine(); + createBuffers(direct); + + try { + boolean closed = false; + + InputStream is = socket.getInputStream(); + OutputStream os = socket.getOutputStream(); + + SSLEngineResult serverResult; // results from last operation + + /* + * Examining the SSLEngineResults could be much more involved, + * and may alter the overall flow of the application. + * + * For example, if we received a BUFFER_OVERFLOW when trying + * to write to the output pipe, we could reallocate a larger + * pipe, but instead we wait for the peer to drain it. + */ + byte[] inbound = new byte[8192]; + byte[] outbound = new byte[8192]; + + while (!isEngineClosed(serverEngine)) { + int len = 0; + + // Inbound data + log("================"); + + // Read from the Client side. + try { + len = is.read(inbound); + if (len == -1) { + throw new Exception("Unexpected EOF"); + } + cTOs.put(inbound, 0, len); + } catch (SocketTimeoutException ste) { + // swallow. Nothing yet, probably waiting on us. + } + + cTOs.flip(); + + serverResult = serverEngine.unwrap(cTOs, serverIn); + log("server unwrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + cTOs.compact(); + + // Outbound data + log("----"); + + serverResult = serverEngine.wrap(serverOut, sTOc); + log("server wrap: ", serverResult); + runDelegatedTasks(serverResult, serverEngine); + + sTOc.flip(); + + if ((len = sTOc.remaining()) != 0) { + sTOc.get(outbound, 0, len); + os.write(outbound, 0, len); + // Give the other side a chance to process + } + + sTOc.compact(); + + if (!closed && (serverOut.remaining() == 0)) { + closed = true; + + /* + * We'll alternate initiatating the shutdown. + * When the server initiates, it will take one more + * loop, but tests the orderly shutdown. + */ + if (serverClose) { + serverEngine.closeOutbound(); + } + serverIn.flip(); + + /* + * A sanity check to ensure we got what was sent. + */ + if (serverIn.remaining() != clientMsg.length) { + throw new Exception("Client: Data length error"); + } + + for (int i = 0; i < clientMsg.length; i++) { + if (clientMsg[i] != serverIn.get()) { + throw new Exception("Client: Data content error"); + } + } + serverIn.compact(); + } + } + return; + } catch (Exception e) { + serverException = e; + } finally { + socket.close(); + + // Wait for the client to join up with us. + thread.join(); + if (serverException != null) { + throw serverException; + } + if (clientException != null) { + throw clientException; + } + } + } + + /* + * Create a client thread which does simple SSLSocket operations. + * We'll write and read one data packet. + */ + private Thread createClientThread(final int port, + final boolean serverClose) throws Exception { + + Thread t = new Thread("ClientThread") { + + @Override + public void run() { + try { + Thread.sleep(1000); // Give server time to finish setup. + + sslSocket = (SSLSocket) sslc.getSocketFactory(). + createSocket("localhost", port); + OutputStream os = sslSocket.getOutputStream(); + InputStream is = sslSocket.getInputStream(); + + // write(byte[]) goes in one shot. + os.write(clientMsg); + + byte[] inbound = new byte[2048]; + int pos = 0; + + int len; +done: + while ((len = is.read(inbound, pos, 2048 - pos)) != -1) { + pos += len; + // Let the client do the closing. + if ((pos == serverMsg.length) && !serverClose) { + sslSocket.close(); + break done; + } + } + + if (pos != serverMsg.length) { + throw new Exception("Client: Data length error"); + } + + for (int i = 0; i < serverMsg.length; i++) { + if (inbound[i] != serverMsg[i]) { + throw new Exception("Client: Data content error"); + } + } + } catch (Exception e) { + clientException = e; + } + } + }; + t.start(); + return t; + } + + /* + * Using the SSLContext created during object creation, + * create/configure the SSLEngines we'll use for this test. + */ + private void createSSLEngine() throws Exception { + /* + * Configure the serverEngine to act as a server in the SSL/TLS + * handshake. + */ + serverEngine = sslc.createSSLEngine(); + serverEngine.setUseClientMode(false); + serverEngine.getNeedClientAuth(); + } + + /* + * Create and size the buffers appropriately. + */ + private void createBuffers(boolean direct) { + + SSLSession session = serverEngine.getSession(); + int appBufferMax = session.getApplicationBufferSize(); + int netBufferMax = session.getPacketBufferSize(); + + /* + * We'll make the input buffers a bit bigger than the max needed + * size, so that unwrap()s following a successful data transfer + * won't generate BUFFER_OVERFLOWS. + * + * We'll use a mix of direct and indirect ByteBuffers for + * tutorial purposes only. In reality, only use direct + * ByteBuffers when they give a clear performance enhancement. + */ + if (direct) { + serverIn = ByteBuffer.allocateDirect(appBufferMax + 50); + cTOs = ByteBuffer.allocateDirect(netBufferMax); + sTOc = ByteBuffer.allocateDirect(netBufferMax); + } else { + serverIn = ByteBuffer.allocate(appBufferMax + 50); + cTOs = ByteBuffer.allocate(netBufferMax); + sTOc = ByteBuffer.allocate(netBufferMax); + } + + serverOut = ByteBuffer.wrap(serverMsg); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static boolean isEngineClosed(SSLEngine engine) { + return (engine.isOutboundDone() && engine.isInboundDone()); + } + + /* + * Logging code + */ + private static boolean resultOnce = true; + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + if (resultOnce) { + resultOnce = false; + System.out.println("The format of the SSLEngineResult is: \n" + + "\t\"getStatus() / getHandshakeStatus()\" +\n" + + "\t\"bytesConsumed() / bytesProduced()\"\n"); + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } +} From f1f3aad11cfda1a45383fc0964d55f9b1da572d9 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 19 Oct 2011 10:15:23 -0400 Subject: [PATCH 06/41] 7102686: Restructure timestamp code so that jars and modules can more easily share the same code Reviewed-by: mchung --- .../classes/sun/security/pkcs/PKCS7.java | 186 +++++++++++++ .../classes/sun/security/pkcs/SignerInfo.java | 63 ++++- .../security/timestamp/HttpTimestamper.java | 51 ++-- .../sun/security/timestamp/TSRequest.java | 57 ++-- .../sun/security/timestamp/TSResponse.java | 113 ++++---- .../classes/sun/security/tools/JarSigner.java | 7 +- .../sun/security/tools/TimestampedSigner.java | 244 ++---------------- .../classes/sun/security/util/Debug.java | 3 +- .../security/util/SignatureFileVerifier.java | 59 +---- 9 files changed, 378 insertions(+), 405 deletions(-) diff --git a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java index 4cdf35dba0e..a3198784729 100644 --- a/jdk/src/share/classes/sun/security/pkcs/PKCS7.java +++ b/jdk/src/share/classes/sun/security/pkcs/PKCS7.java @@ -27,6 +27,7 @@ package sun.security.pkcs; import java.io.*; import java.math.BigInteger; +import java.net.URI; import java.util.*; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; @@ -35,6 +36,7 @@ import java.security.cert.CRLException; import java.security.cert.CertificateFactory; import java.security.*; +import sun.security.timestamp.*; import sun.security.util.*; import sun.security.x509.AlgorithmId; import sun.security.x509.CertificateIssuerName; @@ -68,6 +70,30 @@ public class PKCS7 { private Principal[] certIssuerNames; + /* + * Random number generator for creating nonce values + */ + private static final SecureRandom RANDOM; + static { + SecureRandom tmp = null; + try { + tmp = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + // should not happen + } + RANDOM = tmp; + } + + /* + * Object identifier for the timestamping key purpose. + */ + private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8"; + + /* + * Object identifier for extendedKeyUsage extension + */ + private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37"; + /** * Unmarshals a PKCS7 block from its encoded form, parsing the * encoded bytes from the InputStream. @@ -733,4 +759,164 @@ public class PKCS7 { public boolean isOldStyle() { return this.oldStyle; } + + /** + * Assembles a PKCS #7 signed data message that optionally includes a + * signature timestamp. + * + * @param signature the signature bytes + * @param signerChain the signer's X.509 certificate chain + * @param content the content that is signed; specify null to not include + * it in the PKCS7 data + * @param signatureAlgorithm the name of the signature algorithm + * @param tsaURI the URI of the Timestamping Authority; or null if no + * timestamp is requested + * @return the bytes of the encoded PKCS #7 signed data message + * @throws NoSuchAlgorithmException The exception is thrown if the signature + * algorithm is unrecognised. + * @throws CertificateException The exception is thrown if an error occurs + * while processing the signer's certificate or the TSA's + * certificate. + * @throws IOException The exception is thrown if an error occurs while + * generating the signature timestamp or while generating the signed + * data message. + */ + public static byte[] generateSignedData(byte[] signature, + X509Certificate[] signerChain, + byte[] content, + String signatureAlgorithm, + URI tsaURI) + throws CertificateException, IOException, NoSuchAlgorithmException + { + + // Generate the timestamp token + PKCS9Attributes unauthAttrs = null; + if (tsaURI != null) { + // Timestamp the signature + HttpTimestamper tsa = new HttpTimestamper(tsaURI); + byte[] tsToken = generateTimestampToken(tsa, signature); + + // Insert the timestamp token into the PKCS #7 signer info element + // (as an unsigned attribute) + unauthAttrs = + new PKCS9Attributes(new PKCS9Attribute[]{ + new PKCS9Attribute( + PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR, + tsToken)}); + } + + // Create the SignerInfo + X500Name issuerName = + X500Name.asX500Name(signerChain[0].getIssuerX500Principal()); + BigInteger serialNumber = signerChain[0].getSerialNumber(); + String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm); + String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm); + SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber, + AlgorithmId.get(digAlg), null, + AlgorithmId.get(encAlg), + signature, unauthAttrs); + + // Create the PKCS #7 signed data message + SignerInfo[] signerInfos = {signerInfo}; + AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()}; + // Include or exclude content + ContentInfo contentInfo = (content == null) + ? new ContentInfo(ContentInfo.DATA_OID, null) + : new ContentInfo(content); + PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo, + signerChain, signerInfos); + ByteArrayOutputStream p7out = new ByteArrayOutputStream(); + pkcs7.encodeSignedData(p7out); + + return p7out.toByteArray(); + } + + /** + * Requests, processes and validates a timestamp token from a TSA using + * common defaults. Uses the following defaults in the timestamp request: + * SHA-1 for the hash algorithm, a 64-bit nonce, and request certificate + * set to true. + * + * @param tsa the timestamping authority to use + * @param toBeTimestamped the token that is to be timestamped + * @return the encoded timestamp token + * @throws IOException The exception is thrown if an error occurs while + * communicating with the TSA. + * @throws CertificateException The exception is thrown if the TSA's + * certificate is not permitted for timestamping. + */ + private static byte[] generateTimestampToken(Timestamper tsa, + byte[] toBeTimestamped) + throws IOException, CertificateException + { + // Generate a timestamp + MessageDigest messageDigest = null; + TSRequest tsQuery = null; + try { + // SHA-1 is always used. + messageDigest = MessageDigest.getInstance("SHA-1"); + tsQuery = new TSRequest(toBeTimestamped, messageDigest); + } catch (NoSuchAlgorithmException e) { + // ignore + } + + // Generate a nonce + BigInteger nonce = null; + if (RANDOM != null) { + nonce = new BigInteger(64, RANDOM); + tsQuery.setNonce(nonce); + } + tsQuery.requestCertificate(true); + + TSResponse tsReply = tsa.generateTimestamp(tsQuery); + int status = tsReply.getStatusCode(); + // Handle TSP error + if (status != 0 && status != 1) { + throw new IOException("Error generating timestamp: " + + tsReply.getStatusCodeAsText() + " " + + tsReply.getFailureCodeAsText()); + } + PKCS7 tsToken = tsReply.getToken(); + + TimestampToken tst = tsReply.getTimestampToken(); + if (!tst.getHashAlgorithm().getName().equals("SHA")) { + throw new IOException("Digest algorithm not SHA-1 in " + + "timestamp token"); + } + if (!MessageDigest.isEqual(tst.getHashedMessage(), + tsQuery.getHashedMessage())) { + throw new IOException("Digest octets changed in timestamp token"); + } + + BigInteger replyNonce = tst.getNonce(); + if (replyNonce == null && nonce != null) { + throw new IOException("Nonce missing in timestamp token"); + } + if (replyNonce != null && !replyNonce.equals(nonce)) { + throw new IOException("Nonce changed in timestamp token"); + } + + // Examine the TSA's certificate (if present) + for (SignerInfo si: tsToken.getSignerInfos()) { + X509Certificate cert = si.getCertificate(tsToken); + if (cert == null) { + // Error, we've already set tsRequestCertificate = true + throw new CertificateException( + "Certificate not included in timestamp token"); + } else { + if (!cert.getCriticalExtensionOIDs().contains( + EXTENDED_KEY_USAGE_OID)) { + throw new CertificateException( + "Certificate is not valid for timestamping"); + } + List keyPurposes = cert.getExtendedKeyUsage(); + if (keyPurposes == null || + !keyPurposes.contains(KP_TIMESTAMPING_OID)) { + throw new CertificateException( + "Certificate is not valid for timestamping"); + } + } + } + return tsReply.getEncodedToken(); + } } diff --git a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java index c04b05ffdec..1d327706d78 100644 --- a/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java +++ b/jdk/src/share/classes/sun/security/pkcs/SignerInfo.java @@ -28,10 +28,14 @@ package sun.security.pkcs; import java.io.OutputStream; import java.io.IOException; import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.CertPath; import java.security.cert.X509Certificate; import java.security.*; import java.util.ArrayList; +import sun.security.timestamp.TimestampToken; import sun.security.util.*; import sun.security.x509.AlgorithmId; import sun.security.x509.X500Name; @@ -51,6 +55,8 @@ public class SignerInfo implements DerEncoder { AlgorithmId digestAlgorithmId; AlgorithmId digestEncryptionAlgorithmId; byte[] encryptedDigest; + Timestamp timestamp; + private boolean hasTimestamp = true; PKCS9Attributes authenticatedAttributes; PKCS9Attributes unauthenticatedAttributes; @@ -442,6 +448,62 @@ public class SignerInfo implements DerEncoder { return unauthenticatedAttributes; } + /* + * Extracts a timestamp from a PKCS7 SignerInfo. + * + * Examines the signer's unsigned attributes for a + * signatureTimestampToken attribute. If present, + * then it is parsed to extract the date and time at which the + * timestamp was generated. + * + * @param info A signer information element of a PKCS 7 block. + * + * @return A timestamp token or null if none is present. + * @throws IOException if an error is encountered while parsing the + * PKCS7 data. + * @throws NoSuchAlgorithmException if an error is encountered while + * verifying the PKCS7 object. + * @throws SignatureException if an error is encountered while + * verifying the PKCS7 object. + * @throws CertificateException if an error is encountered while generating + * the TSA's certpath. + */ + public Timestamp getTimestamp() + throws IOException, NoSuchAlgorithmException, SignatureException, + CertificateException + { + if (timestamp != null || !hasTimestamp) + return timestamp; + + if (unauthenticatedAttributes == null) { + hasTimestamp = false; + return null; + } + PKCS9Attribute tsTokenAttr = + unauthenticatedAttributes.getAttribute( + PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID); + if (tsTokenAttr == null) { + hasTimestamp = false; + return null; + } + + PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue()); + // Extract the content (an encoded timestamp token info) + byte[] encTsTokenInfo = tsToken.getContentInfo().getData(); + // Extract the signer (the Timestamping Authority) + // while verifying the content + SignerInfo[] tsa = tsToken.verify(encTsTokenInfo); + // Expect only one signer + ArrayList chain = tsa[0].getCertificateChain(tsToken); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + CertPath tsaChain = cf.generateCertPath(chain); + // Create a timestamp token info object + TimestampToken tsTokenInfo = new TimestampToken(encTsTokenInfo); + // Create a timestamp object + timestamp = new Timestamp(tsTokenInfo.getDate(), tsaChain); + return timestamp; + } + public String toString() { HexDumpEncoder hexDump = new HexDumpEncoder(); @@ -467,5 +529,4 @@ public class SignerInfo implements DerEncoder { } return out; } - } diff --git a/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java b/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java index 54958f726c8..a4a1921bb29 100644 --- a/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java +++ b/jdk/src/share/classes/sun/security/timestamp/HttpTimestamper.java @@ -28,13 +28,13 @@ package sun.security.timestamp; import java.io.BufferedInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.net.URI; import java.net.URL; import java.net.HttpURLConnection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import sun.misc.IOUtils; +import sun.security.util.Debug; /** * A timestamper that communicates with a Timestamping Authority (TSA) @@ -58,20 +58,23 @@ public class HttpTimestamper implements Timestamper { private static final String TS_REPLY_MIME_TYPE = "application/timestamp-reply"; - private static final boolean DEBUG = false; + private static final Debug debug = Debug.getInstance("ts"); /* - * HTTP URL identifying the location of the TSA + * HTTP URI identifying the location of the TSA */ - private String tsaUrl = null; + private URI tsaURI = null; /** * Creates a timestamper that connects to the specified TSA. * - * @param tsa The location of the TSA. It must be an HTTP URL. + * @param tsa The location of the TSA. It must be an HTTP URI. + * @throws IllegalArgumentException if tsaURI is not an HTTP URI */ - public HttpTimestamper(String tsaUrl) { - this.tsaUrl = tsaUrl; + public HttpTimestamper(URI tsaURI) { + if (!tsaURI.getScheme().equalsIgnoreCase("http")) + throw new IllegalArgumentException("TSA must be an HTTP URI"); + this.tsaURI = tsaURI; } /** @@ -85,7 +88,7 @@ public class HttpTimestamper implements Timestamper { public TSResponse generateTimestamp(TSRequest tsQuery) throws IOException { HttpURLConnection connection = - (HttpURLConnection) new URL(tsaUrl).openConnection(); + (HttpURLConnection) tsaURI.toURL().openConnection(); connection.setDoOutput(true); connection.setUseCaches(false); // ignore cache connection.setRequestProperty("Content-Type", TS_QUERY_MIME_TYPE); @@ -93,15 +96,15 @@ public class HttpTimestamper implements Timestamper { // Avoids the "hang" when a proxy is required but none has been set. connection.setConnectTimeout(CONNECT_TIMEOUT); - if (DEBUG) { + if (debug != null) { Set>> headers = - connection.getRequestProperties().entrySet(); - System.out.println(connection.getRequestMethod() + " " + tsaUrl + + connection.getRequestProperties().entrySet(); + debug.println(connection.getRequestMethod() + " " + tsaURI + " HTTP/1.1"); - for (Map.Entry> entry : headers) { - System.out.println(" " + entry); + for (Map.Entry> e : headers) { + debug.println(" " + e); } - System.out.println(); + debug.println(); } connection.connect(); // No HTTP authentication is performed @@ -112,8 +115,8 @@ public class HttpTimestamper implements Timestamper { byte[] request = tsQuery.encode(); output.write(request, 0, request.length); output.flush(); - if (DEBUG) { - System.out.println("sent timestamp query (length=" + + if (debug != null) { + debug.println("sent timestamp query (length=" + request.length + ")"); } } finally { @@ -127,17 +130,17 @@ public class HttpTimestamper implements Timestamper { byte[] replyBuffer = null; try { input = new BufferedInputStream(connection.getInputStream()); - if (DEBUG) { + if (debug != null) { String header = connection.getHeaderField(0); - System.out.println(header); + debug.println(header); int i = 1; while ((header = connection.getHeaderField(i)) != null) { String key = connection.getHeaderFieldKey(i); - System.out.println(" " + ((key==null) ? "" : key + ": ") + + debug.println(" " + ((key==null) ? "" : key + ": ") + header); i++; } - System.out.println(); + debug.println(); } verifyMimeType(connection.getContentType()); @@ -145,8 +148,8 @@ public class HttpTimestamper implements Timestamper { int contentLength = connection.getContentLength(); replyBuffer = IOUtils.readFully(input, contentLength, false); - if (DEBUG) { - System.out.println("received timestamp response (length=" + + if (debug != null) { + debug.println("received timestamp response (length=" + total + ")"); } } finally { diff --git a/jdk/src/share/classes/sun/security/timestamp/TSRequest.java b/jdk/src/share/classes/sun/security/timestamp/TSRequest.java index 241811f5333..9b322192cca 100644 --- a/jdk/src/share/classes/sun/security/timestamp/TSRequest.java +++ b/jdk/src/share/classes/sun/security/timestamp/TSRequest.java @@ -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 @@ -27,10 +27,13 @@ package sun.security.timestamp; import java.io.IOException; import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.cert.X509Extension; import sun.security.util.DerValue; import sun.security.util.DerOutputStream; import sun.security.util.ObjectIdentifier; +import sun.security.x509.AlgorithmId; /** * This class provides a timestamp request, as defined in @@ -64,24 +67,9 @@ import sun.security.util.ObjectIdentifier; public class TSRequest { - private static final ObjectIdentifier SHA1_OID; - private static final ObjectIdentifier MD5_OID; - static { - ObjectIdentifier sha1 = null; - ObjectIdentifier md5 = null; - try { - sha1 = new ObjectIdentifier("1.3.14.3.2.26"); - md5 = new ObjectIdentifier("1.2.840.113549.2.5"); - } catch (IOException ioe) { - // should not happen - } - SHA1_OID = sha1; - MD5_OID = md5; - } - private int version = 1; - private ObjectIdentifier hashAlgorithmId = null; + private AlgorithmId hashAlgorithmId = null; private byte[] hashValue; @@ -94,30 +82,21 @@ public class TSRequest { private X509Extension[] extensions = null; /** - * Constructs a timestamp request for the supplied hash value.. + * Constructs a timestamp request for the supplied data. * - * @param hashValue The hash value. This is the data to be timestamped. - * @param hashAlgorithm The name of the hash algorithm. + * @param toBeTimeStamped The data to be timestamped. + * @param messageDigest The MessageDigest of the hash algorithm to use. + * @throws NoSuchAlgorithmException if the hash algorithm is not supported */ - public TSRequest(byte[] hashValue, String hashAlgorithm) { + public TSRequest(byte[] toBeTimeStamped, MessageDigest messageDigest) + throws NoSuchAlgorithmException { - // Check the common hash algorithms - if ("MD5".equalsIgnoreCase(hashAlgorithm)) { - hashAlgorithmId = MD5_OID; - // Check that the hash value matches the hash algorithm - assert hashValue.length == 16; + this.hashAlgorithmId = AlgorithmId.get(messageDigest.getAlgorithm()); + this.hashValue = messageDigest.digest(toBeTimeStamped); + } - } else if ("SHA-1".equalsIgnoreCase(hashAlgorithm) || - "SHA".equalsIgnoreCase(hashAlgorithm) || - "SHA1".equalsIgnoreCase(hashAlgorithm)) { - hashAlgorithmId = SHA1_OID; - // Check that the hash value matches the hash algorithm - assert hashValue.length == 20; - - } - // Clone the hash value - this.hashValue = new byte[hashValue.length]; - System.arraycopy(hashValue, 0, this.hashValue, 0, hashValue.length); + public byte[] getHashedMessage() { + return hashValue.clone(); } /** @@ -176,9 +155,7 @@ public class TSRequest { // encode messageImprint DerOutputStream messageImprint = new DerOutputStream(); - DerOutputStream hashAlgorithm = new DerOutputStream(); - hashAlgorithm.putOID(hashAlgorithmId); - messageImprint.write(DerValue.tag_Sequence, hashAlgorithm); + hashAlgorithmId.encode(messageImprint); messageImprint.putOctetString(hashValue); request.write(DerValue.tag_Sequence, messageImprint); diff --git a/jdk/src/share/classes/sun/security/timestamp/TSResponse.java b/jdk/src/share/classes/sun/security/timestamp/TSResponse.java index afb8084fed7..0cf223d492a 100644 --- a/jdk/src/share/classes/sun/security/timestamp/TSResponse.java +++ b/jdk/src/share/classes/sun/security/timestamp/TSResponse.java @@ -27,6 +27,7 @@ package sun.security.timestamp; import java.io.IOException; import sun.security.pkcs.PKCS7; +import sun.security.util.Debug; import sun.security.util.DerValue; /** @@ -175,18 +176,20 @@ public class TSResponse { */ public static final int SYSTEM_FAILURE = 25; - private static final boolean DEBUG = false; + private static final Debug debug = Debug.getInstance("ts"); private int status; private String[] statusString = null; - private int failureInfo = -1; + private boolean[] failureInfo = null; private byte[] encodedTsToken = null; private PKCS7 tsToken = null; + private TimestampToken tstInfo; + /** * Constructs an object to store the response to a timestamp request. * @@ -215,11 +218,11 @@ public class TSResponse { } /** - * Retrieve the failure code returned by the TSA. + * Retrieve the failure info returned by the TSA. * - * @return If -1 then no failure code was received. + * @return the failure info, or null if no failure code was received. */ - public int getFailureCode() { + public boolean[] getFailureInfo() { return failureInfo; } @@ -250,42 +253,38 @@ public class TSResponse { } } + private boolean isSet(int position) { + return failureInfo[position]; + } + public String getFailureCodeAsText() { - if (failureInfo == -1) { - return null; + if (failureInfo == null) { + return ""; } - switch (failureInfo) { + try { + if (isSet(BAD_ALG)) + return "Unrecognized or unsupported algorithm identifier."; + if (isSet(BAD_REQUEST)) + return "The requested transaction is not permitted or " + + "supported."; + if (isSet(BAD_DATA_FORMAT)) + return "The data submitted has the wrong format."; + if (isSet(TIME_NOT_AVAILABLE)) + return "The TSA's time source is not available."; + if (isSet(UNACCEPTED_POLICY)) + return "The requested TSA policy is not supported by the TSA."; + if (isSet(UNACCEPTED_EXTENSION)) + return "The requested extension is not supported by the TSA."; + if (isSet(ADD_INFO_NOT_AVAILABLE)) + return "The additional information requested could not be " + + "understood or is not available."; + if (isSet(SYSTEM_FAILURE)) + return "The request cannot be handled due to system failure."; + } catch (ArrayIndexOutOfBoundsException ex) {} - case BAD_ALG: - return "Unrecognized or unsupported alrorithm identifier."; - - case BAD_REQUEST: - return "The requested transaction is not permitted or supported."; - - case BAD_DATA_FORMAT: - return "The data submitted has the wrong format."; - - case TIME_NOT_AVAILABLE: - return "The TSA's time source is not available."; - - case UNACCEPTED_POLICY: - return "The requested TSA policy is not supported by the TSA."; - - case UNACCEPTED_EXTENSION: - return "The requested extension is not supported by the TSA."; - - case ADD_INFO_NOT_AVAILABLE: - return "The additional information requested could not be " + - "understood or is not available."; - - case SYSTEM_FAILURE: - return "The request cannot be handled due to system failure."; - - default: - return ("unknown status code " + status); - } + return ("unknown failure code"); } /** @@ -297,6 +296,10 @@ public class TSResponse { return tsToken; } + public TimestampToken getTimestampToken() { + return tstInfo; + } + /** * Retrieve the ASN.1 BER encoded timestamp token returned by the TSA. * @@ -323,29 +326,30 @@ public class TSResponse { // Parse status - DerValue status = derValue.data.getDerValue(); - // Parse status - this.status = status.data.getInteger(); - if (DEBUG) { - System.out.println("timestamp response: status=" + this.status); + DerValue statusInfo = derValue.data.getDerValue(); + this.status = statusInfo.data.getInteger(); + if (debug != null) { + debug.println("timestamp response: status=" + this.status); } // Parse statusString, if present - if (status.data.available() > 0) { - DerValue[] strings = status.data.getSequence(1); - statusString = new String[strings.length]; - for (int i = 0; i < strings.length; i++) { - statusString[i] = strings[i].data.getUTF8String(); + if (statusInfo.data.available() > 0) { + byte tag = (byte)statusInfo.data.peekByte(); + if (tag == DerValue.tag_SequenceOf) { + DerValue[] strings = statusInfo.data.getSequence(1); + statusString = new String[strings.length]; + for (int i = 0; i < strings.length; i++) { + statusString[i] = strings[i].getUTF8String(); + if (debug != null) { + debug.println("timestamp response: statusString=" + + statusString[i]); + } + } } } // Parse failInfo, if present - if (status.data.available() > 0) { - byte[] failInfo = status.data.getBitString(); - int failureInfo = (new Byte(failInfo[0])).intValue(); - if (failureInfo < 0 || failureInfo > 25 || failInfo.length != 1) { - throw new IOException("Bad encoding for timestamp response: " + - "unrecognized value for the failInfo element"); - } - this.failureInfo = failureInfo; + if (statusInfo.data.available() > 0) { + this.failureInfo + = statusInfo.data.getUnalignedBitString().toBooleanArray(); } // Parse timeStampToken, if present @@ -353,6 +357,7 @@ public class TSResponse { DerValue timestampToken = derValue.data.getDerValue(); encodedTsToken = timestampToken.toByteArray(); tsToken = new PKCS7(encodedTsToken); + tstInfo = new TimestampToken(tsToken.getContentInfo().getData()); } // Check the format of the timestamp response diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index ac2ffde9e58..fe3944f4b29 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -1277,11 +1277,10 @@ public class JarSigner { System.out.println(rb.getString("TSA.location.") + tsaUrl); } if (tsaCert != null) { - String certUrl = - TimestampedSigner.getTimestampingUrl(tsaCert); - if (certUrl != null) { + URI tsaURI = TimestampedSigner.getTimestampingURI(tsaCert); + if (tsaURI != null) { System.out.println(rb.getString("TSA.location.") + - certUrl); + tsaURI); } System.out.println(rb.getString("TSA.certificate.") + printCert("", tsaCert, false, 0, false)); diff --git a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java index 94a6a8b158c..4848a40dcbc 100644 --- a/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java +++ b/jdk/src/share/classes/sun/security/tools/TimestampedSigner.java @@ -25,22 +25,14 @@ package sun.security.tools; -import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.math.BigInteger; import java.net.URI; -import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.security.Principal; -import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; -import java.util.List; import com.sun.jarsigner.*; -import java.util.Arrays; -import sun.security.pkcs.*; -import sun.security.timestamp.*; +import sun.security.pkcs.PKCS7; import sun.security.util.*; import sun.security.x509.*; @@ -56,36 +48,12 @@ import sun.security.x509.*; public final class TimestampedSigner extends ContentSigner { - /* - * Random number generator for creating nonce values - */ - private static final SecureRandom RANDOM; - static { - SecureRandom tmp = null; - try { - tmp = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - // should not happen - } - RANDOM = tmp; - } - /* * Object identifier for the subject information access X.509 certificate * extension. */ private static final String SUBJECT_INFO_ACCESS_OID = "1.3.6.1.5.5.7.1.11"; - /* - * Object identifier for the timestamping key purpose. - */ - private static final String KP_TIMESTAMPING_OID = "1.3.6.1.5.5.7.3.8"; - - /* - * Object identifier for extendedKeyUsage extension - */ - private static final String EXTENDED_KEY_USAGE_OID = "2.5.29.37"; - /* * Object identifier for the timestamping access descriptors. */ @@ -100,26 +68,6 @@ public final class TimestampedSigner extends ContentSigner { AD_TIMESTAMPING_Id = tmp; } - /* - * Location of the TSA. - */ - private String tsaUrl = null; - - /* - * TSA's X.509 certificate. - */ - private X509Certificate tsaCertificate = null; - - /* - * Generates an SHA-1 hash value for the data to be timestamped. - */ - private MessageDigest messageDigest = null; - - /* - * Parameters for the timestamping protocol. - */ - private boolean tsRequestCertificate = true; - /** * Instantiates a content signer that supports timestamped signatures. */ @@ -134,7 +82,7 @@ public final class TimestampedSigner extends ContentSigner { * and optionally the content that was signed, are packaged into a PKCS #7 * signed data message. * - * @param parameters The non-null input parameters. + * @param params The non-null input parameters. * @param omitContent true if the content should be omitted from the * signed data message. Otherwise the content is included. * @param applyTimestamp true if the signature should be timestamped. @@ -151,98 +99,41 @@ public final class TimestampedSigner extends ContentSigner { * @throws NullPointerException The exception is thrown if parameters is * null. */ - public byte[] generateSignedData(ContentSignerParameters parameters, + public byte[] generateSignedData(ContentSignerParameters params, boolean omitContent, boolean applyTimestamp) throws NoSuchAlgorithmException, CertificateException, IOException { - if (parameters == null) { + if (params == null) { throw new NullPointerException(); } - // Parse the signature algorithm to extract the digest and key - // algorithms. The expected format is: + // Parse the signature algorithm to extract the digest + // algorithm. The expected format is: // "with" // or "withand" - String signatureAlgorithm = parameters.getSignatureAlgorithm(); - String keyAlgorithm = - AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm); - String digestAlgorithm = - AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm); - AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm); + String signatureAlgorithm = params.getSignatureAlgorithm(); - // Examine signer's certificate - X509Certificate[] signerCertificateChain = - parameters.getSignerCertificateChain(); - Principal issuerName = signerCertificateChain[0].getIssuerDN(); - if (!(issuerName instanceof X500Name)) { - // must extract the original encoded form of DN for subsequent - // name comparison checks (converting to a String and back to - // an encoded DN could cause the types of String attribute - // values to be changed) - X509CertInfo tbsCert = new - X509CertInfo(signerCertificateChain[0].getTBSCertificate()); - issuerName = (Principal) - tbsCert.get(CertificateIssuerName.NAME + "." + - CertificateIssuerName.DN_NAME); - } - BigInteger serialNumber = signerCertificateChain[0].getSerialNumber(); + X509Certificate[] signerChain = params.getSignerCertificateChain(); + byte[] signature = params.getSignature(); // Include or exclude content - byte[] content = parameters.getContent(); - ContentInfo contentInfo; - if (omitContent) { - contentInfo = new ContentInfo(ContentInfo.DATA_OID, null); - } else { - contentInfo = new ContentInfo(content); - } + byte[] content = (omitContent == true) ? null : params.getContent(); - // Generate the timestamp token - byte[] signature = parameters.getSignature(); - SignerInfo signerInfo = null; + URI tsaURI = null; if (applyTimestamp) { - - tsaCertificate = parameters.getTimestampingAuthorityCertificate(); - URI tsaUri = parameters.getTimestampingAuthority(); - if (tsaUri != null) { - tsaUrl = tsaUri.toString(); - } else { + tsaURI = params.getTimestampingAuthority(); + if (tsaURI == null) { // Examine TSA cert - String certUrl = getTimestampingUrl(tsaCertificate); - if (certUrl == null) { + tsaURI = getTimestampingURI( + params.getTimestampingAuthorityCertificate()); + if (tsaURI == null) { throw new CertificateException( "Subject Information Access extension not found"); } - tsaUrl = certUrl; } - - // Timestamp the signature - byte[] tsToken = generateTimestampToken(signature); - - // Insert the timestamp token into the PKCS #7 signer info element - // (as an unsigned attribute) - PKCS9Attributes unsignedAttrs = - new PKCS9Attributes(new PKCS9Attribute[]{ - new PKCS9Attribute( - PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR, - tsToken)}); - signerInfo = new SignerInfo((X500Name)issuerName, serialNumber, - digestAlgorithmId, null, AlgorithmId.get(keyAlgorithm), - signature, unsignedAttrs); - } else { - signerInfo = new SignerInfo((X500Name)issuerName, serialNumber, - digestAlgorithmId, AlgorithmId.get(keyAlgorithm), signature); } - - SignerInfo[] signerInfos = {signerInfo}; - AlgorithmId[] algorithms = {digestAlgorithmId}; - - // Create the PKCS #7 signed data message - PKCS7 p7 = new PKCS7(algorithms, contentInfo, signerCertificateChain, - null, signerInfos); - ByteArrayOutputStream p7out = new ByteArrayOutputStream(); - p7.encodeSignedData(p7out); - - return p7out.toByteArray(); + return PKCS7.generateSignedData(signature, signerChain, content, + params.getSignatureAlgorithm(), tsaURI); } /** @@ -253,9 +144,9 @@ public final class TimestampedSigner extends ContentSigner { * accessLocation field should contain an HTTP or HTTPS URL. * * @param tsaCertificate An X.509 certificate for the TSA. - * @return An HTTP or HTTPS URL or null if none was found. + * @return An HTTP or HTTPS URI or null if none was found. */ - public static String getTimestampingUrl(X509Certificate tsaCertificate) { + public static URI getTimestampingURI(X509Certificate tsaCertificate) { if (tsaCertificate == null) { return null; @@ -282,7 +173,7 @@ public final class TimestampedSigner extends ContentSigner { uri = (URIName) location.getName(); if (uri.getScheme().equalsIgnoreCase("http") || uri.getScheme().equalsIgnoreCase("https")) { - return uri.getName(); + return uri.getURI(); } } } @@ -292,97 +183,4 @@ public final class TimestampedSigner extends ContentSigner { } return null; } - - /* - * Returns a timestamp token from a TSA for the given content. - * Performs a basic check on the token to confirm that it has been signed - * by a certificate that is permitted to sign timestamps. - * - * @param toBeTimestamped The data to be timestamped. - * @throws IOException The exception is throw if an error occurs while - * communicating with the TSA. - * @throws CertificateException The exception is throw if the TSA's - * certificate is not permitted for timestamping. - */ - private byte[] generateTimestampToken(byte[] toBeTimestamped) - throws CertificateException, IOException { - - // Generate hash value for the data to be timestamped - // SHA-1 is always used. - if (messageDigest == null) { - try { - messageDigest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - // ignore - } - } - byte[] digest = messageDigest.digest(toBeTimestamped); - - // Generate a timestamp - TSRequest tsQuery = new TSRequest(digest, "SHA-1"); - // Generate a nonce - BigInteger nonce = null; - if (RANDOM != null) { - nonce = new BigInteger(64, RANDOM); - tsQuery.setNonce(nonce); - } - tsQuery.requestCertificate(tsRequestCertificate); - - Timestamper tsa = new HttpTimestamper(tsaUrl); // use supplied TSA - TSResponse tsReply = tsa.generateTimestamp(tsQuery); - int status = tsReply.getStatusCode(); - // Handle TSP error - if (status != 0 && status != 1) { - int failureCode = tsReply.getFailureCode(); - if (failureCode == -1) { - throw new IOException("Error generating timestamp: " + - tsReply.getStatusCodeAsText()); - } else { - throw new IOException("Error generating timestamp: " + - tsReply.getStatusCodeAsText() + " " + - tsReply.getFailureCodeAsText()); - } - } - PKCS7 tsToken = tsReply.getToken(); - - TimestampToken tst = new TimestampToken(tsToken.getContentInfo().getData()); - if (!tst.getHashAlgorithm().equals( - new AlgorithmId(new ObjectIdentifier("1.3.14.3.2.26")))) { - throw new IOException("Digest algorithm not SHA-1 in timestamp token"); - } - if (!Arrays.equals(tst.getHashedMessage(), digest)) { - throw new IOException("Digest octets changed in timestamp token"); - } - - BigInteger replyNonce = tst.getNonce(); - if (replyNonce == null && nonce != null) { - throw new IOException("Nonce missing in timestamp token"); - } - if (replyNonce != null && !replyNonce.equals(nonce)) { - throw new IOException("Nonce changed in timestamp token"); - } - - // Examine the TSA's certificate (if present) - for (SignerInfo si: tsToken.getSignerInfos()) { - X509Certificate cert = si.getCertificate(tsToken); - if (cert == null) { - // Error, we've already set tsRequestCertificate = true - throw new CertificateException( - "Certificate not included in timestamp token"); - } else { - if (!cert.getCriticalExtensionOIDs().contains( - EXTENDED_KEY_USAGE_OID)) { - throw new CertificateException( - "Certificate is not valid for timestamping"); - } - List keyPurposes = cert.getExtendedKeyUsage(); - if (keyPurposes == null || - ! keyPurposes.contains(KP_TIMESTAMPING_OID)) { - throw new CertificateException( - "Certificate is not valid for timestamping"); - } - } - } - return tsReply.getEncodedToken(); - } } diff --git a/jdk/src/share/classes/sun/security/util/Debug.java b/jdk/src/share/classes/sun/security/util/Debug.java index 5701a80cf9f..3356cf856e1 100644 --- a/jdk/src/share/classes/sun/security/util/Debug.java +++ b/jdk/src/share/classes/sun/security/util/Debug.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -80,6 +80,7 @@ public class Debug { System.err.println("policy loading and granting"); System.err.println("provider security provider debugging"); System.err.println("scl permissions SecureClassLoader assigns"); + System.err.println("ts timestamping"); System.err.println(); System.err.println("The following can be used with access:"); System.err.println(); diff --git a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java index 1c818f8945b..715a5da356b 100644 --- a/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java +++ b/jdk/src/share/classes/sun/security/util/SignatureFileVerifier.java @@ -35,7 +35,6 @@ import java.util.*; import java.util.jar.*; import sun.security.pkcs.*; -import sun.security.timestamp.TimestampToken; import sun.misc.BASE64Decoder; import sun.security.jca.Providers; @@ -485,7 +484,7 @@ public class SignatureFileVerifier { signers = new ArrayList(); } // Append the new code signer - signers.add(new CodeSigner(certChain, getTimestamp(info))); + signers.add(new CodeSigner(certChain, info.getTimestamp())); if (debug != null) { debug.println("Signature Block Certificate: " + @@ -500,62 +499,6 @@ public class SignatureFileVerifier { } } - /* - * Examines a signature timestamp token to generate a timestamp object. - * - * Examines the signer's unsigned attributes for a - * signatureTimestampToken attribute. If present, - * then it is parsed to extract the date and time at which the - * timestamp was generated. - * - * @param info A signer information element of a PKCS 7 block. - * - * @return A timestamp token or null if none is present. - * @throws IOException if an error is encountered while parsing the - * PKCS7 data. - * @throws NoSuchAlgorithmException if an error is encountered while - * verifying the PKCS7 object. - * @throws SignatureException if an error is encountered while - * verifying the PKCS7 object. - * @throws CertificateException if an error is encountered while generating - * the TSA's certpath. - */ - private Timestamp getTimestamp(SignerInfo info) - throws IOException, NoSuchAlgorithmException, SignatureException, - CertificateException { - - Timestamp timestamp = null; - - // Extract the signer's unsigned attributes - PKCS9Attributes unsignedAttrs = info.getUnauthenticatedAttributes(); - if (unsignedAttrs != null) { - PKCS9Attribute timestampTokenAttr = - unsignedAttrs.getAttribute("signatureTimestampToken"); - if (timestampTokenAttr != null) { - PKCS7 timestampToken = - new PKCS7((byte[])timestampTokenAttr.getValue()); - // Extract the content (an encoded timestamp token info) - byte[] encodedTimestampTokenInfo = - timestampToken.getContentInfo().getData(); - // Extract the signer (the Timestamping Authority) - // while verifying the content - SignerInfo[] tsa = - timestampToken.verify(encodedTimestampTokenInfo); - // Expect only one signer - ArrayList chain = - tsa[0].getCertificateChain(timestampToken); - CertPath tsaChain = certificateFactory.generateCertPath(chain); - // Create a timestamp token info object - TimestampToken timestampTokenInfo = - new TimestampToken(encodedTimestampTokenInfo); - // Create a timestamp object - timestamp = - new Timestamp(timestampTokenInfo.getDate(), tsaChain); - } - } - return timestamp; - } - // for the toHex function private static final char[] hexc = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; From 8d1c6cf60ee55c119f3a9c956d9b4fb257daa718 Mon Sep 17 00:00:00 2001 From: Darryl Mocek Date: Wed, 19 Oct 2011 14:17:47 -0700 Subject: [PATCH 07/41] 5029031: Add Collections.checkedQueue() Reviewed-by: mduigou --- .../share/classes/java/util/Collections.java | 58 ++++++ .../java/util/Collections/CheckedQueue.java | 190 ++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 jdk/test/java/util/Collections/CheckedQueue.java diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java index d15a4292ddd..e55eb59296e 100644 --- a/jdk/src/share/classes/java/util/Collections.java +++ b/jdk/src/share/classes/java/util/Collections.java @@ -2351,6 +2351,64 @@ public class Collections { } } + /** + * Returns a dynamically typesafe view of the specified queue. + * Any attempt to insert an element of the wrong type will result in + * an immediate {@link ClassCastException}. Assuming a queue contains + * no incorrectly typed elements prior to the time a dynamically typesafe + * view is generated, and that all subsequent access to the queue + * takes place through the view, it is guaranteed that the + * queue cannot contain an incorrectly typed element. + * + *

A discussion of the use of dynamically typesafe views may be + * found in the documentation for the {@link #checkedCollection + * checkedCollection} method. + * + *

The returned queue will be serializable if the specified queue + * is serializable. + * + *

Since {@code null} is considered to be a value of any reference + * type, the returned queue permits insertion of {@code null} elements + * whenever the backing queue does. + * + * @param queue the queue for which a dynamically typesafe view is to be + * returned + * @param type the type of element that {@code queue} is permitted to hold + * @return a dynamically typesafe view of the specified queue + * @since 1.8 + */ + public static Queue checkedQueue(Queue queue, Class type) { + return new CheckedQueue<>(queue, type); + } + + /** + * @serial include + */ + static class CheckedQueue + extends CheckedCollection + implements Queue, Serializable + { + private static final long serialVersionUID = 1433151992604707767L; + final Queue queue; + + CheckedQueue(Queue queue, Class elementType) { + super(queue, elementType); + this.queue = queue; + } + + public E element() {return queue.element();} + public boolean equals(Object o) {return o == this || c.equals(o);} + public int hashCode() {return c.hashCode();} + public E peek() {return queue.peek();} + public E poll() {return queue.poll();} + public E remove() {return queue.remove();} + + public boolean offer(E e) { + typeCheck(e); + return add(e); + } + } + /** * Returns a dynamically typesafe view of the specified set. * Any attempt to insert an element of the wrong type will result in diff --git a/jdk/test/java/util/Collections/CheckedQueue.java b/jdk/test/java/util/Collections/CheckedQueue.java new file mode 100644 index 00000000000..6f28e12e9ef --- /dev/null +++ b/jdk/test/java/util/Collections/CheckedQueue.java @@ -0,0 +1,190 @@ +/* + * 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 5020931 + * @summary Unit test for Collections.checkedQueue + */ + +import java.lang.reflect.Method; +import java.util.Collections; +import java.util.Iterator; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +public class CheckedQueue { + static int status = 0; + + public static void main(String[] args) throws Exception { + new CheckedQueue(); + } + + public CheckedQueue() throws Exception { + run(); + } + + private void run() throws Exception { + Method[] methods = this.getClass().getDeclaredMethods(); + + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + String methodName = method.getName(); + + if (methodName.startsWith("test")) { + try { + Object obj = method.invoke(this, new Object[0]); + } catch(Exception e) { + throw new Exception(this.getClass().getName() + "." + + methodName + " test failed, test exception " + + "follows\n" + e.getCause()); + } + } + } + } + + /** + * This test adds items to a queue. + */ + private void test00() { + int arrayLength = 10; + ArrayBlockingQueue abq = new ArrayBlockingQueue(arrayLength); + + for (int i = 0; i < arrayLength; i++) { + abq.add(new String(Integer.toString(i))); + } + } + + /** + * This test tests the CheckedQueue.add method. It creates a queue of + * {@code String}s gets the checked queue, and attempt to add an Integer to + * the checked queue. + */ + private void test01() throws Exception { + int arrayLength = 10; + ArrayBlockingQueue abq = new ArrayBlockingQueue(arrayLength + 1); + + for (int i = 0; i < arrayLength; i++) { + abq.add(new String(Integer.toString(i))); + } + + Queue q = Collections.checkedQueue(abq, String.class); + + try { + q.add(new Integer(0)); + throw new Exception(this.getClass().getName() + "." + "test01 test" + + " failed, should throw ClassCastException."); + } catch(ClassCastException cce) { + // Do nothing. + } + } + + /** + * This test tests the CheckedQueue.add method. It creates a queue of one + * {@code String}, gets the checked queue, and attempt to add an Integer to + * the checked queue. + */ + private void test02() throws Exception { + ArrayBlockingQueue abq = new ArrayBlockingQueue(1); + Queue q = Collections.checkedQueue(abq, String.class); + + try { + q.add(new Integer(0)); + throw new Exception(this.getClass().getName() + "." + "test02 test" + + " failed, should throw ClassCastException."); + } catch(ClassCastException e) { + // Do nothing. + } + } + + /** + * This test tests the Collections.checkedQueue method call for nulls in + * each and both of the parameters. + */ + private void test03() throws Exception { + ArrayBlockingQueue abq = new ArrayBlockingQueue(1); + Queue q; + + try { + q = Collections.checkedQueue(null, String.class); + throw new Exception(this.getClass().getName() + "." + "test03 test" + + " failed, should throw NullPointerException."); + } catch(NullPointerException npe) { + // Do nothing + } + + try { + q = Collections.checkedQueue(abq, null); + throw new Exception(this.getClass().getName() + "." + "test03 test" + + " failed, should throw NullPointerException."); + } catch(Exception e) { + // Do nothing + } + + try { + q = Collections.checkedQueue(null, null); + throw new Exception(this.getClass().getName() + "." + "test03 test" + + " failed, should throw NullPointerException."); + } catch(Exception e) { + // Do nothing + } + } + + /** + * This test tests the CheckedQueue.offer method. + */ + private void test04() throws Exception { + ArrayBlockingQueue abq = new ArrayBlockingQueue(1); + Queue q = Collections.checkedQueue(abq, String.class); + + try { + q.offer(null); + throw new Exception(this.getClass().getName() + "." + "test04 test" + + " failed, should throw NullPointerException."); + } catch (NullPointerException npe) { + // Do nothing + } + + try { + q.offer(new Integer(0)); + throw new Exception(this.getClass().getName() + "." + "test04 test" + + " failed, should throw ClassCastException."); + } catch (ClassCastException cce) { + // Do nothing + } + + q.offer(new String("0")); + + try { + q.offer(new String("1")); + throw new Exception(this.getClass().getName() + "." + "test04 test" + + " failed, should throw IllegalStateException."); + } catch(IllegalStateException ise) { + // Do nothing + } + } + + private void test05() { + + } +} From ed977156e59a5867f00cdbda0174a41fa792d3fe Mon Sep 17 00:00:00 2001 From: Kurchi Subhra Hazra Date: Thu, 20 Oct 2011 09:08:38 +0100 Subject: [PATCH 08/41] 7102704: test/java/net/DatagramSocket/ChangingAddress.java failing Reviewed-by: chegar --- .../net/DatagramSocket/ChangingAddress.java | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 jdk/test/java/net/DatagramSocket/ChangingAddress.java diff --git a/jdk/test/java/net/DatagramSocket/ChangingAddress.java b/jdk/test/java/net/DatagramSocket/ChangingAddress.java deleted file mode 100644 index 42cc78b00a9..00000000000 --- a/jdk/test/java/net/DatagramSocket/ChangingAddress.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 7084030 - * @summary Tests that DatagramSocket.getLocalAddress returns the right local - * address after connect/disconnect. - */ -import java.net.*; - -public class ChangingAddress { - - static void check(DatagramSocket ds, InetAddress expected) { - InetAddress actual = ds.getLocalAddress(); - if (!expected.equals(actual)) { - throw new RuntimeException("Expected:"+expected+" Actual"+ - actual); - } - } - - public static void main(String[] args) throws Exception { - InetAddress lh = InetAddress.getLocalHost(); - SocketAddress remote = new InetSocketAddress(lh, 1234); - InetAddress wildcard = InetAddress.getByAddress - ("localhost", new byte[]{0,0,0,0}); - try (DatagramSocket ds = new DatagramSocket()) { - check(ds, wildcard); - - ds.connect(remote); - check(ds, lh); - - ds.disconnect(); - check(ds, wildcard); - } - } -} From 0ec5b82c857e34c17df7310ec8b6d6e3ac957fb6 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Thu, 20 Oct 2011 09:21:03 +0100 Subject: [PATCH 09/41] 7102665: Move tests to Problemlist Reviewed-by: chegar, alanb --- jdk/test/ProblemList.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 6097bcf7b97..9f91b1879b2 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -377,6 +377,12 @@ java/net/ipv6tests/UdpTest.java linux-all # 7081476 java/net/InetSocketAddress/B6469803.java generic-all +# 7102670 +java/net/InetAddress/CheckJNI.java linux-all + +# failing on vista 32/64 on nightly +# 7102702 +java/net/PortUnreachableException/OneExceptionOnly.java windows-all ############################################################################ # jdk_io From 448e208ddb4f6e991df3c003e294aa0eeff6d08d Mon Sep 17 00:00:00 2001 From: Charles Lee Date: Thu, 13 Oct 2011 12:30:51 +0100 Subject: [PATCH 10/41] 7100054: (porting) Native code should include fcntl.h and unistd.h rather than sys/fcntl.h and sys/unistd.h Use POSIX defined includes for unistd.h and fcntl.h Reviewed-by: dholmes, alanb, chegar, ngmr --- jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c | 2 +- jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c b/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c index df463986093..346bfbbe542 100644 --- a/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c +++ b/jdk/src/solaris/native/sun/nio/fs/genSolarisConstants.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include /** diff --git a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c index ea48d4d07d8..56984a7e352 100644 --- a/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c +++ b/jdk/src/solaris/native/sun/nio/fs/genUnixConstants.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include /** From 1a335eb0477f953f65cad1e8747c3e682b59d779 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 17 Oct 2011 12:54:33 +0100 Subject: [PATCH 11/41] 7097436: Project Coin: duplicate varargs warnings on method annotated with @SafeVarargs Duplicate aliasing check during subtyping leads to spurious varargs diagnostic Reviewed-by: jjg --- .../com/sun/tools/javac/code/Types.java | 107 ++++---- .../tools/javac/varargs/7097436/T7097436.java | 18 ++ .../tools/javac/varargs/7097436/T7097436.out | 6 + .../tools/javac/varargs/warning/Warn5.java | 244 ++++++++++-------- 4 files changed, 215 insertions(+), 160 deletions(-) create mode 100644 langtools/test/tools/javac/varargs/7097436/T7097436.java create mode 100644 langtools/test/tools/javac/varargs/7097436/T7097436.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 55dc74d659a..5fc9d4547ed 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -278,7 +278,6 @@ public class Types { boolean tPrimitive = t.isPrimitive(); boolean sPrimitive = s.isPrimitive(); if (tPrimitive == sPrimitive) { - checkUnsafeVarargsConversion(t, s, warn); return isSubtypeUnchecked(t, s, warn); } if (!allowBoxing) return false; @@ -286,27 +285,6 @@ public class Types { ? isSubtype(boxedClass(t).type, s) : isSubtype(unboxedType(t), s); } - //where - private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { - if (t.tag != ARRAY || isReifiable(t)) return; - ArrayType from = (ArrayType)t; - boolean shouldWarn = false; - switch (s.tag) { - case ARRAY: - ArrayType to = (ArrayType)s; - shouldWarn = from.isVarargs() && - !to.isVarargs() && - !isReifiable(from); - break; - case CLASS: - shouldWarn = from.isVarargs() && - isSubtype(from, s); - break; - } - if (shouldWarn) { - warn.warn(LintCategory.VARARGS); - } - } /** * Is t a subtype of or convertiable via boxing/unboxing @@ -328,42 +306,63 @@ public class Types { * Is t an unchecked subtype of s? */ public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) { - if (t.tag == ARRAY && s.tag == ARRAY) { - if (((ArrayType)t).elemtype.tag <= lastBaseTag) { - return isSameType(elemtype(t), elemtype(s)); - } else { - ArrayType from = (ArrayType)t; - ArrayType to = (ArrayType)s; - if (from.isVarargs() && - !to.isVarargs() && - !isReifiable(from)) { - warn.warn(LintCategory.VARARGS); + boolean result = isSubtypeUncheckedInternal(t, s, warn); + if (result) { + checkUnsafeVarargsConversion(t, s, warn); + } + return result; + } + //where + private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) { + if (t.tag == ARRAY && s.tag == ARRAY) { + if (((ArrayType)t).elemtype.tag <= lastBaseTag) { + return isSameType(elemtype(t), elemtype(s)); + } else { + return isSubtypeUnchecked(elemtype(t), elemtype(s), warn); } - return isSubtypeUnchecked(elemtype(t), elemtype(s), warn); - } - } else if (isSubtype(t, s)) { - return true; - } - else if (t.tag == TYPEVAR) { - return isSubtypeUnchecked(t.getUpperBound(), s, warn); - } - else if (s.tag == UNDETVAR) { - UndetVar uv = (UndetVar)s; - if (uv.inst != null) - return isSubtypeUnchecked(t, uv.inst, warn); - } - else if (!s.isRaw()) { - Type t2 = asSuper(t, s.tsym); - if (t2 != null && t2.isRaw()) { - if (isReifiable(s)) - warn.silentWarn(LintCategory.UNCHECKED); - else - warn.warn(LintCategory.UNCHECKED); + } else if (isSubtype(t, s)) { return true; } + else if (t.tag == TYPEVAR) { + return isSubtypeUnchecked(t.getUpperBound(), s, warn); + } + else if (s.tag == UNDETVAR) { + UndetVar uv = (UndetVar)s; + if (uv.inst != null) + return isSubtypeUnchecked(t, uv.inst, warn); + } + else if (!s.isRaw()) { + Type t2 = asSuper(t, s.tsym); + if (t2 != null && t2.isRaw()) { + if (isReifiable(s)) + warn.silentWarn(LintCategory.UNCHECKED); + else + warn.warn(LintCategory.UNCHECKED); + return true; + } + } + return false; + } + + private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) { + if (t.tag != ARRAY || isReifiable(t)) return; + ArrayType from = (ArrayType)t; + boolean shouldWarn = false; + switch (s.tag) { + case ARRAY: + ArrayType to = (ArrayType)s; + shouldWarn = from.isVarargs() && + !to.isVarargs() && + !isReifiable(from); + break; + case CLASS: + shouldWarn = from.isVarargs(); + break; + } + if (shouldWarn) { + warn.warn(LintCategory.VARARGS); + } } - return false; - } /** * Is t a subtype of s?
diff --git a/langtools/test/tools/javac/varargs/7097436/T7097436.java b/langtools/test/tools/javac/varargs/7097436/T7097436.java new file mode 100644 index 00000000000..cf64baa48dd --- /dev/null +++ b/langtools/test/tools/javac/varargs/7097436/T7097436.java @@ -0,0 +1,18 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7097436 + * @summary ClassCastException occurs in assignment expressions without any heap pollutions + * @compile/fail/ref=T7097436.out -Xlint:varargs -Werror -XDrawDiagnostics T7097436.java + */ + +import java.util.List; + +class T7097436 { + @SafeVarargs + static void m(List... ls) { + Object o = ls; //warning + Object[] oArr = ls; //warning + String s = ls; // no warning + Integer[] iArr = ls; // no warning + } +} diff --git a/langtools/test/tools/javac/varargs/7097436/T7097436.out b/langtools/test/tools/javac/varargs/7097436/T7097436.out new file mode 100644 index 00000000000..6428cdfa497 --- /dev/null +++ b/langtools/test/tools/javac/varargs/7097436/T7097436.out @@ -0,0 +1,6 @@ +T7097436.java:13:20: compiler.warn.varargs.unsafe.use.varargs.param: ls +T7097436.java:14:25: compiler.warn.varargs.unsafe.use.varargs.param: ls +T7097436.java:15:20: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List[], java.lang.String +T7097436.java:16:26: compiler.err.prob.found.req: (compiler.misc.incompatible.types), java.util.List[], java.lang.Integer[] +2 errors +2 warnings diff --git a/langtools/test/tools/javac/varargs/warning/Warn5.java b/langtools/test/tools/javac/varargs/warning/Warn5.java index be7618f760a..966cefa78a8 100644 --- a/langtools/test/tools/javac/varargs/warning/Warn5.java +++ b/langtools/test/tools/javac/varargs/warning/Warn5.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6993978 + * @bug 6993978 7097436 * @summary Project Coin: Annotation to reduce varargs warnings * @author mcimadamore * @run main Warn5 @@ -31,8 +31,8 @@ import com.sun.source.util.JavacTask; import com.sun.tools.javac.api.JavacTool; import java.net.URI; -import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import javax.tools.Diagnostic; import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; @@ -95,7 +95,6 @@ public class Warn5 { METHOD("void m"), CONSTRUCTOR("Test"); - String name; MethodKind(String name) { @@ -155,7 +154,124 @@ public class Warn5 { } } - static class JavaSource extends SimpleJavaFileObject { + enum WarningKind { + UNSAFE_BODY, + UNSAFE_DECL, + MALFORMED_SAFEVARARGS, + REDUNDANT_SAFEVARARGS; + } + + // Create a single file manager and reuse it for each compile to save time. + static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + + public static void main(String... args) throws Exception { + for (SourceLevel sourceLevel : SourceLevel.values()) { + for (XlintOption xlint : XlintOption.values()) { + for (TrustMe trustMe : TrustMe.values()) { + for (SuppressLevel suppressLevel : SuppressLevel.values()) { + for (ModifierKind modKind : ModifierKind.values()) { + for (MethodKind methKind : MethodKind.values()) { + for (SignatureKind sig : SignatureKind.values()) { + for (BodyKind body : BodyKind.values()) { + new Warn5(sourceLevel, + xlint, + trustMe, + suppressLevel, + modKind, + methKind, + sig, + body).test(); + } + } + } + } + } + } + } + } + } + + final SourceLevel sourceLevel; + final XlintOption xlint; + final TrustMe trustMe; + final SuppressLevel suppressLevel; + final ModifierKind modKind; + final MethodKind methKind; + final SignatureKind sig; + final BodyKind body; + final JavaSource source; + final DiagnosticChecker dc; + + public Warn5(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) { + this.sourceLevel = sourceLevel; + this.xlint = xlint; + this.trustMe = trustMe; + this.suppressLevel = suppressLevel; + this.modKind = modKind; + this.methKind = methKind; + this.sig = sig; + this.body = body; + this.source = new JavaSource(); + this.dc = new DiagnosticChecker(); + } + + void test() throws Exception { + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavacTask ct = (JavacTask)tool.getTask(null, fm, dc, + Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source)); + ct.analyze(); + check(); + } + + void check() { + + EnumSet expectedWarnings = EnumSet.noneOf(WarningKind.class); + + if (sourceLevel == SourceLevel.JDK_7 && + trustMe == TrustMe.TRUST && + suppressLevel != SuppressLevel.VARARGS && + xlint != XlintOption.NONE && + sig.isVarargs && !sig.isReifiableArg && body.hasAliasing && + (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE))) { + expectedWarnings.add(WarningKind.UNSAFE_BODY); + } + + if (sourceLevel == SourceLevel.JDK_7 && + trustMe == TrustMe.DONT_TRUST && + sig.isVarargs && + !sig.isReifiableArg && + xlint == XlintOption.ALL) { + expectedWarnings.add(WarningKind.UNSAFE_DECL); + } + + if (sourceLevel == SourceLevel.JDK_7 && + trustMe == TrustMe.TRUST && + (!sig.isVarargs || + (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD))) { + expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS); + } + + if (sourceLevel == SourceLevel.JDK_7 && + trustMe == TrustMe.TRUST && + xlint != XlintOption.NONE && + suppressLevel != SuppressLevel.VARARGS && + (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) && + sig.isVarargs && + sig.isReifiableArg) { + expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS); + } + + if (!expectedWarnings.containsAll(dc.warnings) || + !dc.warnings.containsAll(expectedWarnings)) { + throw new Error("invalid diagnostics for source:\n" + + source.getCharContent(true) + + "\nOptions: " + xlint.getXlintOption() + + "\nExpected warnings: " + expectedWarnings + + "\nFound warnings: " + dc.warnings); + } + } + + class JavaSource extends SimpleJavaFileObject { String template = "import com.sun.tools.javac.api.*;\n" + "import java.util.List;\n" + @@ -167,12 +283,11 @@ public class Warn5 { String source; - public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, - MethodKind methKind, SignatureKind meth, BodyKind body) { + public JavaSource() { super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); source = template.replace("#T", trustMe.anno). replace("#S", suppressLevel.getSuppressAnno()). - replace("#M", meth.getSignature(modKind, methKind)). + replace("#M", sig.getSignature(modKind, methKind)). replace("#B", body.body); } @@ -182,117 +297,34 @@ public class Warn5 { } } - public static void main(String... args) throws Exception { - for (SourceLevel sourceLevel : SourceLevel.values()) { - for (XlintOption xlint : XlintOption.values()) { - for (TrustMe trustMe : TrustMe.values()) { - for (SuppressLevel suppressLevel : SuppressLevel.values()) { - for (ModifierKind modKind : ModifierKind.values()) { - for (MethodKind methKind : MethodKind.values()) { - for (SignatureKind sig : SignatureKind.values()) { - for (BodyKind body : BodyKind.values()) { - test(sourceLevel, - xlint, - trustMe, - suppressLevel, - modKind, - methKind, - sig, - body); - } - } - } - } - } - } - } - } - } + class DiagnosticChecker implements javax.tools.DiagnosticListener { - // Create a single file manager and reuse it for each compile to save time. - static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); - - static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, - ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception { - final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); - JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body); - DiagnosticChecker dc = new DiagnosticChecker(); - JavacTask ct = (JavacTask)tool.getTask(null, fm, dc, - Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source)); - ct.analyze(); - check(sourceLevel, dc, source, xlint, trustMe, - suppressLevel, modKind, methKind, sig, body); - } - - static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source, - XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind, - MethodKind methKind, SignatureKind meth, BodyKind body) { - - boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 && - trustMe == TrustMe.TRUST && - suppressLevel != SuppressLevel.VARARGS && - xlint != XlintOption.NONE && - meth.isVarargs && !meth.isReifiableArg && body.hasAliasing && - (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE)); - - boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 && - trustMe == TrustMe.DONT_TRUST && - meth.isVarargs && - !meth.isReifiableArg && - xlint == XlintOption.ALL; - - boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 && - trustMe == TrustMe.TRUST && - (!meth.isVarargs || - (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD)); - - boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 && - trustMe == TrustMe.TRUST && - xlint != XlintOption.NONE && - suppressLevel != SuppressLevel.VARARGS && - (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) && - meth.isVarargs && - meth.isReifiableArg; - - if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody || - hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl || - hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl || - hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) { - throw new Error("invalid diagnostics for source:\n" + - source.getCharContent(true) + - "\nOptions: " + xlint.getXlintOption() + - "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody + - "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl + - "\nExpected malformed anno error: " + hasMalformedAnnoInDecl + - "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl + - "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody + - "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl + - "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl + - "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl); - } - } - - static class DiagnosticChecker implements javax.tools.DiagnosticListener { - - boolean hasPotentiallyUnsafeBody = false; - boolean hasPotentiallyPollutingDecl = false; - boolean hasMalformedAnnoInDecl = false; - boolean hasRedundantAnnoInDecl = false; + EnumSet warnings = EnumSet.noneOf(WarningKind.class); public void report(Diagnostic diagnostic) { if (diagnostic.getKind() == Diagnostic.Kind.WARNING) { if (diagnostic.getCode().contains("unsafe.use.varargs.param")) { - hasPotentiallyUnsafeBody = true; + setWarning(WarningKind.UNSAFE_BODY); } else if (diagnostic.getCode().contains("redundant.trustme")) { - hasRedundantAnnoInDecl = true; + setWarning(WarningKind.REDUNDANT_SAFEVARARGS); } } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING && diagnostic.getCode().contains("varargs.non.reifiable.type")) { - hasPotentiallyPollutingDecl = true; + setWarning(WarningKind.UNSAFE_DECL); } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR && diagnostic.getCode().contains("invalid.trustme")) { - hasMalformedAnnoInDecl = true; + setWarning(WarningKind.MALFORMED_SAFEVARARGS); } } + + void setWarning(WarningKind wk) { + if (!warnings.add(wk)) { + throw new AssertionError("Duplicate warning of kind " + wk + " in source:\n" + source); + } + } + + boolean hasWarning(WarningKind wk) { + return warnings.contains(wk); + } } } From d3efececf329fb3ff0f811f5e34be0929f3a8cdc Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 17 Oct 2011 12:57:36 +0100 Subject: [PATCH 12/41] 7093325: Redundant entry in bytecode exception table Inlining of finalizers does not update gaps list accordingly Reviewed-by: jjg --- .../classes/com/sun/tools/javac/jvm/Code.java | 23 +- .../classes/com/sun/tools/javac/jvm/Gen.java | 34 +-- langtools/test/tools/javac/T7093325.java | 262 ++++++++++++++++++ 3 files changed, 301 insertions(+), 18 deletions(-) create mode 100644 langtools/test/tools/javac/T7093325.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index ec080df41e7..59f0fc167f6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -1542,7 +1542,28 @@ public class Code { */ public void addCatch( char startPc, char endPc, char handlerPc, char catchType) { - catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); + catchInfo.append(new char[]{startPc, endPc, handlerPc, catchType}); + } + + + public void compressCatchTable() { + ListBuffer compressedCatchInfo = ListBuffer.lb(); + List handlerPcs = List.nil(); + for (char[] catchEntry : catchInfo.elems) { + handlerPcs = handlerPcs.prepend((int)catchEntry[2]); + } + for (char[] catchEntry : catchInfo.elems) { + int startpc = catchEntry[0]; + int endpc = catchEntry[1]; + if (startpc == endpc || + (startpc == (endpc - 1) && + handlerPcs.contains(startpc))) { + continue; + } else { + compressedCatchInfo.append(catchEntry); + } + } + catchInfo = compressedCatchInfo; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index 618700ec83f..f1a2a71f2d6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -959,6 +959,9 @@ public class Gen extends JCTree.Visitor { code.lastFrame = null; code.frameBeforeLast = null; } + + //compress exception table + code.compressCatchTable(); } } @@ -1437,7 +1440,6 @@ public class Gen extends JCTree.Visitor { code.markDead(); } } - // Resolve all breaks. code.resolve(exitChain); @@ -1496,23 +1498,21 @@ public class Gen extends JCTree.Visitor { void registerCatch(DiagnosticPosition pos, int startpc, int endpc, int handler_pc, int catch_type) { - if (startpc != endpc) { - char startpc1 = (char)startpc; - char endpc1 = (char)endpc; - char handler_pc1 = (char)handler_pc; - if (startpc1 == startpc && - endpc1 == endpc && - handler_pc1 == handler_pc) { - code.addCatch(startpc1, endpc1, handler_pc1, - (char)catch_type); + char startpc1 = (char)startpc; + char endpc1 = (char)endpc; + char handler_pc1 = (char)handler_pc; + if (startpc1 == startpc && + endpc1 == endpc && + handler_pc1 == handler_pc) { + code.addCatch(startpc1, endpc1, handler_pc1, + (char)catch_type); + } else { + if (!useJsrLocally && !target.generateStackMapTable()) { + useJsrLocally = true; + throw new CodeSizeOverflow(); } else { - if (!useJsrLocally && !target.generateStackMapTable()) { - useJsrLocally = true; - throw new CodeSizeOverflow(); - } else { - log.error(pos, "limit.code.too.large.for.try.stmt"); - nerrs++; - } + log.error(pos, "limit.code.too.large.for.try.stmt"); + nerrs++; } } } diff --git a/langtools/test/tools/javac/T7093325.java b/langtools/test/tools/javac/T7093325.java new file mode 100644 index 00000000000..42ea3bc0705 --- /dev/null +++ b/langtools/test/tools/javac/T7093325.java @@ -0,0 +1,262 @@ +/* + * 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 7093325 + * @summary Redundant entry in bytecode exception table + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.*; +import com.sun.tools.classfile.Method; +import com.sun.tools.javac.api.JavacTool; + +import java.io.File; +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.ToolProvider; + + +public class T7093325 { + + /** global decls ***/ + + // Create a single file manager and reuse it for each compile to save time. + static StandardJavaFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + + //statistics + static int checkCount = 0; + + enum StatementKind { + THROW("throw new RuntimeException();", false, false), + RETURN_NONEMPTY("System.out.println(); return;", true, false), + RETURN_EMPTY("return;", true, true), + APPLY("System.out.println();", true, false); + + String stmt; + boolean canInline; + boolean empty; + + private StatementKind(String stmt, boolean canInline, boolean empty) { + this.stmt = stmt; + this.canInline = canInline; + this.empty = empty; + } + } + + enum CatchArity { + NONE(""), + ONE("catch (A a) { #S1 }"), + TWO("catch (B b) { #S2 }"), + THREE("catch (C c) { #S3 }"), + FOUR("catch (D d) { #S4 }"); + + String catchStr; + + private CatchArity(String catchStr) { + this.catchStr = catchStr; + } + + String catchers() { + if (this.ordinal() == 0) { + return catchStr; + } else { + return CatchArity.values()[this.ordinal() - 1].catchers() + catchStr; + } + } + } + + public static void main(String... args) throws Exception { + for (CatchArity ca : CatchArity.values()) { + for (StatementKind stmt0 : StatementKind.values()) { + if (ca.ordinal() == 0) { + new T7093325(ca, stmt0).compileAndCheck(); + continue; + } + for (StatementKind stmt1 : StatementKind.values()) { + if (ca.ordinal() == 1) { + new T7093325(ca, stmt0, stmt1).compileAndCheck(); + continue; + } + for (StatementKind stmt2 : StatementKind.values()) { + if (ca.ordinal() == 2) { + new T7093325(ca, stmt0, stmt1, stmt2).compileAndCheck(); + continue; + } + for (StatementKind stmt3 : StatementKind.values()) { + if (ca.ordinal() == 3) { + new T7093325(ca, stmt0, stmt1, stmt2, stmt3).compileAndCheck(); + continue; + } + for (StatementKind stmt4 : StatementKind.values()) { + if (ca.ordinal() == 4) { + new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4).compileAndCheck(); + continue; + } + for (StatementKind stmt5 : StatementKind.values()) { + new T7093325(ca, stmt0, stmt1, stmt2, stmt3, stmt4, stmt5).compileAndCheck(); + } + } + } + } + } + } + } + + System.out.println("Total checks made: " + checkCount); + } + + /** instance decls **/ + + CatchArity ca; + StatementKind[] stmts; + + public T7093325(CatchArity ca, StatementKind... stmts) { + this.ca = ca; + this.stmts = stmts; + } + + void compileAndCheck() throws Exception { + final JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); + JavaSource source = new JavaSource(); + JavacTask ct = (JavacTask)tool.getTask(null, fm, null, + null, null, Arrays.asList(source)); + ct.call(); + verifyBytecode(source); + } + + void verifyBytecode(JavaSource source) { + checkCount++; + boolean lastInlined = false; + boolean hasCode = false; + int gapsCount = 0; + for (int i = 0; i < stmts.length ; i++) { + lastInlined = stmts[i].canInline; + hasCode = hasCode || !stmts[i].empty; + if (lastInlined && hasCode) { + hasCode = false; + gapsCount++; + } + } + if (!lastInlined) { + gapsCount++; + } + + //System.out.printf("gaps %d \n %s \n", gapsCount, source.toString()); + + File compiledTest = new File("Test.class"); + try { + ClassFile cf = ClassFile.read(compiledTest); + if (cf == null) { + throw new Error("Classfile not found: " + compiledTest.getName()); + } + + Method test_method = null; + for (Method m : cf.methods) { + if (m.getName(cf.constant_pool).equals("test")) { + test_method = m; + break; + } + } + + if (test_method == null) { + throw new Error("Method test() not found in class Test"); + } + + Code_attribute code = null; + for (Attribute a : test_method.attributes) { + if (a.getName(cf.constant_pool).equals(Attribute.Code)) { + code = (Code_attribute)a; + break; + } + } + + if (code == null) { + throw new Error("Code attribute not found in method test()"); + } + + int actualGapsCount = 0; + for (int i = 0; i < code.exception_table_langth ; i++) { + int catchType = code.exception_table[i].catch_type; + if (catchType == 0) { //any + actualGapsCount++; + } + } + + if (actualGapsCount != gapsCount) { + throw new Error("Bad exception table for test()\n" + + "expected gaps: " + gapsCount + "\n" + + "found gaps: " + actualGapsCount + "\n" + + source); + } + } catch (Exception e) { + e.printStackTrace(); + throw new Error("error reading " + compiledTest +": " + e); + } + + } + + class JavaSource extends SimpleJavaFileObject { + + static final String source_template = + "class A extends RuntimeException {} \n" + + "class B extends RuntimeException {} \n" + + "class C extends RuntimeException {} \n" + + "class D extends RuntimeException {} \n" + + "class E extends RuntimeException {} \n" + + "class Test {\n" + + " void test() {\n" + + " try { #S0 } #C finally { System.out.println(); }\n" + + " }\n" + + "}"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = source_template.replace("#C", ca.catchers()); + source = source.replace("#S0", stmts[0].stmt); + for (int i = 1; i < ca.ordinal() + 1; i++) { + source = source.replace("#S" + i, stmts[i].stmt); + } + } + + @Override + public String toString() { + return source; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } +} From 747169f70ef9947c6e6f1b2fa4c666bddc0d7021 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Wed, 19 Oct 2011 16:56:05 +0100 Subject: [PATCH 13/41] 7102515: javac running very very long and not returning Verbose resolution diagnostics slow down with operator resolution Reviewed-by: jjg --- .../classes/com/sun/tools/javac/comp/Resolve.java | 2 ++ langtools/test/tools/javac/7102515/T7102515.java | 11 +++++++++++ langtools/test/tools/javac/7102515/T7102515.out | 3 +++ 3 files changed, 16 insertions(+) create mode 100644 langtools/test/tools/javac/7102515/T7102515.java create mode 100644 langtools/test/tools/javac/7102515/T7102515.out diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 43a8977d537..0c37d015188 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -691,6 +691,7 @@ public class Resolve { case ABSENT_MTH: return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); case WRONG_MTH: + if (operator) return bestSoFar; wrongMethods.addCandidate(currentStep, wrongMethod.sym, wrongMethod.explanation); case WRONG_MTHS: return wrongMethods.addCandidate(currentStep, sym, ex.getDiagnostic()); @@ -1685,6 +1686,7 @@ public class Resolve { */ Symbol resolveOperator(DiagnosticPosition pos, int optag, Env env, List argtypes) { + startResolution(); Name name = treeinfo.operatorName(optag); Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes, null, false, false, true); diff --git a/langtools/test/tools/javac/7102515/T7102515.java b/langtools/test/tools/javac/7102515/T7102515.java new file mode 100644 index 00000000000..da9ec633cb2 --- /dev/null +++ b/langtools/test/tools/javac/7102515/T7102515.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7102515 + * @summary javac running very very long and not returning + * @compile/fail/ref=T7102515.out -XDrawDiagnostics T7102515.java + */ + +class T7102515 { + T7102515 badBinary = new T7102515() + new T7102515(); + Object badUnary = badBinary++; +} diff --git a/langtools/test/tools/javac/7102515/T7102515.out b/langtools/test/tools/javac/7102515/T7102515.out new file mode 100644 index 00000000000..00df5201cf4 --- /dev/null +++ b/langtools/test/tools/javac/7102515/T7102515.out @@ -0,0 +1,3 @@ +T7102515.java:9:41: compiler.err.operator.cant.be.applied.1: +, T7102515, T7102515 +T7102515.java:10:32: compiler.err.operator.cant.be.applied: ++, T7102515, null +2 errors From 6c299173e18093413a1b9e02790eae18181df4aa Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 19 Oct 2011 15:29:46 -0700 Subject: [PATCH 14/41] 7101146: Paths should more directly managed by BaseFileManager Reviewed-by: mcimadamore --- .../tools/javac/file/JavacFileManager.java | 28 ++++++----------- .../com/sun/tools/javac/file/Paths.java | 30 ++++--------------- .../tools/javac/nio/JavacPathFileManager.java | 7 +---- .../sun/tools/javac/util/BaseFileManager.java | 24 +++++++++++---- 4 files changed, 34 insertions(+), 55 deletions(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java index ff10fd3ed36..ae6cf2d2757 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -25,7 +25,6 @@ package com.sun.tools.javac.file; -import java.util.Comparator; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; @@ -41,6 +40,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; @@ -54,6 +54,7 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; +import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; import com.sun.tools.javac.main.OptionName; @@ -83,10 +84,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil return buffer.toString().toCharArray(); } - /** Encapsulates knowledge of paths - */ - private Paths paths; - private FSInfo fsInfo; private boolean contextUseOptimizedZip; @@ -154,13 +151,6 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil @Override public void setContext(Context context) { super.setContext(context); - if (paths == null) { - paths = Paths.instance(context); - } else { - // Reuse the Paths object as it stores the locations that - // have been set with setLocation, etc. - paths.setContext(context); - } fsInfo = FSInfo.instance(context); @@ -179,7 +169,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil @Override public boolean isDefaultBootClassPath() { - return paths.isDefaultBootClassPath(); + return searchPaths.isDefaultBootClassPath(); } public JavaFileObject getFileForInput(String name) { @@ -493,7 +483,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil */ private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException { File origZipFileName = zipFileName; - if (!ignoreSymbolFile && paths.isDefaultBootClassPathRtJar(zipFileName)) { + if (!ignoreSymbolFile && searchPaths.isDefaultBootClassPathRtJar(zipFileName)) { File file = zipFileName.getParentFile().getParentFile(); // ${java.home} if (new File(file.getName()).equals(new File("jre"))) file = file.getParentFile(); @@ -780,7 +770,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } else if (location == SOURCE_OUTPUT) { dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir()); } else { - Iterable path = paths.getPathForLocation(location); + Iterable path = searchPaths.getPathForLocation(location); dir = null; for (File f: path) { dir = f; @@ -815,7 +805,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil throws IOException { nullCheck(location); - paths.lazy(); + searchPaths.lazy(); final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null; @@ -824,7 +814,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil else if (location == SOURCE_OUTPUT) sourceOutDir = getOutputLocation(dir, S); else - paths.setPathForLocation(location, path); + searchPaths.setPathForLocation(location, path); } // where private File getOutputDirectory(Iterable path) throws IOException { @@ -854,13 +844,13 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil public Iterable getLocation(Location location) { nullCheck(location); - paths.lazy(); + searchPaths.lazy(); if (location == CLASS_OUTPUT) { return (getClassOutDir() == null ? null : List.of(getClassOutDir())); } else if (location == SOURCE_OUTPUT) { return (getSourceOutDir() == null ? null : List.of(getSourceOutDir())); } else - return paths.getPathForLocation(location); + return searchPaths.getPathForLocation(location); } private File getClassOutDir() { diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java index 3e0ec5abd15..69a74cc79f5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java @@ -41,7 +41,6 @@ import java.util.zip.ZipFile; import javax.tools.JavaFileManager.Location; import com.sun.tools.javac.code.Lint; -import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Options; @@ -61,21 +60,6 @@ import static com.sun.tools.javac.main.OptionName.*; */ public class Paths { - /** The context key for the todo list */ - protected static final Context.Key pathsKey = - new Context.Key(); - - /** Get the Paths instance for this context. - * @param context the context - * @return the Paths instance for this context - */ - public static Paths instance(Context context) { - Paths instance = context.get(pathsKey); - if (instance == null) - instance = new Paths(context); - return instance; - } - /** The log to use for warning output */ private Log log; @@ -88,17 +72,15 @@ public class Paths { /** Access to (possibly cached) file info */ private FSInfo fsInfo; - protected Paths(Context context) { - context.put(pathsKey, this); + public Paths() { pathsForLocation = new HashMap(16); - setContext(context); } - void setContext(Context context) { - log = Log.instance(context); - options = Options.instance(context); - lint = Lint.instance(context); - fsInfo = FSInfo.instance(context); + public void update(Log log, Options options, Lint lint, FSInfo fsInfo) { + this.log = log; + this.options = options; + this.lint = lint; + this.fsInfo = fsInfo; } /** Whether to warn about non-existent path elements */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java index bb0c6205a10..5ed6334cb41 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java @@ -25,9 +25,7 @@ package com.sun.tools.javac.nio; - import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -60,7 +58,6 @@ import javax.tools.StandardLocation; import static java.nio.file.FileVisitOption.*; import static javax.tools.StandardLocation.*; -import com.sun.tools.javac.file.Paths; import com.sun.tools.javac.util.BaseFileManager; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; @@ -125,9 +122,8 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan * Set the context for JavacPathFileManager. */ @Override - protected void setContext(Context context) { + public void setContext(Context context) { super.setContext(context); - searchPaths = Paths.instance(context); } @Override @@ -272,7 +268,6 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan private boolean inited = false; private Map pathsForLocation; - private Paths searchPaths; private static class PathsForLocation extends LinkedHashSet { private static final long serialVersionUID = 6788510222394486733L; diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java index c9d7d8b2b4c..d393088c414 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java @@ -25,11 +25,6 @@ package com.sun.tools.javac.util; -import com.sun.tools.javac.code.Source; -import com.sun.tools.javac.main.JavacOption; -import com.sun.tools.javac.main.OptionName; -import com.sun.tools.javac.main.RecognizedOptions; -import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; @@ -54,6 +49,15 @@ import java.util.Map; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; +import com.sun.tools.javac.code.Lint; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.file.FSInfo; +import com.sun.tools.javac.file.Paths; +import com.sun.tools.javac.main.JavacOption; +import com.sun.tools.javac.main.OptionName; +import com.sun.tools.javac.main.RecognizedOptions; +import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; + /** * Utility methods for building a filemanager. * There are no references here to file-system specific objects such as @@ -63,15 +67,21 @@ public abstract class BaseFileManager { protected BaseFileManager(Charset charset) { this.charset = charset; byteBufferCache = new ByteBufferCache(); + searchPaths = createPaths(); } /** * Set the context for JavacPathFileManager. */ - protected void setContext(Context context) { + public void setContext(Context context) { log = Log.instance(context); options = Options.instance(context); classLoaderClass = options.get("procloader"); + searchPaths.update(log, options, Lint.instance(context), FSInfo.instance(context)); + } + + protected Paths createPaths() { + return new Paths(); } /** @@ -88,6 +98,8 @@ public abstract class BaseFileManager { protected String classLoaderClass; + protected Paths searchPaths; + protected Source getSource() { String sourceName = options.get(OptionName.SOURCE); Source source = null; From 8fb3eec82e4ec24502f6212f4cde57f015524d93 Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Thu, 20 Oct 2011 10:21:35 +0200 Subject: [PATCH 15/41] 7097516: G1: assert(0<= from_card && from_cardis_in_reserved(from)) { + // If the table used to belong to a continues humongous region and is + // now reused for the corresponding start humongous region, we need to + // make sure that we detect this. Thus, we call is_in_reserved_raw() + // instead of just is_in_reserved() here. + if (loc_hr->is_in_reserved_raw(from)) { size_t hw_offset = pointer_delta((HeapWord*)from, loc_hr->bottom()); CardIdx_t from_card = (CardIdx_t) hw_offset >> (CardTableModRefBS::card_shift - LogHeapWordSize); From c8143a724ef6213977d9b5bbfe5071e114397a7a Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Thu, 20 Oct 2011 12:06:20 -0700 Subject: [PATCH 16/41] 7099824: G1: we should take the pending list lock before doing the remark pause Acquire the pending list lock in the prologue method of G1's concurrent VM_Operation and release the lock in the epilogue() method. The locking/unlocking order of the pending list lock and the Heap_lock should match that in the prologue and epilogue methods of VM_GC_Operation. Reviewed-by: tonyp, ysr --- .../g1/concurrentMarkThread.cpp | 19 ++++++++-------- .../gc_implementation/g1/vm_operations_g1.cpp | 22 +++++++++++++++++++ .../gc_implementation/g1/vm_operations_g1.hpp | 8 ++++++- .../shared/concurrentGCThread.cpp | 2 ++ 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index 4e4e6422956..0a4c81a2f46 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -147,12 +147,8 @@ void ConcurrentMarkThread::run() { } } } while (cm()->restart_for_overflow()); + double counting_start_time = os::elapsedVTime(); - - // YSR: These look dubious (i.e. redundant) !!! FIX ME - slt()->manipulatePLL(SurrogateLockerThread::acquirePLL); - slt()->manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); - if (!cm()->has_aborted()) { double count_start_sec = os::elapsedTime(); if (PrintGC) { @@ -175,6 +171,7 @@ void ConcurrentMarkThread::run() { } } } + double end_time = os::elapsedVTime(); _vtime_count_accum += (end_time - counting_start_time); // Update the total virtual time before doing this, since it will try @@ -335,13 +332,15 @@ void ConcurrentMarkThread::sleepBeforeNextCycle() { clear_started(); } -// Note: this method, although exported by the ConcurrentMarkSweepThread, -// which is a non-JavaThread, can only be called by a JavaThread. -// Currently this is done at vm creation time (post-vm-init) by the -// main/Primordial (Java)Thread. -// XXX Consider changing this in the future to allow the CMS thread +// Note: As is the case with CMS - this method, although exported +// by the ConcurrentMarkThread, which is a non-JavaThread, can only +// be called by a JavaThread. Currently this is done at vm creation +// time (post-vm-init) by the main/Primordial (Java)Thread. +// XXX Consider changing this in the future to allow the CM thread // itself to create this thread? void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) { + assert(UseG1GC, "SLT thread needed only for concurrent GC"); + assert(THREAD->is_Java_thread(), "must be a Java thread"); assert(_slt == NULL, "SLT already created"); _slt = SurrogateLockerThread::make(THREAD); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index 04d051b8443..befacd69e5e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" #include "gc_implementation/g1/vm_operations_g1.hpp" @@ -165,6 +166,20 @@ void VM_G1IncCollectionPause::doit_epilogue() { } } +void VM_CGC_Operation::acquire_pending_list_lock() { + // The caller may block while communicating + // with the SLT thread in order to acquire/release the PLL. + ConcurrentMarkThread::slt()-> + manipulatePLL(SurrogateLockerThread::acquirePLL); +} + +void VM_CGC_Operation::release_and_notify_pending_list_lock() { + // The caller may block while communicating + // with the SLT thread in order to acquire/release the PLL. + ConcurrentMarkThread::slt()-> + manipulatePLL(SurrogateLockerThread::releaseAndNotifyPLL); +} + void VM_CGC_Operation::doit() { gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); @@ -180,12 +195,19 @@ void VM_CGC_Operation::doit() { } bool VM_CGC_Operation::doit_prologue() { + // Note the relative order of the locks must match that in + // VM_GC_Operation::doit_prologue() or deadlocks can occur + acquire_pending_list_lock(); + Heap_lock->lock(); SharedHeap::heap()->_thread_holds_heap_lock_for_gc = true; return true; } void VM_CGC_Operation::doit_epilogue() { + // Note the relative order of the unlocks must match that in + // VM_GC_Operation::doit_epilogue() SharedHeap::heap()->_thread_holds_heap_lock_for_gc = false; Heap_lock->unlock(); + release_and_notify_pending_list_lock(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp index 825818dd4e6..c8bbe06198f 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.hpp @@ -93,11 +93,17 @@ public: } }; -// Concurrent GC stop-the-world operations such as initial and final mark; +// Concurrent GC stop-the-world operations such as remark and cleanup; // consider sharing these with CMS's counterparts. class VM_CGC_Operation: public VM_Operation { VoidClosure* _cl; const char* _printGCMessage; + +protected: + // java.lang.ref.Reference support + void acquire_pending_list_lock(); + void release_and_notify_pending_list_lock(); + public: VM_CGC_Operation(VoidClosure* cl, const char *printGCMsg) : _cl(cl), _printGCMessage(printGCMsg) { } diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp index a231e5d8169..0dea4208091 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp @@ -224,6 +224,8 @@ void SurrogateLockerThread::manipulatePLL(SLT_msg_type msg) { MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); assert(_buffer == empty, "Should be empty"); assert(msg != empty, "empty message"); + assert(!Heap_lock->owned_by_self(), "Heap_lock owned by requesting thread"); + _buffer = msg; while (_buffer != empty) { _monitor.notify(); From 2f1ee9427a34aea028b9056fc00fa4e1590ce766 Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Fri, 21 Oct 2011 15:56:24 +0900 Subject: [PATCH 17/41] 7103108: (tz) Support tzdata2011l Reviewed-by: okutsu --- jdk/make/sun/javazic/tzdata/VERSION | 2 +- jdk/make/sun/javazic/tzdata/asia | 66 +++++++++++++++++-- jdk/make/sun/javazic/tzdata/australasia | 14 ++++ jdk/make/sun/javazic/tzdata/europe | 63 +++++++++++++++--- jdk/make/sun/javazic/tzdata/northamerica | 38 ++++------- jdk/make/sun/javazic/tzdata/southamerica | 23 +++++++ jdk/make/sun/javazic/tzdata/zone.tab | 3 +- .../sun/util/resources/TimeZoneNames.java | 16 +++-- .../sun/util/resources/TimeZoneNames_de.java | 16 +++-- .../sun/util/resources/TimeZoneNames_es.java | 16 +++-- .../sun/util/resources/TimeZoneNames_fr.java | 16 +++-- .../sun/util/resources/TimeZoneNames_it.java | 16 +++-- .../sun/util/resources/TimeZoneNames_ja.java | 16 +++-- .../sun/util/resources/TimeZoneNames_ko.java | 16 +++-- .../util/resources/TimeZoneNames_pt_BR.java | 16 +++-- .../sun/util/resources/TimeZoneNames_sv.java | 16 +++-- .../util/resources/TimeZoneNames_zh_CN.java | 16 +++-- .../util/resources/TimeZoneNames_zh_TW.java | 16 +++-- 18 files changed, 268 insertions(+), 117 deletions(-) diff --git a/jdk/make/sun/javazic/tzdata/VERSION b/jdk/make/sun/javazic/tzdata/VERSION index 9ccfe4c299f..fbc87a0d579 100644 --- a/jdk/make/sun/javazic/tzdata/VERSION +++ b/jdk/make/sun/javazic/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2011j +tzdata2011l diff --git a/jdk/make/sun/javazic/tzdata/asia b/jdk/make/sun/javazic/tzdata/asia index 36c52373004..446940c21bf 100644 --- a/jdk/make/sun/javazic/tzdata/asia +++ b/jdk/make/sun/javazic/tzdata/asia @@ -2216,7 +2216,47 @@ Zone Asia/Karachi 4:28:12 - LMT 1907 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html # +# From Steffen Thorsen (2011-08-26): +# Gaza and the West Bank did go back to standard time in the beginning of +# August, and will now enter daylight saving time again on 2011-08-30 +# 00:00 (so two periods of DST in 2011). The pause was because of +# Ramadan. +# +# +# http://www.maannews.net/eng/ViewDetails.aspx?ID=416217 +# +# Additional info: +# +# http://www.timeanddate.com/news/time/palestine-dst-2011.html +# + +# From Alexander Krivenyshev (2011-08-27): +# According to the article in The Jerusalem Post: +# "...Earlier this month, the Palestinian government in the West Bank decided to +# move to standard time for 30 days, during Ramadan. The Palestinians in the +# Gaza Strip accepted the change and also moved their clocks one hour back. +# The Hamas government said on Saturday that it won't observe summertime after +# the Muslim feast of Id al-Fitr, which begins on Tuesday..." +# ... +# +# http://www.jpost.com/MiddleEast/Article.aspx?id=235650 +# +# or +# +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html +# # The rules for Egypt are stolen from the `africa' file. + +# From Steffen Thorsen (2011-09-30): +# West Bank did end Daylight Saving Time this morning/midnight (2011-09-30 +# 00:00). +# So West Bank and Gaza now have the same time again. +# +# Many sources, including: +# +# http://www.maannews.net/eng/ViewDetails.aspx?ID=424808 +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S Rule EgyptAsia 1957 1958 - Oct 1 0:00 0 - @@ -2232,19 +2272,37 @@ Rule Palestine 2005 only - Oct 4 2:00 0 - Rule Palestine 2006 2008 - Apr 1 0:00 1:00 S Rule Palestine 2006 only - Sep 22 0:00 0 - Rule Palestine 2007 only - Sep Thu>=8 2:00 0 - -Rule Palestine 2008 only - Aug lastFri 2:00 0 - +Rule Palestine 2008 only - Aug lastFri 0:00 0 - Rule Palestine 2009 only - Mar lastFri 0:00 1:00 S -Rule Palestine 2010 max - Mar lastSat 0:01 1:00 S -Rule Palestine 2009 max - Sep Fri>=1 2:00 0 - +Rule Palestine 2009 only - Sep Fri>=1 2:00 0 - +Rule Palestine 2010 only - Mar lastSat 0:01 1:00 S Rule Palestine 2010 only - Aug 11 0:00 0 - +# From Arthur David Olson (2011-09-20): +# 2011 transitions per http://www.timeanddate.com as of 2011-09-20. + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct 2:00 Zion EET 1948 May 15 2:00 EgyptAsia EE%sT 1967 Jun 5 2:00 Zion I%sT 1996 2:00 Jordan EE%sT 1999 - 2:00 Palestine EE%sT + 2:00 Palestine EE%sT 2011 Apr 2 12:01 + 2:00 1:00 EEST 2011 Aug 1 + 2:00 - EET + +Zone Asia/Hebron 2:20:23 - LMT 1900 Oct + 2:00 Zion EET 1948 May 15 + 2:00 EgyptAsia EE%sT 1967 Jun 5 + 2:00 Zion I%sT 1996 + 2:00 Jordan EE%sT 1999 + 2:00 Palestine EE%sT 2008 Aug + 2:00 1:00 EEST 2008 Sep + 2:00 Palestine EE%sT 2011 Apr 1 12:01 + 2:00 1:00 EEST 2011 Aug 1 + 2:00 - EET 2011 Aug 30 + 2:00 1:00 EEST 2011 Sep 30 3:00 + 2:00 - EET # Paracel Is # no information diff --git a/jdk/make/sun/javazic/tzdata/australasia b/jdk/make/sun/javazic/tzdata/australasia index 0330fcd9234..722908b4b95 100644 --- a/jdk/make/sun/javazic/tzdata/australasia +++ b/jdk/make/sun/javazic/tzdata/australasia @@ -318,6 +318,18 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html # +# From Steffen Thorsen (2011-10-03): +# Now the dates have been confirmed, and at least our start date +# assumption was correct (end date was one week wrong). +# +# +# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155 +# +# which says +# Members of the public are reminded to change their time to one hour in +# advance at 2am to 3am on October 23, 2011 and one hour back at 3am to +# 2am on February 26 next year. + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - @@ -325,6 +337,8 @@ Rule Fiji 2009 only - Nov 29 2:00 1:00 S Rule Fiji 2010 only - Mar lastSun 3:00 0 - Rule Fiji 2010 only - Oct 24 2:00 1:00 S Rule Fiji 2011 only - Mar Sun>=1 3:00 0 - +Rule Fiji 2011 only - Oct 23 2:00 1:00 S +Rule Fiji 2012 only - Feb 26 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva 12:00 Fiji FJ%sT # Fiji Time diff --git a/jdk/make/sun/javazic/tzdata/europe b/jdk/make/sun/javazic/tzdata/europe index 5c6abc17424..b5394fb5004 100644 --- a/jdk/make/sun/javazic/tzdata/europe +++ b/jdk/make/sun/javazic/tzdata/europe @@ -583,9 +583,9 @@ Rule Russia 1985 1991 - Mar lastSun 2:00s 1:00 S # Rule Russia 1992 only - Mar lastSat 23:00 1:00 S Rule Russia 1992 only - Sep lastSat 23:00 0 - -Rule Russia 1993 max - Mar lastSun 2:00s 1:00 S +Rule Russia 1993 2010 - Mar lastSun 2:00s 1:00 S Rule Russia 1993 1995 - Sep lastSun 2:00s 0 - -Rule Russia 1996 max - Oct lastSun 2:00s 0 - +Rule Russia 1996 2010 - Oct lastSun 2:00s 0 - # From Alexander Krivenyshev (2011-06-14): # According to Kremlin press service, Russian President Dmitry Medvedev @@ -605,7 +605,6 @@ Rule Russia 1996 max - Oct lastSun 2:00s 0 - # From Arthur David Olson (2011-06-15): # Take "abolishing daylight saving time" to mean that time is now considered # to be standard. -# At least for now, keep the "old" Russia rules for the benefit of Belarus. # These are for backward compatibility with older versions. @@ -711,6 +710,23 @@ Zone Europe/Vienna 1:05:20 - LMT 1893 Apr 1:00 EU CE%sT # Belarus +# From Yauhen Kharuzhy (2011-09-16): +# By latest Belarus government act Europe/Minsk timezone was changed to +# GMT+3 without DST (was GMT+2 with DST). +# +# Sources (Russian language): +# 1. +# +# http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html +# +# 2. +# +# http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/ +# +# 3. +# +# http://news.tut.by/society/250578.html +# # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Europe/Minsk 1:50:16 - LMT 1880 1:50 - MMT 1924 May 2 # Minsk Mean Time @@ -722,7 +738,8 @@ Zone Europe/Minsk 1:50:16 - LMT 1880 2:00 1:00 EEST 1991 Sep 29 2:00s 2:00 - EET 1992 Mar 29 0:00s 2:00 1:00 EEST 1992 Sep 27 0:00s - 2:00 Russia EE%sT + 2:00 Russia EE%sT 2011 Mar 27 2:00s + 3:00 - FET # Further-eastern European Time # Belgium # @@ -2056,7 +2073,7 @@ Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr 2:00 Poland CE%sT 1946 3:00 Russia MSK/MSD 1991 Mar 31 2:00s 2:00 Russia EE%sT 2011 Mar 27 2:00s - 3:00 - KALT + 3:00 - FET # Further-eastern European Time # # From Oscar van Vlijmen (2001-08-25): [This region consists of] # Respublika Adygeya, Arkhangel'skaya oblast', @@ -2211,7 +2228,7 @@ Zone Asia/Irkutsk 6:57:20 - LMT 1880 # [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'. # From Oscar van Vlijmen (2009-11-29): -# ...some regions of RUssia were merged with others since 2005... +# ...some regions of [Russia] were merged with others since 2005... # Some names were changed, no big deal, except for one instance: a new name. # YAK/YAKST: UTC+9 Zabajkal'skij kraj. @@ -2635,6 +2652,28 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents. # of March at 3am the time is changing to 4am and each last Sunday of # October the time at 4am is changing to 3am" +# From Alexander Krivenyshev (2011-09-20): +# On September 20, 2011 the deputies of the Verkhovna Rada agreed to +# abolish the transfer clock to winter time. +# +# Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got +# approval from 266 deputies. +# +# Ukraine abolishes transter back to the winter time (in Russian) +# +# http://news.mail.ru/politics/6861560/ +# +# +# The Ukrainians will no longer change the clock (in Russian) +# +# http://www.segodnya.ua/news/14290482.html +# +# +# Deputies cancelled the winter time (in Russian) +# +# http://www.pravda.com.ua/rus/news/2011/09/20/6600616/ +# + # Zone NAME GMTOFF RULES FORMAT [UNTIL] # Most of Ukraine since 1970 has been like Kiev. # "Kyiv" is the transliteration of the Ukrainian name, but @@ -2648,7 +2687,8 @@ Zone Europe/Kiev 2:02:04 - LMT 1880 3:00 - MSK 1990 Jul 1 2:00 2:00 - EET 1992 2:00 E-Eur EE%sT 1995 - 2:00 EU EE%sT + 2:00 EU EE%sT 2011 Mar lastSun 1:00u + 3:00 - FET # Further-eastern European Time # Ruthenia used CET 1990/1991. # "Uzhhorod" is the transliteration of the Ukrainian name, but # "Uzhgorod" is more common in English. @@ -2662,7 +2702,8 @@ Zone Europe/Uzhgorod 1:29:12 - LMT 1890 Oct 1:00 - CET 1991 Mar 31 3:00 2:00 - EET 1992 2:00 E-Eur EE%sT 1995 - 2:00 EU EE%sT + 2:00 EU EE%sT 2011 Mar lastSun 1:00u + 3:00 - FET # Further-eastern European Time # Zaporozh'ye and eastern Lugansk oblasts observed DST 1990/1991. # "Zaporizhia" is the transliteration of the Ukrainian name, but # "Zaporozh'ye" is more common in English. Use the common English @@ -2675,7 +2716,8 @@ Zone Europe/Zaporozhye 2:20:40 - LMT 1880 1:00 C-Eur CE%sT 1943 Oct 25 3:00 Russia MSK/MSD 1991 Mar 31 2:00 2:00 E-Eur EE%sT 1995 - 2:00 EU EE%sT + 2:00 EU EE%sT 2011 Mar lastSun 1:00u + 3:00 - FET # Further-eastern European Time # Central Crimea used Moscow time 1994/1997. Zone Europe/Simferopol 2:16:24 - LMT 1880 2:16 - SMT 1924 May 2 # Simferopol Mean T @@ -2700,7 +2742,8 @@ Zone Europe/Simferopol 2:16:24 - LMT 1880 # Assume it happened in March by not changing the clocks. 3:00 Russia MSK/MSD 1997 3:00 - MSK 1997 Mar lastSun 1:00u - 2:00 EU EE%sT + 2:00 EU EE%sT 2011 Mar lastSun 1:00u + 3:00 - FET # Further-eastern European Time ############################################################################### diff --git a/jdk/make/sun/javazic/tzdata/northamerica b/jdk/make/sun/javazic/tzdata/northamerica index d31b7f0ad03..fbefc6d320d 100644 --- a/jdk/make/sun/javazic/tzdata/northamerica +++ b/jdk/make/sun/javazic/tzdata/northamerica @@ -505,7 +505,7 @@ Zone America/Juneau 15:02:19 - LMT 1867 Oct 18 -8:00 US P%sT 1983 Oct 30 2:00 -9:00 US Y%sT 1983 Nov 30 -9:00 US AK%sT -Zone America/Sitka -14:58:47 - LMT 1867 Oct 18 +Zone America/Sitka 14:58:47 - LMT 1867 Oct 18 -9:01:13 - LMT 1900 Aug 20 12:00 -8:00 - PST 1942 -8:00 US P%sT 1946 @@ -1190,31 +1190,21 @@ Rule StJohns 1960 1986 - Oct lastSun 2:00 0 S # INMS (2000-09-12) says that, since 1988 at least, Newfoundland switches # at 00:01 local time. For now, assume it started in 1987. -# From Michael Pelley (2011-08-05): -# The Government of Newfoundland and Labrador has pending changes to -# modify the hour for daylight savings time to come into effect in -# November 2011. This modification would change the time from 12:01AM to -# 2:00AM on the dates of the switches of Daylight Savings Time to/from -# Standard Time. -# -# As a matter of reference, in Canada provinces have the authority of -# setting time zone information. The legislation has passed our -# legislative body (The House of Assembly) and is awaiting the -# proclamation to come into effect. You may find this information at: -# -# http://www.assembly.nl.ca/legislation/sr/lists/Proclamation.htm -# -# and -# search within that web page for Standard Time (Amendment) Act. The Act -# may be found at: -# -# http://www.assembly.nl.ca/business/bills/Bill1106.htm +# From Michael Pelley (2011-09-12): +# We received today, Monday, September 12, 2011, notification that the +# changes to the Newfoundland Standard Time Act have been proclaimed. +# The change in the Act stipulates that the change from Daylight Savings +# Time to Standard Time and from Standard Time to Daylight Savings Time +# now occurs at 2:00AM. +# ... +# +# http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm # # ... -# MICHAEL PELLEY | Manager of Enterprise Architecture - Solution Delivery -# Office of the Chief Information Officer Executive Council Government of -# Newfoundland & Labrador P.O. Box 8700, 40 Higgins Line, St. John's NL -# A1B 4J6 +# MICHAEL PELLEY | Manager of Enterprise Architecture - Solution Delivery +# Office of the Chief Information Officer +# Executive Council +# Government of Newfoundland & Labrador Rule StJohns 1987 only - Apr Sun>=1 0:01 1:00 D Rule StJohns 1987 2006 - Oct lastSun 0:01 0 S diff --git a/jdk/make/sun/javazic/tzdata/southamerica b/jdk/make/sun/javazic/tzdata/southamerica index 215d95defbc..0f155002da4 100644 --- a/jdk/make/sun/javazic/tzdata/southamerica +++ b/jdk/make/sun/javazic/tzdata/southamerica @@ -819,6 +819,26 @@ Zone America/La_Paz -4:32:36 - LMT 1890 # # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html # +# +# From Alexander Krivenyshev (2011-10-04): +# State Bahia will return to Daylight savings time this year after 8 years off. +# The announcement was made by Governor Jaques Wagner in an interview to a +# television station in Salvador. + +# In Portuguese: +# +# http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html +# and +# +# http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html +# + +# From Guilherme Bernardes Rodrigues (2011-10-07): +# There is news in the media, however there is still no decree about it. +# I just send a e-mail to Zulmira Brandão at +# http://pcdsh01.on.br/ the +# oficial agency about time in Brazil, and she confirmed that the old rule is +# still in force. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S # Decree 20,466 (1931-10-01) @@ -1057,6 +1077,9 @@ Zone America/Maceio -2:22:52 - LMT 1914 Zone America/Bahia -2:34:04 - LMT 1914 -3:00 Brazil BR%sT 2003 Sep 24 -3:00 - BRT +# as noted above, not yet in operation. +# -3:00 - BRT 2011 Oct 16 +# -3:00 Brazil BR%sT # # Goias (GO), Distrito Federal (DF), Minas Gerais (MG), # Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR), diff --git a/jdk/make/sun/javazic/tzdata/zone.tab b/jdk/make/sun/javazic/tzdata/zone.tab index 81ce7f5a56f..89d3c8ea835 100644 --- a/jdk/make/sun/javazic/tzdata/zone.tab +++ b/jdk/make/sun/javazic/tzdata/zone.tab @@ -341,7 +341,8 @@ PL +5215+02100 Europe/Warsaw PM +4703-05620 America/Miquelon PN -2504-13005 Pacific/Pitcairn PR +182806-0660622 America/Puerto_Rico -PS +3130+03428 Asia/Gaza +PS +3130+03428 Asia/Gaza Gaza Strip +PS +313200+0350542 Asia/Hebron West Bank PT +3843-00908 Europe/Lisbon mainland PT +3238-01654 Atlantic/Madeira Madeira Islands PT +3744-02540 Atlantic/Azores Azores diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java index c4862dc75aa..0acde8aa898 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -103,6 +103,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Eastern Daylight Time", "EDT"}; String EST_NSW[] = new String[] {"Eastern Standard Time (New South Wales)", "EST", "Eastern Summer Time (New South Wales)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Ghana Mean Time", "GMT", "Ghana Summer Time", "GHST"}; String GAMBIER[] = new String[] {"Gambier Time", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Tajikistan Summer Time", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Hovd Time", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Samara Summer Time", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Volgograd Summer Time", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java index 763f7f51fb1..7f2b91396eb 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "\u00d6stliche Sommerzeit", "EDT"}; String EST_NSW[] = new String[] {"\u00d6stliche Normalzeit (New South Wales)", "EST", "\u00d6stliche Sommerzeit (New South Wales)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Ghanaische Normalzeit", "GMT", "Ghanaische Sommerzeit", "GHST"}; String GAMBIER[] = new String[] {"Gambier Zeit", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Tadschikische Sommerzeit", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Hovd Zeit", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Samarische Sommerzeit", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { "Wolgograder Sommerzeit", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java index 1c09f1e585c..0b0beedc699 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano Oriental", "EDT"}; String EST_NSW[] = new String[] {"Hora est\u00e1ndar Oriental (Nueva Gales del Sur)", "EST", "Hora de verano Oriental (Nueva Gales del Sur)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Hora central de Ghana", "GMT", "Hora de verano de Ghana", "GHST"}; String GAMBIER[] = new String[] {"Hora de Gambier", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Tajikist\u00e1n", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Hora de Hovd", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Samara", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { "Hora de verano de Volgogrado", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java index fba1e827b0a..4816c6a07f2 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure avanc\u00e9e de l'Est", "EDT"} ; String EST_NSW[] = new String[] {"Heure normale de l'Est (Nouvelle-Galles du Sud)", "EST", "Heure d'\u00e9t\u00e9 de l'Est (Nouvelle-Galles du Sud)", "EST"} ; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Heure du Ghana", "GMT", "Heure d'\u00e9t\u00e9 du Ghana", "GHST"}; String GAMBIER[] = new String[] {"Heure de Gambi", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 du Tadjikistan", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Heure de Hovd", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Samara", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { "Heure d'\u00e9t\u00e9 de Volgograd", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java index c2bb1d673f0..b0f1efbfe04 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora legale USA orientale", "EDT"}; String EST_NSW[] = new String[] {"Ora solare dell'Australia orientale (Nuovo Galles del Sud)", "EST", "Ora estiva dell'Australia orientale (Nuovo Galles del Sud)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Ora media del Ghana", "GMT", "Ora legale del Ghana", "GHST"}; String GAMBIER[] = new String[] {"Ora di Gambier", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva del Tagikistan", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Ora di Hovd", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva di Samara", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { "Ora estiva di Volgograd", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java index a0d9d7c863f..8225fb9e8c7 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u6771\u90e8\u590f\u6642\u9593", "EDT"}; String EST_NSW[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642 (\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9\u30a6\u30a7\u30fc\u30eb\u30ba)", "EST", "\u6771\u90e8\u590f\u6642\u9593 (\u30cb\u30e5\u30fc\u30b5\u30a6\u30b9\u30a6\u30a7\u30fc\u30eb\u30ba)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"\u30ac\u30fc\u30ca\u6a19\u6e96\u6642", "GMT", "\u30ac\u30fc\u30ca\u590f\u6642\u9593", "GHST"}; String GAMBIER[] = new String[] {"\u30ac\u30f3\u30d3\u30a2\u6642\u9593", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30bf\u30b8\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"\u30db\u30d6\u30c9\u6642\u9593", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30b5\u30de\u30e9\u590f\u6642\u9593", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { "\u30dc\u30eb\u30b4\u30b0\u30e9\u30fc\u30c9\u590f\u6642\u9593", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java index 2079655f736..38ca0499024 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "EDT"}; String EST_NSW[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)", "EST", "\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04(\ub274 \uc0ac\uc6b0\uc2a4 \uc6e8\uc77c\uc988)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"\uac00\ub098 \ud45c\uc900\uc2dc", "GMT", "\uac00\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "GHST"}; String GAMBIER[] = new String[] {"\uac10\ube44\uc544 \uc2dc\uac04", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ud0c0\uc9c0\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Hovd \uc2dc\uac04", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\uc0ac\ub9c8\ub77c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { "\ubcfc\uace0\uadf8\ub77c\ub4dc \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java index 89191d0674f..5256d59a369 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java @@ -101,6 +101,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Hor\u00e1rio de luz natural oriental", "EDT"}; String EST_NSW[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental (Nova Gales do Sul)", "EST", "Fuso hor\u00e1rio de ver\u00e3o oriental (Nova Gales do Sul)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Fuso hor\u00e1rio do meridiano de Gana", "GMT", "Fuso hor\u00e1rio de ver\u00e3o de Gana", "GHST"}; String GAMBIER[] = new String[] {"Fuso hor\u00e1rio de Gambier", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o do Tadjiquist\u00e3o", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Fuso hor\u00e1rio de Hovd", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o de Samara", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { "Fuso hor\u00e1rio de ver\u00e3o de Volgogrado", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java index 007e5534a13..bb15b2a5268 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Eastern, sommartid", "EDT"}; String EST_NSW[] = new String[] {"Eastern, normaltid (Nya Sydwales)", "EST", "Eastern, sommartid (Nya Sydwales)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"Ghana, normaltid", "GMT", "Ghana, sommartid", "GHST"}; String GAMBIER[] = new String[] {"Gambier, normaltid", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Tadzjikistan, sommartid", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"Hovd, normaltid", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Samara, sommartid", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { "Volgograd, sommartid", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java index d7521372bbd..dacacf3492c 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u4e1c\u90e8\u590f\u4ee4\u65f6", "EDT"}; String EST_NSW[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09", "EST", "\u4e1c\u90e8\u590f\u4ee4\u65f6\uff08\u65b0\u5357\u5a01\u5c14\u65af\uff09", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"\u52a0\u7eb3\u65f6\u95f4", "GMT", "\u52a0\u7eb3\u590f\u4ee4\u65f6", "GHST"}; String GAMBIER[] = new String[] {"\u5188\u6bd4\u4e9a\u65f6\u95f4", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u5854\u5409\u514b\u65af\u5766\u590f\u4ee4\u65f6", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"\u79d1\u5e03\u591a\u65f6\u95f4", "HOVT", @@ -674,9 +677,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -684,7 +686,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -697,14 +699,14 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u6c99\u9a6c\u62c9\u590f\u4ee4\u65f6", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -713,7 +715,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { "\u4f0f\u5c14\u52a0\u683c\u52d2\u590f\u4ee4\u65f6", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java index 9a7fbe9479a..1c63e72bef2 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java @@ -103,6 +103,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u6771\u65b9\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "EDT"}; String EST_NSW[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593 (\u65b0\u5357\u5a01\u723e\u65af)", "EST", "\u6771\u65b9\u590f\u4ee4\u6642\u9593 (\u65b0\u5357\u5a01\u723e\u65af)", "EST"}; + String FET[] = new String[] {"Further-eastern European Time", "FET", + "Further-eastern European Summer Time", "FEST"}; String GHMT[] = new String[] {"\u8fe6\u7d0d\u5e73\u5747\u6642\u9593", "GMT", "\u8fe6\u7d0d\u590f\u4ee4\u6642\u9593", "GHST"}; String GAMBIER[] = new String[] {"\u7518\u6bd4\u723e\u6642\u9593", "GAMT", @@ -511,6 +513,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u5854\u5409\u514b\u590f\u4ee4\u6642\u9593", "TJST"}}, {"Asia/Gaza", EET}, {"Asia/Harbin", CTT}, + {"Asia/Hebron", EET}, {"Asia/Ho_Chi_Minh", ICT}, {"Asia/Hong_Kong", HKT}, {"Asia/Hovd", new String[] {"\u4faf\u5fb7 (Hovd) \u6642\u9593", "HOVT", @@ -675,9 +678,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", new String[] {"Kaliningrad Time", "KALT", - "Kaliningrad Summer Time", "KALST"}}, - {"Europe/Kiev", EET}, + {"Europe/Kaliningrad", FET}, + {"Europe/Kiev", FET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, {"Europe/London", GMTBST}, @@ -685,7 +687,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { {"Europe/Madrid", CET}, {"Europe/Malta", CET}, {"Europe/Mariehamn", EET}, - {"Europe/Minsk", EET}, + {"Europe/Minsk", FET}, {"Europe/Monaco", CET}, {"Europe/Moscow", MSK}, {"Europe/Nicosia", EET}, @@ -698,14 +700,14 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u6c99\u99ac\u62c9\u590f\u4ee4\u6642\u9593", "SAMST"}}, {"Europe/San_Marino", CET}, {"Europe/Sarajevo", CET}, - {"Europe/Simferopol", EET}, + {"Europe/Simferopol", FET}, {"Europe/Skopje", CET}, {"Europe/Sofia", EET}, {"Europe/Stockholm", CET}, {"Europe/Tallinn", EET}, {"Europe/Tirane", CET}, {"Europe/Tiraspol", EET}, - {"Europe/Uzhgorod", EET}, + {"Europe/Uzhgorod", FET}, {"Europe/Vaduz", CET}, {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, @@ -714,7 +716,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { "\u4f0f\u723e\u52a0\u683c\u52d2\u590f\u4ee4\u6642\u9593", "VOLST"}}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, - {"Europe/Zaporozhye", EET}, + {"Europe/Zaporozhye", FET}, {"Europe/Zurich", CET}, {"GB", GMTBST}, {"GB-Eire", GMTBST}, From 27ae28ada043fd66dca39379c2415ebc225130b0 Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Fri, 21 Oct 2011 18:01:01 +0900 Subject: [PATCH 18/41] 7103405: Correct display names for Pacific/Apia timezone Reviewed-by: okutsu --- jdk/src/share/classes/sun/util/resources/TimeZoneNames.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java | 2 +- .../share/classes/sun/util/resources/TimeZoneNames_pt_BR.java | 2 +- jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java | 2 +- .../share/classes/sun/util/resources/TimeZoneNames_zh_CN.java | 2 +- .../share/classes/sun/util/resources/TimeZoneNames_zh_TW.java | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java index 0acde8aa898..9a194512dfb 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java @@ -188,7 +188,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Samoa Standard Time", "SST", "Samoa Daylight Time", "SDT"}; String WST_SAMOA[] = new String[] {"West Samoa Time", "WST", - "West Samoa Summer Time", "WSST"}; + "West Samoa Daylight Time", "WSDT"}; String ChST[] = new String[] {"Chamorro Standard Time", "ChST", "Chamorro Daylight Time", "ChDT"}; String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java index 7f2b91396eb..cd6dce69060 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Samoa Normalzeit", "SST", "Samoa Sommerzeit", "SDT"}; String WST_SAMOA[] = new String[] {"West Samoa Zeit", "WST", - "West Samoa Sommerzeit", "WSST"}; + "West Samoa Sommerzeit", "WSDT"}; String ChST[] = new String[] {"Chamorro Normalzeit", "ChST", "Chamorro Sommerzeit", "ChDT"}; String VICTORIA[] = new String[] {"\u00d6stliche Normalzeit (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java index 0b0beedc699..ba28d638990 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Hora est\u00e1ndar de Samoa", "SST", "Hora de verano de Samoa", "SDT"}; String WST_SAMOA[] = new String[] {"Hora de Samoa Occidental", "WST", - "Hora de verano de Samoa Occidental", "WSST"}; + "Hora de verano de Samoa Occidental", "WSDT"}; String ChST[] = new String[] {"Hora est\u00e1ndar de Chamorro", "ChST", "Hora de verano de Chamorro", "ChDT"}; String VICTORIA[] = new String[] {"Hora est\u00e1ndar del Este (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java index 4816c6a07f2..1cb8bbcf4b8 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Heure standard de Samoa", "SST", "Heure avanc\u00e9e de Samoa", "SDT"}; String WST_SAMOA[] = new String[] {"Heure des Samoas occidentales", "WST", - "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSST"} ; + "Heure d'\u00e9t\u00e9 des Samoas occidentales", "WSDT"} ; String ChST[] = new String[] {"Heure normale des \u00eeles Mariannes", "ChST", "Heure d'\u00e9t\u00e9 des \u00eeles Mariannes", "ChDT"}; String VICTORIA[] = new String[] {"Heure standard d'Australie orientale (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java index b0f1efbfe04..216f9dc5f72 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Ora standard di Samoa", "SST", "Ora legale di Samoa", "SDT"}; String WST_SAMOA[] = new String[] {"Ora di Samoa", "WST", - "Ora estiva di Samoa", "WSST"}; + "Ora estiva di Samoa", "WSDT"}; String ChST[] = new String[] {"Ora standard di Chamorro", "ChST", "Ora legale di Chamorro", "ChDT"}; String VICTORIA[] = new String[] {"Ora orientale standard (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java index 8225fb9e8c7..fdf98fc5b4d 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"\u30b5\u30e2\u30a2\u6a19\u6e96\u6642", "SST", "\u30b5\u30e2\u30a2\u590f\u6642\u9593", "SDT"}; String WST_SAMOA[] = new String[] {"\u897f\u30b5\u30e2\u30a2\u6642\u9593", "WST", - "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSST"}; + "\u897f\u30b5\u30e2\u30a2\u590f\u6642\u9593", "WSDT"}; String ChST[] = new String[] {"\u30b0\u30a2\u30e0\u6a19\u6e96\u6642", "ChST", "\u30b0\u30a2\u30e0\u590f\u6642\u9593", "ChDT"}; String VICTORIA[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642 (\u30d3\u30af\u30c8\u30ea\u30a2)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java index 38ca0499024..060e6b3105f 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"\uc0ac\ubaa8\uc544 \ud45c\uc900\uc2dc", "SST", "\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "SDT"}; String WST_SAMOA[] = new String[] {"\uc11c\uc0ac\ubaa8\uc544 \uc2dc\uac04", "WST", - "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSST"}; + "\uc11c\uc0ac\ubaa8\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WSDT"}; String ChST[] = new String[] {"\ucc28\ubaa8\ub85c \ud45c\uc900\uc2dc", "ChST", "\ucc28\ubaa8\ub85c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ChDT"}; String VICTORIA[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc(\ube45\ud1a0\ub9ac\uc544)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java index 5256d59a369..31356369a9f 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_pt_BR.java @@ -186,7 +186,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Samoa", "SST", "Hor\u00e1rio de luz natural de Samoa", "SDT"}; String WST_SAMOA[] = new String[] {"Fuso hor\u00e1rio de Samoa Ocidental", "WST", - "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSST"}; + "Fuso hor\u00e1rio de ver\u00e3o de Samoa Ocidental", "WSDT"}; String ChST[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o de Chamorro", "ChST", "Hor\u00e1rio de luz natural de Chamorro", "ChDT"}; String VICTORIA[] = new String[] {"Fuso hor\u00e1rio padr\u00e3o oriental (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java index bb15b2a5268..f399e0d69b4 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"Samoa, normaltid", "SST", "Samoa, sommartid", "SDT"}; String WST_SAMOA[] = new String[] {"V\u00e4stsamoansk tid", "WST", - "V\u00e4stsamoansk sommartid", "WSST"}; + "V\u00e4stsamoansk sommartid", "WSDT"}; String ChST[] = new String[] {"Chamorro, normaltid", "ChST", "Chamorro, sommartid", "ChDT"}; String VICTORIA[] = new String[] {"\u00d6stlig normaltid (Victoria)", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java index dacacf3492c..28dd24f85f5 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"\u8428\u6469\u4e9a\u7fa4\u5c9b\u6807\u51c6\u65f6\u95f4", "SST", "\u8428\u6469\u4e9a\u7fa4\u5c9b\u590f\u4ee4\u65f6", "SDT"}; String WST_SAMOA[] = new String[] {"\u897f\u8428\u6469\u4e9a\u65f6\u95f4", "WST", - "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSST"}; + "\u897f\u8428\u6469\u4e9a\u590f\u4ee4\u65f6", "WSDT"}; String ChST[] = new String[] {"Chamorro \u6807\u51c6\u65f6\u95f4", "ChST", "Chamorro \u590f\u4ee4\u65f6", "ChDT"}; String VICTORIA[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4\uff08\u7ef4\u591a\u5229\u4e9a\uff09", "EST", diff --git a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java index 1c63e72bef2..bafb87e408e 100644 --- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java @@ -188,7 +188,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle { String SAMOA[] = new String[] {"\u85a9\u6469\u4e9e\u6a19\u6e96\u6642\u9593", "SST", "\u85a9\u6469\u4e9e\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "SDT"}; String WST_SAMOA[] = new String[] {"\u897f\u85a9\u6469\u4e9e\u6642\u9593", "WST", - "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSST"}; + "\u897f\u85a9\u6469\u4e9e\u590f\u4ee4\u6642\u9593", "WSDT"}; String ChST[] = new String[] {"\u67e5\u83ab\u6d1b\u6a19\u6e96\u6642\u9593", "ChST", "\u67e5\u83ab\u6d1b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "ChDT"}; String VICTORIA[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642\u9593 (\u7dad\u591a\u5229\u4e9e\u90a6)", "EST", From 5955806228a2303d22f38bb6f129bc51fc6a132a Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Fri, 21 Oct 2011 14:14:29 -0700 Subject: [PATCH 19/41] 7098530: tools/javac/javazip/Test.sh can fail on Windows Fix cygpath command to properly convert path Reviewed-by: jjg --- langtools/test/tools/javac/javazip/Test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langtools/test/tools/javac/javazip/Test.sh b/langtools/test/tools/javac/javazip/Test.sh index 896b6a8d77a..c8a59a600be 100644 --- a/langtools/test/tools/javac/javazip/Test.sh +++ b/langtools/test/tools/javac/javazip/Test.sh @@ -47,7 +47,7 @@ case "$OS" in ;; CYGWIN* ) FS="/" - SCR=`pwd | cygpath -d` + SCR=`pwd | cygpath -d -f -` ;; Windows* ) FS="\\" From 1c38082fccfcb172e86417305953116bf4a88c75 Mon Sep 17 00:00:00 2001 From: Alejandro Murillo Date: Fri, 21 Oct 2011 16:00:50 -0700 Subject: [PATCH 20/41] 7103619: Bump the hs23 build number to 04 Reviewed-by: johnc --- hotspot/make/hotspot_version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 72ac0d3920e..09ea6779834 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011 HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=03 +HS_BUILD_NUMBER=04 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 From 72c2cfef4f2fd0ba9ec3d84d9f544c4a488560f5 Mon Sep 17 00:00:00 2001 From: John Cuthbertson Date: Sun, 23 Oct 2011 23:06:06 -0700 Subject: [PATCH 21/41] 7096030: G1: PrintGCDetails enhancements 7102445: G1: Unnecessary Resource allocations during RSet scanning Add a new per-worker thread line in the PrintGCDetails output. GC Worker Other is the difference between the elapsed time for the parallel phase of the evacuation pause and the sum of the times of the sub-phases (external root scanning, mark stack scanning, RSet updating, RSet scanning, object copying, and termination) for that worker. During RSet scanning, stack allocate DirtyCardToOopClosure objects; allocating these in a resource area was causing abnormally high GC Worker Other times while the worker thread freed ResourceArea chunks. Reviewed-by: tonyp, jwilhelm, brutisso --- .../gc_implementation/g1/g1CollectedHeap.cpp | 44 ++-- .../g1/g1CollectorPolicy.cpp | 213 ++++++++++-------- .../g1/g1CollectorPolicy.hpp | 13 +- .../vm/gc_implementation/g1/g1RemSet.cpp | 10 +- .../vm/gc_implementation/g1/heapRegion.cpp | 8 - .../vm/gc_implementation/g1/heapRegion.hpp | 5 - 6 files changed, 159 insertions(+), 134 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index b8b80ae9e5d..62a5bb57b19 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -5502,34 +5502,36 @@ void G1CollectedHeap::cleanUpCardTable() { CardTableModRefBS* ct_bs = (CardTableModRefBS*) (barrier_set()); double start = os::elapsedTime(); - // Iterate over the dirty cards region list. - G1ParCleanupCTTask cleanup_task(ct_bs, this); + { + // Iterate over the dirty cards region list. + G1ParCleanupCTTask cleanup_task(ct_bs, this); - if (ParallelGCThreads > 0) { - set_par_threads(workers()->total_workers()); - workers()->run_task(&cleanup_task); - set_par_threads(0); - } else { - while (_dirty_cards_region_list) { - HeapRegion* r = _dirty_cards_region_list; - cleanup_task.clear_cards(r); - _dirty_cards_region_list = r->get_next_dirty_cards_region(); - if (_dirty_cards_region_list == r) { - // The last region. - _dirty_cards_region_list = NULL; + if (ParallelGCThreads > 0) { + set_par_threads(workers()->total_workers()); + workers()->run_task(&cleanup_task); + set_par_threads(0); + } else { + while (_dirty_cards_region_list) { + HeapRegion* r = _dirty_cards_region_list; + cleanup_task.clear_cards(r); + _dirty_cards_region_list = r->get_next_dirty_cards_region(); + if (_dirty_cards_region_list == r) { + // The last region. + _dirty_cards_region_list = NULL; + } + r->set_next_dirty_cards_region(NULL); } - r->set_next_dirty_cards_region(NULL); } +#ifndef PRODUCT + if (G1VerifyCTCleanup || VerifyAfterGC) { + G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); + heap_region_iterate(&cleanup_verifier); + } +#endif } double elapsed = os::elapsedTime() - start; g1_policy()->record_clear_ct_time(elapsed * 1000.0); -#ifndef PRODUCT - if (G1VerifyCTCleanup || VerifyAfterGC) { - G1VerifyCardTableCleanup cleanup_verifier(this, ct_bs); - heap_region_iterate(&cleanup_verifier); - } -#endif } void G1CollectedHeap::free_collection_set(HeapRegion* cs_head) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index bc575fa673e..b7fd0c190f7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -320,6 +320,7 @@ G1CollectorPolicy::G1CollectorPolicy() : _par_last_termination_attempts = new double[_parallel_gc_threads]; _par_last_gc_worker_end_times_ms = new double[_parallel_gc_threads]; _par_last_gc_worker_times_ms = new double[_parallel_gc_threads]; + _par_last_gc_worker_other_times_ms = new double[_parallel_gc_threads]; // start conservatively _expensive_region_limit_ms = 0.5 * (double) MaxGCPauseMillis; @@ -976,6 +977,7 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, _par_last_termination_attempts[i] = -1234.0; _par_last_gc_worker_end_times_ms[i] = -1234.0; _par_last_gc_worker_times_ms[i] = -1234.0; + _par_last_gc_worker_other_times_ms[i] = -1234.0; } #endif @@ -984,8 +986,10 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec, _cur_aux_times_set[i] = false; } - _satb_drain_time_set = false; - _last_satb_drain_processed_buffers = -1; + // These are initialized to zero here and they are set during + // the evacuation pause if marking is in progress. + _cur_satb_drain_time_ms = 0.0; + _last_satb_drain_processed_buffers = 0; _last_young_gc_full = false; @@ -1097,61 +1101,65 @@ void G1CollectorPolicy::print_par_sizes(int level, (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min); } -void G1CollectorPolicy::print_stats (int level, - const char* str, - double value) { +void G1CollectorPolicy::print_stats(int level, + const char* str, + double value) { LineBuffer(level).append_and_print_cr("[%s: %5.1lf ms]", str, value); } -void G1CollectorPolicy::print_stats (int level, - const char* str, - int value) { +void G1CollectorPolicy::print_stats(int level, + const char* str, + int value) { LineBuffer(level).append_and_print_cr("[%s: %d]", str, value); } -double G1CollectorPolicy::avg_value (double* data) { +double G1CollectorPolicy::avg_value(double* data) { if (G1CollectedHeap::use_parallel_gc_threads()) { double ret = 0.0; - for (uint i = 0; i < ParallelGCThreads; ++i) + for (uint i = 0; i < ParallelGCThreads; ++i) { ret += data[i]; + } return ret / (double) ParallelGCThreads; } else { return data[0]; } } -double G1CollectorPolicy::max_value (double* data) { +double G1CollectorPolicy::max_value(double* data) { if (G1CollectedHeap::use_parallel_gc_threads()) { double ret = data[0]; - for (uint i = 1; i < ParallelGCThreads; ++i) - if (data[i] > ret) + for (uint i = 1; i < ParallelGCThreads; ++i) { + if (data[i] > ret) { ret = data[i]; + } + } return ret; } else { return data[0]; } } -double G1CollectorPolicy::sum_of_values (double* data) { +double G1CollectorPolicy::sum_of_values(double* data) { if (G1CollectedHeap::use_parallel_gc_threads()) { double sum = 0.0; - for (uint i = 0; i < ParallelGCThreads; i++) + for (uint i = 0; i < ParallelGCThreads; i++) { sum += data[i]; + } return sum; } else { return data[0]; } } -double G1CollectorPolicy::max_sum (double* data1, - double* data2) { +double G1CollectorPolicy::max_sum(double* data1, double* data2) { double ret = data1[0] + data2[0]; if (G1CollectedHeap::use_parallel_gc_threads()) { for (uint i = 1; i < ParallelGCThreads; ++i) { double data = data1[i] + data2[i]; - if (data > ret) + if (data > ret) { ret = data; + } } } return ret; @@ -1251,6 +1259,10 @@ void G1CollectorPolicy::record_collection_pause_end() { _n_pauses++; + // These values are used to update the summary information that is + // displayed when TraceGen0Time is enabled, and are output as part + // of the PrintGCDetails output, in the non-parallel case. + double ext_root_scan_time = avg_value(_par_last_ext_root_scan_times_ms); double mark_stack_scan_time = avg_value(_par_last_mark_stack_scan_times_ms); double update_rs_time = avg_value(_par_last_update_rs_times_ms); @@ -1260,42 +1272,68 @@ void G1CollectorPolicy::record_collection_pause_end() { double obj_copy_time = avg_value(_par_last_obj_copy_times_ms); double termination_time = avg_value(_par_last_termination_times_ms); - double parallel_known_time = update_rs_time + - ext_root_scan_time + - mark_stack_scan_time + - scan_rs_time + - obj_copy_time + - termination_time; + double known_time = ext_root_scan_time + + mark_stack_scan_time + + update_rs_time + + scan_rs_time + + obj_copy_time; - double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time; + double other_time_ms = elapsed_ms; - PauseSummary* summary = _summary; + // Subtract the SATB drain time. It's initialized to zero at the + // start of the pause and is updated during the pause if marking + // is in progress. + other_time_ms -= _cur_satb_drain_time_ms; + + if (parallel) { + other_time_ms -= _cur_collection_par_time_ms; + } else { + other_time_ms -= known_time; + } + + // Subtract the time taken to clean the card table from the + // current value of "other time" + other_time_ms -= _cur_clear_ct_time_ms; + + // TraceGen0Time and TraceGen1Time summary info updating. + _all_pause_times_ms->add(elapsed_ms); if (update_stats) { _recent_rs_scan_times_ms->add(scan_rs_time); _recent_pause_times_ms->add(elapsed_ms); _recent_rs_sizes->add(rs_size); - MainBodySummary* body_summary = summary->main_body_summary(); - guarantee(body_summary != NULL, "should not be null!"); + _summary->record_total_time_ms(elapsed_ms); + _summary->record_other_time_ms(other_time_ms); - if (_satb_drain_time_set) - body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms); - else - body_summary->record_satb_drain_time_ms(0.0); + MainBodySummary* body_summary = _summary->main_body_summary(); + assert(body_summary != NULL, "should not be null!"); + + // This will be non-zero iff marking is currently in progress (i.e. + // _g1->mark_in_progress() == true) and the currrent pause was not + // an initial mark pause. Since the body_summary items are NumberSeqs, + // however, they have to be consistent and updated in lock-step with + // each other. Therefore we unconditionally record the SATB drain + // time - even if it's zero. + body_summary->record_satb_drain_time_ms(_cur_satb_drain_time_ms); body_summary->record_ext_root_scan_time_ms(ext_root_scan_time); body_summary->record_mark_stack_scan_time_ms(mark_stack_scan_time); body_summary->record_update_rs_time_ms(update_rs_time); body_summary->record_scan_rs_time_ms(scan_rs_time); body_summary->record_obj_copy_time_ms(obj_copy_time); + if (parallel) { body_summary->record_parallel_time_ms(_cur_collection_par_time_ms); - body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms); body_summary->record_termination_time_ms(termination_time); + + double parallel_known_time = known_time + termination_time; + double parallel_other_time = _cur_collection_par_time_ms - parallel_known_time; body_summary->record_parallel_other_time_ms(parallel_other_time); } + body_summary->record_mark_closure_time_ms(_mark_closure_time_ms); + body_summary->record_clear_ct_time_ms(_cur_clear_ct_time_ms); // We exempt parallel collection from this check because Alloc Buffer // fragmentation can produce negative collections. Same with evac @@ -1307,6 +1345,7 @@ void G1CollectorPolicy::record_collection_pause_end() { || _g1->evacuation_failed() || surviving_bytes <= _collection_set_bytes_used_before, "Or else negative collection!"); + _recent_CS_bytes_used_before->add(_collection_set_bytes_used_before); _recent_CS_bytes_surviving->add(surviving_bytes); @@ -1357,6 +1396,13 @@ void G1CollectorPolicy::record_collection_pause_end() { } } + for (int i = 0; i < _aux_num; ++i) { + if (_cur_aux_times_set[i]) { + _all_aux_times_ms[i].add(_cur_aux_times_ms[i]); + } + } + + if (G1PolicyVerbose > 1) { gclog_or_tty->print_cr(" Recording collection pause(%d)", _n_pauses); } @@ -1383,61 +1429,60 @@ void G1CollectorPolicy::record_collection_pause_end() { recent_avg_pause_time_ratio() * 100.0); } - double other_time_ms = elapsed_ms; - - if (_satb_drain_time_set) { - other_time_ms -= _cur_satb_drain_time_ms; - } - - if (parallel) { - other_time_ms -= _cur_collection_par_time_ms + _cur_clear_ct_time_ms; - } else { - other_time_ms -= - update_rs_time + - ext_root_scan_time + mark_stack_scan_time + - scan_rs_time + obj_copy_time; - } - + // PrintGCDetails output if (PrintGCDetails) { + bool print_marking_info = + _g1->mark_in_progress() && !last_pause_included_initial_mark; + gclog_or_tty->print_cr("%s, %1.8lf secs]", (last_pause_included_initial_mark) ? " (initial-mark)" : "", elapsed_ms / 1000.0); - if (_satb_drain_time_set) { + if (print_marking_info) { print_stats(1, "SATB Drain Time", _cur_satb_drain_time_ms); - } - if (_last_satb_drain_processed_buffers >= 0) { print_stats(2, "Processed Buffers", _last_satb_drain_processed_buffers); } + if (parallel) { print_stats(1, "Parallel Time", _cur_collection_par_time_ms); - print_par_stats(2, "GC Worker Start Time", _par_last_gc_worker_start_times_ms); + print_par_stats(2, "GC Worker Start", _par_last_gc_worker_start_times_ms); + print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); + if (print_marking_info) { + print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms); + } print_par_stats(2, "Update RS", _par_last_update_rs_times_ms); print_par_sizes(3, "Processed Buffers", _par_last_update_rs_processed_buffers); - print_par_stats(2, "Ext Root Scanning", _par_last_ext_root_scan_times_ms); - print_par_stats(2, "Mark Stack Scanning", _par_last_mark_stack_scan_times_ms); print_par_stats(2, "Scan RS", _par_last_scan_rs_times_ms); print_par_stats(2, "Object Copy", _par_last_obj_copy_times_ms); print_par_stats(2, "Termination", _par_last_termination_times_ms); print_par_sizes(3, "Termination Attempts", _par_last_termination_attempts); - print_par_stats(2, "GC Worker End Time", _par_last_gc_worker_end_times_ms); + print_par_stats(2, "GC Worker End", _par_last_gc_worker_end_times_ms); for (int i = 0; i < _parallel_gc_threads; i++) { _par_last_gc_worker_times_ms[i] = _par_last_gc_worker_end_times_ms[i] - _par_last_gc_worker_start_times_ms[i]; - } - print_par_stats(2, "GC Worker Times", _par_last_gc_worker_times_ms); - print_stats(2, "Parallel Other", parallel_other_time); - print_stats(1, "Clear CT", _cur_clear_ct_time_ms); + double worker_known_time = _par_last_ext_root_scan_times_ms[i] + + _par_last_mark_stack_scan_times_ms[i] + + _par_last_update_rs_times_ms[i] + + _par_last_scan_rs_times_ms[i] + + _par_last_obj_copy_times_ms[i] + + _par_last_termination_times_ms[i]; + + _par_last_gc_worker_other_times_ms[i] = _cur_collection_par_time_ms - worker_known_time; + } + print_par_stats(2, "GC Worker", _par_last_gc_worker_times_ms); + print_par_stats(2, "GC Worker Other", _par_last_gc_worker_other_times_ms); } else { - print_stats(1, "Update RS", update_rs_time); - print_stats(2, "Processed Buffers", - (int)update_rs_processed_buffers); print_stats(1, "Ext Root Scanning", ext_root_scan_time); - print_stats(1, "Mark Stack Scanning", mark_stack_scan_time); + if (print_marking_info) { + print_stats(1, "Mark Stack Scanning", mark_stack_scan_time); + } + print_stats(1, "Update RS", update_rs_time); + print_stats(2, "Processed Buffers", (int)update_rs_processed_buffers); print_stats(1, "Scan RS", scan_rs_time); print_stats(1, "Object Copying", obj_copy_time); } + print_stats(1, "Clear CT", _cur_clear_ct_time_ms); #ifndef PRODUCT print_stats(1, "Cur Clear CC", _cur_clear_cc_time_ms); print_stats(1, "Cum Clear CC", _cum_clear_cc_time_ms); @@ -1461,16 +1506,6 @@ void G1CollectorPolicy::record_collection_pause_end() { } } - _all_pause_times_ms->add(elapsed_ms); - if (update_stats) { - summary->record_total_time_ms(elapsed_ms); - summary->record_other_time_ms(other_time_ms); - } - for (int i = 0; i < _aux_num; ++i) - if (_cur_aux_times_set[i]) { - _all_aux_times_ms[i].add(_cur_aux_times_ms[i]); - } - // Update the efficiency-since-mark vars. double proc_ms = elapsed_ms * (double) _parallel_gc_threads; if (elapsed_ms < MIN_TIMER_GRANULARITY) { @@ -2138,17 +2173,17 @@ void G1CollectorPolicy::count_CS_bytes_used() { _g1->collection_set_iterate(&cs_closure); } -void G1CollectorPolicy::print_summary (int level, - const char* str, - NumberSeq* seq) const { +void G1CollectorPolicy::print_summary(int level, + const char* str, + NumberSeq* seq) const { double sum = seq->sum(); LineBuffer(level + 1).append_and_print_cr("%-24s = %8.2lf s (avg = %8.2lf ms)", str, sum / 1000.0, seq->avg()); } -void G1CollectorPolicy::print_summary_sd (int level, - const char* str, - NumberSeq* seq) const { +void G1CollectorPolicy::print_summary_sd(int level, + const char* str, + NumberSeq* seq) const { print_summary(level, str, seq); LineBuffer(level + 6).append_and_print_cr("(num = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", seq->num(), seq->sd(), seq->maximum()); @@ -2211,20 +2246,18 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { print_summary(1, "SATB Drain", body_summary->get_satb_drain_seq()); if (parallel) { print_summary(1, "Parallel Time", body_summary->get_parallel_seq()); + print_summary(2, "Ext Root Scanning", body_summary->get_ext_root_scan_seq()); + print_summary(2, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq()); print_summary(2, "Update RS", body_summary->get_update_rs_seq()); - print_summary(2, "Ext Root Scanning", - body_summary->get_ext_root_scan_seq()); - print_summary(2, "Mark Stack Scanning", - body_summary->get_mark_stack_scan_seq()); print_summary(2, "Scan RS", body_summary->get_scan_rs_seq()); print_summary(2, "Object Copy", body_summary->get_obj_copy_seq()); print_summary(2, "Termination", body_summary->get_termination_seq()); - print_summary(2, "Other", body_summary->get_parallel_other_seq()); + print_summary(2, "Parallel Other", body_summary->get_parallel_other_seq()); { NumberSeq* other_parts[] = { - body_summary->get_update_rs_seq(), body_summary->get_ext_root_scan_seq(), body_summary->get_mark_stack_scan_seq(), + body_summary->get_update_rs_seq(), body_summary->get_scan_rs_seq(), body_summary->get_obj_copy_seq(), body_summary->get_termination_seq() @@ -2234,18 +2267,16 @@ void G1CollectorPolicy::print_summary(PauseSummary* summary) const { check_other_times(2, body_summary->get_parallel_other_seq(), &calc_other_times_ms); } - print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq()); - print_summary(1, "Clear CT", body_summary->get_clear_ct_seq()); } else { + print_summary(1, "Ext Root Scanning", body_summary->get_ext_root_scan_seq()); + print_summary(1, "Mark Stack Scanning", body_summary->get_mark_stack_scan_seq()); print_summary(1, "Update RS", body_summary->get_update_rs_seq()); - print_summary(1, "Ext Root Scanning", - body_summary->get_ext_root_scan_seq()); - print_summary(1, "Mark Stack Scanning", - body_summary->get_mark_stack_scan_seq()); print_summary(1, "Scan RS", body_summary->get_scan_rs_seq()); print_summary(1, "Object Copy", body_summary->get_obj_copy_seq()); } } + print_summary(1, "Mark Closure", body_summary->get_mark_closure_seq()); + print_summary(1, "Clear CT", body_summary->get_clear_ct_seq()); print_summary(1, "Other", summary->get_other_seq()); { if (body_summary != NULL) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp index eae256f6e1a..cff48707abc 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp @@ -74,7 +74,7 @@ class MainBodySummary: public CHeapObj { define_num_seq(termination) // parallel only define_num_seq(parallel_other) // parallel only define_num_seq(mark_closure) - define_num_seq(clear_ct) // parallel only + define_num_seq(clear_ct) }; class Summary: public PauseSummary, @@ -115,7 +115,6 @@ private: double _cur_collection_par_time_ms; double _cur_satb_drain_time_ms; double _cur_clear_ct_time_ms; - bool _satb_drain_time_set; double _cur_ref_proc_time_ms; double _cur_ref_enq_time_ms; @@ -176,6 +175,11 @@ private: double* _par_last_gc_worker_end_times_ms; double* _par_last_gc_worker_times_ms; + // Each workers 'other' time i.e. the elapsed time of the parallel + // phase of the pause minus the sum of the individual sub-phase + // times for a given worker thread. + double* _par_last_gc_worker_other_times_ms; + // indicates whether we are in full young or partially young GC mode bool _full_young_gcs; @@ -892,11 +896,12 @@ public: } void record_satb_drain_time(double ms) { + assert(_g1->mark_in_progress(), "shouldn't be here otherwise"); _cur_satb_drain_time_ms = ms; - _satb_drain_time_set = true; } - void record_satb_drain_processed_buffers (int processed_buffers) { + void record_satb_drain_processed_buffers(int processed_buffers) { + assert(_g1->mark_in_progress(), "shouldn't be here otherwise"); _last_satb_drain_processed_buffers = processed_buffers; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 1e6373cf709..c24597b0b32 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -122,10 +122,10 @@ public: void set_try_claimed() { _try_claimed = true; } void scanCard(size_t index, HeapRegion *r) { - DirtyCardToOopClosure* cl = - r->new_dcto_closure(_oc, - CardTableModRefBS::Precise, - HeapRegionDCTOC::IntoCSFilterKind); + // Stack allocate the DirtyCardToOopClosure instance + HeapRegionDCTOC cl(_g1h, r, _oc, + CardTableModRefBS::Precise, + HeapRegionDCTOC::IntoCSFilterKind); // Set the "from" region in the closure. _oc->set_region(r); @@ -140,7 +140,7 @@ public: // scans (the rsets of the regions in the cset can intersect). _ct_bs->set_card_claimed(index); _cards_done++; - cl->do_MemRegion(mr); + cl.do_MemRegion(mr); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 8230e6187c7..c85611f84ac 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -340,14 +340,6 @@ void HeapRegion::reset_after_compaction() { init_top_at_mark_start(); } -DirtyCardToOopClosure* -HeapRegion::new_dcto_closure(OopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - HeapRegionDCTOC::FilterKind fk) { - return new HeapRegionDCTOC(G1CollectedHeap::heap(), - this, cl, precision, fk); -} - void HeapRegion::hr_clear(bool par, bool clear_space) { assert(_humongous_type == NotHumongous, "we should have already filtered out humongous regions"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 67e9d8905bb..7071ad495be 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -577,11 +577,6 @@ class HeapRegion: public G1OffsetTableContigSpace { // allocated in the current region before the last call to "save_mark". void oop_before_save_marks_iterate(OopClosure* cl); - DirtyCardToOopClosure* - new_dcto_closure(OopClosure* cl, - CardTableModRefBS::PrecisionStyle precision, - HeapRegionDCTOC::FilterKind fk); - // Note the start or end of marking. This tells the heap region // that the collector is about to start or has finished (concurrently) // marking the heap. From 063b622daf428d6d78988fb3adba57cdbff5154a Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 24 Oct 2011 13:00:20 +0100 Subject: [PATCH 22/41] 7096014: Javac tokens should retain state Refactor javac tokens from enum constants to stateful instances (to keep track of position, comments, etc.) Reviewed-by: jjg --- .../sun/tools/apt/main/AptJavaCompiler.java | 1 - .../sun/tools/javac/parser/EndPosParser.java | 6 +- .../sun/tools/javac/parser/JavaTokenizer.java | 896 ++++++++++++++ .../sun/tools/javac/parser/JavacParser.java | 1033 ++++++++-------- ...mentScanner.java => JavadocTokenizer.java} | 46 +- .../com/sun/tools/javac/parser/Keywords.java | 98 -- .../com/sun/tools/javac/parser/Lexer.java | 89 +- .../sun/tools/javac/parser/ParserFactory.java | 4 +- .../com/sun/tools/javac/parser/Scanner.java | 1085 +---------------- .../tools/javac/parser/ScannerFactory.java | 8 +- .../com/sun/tools/javac/parser/Token.java | 198 --- .../com/sun/tools/javac/parser/Tokens.java | 423 +++++++ .../sun/tools/javac/parser/UnicodeReader.java | 227 ++++ .../JavacProcessingEnvironment.java | 6 +- .../com/sun/tools/javadoc/JavadocTool.java | 1 - .../tools/javac/api/TestJavacTaskScanner.java | 6 +- .../depDocComment/DeprecatedDocComment3.java | 41 + .../javac/tree/DocCommentToplevelTest.java | 196 +++ 18 files changed, 2370 insertions(+), 1994 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java rename langtools/src/share/classes/com/sun/tools/javac/parser/{DocCommentScanner.java => JavadocTokenizer.java} (94%) delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/parser/Token.java create mode 100644 langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java create mode 100644 langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java create mode 100644 langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java create mode 100644 langtools/test/tools/javac/tree/DocCommentToplevelTest.java diff --git a/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java b/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java index 89658e2bfe3..32d10ab50c5 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/apt/main/AptJavaCompiler.java @@ -42,7 +42,6 @@ import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.apt.comp.*; import com.sun.tools.apt.util.Bark; import com.sun.mirror.apt.AnnotationProcessorFactory; -import com.sun.tools.javac.parser.DocCommentScanner; /** *

This is NOT part of any supported API. diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java index 715839bd776..e428f6e0b54 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java @@ -67,14 +67,14 @@ public class EndPosParser extends JavacParser { /** {@inheritDoc} */ @Override protected T to(T t) { - storeEnd(t, S.endPos()); + storeEnd(t, token.endPos); return t; } /** {@inheritDoc} */ @Override protected T toP(T t) { - storeEnd(t, S.prevEndPos()); + storeEnd(t, S.prevToken().endPos); return t; } @@ -88,7 +88,7 @@ public class EndPosParser extends JavacParser { /** {@inheritDoc} */ @Override JCExpression parExpression() { - int pos = S.pos(); + int pos = token.pos; JCExpression t = super.parExpression(); return toP(F.at(pos).Parens(t)); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java new file mode 100644 index 00000000000..f5a99ae9fa4 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavaTokenizer.java @@ -0,0 +1,896 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.parser; + +import java.nio.CharBuffer; +import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.util.*; + + +import static com.sun.tools.javac.parser.Tokens.*; +import static com.sun.tools.javac.util.LayoutCharacters.*; + +/** The lexical analyzer maps an input stream consisting of + * ASCII characters and Unicode escapes into a token sequence. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class JavaTokenizer { + + private static boolean scannerDebug = false; + + /** Allow hex floating-point literals. + */ + private boolean allowHexFloats; + + /** Allow binary literals. + */ + private boolean allowBinaryLiterals; + + /** Allow underscores in literals. + */ + private boolean allowUnderscoresInLiterals; + + /** The source language setting. + */ + private Source source; + + /** The log to be used for error reporting. + */ + private final Log log; + + /** The name table. */ + private final Names names; + + /** The token factory. */ + private final Tokens tokens; + + /** The token kind, set by nextToken(). + */ + protected TokenKind tk; + + /** The token's radix, set by nextToken(). + */ + protected int radix; + + /** The token's name, set by nextToken(). + */ + protected Name name; + + /** The position where a lexical error occurred; + */ + protected int errPos = Position.NOPOS; + + /** Has a @deprecated been encountered in last doc comment? + * this needs to be reset by client. + */ + protected boolean deprecatedFlag = false; + + /** A character buffer for saved chars. + */ + protected char[] sbuf = new char[128]; + protected int sp; + + protected UnicodeReader reader; + + private static final boolean hexFloatsWork = hexFloatsWork(); + private static boolean hexFloatsWork() { + try { + Float.valueOf("0x1.0p1"); + return true; + } catch (NumberFormatException ex) { + return false; + } + } + + /** + * Create a scanner from the input array. This method might + * modify the array. To avoid copying the input array, ensure + * that {@code inputLength < input.length} or + * {@code input[input.length -1]} is a white space character. + * + * @param fac the factory which created this Scanner + * @param input the input, might be modified + * @param inputLength the size of the input. + * Must be positive and less than or equal to input.length. + */ + protected JavaTokenizer(ScannerFactory fac, CharBuffer buf) { + this(fac, new UnicodeReader(fac, buf)); + } + + protected JavaTokenizer(ScannerFactory fac, char[] buf, int inputLength) { + this(fac, new UnicodeReader(fac, buf, inputLength)); + } + + protected JavaTokenizer(ScannerFactory fac, UnicodeReader reader) { + log = fac.log; + names = fac.names; + tokens = fac.tokens; + source = fac.source; + this.reader = reader; + allowBinaryLiterals = source.allowBinaryLiterals(); + allowHexFloats = source.allowHexFloats(); + allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); + } + + /** Report an error at the given position using the provided arguments. + */ + protected void lexError(int pos, String key, Object... args) { + log.error(pos, key, args); + tk = TokenKind.ERROR; + errPos = pos; + } + + /** Read next character in comment, skipping over double '\' characters. + */ + protected void scanCommentChar() { + reader.scanChar(); + if (reader.ch == '\\') { + if (reader.peekChar() == '\\' && !reader.isUnicode()) { + reader.skipChar(); + } else { + reader.convertUnicode(); + } + } + } + + /** Append a character to sbuf. + */ + private void putChar(char ch) { + if (sp == sbuf.length) { + char[] newsbuf = new char[sbuf.length * 2]; + System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); + sbuf = newsbuf; + } + sbuf[sp++] = ch; + } + + /** Read next character in character or string literal and copy into sbuf. + */ + private void scanLitChar(int pos) { + if (reader.ch == '\\') { + if (reader.peekChar() == '\\' && !reader.isUnicode()) { + reader.skipChar(); + putChar('\\'); + reader.scanChar(); + } else { + reader.scanChar(); + switch (reader.ch) { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + char leadch = reader.ch; + int oct = reader.digit(pos, 8); + reader.scanChar(); + if ('0' <= reader.ch && reader.ch <= '7') { + oct = oct * 8 + reader.digit(pos, 8); + reader.scanChar(); + if (leadch <= '3' && '0' <= reader.ch && reader.ch <= '7') { + oct = oct * 8 + reader.digit(pos, 8); + reader.scanChar(); + } + } + putChar((char)oct); + break; + case 'b': + putChar('\b'); reader.scanChar(); break; + case 't': + putChar('\t'); reader.scanChar(); break; + case 'n': + putChar('\n'); reader.scanChar(); break; + case 'f': + putChar('\f'); reader.scanChar(); break; + case 'r': + putChar('\r'); reader.scanChar(); break; + case '\'': + putChar('\''); reader.scanChar(); break; + case '\"': + putChar('\"'); reader.scanChar(); break; + case '\\': + putChar('\\'); reader.scanChar(); break; + default: + lexError(reader.bp, "illegal.esc.char"); + } + } + } else if (reader.bp != reader.buflen) { + putChar(reader.ch); reader.scanChar(); + } + } + + private void scanDigits(int pos, int digitRadix) { + char saveCh; + int savePos; + do { + if (reader.ch != '_') { + putChar(reader.ch); + } else { + if (!allowUnderscoresInLiterals) { + lexError(pos, "unsupported.underscore.lit", source.name); + allowUnderscoresInLiterals = true; + } + } + saveCh = reader.ch; + savePos = reader.bp; + reader.scanChar(); + } while (reader.digit(pos, digitRadix) >= 0 || reader.ch == '_'); + if (saveCh == '_') + lexError(savePos, "illegal.underscore"); + } + + /** Read fractional part of hexadecimal floating point number. + */ + private void scanHexExponentAndSuffix(int pos) { + if (reader.ch == 'p' || reader.ch == 'P') { + putChar(reader.ch); + reader.scanChar(); + skipIllegalUnderscores(); + if (reader.ch == '+' || reader.ch == '-') { + putChar(reader.ch); + reader.scanChar(); + } + skipIllegalUnderscores(); + if ('0' <= reader.ch && reader.ch <= '9') { + scanDigits(pos, 10); + if (!allowHexFloats) { + lexError(pos, "unsupported.fp.lit", source.name); + allowHexFloats = true; + } + else if (!hexFloatsWork) + lexError(pos, "unsupported.cross.fp.lit"); + } else + lexError(pos, "malformed.fp.lit"); + } else { + lexError(pos, "malformed.fp.lit"); + } + if (reader.ch == 'f' || reader.ch == 'F') { + putChar(reader.ch); + reader.scanChar(); + tk = TokenKind.FLOATLITERAL; + radix = 16; + } else { + if (reader.ch == 'd' || reader.ch == 'D') { + putChar(reader.ch); + reader.scanChar(); + } + tk = TokenKind.DOUBLELITERAL; + radix = 16; + } + } + + /** Read fractional part of floating point number. + */ + private void scanFraction(int pos) { + skipIllegalUnderscores(); + if ('0' <= reader.ch && reader.ch <= '9') { + scanDigits(pos, 10); + } + int sp1 = sp; + if (reader.ch == 'e' || reader.ch == 'E') { + putChar(reader.ch); + reader.scanChar(); + skipIllegalUnderscores(); + if (reader.ch == '+' || reader.ch == '-') { + putChar(reader.ch); + reader.scanChar(); + } + skipIllegalUnderscores(); + if ('0' <= reader.ch && reader.ch <= '9') { + scanDigits(pos, 10); + return; + } + lexError(pos, "malformed.fp.lit"); + sp = sp1; + } + } + + /** Read fractional part and 'd' or 'f' suffix of floating point number. + */ + private void scanFractionAndSuffix(int pos) { + radix = 10; + scanFraction(pos); + if (reader.ch == 'f' || reader.ch == 'F') { + putChar(reader.ch); + reader.scanChar(); + tk = TokenKind.FLOATLITERAL; + } else { + if (reader.ch == 'd' || reader.ch == 'D') { + putChar(reader.ch); + reader.scanChar(); + } + tk = TokenKind.DOUBLELITERAL; + } + } + + /** Read fractional part and 'd' or 'f' suffix of floating point number. + */ + private void scanHexFractionAndSuffix(int pos, boolean seendigit) { + radix = 16; + Assert.check(reader.ch == '.'); + putChar(reader.ch); + reader.scanChar(); + skipIllegalUnderscores(); + if (reader.digit(pos, 16) >= 0) { + seendigit = true; + scanDigits(pos, 16); + } + if (!seendigit) + lexError(pos, "invalid.hex.number"); + else + scanHexExponentAndSuffix(pos); + } + + private void skipIllegalUnderscores() { + if (reader.ch == '_') { + lexError(reader.bp, "illegal.underscore"); + while (reader.ch == '_') + reader.scanChar(); + } + } + + /** Read a number. + * @param radix The radix of the number; one of 2, j8, 10, 16. + */ + private void scanNumber(int pos, int radix) { + // for octal, allow base-10 digit in case it's a float literal + this.radix = radix; + int digitRadix = (radix == 8 ? 10 : radix); + boolean seendigit = false; + if (reader.digit(pos, digitRadix) >= 0) { + seendigit = true; + scanDigits(pos, digitRadix); + } + if (radix == 16 && reader.ch == '.') { + scanHexFractionAndSuffix(pos, seendigit); + } else if (seendigit && radix == 16 && (reader.ch == 'p' || reader.ch == 'P')) { + scanHexExponentAndSuffix(pos); + } else if (digitRadix == 10 && reader.ch == '.') { + putChar(reader.ch); + reader.scanChar(); + scanFractionAndSuffix(pos); + } else if (digitRadix == 10 && + (reader.ch == 'e' || reader.ch == 'E' || + reader.ch == 'f' || reader.ch == 'F' || + reader.ch == 'd' || reader.ch == 'D')) { + scanFractionAndSuffix(pos); + } else { + if (reader.ch == 'l' || reader.ch == 'L') { + reader.scanChar(); + tk = TokenKind.LONGLITERAL; + } else { + tk = TokenKind.INTLITERAL; + } + } + } + + /** Read an identifier. + */ + private void scanIdent() { + boolean isJavaIdentifierPart; + char high; + do { + if (sp == sbuf.length) putChar(reader.ch); else sbuf[sp++] = reader.ch; + // optimization, was: putChar(reader.ch); + + reader.scanChar(); + switch (reader.ch) { + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case '$': case '_': + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case '\u0000': case '\u0001': case '\u0002': case '\u0003': + case '\u0004': case '\u0005': case '\u0006': case '\u0007': + case '\u0008': case '\u000E': case '\u000F': case '\u0010': + case '\u0011': case '\u0012': case '\u0013': case '\u0014': + case '\u0015': case '\u0016': case '\u0017': + case '\u0018': case '\u0019': case '\u001B': + case '\u007F': + break; + case '\u001A': // EOI is also a legal identifier part + if (reader.bp >= reader.buflen) { + name = names.fromChars(sbuf, 0, sp); + tk = tokens.lookupKind(name); + return; + } + break; + default: + if (reader.ch < '\u0080') { + // all ASCII range chars already handled, above + isJavaIdentifierPart = false; + } else { + high = reader.scanSurrogates(); + if (high != 0) { + if (sp == sbuf.length) { + putChar(high); + } else { + sbuf[sp++] = high; + } + isJavaIdentifierPart = Character.isJavaIdentifierPart( + Character.toCodePoint(high, reader.ch)); + } else { + isJavaIdentifierPart = Character.isJavaIdentifierPart(reader.ch); + } + } + if (!isJavaIdentifierPart) { + name = names.fromChars(sbuf, 0, sp); + tk = tokens.lookupKind(name); + return; + } + } + } while (true); + } + + /** Return true if reader.ch can be part of an operator. + */ + private boolean isSpecial(char ch) { + switch (ch) { + case '!': case '%': case '&': case '*': case '?': + case '+': case '-': case ':': case '<': case '=': + case '>': case '^': case '|': case '~': + case '@': + return true; + default: + return false; + } + } + + /** Read longest possible sequence of special characters and convert + * to token. + */ + private void scanOperator() { + while (true) { + putChar(reader.ch); + Name newname = names.fromChars(sbuf, 0, sp); + TokenKind tk1 = tokens.lookupKind(newname); + if (tk1 == TokenKind.IDENTIFIER) { + sp--; + break; + } + tk = tk1; + reader.scanChar(); + if (!isSpecial(reader.ch)) break; + } + } + + /** + * Scan a documentation comment; determine if a deprecated tag is present. + * Called once the initial /, * have been skipped, positioned at the second * + * (which is treated as the beginning of the first line). + * Stops positioned at the closing '/'. + */ + @SuppressWarnings("fallthrough") + private void scanDocComment() { + boolean deprecatedPrefix = false; + + forEachLine: + while (reader.bp < reader.buflen) { + + // Skip optional WhiteSpace at beginning of line + while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) { + scanCommentChar(); + } + + // Skip optional consecutive Stars + while (reader.bp < reader.buflen && reader.ch == '*') { + scanCommentChar(); + if (reader.ch == '/') { + return; + } + } + + // Skip optional WhiteSpace after Stars + while (reader.bp < reader.buflen && (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF)) { + scanCommentChar(); + } + + deprecatedPrefix = false; + // At beginning of line in the JavaDoc sense. + if (reader.bp < reader.buflen && reader.ch == '@' && !deprecatedFlag) { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'd') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'e') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'p') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'r') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'e') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'c') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'a') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 't') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'e') { + scanCommentChar(); + if (reader.bp < reader.buflen && reader.ch == 'd') { + deprecatedPrefix = true; + scanCommentChar(); + }}}}}}}}}}} + if (deprecatedPrefix && reader.bp < reader.buflen) { + if (Character.isWhitespace(reader.ch)) { + deprecatedFlag = true; + } else if (reader.ch == '*') { + scanCommentChar(); + if (reader.ch == '/') { + deprecatedFlag = true; + return; + } + } + } + + // Skip rest of line + while (reader.bp < reader.buflen) { + switch (reader.ch) { + case '*': + scanCommentChar(); + if (reader.ch == '/') { + return; + } + break; + case CR: // (Spec 3.4) + scanCommentChar(); + if (reader.ch != LF) { + continue forEachLine; + } + /* fall through to LF case */ + case LF: // (Spec 3.4) + scanCommentChar(); + continue forEachLine; + default: + scanCommentChar(); + } + } // rest of line + } // forEachLine + return; + } + + /** Read token. + */ + public Token readToken() { + + sp = 0; + name = null; + deprecatedFlag = false; + radix = 0; + int pos = 0; + int endPos = 0; + + try { + loop: while (true) { + pos = reader.bp; + switch (reader.ch) { + case ' ': // (Spec 3.6) + case '\t': // (Spec 3.6) + case FF: // (Spec 3.6) + do { + reader.scanChar(); + } while (reader.ch == ' ' || reader.ch == '\t' || reader.ch == FF); + processWhiteSpace(pos, reader.bp); + break; + case LF: // (Spec 3.4) + reader.scanChar(); + processLineTerminator(pos, reader.bp); + break; + case CR: // (Spec 3.4) + reader.scanChar(); + if (reader.ch == LF) { + reader.scanChar(); + } + processLineTerminator(pos, reader.bp); + break; + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': + case 'Z': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': + case 'z': + case '$': case '_': + scanIdent(); + break loop; + case '0': + reader.scanChar(); + if (reader.ch == 'x' || reader.ch == 'X') { + reader.scanChar(); + skipIllegalUnderscores(); + if (reader.ch == '.') { + scanHexFractionAndSuffix(pos, false); + } else if (reader.digit(pos, 16) < 0) { + lexError(pos, "invalid.hex.number"); + } else { + scanNumber(pos, 16); + } + } else if (reader.ch == 'b' || reader.ch == 'B') { + if (!allowBinaryLiterals) { + lexError(pos, "unsupported.binary.lit", source.name); + allowBinaryLiterals = true; + } + reader.scanChar(); + skipIllegalUnderscores(); + if (reader.digit(pos, 2) < 0) { + lexError(pos, "invalid.binary.number"); + } else { + scanNumber(pos, 2); + } + } else { + putChar('0'); + if (reader.ch == '_') { + int savePos = reader.bp; + do { + reader.scanChar(); + } while (reader.ch == '_'); + if (reader.digit(pos, 10) < 0) { + lexError(savePos, "illegal.underscore"); + } + } + scanNumber(pos, 8); + } + break loop; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + scanNumber(pos, 10); + break loop; + case '.': + reader.scanChar(); + if ('0' <= reader.ch && reader.ch <= '9') { + putChar('.'); + scanFractionAndSuffix(pos); + } else if (reader.ch == '.') { + putChar('.'); putChar('.'); + reader.scanChar(); + if (reader.ch == '.') { + reader.scanChar(); + putChar('.'); + tk = TokenKind.ELLIPSIS; + } else { + lexError(pos, "malformed.fp.lit"); + } + } else { + tk = TokenKind.DOT; + } + break loop; + case ',': + reader.scanChar(); tk = TokenKind.COMMA; break loop; + case ';': + reader.scanChar(); tk = TokenKind.SEMI; break loop; + case '(': + reader.scanChar(); tk = TokenKind.LPAREN; break loop; + case ')': + reader.scanChar(); tk = TokenKind.RPAREN; break loop; + case '[': + reader.scanChar(); tk = TokenKind.LBRACKET; break loop; + case ']': + reader.scanChar(); tk = TokenKind.RBRACKET; break loop; + case '{': + reader.scanChar(); tk = TokenKind.LBRACE; break loop; + case '}': + reader.scanChar(); tk = TokenKind.RBRACE; break loop; + case '/': + reader.scanChar(); + if (reader.ch == '/') { + do { + scanCommentChar(); + } while (reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen); + if (reader.bp < reader.buflen) { + processComment(pos, reader.bp, CommentStyle.LINE); + } + break; + } else if (reader.ch == '*') { + reader.scanChar(); + CommentStyle style; + if (reader.ch == '*') { + style = CommentStyle.JAVADOC; + scanDocComment(); + } else { + style = CommentStyle.BLOCK; + while (reader.bp < reader.buflen) { + if (reader.ch == '*') { + reader.scanChar(); + if (reader.ch == '/') break; + } else { + scanCommentChar(); + } + } + } + if (reader.ch == '/') { + reader.scanChar(); + processComment(pos, reader.bp, style); + break; + } else { + lexError(pos, "unclosed.comment"); + break loop; + } + } else if (reader.ch == '=') { + tk = TokenKind.SLASHEQ; + reader.scanChar(); + } else { + tk = TokenKind.SLASH; + } + break loop; + case '\'': + reader.scanChar(); + if (reader.ch == '\'') { + lexError(pos, "empty.char.lit"); + } else { + if (reader.ch == CR || reader.ch == LF) + lexError(pos, "illegal.line.end.in.char.lit"); + scanLitChar(pos); + char ch2 = reader.ch; + if (reader.ch == '\'') { + reader.scanChar(); + tk = TokenKind.CHARLITERAL; + } else { + lexError(pos, "unclosed.char.lit"); + } + } + break loop; + case '\"': + reader.scanChar(); + while (reader.ch != '\"' && reader.ch != CR && reader.ch != LF && reader.bp < reader.buflen) + scanLitChar(pos); + if (reader.ch == '\"') { + tk = TokenKind.STRINGLITERAL; + reader.scanChar(); + } else { + lexError(pos, "unclosed.str.lit"); + } + break loop; + default: + if (isSpecial(reader.ch)) { + scanOperator(); + } else { + boolean isJavaIdentifierStart; + if (reader.ch < '\u0080') { + // all ASCII range chars already handled, above + isJavaIdentifierStart = false; + } else { + char high = reader.scanSurrogates(); + if (high != 0) { + if (sp == sbuf.length) { + putChar(high); + } else { + sbuf[sp++] = high; + } + + isJavaIdentifierStart = Character.isJavaIdentifierStart( + Character.toCodePoint(high, reader.ch)); + } else { + isJavaIdentifierStart = Character.isJavaIdentifierStart(reader.ch); + } + } + if (isJavaIdentifierStart) { + scanIdent(); + } else if (reader.bp == reader.buflen || reader.ch == EOI && reader.bp + 1 == reader.buflen) { // JLS 3.5 + tk = TokenKind.EOF; + pos = reader.buflen; + } else { + lexError(pos, "illegal.char", String.valueOf((int)reader.ch)); + reader.scanChar(); + } + } + break loop; + } + } + endPos = reader.bp; + switch (tk.tag) { + case DEFAULT: return new Token(tk, pos, endPos, deprecatedFlag); + case NAMED: return new NamedToken(tk, pos, endPos, name, deprecatedFlag); + case STRING: return new StringToken(tk, pos, endPos, new String(sbuf, 0, sp), deprecatedFlag); + case NUMERIC: return new NumericToken(tk, pos, endPos, new String(sbuf, 0, sp), radix, deprecatedFlag); + default: throw new AssertionError(); + } + } + finally { + if (scannerDebug) { + System.out.println("nextToken(" + pos + + "," + endPos + ")=|" + + new String(reader.getRawCharacters(pos, endPos)) + + "|"); + } + } + } + + /** Return the position where a lexical error occurred; + */ + public int errPos() { + return errPos; + } + + /** Set the position where a lexical error occurred; + */ + public void errPos(int pos) { + errPos = pos; + } + + public enum CommentStyle { + LINE, + BLOCK, + JAVADOC, + } + + /** + * Called when a complete comment has been scanned. pos and endPos + * will mark the comment boundary. + */ + protected void processComment(int pos, int endPos, CommentStyle style) { + if (scannerDebug) + System.out.println("processComment(" + pos + + "," + endPos + "," + style + ")=|" + + new String(reader.getRawCharacters(pos, endPos)) + + "|"); + } + + /** + * Called when a complete whitespace run has been scanned. pos and endPos + * will mark the whitespace boundary. + */ + protected void processWhiteSpace(int pos, int endPos) { + if (scannerDebug) + System.out.println("processWhitespace(" + pos + + "," + endPos + ")=|" + + new String(reader.getRawCharacters(pos, endPos)) + + "|"); + } + + /** + * Called when a line terminator has been processed. + */ + protected void processLineTerminator(int pos, int endPos) { + if (scannerDebug) + System.out.println("processTerminator(" + pos + + "," + endPos + ")=|" + + new String(reader.getRawCharacters(pos, endPos)) + + "|"); + } + + /** Build a map for translating between line numbers and + * positions in the input. + * + * @return a LineMap */ + public Position.LineMap getLineMap() { + return Position.makeLineMap(reader.getRawCharacters(), reader.buflen, false); + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 2151a67cdd5..9c754978a56 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -28,6 +28,7 @@ package com.sun.tools.javac.parser; import java.util.*; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.parser.Tokens.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.*; @@ -36,7 +37,7 @@ 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 static com.sun.tools.javac.parser.Token.*; +import static com.sun.tools.javac.parser.Tokens.TokenKind.*; /** The parser maps a token sequence into an abstract syntax * tree. It operates by recursive descent, with code derived @@ -67,9 +68,6 @@ public class JavacParser implements Parser { */ private Log log; - /** The keyword table. */ - private Keywords keywords; - /** The Source language setting. */ private Source source; @@ -83,11 +81,10 @@ public class JavacParser implements Parser { boolean keepDocComments, boolean keepLineMap) { this.S = S; - S.nextToken(); // prime the pump + nextToken(); // prime the pump this.F = fac.F; this.log = fac.log; this.names = fac.names; - this.keywords = fac.keywords; this.source = fac.source; this.allowGenerics = source.allowGenerics(); this.allowVarargs = source.allowVarargs(); @@ -178,7 +175,16 @@ public class JavacParser implements Parser { */ private int lastmode = 0; -/* ---------- error recovery -------------- */ + /* ---------- token management -------------- */ + + protected Token token; + + protected void nextToken() { + S.nextToken(); + token = S.token(); + } + + /* ---------- error recovery -------------- */ private JCErroneous errorTree; @@ -186,9 +192,9 @@ public class JavacParser implements Parser { */ private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { while (true) { - switch (S.token()) { + switch (token.kind) { case SEMI: - S.nextToken(); + nextToken(); return; case PUBLIC: case FINAL: @@ -249,15 +255,15 @@ public class JavacParser implements Parser { return; break; } - S.nextToken(); + nextToken(); } } - private JCErroneous syntaxError(int pos, String key, Token... args) { + private JCErroneous syntaxError(int pos, String key, TokenKind... args) { return syntaxError(pos, List.nil(), key, args); } - private JCErroneous syntaxError(int pos, List errs, String key, Token... args) { + private JCErroneous syntaxError(int pos, List errs, String key, TokenKind... args) { setErrorEndPos(pos); JCErroneous err = F.at(pos).Erroneous(errs); reportSyntaxError(err, key, (Object[])args); @@ -287,16 +293,16 @@ public class JavacParser implements Parser { 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) { + if (token.kind == EOF) { error(diagPos, "premature.eof"); } else { error(diagPos, key, args); } } S.errPos(pos); - if (S.pos() == errorPos) - S.nextToken(); // guarantee progress - errorPos = S.pos(); + if (token.pos == errorPos) + nextToken(); // guarantee progress + errorPos = token.pos; } @@ -304,25 +310,25 @@ public class JavacParser implements Parser { * reported at the same position. */ private JCErroneous syntaxError(String key) { - return syntaxError(S.pos(), key); + return syntaxError(token.pos, key); } /** Generate a syntax error at current position unless one was * already reported at the same position. */ - private JCErroneous syntaxError(String key, Token arg) { - return syntaxError(S.pos(), key, arg); + private JCErroneous syntaxError(String key, TokenKind arg) { + return syntaxError(token.pos, key, arg); } /** If next input token matches given token, skip it, otherwise report * an error. */ - public void accept(Token token) { - if (S.token() == token) { - S.nextToken(); + public void accept(TokenKind tk) { + if (token.kind == tk) { + nextToken(); } else { - setErrorEndPos(S.pos()); - reportSyntaxError(S.prevEndPos(), "expected", token); + setErrorEndPos(token.pos); + reportSyntaxError(S.prevToken().endPos, "expected", tk); } } @@ -340,14 +346,14 @@ public class JavacParser implements Parser { /** Report an illegal start of expression/type error at current position. */ JCExpression illegal() { - return illegal(S.pos()); + return illegal(token.pos); } /** Diagnose a modifier flag from the set, if any. */ void checkNoMods(long mods) { if (mods != 0) { long lowestMod = mods & -mods; - error(S.pos(), "mod.not.allowed.here", + error(token.pos, "mod.not.allowed.here", Flags.asFlagSet(lowestMod)); } } @@ -435,30 +441,30 @@ public class JavacParser implements Parser { * Ident = IDENTIFIER */ Name ident() { - if (S.token() == IDENTIFIER) { - Name name = S.name(); - S.nextToken(); + if (token.kind == IDENTIFIER) { + Name name = token.name(); + nextToken(); return name; - } else if (S.token() == ASSERT) { + } else if (token.kind == ASSERT) { if (allowAsserts) { - error(S.pos(), "assert.as.identifier"); - S.nextToken(); + error(token.pos, "assert.as.identifier"); + nextToken(); return names.error; } else { - warning(S.pos(), "assert.as.identifier"); - Name name = S.name(); - S.nextToken(); + warning(token.pos, "assert.as.identifier"); + Name name = token.name(); + nextToken(); return name; } - } else if (S.token() == ENUM) { + } else if (token.kind == ENUM) { if (allowEnums) { - error(S.pos(), "enum.as.identifier"); - S.nextToken(); + error(token.pos, "enum.as.identifier"); + nextToken(); return names.error; } else { - warning(S.pos(), "enum.as.identifier"); - Name name = S.name(); - S.nextToken(); + warning(token.pos, "enum.as.identifier"); + Name name = token.name(); + nextToken(); return name; } } else { @@ -471,17 +477,17 @@ public class JavacParser implements Parser { * Qualident = Ident { DOT Ident } */ public JCExpression qualident() { - JCExpression t = toP(F.at(S.pos()).Ident(ident())); - while (S.token() == DOT) { - int pos = S.pos(); - S.nextToken(); + JCExpression t = toP(F.at(token.pos).Ident(ident())); + while (token.kind == DOT) { + int pos = token.pos; + nextToken(); t = toP(F.at(pos).Select(t, ident())); } return t; } JCExpression literal(Name prefix) { - return literal(prefix, S.pos()); + return literal(prefix, token.pos); } /** @@ -498,27 +504,29 @@ public class JavacParser implements Parser { */ JCExpression literal(Name prefix, int pos) { JCExpression t = errorTree; - switch (S.token()) { + switch (token.kind) { case INTLITERAL: try { t = F.at(pos).Literal( TypeTags.INT, - Convert.string2int(strval(prefix), S.radix())); + Convert.string2int(strval(prefix), token.radix())); } catch (NumberFormatException ex) { - error(S.pos(), "int.number.too.large", strval(prefix)); + error(token.pos, "int.number.too.large", strval(prefix)); } break; case LONGLITERAL: try { t = F.at(pos).Literal( TypeTags.LONG, - new Long(Convert.string2long(strval(prefix), S.radix()))); + new Long(Convert.string2long(strval(prefix), token.radix()))); } catch (NumberFormatException ex) { - error(S.pos(), "int.number.too.large", strval(prefix)); + error(token.pos, "int.number.too.large", strval(prefix)); } break; case FLOATLITERAL: { - String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); + String proper = token.radix() == 16 ? + ("0x"+ token.stringVal()) : + token.stringVal(); Float n; try { n = Float.valueOf(proper); @@ -527,15 +535,17 @@ public class JavacParser implements Parser { n = Float.NaN; } if (n.floatValue() == 0.0f && !isZero(proper)) - error(S.pos(), "fp.number.too.small"); + error(token.pos, "fp.number.too.small"); else if (n.floatValue() == Float.POSITIVE_INFINITY) - error(S.pos(), "fp.number.too.large"); + error(token.pos, "fp.number.too.large"); else t = F.at(pos).Literal(TypeTags.FLOAT, n); break; } case DOUBLELITERAL: { - String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); + String proper = token.radix() == 16 ? + ("0x"+ token.stringVal()) : + token.stringVal(); Double n; try { n = Double.valueOf(proper); @@ -544,9 +554,9 @@ public class JavacParser implements Parser { n = Double.NaN; } if (n.doubleValue() == 0.0d && !isZero(proper)) - error(S.pos(), "fp.number.too.small"); + error(token.pos, "fp.number.too.small"); else if (n.doubleValue() == Double.POSITIVE_INFINITY) - error(S.pos(), "fp.number.too.large"); + error(token.pos, "fp.number.too.large"); else t = F.at(pos).Literal(TypeTags.DOUBLE, n); break; @@ -554,17 +564,17 @@ public class JavacParser implements Parser { case CHARLITERAL: t = F.at(pos).Literal( TypeTags.CHAR, - S.stringVal().charAt(0) + 0); + token.stringVal().charAt(0) + 0); break; case STRINGLITERAL: t = F.at(pos).Literal( TypeTags.CLASS, - S.stringVal()); + token.stringVal()); break; case TRUE: case FALSE: t = F.at(pos).Literal( TypeTags.BOOLEAN, - (S.token() == TRUE ? 1 : 0)); + (token.kind == TRUE ? 1 : 0)); break; case NULL: t = F.at(pos).Literal( @@ -576,8 +586,8 @@ public class JavacParser implements Parser { } if (t == errorTree) t = F.at(pos).Erroneous(); - storeEnd(t, S.endPos()); - S.nextToken(); + storeEnd(t, token.endPos); + nextToken(); return t; } //where @@ -590,7 +600,7 @@ public class JavacParser implements Parser { } String strval(Name prefix) { - String s = S.stringVal(); + String s = token.stringVal(); return prefix.isEmpty() ? s : prefix + s; } @@ -627,17 +637,17 @@ public class JavacParser implements Parser { JCExpression term() { JCExpression t = term1(); if ((mode & EXPR) != 0 && - S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0) + token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0) return termRest(t); else return t; } JCExpression termRest(JCExpression t) { - switch (S.token()) { + switch (token.kind) { case EQ: { - int pos = S.pos(); - S.nextToken(); + int pos = token.pos; + nextToken(); mode = EXPR; JCExpression t1 = term(); return toP(F.at(pos).Assign(t, t1)); @@ -653,12 +663,12 @@ public class JavacParser implements Parser { case LTLTEQ: case GTGTEQ: case GTGTGTEQ: - int pos = S.pos(); - Token token = S.token(); - S.nextToken(); + int pos = token.pos; + TokenKind tk = token.kind; + nextToken(); mode = EXPR; JCExpression t1 = term(); - return F.at(pos).Assignop(optag(token), t, t1); + return F.at(pos).Assignop(optag(tk), t, t1); default: return t; } @@ -670,7 +680,7 @@ public class JavacParser implements Parser { */ JCExpression term1() { JCExpression t = term2(); - if ((mode & EXPR) != 0 && S.token() == QUES) { + if ((mode & EXPR) != 0 && token.kind == QUES) { mode = EXPR; return term1Rest(t); } else { @@ -681,9 +691,9 @@ public class JavacParser implements Parser { /** Expression1Rest = ["?" Expression ":" Expression1] */ JCExpression term1Rest(JCExpression t) { - if (S.token() == QUES) { - int pos = S.pos(); - S.nextToken(); + if (token.kind == QUES) { + int pos = token.pos; + nextToken(); JCExpression t1 = term(); accept(COLON); JCExpression t2 = term1(); @@ -699,7 +709,7 @@ public class JavacParser implements Parser { */ JCExpression term2() { JCExpression t = term3(); - if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) { + if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) { mode = EXPR; return term2Rest(t, TreeInfo.orPrec); } else { @@ -725,28 +735,23 @@ public class JavacParser implements Parser { JCExpression[] odStack = newOdStack(); List savedOp = opStackSupply.elems; Token[] opStack = newOpStack(); - List savedPos = posStackSupply.elems; - int[] posStack = newPosStack(); + // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; int top = 0; odStack[0] = t; - int startPos = S.pos(); - Token topOp = ERROR; - int topOpPos = Position.NOPOS; - while (prec(S.token()) >= minprec) { - posStack[top] = topOpPos; + int startPos = token.pos; + Token topOp = Tokens.DUMMY; + while (prec(token.kind) >= minprec) { opStack[top] = topOp; top++; - topOp = S.token(); - topOpPos = S.pos(); - S.nextToken(); - odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3(); - while (top > 0 && prec(topOp) >= prec(S.token())) { - odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1], + topOp = token; + nextToken(); + odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3(); + while (top > 0 && prec(topOp.kind) >= prec(token.kind)) { + odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1], odStack[top]); top--; topOp = opStack[top]; - topOpPos = posStack[top]; } } Assert.check(top == 0); @@ -761,14 +766,13 @@ public class JavacParser implements Parser { odStackSupply.elems = savedOd; // optimization opStackSupply.elems = savedOp; // optimization - posStackSupply.elems = savedPos; // optimization return t; } //where /** Construct a binary or type test node. */ private JCExpression makeOp(int pos, - Token topOp, + TokenKind topOp, JCExpression od1, JCExpression od2) { @@ -817,7 +821,6 @@ public class JavacParser implements Parser { */ ListBuffer odStackSupply = new ListBuffer(); ListBuffer opStackSupply = new ListBuffer(); - ListBuffer posStackSupply = new ListBuffer(); private JCExpression[] newOdStack() { if (odStackSupply.elems == odStackSupply.last) @@ -835,14 +838,6 @@ public class JavacParser implements Parser { return opStack; } - private int[] newPosStack() { - if (posStackSupply.elems == posStackSupply.last) - posStackSupply.append(new int[infixPrecedenceLevels + 1]); - int[] posStack = posStackSupply.elems.head; - posStackSupply.elems = posStackSupply.elems.tail; - return posStack; - } - /** Expression3 = PrefixOp Expression3 * | "(" Expr | TypeNoParams ")" Expression3 * | Primary {Selector} {PostfixOp} @@ -871,10 +866,10 @@ public class JavacParser implements Parser { * SuperSuffix = Arguments | "." Ident [Arguments] */ protected JCExpression term3() { - int pos = S.pos(); + int pos = token.pos; JCExpression t; List typeArgs = typeArgumentsOpt(EXPR); - switch (S.token()) { + switch (token.kind) { case QUES: if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { mode = TYPE; @@ -883,49 +878,49 @@ public class JavacParser implements Parser { return illegal(); case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: if (typeArgs == null && (mode & EXPR) != 0) { - Token token = S.token(); - S.nextToken(); + TokenKind tk = token.kind; + nextToken(); mode = EXPR; - if (token == SUB && - (S.token() == INTLITERAL || S.token() == LONGLITERAL) && - S.radix() == 10) { + if (tk == SUB && + (token.kind == INTLITERAL || token.kind == LONGLITERAL) && + token.radix() == 10) { mode = EXPR; t = literal(names.hyphen, pos); } else { t = term3(); - return F.at(pos).Unary(unoptag(token), t); + return F.at(pos).Unary(unoptag(tk), t); } } else return illegal(); break; case LPAREN: if (typeArgs == null && (mode & EXPR) != 0) { - S.nextToken(); + nextToken(); mode = EXPR | TYPE | NOPARAMS; t = term3(); - if ((mode & TYPE) != 0 && S.token() == LT) { + if ((mode & TYPE) != 0 && token.kind == LT) { // Could be a cast to a parameterized type int op = JCTree.LT; - int pos1 = S.pos(); - S.nextToken(); + int pos1 = token.pos; + nextToken(); mode &= (EXPR | TYPE); mode |= TYPEARG; JCExpression t1 = term3(); if ((mode & TYPE) != 0 && - (S.token() == COMMA || S.token() == GT)) { + (token.kind == COMMA || token.kind == GT)) { mode = TYPE; ListBuffer args = new ListBuffer(); args.append(t1); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); args.append(typeArgument()); } accept(GT); t = toP(F.at(pos1).TypeApply(t, args.toList())); checkGenerics(); - while (S.token() == DOT) { - S.nextToken(); + while (token.kind == DOT) { + nextToken(); mode = TYPE; - t = toP(F.at(S.pos()).Select(t, ident())); + t = toP(F.at(token.pos).Select(t, ident())); t = typeArgumentsOpt(t); } t = bracketsOpt(toP(t)); @@ -948,7 +943,7 @@ public class JavacParser implements Parser { JCExpression t1 = term3(); return F.at(pos).TypeCast(t, t1); } else if ((lastmode & TYPE) != 0) { - switch (S.token()) { + switch (token.kind) { /*case PLUSPLUS: case SUBSUB: */ case BANG: case TILDE: case LPAREN: case THIS: case SUPER: @@ -969,7 +964,7 @@ public class JavacParser implements Parser { if ((mode & EXPR) != 0) { mode = EXPR; t = to(F.at(pos).Ident(names._this)); - S.nextToken(); + nextToken(); if (typeArgs == null) t = argumentsOpt(null, t); else @@ -997,22 +992,22 @@ public class JavacParser implements Parser { if (typeArgs != null) return illegal(); if ((mode & EXPR) != 0) { mode = EXPR; - S.nextToken(); - if (S.token() == LT) typeArgs = typeArguments(false); + nextToken(); + if (token.kind == LT) typeArgs = typeArguments(false); t = creator(pos, typeArgs); typeArgs = null; } else return illegal(); break; case IDENTIFIER: case ASSERT: case ENUM: if (typeArgs != null) return illegal(); - t = toP(F.at(S.pos()).Ident(ident())); + t = toP(F.at(token.pos).Ident(ident())); loop: while (true) { - pos = S.pos(); - switch (S.token()) { + pos = token.pos; + switch (token.kind) { case LBRACKET: - S.nextToken(); - if (S.token() == RBRACKET) { - S.nextToken(); + nextToken(); + if (token.kind == RBRACKET) { + nextToken(); t = bracketsOpt(t); t = toP(F.at(pos).TypeArray(t)); t = bracketsSuffix(t); @@ -1033,24 +1028,24 @@ public class JavacParser implements Parser { } break loop; case DOT: - S.nextToken(); + nextToken(); int oldmode = mode; mode &= ~NOPARAMS; typeArgs = typeArgumentsOpt(EXPR); mode = oldmode; if ((mode & EXPR) != 0) { - switch (S.token()) { + switch (token.kind) { case CLASS: if (typeArgs != null) return illegal(); mode = EXPR; t = to(F.at(pos).Select(t, names._class)); - S.nextToken(); + nextToken(); break loop; case THIS: if (typeArgs != null) return illegal(); mode = EXPR; t = to(F.at(pos).Select(t, names._this)); - S.nextToken(); + nextToken(); break loop; case SUPER: mode = EXPR; @@ -1061,9 +1056,9 @@ public class JavacParser implements Parser { case NEW: if (typeArgs != null) return illegal(); mode = EXPR; - int pos1 = S.pos(); - S.nextToken(); - if (S.token() == LT) typeArgs = typeArguments(false); + int pos1 = token.pos; + nextToken(); + if (token.kind == LT) typeArgs = typeArguments(false); t = innerCreator(pos1, typeArgs, t); typeArgs = null; break loop; @@ -1087,8 +1082,8 @@ public class JavacParser implements Parser { case VOID: if (typeArgs != null) illegal(); if ((mode & EXPR) != 0) { - S.nextToken(); - if (S.token() == DOT) { + nextToken(); + if (token.kind == DOT) { JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID)); t = bracketsSuffix(ti); } else { @@ -1099,7 +1094,7 @@ public class JavacParser implements Parser { // a void type (like other primitive types) to the next phase. // The error will be reported in Attr.attribTypes or Attr.visitApply. JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID)); - S.nextToken(); + nextToken(); return ti; //return illegal(); } @@ -1109,14 +1104,14 @@ public class JavacParser implements Parser { } if (typeArgs != null) illegal(); while (true) { - int pos1 = S.pos(); - if (S.token() == LBRACKET) { - S.nextToken(); + int pos1 = token.pos; + if (token.kind == LBRACKET) { + nextToken(); if ((mode & TYPE) != 0) { int oldmode = mode; mode = TYPE; - if (S.token() == RBRACKET) { - S.nextToken(); + if (token.kind == RBRACKET) { + nextToken(); t = bracketsOpt(t); t = toP(F.at(pos1).TypeArray(t)); return t; @@ -1129,21 +1124,21 @@ public class JavacParser implements Parser { t = to(F.at(pos1).Indexed(t, t1)); } accept(RBRACKET); - } else if (S.token() == DOT) { - S.nextToken(); + } else if (token.kind == DOT) { + nextToken(); typeArgs = typeArgumentsOpt(EXPR); - if (S.token() == SUPER && (mode & EXPR) != 0) { + if (token.kind == SUPER && (mode & EXPR) != 0) { mode = EXPR; t = to(F.at(pos1).Select(t, names._super)); - S.nextToken(); + nextToken(); t = arguments(typeArgs, t); typeArgs = null; - } else if (S.token() == NEW && (mode & EXPR) != 0) { + } else if (token.kind == NEW && (mode & EXPR) != 0) { if (typeArgs != null) return illegal(); mode = EXPR; - int pos2 = S.pos(); - S.nextToken(); - if (S.token() == LT) typeArgs = typeArguments(false); + int pos2 = token.pos; + nextToken(); + if (token.kind == LT) typeArgs = typeArguments(false); t = innerCreator(pos2, typeArgs, t); typeArgs = null; } else { @@ -1155,11 +1150,11 @@ public class JavacParser implements Parser { break; } } - while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) { + while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) { mode = EXPR; - t = to(F.at(S.pos()).Unary( - S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); - S.nextToken(); + t = to(F.at(token.pos).Unary( + token.kind == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); + nextToken(); } return toP(t); } @@ -1167,13 +1162,13 @@ public class JavacParser implements Parser { /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] */ JCExpression superSuffix(List typeArgs, JCExpression t) { - S.nextToken(); - if (S.token() == LPAREN || typeArgs != null) { + nextToken(); + if (token.kind == LPAREN || typeArgs != null) { t = arguments(typeArgs, t); } else { - int pos = S.pos(); + int pos = token.pos; accept(DOT); - typeArgs = (S.token() == LT) ? typeArguments(false) : null; + typeArgs = (token.kind == LT) ? typeArguments(false) : null; t = toP(F.at(pos).Select(t, ident())); t = argumentsOpt(typeArgs, t); } @@ -1183,15 +1178,15 @@ public class JavacParser implements Parser { /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN */ JCPrimitiveTypeTree basicType() { - JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token()))); - S.nextToken(); + JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind))); + nextToken(); return t; } /** ArgumentsOpt = [ Arguments ] */ JCExpression argumentsOpt(List typeArgs, JCExpression t) { - if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) { + if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) { mode = EXPR; return arguments(typeArgs, t); } else { @@ -1203,24 +1198,24 @@ public class JavacParser implements Parser { */ List arguments() { ListBuffer args = lb(); - if (S.token() == LPAREN) { - S.nextToken(); - if (S.token() != RPAREN) { + if (token.kind == LPAREN) { + nextToken(); + if (token.kind != RPAREN) { args.append(parseExpression()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); args.append(parseExpression()); } } accept(RPAREN); } else { - syntaxError(S.pos(), "expected", LPAREN); + syntaxError(token.pos, "expected", LPAREN); } return args.toList(); } JCMethodInvocation arguments(List typeArgs, JCExpression t) { - int pos = S.pos(); + int pos = token.pos; List args = arguments(); return toP(F.at(pos).Apply(typeArgs, t, args)); } @@ -1228,7 +1223,7 @@ public class JavacParser implements Parser { /** TypeArgumentsOpt = [ TypeArguments ] */ JCExpression typeArgumentsOpt(JCExpression t) { - if (S.token() == LT && + if (token.kind == LT && (mode & TYPE) != 0 && (mode & NOPARAMS) == 0) { mode = TYPE; @@ -1243,7 +1238,7 @@ public class JavacParser implements Parser { } List typeArgumentsOpt(int useMode) { - if (S.token() == LT) { + if (token.kind == LT) { checkGenerics(); if ((mode & useMode) == 0 || (mode & NOPARAMS) != 0) { @@ -1258,47 +1253,37 @@ public class JavacParser implements Parser { /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" */ List typeArguments(boolean diamondAllowed) { - if (S.token() == LT) { - S.nextToken(); - if (S.token() == GT && diamondAllowed) { + if (token.kind == LT) { + nextToken(); + if (token.kind == GT && diamondAllowed) { checkDiamond(); mode |= DIAMOND; - S.nextToken(); + nextToken(); return List.nil(); } else { ListBuffer args = ListBuffer.lb(); args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); } - switch (S.token()) { - case GTGTGTEQ: - S.token(GTGTEQ); - break; - case GTGTEQ: - S.token(GTEQ); - break; - case GTEQ: - S.token(EQ); - break; - case GTGTGT: - S.token(GTGT); - break; - case GTGT: - S.token(GT); + switch (token.kind) { + + case GTGTGTEQ: case GTGTEQ: case GTEQ: + case GTGTGT: case GTGT: + token = S.split(); break; case GT: - S.nextToken(); + nextToken(); break; default: - args.append(syntaxError(S.pos(), "expected", GT)); + args.append(syntaxError(token.pos, "expected", GT)); break; } return args.toList(); } } else { - return List.of(syntaxError(S.pos(), "expected", LT)); + return List.of(syntaxError(token.pos, "expected", LT)); } } @@ -1308,24 +1293,24 @@ public class JavacParser implements Parser { * | "?" SUPER Type */ JCExpression typeArgument() { - if (S.token() != QUES) return parseType(); - int pos = S.pos(); - S.nextToken(); - if (S.token() == EXTENDS) { + if (token.kind != QUES) return parseType(); + int pos = token.pos; + nextToken(); + if (token.kind == EXTENDS) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS)); - S.nextToken(); + nextToken(); JCExpression bound = parseType(); return F.at(pos).Wildcard(t, bound); - } else if (S.token() == SUPER) { + } else if (token.kind == SUPER) { TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER)); - S.nextToken(); + nextToken(); JCExpression bound = parseType(); return F.at(pos).Wildcard(t, bound); - } else if (S.token() == IDENTIFIER) { + } else if (token.kind == IDENTIFIER) { //error recovery 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())); + JCIdent id = toP(F.at(token.pos).Ident(ident())); JCErroneous err = F.at(pos).Erroneous(List.of(wc, id)); reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER); return err; @@ -1336,7 +1321,7 @@ public class JavacParser implements Parser { } JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) { - int pos = S.pos(); + int pos = token.pos; List args = typeArguments(diamondAllowed); return toP(F.at(pos).TypeApply(t, args)); } @@ -1344,9 +1329,9 @@ public class JavacParser implements Parser { /** BracketsOpt = {"[" "]"} */ private JCExpression bracketsOpt(JCExpression t) { - if (S.token() == LBRACKET) { - int pos = S.pos(); - S.nextToken(); + if (token.kind == LBRACKET) { + int pos = token.pos; + nextToken(); t = bracketsOptCont(t, pos); F.at(pos); } @@ -1363,17 +1348,17 @@ public class JavacParser implements Parser { * BracketsSuffixType = */ JCExpression bracketsSuffix(JCExpression t) { - if ((mode & EXPR) != 0 && S.token() == DOT) { + if ((mode & EXPR) != 0 && token.kind == DOT) { mode = EXPR; - int pos = S.pos(); - S.nextToken(); + int pos = token.pos; + nextToken(); accept(CLASS); - if (S.pos() == errorEndPos) { + if (token.pos == errorEndPos) { // error recovery Name name = null; - if (S.token() == IDENTIFIER) { - name = S.name(); - S.nextToken(); + if (token.kind == IDENTIFIER) { + name = token.name(); + nextToken(); } else { name = names.error; } @@ -1384,7 +1369,7 @@ public class JavacParser implements Parser { } else if ((mode & TYPE) != 0) { mode = TYPE; } else { - syntaxError(S.pos(), "dot.class.expected"); + syntaxError(token.pos, "dot.class.expected"); } return t; } @@ -1392,7 +1377,7 @@ public class JavacParser implements Parser { /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) */ JCExpression creator(int newpos, List typeArgs) { - switch (S.token()) { + switch (token.kind) { case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: case DOUBLE: case BOOLEAN: if (typeArgs == null) @@ -1405,29 +1390,29 @@ public class JavacParser implements Parser { mode = TYPE; boolean diamondFound = false; int lastTypeargsPos = -1; - if (S.token() == LT) { + if (token.kind == LT) { checkGenerics(); - lastTypeargsPos = S.pos(); + lastTypeargsPos = token.pos; t = typeArguments(t, true); diamondFound = (mode & DIAMOND) != 0; } - while (S.token() == DOT) { + while (token.kind == DOT) { if (diamondFound) { //cannot select after a diamond illegal(); } - int pos = S.pos(); - S.nextToken(); + int pos = token.pos; + nextToken(); t = toP(F.at(pos).Select(t, ident())); - if (S.token() == LT) { - lastTypeargsPos = S.pos(); + if (token.kind == LT) { + lastTypeargsPos = token.pos; checkGenerics(); t = typeArguments(t, true); diamondFound = (mode & DIAMOND) != 0; } } mode = oldmode; - if (S.token() == LBRACKET) { + if (token.kind == LBRACKET) { JCExpression e = arrayCreatorRest(newpos, t); if (diamondFound) { reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond"); @@ -1441,17 +1426,17 @@ public class JavacParser implements Parser { // modified to improve error recovery. pos = typeArgs.head.pos; } - setErrorEndPos(S.prevEndPos()); + setErrorEndPos(S.prevToken().endPos); 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) { + } else if (token.kind == LPAREN) { return classCreatorRest(newpos, null, typeArgs, t); } else { - setErrorEndPos(S.pos()); - reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET); + setErrorEndPos(token.pos); + reportSyntaxError(token.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))); } @@ -1460,8 +1445,8 @@ public class JavacParser implements Parser { /** InnerCreator = Ident [TypeArguments] ClassCreatorRest */ JCExpression innerCreator(int newpos, List typeArgs, JCExpression encl) { - JCExpression t = toP(F.at(S.pos()).Ident(ident())); - if (S.token() == LT) { + JCExpression t = toP(F.at(token.pos).Ident(ident())); + if (token.kind == LT) { int oldmode = mode; checkGenerics(); t = typeArguments(t, true); @@ -1475,23 +1460,23 @@ public class JavacParser implements Parser { */ JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { accept(LBRACKET); - if (S.token() == RBRACKET) { + if (token.kind == RBRACKET) { accept(RBRACKET); elemtype = bracketsOpt(elemtype); - if (S.token() == LBRACE) { + if (token.kind == LBRACE) { return arrayInitializer(newpos, elemtype); } else { JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.nil(), null)); - return syntaxError(S.pos(), List.of(t), "array.dimension.missing"); + return syntaxError(token.pos, List.of(t), "array.dimension.missing"); } } else { ListBuffer dims = new ListBuffer(); dims.append(parseExpression()); accept(RBRACKET); - while (S.token() == LBRACKET) { - int pos = S.pos(); - S.nextToken(); - if (S.token() == RBRACKET) { + while (token.kind == LBRACKET) { + int pos = token.pos; + nextToken(); + if (token.kind == RBRACKET) { elemtype = bracketsOptCont(elemtype, pos); } else { dims.append(parseExpression()); @@ -1511,8 +1496,8 @@ public class JavacParser implements Parser { { List args = arguments(); JCClassDecl body = null; - if (S.token() == LBRACE) { - int pos = S.pos(); + if (token.kind == LBRACE) { + int pos = token.pos; List defs = classOrInterfaceBody(names.empty, false); JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); body = toP(F.at(pos).AnonymousClassDef(mods, defs)); @@ -1525,13 +1510,13 @@ public class JavacParser implements Parser { JCExpression arrayInitializer(int newpos, JCExpression t) { accept(LBRACE); ListBuffer elems = new ListBuffer(); - if (S.token() == COMMA) { - S.nextToken(); - } else if (S.token() != RBRACE) { + if (token.kind == COMMA) { + nextToken(); + } else if (token.kind != RBRACE) { elems.append(variableInitializer()); - while (S.token() == COMMA) { - S.nextToken(); - if (S.token() == RBRACE) break; + while (token.kind == COMMA) { + nextToken(); + if (token.kind == RBRACE) break; elems.append(variableInitializer()); } } @@ -1542,7 +1527,7 @@ public class JavacParser implements Parser { /** VariableInitializer = ArrayInitializer | Expression */ public JCExpression variableInitializer() { - return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression(); + return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression(); } /** ParExpression = "(" Expression ")" @@ -1560,19 +1545,19 @@ public class JavacParser implements Parser { accept(LBRACE); List stats = blockStatements(); JCBlock t = F.at(pos).Block(flags, stats); - while (S.token() == CASE || S.token() == DEFAULT) { - syntaxError("orphaned", S.token()); + while (token.kind == CASE || token.kind == DEFAULT) { + syntaxError("orphaned", token.kind); switchBlockStatementGroups(); } // the Block node has a field "endpos" for first char of last token, which is // usually but not necessarily the last char of the last token. - t.endpos = S.pos(); + t.endpos = token.pos; accept(RBRACE); return toP(t); } public JCBlock block() { - return block(S.pos(), 0); + return block(token.pos, 0); } /** BlockStatements = { BlockStatement } @@ -1588,8 +1573,8 @@ public class JavacParser implements Parser { int lastErrPos = -1; ListBuffer stats = new ListBuffer(); while (true) { - int pos = S.pos(); - switch (S.token()) { + int pos = token.pos; + switch (token.kind) { case RBRACE: case CASE: case DEFAULT: case EOF: return stats.toList(); case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: @@ -1599,64 +1584,63 @@ public class JavacParser implements Parser { break; case MONKEYS_AT: case FINAL: { - String dc = S.docComment(); + String dc = token.docComment; JCModifiers mods = modifiersOpt(); - if (S.token() == INTERFACE || - S.token() == CLASS || - allowEnums && S.token() == ENUM) { + if (token.kind == INTERFACE || + token.kind == CLASS || + allowEnums && token.kind == ENUM) { stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); } else { JCExpression t = parseType(); stats.appendList(variableDeclarators(mods, t, new ListBuffer())); // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), S.endPos()); + storeEnd(stats.elems.last(), token.endPos); accept(SEMI); } break; } case ABSTRACT: case STRICTFP: { - String dc = S.docComment(); + String dc = token.docComment; JCModifiers mods = modifiersOpt(); stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); break; } case INTERFACE: case CLASS: - stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), - S.docComment())); + String dc = token.docComment; + stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); break; case ENUM: case ASSERT: - if (allowEnums && S.token() == ENUM) { - error(S.pos(), "local.enum"); - stats. - append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), - S.docComment())); + if (allowEnums && token.kind == ENUM) { + error(token.pos, "local.enum"); + dc = token.docComment; + stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc)); break; - } else if (allowAsserts && S.token() == ASSERT) { + } else if (allowAsserts && token.kind == ASSERT) { stats.append(parseStatement()); break; } /* fall through to default */ default: - Name name = S.name(); + Token prevToken = token; JCExpression t = term(EXPR | TYPE); - if (S.token() == COLON && t.getTag() == JCTree.IDENT) { - S.nextToken(); + if (token.kind == COLON && t.getTag() == JCTree.IDENT) { + nextToken(); JCStatement stat = parseStatement(); - stats.append(F.at(pos).Labelled(name, stat)); + stats.append(F.at(pos).Labelled(prevToken.name(), stat)); } else if ((lastmode & TYPE) != 0 && - (S.token() == IDENTIFIER || - S.token() == ASSERT || - S.token() == ENUM)) { - pos = S.pos(); + (token.kind == IDENTIFIER || + token.kind == ASSERT || + token.kind == ENUM)) { + pos = token.pos; JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); F.at(pos); stats.appendList(variableDeclarators(mods, t, new ListBuffer())); // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon - storeEnd(stats.elems.last(), S.endPos()); + storeEnd(stats.elems.last(), token.endPos); accept(SEMI); } else { // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon @@ -1666,15 +1650,12 @@ public class JavacParser implements Parser { } // error recovery - if (S.pos() == lastErrPos) + if (token.pos == lastErrPos) return stats.toList(); - if (S.pos() <= errorEndPos) { + if (token.pos <= errorEndPos) { skip(false, true, true, true); - lastErrPos = S.pos(); + lastErrPos = token.pos; } - - // ensure no dangling /** @deprecated */ active - S.resetDeprecatedFlag(); } } @@ -1700,29 +1681,29 @@ public class JavacParser implements Parser { */ @SuppressWarnings("fallthrough") public JCStatement parseStatement() { - int pos = S.pos(); - switch (S.token()) { + int pos = token.pos; + switch (token.kind) { case LBRACE: return block(); case IF: { - S.nextToken(); + nextToken(); JCExpression cond = parExpression(); JCStatement thenpart = parseStatement(); JCStatement elsepart = null; - if (S.token() == ELSE) { - S.nextToken(); + if (token.kind == ELSE) { + nextToken(); elsepart = parseStatement(); } return F.at(pos).If(cond, thenpart, elsepart); } case FOR: { - S.nextToken(); + nextToken(); accept(LPAREN); - List inits = S.token() == SEMI ? List.nil() : forInit(); + List inits = token.kind == SEMI ? List.nil() : forInit(); if (inits.length() == 1 && inits.head.getTag() == JCTree.VARDEF && ((JCVariableDecl) inits.head).init == null && - S.token() == COLON) { + token.kind == COLON) { checkForeach(); JCVariableDecl var = (JCVariableDecl)inits.head; accept(COLON); @@ -1732,22 +1713,22 @@ public class JavacParser implements Parser { return F.at(pos).ForeachLoop(var, expr, body); } else { accept(SEMI); - JCExpression cond = S.token() == SEMI ? null : parseExpression(); + JCExpression cond = token.kind == SEMI ? null : parseExpression(); accept(SEMI); - List steps = S.token() == RPAREN ? List.nil() : forUpdate(); + List steps = token.kind == RPAREN ? List.nil() : forUpdate(); accept(RPAREN); JCStatement body = parseStatement(); return F.at(pos).ForLoop(inits, cond, steps, body); } } case WHILE: { - S.nextToken(); + nextToken(); JCExpression cond = parExpression(); JCStatement body = parseStatement(); return F.at(pos).WhileLoop(cond, body); } case DO: { - S.nextToken(); + nextToken(); JCStatement body = parseStatement(); accept(WHILE); JCExpression cond = parExpression(); @@ -1756,21 +1737,21 @@ public class JavacParser implements Parser { return t; } case TRY: { - S.nextToken(); + nextToken(); List resources = List.nil(); - if (S.token() == LPAREN) { + if (token.kind == LPAREN) { checkTryWithResources(); - S.nextToken(); + nextToken(); resources = resources(); accept(RPAREN); } JCBlock body = block(); ListBuffer catchers = new ListBuffer(); JCBlock finalizer = null; - if (S.token() == CATCH || S.token() == FINALLY) { - while (S.token() == CATCH) catchers.append(catchClause()); - if (S.token() == FINALLY) { - S.nextToken(); + if (token.kind == CATCH || token.kind == FINALLY) { + while (token.kind == CATCH) catchers.append(catchClause()); + if (token.kind == FINALLY) { + nextToken(); finalizer = block(); } } else { @@ -1783,7 +1764,7 @@ public class JavacParser implements Parser { return F.at(pos).Try(resources, body, catchers.toList(), finalizer); } case SWITCH: { - S.nextToken(); + nextToken(); JCExpression selector = parExpression(); accept(LBRACE); List cases = switchBlockStatementGroups(); @@ -1792,41 +1773,41 @@ public class JavacParser implements Parser { return t; } case SYNCHRONIZED: { - S.nextToken(); + nextToken(); JCExpression lock = parExpression(); JCBlock body = block(); return F.at(pos).Synchronized(lock, body); } case RETURN: { - S.nextToken(); - JCExpression result = S.token() == SEMI ? null : parseExpression(); + nextToken(); + JCExpression result = token.kind == SEMI ? null : parseExpression(); JCReturn t = to(F.at(pos).Return(result)); accept(SEMI); return t; } case THROW: { - S.nextToken(); + nextToken(); JCExpression exc = parseExpression(); JCThrow t = to(F.at(pos).Throw(exc)); accept(SEMI); return t; } case BREAK: { - S.nextToken(); - Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; + nextToken(); + Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; JCBreak t = to(F.at(pos).Break(label)); accept(SEMI); return t; } case CONTINUE: { - S.nextToken(); - Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; + nextToken(); + Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null; JCContinue t = to(F.at(pos).Continue(label)); accept(SEMI); return t; } case SEMI: - S.nextToken(); + nextToken(); return toP(F.at(pos).Skip()); case ELSE: return toP(F.Exec(syntaxError("else.without.if"))); @@ -1835,12 +1816,12 @@ public class JavacParser implements Parser { case CATCH: return toP(F.Exec(syntaxError("catch.without.try"))); case ASSERT: { - if (allowAsserts && S.token() == ASSERT) { - S.nextToken(); + if (allowAsserts && token.kind == ASSERT) { + nextToken(); JCExpression assertion = parseExpression(); JCExpression message = null; - if (S.token() == COLON) { - S.nextToken(); + if (token.kind == COLON) { + nextToken(); message = parseExpression(); } JCAssert t = to(F.at(pos).Assert(assertion, message)); @@ -1851,12 +1832,12 @@ public class JavacParser implements Parser { } case ENUM: default: - Name name = S.name(); + Token prevToken = token; JCExpression expr = parseExpression(); - if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { - S.nextToken(); + if (token.kind == COLON && expr.getTag() == JCTree.IDENT) { + nextToken(); JCStatement stat = parseStatement(); - return F.at(pos).Labelled(name, stat); + return F.at(pos).Labelled(prevToken.name(), stat); } else { // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); @@ -1869,7 +1850,7 @@ public class JavacParser implements Parser { /** CatchClause = CATCH "(" FormalParameter ")" Block */ protected JCCatch catchClause() { - int pos = S.pos(); + int pos = token.pos; accept(CATCH); accept(LPAREN); JCModifiers mods = optFinal(Flags.PARAMETER); @@ -1886,9 +1867,9 @@ public class JavacParser implements Parser { List catchTypes() { ListBuffer catchTypes = ListBuffer.lb(); catchTypes.add(parseType()); - while (S.token() == BAR) { + while (token.kind == BAR) { checkMulticatch(); - S.nextToken(); + nextToken(); catchTypes.add(qualident()); } return catchTypes.toList(); @@ -1901,33 +1882,33 @@ public class JavacParser implements Parser { List switchBlockStatementGroups() { ListBuffer cases = new ListBuffer(); while (true) { - int pos = S.pos(); - switch (S.token()) { + int pos = token.pos; + switch (token.kind) { case CASE: { - S.nextToken(); + nextToken(); JCExpression pat = parseExpression(); accept(COLON); List stats = blockStatements(); JCCase c = F.at(pos).Case(pat, stats); if (stats.isEmpty()) - storeEnd(c, S.prevEndPos()); + storeEnd(c, S.prevToken().endPos); cases.append(c); break; } case DEFAULT: { - S.nextToken(); + nextToken(); accept(COLON); List stats = blockStatements(); JCCase c = F.at(pos).Case(null, stats); if (stats.isEmpty()) - storeEnd(c, S.prevEndPos()); + storeEnd(c, S.prevToken().endPos); cases.append(c); break; } case RBRACE: case EOF: return cases.toList(); default: - S.nextToken(); // to ensure progress + nextToken(); // to ensure progress syntaxError(pos, "expected3", CASE, DEFAULT, RBRACE); } @@ -1941,9 +1922,9 @@ public class JavacParser implements Parser { T stats) { // This Exec is a "StatementExpression"; it subsumes no terminating token stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); - while (S.token() == COMMA) { - S.nextToken(); - pos = S.pos(); + while (token.kind == COMMA) { + nextToken(); + pos = token.pos; JCExpression t = parseExpression(); // This Exec is a "StatementExpression"; it subsumes no terminating token stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); @@ -1956,13 +1937,13 @@ public class JavacParser implements Parser { */ List forInit() { ListBuffer stats = lb(); - int pos = S.pos(); - if (S.token() == FINAL || S.token() == MONKEYS_AT) { + int pos = token.pos; + if (token.kind == FINAL || token.kind == MONKEYS_AT) { return variableDeclarators(optFinal(0), parseType(), stats).toList(); } else { JCExpression t = term(EXPR | TYPE); if ((lastmode & TYPE) != 0 && - (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) + (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM)) return variableDeclarators(modifiersOpt(), t, stats).toList(); else return moreStatementExpressions(pos, t, stats).toList(); @@ -1972,7 +1953,7 @@ public class JavacParser implements Parser { /** ForUpdate = StatementExpression MoreStatementExpressions */ List forUpdate() { - return moreStatementExpressions(S.pos(), + return moreStatementExpressions(token.pos, parseExpression(), new ListBuffer()).toList(); } @@ -1980,11 +1961,11 @@ public class JavacParser implements Parser { /** AnnotationsOpt = { '@' Annotation } */ List annotationsOpt() { - if (S.token() != MONKEYS_AT) return List.nil(); // optimization + if (token.kind != MONKEYS_AT) return List.nil(); // optimization ListBuffer buf = new ListBuffer(); - while (S.token() == MONKEYS_AT) { - int pos = S.pos(); - S.nextToken(); + while (token.kind == MONKEYS_AT) { + int pos = token.pos; + nextToken(); buf.append(annotation(pos)); } return buf.toList(); @@ -2004,21 +1985,20 @@ public class JavacParser implements Parser { int pos; if (partial == null) { flags = 0; - pos = S.pos(); + pos = token.pos; } else { flags = partial.flags; annotations.appendList(partial.annotations); pos = partial.pos; } - if (S.deprecatedFlag()) { + if (token.deprecatedFlag) { flags |= Flags.DEPRECATED; - S.resetDeprecatedFlag(); } int lastPos = Position.NOPOS; loop: while (true) { long flag; - switch (S.token()) { + switch (token.kind) { case PRIVATE : flag = Flags.PRIVATE; break; case PROTECTED : flag = Flags.PROTECTED; break; case PUBLIC : flag = Flags.PUBLIC; break; @@ -2031,15 +2011,15 @@ public class JavacParser implements Parser { 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; + case ERROR : flag = 0; nextToken(); break; default: break loop; } - if ((flags & flag) != 0) error(S.pos(), "repeated.modifier"); - lastPos = S.pos(); - S.nextToken(); + if ((flags & flag) != 0) error(token.pos, "repeated.modifier"); + lastPos = token.pos; + nextToken(); if (flag == Flags.ANNOTATION) { checkAnnotations(); - if (S.token() != INTERFACE) { + if (token.kind != INTERFACE) { JCAnnotation ann = annotation(lastPos); // if first modifier is an annotation, set pos to annotation's. if (flags == 0 && annotations.isEmpty()) @@ -2051,7 +2031,7 @@ public class JavacParser implements Parser { } flags |= flag; } - switch (S.token()) { + switch (token.kind) { case ENUM: flags |= Flags.ENUM; break; case INTERFACE: flags |= Flags.INTERFACE; break; default: break; @@ -2064,7 +2044,7 @@ public class JavacParser implements Parser { JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); if (pos != Position.NOPOS) - storeEnd(mods, S.prevEndPos()); + storeEnd(mods, S.prevToken().endPos); return mods; } @@ -2077,22 +2057,22 @@ public class JavacParser implements Parser { JCTree ident = qualident(); List fieldValues = annotationFieldValuesOpt(); JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); - storeEnd(ann, S.prevEndPos()); + storeEnd(ann, S.prevToken().endPos); return ann; } List annotationFieldValuesOpt() { - return (S.token() == LPAREN) ? annotationFieldValues() : List.nil(); + return (token.kind == LPAREN) ? annotationFieldValues() : List.nil(); } /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ List annotationFieldValues() { accept(LPAREN); ListBuffer buf = new ListBuffer(); - if (S.token() != RPAREN) { + if (token.kind != RPAREN) { buf.append(annotationFieldValue()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); buf.append(annotationFieldValue()); } } @@ -2104,11 +2084,11 @@ public class JavacParser implements Parser { * | Identifier "=" AnnotationValue */ JCExpression annotationFieldValue() { - if (S.token() == IDENTIFIER) { + if (token.kind == IDENTIFIER) { mode = EXPR; JCExpression t1 = term1(); - if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { - int pos = S.pos(); + if (t1.getTag() == JCTree.IDENT && token.kind == EQ) { + int pos = token.pos; accept(EQ); JCExpression v = annotationValue(); return toP(F.at(pos).Assign(t1, v)); @@ -2125,20 +2105,20 @@ public class JavacParser implements Parser { */ JCExpression annotationValue() { int pos; - switch (S.token()) { + switch (token.kind) { case MONKEYS_AT: - pos = S.pos(); - S.nextToken(); + pos = token.pos; + nextToken(); return annotation(pos); case LBRACE: - pos = S.pos(); + pos = token.pos; accept(LBRACE); ListBuffer buf = new ListBuffer(); - if (S.token() != RBRACE) { + if (token.kind != RBRACE) { buf.append(annotationValue()); - while (S.token() == COMMA) { - S.nextToken(); - if (S.token() == RBRACE) break; + while (token.kind == COMMA) { + nextToken(); + if (token.kind == RBRACE) break; buf.append(annotationValue()); } } @@ -2156,7 +2136,7 @@ public class JavacParser implements Parser { JCExpression type, T vdefs) { - return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); + return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs); } /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } @@ -2174,10 +2154,10 @@ public class JavacParser implements Parser { T vdefs) { vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); - while (S.token() == COMMA) { + while (token.kind == COMMA) { // All but last of multiple declarators subsume a comma - storeEnd((JCTree)vdefs.elems.last(), S.endPos()); - S.nextToken(); + storeEnd((JCTree)vdefs.elems.last(), token.endPos); + nextToken(); vdefs.append(variableDeclarator(mods, type, reqInit, dc)); } return vdefs; @@ -2187,7 +2167,7 @@ public class JavacParser implements Parser { * ConstantDeclarator = Ident ConstantDeclaratorRest */ JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { - return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); + return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc); } /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] @@ -2200,11 +2180,11 @@ public class JavacParser implements Parser { boolean reqInit, String dc) { type = bracketsOpt(type); JCExpression init = null; - if (S.token() == EQ) { - S.nextToken(); + if (token.kind == EQ) { + nextToken(); init = variableInitializer(); } - else if (reqInit) syntaxError(S.pos(), "expected", EQ); + else if (reqInit) syntaxError(token.pos, "expected", EQ); JCVariableDecl result = toP(F.at(pos).VarDef(mods, name, type, init)); attach(result, dc); @@ -2214,11 +2194,11 @@ public class JavacParser implements Parser { /** VariableDeclaratorId = Ident BracketsOpt */ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { - int pos = S.pos(); + int pos = token.pos; Name name = ident(); if ((mods.flags & Flags.VARARGS) != 0 && - S.token() == LBRACKET) { - log.error(S.pos(), "varargs.and.old.array.syntax"); + token.kind == LBRACKET) { + log.error(token.pos, "varargs.and.old.array.syntax"); } type = bracketsOpt(type); return toP(F.at(pos).VarDef(mods, name, type, null)); @@ -2229,12 +2209,12 @@ public class JavacParser implements Parser { List resources() { ListBuffer defs = new ListBuffer(); defs.append(resource()); - while (S.token() == SEMI) { + while (token.kind == SEMI) { // All but last of multiple declarators must subsume a semicolon - storeEnd(defs.elems.last(), S.endPos()); - int semiColonPos = S.pos(); - S.nextToken(); - if (S.token() == RPAREN) { // Optional trailing semicolon + storeEnd(defs.elems.last(), token.endPos); + int semiColonPos = token.pos; + nextToken(); + if (token.kind == RPAREN) { // Optional trailing semicolon // after last resource break; } @@ -2248,7 +2228,7 @@ public class JavacParser implements Parser { protected JCTree resource() { JCModifiers optFinal = optFinal(Flags.FINAL); JCExpression type = parseType(); - int pos = S.pos(); + int pos = token.pos; Name ident = ident(); return variableDeclaratorRest(pos, optFinal, type, ident, true, null); } @@ -2256,54 +2236,61 @@ public class JavacParser implements Parser { /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} */ public JCTree.JCCompilationUnit parseCompilationUnit() { - int pos = S.pos(); + Token firstToken = token; JCExpression pid = null; - String dc = S.docComment(); JCModifiers mods = null; + boolean consumedToplevelDoc = false; + boolean seenImport = false; + boolean seenPackage = false; List packageAnnotations = List.nil(); - if (S.token() == MONKEYS_AT) + if (token.kind == MONKEYS_AT) mods = modifiersOpt(); - if (S.token() == PACKAGE) { + if (token.kind == PACKAGE) { + seenPackage = true; if (mods != null) { checkNoMods(mods.flags); packageAnnotations = mods.annotations; mods = null; } - S.nextToken(); + nextToken(); pid = qualident(); accept(SEMI); } ListBuffer defs = new ListBuffer(); boolean checkForImports = true; - while (S.token() != EOF) { - if (S.pos() <= errorEndPos) { + boolean firstTypeDecl = true; + while (token.kind != EOF) { + if (token.pos <= errorEndPos) { // error recovery skip(checkForImports, false, false, false); - if (S.token() == EOF) + if (token.kind == EOF) break; } - if (checkForImports && mods == null && S.token() == IMPORT) { + if (checkForImports && mods == null && token.kind == IMPORT) { + seenImport = true; defs.append(importDeclaration()); } else { - JCTree def = typeDeclaration(mods); - if (keepDocComments && dc != null && docComments.get(def) == dc) { - // If the first type declaration has consumed the first doc - // comment, then don't use it for the top level comment as well. - dc = null; + String docComment = token.docComment; + if (firstTypeDecl && !seenImport && !seenPackage) { + docComment = firstToken.docComment; + consumedToplevelDoc = true; } + JCTree def = typeDeclaration(mods, docComment); if (def instanceof JCExpressionStatement) def = ((JCExpressionStatement)def).expr; defs.append(def); if (def instanceof JCClassDecl) checkForImports = false; mods = null; + firstTypeDecl = false; } } - JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); - attach(toplevel, dc); + JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList()); + if (!consumedToplevelDoc) + attach(toplevel, firstToken.docComment); if (defs.elems.isEmpty()) - storeEnd(toplevel, S.prevEndPos()); + storeEnd(toplevel, S.prevToken().endPos); if (keepDocComments) toplevel.docComments = docComments; if (keepLineMap) @@ -2314,26 +2301,26 @@ public class JavacParser implements Parser { /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" */ JCTree importDeclaration() { - int pos = S.pos(); - S.nextToken(); + int pos = token.pos; + nextToken(); boolean importStatic = false; - if (S.token() == STATIC) { + if (token.kind == STATIC) { checkStaticImports(); importStatic = true; - S.nextToken(); + nextToken(); } - JCExpression pid = toP(F.at(S.pos()).Ident(ident())); + JCExpression pid = toP(F.at(token.pos).Ident(ident())); do { - int pos1 = S.pos(); + int pos1 = token.pos; accept(DOT); - if (S.token() == STAR) { + if (token.kind == STAR) { pid = to(F.at(pos1).Select(pid, names.asterisk)); - S.nextToken(); + nextToken(); break; } else { pid = toP(F.at(pos1).Select(pid, ident())); } - } while (S.token() == DOT); + } while (token.kind == DOT); accept(SEMI); return toP(F.at(pos).Import(pid, importStatic)); } @@ -2341,14 +2328,13 @@ public class JavacParser implements Parser { /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration * | ";" */ - JCTree typeDeclaration(JCModifiers mods) { - int pos = S.pos(); - if (mods == null && S.token() == SEMI) { - S.nextToken(); + JCTree typeDeclaration(JCModifiers mods, String docComment) { + int pos = token.pos; + if (mods == null && token.kind == SEMI) { + nextToken(); return toP(F.at(pos).Skip()); } else { - String dc = S.docComment(); - return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); + return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment); } } @@ -2358,19 +2344,19 @@ public class JavacParser implements Parser { * @param dc The documentation comment for the class, or null. */ JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { - if (S.token() == CLASS) { + if (token.kind == CLASS) { return classDeclaration(mods, dc); - } else if (S.token() == INTERFACE) { + } else if (token.kind == INTERFACE) { return interfaceDeclaration(mods, dc); } else if (allowEnums) { - if (S.token() == ENUM) { + if (token.kind == ENUM) { return enumDeclaration(mods, dc); } else { - int pos = S.pos(); + int pos = token.pos; List errs; - if (S.token() == IDENTIFIER) { + if (token.kind == IDENTIFIER) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); - setErrorEndPos(S.pos()); + setErrorEndPos(token.pos); } else { errs = List.of(mods); } @@ -2378,16 +2364,16 @@ public class JavacParser implements Parser { CLASS, INTERFACE, ENUM))); } } else { - if (S.token() == ENUM) { - error(S.pos(), "enums.not.supported.in.source", source.name); + if (token.kind == ENUM) { + error(token.pos, "enums.not.supported.in.source", source.name); allowEnums = true; return enumDeclaration(mods, dc); } - int pos = S.pos(); + int pos = token.pos; List errs; - if (S.token() == IDENTIFIER) { + if (token.kind == IDENTIFIER) { errs = List.of(mods, toP(F.at(pos).Ident(ident()))); - setErrorEndPos(S.pos()); + setErrorEndPos(token.pos); } else { errs = List.of(mods); } @@ -2402,20 +2388,20 @@ public class JavacParser implements Parser { * @param dc The documentation comment for the class, or null. */ JCClassDecl classDeclaration(JCModifiers mods, String dc) { - int pos = S.pos(); + int pos = token.pos; accept(CLASS); Name name = ident(); List typarams = typeParametersOpt(); JCExpression extending = null; - if (S.token() == EXTENDS) { - S.nextToken(); + if (token.kind == EXTENDS) { + nextToken(); extending = parseType(); } List implementing = List.nil(); - if (S.token() == IMPLEMENTS) { - S.nextToken(); + if (token.kind == IMPLEMENTS) { + nextToken(); implementing = typeList(); } List defs = classOrInterfaceBody(name, false); @@ -2431,15 +2417,15 @@ public class JavacParser implements Parser { * @param dc The documentation comment for the interface, or null. */ JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { - int pos = S.pos(); + int pos = token.pos; accept(INTERFACE); Name name = ident(); List typarams = typeParametersOpt(); List extending = List.nil(); - if (S.token() == EXTENDS) { - S.nextToken(); + if (token.kind == EXTENDS) { + nextToken(); extending = typeList(); } List defs = classOrInterfaceBody(name, true); @@ -2454,13 +2440,13 @@ public class JavacParser implements Parser { * @param dc The documentation comment for the enum, or null. */ JCClassDecl enumDeclaration(JCModifiers mods, String dc) { - int pos = S.pos(); + int pos = token.pos; accept(ENUM); Name name = ident(); List implementing = List.nil(); - if (S.token() == IMPLEMENTS) { - S.nextToken(); + if (token.kind == IMPLEMENTS) { + nextToken(); implementing = typeList(); } @@ -2479,27 +2465,27 @@ public class JavacParser implements Parser { List enumBody(Name enumName) { accept(LBRACE); ListBuffer defs = new ListBuffer(); - if (S.token() == COMMA) { - S.nextToken(); - } else if (S.token() != RBRACE && S.token() != SEMI) { + if (token.kind == COMMA) { + nextToken(); + } else if (token.kind != RBRACE && token.kind != SEMI) { defs.append(enumeratorDeclaration(enumName)); - while (S.token() == COMMA) { - S.nextToken(); - if (S.token() == RBRACE || S.token() == SEMI) break; + while (token.kind == COMMA) { + nextToken(); + if (token.kind == RBRACE || token.kind == SEMI) break; defs.append(enumeratorDeclaration(enumName)); } - if (S.token() != SEMI && S.token() != RBRACE) { - defs.append(syntaxError(S.pos(), "expected3", + if (token.kind != SEMI && token.kind != RBRACE) { + defs.append(syntaxError(token.pos, "expected3", COMMA, RBRACE, SEMI)); - S.nextToken(); + nextToken(); } } - if (S.token() == SEMI) { - S.nextToken(); - while (S.token() != RBRACE && S.token() != EOF) { + if (token.kind == SEMI) { + nextToken(); + while (token.kind != RBRACE && token.kind != EOF) { defs.appendList(classOrInterfaceBodyDeclaration(enumName, false)); - if (S.pos() <= errorEndPos) { + if (token.pos <= errorEndPos) { // error recovery skip(false, true, true, false); } @@ -2512,23 +2498,22 @@ public class JavacParser implements Parser { /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] */ JCTree enumeratorDeclaration(Name enumName) { - String dc = S.docComment(); + String dc = token.docComment; int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; - if (S.deprecatedFlag()) { + if (token.deprecatedFlag) { flags |= Flags.DEPRECATED; - S.resetDeprecatedFlag(); } - int pos = S.pos(); + int pos = token.pos; List annotations = annotationsOpt(); JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); List typeArgs = typeArgumentsOpt(); - int identPos = S.pos(); + int identPos = token.pos; Name name = ident(); - int createPos = S.pos(); - List args = (S.token() == LPAREN) + int createPos = token.pos; + List args = (token.kind == LPAREN) ? arguments() : List.nil(); JCClassDecl body = null; - if (S.token() == LBRACE) { + if (token.kind == LBRACE) { JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); List defs = classOrInterfaceBody(names.empty, false); body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); @@ -2538,7 +2523,7 @@ public class JavacParser implements Parser { JCIdent ident = F.at(identPos).Ident(enumName); JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); if (createPos != identPos) - storeEnd(create, S.prevEndPos()); + storeEnd(create, S.prevToken().endPos); ident = F.at(identPos).Ident(enumName); JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); attach(result, dc); @@ -2550,8 +2535,8 @@ public class JavacParser implements Parser { List typeList() { ListBuffer ts = new ListBuffer(); ts.append(parseType()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); ts.append(parseType()); } return ts.toList(); @@ -2562,16 +2547,16 @@ public class JavacParser implements Parser { */ List classOrInterfaceBody(Name className, boolean isInterface) { accept(LBRACE); - if (S.pos() <= errorEndPos) { + if (token.pos <= errorEndPos) { // error recovery skip(false, true, false, false); - if (S.token() == LBRACE) - S.nextToken(); + if (token.kind == LBRACE) + nextToken(); } ListBuffer defs = new ListBuffer(); - while (S.token() != RBRACE && S.token() != EOF) { + while (token.kind != RBRACE && token.kind != EOF) { defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); - if (S.pos() <= errorEndPos) { + if (token.pos <= errorEndPos) { // error recovery skip(false, true, true, false); } @@ -2598,23 +2583,23 @@ public class JavacParser implements Parser { * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) */ protected List classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { - if (S.token() == SEMI) { - S.nextToken(); + if (token.kind == SEMI) { + nextToken(); return List.nil(); } else { - String dc = S.docComment(); - int pos = S.pos(); + String dc = token.docComment; + int pos = token.pos; JCModifiers mods = modifiersOpt(); - if (S.token() == CLASS || - S.token() == INTERFACE || - allowEnums && S.token() == ENUM) { + if (token.kind == CLASS || + token.kind == INTERFACE || + allowEnums && token.kind == ENUM) { return List.of(classOrInterfaceOrEnumDeclaration(mods, dc)); - } else if (S.token() == LBRACE && !isInterface && + } else if (token.kind == LBRACE && !isInterface && (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && mods.annotations.isEmpty()) { return List.of(block(pos, mods.flags)); } else { - pos = S.pos(); + pos = token.pos; List typarams = typeParametersOpt(); // if there are type parameters but no modifiers, save the start // position of the method in the modifiers. @@ -2622,26 +2607,26 @@ public class JavacParser implements Parser { mods.pos = pos; storeEnd(mods, pos); } - Name name = S.name(); - pos = S.pos(); + Token tk = token; + pos = token.pos; JCExpression type; - boolean isVoid = S.token() == VOID; + boolean isVoid = token.kind == VOID; if (isVoid) { type = to(F.at(pos).TypeIdent(TypeTags.VOID)); - S.nextToken(); + nextToken(); } else { type = parseType(); } - if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { - if (isInterface || name != className) + if (token.kind == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { + if (isInterface || tk.name() != className) error(pos, "invalid.meth.decl.ret.type.req"); return List.of(methodDeclaratorRest( pos, mods, null, names.init, typarams, isInterface, true, dc)); } else { - pos = S.pos(); - name = ident(); - if (S.token() == LPAREN) { + pos = token.pos; + Name name = ident(); + if (token.kind == LPAREN) { return List.of(methodDeclaratorRest( pos, mods, type, name, typarams, isInterface, isVoid, dc)); @@ -2649,16 +2634,16 @@ public class JavacParser implements Parser { List defs = variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, new ListBuffer()).toList(); - storeEnd(defs.last(), S.endPos()); + storeEnd(defs.last(), token.endPos); accept(SEMI); return defs; } else { - pos = S.pos(); + pos = token.pos; List err = isVoid ? List.of(toP(F.at(pos).MethodDef(mods, name, type, typarams, List.nil(), List.nil(), null, null))) : null; - return List.of(syntaxError(S.pos(), err, "expected", LPAREN)); + return List.of(syntaxError(token.pos, err, "expected", LPAREN)); } } } @@ -2686,27 +2671,27 @@ public class JavacParser implements Parser { List params = formalParameters(); if (!isVoid) type = bracketsOpt(type); List thrown = List.nil(); - if (S.token() == THROWS) { - S.nextToken(); + if (token.kind == THROWS) { + nextToken(); thrown = qualidentList(); } JCBlock body = null; JCExpression defaultValue; - if (S.token() == LBRACE) { + if (token.kind == LBRACE) { body = block(); defaultValue = null; } else { - if (S.token() == DEFAULT) { + if (token.kind == DEFAULT) { accept(DEFAULT); defaultValue = annotationValue(); } else { defaultValue = null; } accept(SEMI); - if (S.pos() <= errorEndPos) { + if (token.pos <= errorEndPos) { // error recovery skip(false, true, false, false); - if (S.token() == LBRACE) { + if (token.kind == LBRACE) { body = block(); } } @@ -2725,8 +2710,8 @@ public class JavacParser implements Parser { List qualidentList() { ListBuffer ts = new ListBuffer(); ts.append(qualident()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); ts.append(qualident()); } return ts.toList(); @@ -2735,13 +2720,13 @@ public class JavacParser implements Parser { /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] */ List typeParametersOpt() { - if (S.token() == LT) { + if (token.kind == LT) { checkGenerics(); ListBuffer typarams = new ListBuffer(); - S.nextToken(); + nextToken(); typarams.append(typeParameter()); - while (S.token() == COMMA) { - S.nextToken(); + while (token.kind == COMMA) { + nextToken(); typarams.append(typeParameter()); } accept(GT); @@ -2756,14 +2741,14 @@ public class JavacParser implements Parser { * TypeVariable = Ident */ JCTypeParameter typeParameter() { - int pos = S.pos(); + int pos = token.pos; Name name = ident(); ListBuffer bounds = new ListBuffer(); - if (S.token() == EXTENDS) { - S.nextToken(); + if (token.kind == EXTENDS) { + nextToken(); bounds.append(parseType()); - while (S.token() == AMP) { - S.nextToken(); + while (token.kind == AMP) { + nextToken(); bounds.append(parseType()); } } @@ -2778,10 +2763,10 @@ public class JavacParser implements Parser { ListBuffer params = new ListBuffer(); JCVariableDecl lastParam = null; accept(LPAREN); - if (S.token() != RPAREN) { + if (token.kind != RPAREN) { params.append(lastParam = formalParameter()); - while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { - S.nextToken(); + while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) { + nextToken(); params.append(lastParam = formalParameter()); } } @@ -2802,11 +2787,11 @@ public class JavacParser implements Parser { protected JCVariableDecl formalParameter() { JCModifiers mods = optFinal(Flags.PARAMETER); JCExpression type = parseType(); - if (S.token() == ELLIPSIS) { + if (token.kind == ELLIPSIS) { checkVarargs(); mods.flags |= Flags.VARARGS; - type = to(F.at(S.pos()).TypeArray(type)); - S.nextToken(); + type = to(F.at(token.pos).TypeArray(type)); + nextToken(); } return variableDeclaratorId(mods, type); } @@ -2849,7 +2834,7 @@ public class JavacParser implements Parser { /** Return precedence of operator represented by token, * -1 if token is not a binary operator. @see TreeInfo.opPrec */ - static int prec(Token token) { + static int prec(TokenKind token) { int oc = optag(token); return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; } @@ -2869,7 +2854,7 @@ public class JavacParser implements Parser { /** Return operation tag of binary operator represented by token, * -1 if token is not a binary operator. */ - static int optag(Token token) { + static int optag(TokenKind token) { switch (token) { case BARBAR: return JCTree.OR; @@ -2941,7 +2926,7 @@ public class JavacParser implements Parser { /** Return operation tag of unary operator represented by token, * -1 if token is not a binary operator. */ - static int unoptag(Token token) { + static int unoptag(TokenKind token) { switch (token) { case PLUS: return JCTree.POS; @@ -2963,7 +2948,7 @@ public class JavacParser implements Parser { /** Return type tag of basic type represented by token, * -1 if token is not a basic type identifier. */ - static int typetag(Token token) { + static int typetag(TokenKind token) { switch (token) { case BYTE: return TypeTags.BYTE; @@ -2988,49 +2973,49 @@ public class JavacParser implements Parser { void checkGenerics() { if (!allowGenerics) { - error(S.pos(), "generics.not.supported.in.source", source.name); + error(token.pos, "generics.not.supported.in.source", source.name); allowGenerics = true; } } void checkVarargs() { if (!allowVarargs) { - error(S.pos(), "varargs.not.supported.in.source", source.name); + error(token.pos, "varargs.not.supported.in.source", source.name); allowVarargs = true; } } void checkForeach() { if (!allowForeach) { - error(S.pos(), "foreach.not.supported.in.source", source.name); + error(token.pos, "foreach.not.supported.in.source", source.name); allowForeach = true; } } void checkStaticImports() { if (!allowStaticImport) { - error(S.pos(), "static.import.not.supported.in.source", source.name); + error(token.pos, "static.import.not.supported.in.source", source.name); allowStaticImport = true; } } void checkAnnotations() { if (!allowAnnotations) { - error(S.pos(), "annotations.not.supported.in.source", source.name); + error(token.pos, "annotations.not.supported.in.source", source.name); allowAnnotations = true; } } void checkDiamond() { if (!allowDiamond) { - error(S.pos(), "diamond.not.supported.in.source", source.name); + error(token.pos, "diamond.not.supported.in.source", source.name); allowDiamond = true; } } void checkMulticatch() { if (!allowMulticatch) { - error(S.pos(), "multicatch.not.supported.in.source", source.name); + error(token.pos, "multicatch.not.supported.in.source", source.name); allowMulticatch = true; } } void checkTryWithResources() { if (!allowTWR) { - error(S.pos(), "try.with.resources.not.supported.in.source", source.name); + error(token.pos, "try.with.resources.not.supported.in.source", source.name); allowTWR = true; } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java similarity index 94% rename from langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java rename to langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java index e6d687d4ca9..680485efddb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/DocCommentScanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavadocTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, 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 @@ -25,9 +25,12 @@ package com.sun.tools.javac.parser; +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.parser.Tokens.Token; +import com.sun.tools.javac.util.*; + import java.nio.*; -import com.sun.tools.javac.util.*; import static com.sun.tools.javac.util.LayoutCharacters.*; /** An extension to the base lexical analyzer that captures @@ -40,26 +43,22 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class DocCommentScanner extends Scanner { +public class JavadocTokenizer extends JavaTokenizer { /** Create a scanner from the input buffer. buffer must implement * array() and compact(), and remaining() must be less than limit(). */ - protected DocCommentScanner(ScannerFactory fac, CharBuffer buffer) { + protected JavadocTokenizer(ScannerFactory fac, CharBuffer buffer) { super(fac, buffer); } /** Create a scanner from the input array. The array must have at * least a single character of extra space. */ - protected DocCommentScanner(ScannerFactory fac, char[] input, int inputLength) { + protected JavadocTokenizer(ScannerFactory fac, char[] input, int inputLength) { super(fac, input, inputLength); } - /** Starting position of the comment in original source - */ - private int pos; - /** The comment input buffer, index of next chacter to be read, * index of one past last character in buffer. */ @@ -178,6 +177,14 @@ public class DocCommentScanner extends Scanner { } } + @Override + public Token readToken() { + docComment = null; + Token tk = super.readToken(); + tk.docComment = docComment; + return tk; + } + /** * Read next character in doc comment, skipping over double '\' characters. * If a double '\' is skipped, put in the buffer and update buffer count. @@ -196,32 +203,17 @@ public class DocCommentScanner extends Scanner { } } - /* Reset doc comment before reading each new token - */ - public void nextToken() { - docComment = null; - super.nextToken(); - } - - /** - * Returns the documentation string of the current token. - */ - public String docComment() { - return docComment; - } - /** * Process a doc comment and make the string content available. * Strips leading whitespace and stars. */ @SuppressWarnings("fallthrough") - protected void processComment(CommentStyle style) { + protected void processComment(int pos, int endPos, CommentStyle style) { if (style != CommentStyle.JAVADOC) { return; } - pos = pos(); - buf = getRawCharacters(pos, endPos()); + buf = reader.getRawCharacters(pos, endPos); buflen = buf.length; bp = 0; col = 0; @@ -414,7 +406,7 @@ public class DocCommentScanner extends Scanner { * * @return a LineMap */ public Position.LineMap getLineMap() { - char[] buf = getRawCharacters(); + char[] buf = reader.getRawCharacters(); return Position.makeLineMap(buf, buf.length, true); } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java deleted file mode 100644 index 43386bf93f5..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Keywords.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.parser; - -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Log; -import com.sun.tools.javac.util.Name; -import com.sun.tools.javac.util.Names; - -import static com.sun.tools.javac.parser.Token.*; - -/** - * Map from Name to Token and Token to String. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Keywords { - public static final Context.Key keywordsKey = - new Context.Key(); - - public static Keywords instance(Context context) { - Keywords instance = context.get(keywordsKey); - if (instance == null) - instance = new Keywords(context); - return instance; - } - - private final Names names; - - protected Keywords(Context context) { - context.put(keywordsKey, this); - names = Names.instance(context); - - for (Token t : Token.values()) { - if (t.name != null) - enterKeyword(t.name, t); - else - tokenName[t.ordinal()] = null; - } - - key = new Token[maxKey+1]; - for (int i = 0; i <= maxKey; i++) key[i] = IDENTIFIER; - for (Token t : Token.values()) { - if (t.name != null) - key[tokenName[t.ordinal()].getIndex()] = t; - } - } - - - public Token key(Name name) { - return (name.getIndex() > maxKey) ? IDENTIFIER : key[name.getIndex()]; - } - - /** - * Keyword array. Maps name indices to Token. - */ - private final Token[] key; - - /** The number of the last entered keyword. - */ - private int maxKey = 0; - - /** The names of all tokens. - */ - private Name[] tokenName = new Name[Token.values().length]; - - private void enterKeyword(String s, Token token) { - Name n = names.fromString(s); - tokenName[token.ordinal()] = n; - if (n.getIndex() > maxKey) maxKey = n.getIndex(); - } -} diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java index 90f6afe124d..57d7a985e63 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Lexer.java @@ -25,7 +25,7 @@ package com.sun.tools.javac.parser; -import com.sun.tools.javac.util.*; +import com.sun.tools.javac.parser.Tokens.*; import com.sun.tools.javac.util.Position.LineMap; /** @@ -40,22 +40,26 @@ import com.sun.tools.javac.util.Position.LineMap; public interface Lexer { /** - * Has a @deprecated been encountered in last doc comment? - * This needs to be reset by client with resetDeprecatedFlag. + * Consume the next token. */ - boolean deprecatedFlag(); - - void resetDeprecatedFlag(); + void nextToken(); /** - * Returns the documentation string of the current token. + * Return current token. */ - String docComment(); + Token token(); /** - * Return the last character position of the current token. + * Return the last character position of the previous token. */ - int endPos(); + Token prevToken(); + + /** + * Splits the current token in two and return the first (splitted) token. + * For instance '<<<' is splitted into two tokens '<' and '<<' respectively, + * and the latter is returned. + */ + Token split(); /** * Return the position where a lexical error occurred; @@ -74,69 +78,4 @@ public interface Lexer { * @return a LineMap */ LineMap getLineMap(); - - /** - * Returns a copy of the input buffer, up to its inputLength. - * Unicode escape sequences are not translated. - */ - char[] getRawCharacters(); - - /** - * Returns a copy of a character array subset of the input buffer. - * The returned array begins at the beginIndex and - * extends to the character at index endIndex - 1. - * Thus the length of the substring is endIndex-beginIndex. - * This behavior is like - * String.substring(beginIndex, endIndex). - * Unicode escape sequences are not translated. - * - * @param beginIndex the beginning index, inclusive. - * @param endIndex the ending index, exclusive. - * @throws IndexOutOfBounds if either offset is outside of the - * array bounds - */ - char[] getRawCharacters(int beginIndex, int endIndex); - - /** - * Return the name of an identifier or token for the current token. - */ - Name name(); - - /** - * Read token. - */ - void nextToken(); - - /** - * Return the current token's position: a 0-based - * offset from beginning of the raw input stream - * (before unicode translation) - */ - int pos(); - - /** - * Return the last character position of the previous token. - */ - int prevEndPos(); - - /** - * Return the radix of a numeric literal token. - */ - int radix(); - - /** - * The value of a literal token, recorded as a string. - * For integers, leading 0x and 'l' suffixes are suppressed. - */ - String stringVal(); - - /** - * Return the current token, set by nextToken(). - */ - Token token(); - - /** - * Sets the current token. - */ - void token(Token token); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java index 709bd5f1018..ed70d0b27df 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java @@ -55,7 +55,7 @@ public class ParserFactory { final TreeMaker F; final Log log; - final Keywords keywords; + final Tokens tokens; final Source source; final Names names; final Options options; @@ -67,7 +67,7 @@ public class ParserFactory { this.F = TreeMaker.instance(context); this.log = Log.instance(context); this.names = Names.instance(context); - this.keywords = Keywords.instance(context); + this.tokens = Tokens.instance(context); this.source = Source.instance(context); this.options = Options.instance(context); this.scannerFactory = ScannerFactory.instance(context); diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java index f2d62db7fe8..41f50cb0110 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Scanner.java @@ -27,13 +27,11 @@ package com.sun.tools.javac.parser; import java.nio.*; -import com.sun.tools.javac.code.Source; -import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.util.*; +import com.sun.tools.javac.util.Position.LineMap; +import com.sun.tools.javac.parser.JavaTokenizer.*; - -import static com.sun.tools.javac.parser.Token.*; -import static com.sun.tools.javac.util.LayoutCharacters.*; +import static com.sun.tools.javac.parser.Tokens.*; /** The lexical analyzer maps an input stream consisting of * ASCII characters and Unicode escapes into a token sequence. @@ -45,119 +43,17 @@ import static com.sun.tools.javac.util.LayoutCharacters.*; */ public class Scanner implements Lexer { - private static boolean scannerDebug = false; - - /* Output variables; set by nextToken(): - */ + private Tokens tokens; /** The token, set by nextToken(). */ private Token token; - /** Allow hex floating-point literals. + /** The previous token, set by nextToken(). */ - private boolean allowHexFloats; - - /** Allow binary literals. - */ - private boolean allowBinaryLiterals; - - /** Allow underscores in literals. - */ - private boolean allowUnderscoresInLiterals; - - /** The source language setting. - */ - private Source source; - - /** The token's position, 0-based offset from beginning of text. - */ - private int pos; - - /** Character position just after the last character of the token. - */ - private int endPos; - - /** The last character position of the previous token. - */ - private int prevEndPos; - - /** The position where a lexical error occurred; - */ - private int errPos = Position.NOPOS; - - /** The name of an identifier or token: - */ - private Name name; - - /** The radix of a numeric literal token. - */ - private int radix; - - /** Has a @deprecated been encountered in last doc comment? - * this needs to be reset by client. - */ - protected boolean deprecatedFlag = false; - - /** A character buffer for literals. - */ - private char[] sbuf = new char[128]; - private int sp; - - /** The input buffer, index of next chacter to be read, - * index of one past last character in buffer. - */ - private char[] buf; - private int bp; - private int buflen; - private int eofPos; - - /** The current character. - */ - private char ch; - - /** The buffer index of the last converted unicode character - */ - private int unicodeConversionBp = -1; - - /** The log to be used for error reporting. - */ - private final Log log; - - /** The name table. */ - private final Names names; - - /** The keyword table. */ - private final Keywords keywords; - - /** Common code for constructors. */ - private Scanner(ScannerFactory fac) { - log = fac.log; - names = fac.names; - keywords = fac.keywords; - source = fac.source; - allowBinaryLiterals = source.allowBinaryLiterals(); - allowHexFloats = source.allowHexFloats(); - allowUnderscoresInLiterals = source.allowUnderscoresInLiterals(); - } - - private static final boolean hexFloatsWork = hexFloatsWork(); - private static boolean hexFloatsWork() { - try { - Float.valueOf("0x1.0p1"); - return true; - } catch (NumberFormatException ex) { - return false; - } - } - - /** Create a scanner from the input buffer. buffer must implement - * array() and compact(), and remaining() must be less than limit(). - */ - protected Scanner(ScannerFactory fac, CharBuffer buffer) { - this(fac, JavacFileManager.toArray(buffer), buffer.limit()); - } + private Token prevToken; + private JavaTokenizer tokenizer; /** * Create a scanner from the input array. This method might * modify the array. To avoid copying the input array, ensure @@ -169,972 +65,49 @@ public class Scanner implements Lexer { * @param inputLength the size of the input. * Must be positive and less than or equal to input.length. */ - protected Scanner(ScannerFactory fac, char[] input, int inputLength) { - this(fac); - eofPos = inputLength; - if (inputLength == input.length) { - if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) { - inputLength--; - } else { - char[] newInput = new char[inputLength + 1]; - System.arraycopy(input, 0, newInput, 0, input.length); - input = newInput; - } - } - buf = input; - buflen = inputLength; - buf[buflen] = EOI; - bp = -1; - scanChar(); + protected Scanner(ScannerFactory fac, CharBuffer buf) { + this(fac, new JavaTokenizer(fac, buf)); } - /** Report an error at the given position using the provided arguments. - */ - private void lexError(int pos, String key, Object... args) { - log.error(pos, key, args); - token = ERROR; - errPos = pos; + protected Scanner(ScannerFactory fac, char[] buf, int inputLength) { + this(fac, new JavaTokenizer(fac, buf, inputLength)); } - /** Report an error at the current token position using the provided - * arguments. - */ - private void lexError(String key, Object... args) { - lexError(pos, key, args); + protected Scanner(ScannerFactory fac, JavaTokenizer tokenizer) { + this.tokenizer = tokenizer; + tokens = fac.tokens; + token = prevToken = DUMMY; } - /** Convert an ASCII digit from its base (8, 10, or 16) - * to its value. - */ - private int digit(int base) { - char c = ch; - int result = Character.digit(c, base); - if (result >= 0 && c > 0x7f) { - lexError(pos+1, "illegal.nonascii.digit"); - ch = "0123456789abcdef".charAt(result); - } - return result; - } - - /** Convert unicode escape; bp points to initial '\' character - * (Spec 3.3). - */ - private void convertUnicode() { - if (ch == '\\' && unicodeConversionBp != bp) { - bp++; ch = buf[bp]; - if (ch == 'u') { - do { - bp++; ch = buf[bp]; - } while (ch == 'u'); - int limit = bp + 3; - if (limit < buflen) { - int d = digit(16); - int code = d; - while (bp < limit && d >= 0) { - bp++; ch = buf[bp]; - d = digit(16); - code = (code << 4) + d; - } - if (d >= 0) { - ch = (char)code; - unicodeConversionBp = bp; - return; - } - } - lexError(bp, "illegal.unicode.esc"); - } else { - bp--; - ch = '\\'; - } - } - } - - /** Read next character. - */ - private void scanChar() { - ch = buf[++bp]; - if (ch == '\\') { - convertUnicode(); - } - } - - /** Read next character in comment, skipping over double '\' characters. - */ - private void scanCommentChar() { - scanChar(); - if (ch == '\\') { - if (buf[bp+1] == '\\' && unicodeConversionBp != bp) { - bp++; - } else { - convertUnicode(); - } - } - } - - /** Append a character to sbuf. - */ - private void putChar(char ch) { - if (sp == sbuf.length) { - char[] newsbuf = new char[sbuf.length * 2]; - System.arraycopy(sbuf, 0, newsbuf, 0, sbuf.length); - sbuf = newsbuf; - } - sbuf[sp++] = ch; - } - - /** Read next character in character or string literal and copy into sbuf. - */ - private void scanLitChar() { - if (ch == '\\') { - if (buf[bp+1] == '\\' && unicodeConversionBp != bp) { - bp++; - putChar('\\'); - scanChar(); - } else { - scanChar(); - switch (ch) { - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - char leadch = ch; - int oct = digit(8); - scanChar(); - if ('0' <= ch && ch <= '7') { - oct = oct * 8 + digit(8); - scanChar(); - if (leadch <= '3' && '0' <= ch && ch <= '7') { - oct = oct * 8 + digit(8); - scanChar(); - } - } - putChar((char)oct); - break; - case 'b': - putChar('\b'); scanChar(); break; - case 't': - putChar('\t'); scanChar(); break; - case 'n': - putChar('\n'); scanChar(); break; - case 'f': - putChar('\f'); scanChar(); break; - case 'r': - putChar('\r'); scanChar(); break; - case '\'': - putChar('\''); scanChar(); break; - case '\"': - putChar('\"'); scanChar(); break; - case '\\': - putChar('\\'); scanChar(); break; - default: - lexError(bp, "illegal.esc.char"); - } - } - } else if (bp != buflen) { - putChar(ch); scanChar(); - } - } - - private void scanDigits(int digitRadix) { - char saveCh; - int savePos; - do { - if (ch != '_') { - putChar(ch); - } else { - if (!allowUnderscoresInLiterals) { - lexError("unsupported.underscore.lit", source.name); - allowUnderscoresInLiterals = true; - } - } - saveCh = ch; - savePos = bp; - scanChar(); - } while (digit(digitRadix) >= 0 || ch == '_'); - if (saveCh == '_') - lexError(savePos, "illegal.underscore"); - } - - /** Read fractional part of hexadecimal floating point number. - */ - private void scanHexExponentAndSuffix() { - if (ch == 'p' || ch == 'P') { - putChar(ch); - scanChar(); - skipIllegalUnderscores(); - if (ch == '+' || ch == '-') { - putChar(ch); - scanChar(); - } - skipIllegalUnderscores(); - if ('0' <= ch && ch <= '9') { - scanDigits(10); - if (!allowHexFloats) { - lexError("unsupported.fp.lit", source.name); - allowHexFloats = true; - } - else if (!hexFloatsWork) - lexError("unsupported.cross.fp.lit"); - } else - lexError("malformed.fp.lit"); - } else { - lexError("malformed.fp.lit"); - } - if (ch == 'f' || ch == 'F') { - putChar(ch); - scanChar(); - token = FLOATLITERAL; - } else { - if (ch == 'd' || ch == 'D') { - putChar(ch); - scanChar(); - } - token = DOUBLELITERAL; - } - } - - /** Read fractional part of floating point number. - */ - private void scanFraction() { - skipIllegalUnderscores(); - if ('0' <= ch && ch <= '9') { - scanDigits(10); - } - int sp1 = sp; - if (ch == 'e' || ch == 'E') { - putChar(ch); - scanChar(); - skipIllegalUnderscores(); - if (ch == '+' || ch == '-') { - putChar(ch); - scanChar(); - } - skipIllegalUnderscores(); - if ('0' <= ch && ch <= '9') { - scanDigits(10); - return; - } - lexError("malformed.fp.lit"); - sp = sp1; - } - } - - /** Read fractional part and 'd' or 'f' suffix of floating point number. - */ - private void scanFractionAndSuffix() { - this.radix = 10; - scanFraction(); - if (ch == 'f' || ch == 'F') { - putChar(ch); - scanChar(); - token = FLOATLITERAL; - } else { - if (ch == 'd' || ch == 'D') { - putChar(ch); - scanChar(); - } - token = DOUBLELITERAL; - } - } - - /** Read fractional part and 'd' or 'f' suffix of floating point number. - */ - private void scanHexFractionAndSuffix(boolean seendigit) { - this.radix = 16; - Assert.check(ch == '.'); - putChar(ch); - scanChar(); - skipIllegalUnderscores(); - if (digit(16) >= 0) { - seendigit = true; - scanDigits(16); - } - if (!seendigit) - lexError("invalid.hex.number"); - else - scanHexExponentAndSuffix(); - } - - private void skipIllegalUnderscores() { - if (ch == '_') { - lexError(bp, "illegal.underscore"); - while (ch == '_') - scanChar(); - } - } - - /** Read a number. - * @param radix The radix of the number; one of 2, j8, 10, 16. - */ - private void scanNumber(int radix) { - this.radix = radix; - // for octal, allow base-10 digit in case it's a float literal - int digitRadix = (radix == 8 ? 10 : radix); - boolean seendigit = false; - if (digit(digitRadix) >= 0) { - seendigit = true; - scanDigits(digitRadix); - } - if (radix == 16 && ch == '.') { - scanHexFractionAndSuffix(seendigit); - } else if (seendigit && radix == 16 && (ch == 'p' || ch == 'P')) { - scanHexExponentAndSuffix(); - } else if (digitRadix == 10 && ch == '.') { - putChar(ch); - scanChar(); - scanFractionAndSuffix(); - } else if (digitRadix == 10 && - (ch == 'e' || ch == 'E' || - ch == 'f' || ch == 'F' || - ch == 'd' || ch == 'D')) { - scanFractionAndSuffix(); - } else { - if (ch == 'l' || ch == 'L') { - scanChar(); - token = LONGLITERAL; - } else { - token = INTLITERAL; - } - } - } - - /** Read an identifier. - */ - private void scanIdent() { - boolean isJavaIdentifierPart; - char high; - do { - if (sp == sbuf.length) putChar(ch); else sbuf[sp++] = ch; - // optimization, was: putChar(ch); - - scanChar(); - switch (ch) { - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case '$': case '_': - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case '\u0000': case '\u0001': case '\u0002': case '\u0003': - case '\u0004': case '\u0005': case '\u0006': case '\u0007': - case '\u0008': case '\u000E': case '\u000F': case '\u0010': - case '\u0011': case '\u0012': case '\u0013': case '\u0014': - case '\u0015': case '\u0016': case '\u0017': - case '\u0018': case '\u0019': case '\u001B': - case '\u007F': - break; - case '\u001A': // EOI is also a legal identifier part - if (bp >= buflen) { - name = names.fromChars(sbuf, 0, sp); - token = keywords.key(name); - return; - } - break; - default: - if (ch < '\u0080') { - // all ASCII range chars already handled, above - isJavaIdentifierPart = false; - } else { - high = scanSurrogates(); - if (high != 0) { - if (sp == sbuf.length) { - putChar(high); - } else { - sbuf[sp++] = high; - } - isJavaIdentifierPart = Character.isJavaIdentifierPart( - Character.toCodePoint(high, ch)); - } else { - isJavaIdentifierPart = Character.isJavaIdentifierPart(ch); - } - } - if (!isJavaIdentifierPart) { - name = names.fromChars(sbuf, 0, sp); - token = keywords.key(name); - return; - } - } - } while (true); - } - - /** Are surrogates supported? - */ - final static boolean surrogatesSupported = surrogatesSupported(); - private static boolean surrogatesSupported() { - try { - Character.isHighSurrogate('a'); - return true; - } catch (NoSuchMethodError ex) { - return false; - } - } - - /** Scan surrogate pairs. If 'ch' is a high surrogate and - * the next character is a low surrogate, then put the low - * surrogate in 'ch', and return the high surrogate. - * otherwise, just return 0. - */ - private char scanSurrogates() { - if (surrogatesSupported && Character.isHighSurrogate(ch)) { - char high = ch; - - scanChar(); - - if (Character.isLowSurrogate(ch)) { - return high; - } - - ch = high; - } - - return 0; - } - - /** Return true if ch can be part of an operator. - */ - private boolean isSpecial(char ch) { - switch (ch) { - case '!': case '%': case '&': case '*': case '?': - case '+': case '-': case ':': case '<': case '=': - case '>': case '^': case '|': case '~': - case '@': - return true; - default: - return false; - } - } - - /** Read longest possible sequence of special characters and convert - * to token. - */ - private void scanOperator() { - while (true) { - putChar(ch); - Name newname = names.fromChars(sbuf, 0, sp); - if (keywords.key(newname) == IDENTIFIER) { - sp--; - break; - } - name = newname; - token = keywords.key(newname); - scanChar(); - if (!isSpecial(ch)) break; - } - } - - /** - * Scan a documention comment; determine if a deprecated tag is present. - * Called once the initial /, * have been skipped, positioned at the second * - * (which is treated as the beginning of the first line). - * Stops positioned at the closing '/'. - */ - @SuppressWarnings("fallthrough") - private void scanDocComment() { - boolean deprecatedPrefix = false; - - forEachLine: - while (bp < buflen) { - - // Skip optional WhiteSpace at beginning of line - while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) { - scanCommentChar(); - } - - // Skip optional consecutive Stars - while (bp < buflen && ch == '*') { - scanCommentChar(); - if (ch == '/') { - return; - } - } - - // Skip optional WhiteSpace after Stars - while (bp < buflen && (ch == ' ' || ch == '\t' || ch == FF)) { - scanCommentChar(); - } - - deprecatedPrefix = false; - // At beginning of line in the JavaDoc sense. - if (bp < buflen && ch == '@' && !deprecatedFlag) { - scanCommentChar(); - if (bp < buflen && ch == 'd') { - scanCommentChar(); - if (bp < buflen && ch == 'e') { - scanCommentChar(); - if (bp < buflen && ch == 'p') { - scanCommentChar(); - if (bp < buflen && ch == 'r') { - scanCommentChar(); - if (bp < buflen && ch == 'e') { - scanCommentChar(); - if (bp < buflen && ch == 'c') { - scanCommentChar(); - if (bp < buflen && ch == 'a') { - scanCommentChar(); - if (bp < buflen && ch == 't') { - scanCommentChar(); - if (bp < buflen && ch == 'e') { - scanCommentChar(); - if (bp < buflen && ch == 'd') { - deprecatedPrefix = true; - scanCommentChar(); - }}}}}}}}}}} - if (deprecatedPrefix && bp < buflen) { - if (Character.isWhitespace(ch)) { - deprecatedFlag = true; - } else if (ch == '*') { - scanCommentChar(); - if (ch == '/') { - deprecatedFlag = true; - return; - } - } - } - - // Skip rest of line - while (bp < buflen) { - switch (ch) { - case '*': - scanCommentChar(); - if (ch == '/') { - return; - } - break; - case CR: // (Spec 3.4) - scanCommentChar(); - if (ch != LF) { - continue forEachLine; - } - /* fall through to LF case */ - case LF: // (Spec 3.4) - scanCommentChar(); - continue forEachLine; - default: - scanCommentChar(); - } - } // rest of line - } // forEachLine - return; - } - - /** The value of a literal token, recorded as a string. - * For integers, leading 0x and 'l' suffixes are suppressed. - */ - public String stringVal() { - return new String(sbuf, 0, sp); - } - - /** Read token. - */ - public void nextToken() { - - try { - prevEndPos = endPos; - sp = 0; - - while (true) { - pos = bp; - switch (ch) { - case ' ': // (Spec 3.6) - case '\t': // (Spec 3.6) - case FF: // (Spec 3.6) - do { - scanChar(); - } while (ch == ' ' || ch == '\t' || ch == FF); - endPos = bp; - processWhiteSpace(); - break; - case LF: // (Spec 3.4) - scanChar(); - endPos = bp; - processLineTerminator(); - break; - case CR: // (Spec 3.4) - scanChar(); - if (ch == LF) { - scanChar(); - } - endPos = bp; - processLineTerminator(); - break; - case 'A': case 'B': case 'C': case 'D': case 'E': - case 'F': case 'G': case 'H': case 'I': case 'J': - case 'K': case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': case 'T': - case 'U': case 'V': case 'W': case 'X': case 'Y': - case 'Z': - case 'a': case 'b': case 'c': case 'd': case 'e': - case 'f': case 'g': case 'h': case 'i': case 'j': - case 'k': case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': - case 'z': - case '$': case '_': - scanIdent(); - return; - case '0': - scanChar(); - if (ch == 'x' || ch == 'X') { - scanChar(); - skipIllegalUnderscores(); - if (ch == '.') { - scanHexFractionAndSuffix(false); - } else if (digit(16) < 0) { - lexError("invalid.hex.number"); - } else { - scanNumber(16); - } - } else if (ch == 'b' || ch == 'B') { - if (!allowBinaryLiterals) { - lexError("unsupported.binary.lit", source.name); - allowBinaryLiterals = true; - } - scanChar(); - skipIllegalUnderscores(); - if (digit(2) < 0) { - lexError("invalid.binary.number"); - } else { - scanNumber(2); - } - } else { - putChar('0'); - if (ch == '_') { - int savePos = bp; - do { - scanChar(); - } while (ch == '_'); - if (digit(10) < 0) { - lexError(savePos, "illegal.underscore"); - } - } - scanNumber(8); - } - return; - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - scanNumber(10); - return; - case '.': - scanChar(); - if ('0' <= ch && ch <= '9') { - putChar('.'); - scanFractionAndSuffix(); - } else if (ch == '.') { - putChar('.'); putChar('.'); - scanChar(); - if (ch == '.') { - scanChar(); - putChar('.'); - token = ELLIPSIS; - } else { - lexError("malformed.fp.lit"); - } - } else { - token = DOT; - } - return; - case ',': - scanChar(); token = COMMA; return; - case ';': - scanChar(); token = SEMI; return; - case '(': - scanChar(); token = LPAREN; return; - case ')': - scanChar(); token = RPAREN; return; - case '[': - scanChar(); token = LBRACKET; return; - case ']': - scanChar(); token = RBRACKET; return; - case '{': - scanChar(); token = LBRACE; return; - case '}': - scanChar(); token = RBRACE; return; - case '/': - scanChar(); - if (ch == '/') { - do { - scanCommentChar(); - } while (ch != CR && ch != LF && bp < buflen); - if (bp < buflen) { - endPos = bp; - processComment(CommentStyle.LINE); - } - break; - } else if (ch == '*') { - scanChar(); - CommentStyle style; - if (ch == '*') { - style = CommentStyle.JAVADOC; - scanDocComment(); - } else { - style = CommentStyle.BLOCK; - while (bp < buflen) { - if (ch == '*') { - scanChar(); - if (ch == '/') break; - } else { - scanCommentChar(); - } - } - } - if (ch == '/') { - scanChar(); - endPos = bp; - processComment(style); - break; - } else { - lexError("unclosed.comment"); - return; - } - } else if (ch == '=') { - name = names.slashequals; - token = SLASHEQ; - scanChar(); - } else { - name = names.slash; - token = SLASH; - } - return; - case '\'': - scanChar(); - if (ch == '\'') { - lexError("empty.char.lit"); - } else { - if (ch == CR || ch == LF) - lexError(pos, "illegal.line.end.in.char.lit"); - scanLitChar(); - if (ch == '\'') { - scanChar(); - token = CHARLITERAL; - } else { - lexError(pos, "unclosed.char.lit"); - } - } - return; - case '\"': - scanChar(); - while (ch != '\"' && ch != CR && ch != LF && bp < buflen) - scanLitChar(); - if (ch == '\"') { - token = STRINGLITERAL; - scanChar(); - } else { - lexError(pos, "unclosed.str.lit"); - } - return; - default: - if (isSpecial(ch)) { - scanOperator(); - } else { - boolean isJavaIdentifierStart; - if (ch < '\u0080') { - // all ASCII range chars already handled, above - isJavaIdentifierStart = false; - } else { - char high = scanSurrogates(); - if (high != 0) { - if (sp == sbuf.length) { - putChar(high); - } else { - sbuf[sp++] = high; - } - - isJavaIdentifierStart = Character.isJavaIdentifierStart( - Character.toCodePoint(high, ch)); - } else { - isJavaIdentifierStart = Character.isJavaIdentifierStart(ch); - } - } - if (isJavaIdentifierStart) { - scanIdent(); - } else if (bp == buflen || ch == EOI && bp+1 == buflen) { // JLS 3.5 - token = EOF; - pos = bp = eofPos; - } else { - lexError("illegal.char", String.valueOf((int)ch)); - scanChar(); - } - } - return; - } - } - } finally { - endPos = bp; - if (scannerDebug) - System.out.println("nextToken(" + pos - + "," + endPos + ")=|" + - new String(getRawCharacters(pos, endPos)) - + "|"); - } - } - - /** Return the current token, set by nextToken(). - */ public Token token() { return token; } - /** 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; + public Token prevToken() { + return prevToken; } - /** Return the current token's position: a 0-based - * offset from beginning of the raw input stream - * (before unicode translation) - */ - public int pos() { - return pos; + public void nextToken() { + prevToken = token; + token = tokenizer.readToken(); } - /** Return the last character position of the current token. - */ - public int endPos() { - return endPos; + public Token split() { + Token[] splitTokens = token.split(tokens); + prevToken = splitTokens[0]; + token = splitTokens[1]; + return token; } - /** Return the last character position of the previous token. - */ - public int prevEndPos() { - return prevEndPos; + public LineMap getLineMap() { + return tokenizer.getLineMap(); } - /** Return the position where a lexical error occurred; - */ public int errPos() { - return errPos; + return tokenizer.errPos(); } - /** Set the position where a lexical error occurred; - */ public void errPos(int pos) { - errPos = pos; + tokenizer.errPos(pos); } - - /** Return the name of an identifier or token for the current token. - */ - public Name name() { - return name; - } - - /** Return the radix of a numeric literal token. - */ - public int radix() { - return radix; - } - - /** Has a @deprecated been encountered in last doc comment? - * This needs to be reset by client with resetDeprecatedFlag. - */ - public boolean deprecatedFlag() { - return deprecatedFlag; - } - - public void resetDeprecatedFlag() { - deprecatedFlag = false; - } - - /** - * Returns the documentation string of the current token. - */ - public String docComment() { - return null; - } - - /** - * Returns a copy of the input buffer, up to its inputLength. - * Unicode escape sequences are not translated. - */ - public char[] getRawCharacters() { - char[] chars = new char[buflen]; - System.arraycopy(buf, 0, chars, 0, buflen); - return chars; - } - - /** - * Returns a copy of a character array subset of the input buffer. - * The returned array begins at the beginIndex and - * extends to the character at index endIndex - 1. - * Thus the length of the substring is endIndex-beginIndex. - * This behavior is like - * String.substring(beginIndex, endIndex). - * Unicode escape sequences are not translated. - * - * @param beginIndex the beginning index, inclusive. - * @param endIndex the ending index, exclusive. - * @throws IndexOutOfBounds if either offset is outside of the - * array bounds - */ - public char[] getRawCharacters(int beginIndex, int endIndex) { - int length = endIndex - beginIndex; - char[] chars = new char[length]; - System.arraycopy(buf, beginIndex, chars, 0, length); - return chars; - } - - public enum CommentStyle { - LINE, - BLOCK, - JAVADOC, - } - - /** - * Called when a complete comment has been scanned. pos and endPos - * will mark the comment boundary. - */ - protected void processComment(CommentStyle style) { - if (scannerDebug) - System.out.println("processComment(" + pos - + "," + endPos + "," + style + ")=|" - + new String(getRawCharacters(pos, endPos)) - + "|"); - } - - /** - * Called when a complete whitespace run has been scanned. pos and endPos - * will mark the whitespace boundary. - */ - protected void processWhiteSpace() { - if (scannerDebug) - System.out.println("processWhitespace(" + pos - + "," + endPos + ")=|" + - new String(getRawCharacters(pos, endPos)) - + "|"); - } - - /** - * Called when a line terminator has been processed. - */ - protected void processLineTerminator() { - if (scannerDebug) - System.out.println("processTerminator(" + pos - + "," + endPos + ")=|" + - new String(getRawCharacters(pos, endPos)) - + "|"); - } - - /** Build a map for translating between line numbers and - * positions in the input. - * - * @return a LineMap */ - public Position.LineMap getLineMap() { - return Position.makeLineMap(buf, buflen, false); - } - } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java b/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java index 86c9bb2b11c..d03d77b62cd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ScannerFactory.java @@ -57,7 +57,7 @@ public class ScannerFactory { final Log log; final Names names; final Source source; - final Keywords keywords; + final Tokens tokens; /** Create a new scanner factory. */ protected ScannerFactory(Context context) { @@ -65,14 +65,14 @@ public class ScannerFactory { this.log = Log.instance(context); this.names = Names.instance(context); this.source = Source.instance(context); - this.keywords = Keywords.instance(context); + this.tokens = Tokens.instance(context); } public Scanner newScanner(CharSequence input, boolean keepDocComments) { if (input instanceof CharBuffer) { CharBuffer buf = (CharBuffer) input; if (keepDocComments) - return new DocCommentScanner(this, buf); + return new Scanner(this, new JavadocTokenizer(this, buf)); else return new Scanner(this, buf); } else { @@ -83,7 +83,7 @@ public class ScannerFactory { public Scanner newScanner(char[] input, int inputLength, boolean keepDocComments) { if (keepDocComments) - return new DocCommentScanner(this, input, inputLength); + return new Scanner(this, new JavadocTokenizer(this, input, inputLength)); else return new Scanner(this, input, inputLength); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Token.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Token.java deleted file mode 100644 index 8fec6f8aeb7..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Token.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.parser; - -import java.util.Locale; - -import com.sun.tools.javac.api.Formattable; -import com.sun.tools.javac.api.Messages; - -/** An interface that defines codes for Java source tokens - * returned from lexical analysis. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public enum Token implements Formattable { - EOF, - ERROR, - IDENTIFIER, - ABSTRACT("abstract"), - ASSERT("assert"), - BOOLEAN("boolean"), - BREAK("break"), - BYTE("byte"), - CASE("case"), - CATCH("catch"), - CHAR("char"), - CLASS("class"), - CONST("const"), - CONTINUE("continue"), - DEFAULT("default"), - DO("do"), - DOUBLE("double"), - ELSE("else"), - ENUM("enum"), - EXTENDS("extends"), - FINAL("final"), - FINALLY("finally"), - FLOAT("float"), - FOR("for"), - GOTO("goto"), - IF("if"), - IMPLEMENTS("implements"), - IMPORT("import"), - INSTANCEOF("instanceof"), - INT("int"), - INTERFACE("interface"), - LONG("long"), - NATIVE("native"), - NEW("new"), - PACKAGE("package"), - PRIVATE("private"), - PROTECTED("protected"), - PUBLIC("public"), - RETURN("return"), - SHORT("short"), - STATIC("static"), - STRICTFP("strictfp"), - SUPER("super"), - SWITCH("switch"), - SYNCHRONIZED("synchronized"), - THIS("this"), - THROW("throw"), - THROWS("throws"), - TRANSIENT("transient"), - TRY("try"), - VOID("void"), - VOLATILE("volatile"), - WHILE("while"), - INTLITERAL, - LONGLITERAL, - FLOATLITERAL, - DOUBLELITERAL, - CHARLITERAL, - STRINGLITERAL, - TRUE("true"), - FALSE("false"), - NULL("null"), - LPAREN("("), - RPAREN(")"), - LBRACE("{"), - RBRACE("}"), - LBRACKET("["), - RBRACKET("]"), - SEMI(";"), - COMMA(","), - DOT("."), - ELLIPSIS("..."), - EQ("="), - GT(">"), - LT("<"), - BANG("!"), - TILDE("~"), - QUES("?"), - COLON(":"), - EQEQ("=="), - LTEQ("<="), - GTEQ(">="), - BANGEQ("!="), - AMPAMP("&&"), - BARBAR("||"), - PLUSPLUS("++"), - SUBSUB("--"), - PLUS("+"), - SUB("-"), - STAR("*"), - SLASH("/"), - AMP("&"), - BAR("|"), - CARET("^"), - PERCENT("%"), - LTLT("<<"), - GTGT(">>"), - GTGTGT(">>>"), - PLUSEQ("+="), - SUBEQ("-="), - STAREQ("*="), - SLASHEQ("/="), - AMPEQ("&="), - BAREQ("|="), - CARETEQ("^="), - PERCENTEQ("%="), - LTLTEQ("<<="), - GTGTEQ(">>="), - GTGTGTEQ(">>>="), - MONKEYS_AT("@"), - CUSTOM; - - Token() { - this(null); - } - Token(String name) { - this.name = name; - } - - public final String name; - - public String toString() { - switch (this) { - case IDENTIFIER: - return "token.identifier"; - case CHARLITERAL: - return "token.character"; - case STRINGLITERAL: - return "token.string"; - case INTLITERAL: - return "token.integer"; - case LONGLITERAL: - return "token.long-integer"; - case FLOATLITERAL: - return "token.float"; - case DOUBLELITERAL: - return "token.double"; - case ERROR: - return "token.bad-symbol"; - case EOF: - return "token.end-of-input"; - case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN: - case LBRACKET: case RBRACKET: case LBRACE: case RBRACE: - return "'" + name + "'"; - default: - return name; - } - } - - public String getKind() { - return "Token"; - } - - public String toString(Locale locale, Messages messages) { - return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString()); - } -} diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java new file mode 100644 index 00000000000..934dfb90520 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java @@ -0,0 +1,423 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.parser; + +import java.util.Locale; + +import com.sun.tools.javac.api.Formattable; +import com.sun.tools.javac.api.Messages; +import com.sun.tools.javac.parser.Tokens.Token.Tag; +import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Names; + +/** A class that defines codes/utilities for Java source tokens + * returned from lexical analysis. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class Tokens { + + private final Names names; + + /** + * Keyword array. Maps name indices to Token. + */ + private final TokenKind[] key; + + /** The number of the last entered keyword. + */ + private int maxKey = 0; + + /** The names of all tokens. + */ + private Name[] tokenName = new Name[TokenKind.values().length]; + + public static final Context.Key tokensKey = + new Context.Key(); + + public static Tokens instance(Context context) { + Tokens instance = context.get(tokensKey); + if (instance == null) + instance = new Tokens(context); + return instance; + } + + protected Tokens(Context context) { + context.put(tokensKey, this); + names = Names.instance(context); + + for (TokenKind t : TokenKind.values()) { + if (t.name != null) + enterKeyword(t.name, t); + else + tokenName[t.ordinal()] = null; + } + + key = new TokenKind[maxKey+1]; + for (int i = 0; i <= maxKey; i++) key[i] = TokenKind.IDENTIFIER; + for (TokenKind t : TokenKind.values()) { + if (t.name != null) + key[tokenName[t.ordinal()].getIndex()] = t; + } + } + + private void enterKeyword(String s, TokenKind token) { + Name n = names.fromString(s); + tokenName[token.ordinal()] = n; + if (n.getIndex() > maxKey) maxKey = n.getIndex(); + } + + /** + * Create a new token given a name; if the name corresponds to a token name, + * a new token of the corresponding kind is returned; otherwise, an + * identifier token is returned. + */ + TokenKind lookupKind(Name name) { + return (name.getIndex() > maxKey) ? TokenKind.IDENTIFIER : key[name.getIndex()]; + } + + TokenKind lookupKind(String name) { + return lookupKind(names.fromString(name)); + } + + /** + * This enum defines all tokens used by the javac scanner. A token is + * optionally associated with a name. + */ + public enum TokenKind implements Formattable { + EOF(), + ERROR(), + IDENTIFIER(Tag.NAMED), + ABSTRACT("abstract"), + ASSERT("assert", Tag.NAMED), + BOOLEAN("boolean", Tag.NAMED), + BREAK("break"), + BYTE("byte", Tag.NAMED), + CASE("case"), + CATCH("catch"), + CHAR("char", Tag.NAMED), + CLASS("class"), + CONST("const"), + CONTINUE("continue"), + DEFAULT("default"), + DO("do"), + DOUBLE("double", Tag.NAMED), + ELSE("else"), + ENUM("enum", Tag.NAMED), + EXTENDS("extends"), + FINAL("final"), + FINALLY("finally"), + FLOAT("float", Tag.NAMED), + FOR("for"), + GOTO("goto"), + IF("if"), + IMPLEMENTS("implements"), + IMPORT("import"), + INSTANCEOF("instanceof"), + INT("int", Tag.NAMED), + INTERFACE("interface"), + LONG("long", Tag.NAMED), + NATIVE("native"), + NEW("new"), + PACKAGE("package"), + PRIVATE("private"), + PROTECTED("protected"), + PUBLIC("public"), + RETURN("return"), + SHORT("short", Tag.NAMED), + STATIC("static"), + STRICTFP("strictfp"), + SUPER("super", Tag.NAMED), + SWITCH("switch"), + SYNCHRONIZED("synchronized"), + THIS("this", Tag.NAMED), + THROW("throw"), + THROWS("throws"), + TRANSIENT("transient"), + TRY("try"), + VOID("void", Tag.NAMED), + VOLATILE("volatile"), + WHILE("while"), + INTLITERAL(Tag.NUMERIC), + LONGLITERAL(Tag.NUMERIC), + FLOATLITERAL(Tag.NUMERIC), + DOUBLELITERAL(Tag.NUMERIC), + CHARLITERAL(Tag.NUMERIC), + STRINGLITERAL(Tag.STRING), + TRUE("true", Tag.NAMED), + FALSE("false", Tag.NAMED), + NULL("null", Tag.NAMED), + LPAREN("("), + RPAREN(")"), + LBRACE("{"), + RBRACE("}"), + LBRACKET("["), + RBRACKET("]"), + SEMI(";"), + COMMA(","), + DOT("."), + ELLIPSIS("..."), + EQ("="), + GT(">"), + LT("<"), + BANG("!"), + TILDE("~"), + QUES("?"), + COLON(":"), + EQEQ("=="), + LTEQ("<="), + GTEQ(">="), + BANGEQ("!="), + AMPAMP("&&"), + BARBAR("||"), + PLUSPLUS("++"), + SUBSUB("--"), + PLUS("+"), + SUB("-"), + STAR("*"), + SLASH("/"), + AMP("&"), + BAR("|"), + CARET("^"), + PERCENT("%"), + LTLT("<<"), + GTGT(">>"), + GTGTGT(">>>"), + PLUSEQ("+="), + SUBEQ("-="), + STAREQ("*="), + SLASHEQ("/="), + AMPEQ("&="), + BAREQ("|="), + CARETEQ("^="), + PERCENTEQ("%="), + LTLTEQ("<<="), + GTGTEQ(">>="), + GTGTGTEQ(">>>="), + MONKEYS_AT("@"), + CUSTOM; + + public final String name; + public final Tag tag; + + TokenKind() { + this(null, Tag.DEFAULT); + } + + TokenKind(String name) { + this(name, Tag.DEFAULT); + } + + TokenKind(Tag tag) { + this(null, tag); + } + + TokenKind(String name, Tag tag) { + this.name = name; + this.tag = tag; + } + + public String toString() { + switch (this) { + case IDENTIFIER: + return "token.identifier"; + case CHARLITERAL: + return "token.character"; + case STRINGLITERAL: + return "token.string"; + case INTLITERAL: + return "token.integer"; + case LONGLITERAL: + return "token.long-integer"; + case FLOATLITERAL: + return "token.float"; + case DOUBLELITERAL: + return "token.double"; + case ERROR: + return "token.bad-symbol"; + case EOF: + return "token.end-of-input"; + case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN: + case LBRACKET: case RBRACKET: case LBRACE: case RBRACE: + return "'" + name + "'"; + default: + return name; + } + } + + public String getKind() { + return "Token"; + } + + public String toString(Locale locale, Messages messages) { + return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString()); + } + } + + /** + * This is the class representing a javac token. Each token has several fields + * that are set by the javac lexer (i.e. start/end position, string value, etc). + */ + public static class Token { + + /** tags constants **/ + enum Tag { + DEFAULT, + NAMED, + STRING, + NUMERIC; + } + + /** The token kind */ + public final TokenKind kind; + + /** The start position of this token */ + public final int pos; + + /** The end position of this token */ + public final int endPos; + + /** Is this token preceeded by a deprecated comment? */ + public final boolean deprecatedFlag; + + /** Is this token preceeded by a deprecated comment? */ + public String docComment; + + Token(TokenKind kind, int pos, int endPos, + boolean deprecatedFlag) { + this.kind = kind; + this.pos = pos; + this.endPos = endPos; + this.deprecatedFlag = deprecatedFlag; + checkKind(); + } + + Token[] split(Tokens tokens) { + if (kind.name.length() < 2 || kind.tag != Tag.DEFAULT) { + throw new AssertionError("Cant split" + kind); + } + + TokenKind t1 = tokens.lookupKind(kind.name.substring(0, 1)); + TokenKind t2 = tokens.lookupKind(kind.name.substring(1)); + + if (t1 == null || t2 == null) { + throw new AssertionError("Cant split - bad subtokens"); + } + return new Token[] { + new Token(t1, pos, pos + t1.name.length(), deprecatedFlag), + new Token(t2, pos + t1.name.length(), endPos, false) + }; + } + + protected void checkKind() { + if (kind.tag != Tag.DEFAULT) { + throw new AssertionError("Bad token kind - expected " + Tag.STRING); + } + } + + public Name name() { + throw new UnsupportedOperationException(); + } + + public String stringVal() { + throw new UnsupportedOperationException(); + } + + public int radix() { + throw new UnsupportedOperationException(); + } + } + + final static class NamedToken extends Token { + /** The name of this token */ + public final Name name; + + public NamedToken(TokenKind kind, int pos, int endPos, Name name, boolean deprecatedFlag) { + super(kind, pos, endPos, deprecatedFlag); + this.name = name; + } + + protected void checkKind() { + if (kind.tag != Tag.NAMED) { + throw new AssertionError("Bad token kind - expected " + Tag.NAMED); + } + } + + @Override + public Name name() { + return name; + } + } + + static class StringToken extends Token { + /** The string value of this token */ + public final String stringVal; + + public StringToken(TokenKind kind, int pos, int endPos, String stringVal, boolean deprecatedFlag) { + super(kind, pos, endPos, deprecatedFlag); + this.stringVal = stringVal; + } + + protected void checkKind() { + if (kind.tag != Tag.STRING) { + throw new AssertionError("Bad token kind - expected " + Tag.STRING); + } + } + + @Override + public String stringVal() { + return stringVal; + } + } + + final static class NumericToken extends StringToken { + /** The 'radix' value of this token */ + public final int radix; + + public NumericToken(TokenKind kind, int pos, int endPos, String stringVal, int radix, boolean deprecatedFlag) { + super(kind, pos, endPos, stringVal, deprecatedFlag); + this.radix = radix; + } + + protected void checkKind() { + if (kind.tag != Tag.NUMERIC) { + throw new AssertionError("Bad token kind - expected " + Tag.NUMERIC); + } + } + + @Override + public int radix() { + return radix; + } + } + + public static final Token DUMMY = + new Token(TokenKind.ERROR, 0, 0, false); +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java new file mode 100644 index 00000000000..c5718c6fc47 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/UnicodeReader.java @@ -0,0 +1,227 @@ +/* + * 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. + */ + +package com.sun.tools.javac.parser; + +import com.sun.tools.javac.file.JavacFileManager; +import java.nio.CharBuffer; +import com.sun.tools.javac.util.Log; +import static com.sun.tools.javac.util.LayoutCharacters.*; + +/** The char reader used by the javac lexer/tokenizer. Returns the sequence of + * characters contained in the input stream, handling unicode escape accordingly. + * Additionally, it provide features for saving chars into a buffer and to retrieve + * them at a later stage. + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class UnicodeReader { + + /** The input buffer, index of next character to be read, + * index of one past last character in buffer. + */ + protected char[] buf; + protected int bp; + protected final int buflen; + + /** The current character. + */ + protected char ch; + + /** The buffer index of the last converted unicode character + */ + protected int unicodeConversionBp = -1; + + protected Log log; + + /** + * Create a scanner from the input array. This method might + * modify the array. To avoid copying the input array, ensure + * that {@code inputLength < input.length} or + * {@code input[input.length -1]} is a white space character. + * + * @param fac the factory which created this Scanner + * @param input the input, might be modified + * @param inputLength the size of the input. + * Must be positive and less than or equal to input.length. + */ + protected UnicodeReader(ScannerFactory sf, CharBuffer buffer) { + this(sf, JavacFileManager.toArray(buffer), buffer.limit()); + } + + protected UnicodeReader(ScannerFactory sf, char[] input, int inputLength) { + log = sf.log; + if (inputLength == input.length) { + if (input.length > 0 && Character.isWhitespace(input[input.length - 1])) { + inputLength--; + } else { + char[] newInput = new char[inputLength + 1]; + System.arraycopy(input, 0, newInput, 0, input.length); + input = newInput; + } + } + buf = input; + buflen = inputLength; + buf[buflen] = EOI; + bp = -1; + scanChar(); + } + + /** Read next character. + */ + protected void scanChar() { + if (bp < buflen) { + ch = buf[++bp]; + if (ch == '\\') { + convertUnicode(); + } + } + } + + /** Convert unicode escape; bp points to initial '\' character + * (Spec 3.3). + */ + protected void convertUnicode() { + if (ch == '\\' && unicodeConversionBp != bp) { + bp++; ch = buf[bp]; + if (ch == 'u') { + do { + bp++; ch = buf[bp]; + } while (ch == 'u'); + int limit = bp + 3; + if (limit < buflen) { + int d = digit(bp, 16); + int code = d; + while (bp < limit && d >= 0) { + bp++; ch = buf[bp]; + d = digit(bp, 16); + code = (code << 4) + d; + } + if (d >= 0) { + ch = (char)code; + unicodeConversionBp = bp; + return; + } + } + log.error(bp, "illegal.unicode.esc"); + } else { + bp--; + ch = '\\'; + } + } + } + + /** Are surrogates supported? + */ + final static boolean surrogatesSupported = surrogatesSupported(); + private static boolean surrogatesSupported() { + try { + Character.isHighSurrogate('a'); + return true; + } catch (NoSuchMethodError ex) { + return false; + } + } + + /** Scan surrogate pairs. If 'ch' is a high surrogate and + * the next character is a low surrogate, then put the low + * surrogate in 'ch', and return the high surrogate. + * otherwise, just return 0. + */ + protected char scanSurrogates() { + if (surrogatesSupported && Character.isHighSurrogate(ch)) { + char high = ch; + + scanChar(); + + if (Character.isLowSurrogate(ch)) { + return high; + } + + ch = high; + } + + return 0; + } + + /** Convert an ASCII digit from its base (8, 10, or 16) + * to its value. + */ + protected int digit(int pos, int base) { + char c = ch; + int result = Character.digit(c, base); + if (result >= 0 && c > 0x7f) { + log.error(pos + 1, "illegal.nonascii.digit"); + ch = "0123456789abcdef".charAt(result); + } + return result; + } + + protected boolean isUnicode() { + return unicodeConversionBp == bp; + } + + protected void skipChar() { + bp++; + } + + protected char peekChar() { + return buf[bp + 1]; + } + + /** + * Returns a copy of the input buffer, up to its inputLength. + * Unicode escape sequences are not translated. + */ + public char[] getRawCharacters() { + char[] chars = new char[buflen]; + System.arraycopy(buf, 0, chars, 0, buflen); + return chars; + } + + /** + * Returns a copy of a character array subset of the input buffer. + * The returned array begins at the beginIndex and + * extends to the character at index endIndex - 1. + * Thus the length of the substring is endIndex-beginIndex. + * This behavior is like + * String.substring(beginIndex, endIndex). + * Unicode escape sequences are not translated. + * + * @param beginIndex the beginning index, inclusive. + * @param endIndex the ending index, exclusive. + * @throws IndexOutOfBounds if either offset is outside of the + * array bounds + */ + public char[] getRawCharacters(int beginIndex, int endIndex) { + int length = endIndex - beginIndex; + char[] chars = new char[length]; + System.arraycopy(buf, beginIndex, chars, 0, length); + return chars; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index e8040766280..ce16646eea1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -1072,9 +1072,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea Assert.checkNonNull(names); next.put(Names.namesKey, names); - Keywords keywords = Keywords.instance(context); - Assert.checkNonNull(keywords); - next.put(Keywords.keywordsKey, keywords); + Tokens tokens = Tokens.instance(context); + Assert.checkNonNull(tokens); + next.put(Tokens.tokensKey, tokens); JavaCompiler oldCompiler = JavaCompiler.instance(context); JavaCompiler nextCompiler = JavaCompiler.instance(next); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java index 12096869f4f..a5592acf8ad 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java @@ -39,7 +39,6 @@ import javax.tools.StandardLocation; import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.comp.Annotate; -import com.sun.tools.javac.parser.DocCommentScanner; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; diff --git a/langtools/test/tools/javac/api/TestJavacTaskScanner.java b/langtools/test/tools/javac/api/TestJavacTaskScanner.java index 40bde1679e5..ba50138ecc1 100644 --- a/langtools/test/tools/javac/api/TestJavacTaskScanner.java +++ b/langtools/test/tools/javac/api/TestJavacTaskScanner.java @@ -32,6 +32,7 @@ import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.parser.*; +import com.sun.tools.javac.parser.Tokens.Token; import com.sun.tools.javac.util.*; import java.io.*; import java.net.*; @@ -93,7 +94,7 @@ public class TestJavacTaskScanner extends ToolTester { check(numTokens, "#Tokens", 1222); check(numParseTypeElements, "#parseTypeElements", 136); - check(numAllMembers, "#allMembers", 67); + check(numAllMembers, "#allMembers", 52); } void check(int value, String name, int expected) { @@ -206,7 +207,8 @@ class MyScanner extends Scanner { public void nextToken() { super.nextToken(); - System.err.format("Saw token %s (%s)%n", token(), name()); + Token tk = token(); + System.err.format("Saw token %s %n", tk.kind); test.numTokens++; } diff --git a/langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java new file mode 100644 index 00000000000..d7f4dbc0f2c --- /dev/null +++ b/langtools/test/tools/javac/depDocComment/DeprecatedDocComment3.java @@ -0,0 +1,41 @@ +/* + * 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 7096014 + * @summary Javac tokens should retain state + * @compile -Xlint -Werror DeprecatedDocComment3.java + */ + +class DeprecatedDocComment3 { + static class Foo { } + + ; /** @deprecated */ ; + + static class A {} + + static class B { + A a; //not deprecated! + } +} diff --git a/langtools/test/tools/javac/tree/DocCommentToplevelTest.java b/langtools/test/tools/javac/tree/DocCommentToplevelTest.java new file mode 100644 index 00000000000..ff236024f0f --- /dev/null +++ b/langtools/test/tools/javac/tree/DocCommentToplevelTest.java @@ -0,0 +1,196 @@ +/* + * 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 7096014 + * @summary Javac tokens should retain state + */ + +import com.sun.source.tree.*; +import com.sun.source.util.*; +import com.sun.tools.javac.tree.JCTree; + +import java.net.URI; +import java.util.*; +import javax.tools.*; + + +public class DocCommentToplevelTest { + + enum PackageKind { + HAS_PKG("package pkg;"), + NO_PKG(""); + + String pkgStr; + + PackageKind(String pkgStr) { + this.pkgStr = pkgStr; + } + } + + enum ImportKind { + ZERO(""), + ONE("import java.lang.*;"), + TWO("import java.lang.*; import java.util.*;"); + + String importStr; + + ImportKind(String importStr) { + this.importStr = importStr; + } + } + + enum ModifierKind { + DEFAULT(""), + PUBLIC("public"); + + String modStr; + + ModifierKind(String modStr) { + this.modStr = modStr; + } + } + + enum ToplevelDocKind { + HAS_DOC("/** Toplevel! */"), + NO_DOC(""); + + String docStr; + + ToplevelDocKind(String docStr) { + this.docStr = docStr; + } + } + + static int errors; + static int checks; + + public static void main(String... args) throws Exception { + //create default shared JavaCompiler - reused across multiple compilations + JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + for (PackageKind pk : PackageKind.values()) { + for (ImportKind ik : ImportKind.values()) { + for (ModifierKind mk1 : ModifierKind.values()) { + for (ModifierKind mk2 : ModifierKind.values()) { + for (ToplevelDocKind tdk : ToplevelDocKind.values()) { + new DocCommentToplevelTest(pk, ik, mk1, mk2, tdk).run(comp, fm); + } + } + } + } + } + + if (errors > 0) + throw new AssertionError(errors + " errors found"); + + System.out.println(checks + " checks were made"); + } + + PackageKind pk; + ImportKind ik; + ModifierKind mk1; + ModifierKind mk2; + ToplevelDocKind tdk; + JavaSource source; + + DocCommentToplevelTest(PackageKind pk, ImportKind ik, ModifierKind mk1, ModifierKind mk2, ToplevelDocKind tdk) { + this.pk = pk; + this.ik = ik; + this.mk1 = mk1; + this.mk2 = mk2; + this.tdk = tdk; + source = new JavaSource(); + } + + void run(JavaCompiler comp, JavaFileManager fm) throws Exception { + JavacTask task = (JavacTask)comp.getTask(null, fm, null, Arrays.asList("-printsource"), null, Arrays.asList(source)); + for (CompilationUnitTree cu: task.parse()) { + check(cu); + } + } + + void check(CompilationUnitTree cu) { + checks++; + + new TreeScanner() { + + Map docComments; + + @Override + public ClassTree visitCompilationUnit(CompilationUnitTree node, Void unused) { + docComments = ((JCTree.JCCompilationUnit)node).docComments; + boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC && + (pk != PackageKind.NO_PKG || ik != ImportKind.ZERO); + boolean foundComment = docComments.get(node) != null; + if (expectedComment != foundComment) { + error("Unexpected comment " + docComments.get(node) + " on toplevel"); + } + return super.visitCompilationUnit(node, null); + } + + @Override + public ClassTree visitClass(ClassTree node, Void unused) { + boolean expectedComment = tdk == ToplevelDocKind.HAS_DOC && + pk == PackageKind.NO_PKG && ik == ImportKind.ZERO && + node.getSimpleName().toString().equals("First"); + boolean foundComment = docComments.get(node) != null; + if (expectedComment != foundComment) { + error("Unexpected comment " + docComments.get(node) + " on class " + node.getSimpleName()); + } + return super.visitClass(node, unused); + } + }.scan(cu, null); + } + + void error(String msg) { + System.err.println("Error: " + msg); + System.err.println("Source: " + source.source); + errors++; + } + + class JavaSource extends SimpleJavaFileObject { + + String template = "#D\n#P\n#I\n" + + "#M1 class First { }\n" + + "#M2 class Second { }\n"; + + String source; + + public JavaSource() { + super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); + source = template.replace("#P", pk.pkgStr) + .replace("#I", ik.importStr) + .replace("#M1", mk1.modStr) + .replace("#M2", mk2.modStr) + .replace("#D", tdk.docStr); + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return source; + } + } +} From 7873cba6b26b7d3332a005ab998930d85ca8c844 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 24 Oct 2011 13:00:30 +0100 Subject: [PATCH 23/41] 7098660: Write better overload resolution/inference tests Add overload/inference debug diagnostics - added test harness using annotations to check outcome of overload resolution/inference Reviewed-by: jjg --- .../com/sun/tools/javac/code/Printer.java | 2 +- .../com/sun/tools/javac/comp/Infer.java | 18 +- .../com/sun/tools/javac/comp/Resolve.java | 165 +++++- .../tools/javac/resources/compiler.properties | 49 ++ .../diags/examples/ApplicableMethodFound.java | 33 ++ .../examples/ApplicableMethodFound1.java | 34 ++ .../diags/examples/DeferredMethodInst.java | 35 ++ .../javac/diags/examples/FullInstSig.java | 34 ++ .../examples/NotApplicableMethodFound.java | 35 ++ .../javac/diags/examples/PartialInstSig.java | 34 ++ .../diags/examples/VerboseResolveMulti.java | 33 ++ .../diags/examples/VerboseResolveMulti1.java | 35 ++ .../test/tools/javac/resolve/Candidate.java | 68 +++ langtools/test/tools/javac/resolve/Pos.java | 31 ++ .../tools/javac/resolve/ResolveHarness.java | 475 ++++++++++++++++++ .../tools/javac/resolve/TraceResolve.java | 29 ++ .../tests/BoxedReturnTypeInference.java | 60 +++ .../PrimitiveOverReferenceOverInferred.java | 92 ++++ .../PrimitiveOverReferenceOverVarargs.java | 108 ++++ ...rimitiveOverReferenceVarargsAmbiguous.java | 76 +++ .../resolve/tests/PrimitiveOverload.java | 113 +++++ .../tests/PrimitiveReturnTypeInference.java | 60 +++ .../resolve/tests/ReferenceOverInferred.java | 76 +++ .../resolve/tests/ReferenceOverVarargs.java | 93 ++++ .../resolve/tests/ReferenceOverload.java | 95 ++++ 25 files changed, 1854 insertions(+), 29 deletions(-) create mode 100644 langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java create mode 100644 langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java create mode 100644 langtools/test/tools/javac/diags/examples/DeferredMethodInst.java create mode 100644 langtools/test/tools/javac/diags/examples/FullInstSig.java create mode 100644 langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java create mode 100644 langtools/test/tools/javac/diags/examples/PartialInstSig.java create mode 100644 langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java create mode 100644 langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java create mode 100644 langtools/test/tools/javac/resolve/Candidate.java create mode 100644 langtools/test/tools/javac/resolve/Pos.java create mode 100644 langtools/test/tools/javac/resolve/ResolveHarness.java create mode 100644 langtools/test/tools/javac/resolve/TraceResolve.java create mode 100644 langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java create mode 100644 langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java create mode 100644 langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java create mode 100644 langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java create mode 100644 langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java create mode 100644 langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java create mode 100644 langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java create mode 100644 langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java create mode 100644 langtools/test/tools/javac/resolve/tests/ReferenceOverload.java diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java index 59aa924385d..f639caeef45 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java @@ -258,7 +258,7 @@ public abstract class Printer implements Type.Visitor, Symbol.Vi ClassType norm = (ClassType) t.tsym.type; if (norm == null) { s = localize(locale, "compiler.misc.anonymous.class", (Object) null); - } else if (norm.interfaces_field.nonEmpty()) { + } else if (norm.interfaces_field != null && norm.interfaces_field.nonEmpty()) { s = localize(locale, "compiler.misc.anonymous.class", visit(norm.interfaces_field.head, locale)); } else { diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index 3c9ed3af15d..cc5ed20727e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -34,7 +34,8 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Type.ForAll.ConstraintKind; import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; +import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import static com.sun.tools.javac.code.TypeTags.*; @@ -56,6 +57,7 @@ public class Infer { Types types; Check chk; Resolve rs; + Log log; JCDiagnostic.Factory diags; public static Infer instance(Context context) { @@ -70,6 +72,7 @@ public class Infer { syms = Symtab.instance(context); types = Types.instance(context); rs = Resolve.instance(context); + log = Log.instance(context); chk = Check.instance(context); diags = JCDiagnostic.Factory.instance(context); ambiguousNoInstanceException = @@ -460,7 +463,7 @@ public class Infer { // quantify result type with them final List inferredTypes = insttypes.toList(); final List all_tvars = tvars; //this is the wrong tvars - return new UninferredMethodType(mt, restvars.toList()) { + return new UninferredMethodType(env.tree.pos(), msym, mt, restvars.toList()) { @Override List getConstraints(TypeVar tv, ConstraintKind ck) { for (Type t : restundet.toList()) { @@ -502,13 +505,17 @@ public class Infer { * type - when the return type is instantiated (see Infer.instantiateExpr) * the underlying method type is also updated. */ - static abstract class UninferredMethodType extends DelegatedType { + abstract class UninferredMethodType extends DelegatedType { final List tvars; + final Symbol msym; + final DiagnosticPosition pos; - public UninferredMethodType(MethodType mtype, List tvars) { + public UninferredMethodType(DiagnosticPosition pos, Symbol msym, MethodType mtype, List tvars) { super(METHOD, new MethodType(mtype.argtypes, null, mtype.thrown, mtype.tsym)); this.tvars = tvars; + this.msym = msym; + this.pos = pos; asMethodType().restype = new UninferredReturnType(tvars, mtype.restype); } @@ -543,6 +550,9 @@ public class Infer { public Type inst(List actuals, Types types) { Type newRestype = super.inst(actuals, types); instantiateReturnType(newRestype, actuals, types); + if (rs.verboseResolutionMode.contains(VerboseResolutionMode.DEFERRED_INST)) { + log.note(pos, "deferred.method.inst", msym, UninferredMethodType.this.qtype, newRestype); + } return newRestype; } @Override diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 0c37d015188..3d6374dbaf1 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -25,29 +25,33 @@ package com.sun.tools.javac.comp; -import com.sun.tools.javac.util.*; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; -import com.sun.tools.javac.code.*; -import com.sun.tools.javac.jvm.*; -import com.sun.tools.javac.tree.*; import com.sun.tools.javac.api.Formattable.LocalizedString; -import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; - +import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.jvm.*; +import com.sun.tools.javac.tree.*; 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.JCDiagnostic.DiagnosticType; + +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import javax.lang.model.element.ElementVisitor; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTags.*; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticType; -import javax.lang.model.element.ElementVisitor; - -import java.util.Map; -import java.util.Set; -import java.util.HashMap; -import java.util.HashSet; +import static com.sun.tools.javac.comp.Resolve.MethodResolutionPhase.*; /** Helper class for name resolution, used mostly by the attribution phase. * @@ -73,9 +77,45 @@ public class Resolve { public final boolean varargsEnabled; // = source.allowVarargs(); public final boolean allowMethodHandles; private final boolean debugResolve; + final EnumSet verboseResolutionMode; Scope polymorphicSignatureScope; + enum VerboseResolutionMode { + SUCCESS("success"), + FAILURE("failure"), + APPLICABLE("applicable"), + INAPPLICABLE("inapplicable"), + DEFERRED_INST("deferred-inference"), + PREDEF("predef"), + OBJECT_INIT("object-init"), + INTERNAL("internal"); + + String opt; + + private VerboseResolutionMode(String opt) { + this.opt = opt; + } + + static EnumSet getVerboseResolutionMode(Options opts) { + String s = opts.get("verboseResolution"); + EnumSet res = EnumSet.noneOf(VerboseResolutionMode.class); + if (s == null) return res; + if (s.contains("all")) { + res = EnumSet.allOf(VerboseResolutionMode.class); + } + Collection args = Arrays.asList(s.split(",")); + for (VerboseResolutionMode mode : values()) { + if (args.contains(mode.opt)) { + res.add(mode); + } else if (args.contains("-" + mode.opt)) { + res.remove(mode); + } + } + return res; + } + } + public static Resolve instance(Context context) { Resolve instance = context.get(resolveKey); if (instance == null) @@ -111,6 +151,7 @@ public class Resolve { varargsEnabled = source.allowVarargs(); Options options = Options.instance(context); debugResolve = options.isSet("debugresolve"); + verboseResolutionMode = VerboseResolutionMode.getVerboseResolutionMode(options); Target target = Target.instance(context); allowMethodHandles = target.hasMethodHandles(); polymorphicSignatureScope = new Scope(syms.noSymbol); @@ -684,9 +725,11 @@ public class Resolve { if (!sym.isInheritedIn(site.tsym, types)) return bestSoFar; Assert.check(sym.kind < AMBIGUOUS); try { - rawInstantiate(env, site, sym, argtypes, typeargtypes, + Type mt = rawInstantiate(env, site, sym, argtypes, typeargtypes, allowBoxing, useVarargs, Warner.noWarnings); + if (!operator) addVerboseApplicableCandidateDiag(sym ,mt); } catch (InapplicableMethodException ex) { + if (!operator) addVerboseInapplicableCandidateDiag(sym, ex.getDiagnostic()); switch (bestSoFar.kind) { case ABSENT_MTH: return wrongMethod.setWrongSym(sym, ex.getDiagnostic()); @@ -709,6 +752,34 @@ public class Resolve { : mostSpecific(sym, bestSoFar, env, site, allowBoxing && operator, useVarargs); } + //where + void addVerboseApplicableCandidateDiag(Symbol sym, Type inst) { + if (!verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) + return; + + JCDiagnostic subDiag = null; + if (inst.getReturnType().tag == FORALL) { + Type diagType = types.createMethodTypeWithReturn(inst.asMethodType(), + ((ForAll)inst.getReturnType()).qtype); + subDiag = diags.fragment("partial.inst.sig", diagType); + } else if (sym.type.tag == FORALL) { + subDiag = diags.fragment("full.inst.sig", inst.asMethodType()); + } + + String key = subDiag == null ? + "applicable.method.found" : + "applicable.method.found.1"; + + verboseResolutionCandidateDiags.put(sym, + diags.fragment(key, verboseResolutionCandidateDiags.size(), sym, subDiag)); + } + + void addVerboseInapplicableCandidateDiag(Symbol sym, JCDiagnostic subDiag) { + if (!verboseResolutionMode.contains(VerboseResolutionMode.INAPPLICABLE)) + return; + verboseResolutionCandidateDiags.put(sym, + diags.fragment("not.applicable.method.found", verboseResolutionCandidateDiags.size(), sym, subDiag)); + } /* Return the most specific of the two methods for a call, * given that both are accessible and applicable. @@ -906,8 +977,9 @@ public class Resolve { boolean allowBoxing, boolean useVarargs, boolean operator) { + verboseResolutionCandidateDiags.clear(); Symbol bestSoFar = methodNotFound; - return findMethod(env, + bestSoFar = findMethod(env, site, name, argtypes, @@ -919,6 +991,8 @@ public class Resolve { useVarargs, operator, new HashSet()); + reportVerboseResolutionDiagnostic(env.tree.pos(), name, site, argtypes, typeargtypes, bestSoFar); + return bestSoFar; } // where private Symbol findMethod(Env env, @@ -976,6 +1050,37 @@ public class Resolve { } return bestSoFar; } + //where + void reportVerboseResolutionDiagnostic(DiagnosticPosition dpos, Name name, Type site, List argtypes, List typeargtypes, Symbol bestSoFar) { + boolean success = bestSoFar.kind < ERRONEOUS; + + if (success && !verboseResolutionMode.contains(VerboseResolutionMode.SUCCESS)) { + return; + } else if (!success && !verboseResolutionMode.contains(VerboseResolutionMode.FAILURE)) { + return; + } + + if (bestSoFar.name == names.init && + bestSoFar.owner == syms.objectType.tsym && + !verboseResolutionMode.contains(VerboseResolutionMode.OBJECT_INIT)) { + return; //skip diags for Object constructor resolution + } else if (site == syms.predefClass.type && !verboseResolutionMode.contains(VerboseResolutionMode.PREDEF)) { + return; //skip spurious diags for predef symbols (i.e. operators) + } else if (internalResolution && !verboseResolutionMode.contains(VerboseResolutionMode.INTERNAL)) { + return; + } + + int pos = 0; + for (Symbol s : verboseResolutionCandidateDiags.keySet()) { + if (s == bestSoFar) break; + pos++; + } + String key = success ? "verbose.resolve.multi" : "verbose.resolve.multi.1"; + JCDiagnostic main = diags.note(log.currentSource(), dpos, key, name, site.tsym, pos, currentStep, + methodArguments(argtypes), methodArguments(typeargtypes)); + JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, List.from(verboseResolutionCandidateDiags.values().toArray(new JCDiagnostic[verboseResolutionCandidateDiags.size()]))); + log.report(d); + } /** Find unqualified method matching given name, type and value arguments. * @param env The current environment. @@ -1544,12 +1649,19 @@ public class Resolve { Type site, Name name, List argtypes, List typeargtypes) { - Symbol sym = resolveQualifiedMethod( - pos, env, site.tsym, site, name, argtypes, typeargtypes); - if (sym.kind == MTH) return (MethodSymbol)sym; - else throw new FatalError( - diags.fragment("fatal.err.cant.locate.meth", - name)); + boolean prevInternal = internalResolution; + try { + internalResolution = true; + Symbol sym = resolveQualifiedMethod( + pos, env, site.tsym, site, name, argtypes, typeargtypes); + if (sym.kind == MTH) return (MethodSymbol)sym; + else throw new FatalError( + diags.fragment("fatal.err.cant.locate.meth", + name)); + } + finally { + internalResolution = prevInternal; + } } /** Resolve constructor. @@ -1830,7 +1942,7 @@ public class Resolve { private final LocalizedString noArgs = new LocalizedString("compiler.misc.no.args"); public Object methodArguments(List argtypes) { - return argtypes.isEmpty() ? noArgs : argtypes; + return argtypes == null || argtypes.isEmpty() ? noArgs : argtypes; } /** @@ -2377,10 +2489,15 @@ public class Resolve { private Map methodResolutionCache = new HashMap(MethodResolutionPhase.values().length); + private Map verboseResolutionCandidateDiags = + new LinkedHashMap(); + final List methodResolutionSteps = List.of(BASIC, BOX, VARARITY); private MethodResolutionPhase currentStep = null; + private boolean internalResolution = false; + private MethodResolutionPhase firstErroneousResolutionPhase() { MethodResolutionPhase bestSoFar = BASIC; Symbol sym = methodNotFound; diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 7fab25ee989..9b3574e7abd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1943,6 +1943,55 @@ compiler.err.string.switch.not.supported.in.source=\ strings in switch are not supported in -source {0}\n\ (use -source 7 or higher to enable strings in switch) +######################################## +# Diagnostics for verbose resolution +# used by Resolve (debug only) +######################################## + +# 0: number, 1: symbol, 2: unused +compiler.misc.applicable.method.found=\ + #{0} applicable method found: {1} + +# 0: number, 1: symbol, 2: message segment +compiler.misc.applicable.method.found.1=\ + #{0} applicable method found: {1}\n\ + ({2}) + +# 0: number, 1: symbol, 2: message segment +compiler.misc.not.applicable.method.found=\ + #{0} not applicable method found: {1}\n\ + ({2}) + +# 0: type +compiler.misc.full.inst.sig=\ + fully instantiated to: {0} + +# 0: type +compiler.misc.partial.inst.sig=\ + partially instantiated to: {0} + +# 0: name, 1: symbol, 2: number, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment +compiler.note.verbose.resolve.multi=\ + resolving method {0} in type {1} to candidate {2}\n\ + phase: {3}\n\ + with actuals: {4}\n\ + with type-args: {5}\n\ + candidates: + +# 0: name, 1: symbol, 2: unused, 3: MethodResolutionPhase, 4: list of type or message segment, 5: list of type or message segment +compiler.note.verbose.resolve.multi.1=\ + erroneous resolution for method {0} in type {1}\n\ + phase: {3}\n\ + with actuals: {4}\n\ + with type-args: {5}\n\ + candidates: + +# 0: symbol, 1: type, 2: type +compiler.note.deferred.method.inst=\ + Deferred instantiation of method {0}\n\ + instantiated signature: {1}\n\ + target-type: {2} + ######################################## # Diagnostics for where clause implementation # used by the RichDiagnosticFormatter. diff --git a/langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java new file mode 100644 index 00000000000..675544939b3 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found +// key: compiler.note.verbose.resolve.multi +// options: -XDverboseResolution=applicable,success + +class ApplicableMethodFound { + + void m() {} + + { m(); } +} diff --git a/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java new file mode 100644 index 00000000000..7764d50e518 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/ApplicableMethodFound1.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found.1 +// key: compiler.note.verbose.resolve.multi +// key: compiler.misc.full.inst.sig +// options: -XDverboseResolution=applicable,success + +class ApplicableMethodFound1 { + + void m(X x) {} + + { m(1); } +} diff --git a/langtools/test/tools/javac/diags/examples/DeferredMethodInst.java b/langtools/test/tools/javac/diags/examples/DeferredMethodInst.java new file mode 100644 index 00000000000..ff56e5e0212 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DeferredMethodInst.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found.1 +// key: compiler.note.verbose.resolve.multi +// key: compiler.note.deferred.method.inst +// key: compiler.misc.partial.inst.sig +// options: -XDverboseResolution=applicable,success,deferred-inference + +class DeferredMethodInst { + + X m() { return null; } + + { Integer i = m(); } +} diff --git a/langtools/test/tools/javac/diags/examples/FullInstSig.java b/langtools/test/tools/javac/diags/examples/FullInstSig.java new file mode 100644 index 00000000000..fc0d642b278 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/FullInstSig.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found.1 +// key: compiler.note.verbose.resolve.multi +// key: compiler.misc.full.inst.sig +// options: -XDverboseResolution=applicable,success + +class FullInstSig { + + void m(X x) {} + + { m(1); } +} diff --git a/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java new file mode 100644 index 00000000000..bfd2bfb35b7 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/NotApplicableMethodFound.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.misc.not.applicable.method.found +// key: compiler.note.verbose.resolve.multi.1 +// key: compiler.err.cant.apply.symbol.1 +// key: compiler.misc.no.conforming.assignment.exists +// options: -XDverboseResolution=inapplicable,failure + +class NotApplicableMethodFound { + + void m(int i) {} + + { m(""); } +} diff --git a/langtools/test/tools/javac/diags/examples/PartialInstSig.java b/langtools/test/tools/javac/diags/examples/PartialInstSig.java new file mode 100644 index 00000000000..c095bdd1c9b --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PartialInstSig.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found.1 +// key: compiler.note.verbose.resolve.multi +// key: compiler.misc.partial.inst.sig +// options: -XDverboseResolution=applicable,success + +class PartialInstSig { + + X m() { return null; } + + { m(); } +} diff --git a/langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java new file mode 100644 index 00000000000..59a8d3c8716 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +// key: compiler.misc.applicable.method.found +// key: compiler.note.verbose.resolve.multi +// options: -XDverboseResolution=applicable,success + +class VerboseResolveMulti { + + void m() {} + + { m(); } +} diff --git a/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java new file mode 100644 index 00000000000..b72f416dccf --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/VerboseResolveMulti1.java @@ -0,0 +1,35 @@ +/* + * 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. + */ + +// key: compiler.misc.not.applicable.method.found +// key: compiler.note.verbose.resolve.multi.1 +// key: compiler.err.cant.apply.symbol.1 +// key: compiler.misc.no.conforming.assignment.exists +// options: -XDverboseResolution=inapplicable,failure + +class VerboseResolveMulti1 { + + void m(int i) {} + + { m(""); } +} diff --git a/langtools/test/tools/javac/resolve/Candidate.java b/langtools/test/tools/javac/resolve/Candidate.java new file mode 100644 index 00000000000..a36208b56fa --- /dev/null +++ b/langtools/test/tools/javac/resolve/Candidate.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@interface Candidate { + /** + * the candidate position (line/col of the method call for which this candidate + * is a potential overload candidate) + */ + Pos pos() default @Pos(userDefined=false); + /** + * resolution phases for which this candidate is applicable + */ + Phase[] applicable() default { }; + /** + * is this candidate the most specific (in the resolution phases for which it + * is also applicable) + */ + boolean mostSpecific() default false; + /** + * this candidate inferred signature (in the resolution phases for which it + * is also applicable, in case it corresponds to a generic method) + */ + String sig() default ""; +} + +enum Phase { + BASIC("BASIC"), + BOX("BOX"), + VARARGS("VARARITY"); + + final String javacString; + + private Phase(String javacString) { + this.javacString = javacString; + } + + static Phase fromString(String s) { + for (Phase phase : Phase.values()) { + if (phase.javacString.equals(s)) { + return phase; + } + } + throw new AssertionError("Invalid resolution phase string " + s); + } +} diff --git a/langtools/test/tools/javac/resolve/Pos.java b/langtools/test/tools/javac/resolve/Pos.java new file mode 100644 index 00000000000..d778536e9f0 --- /dev/null +++ b/langtools/test/tools/javac/resolve/Pos.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target(ElementType.ANNOTATION_TYPE) +@interface Pos { + long line() default -1; + long col() default -1; + boolean userDefined() default true; +} \ No newline at end of file diff --git a/langtools/test/tools/javac/resolve/ResolveHarness.java b/langtools/test/tools/javac/resolve/ResolveHarness.java new file mode 100644 index 00000000000..609b3d84d13 --- /dev/null +++ b/langtools/test/tools/javac/resolve/ResolveHarness.java @@ -0,0 +1,475 @@ +/* + * 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 7098660 + * @summary Write better overload resolution/inference tests + * @library ../lib + * @build JavacTestingAbstractProcessor ResolveHarness + * @run main ResolveHarness + */ + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.ClientCodeWrapper.DiagnosticSourceUnwrapper; +import com.sun.tools.javac.code.Type.MethodType; +import com.sun.tools.javac.util.JCDiagnostic; + +import java.io.File; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; +import javax.tools.Diagnostic.Kind; +import javax.tools.DiagnosticListener; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import static javax.tools.StandardLocation.*; + +public class ResolveHarness implements javax.tools.DiagnosticListener { + + static int nerrors = 0; + + static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + public static void main(String[] args) throws Exception { + fm.setLocation(SOURCE_PATH, + Arrays.asList(new File(System.getProperty("test.src"), "tests"))); + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(JavaFileObject.Kind.SOURCE), true)) { + new ResolveHarness(jfo).check(); + } + if (nerrors > 0) { + throw new AssertionError("Errors were found"); + } + } + + + JavaFileObject jfo; + DiagnosticProcessor[] diagProcessors; + Map candidatesMap = new HashMap(); + Set declaredKeys = new HashSet<>(); + List> diags = new ArrayList<>(); + List seenCandidates = new ArrayList<>(); + + protected ResolveHarness(JavaFileObject jfo) { + this.jfo = jfo; + this.diagProcessors = new DiagnosticProcessor[] { + new VerboseResolutionNoteProcessor(), + new VerboseDeferredInferenceNoteProcessor(), + new ErrorProcessor() + }; + } + + protected void check() throws Exception { + String[] options = { + "-XDshouldStopPolicy=ATTR", + "-XDverboseResolution=success,failure,applicable,inapplicable,deferred-inference" + }; + + AbstractProcessor[] processors = { new ResolveCandidateFinder(), null }; + + @SuppressWarnings("unchecked") + DiagnosticListener[] diagListeners = + new DiagnosticListener[] { new DiagnosticHandler(false), new DiagnosticHandler(true) }; + + for (int i = 0 ; i < options.length ; i ++) { + JavacTask ct = (JavacTask)comp.getTask(null, fm, diagListeners[i], + Arrays.asList(options[i]), null, Arrays.asList(jfo)); + if (processors[i] != null) { + ct.setProcessors(Collections.singleton(processors[i])); + } + ct.analyze(); + } + + //check diags + for (Diagnostic diag : diags) { + for (DiagnosticProcessor proc : diagProcessors) { + if (proc.matches(diag)) { + proc.process(diag); + break; + } + } + } + //check all candidates have been used up + for (Map.Entry entry : candidatesMap.entrySet()) { + if (!seenCandidates.contains(entry.getKey())) { + error("Redundant @Candidate annotation on method " + entry.getKey().elem); + } + } + } + + public void report(Diagnostic diagnostic) { + diags.add(diagnostic); + } + + Candidate getCandidateAtPos(Element methodSym, long line, long col) { + Candidate c = candidatesMap.get(new ElementKey(methodSym)); + if (c != null) { + Pos pos = c.pos(); + if (!pos.userDefined() || + (pos.line() == line && pos.col() == col)) { + seenCandidates.add(new ElementKey(methodSym)); + return c; + } + } else { + error("Missing @Candidate annotation on method " + methodSym); + } + return null; + } + + void checkSig(Candidate c, Element methodSym, MethodType mtype) { + if (c.sig().length() > 0 && !c.sig().equals(mtype.toString())) { + error("Inferred type mismatch for method: " + methodSym); + } + } + + protected void error(String msg) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\nreason: %s\n", jfo.getName(), msg); + } + + /** + * Base class for diagnostic processor. It provides methods for matching and + * processing a given diagnostic object (overridden by subclasses). + */ + abstract class DiagnosticProcessor { + + List codes; + Diagnostic.Kind kind; + + public DiagnosticProcessor(Kind kind, String... codes) { + this.codes = Arrays.asList(codes); + this.kind = kind; + } + + abstract void process(Diagnostic diagnostic); + + boolean matches(Diagnostic diagnostic) { + return (codes.isEmpty() || codes.contains(diagnostic.getCode())) && + diagnostic.getKind() == kind; + } + + JCDiagnostic asJCDiagnostic(Diagnostic diagnostic) { + if (diagnostic instanceof JCDiagnostic) { + return (JCDiagnostic)diagnostic; + } else if (diagnostic instanceof DiagnosticSourceUnwrapper) { + return ((DiagnosticSourceUnwrapper)diagnostic).d; + } else { + throw new AssertionError("Cannot convert diagnostic to JCDiagnostic: " + diagnostic.getClass().getName()); + } + } + + List subDiagnostics(Diagnostic diagnostic) { + JCDiagnostic diag = asJCDiagnostic(diagnostic); + if (diag instanceof JCDiagnostic.MultilineDiagnostic) { + return ((JCDiagnostic.MultilineDiagnostic)diag).getSubdiagnostics(); + } else { + throw new AssertionError("Cannot extract subdiagnostics: " + diag.getClass().getName()); + } + } + } + + /** + * Processor for verbose resolution notes generated by javac. The processor + * checks that the diagnostic is associated with a method declared by + * a class annotated with the special @TraceResolve marker annotation. If + * that's the case, all subdiagnostics (one for each resolution candidate) + * are checked against the corresponding @Candidate annotations, using + * a VerboseCandidateSubdiagProcessor. + */ + class VerboseResolutionNoteProcessor extends DiagnosticProcessor { + + VerboseResolutionNoteProcessor() { + super(Kind.NOTE, + "compiler.note.verbose.resolve.multi", + "compiler.note.verbose.resolve.multi.1"); + } + + @Override + void process(Diagnostic diagnostic) { + Element siteSym = getSiteSym(diagnostic); + if (siteSym.getAnnotation(TraceResolve.class) == null) { + return; + } + int candidateIdx = 0; + for (JCDiagnostic d : subDiagnostics(diagnostic)) { + boolean isMostSpecific = candidateIdx++ == mostSpecific(diagnostic); + VerboseCandidateSubdiagProcessor subProc = + new VerboseCandidateSubdiagProcessor(isMostSpecific, phase(diagnostic), success(diagnostic)); + if (subProc.matches(d)) { + subProc.process(d); + } else { + throw new AssertionError("Bad subdiagnostic: " + d.getCode()); + } + } + } + + Element getSiteSym(Diagnostic diagnostic) { + return (Element)asJCDiagnostic(diagnostic).getArgs()[1]; + } + + int mostSpecific(Diagnostic diagnostic) { + return success(diagnostic) ? + (Integer)asJCDiagnostic(diagnostic).getArgs()[2] : -1; + } + + boolean success(Diagnostic diagnostic) { + return diagnostic.getCode().equals("compiler.note.verbose.resolve.multi"); + } + + Phase phase(Diagnostic diagnostic) { + return Phase.fromString(asJCDiagnostic(diagnostic).getArgs()[3].toString()); + } + } + + /** + * Processor for verbose resolution subdiagnostic notes generated by javac. + * The processor checks that the details of the overload candidate + * match against the info contained in the corresponding @Candidate + * annotation (if any). + */ + class VerboseCandidateSubdiagProcessor extends DiagnosticProcessor { + + boolean mostSpecific; + Phase phase; + boolean success; + + public VerboseCandidateSubdiagProcessor(boolean mostSpecific, Phase phase, boolean success) { + super(Kind.OTHER, + "compiler.misc.applicable.method.found", + "compiler.misc.applicable.method.found.1", + "compiler.misc.not.applicable.method.found"); + this.mostSpecific = mostSpecific; + this.phase = phase; + this.success = success; + } + + @Override + void process(Diagnostic diagnostic) { + Element methodSym = methodSym(diagnostic); + Candidate c = getCandidateAtPos(methodSym, + asJCDiagnostic(diagnostic).getLineNumber(), + asJCDiagnostic(diagnostic).getColumnNumber()); + if (c == null) { + return; //nothing to check + } + + if (c.applicable().length == 0 && c.mostSpecific()) { + error("Inapplicable method cannot be most specific " + methodSym); + } + + if (isApplicable(diagnostic) != Arrays.asList(c.applicable()).contains(phase)) { + error("Invalid candidate's applicability " + methodSym); + } + + if (success) { + for (Phase p : c.applicable()) { + if (phase.ordinal() < p.ordinal()) { + error("Invalid phase " + p + " on method " + methodSym); + } + } + } + + if (Arrays.asList(c.applicable()).contains(phase)) { //applicable + if (c.mostSpecific() != mostSpecific) { + error("Invalid most specific value for method " + methodSym); + } + MethodType mtype = getSig(diagnostic); + if (mtype != null) { + checkSig(c, methodSym, mtype); + } + } + } + + boolean isApplicable(Diagnostic diagnostic) { + return !diagnostic.getCode().equals("compiler.misc.not.applicable.method.found"); + } + + Element methodSym(Diagnostic diagnostic) { + return (Element)asJCDiagnostic(diagnostic).getArgs()[1]; + } + + MethodType getSig(Diagnostic diagnostic) { + JCDiagnostic details = (JCDiagnostic)asJCDiagnostic(diagnostic).getArgs()[2]; + if (details == null) { + return null; + } else if (details instanceof JCDiagnostic) { + return details.getCode().equals("compiler.misc.full.inst.sig") ? + (MethodType)details.getArgs()[0] : null; + } else { + throw new AssertionError("Bad diagnostic arg: " + details); + } + } + } + + /** + * Processor for verbose deferred inference notes generated by javac. The + * processor checks that the inferred signature for a given generic method + * call corresponds to the one (if any) declared in the @Candidate annotation. + */ + class VerboseDeferredInferenceNoteProcessor extends DiagnosticProcessor { + + public VerboseDeferredInferenceNoteProcessor() { + super(Kind.NOTE, "compiler.note.deferred.method.inst"); + } + + @Override + void process(Diagnostic diagnostic) { + Element methodSym = methodSym(diagnostic); + Candidate c = getCandidateAtPos(methodSym, + asJCDiagnostic(diagnostic).getLineNumber(), + asJCDiagnostic(diagnostic).getColumnNumber()); + MethodType sig = sig(diagnostic); + if (c != null && sig != null) { + checkSig(c, methodSym, sig); + } + } + + Element methodSym(Diagnostic diagnostic) { + return (Element)asJCDiagnostic(diagnostic).getArgs()[0]; + } + + MethodType sig(Diagnostic diagnostic) { + return (MethodType)asJCDiagnostic(diagnostic).getArgs()[1]; + } + } + + /** + * Processor for all error diagnostics; if the error key is not declared in + * the test file header, the processor reports an error. + */ + class ErrorProcessor extends DiagnosticProcessor { + + public ErrorProcessor() { + super(Diagnostic.Kind.ERROR); + } + + @Override + void process(Diagnostic diagnostic) { + if (!declaredKeys.contains(diagnostic.getCode())) { + error("Unexpected compilation error key '" + diagnostic.getCode() + "'"); + } + } + } + + @SupportedAnnotationTypes({"Candidate","TraceResolve"}) + class ResolveCandidateFinder extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) + return true; + + TypeElement traceResolveAnno = elements.getTypeElement("TraceResolve"); + TypeElement candidateAnno = elements.getTypeElement("Candidate"); + + if (!annotations.contains(traceResolveAnno)) { + error("no @TraceResolve annotation found in test class"); + } + + if (!annotations.contains(candidateAnno)) { + error("no @candidate annotation found in test class"); + } + + for (Element elem: roundEnv.getElementsAnnotatedWith(traceResolveAnno)) { + TraceResolve traceResolve = elem.getAnnotation(TraceResolve.class); + declaredKeys.addAll(Arrays.asList(traceResolve.keys())); + } + + for (Element elem: roundEnv.getElementsAnnotatedWith(candidateAnno)) { + candidatesMap.put(new ElementKey(elem), elem.getAnnotation(Candidate.class)); + } + return true; + } + } + + class ElementKey { + + String key; + Element elem; + + public ElementKey(Element elem) { + this.elem = elem; + this.key = computeKey(elem); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ElementKey) { + ElementKey other = (ElementKey)obj; + return other.key.equals(key); + } + return false; + } + + @Override + public int hashCode() { + return key.hashCode(); + } + + String computeKey(Element e) { + StringBuilder buf = new StringBuilder(); + while (e != null) { + buf.append(e.toString()); + e = e.getEnclosingElement(); + } + buf.append(jfo.getName()); + return buf.toString(); + } + + @Override + public String toString() { + return "Key{"+key+"}"; + } + } + + class DiagnosticHandler implements DiagnosticListener { + + boolean shouldRecordDiags; + + DiagnosticHandler(boolean shouldRecordDiags) { + this.shouldRecordDiags = shouldRecordDiags; + } + + public void report(Diagnostic diagnostic) { + if (shouldRecordDiags) + diags.add(diagnostic); + } + + } +} diff --git a/langtools/test/tools/javac/resolve/TraceResolve.java b/langtools/test/tools/javac/resolve/TraceResolve.java new file mode 100644 index 00000000000..ddc83996e80 --- /dev/null +++ b/langtools/test/tools/javac/resolve/TraceResolve.java @@ -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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@interface TraceResolve { + String[] keys() default {}; +} diff --git a/langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java b/langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java new file mode 100644 index 00000000000..dcde2567192 --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/BoxedReturnTypeInference.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +@TraceResolve +class BoxedReturnTypeInference { + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true) + static B m_byte() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true) + static S m_short() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true) + static I m_int() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true) + static L m_long() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true) + static F m_float() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true) + static D m_double() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true) + static C m_char() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true) + static Z m_bool() { return null; } + + { + Byte b = m_byte(); + Short s = m_short(); + Integer i = m_int(); + Long l = m_long(); + Float f = m_float(); + Double d = m_double(); + Character c= m_char(); + Boolean z = m_bool(); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java new file mode 100644 index 00000000000..843169cf35c --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverInferred.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +@TraceResolve +class PrimitiveOverReference { + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_byte(byte b) {} + @Candidate + static void m_byte(Byte b) {} + @Candidate + static void m_byte(B b) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_short(short s) {} + @Candidate + static void m_short(Short s) {} + @Candidate + static void m_short(S s) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_int(int i) {} + @Candidate + static void m_int(Integer i) {} + @Candidate + static void m_int(I i) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_long(long l) {} + @Candidate + static void m_long(Long l) {} + @Candidate + static void m_long(L l) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_float(float f) {} + @Candidate + static void m_float(Float f) {} + @Candidate + static void m_float(F f) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_double(double d) {} + @Candidate + static void m_double(Double d) {} + @Candidate + static void m_double(D d) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_char(char c) {} + @Candidate + static void m_char(Character c) {} + @Candidate + static void m_char(C c) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_bool(boolean z) {} + @Candidate + static void m_bool(Boolean z) {} + @Candidate + static void m_bool(Z z) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + m_char('?'); + m_bool(false); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java new file mode 100644 index 00000000000..a07909ede0b --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceOverVarargs.java @@ -0,0 +1,108 @@ +/* + * 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. + */ + +@TraceResolve +class PrimitiveOverReference { + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_byte(byte b) {} + @Candidate + static void m_byte(Byte b) {} + @Candidate + static void m_byte(byte... b) {} + @Candidate + static void m_byte(Byte... b) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_short(short s) {} + @Candidate + static void m_short(Short s) {} + @Candidate + static void m_short(short... s) {} + @Candidate + static void m_short(Short... s) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_int(int i) {} + @Candidate + static void m_int(Integer i) {} + @Candidate + static void m_int(int... i) {} + @Candidate + static void m_int(Integer... i) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_long(long l) {} + @Candidate + static void m_long(Long l) {} + @Candidate + static void m_long(long... l) {} + @Candidate + static void m_long(Long... l) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_float(float f) {} + @Candidate + static void m_float(Float f) {} + @Candidate + static void m_float(float... f) {} + @Candidate + static void m_float(Float... f) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_double(double d) {} + @Candidate + static void m_double(Double d) {} + @Candidate + static void m_double(double... d) {} + @Candidate + static void m_double(Double... d) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_char(char c) {} + @Candidate + static void m_char(Character c) {} + @Candidate + static void m_char(char... c) {} + @Candidate + static void m_char(Character... c) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_bool(boolean z) {} + @Candidate + static void m_bool(Boolean z) {} + @Candidate + static void m_bool(boolean... z) {} + @Candidate + static void m_bool(Boolean... z) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + m_char('?'); + m_bool(false); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java new file mode 100644 index 00000000000..80ac69dd95d --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverReferenceVarargsAmbiguous.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +@TraceResolve(keys={"compiler.err.ref.ambiguous"}) +class PrimitiveOverReferenceVarargsAmbiguous { + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_byte(byte... b) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_byte(Byte... b) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_short(short... s) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_short(Short... s) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_int(int... i) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_int(Integer... i) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_long(long... l) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_long(Long... l) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_float(float... f) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_float(Float... f) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_double(double... d) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_double(Double... d) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_char(char... c) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_char(Character... c) {} + + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_bool(boolean... z) {} + @Candidate(applicable=Phase.VARARGS, mostSpecific=false) + static void m_bool(Boolean... z) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + m_char('?'); + m_bool(false); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java b/langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java new file mode 100644 index 00000000000..752b697f4cb --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveOverload.java @@ -0,0 +1,113 @@ +/* + * 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. + */ + +@TraceResolve +class PrimitiveOverload { + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_byte(byte b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_byte(short b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_byte(int b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_byte(long b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_byte(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_byte(double b) {} + + @Candidate + static void m_short(byte b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_short(short b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_short(int b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_short(long b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_short(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_short(double b) {} + + @Candidate + static void m_int(byte b) {} + @Candidate + static void m_int(short b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_int(int b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_int(long b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_int(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_int(double b) {} + + @Candidate + static void m_long(byte b) {} + @Candidate + static void m_long(short b) {} + @Candidate + static void m_long(int b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_long(long b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_long(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_long(double b) {} + + @Candidate + static void m_float(byte b) {} + @Candidate + static void m_float(short b) {} + @Candidate + static void m_float(int b) {} + @Candidate + static void m_float(long b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_float(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_float(double b) {} + + @Candidate + static void m_double(byte b) {} + @Candidate + static void m_double(short b) {} + @Candidate + static void m_double(int b) {} + @Candidate + static void m_double(long b) {} + @Candidate + static void m_double(float b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_double(double b) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java b/langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java new file mode 100644 index 00000000000..04a15066cbb --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/PrimitiveReturnTypeInference.java @@ -0,0 +1,60 @@ +/* + * 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. + */ + +@TraceResolve +class PrimitiveReturnTypeInference { + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Byte", mostSpecific=true) + static B m_byte() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Short", mostSpecific=true) + static S m_short() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Integer", mostSpecific=true) + static I m_int() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Long", mostSpecific=true) + static L m_long() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Float", mostSpecific=true) + static F m_float() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Double", mostSpecific=true) + static D m_double() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Character", mostSpecific=true) + static C m_char() { return null; } + + @Candidate(applicable=Phase.BASIC, sig="()java.lang.Boolean", mostSpecific=true) + static Z m_bool() { return null; } + + { + byte b = m_byte(); + short s = m_short(); + int i = m_int(); + long l = m_long(); + float f = m_float(); + double d = m_double(); + char c= m_char(); + boolean z = m_bool(); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java b/langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java new file mode 100644 index 00000000000..ed687739f0e --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverInferred.java @@ -0,0 +1,76 @@ +/* + * 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. + */ + +@TraceResolve +class PrimitiveOverInferred { + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_byte(Byte b) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Byte)void") + static void m_byte(B b) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_short(Short s) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Short)void") + static void m_short(S s) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_int(Integer i) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Integer)void") + static void m_int(I i) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_long(Long l) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Long)void") + static void m_long(L l) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_float(Float f) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Float)void") + static void m_float(F f) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_double(Double d) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Double)void") + static void m_double(D d) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_char(Character c) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Character)void") + static void m_char(C c) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_bool(Boolean z) {} + @Candidate(applicable=Phase.BOX, sig="(java.lang.Boolean)void") + static void m_bool(Z z) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + m_char('?'); + m_bool(false); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java b/langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java new file mode 100644 index 00000000000..c089e2d3e6c --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverVarargs.java @@ -0,0 +1,93 @@ +/* + * 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. + */ + +@TraceResolve +class ReferenceOverVarargs { + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_byte(Byte b) {} + @Candidate + static void m_byte(byte... b) {} + @Candidate + static void m_byte(Byte... b) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_short(Short s) {} + @Candidate + static void m_short(short... s) {} + @Candidate + static void m_short(Short... s) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_int(Integer i) {} + @Candidate + static void m_int(int... i) {} + @Candidate + static void m_int(Integer... i) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_long(Long l) {} + @Candidate + static void m_long(long... l) {} + @Candidate + static void m_long(Long... l) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_float(Float f) {} + @Candidate + static void m_float(float... f) {} + @Candidate + static void m_float(Float... f) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_double(Double d) {} + @Candidate + static void m_double(double... d) {} + @Candidate + static void m_double(Double... d) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_char(Character c) {} + @Candidate + static void m_char(char... c) {} + @Candidate + static void m_char(Character... c) {} + + @Candidate(applicable=Phase.BOX, mostSpecific=true) + static void m_bool(Boolean z) {} + @Candidate + static void m_bool(boolean... z) {} + @Candidate + static void m_bool(Boolean... z) {} + + { + m_byte((byte)0); + m_short((short)0); + m_int(0); + m_long(0L); + m_float(0.0f); + m_double(0.0); + m_char('?'); + m_bool(false); + } +} diff --git a/langtools/test/tools/javac/resolve/tests/ReferenceOverload.java b/langtools/test/tools/javac/resolve/tests/ReferenceOverload.java new file mode 100644 index 00000000000..578bc51a68c --- /dev/null +++ b/langtools/test/tools/javac/resolve/tests/ReferenceOverload.java @@ -0,0 +1,95 @@ +/* + * 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. + */ + +@TraceResolve +class ReferenceOverload { + + static class A {} + static class B extends A {} + static class C extends B {} + static class D extends C {} + static class E extends D {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_A(A a) {} + @Candidate + static void m_A(B a) {} + @Candidate + static void m_A(C a) {} + @Candidate + static void m_A(D a) {} + @Candidate + static void m_A(E a) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_B(A b) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_B(B b) {} + @Candidate + static void m_B(C b) {} + @Candidate + static void m_B(D b) {} + @Candidate + static void m_B(E b) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_C(A c) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_C(B c) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_C(C c) {} + @Candidate + static void m_C(D c) {} + @Candidate + static void m_C(E c) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_D(A d) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_D(B d) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_D(C d) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_D(D d) {} + @Candidate + static void m_D(E d) {} + + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_E(A e) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_E(B e) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_E(C e) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=false) + static void m_E(D e) {} + @Candidate(applicable=Phase.BASIC, mostSpecific=true) + static void m_E(E e) {} + + { + m_A((A)null); + m_B((B)null); + m_C((C)null); + m_D((D)null); + m_E((E)null); + } +} From de7b2614765602453293cac1e7046f026dc63616 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 24 Oct 2011 20:55:08 +0100 Subject: [PATCH 24/41] 7104209: Cleanup and remove librmi (native library) Reviewed-by: mduigou, alanb --- jdk/make/java/java/mapfile-vers | 2 +- jdk/make/sun/rmi/rmi/Makefile | 31 +------------ jdk/make/sun/rmi/rmi/mapfile-vers | 33 -------------- .../classes/java/io/ObjectInputStream.java | 5 ++- jdk/src/share/classes/sun/misc/VM.java | 6 +++ .../sun/rmi/server/MarshalInputStream.java | 4 +- .../share/native/java/io/ObjectInputStream.c | 13 ------ jdk/src/share/native/sun/misc/VM.c | 5 +++ .../sun/rmi/server/MarshalInputStream.c | 44 ------------------- 9 files changed, 19 insertions(+), 124 deletions(-) delete mode 100644 jdk/make/sun/rmi/rmi/mapfile-vers delete mode 100644 jdk/src/share/native/sun/rmi/server/MarshalInputStream.c diff --git a/jdk/make/java/java/mapfile-vers b/jdk/make/java/java/mapfile-vers index 74523b44674..8517e713dd9 100644 --- a/jdk/make/java/java/mapfile-vers +++ b/jdk/make/java/java/mapfile-vers @@ -90,7 +90,6 @@ SUNWprivate_1.1 { Java_java_io_FileSystem_getFileSystem; Java_java_io_ObjectInputStream_bytesToDoubles; Java_java_io_ObjectInputStream_bytesToFloats; - Java_java_io_ObjectInputStream_latestUserDefinedLoader; Java_java_io_ObjectOutputStream_doublesToBytes; Java_java_io_ObjectOutputStream_floatsToBytes; Java_java_io_ObjectStreamClass_hasStaticInitializer; @@ -275,6 +274,7 @@ SUNWprivate_1.1 { Java_sun_misc_Version_getJvmVersionInfo; Java_sun_misc_Version_getJvmSpecialVersion; Java_sun_misc_VM_getThreadStateValues; + Java_sun_misc_VM_latestUserDefinedLoader; Java_sun_misc_VM_initialize; Java_sun_misc_VMSupport_initAgentProperties; diff --git a/jdk/make/sun/rmi/rmi/Makefile b/jdk/make/sun/rmi/rmi/Makefile index 127777229e4..1718329b00c 100644 --- a/jdk/make/sun/rmi/rmi/Makefile +++ b/jdk/make/sun/rmi/rmi/Makefile @@ -30,15 +30,8 @@ BUILDDIR = ../../.. PACKAGE = sun.rmi PRODUCT = sun -LIBRARY = rmi include $(BUILDDIR)/common/Defs.gmk -# -# Add use of a mapfile -# -FILES_m = mapfile-vers -include $(BUILDDIR)/common/Mapfile-vers.gmk - # # Java files to compile. # @@ -51,32 +44,10 @@ AUTO_FILES_JAVA_DIRS = \ sun/rmi/transport \ com/sun/rmi -# -# Native files to compile. -# -FILES_c = \ - sun/rmi/server/MarshalInputStream.c - -# -# Add ambient vpath to pick up files not part of sun.rmi package -# -vpath %.c $(SHARE_SRC)/native/sun/rmi/server - -# -# Exported files that require generated .h -# -FILES_export = \ - sun/rmi/server/MarshalInputStream.java - -# -# Link to JVM for JVM_LatestUserDefinedLoader -# -OTHER_LDLIBS = $(JVMLIB) - # # Rules # -include $(BUILDDIR)/common/Library.gmk +include $(BUILDDIR)/common/Rules.gmk # # Full package names of implementations requiring stubs diff --git a/jdk/make/sun/rmi/rmi/mapfile-vers b/jdk/make/sun/rmi/rmi/mapfile-vers deleted file mode 100644 index dc334026fde..00000000000 --- a/jdk/make/sun/rmi/rmi/mapfile-vers +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright (c) 2005, 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. -# - -# Define library interface. - -SUNWprivate_1.1 { - global: - Java_sun_rmi_server_MarshalInputStream_latestUserDefinedLoader; - local: - *; -}; diff --git a/jdk/src/share/classes/java/io/ObjectInputStream.java b/jdk/src/share/classes/java/io/ObjectInputStream.java index 26a764f7a1e..04705e63229 100644 --- a/jdk/src/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/share/classes/java/io/ObjectInputStream.java @@ -2025,8 +2025,9 @@ public class ObjectInputStream * This method should not be removed or its signature changed without * corresponding modifications to the above class. */ - // REMIND: change name to something more accurate? - private static native ClassLoader latestUserDefinedLoader(); + private static ClassLoader latestUserDefinedLoader() { + return sun.misc.VM.latestUserDefinedLoader(); + } /** * Default GetField implementation. diff --git a/jdk/src/share/classes/sun/misc/VM.java b/jdk/src/share/classes/sun/misc/VM.java index bcec901e706..e1fb584bb2c 100644 --- a/jdk/src/share/classes/sun/misc/VM.java +++ b/jdk/src/share/classes/sun/misc/VM.java @@ -371,6 +371,12 @@ public class VM { private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010; private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020; + /* + * Returns the first non-null class loader up the execution stack, + * or null if only code from the null class loader is on the stack. + */ + public static native ClassLoader latestUserDefinedLoader(); + static { initialize(); } diff --git a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java index b67e72b9108..e560376f68d 100644 --- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java +++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java @@ -262,7 +262,9 @@ public class MarshalInputStream extends ObjectInputStream { * Returns the first non-null class loader up the execution stack, or null * if only code from the null class loader is on the stack. */ - private static native ClassLoader latestUserDefinedLoader(); + private static ClassLoader latestUserDefinedLoader() { + return sun.misc.VM.latestUserDefinedLoader(); + } /** * Fix for 4179055: Need to assist resolving sun stubs; resolve diff --git a/jdk/src/share/native/java/io/ObjectInputStream.c b/jdk/src/share/native/java/io/ObjectInputStream.c index 8b8a710e614..1e288e911ec 100644 --- a/jdk/src/share/native/java/io/ObjectInputStream.c +++ b/jdk/src/share/native/java/io/ObjectInputStream.c @@ -173,16 +173,3 @@ Java_java_io_ObjectInputStream_bytesToDoubles(JNIEnv *env, (*env)->ReleasePrimitiveArrayCritical(env, dst, doubles, 0); } -/* - * Class: java_io_ObjectInputStream - * Method: latestUserDefinedLoader - * Signature: ()Ljava/lang/ClassLoader; - * - * Returns the first non-null class loader up the execution stack, or null - * if only code from the null class loader is on the stack. - */ -JNIEXPORT jobject JNICALL -Java_java_io_ObjectInputStream_latestUserDefinedLoader(JNIEnv *env, jclass cls) -{ - return JVM_LatestUserDefinedLoader(env); -} diff --git a/jdk/src/share/native/sun/misc/VM.c b/jdk/src/share/native/sun/misc/VM.c index 8744da78403..2dbeb985d81 100644 --- a/jdk/src/share/native/sun/misc/VM.c +++ b/jdk/src/share/native/sun/misc/VM.c @@ -111,6 +111,11 @@ Java_sun_misc_VM_getThreadStateValues(JNIEnv *env, jclass cls, get_thread_state_info(env, JAVA_THREAD_STATE_TERMINATED, values, names); } +JNIEXPORT jobject JNICALL +Java_sun_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) { + return JVM_LatestUserDefinedLoader(env); +} + typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t); JNIEXPORT void JNICALL diff --git a/jdk/src/share/native/sun/rmi/server/MarshalInputStream.c b/jdk/src/share/native/sun/rmi/server/MarshalInputStream.c deleted file mode 100644 index 089afbdb330..00000000000 --- a/jdk/src/share/native/sun/rmi/server/MarshalInputStream.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2000, 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. - */ - -#include "jni.h" -#include "jvm.h" -#include "jni_util.h" - -#include "sun_rmi_server_MarshalInputStream.h" - -/* - * Class: sun_rmi_server_MarshalInputStream - * Method: latestUserDefinedLoader - * Signature: ()Ljava/lang/ClassLoader; - * - * Returns the first non-null class loader up the execution stack, or null - * if only code from the null class loader is on the stack. - */ -JNIEXPORT jobject JNICALL -Java_sun_rmi_server_MarshalInputStream_latestUserDefinedLoader(JNIEnv *env, jclass cls) -{ - return JVM_LatestUserDefinedLoader(env); -} From f5ff85a77a4969f0809cc2892fef0f478910f878 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Mon, 24 Oct 2011 21:03:41 +0100 Subject: [PATCH 25/41] 7103549: Remove dependencies on libjava and libjvm from security libraries Reviewed-by: vinnie, ohair, alanb, dholmes --- .../com/sun/security/auth/module/Makefile | 4 - jdk/make/common/Defs.gmk | 24 +++++- jdk/make/common/Library.gmk | 2 +- jdk/make/sun/security/ec/Makefile | 6 +- jdk/make/sun/security/jgss/wrapper/Makefile | 3 +- jdk/make/sun/security/krb5/Makefile | 9 -- jdk/make/sun/security/mscapi/Makefile | 2 +- jdk/make/sun/security/pkcs11/Makefile | 6 +- jdk/make/sun/security/smartcardio/Makefile | 4 +- .../sun/security/pkcs11/wrapper/p11_convert.c | 38 ++++---- .../sun/security/pkcs11/wrapper/p11_digest.c | 4 +- .../sun/security/pkcs11/wrapper/p11_dual.c | 8 +- .../sun/security/pkcs11/wrapper/p11_general.c | 7 +- .../sun/security/pkcs11/wrapper/p11_keymgmt.c | 4 +- .../sun/security/pkcs11/wrapper/p11_mutex.c | 28 +++--- .../sun/security/pkcs11/wrapper/p11_objmgmt.c | 4 +- .../security/pkcs11/wrapper/p11_sessmgmt.c | 12 ++- .../sun/security/pkcs11/wrapper/p11_sign.c | 20 ++--- .../sun/security/pkcs11/wrapper/p11_util.c | 86 ++++++++++++------- .../security/pkcs11/wrapper/pkcs11wrapper.h | 3 +- .../native/sun/security/pkcs11/j2secmod_md.c | 4 +- .../native/sun/security/smartcardio/pcsc_md.c | 32 ++++++- .../native/sun/security/pkcs11/j2secmod_md.c | 4 +- 23 files changed, 180 insertions(+), 134 deletions(-) diff --git a/jdk/make/com/sun/security/auth/module/Makefile b/jdk/make/com/sun/security/auth/module/Makefile index c274fac637a..2f6aabab01d 100644 --- a/jdk/make/com/sun/security/auth/module/Makefile +++ b/jdk/make/com/sun/security/auth/module/Makefile @@ -78,7 +78,3 @@ endif # linux # include $(BUILDDIR)/common/Library.gmk -# -# JVMDI implementation lives in the VM. -# -OTHER_LDLIBS = $(JVMLIB) diff --git a/jdk/make/common/Defs.gmk b/jdk/make/common/Defs.gmk index e46aedeffe1..99d1ed1a69e 100644 --- a/jdk/make/common/Defs.gmk +++ b/jdk/make/common/Defs.gmk @@ -220,14 +220,30 @@ JDK_LOCALES = ja zh_CN JRE_NONEXIST_LOCALES = en en_US de_DE es_ES fr_FR it_IT ja_JP ko_KR sv_SE zh # -# All libraries except libjava and libjvm itself link against libjvm and -# libjava, the latter for its exported common utilities. libjava only links -# against libjvm. Programs' makefiles take their own responsibility for +# For now, most libraries except libjava and libjvm itself link against libjvm +# and libjava, the latter for its exported common utilities. libjava only +# links against libjvm. Programs' makefiles take their own responsibility for # adding other libs. # +# The makefiles for these packages do not link against libjvm and libjava. +# This list will eventually go away and each Programs' makefiles +# will have to explicitly declare that they want to link to libjava/libjvm +# +NO_JAVALIB_PKGS = \ + sun.security.mscapi \ + sun.security.krb5 \ + sun.security.pkcs11 \ + sun.security.jgss \ + sun.security.jgss.wrapper \ + sun.security.ec \ + sun.security.smartcardio \ + com.sun.security.auth.module + ifdef PACKAGE # put JAVALIB first, but do not lose any platform specific values.... - LDLIBS_COMMON = $(JAVALIB) + ifeq (,$(findstring $(PACKAGE),$(NO_JAVALIB_PKGS))) + LDLIBS_COMMON = $(JAVALIB) + endif endif # PACKAGE # diff --git a/jdk/make/common/Library.gmk b/jdk/make/common/Library.gmk index 9999406b718..6c9b97997ce 100644 --- a/jdk/make/common/Library.gmk +++ b/jdk/make/common/Library.gmk @@ -165,7 +165,7 @@ $(ACTUAL_LIBRARY):: $(OBJDIR)/$(LIBRARY).lcf $(LINK) -dll -out:$(OBJDIR)/$(@F) \ -map:$(OBJDIR)/$(LIBRARY).map \ $(LFLAGS) @$(OBJDIR)/$(LIBRARY).lcf \ - $(OTHER_LCF) $(JAVALIB) $(LDLIBS) + $(OTHER_LCF) $(LDLIBS) $(CP) $(OBJDIR)/$(@F) $@ @$(call binary_file_verification,$@) $(CP) $(OBJDIR)/$(LIBRARY).map $(@D) diff --git a/jdk/make/sun/security/ec/Makefile b/jdk/make/sun/security/ec/Makefile index 4c95e33bde7..146a24e7a9b 100644 --- a/jdk/make/sun/security/ec/Makefile +++ b/jdk/make/sun/security/ec/Makefile @@ -192,10 +192,8 @@ ifeq ($(NATIVE_ECC_AVAILABLE), true) # # Libraries to link # - ifeq ($(PLATFORM), windows) - OTHER_LDLIBS += $(JVMLIB) - else - OTHER_LDLIBS = -ldl $(JVMLIB) $(LIBCXX) + ifneq ($(PLATFORM), windows) + OTHER_LDLIBS = $(LIBCXX) endif include $(BUILDDIR)/common/Mapfile-vers.gmk diff --git a/jdk/make/sun/security/jgss/wrapper/Makefile b/jdk/make/sun/security/jgss/wrapper/Makefile index c7c0a6a1672..fead6e2e8d1 100644 --- a/jdk/make/sun/security/jgss/wrapper/Makefile +++ b/jdk/make/sun/security/jgss/wrapper/Makefile @@ -72,5 +72,6 @@ include $(BUILDDIR)/common/Library.gmk # Libraries to link # ifneq ($(PLATFORM), windows) - OTHER_LDLIBS = -ldl $(JVMLIB) + OTHER_LDLIBS = -ldl endif + diff --git a/jdk/make/sun/security/krb5/Makefile b/jdk/make/sun/security/krb5/Makefile index 3b6d4f62046..848a694b7b5 100644 --- a/jdk/make/sun/security/krb5/Makefile +++ b/jdk/make/sun/security/krb5/Makefile @@ -69,15 +69,6 @@ else include $(BUILDDIR)/common/Classes.gmk endif # PLATFORM -# -# Libraries to link -# -ifeq ($(PLATFORM), windows) - OTHER_LDLIBS = $(JVMLIB) -else - OTHER_LDLIBS = -ldl $(JVMLIB) -endif - build: ifeq ($(PLATFORM),windows) $(call make-launcher, kinit, sun.security.krb5.internal.tools.Kinit, , ) diff --git a/jdk/make/sun/security/mscapi/Makefile b/jdk/make/sun/security/mscapi/Makefile index 405941fe7ba..389d5a1a016 100644 --- a/jdk/make/sun/security/mscapi/Makefile +++ b/jdk/make/sun/security/mscapi/Makefile @@ -159,7 +159,7 @@ include $(BUILDDIR)/common/Library.gmk # Libraries to link # ifeq ($(PLATFORM), windows) - OTHER_LDLIBS += $(JVMLIB) Crypt32.Lib + OTHER_LDLIBS += Crypt32.Lib endif # diff --git a/jdk/make/sun/security/pkcs11/Makefile b/jdk/make/sun/security/pkcs11/Makefile index 2d59f13a018..04057765a36 100644 --- a/jdk/make/sun/security/pkcs11/Makefile +++ b/jdk/make/sun/security/pkcs11/Makefile @@ -159,10 +159,8 @@ include $(BUILDDIR)/common/Library.gmk # # Libraries to link # -ifeq ($(PLATFORM), windows) - OTHER_LDLIBS = $(JVMLIB) -else - OTHER_LDLIBS = -ldl $(JVMLIB) +ifneq ($(PLATFORM), windows) + OTHER_LDLIBS = -ldl endif # Other config files diff --git a/jdk/make/sun/security/smartcardio/Makefile b/jdk/make/sun/security/smartcardio/Makefile index 75b315d6f52..1dae7a11f16 100644 --- a/jdk/make/sun/security/smartcardio/Makefile +++ b/jdk/make/sun/security/smartcardio/Makefile @@ -73,8 +73,8 @@ include $(BUILDDIR)/common/Library.gmk # Libraries to link # ifeq ($(PLATFORM), windows) - OTHER_LDLIBS = $(JVMLIB) winscard.lib + OTHER_LDLIBS = winscard.lib else - OTHER_LDLIBS = -ldl $(JVMLIB) + OTHER_LDLIBS = -ldl OTHER_CFLAGS = -D__sun_jdk endif diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c index c32a278b585..34080238b1b 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_convert.c @@ -273,7 +273,7 @@ CK_VERSION_PTR jVersionToCKVersionPtr(JNIEnv *env, jobject jVersion) /* allocate memory for CK_VERSION pointer */ ckpVersion = (CK_VERSION_PTR) malloc(sizeof(CK_VERSION)); if (ckpVersion == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } ckpVersion->major = jByteToCKByte(jMajor); @@ -326,7 +326,7 @@ CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate) /* allocate memory for CK_DATE pointer */ ckpDate = (CK_DATE *) malloc(sizeof(CK_DATE)); if (ckpDate == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -340,7 +340,7 @@ CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate) jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar)); if (jTempChars == NULL) { free(ckpDate); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } (*env)->GetCharArrayRegion(env, jYear, 0, ckLength, jTempChars); @@ -364,7 +364,7 @@ CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate) jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar)); if (jTempChars == NULL) { free(ckpDate); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } (*env)->GetCharArrayRegion(env, jMonth, 0, ckLength, jTempChars); @@ -388,7 +388,7 @@ CK_DATE * jDateObjectPtrToCKDatePtr(JNIEnv *env, jobject jDate) jTempChars = (jchar*) malloc((ckLength) * sizeof(jchar)); if (jTempChars == NULL) { free(ckpDate); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } (*env)->GetCharArrayRegion(env, jDay, 0, ckLength, jTempChars); @@ -558,7 +558,7 @@ CK_TLS_PRF_PARAMS jTlsPrfParamsToCKTlsPrfParam(JNIEnv *env, jobject jParam) if (ckParam.pulOutputLen == NULL) { free(ckParam.pSeed); free(ckParam.pLabel); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return ckParam; } jByteArrayToCKByteArray(env, jOutput, &(ckParam.pOutput), ckParam.pulOutputLen); @@ -665,7 +665,7 @@ CK_SSL3_KEY_MAT_PARAMS jSsl3KeyMatParamToCKSsl3KeyMatParam(JNIEnv *env, jobject if (ckParam.pReturnedKeyMaterial == NULL) { free(ckParam.RandomInfo.pClientRandom); free(ckParam.RandomInfo.pServerRandom); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return ckParam; } @@ -1013,7 +1013,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR) malloc(sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1040,7 +1040,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_SSL3_KEY_MAT_PARAMS_PTR) malloc(sizeof(CK_SSL3_KEY_MAT_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1067,7 +1067,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_TLS_PRF_PARAMS_PTR) malloc(sizeof(CK_TLS_PRF_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1094,7 +1094,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_AES_CTR_PARAMS_PTR) malloc(sizeof(CK_AES_CTR_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1121,7 +1121,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_RSA_PKCS_OAEP_PARAMS_PTR) malloc(sizeof(CK_RSA_PKCS_OAEP_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1148,7 +1148,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_PBE_PARAMS_PTR) malloc(sizeof(CK_PBE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1175,7 +1175,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_PKCS5_PBKD2_PARAMS_PTR) malloc(sizeof(CK_PKCS5_PBKD2_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1202,7 +1202,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_RSA_PKCS_PSS_PARAMS_PTR) malloc(sizeof(CK_RSA_PKCS_PSS_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1229,7 +1229,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_ECDH1_DERIVE_PARAMS_PTR) malloc(sizeof(CK_ECDH1_DERIVE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1256,7 +1256,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_ECDH2_DERIVE_PARAMS_PTR) malloc(sizeof(CK_ECDH2_DERIVE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1283,7 +1283,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_X9_42_DH1_DERIVE_PARAMS_PTR) malloc(sizeof(CK_X9_42_DH1_DERIVE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } @@ -1310,7 +1310,7 @@ void jMechanismParameterToCKMechanismParameterSlow(JNIEnv *env, jobject jParam, ckpParam = (CK_X9_42_DH2_DERIVE_PARAMS_PTR) malloc(sizeof(CK_X9_42_DH2_DERIVE_PARAMS)); if (ckpParam == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c index b7288c1c842..d33e4e206f3 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_digest.c @@ -131,7 +131,7 @@ JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestSingle /* always use single part op, even for large data */ bufP = (CK_BYTE_PTR) malloc((size_t)jInLen); if (bufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0; } } @@ -190,7 +190,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestUpdate bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen); bufP = (CK_BYTE_PTR) malloc((size_t)bufLen); if (bufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c index 1d030c51e86..a76e4042f9b 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_dual.c @@ -92,7 +92,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DigestEn ckpEncryptedPart = (CK_BYTE_PTR) malloc(ckEncryptedPartLength * sizeof(CK_BYTE)); if (ckpEncryptedPart == NULL) { free(ckpPart); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -144,7 +144,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptD ckpPart = (CK_BYTE_PTR) malloc(ckPartLength * sizeof(CK_BYTE)); if (ckpPart == NULL) { free(ckpEncryptedPart); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -196,7 +196,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignEncr ckpEncryptedPart = (CK_BYTE_PTR) malloc(ckEncryptedPartLength * sizeof(CK_BYTE)); if (ckpEncryptedPart == NULL) { free(ckpPart); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -248,7 +248,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptV ckpPart = (CK_BYTE_PTR) malloc(ckPartLength * sizeof(CK_BYTE)); if (ckpPart == NULL) { free(ckpEncryptedPart); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c index a48c08b4db6..14085a16213 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_general.c @@ -71,7 +71,10 @@ jfieldID mech_pParameterID; jclass jByteArrayClass; jclass jLongClass; +JavaVM* jvm = NULL; + JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { + jvm = vm; return JNI_VERSION_1_4; } @@ -351,7 +354,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetSlotList ckpSlotList = (CK_SLOT_ID_PTR) malloc(ckTokenNumber * sizeof(CK_SLOT_ID)); if (ckpSlotList == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -652,7 +655,7 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetMechanismList ckpMechanismList = (CK_MECHANISM_TYPE_PTR) malloc(ckMechanismNumber * sizeof(CK_MECHANISM_TYPE)); if (ckpMechanismList == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c index 7f987fb3c26..e74230f17a6 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c @@ -165,7 +165,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Generate if (ckMechanism.pParameter != NULL_PTR) { free(ckMechanism.pParameter); } - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } ckpPublicKeyHandle = ckpKeyHandles; /* first element of array is Public Key */ @@ -253,7 +253,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1WrapKey if (ckMechanism.pParameter != NULL_PTR) { free(ckMechanism.pParameter); } - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c index 6bc1edcd99c..29c80b8a799 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c @@ -92,7 +92,7 @@ CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) /* convert the Java InitArgs object to a pointer to a CK_C_INITIALIZE_ARGS structure */ ckpInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); if (ckpInitArgs == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL_PTR; } @@ -141,7 +141,7 @@ CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) ckpGlobalInitArgs = (CK_C_INITIALIZE_ARGS_PTR) malloc(sizeof(CK_C_INITIALIZE_ARGS)); if (ckpGlobalInitArgs == NULL) { free(ckpInitArgs); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL_PTR; } @@ -178,9 +178,8 @@ CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) */ CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex) { - JavaVM *jvm; + extern JavaVM *jvm; JNIEnv *env; - jsize actualNumberVMs; jint returnValue; jthrowable pkcs11Exception; jclass pkcs11ExceptionClass; @@ -196,8 +195,7 @@ CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex) /* Get the currently running Java VM */ - returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); - if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ;} /* there is no VM running */ + if (jvm == NULL) { return rv ;} /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); @@ -273,9 +271,8 @@ CK_RV callJCreateMutex(CK_VOID_PTR_PTR ppMutex) */ CK_RV callJDestroyMutex(CK_VOID_PTR pMutex) { - JavaVM *jvm; + extern JavaVM *jvm; JNIEnv *env; - jsize actualNumberVMs; jint returnValue; jthrowable pkcs11Exception; jclass pkcs11ExceptionClass; @@ -291,8 +288,7 @@ CK_RV callJDestroyMutex(CK_VOID_PTR pMutex) /* Get the currently running Java VM */ - returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); - if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */ + if (jvm == NULL) { return rv ; } /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); @@ -367,9 +363,8 @@ CK_RV callJDestroyMutex(CK_VOID_PTR pMutex) */ CK_RV callJLockMutex(CK_VOID_PTR pMutex) { - JavaVM *jvm; + extern JavaVM *jvm; JNIEnv *env; - jsize actualNumberVMs; jint returnValue; jthrowable pkcs11Exception; jclass pkcs11ExceptionClass; @@ -385,8 +380,7 @@ CK_RV callJLockMutex(CK_VOID_PTR pMutex) /* Get the currently running Java VM */ - returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); - if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */ + if (jvm == NULL) { return rv ; } /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); @@ -457,9 +451,8 @@ CK_RV callJLockMutex(CK_VOID_PTR pMutex) */ CK_RV callJUnlockMutex(CK_VOID_PTR pMutex) { - JavaVM *jvm; + extern JavaVM *jvm; JNIEnv *env; - jsize actualNumberVMs; jint returnValue; jthrowable pkcs11Exception; jclass pkcs11ExceptionClass; @@ -475,8 +468,7 @@ CK_RV callJUnlockMutex(CK_VOID_PTR pMutex) /* Get the currently running Java VM */ - returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); - if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */ + if (jvm == NULL) { return rv ; } /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c index aea03eeba0d..910453eacd7 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_objmgmt.c @@ -258,7 +258,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetAttributeVa ckpAttributes[i].pValue = (void *) malloc(ckBufferLength); if (ckpAttributes[i].pValue == NULL) { freeCKAttributeArray(ckpAttributes, i); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } ckpAttributes[i].ulValueLen = ckBufferLength; @@ -390,7 +390,7 @@ JNIEXPORT jlongArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1FindObje ckMaxObjectLength = jLongToCKULong(jMaxObjectCount); ckpObjectHandleArray = (CK_OBJECT_HANDLE_PTR) malloc(sizeof(CK_OBJECT_HANDLE) * ckMaxObjectLength); if (ckpObjectHandleArray == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c index 1b7538a49a3..524fde013af 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sessmgmt.c @@ -98,7 +98,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1OpenSession if (jNotify != NULL) { notifyEncapsulation = (NotifyEncapsulation *) malloc(sizeof(NotifyEncapsulation)); if (notifyEncapsulation == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0L; } notifyEncapsulation->jApplicationData = (jApplication != NULL) @@ -301,7 +301,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetOpera ckpState = (CK_BYTE_PTR) malloc(ckStateLength); if (ckpState == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -435,7 +435,7 @@ void putNotifyEntry(JNIEnv *env, CK_SESSION_HANDLE hSession, NotifyEncapsulation newNode = (NotifyListNode *) malloc(sizeof(NotifyListNode)); if (newNode == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } newNode->hSession = hSession; @@ -558,9 +558,8 @@ CK_RV notifyCallback( ) { NotifyEncapsulation *notifyEncapsulation; - JavaVM *jvm; + extern JavaVM *jvm; JNIEnv *env; - jsize actualNumberVMs; jint returnValue; jlong jSessionHandle; jlong jEvent; @@ -577,8 +576,7 @@ CK_RV notifyCallback( notifyEncapsulation = (NotifyEncapsulation *) pApplication; /* Get the currently running Java VM */ - returnValue = JNI_GetCreatedJavaVMs(&jvm, (jsize) 1, &actualNumberVMs); - if ((returnValue != 0) || (actualNumberVMs <= 0)) { return rv ; } /* there is no VM running */ + if (jvm == NULL) { return rv ; } /* there is no VM running */ /* Determine, if current thread is already attached */ returnValue = (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION_1_2); diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c index e4a43937f51..e07bcf59d59 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_sign.c @@ -132,7 +132,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Sign ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE)); if (ckpSignature == NULL) { free(ckpData); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } @@ -146,7 +146,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Sign ckpSignature = (CK_BYTE_PTR) malloc(256 * sizeof(CK_BYTE)); if (ckpSignature == NULL) { free(ckpData); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength); @@ -156,7 +156,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1Sign ckpSignature = (CK_BYTE_PTR) malloc(ckSignatureLength * sizeof(CK_BYTE)); if (ckpSignature == NULL) { free(ckpData); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } rv = (*ckpFunctions->C_Sign)(ckSessionHandle, ckpData, ckDataLength, ckpSignature, &ckSignatureLength); @@ -210,7 +210,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignUpdate bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen); bufP = (CK_BYTE_PTR) malloc((size_t)bufLen); if (bufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } } @@ -270,7 +270,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignFina if (rv == CKR_BUFFER_TOO_SMALL) { bufP = (CK_BYTE_PTR) malloc(ckSignatureLength); if (bufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } rv = (*ckpFunctions->C_SignFinal)(ckSessionHandle, bufP, &ckSignatureLength); @@ -355,7 +355,7 @@ JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignRecover } else { inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen); if (inBufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0; } } @@ -373,7 +373,7 @@ JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1SignRecover if (inBufP != INBUF) { free(inBufP); } - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0; } rv = (*ckpFunctions->C_SignRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckSignatureLength); @@ -508,7 +508,7 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyUpdate bufLen = min(MAX_HEAP_BUFFER_LEN, jInLen); bufP = (CK_BYTE_PTR) malloc((size_t)bufLen); if (bufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } } @@ -638,7 +638,7 @@ JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyRecover } else { inBufP = (CK_BYTE_PTR) malloc((size_t)jInLen); if (inBufP == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0; } } @@ -656,7 +656,7 @@ JNIEXPORT jint JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_C_1VerifyRecover outBufP = (CK_BYTE_PTR) malloc(ckDataLength); if (outBufP == NULL) { if (inBufP != INBUF) { free(inBufP); } - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return 0; } rv = (*ckpFunctions->C_VerifyRecover)(ckSessionHandle, inBufP, jInLen, outBufP, &ckDataLength); diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c index 36a4b15943a..9436f1ece4c 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_util.c @@ -213,28 +213,52 @@ jlong ckAssertReturnValueOK(JNIEnv *env, CK_RV returnValue) return jErrorCode ; } + /* - * This function simply throws an IOException - * - * @param env Used to call JNI funktions and to get the Exception class. - * @param message The message string of the Exception object. + * Throws a Java Exception by name */ -void throwIOException(JNIEnv *env, const char *message) +void throwByName(JNIEnv *env, const char *name, const char *msg) { - JNU_ThrowByName(env, CLASS_IO_EXCEPTION, message); + jclass cls = (*env)->FindClass(env, name); + + if (cls != 0) /* Otherwise an exception has already been thrown */ + (*env)->ThrowNew(env, cls, msg); +} + +/* + * Throws java.lang.OutOfMemoryError + */ +void throwOutOfMemoryError(JNIEnv *env, const char *msg) +{ + throwByName(env, "java/lang/OutOfMemoryError", msg); +} + +/* + * Throws java.lang.NullPointerException + */ +void throwNullPointerException(JNIEnv *env, const char *msg) +{ + throwByName(env, "java/lang/NullPointerException", msg); +} + +/* + * Throws java.io.IOException + */ +void throwIOException(JNIEnv *env, const char *msg) +{ + throwByName(env, "java/io/IOException", msg); } /* * This function simply throws a PKCS#11RuntimeException with the given - * string as its message. If the message is NULL, the exception is created - * using the default constructor. + * string as its message. * * @param env Used to call JNI funktions and to get the Exception class. * @param jmessage The message string of the Exception object. */ void throwPKCS11RuntimeException(JNIEnv *env, const char *message) { - JNU_ThrowByName(env, CLASS_PKCS11RUNTIMEEXCEPTION, message); + throwByName(env, CLASS_PKCS11RUNTIMEEXCEPTION, message); } /* @@ -318,7 +342,7 @@ void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBO *ckpLength = (*env)->GetArrayLength(env, jArray); jpTemp = (jboolean*) malloc((*ckpLength) * sizeof(jboolean)); if (jpTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } (*env)->GetBooleanArrayRegion(env, jArray, 0, *ckpLength, jpTemp); @@ -330,7 +354,7 @@ void jBooleanArrayToCKBBoolArray(JNIEnv *env, const jbooleanArray jArray, CK_BBO *ckpArray = (CK_BBOOL*) malloc ((*ckpLength) * sizeof(CK_BBOOL)); if (*ckpArray == NULL) { free(jpTemp); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } for (i=0; i<(*ckpLength); i++) { @@ -360,7 +384,7 @@ void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR * *ckpLength = (*env)->GetArrayLength(env, jArray); jpTemp = (jbyte*) malloc((*ckpLength) * sizeof(jbyte)); if (jpTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } (*env)->GetByteArrayRegion(env, jArray, 0, *ckpLength, jpTemp); @@ -376,7 +400,7 @@ void jByteArrayToCKByteArray(JNIEnv *env, const jbyteArray jArray, CK_BYTE_PTR * *ckpArray = (CK_BYTE_PTR) malloc ((*ckpLength) * sizeof(CK_BYTE)); if (*ckpArray == NULL) { free(jpTemp); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } for (i=0; i<(*ckpLength); i++) { @@ -407,7 +431,7 @@ void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR *ckpLength = (*env)->GetArrayLength(env, jArray); jTemp = (jlong*) malloc((*ckpLength) * sizeof(jlong)); if (jTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } (*env)->GetLongArrayRegion(env, jArray, 0, *ckpLength, jTemp); @@ -419,7 +443,7 @@ void jLongArrayToCKULongArray(JNIEnv *env, const jlongArray jArray, CK_ULONG_PTR *ckpArray = (CK_ULONG_PTR) malloc (*ckpLength * sizeof(CK_ULONG)); if (*ckpArray == NULL) { free(jTemp); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } for (i=0; i<(*ckpLength); i++) { @@ -449,7 +473,7 @@ void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR * *ckpLength = (*env)->GetArrayLength(env, jArray); jpTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar)); if (jpTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jpTemp); @@ -461,7 +485,7 @@ void jCharArrayToCKCharArray(JNIEnv *env, const jcharArray jArray, CK_CHAR_PTR * *ckpArray = (CK_CHAR_PTR) malloc (*ckpLength * sizeof(CK_CHAR)); if (*ckpArray == NULL) { free(jpTemp); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } for (i=0; i<(*ckpLength); i++) { @@ -491,7 +515,7 @@ void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CH *ckpLength = (*env)->GetArrayLength(env, jArray); jTemp = (jchar*) malloc((*ckpLength) * sizeof(jchar)); if (jTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } (*env)->GetCharArrayRegion(env, jArray, 0, *ckpLength, jTemp); @@ -503,7 +527,7 @@ void jCharArrayToCKUTF8CharArray(JNIEnv *env, const jcharArray jArray, CK_UTF8CH *ckpArray = (CK_UTF8CHAR_PTR) malloc (*ckpLength * sizeof(CK_UTF8CHAR)); if (*ckpArray == NULL) { free(jTemp); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } for (i=0; i<(*ckpLength); i++) { @@ -538,7 +562,7 @@ void jStringToCKUTF8CharArray(JNIEnv *env, const jstring jArray, CK_UTF8CHAR_PTR *ckpArray = (CK_UTF8CHAR_PTR) malloc((*ckpLength + 1) * sizeof(CK_UTF8CHAR)); if (*ckpArray == NULL) { (*env)->ReleaseStringUTFChars(env, (jstring) jArray, pCharArray); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } strcpy((char*)*ckpArray, pCharArray); @@ -571,7 +595,7 @@ void jAttributeArrayToCKAttributeArray(JNIEnv *env, jobjectArray jArray, CK_ATTR *ckpLength = jLongToCKULong(jLength); *ckpArray = (CK_ATTRIBUTE_PTR) malloc(*ckpLength * sizeof(CK_ATTRIBUTE)); if (*ckpArray == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } TRACE1(", converting %d attibutes", jLength); @@ -613,7 +637,7 @@ jbyteArray ckByteArrayToJByteArray(JNIEnv *env, const CK_BYTE_PTR ckpArray, CK_U } else { jpTemp = (jbyte*) malloc((ckLength) * sizeof(jbyte)); if (jpTemp == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } for (i=0; iCallBooleanMethod(env, jObject, jValueMethod); ckpValue = (CK_BBOOL *) malloc(sizeof(CK_BBOOL)); if (ckpValue == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } *ckpValue = jBooleanToCKBBool(jValue); @@ -842,7 +866,7 @@ CK_BYTE_PTR jByteObjectToCKBytePtr(JNIEnv *env, jobject jObject) jValue = (*env)->CallByteMethod(env, jObject, jValueMethod); ckpValue = (CK_BYTE_PTR) malloc(sizeof(CK_BYTE)); if (ckpValue == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } *ckpValue = jByteToCKByte(jValue); @@ -871,7 +895,7 @@ CK_ULONG* jIntegerObjectToCKULongPtr(JNIEnv *env, jobject jObject) jValue = (*env)->CallIntMethod(env, jObject, jValueMethod); ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG)); if (ckpValue == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } *ckpValue = jLongToCKLong(jValue); @@ -900,7 +924,7 @@ CK_ULONG* jLongObjectToCKULongPtr(JNIEnv *env, jobject jObject) jValue = (*env)->CallLongMethod(env, jObject, jValueMethod); ckpValue = (CK_ULONG *) malloc(sizeof(CK_ULONG)); if (ckpValue == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } *ckpValue = jLongToCKULong(jValue); @@ -930,7 +954,7 @@ CK_CHAR_PTR jCharObjectToCKCharPtr(JNIEnv *env, jobject jObject) jValue = (*env)->CallCharMethod(env, jObject, jValueMethod); ckpValue = (CK_CHAR_PTR) malloc(sizeof(CK_CHAR)); if (ckpValue == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return NULL; } *ckpValue = jCharToCKChar(jValue); @@ -1087,7 +1111,7 @@ void jObjectToPrimitiveCKObjectPtrPtr(JNIEnv *env, jobject jObject, CK_VOID_PTR malloc((strlen(exceptionMsgPrefix) + strlen(classNameString) + 1)); if (exceptionMsg == NULL) { (*env)->ReleaseStringUTFChars(env, jClassNameString, classNameString); - JNU_ThrowOutOfMemoryError(env, 0); + throwOutOfMemoryError(env, 0); return; } strcpy(exceptionMsg, exceptionMsgPrefix); diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h index ff6d550d523..bf3adf86a9d 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h @@ -228,7 +228,6 @@ #define CLASS_PKCS11EXCEPTION "sun/security/pkcs11/wrapper/PKCS11Exception" #define CLASS_PKCS11RUNTIMEEXCEPTION "sun/security/pkcs11/wrapper/PKCS11RuntimeException" #define CLASS_FILE_NOT_FOUND_EXCEPTION "java/io/FileNotFoundException" -#define CLASS_IO_EXCEPTION "java/io/IOException" #define CLASS_C_INITIALIZE_ARGS "sun/security/pkcs11/wrapper/CK_C_INITIALIZE_ARGS" #define CLASS_CREATEMUTEX "sun/security/pkcs11/wrapper/CK_CREATEMUTEX" #define CLASS_DESTROYMUTEX "sun/security/pkcs11/wrapper/CK_DESTROYMUTEX" @@ -280,6 +279,8 @@ */ jlong ckAssertReturnValueOK(JNIEnv *env, CK_RV returnValue); +void throwOutOfMemoryError(JNIEnv *env, const char *message); +void throwNullPointerException(JNIEnv *env, const char *message); void throwIOException(JNIEnv *env, const char *message); void throwPKCS11RuntimeException(JNIEnv *env, const char *message); void throwDisconnectedRuntimeException(JNIEnv *env); diff --git a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c index b445899f73b..b763bc25bb4 100644 --- a/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c +++ b/jdk/src/solaris/native/sun/security/pkcs11/j2secmod_md.c @@ -40,7 +40,7 @@ void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) { if (fAddress == NULL) { char errorMessage[256]; snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName); - JNU_ThrowNullPointerException(env, errorMessage); + throwNullPointerException(env, errorMessage); return NULL; } return fAddress; @@ -69,7 +69,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssLoadLibrary dprintf2("-handle: %u (0X%X)\n", hModule, hModule); if (hModule == NULL) { - JNU_ThrowIOException(env, dlerror()); + throwIOException(env, dlerror()); return 0; } diff --git a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c index 67e452da340..c7379810fab 100644 --- a/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c +++ b/jdk/src/solaris/native/sun/security/smartcardio/pcsc_md.c @@ -51,12 +51,40 @@ FPTR_SCardBeginTransaction scardBeginTransaction; FPTR_SCardEndTransaction scardEndTransaction; FPTR_SCardControl scardControl; +/* + * Throws a Java Exception by name + */ +void throwByName(JNIEnv *env, const char *name, const char *msg) +{ + jclass cls = (*env)->FindClass(env, name); + + if (cls != 0) /* Otherwise an exception has already been thrown */ + (*env)->ThrowNew(env, cls, msg); +} + +/* + * Throws java.lang.NullPointerException + */ +void throwNullPointerException(JNIEnv *env, const char *msg) +{ + throwByName(env, "java/lang/NullPointerException", msg); +} + +/* + * Throws java.io.IOException + */ +void throwIOException(JNIEnv *env, const char *msg) +{ + throwByName(env, "java/io/IOException", msg); +} + + void *findFunction(JNIEnv *env, void *hModule, char *functionName) { void *fAddress = dlsym(hModule, functionName); if (fAddress == NULL) { char errorMessage[256]; snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName); - JNU_ThrowNullPointerException(env, errorMessage); + throwNullPointerException(env, errorMessage); return NULL; } return fAddress; @@ -69,7 +97,7 @@ JNIEXPORT void JNICALL Java_sun_security_smartcardio_PlatformPCSC_initialize (*env)->ReleaseStringUTFChars(env, jLibName, libName); if (hModule == NULL) { - JNU_ThrowIOException(env, dlerror()); + throwIOException(env, dlerror()); return; } scardEstablishContext = (FPTR_SCardEstablishContext)findFunction(env, hModule, "SCardEstablishContext"); diff --git a/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c b/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c index 4a8d7583a4c..fac24a6063f 100644 --- a/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c +++ b/jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.c @@ -37,7 +37,7 @@ void *findFunction(JNIEnv *env, jlong jHandle, const char *functionName) { if (fAddress == NULL) { char errorMessage[256]; _snprintf(errorMessage, sizeof(errorMessage), "Symbol not found: %s", functionName); - JNU_ThrowNullPointerException(env, errorMessage); + throwNullPointerException(env, errorMessage); return NULL; } return fAddress; @@ -78,7 +78,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_pkcs11_Secmod_nssLoadLibrary NULL ); dprintf1("-error: %s\n", lpMsgBuf); - JNU_ThrowIOException(env, (char*)lpMsgBuf); + throwIOException(env, (char*)lpMsgBuf); LocalFree(lpMsgBuf); return 0; } From 616b1a997f8f5d7b821cdc151903092a3c20325f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 25 Oct 2011 09:27:20 +0100 Subject: [PATCH 26/41] 7104577: Changes for 7104209 cause many RMI tests to fail Reviewed-by: chegar --- .../share/classes/sun/rmi/server/MarshalInputStream.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java index e560376f68d..cb32017b4ad 100644 --- a/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java +++ b/jdk/src/share/classes/sun/rmi/server/MarshalInputStream.java @@ -109,14 +109,6 @@ public class MarshalInputStream extends ObjectInputStream { } } - /** - * Load the "rmi" native library. - */ - static { - java.security.AccessController.doPrivileged( - new sun.security.action.LoadLibraryAction("rmi")); - } - /** * Create a new MarshalInputStream object. */ From 1469ebc6da4d8b22ee13ce081f850111af281f24 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Tue, 25 Oct 2011 15:40:34 +0100 Subject: [PATCH 27/41] 7104618: MessageInfo.java is failing after lexer changes Two langtools regression tests cannot be built due to a bad import statement Reviewed-by: jjg --- langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java index 0c8c2153817..1544e57773b 100644 --- a/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java +++ b/langtools/test/tools/javac/diags/ArgTypeCompilerFactory.java @@ -35,7 +35,7 @@ import com.sun.tools.javac.code.*; import com.sun.tools.javac.file.*; import com.sun.tools.javac.main.Main; import com.sun.tools.javac.main.JavaCompiler; -import com.sun.tools.javac.parser.Token; +import com.sun.tools.javac.parser.Tokens.TokenKind; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration; import javax.lang.model.SourceVersion; @@ -319,7 +319,7 @@ class ArgTypeCompilerFactory implements Example.Compiler.Factory { return "modifier"; if (o instanceof KindName) return "symbol kind"; - if (o instanceof Token) + if (o instanceof TokenKind) return "token"; if (o instanceof Symbol) return "symbol"; From d20f9f51bc1fa35eee20112666867386912cd62c Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 25 Oct 2011 10:48:05 -0700 Subject: [PATCH 28/41] 7104039: refactor/cleanup javac Paths class Reviewed-by: mcimadamore --- .../classes/com/sun/tools/apt/main/Main.java | 4 +- .../tools/javac/file/JavacFileManager.java | 75 +- .../com/sun/tools/javac/file/Locations.java | 769 ++++++++++++++++++ .../com/sun/tools/javac/file/Paths.java | 540 ------------ .../tools/javac/nio/JavacPathFileManager.java | 8 +- .../sun/tools/javac/util/BaseFileManager.java | 12 +- .../com/sun/tools/javadoc/DocletInvoker.java | 2 +- 7 files changed, 789 insertions(+), 621 deletions(-) create mode 100644 langtools/src/share/classes/com/sun/tools/javac/file/Locations.java delete mode 100644 langtools/src/share/classes/com/sun/tools/javac/file/Paths.java diff --git a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java index 5c2cfcc4b7d..80e7e1dbda5 100644 --- a/langtools/src/share/classes/com/sun/tools/apt/main/Main.java +++ b/langtools/src/share/classes/com/sun/tools/apt/main/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2010, 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 @@ -56,7 +56,7 @@ import com.sun.tools.apt.comp.UsageMessageNeededException; import com.sun.tools.apt.util.Bark; import com.sun.mirror.apt.AnnotationProcessorFactory; -import static com.sun.tools.javac.file.Paths.pathToURLs; +import static com.sun.tools.javac.file.Locations.pathToURLs; /** This class provides a commandline interface to the apt build-time * tool. diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java index ae6cf2d2757..78774566915 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -54,17 +54,14 @@ import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; -import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.file.RelativePath.RelativeFile; import com.sun.tools.javac.file.RelativePath.RelativeDirectory; -import com.sun.tools.javac.main.OptionName; import com.sun.tools.javac.util.BaseFileManager; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import static javax.tools.StandardLocation.*; -import static com.sun.tools.javac.main.OptionName.*; /** * This class provides access to the source, class and other files @@ -89,23 +86,9 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil private boolean contextUseOptimizedZip; private ZipFileIndexCache zipFileIndexCache; - private final File uninited = new File("U N I N I T E D"); - private final Set sourceOrClass = EnumSet.of(JavaFileObject.Kind.SOURCE, JavaFileObject.Kind.CLASS); - /** The standard output directory, primarily used for classes. - * Initialized by the "-d" option. - * If classOutDir = null, files are written into same directory as the sources - * they were generated from. - */ - private File classOutDir = uninited; - - /** The output directory, used when generating sources while processing annotations. - * Initialized by the "-s" option. - */ - private File sourceOutDir = uninited; - protected boolean mmappedIO; protected boolean ignoreSymbolFile; @@ -169,7 +152,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil @Override public boolean isDefaultBootClassPath() { - return searchPaths.isDefaultBootClassPath(); + return locations.isDefaultBootClassPath(); } public JavaFileObject getFileForInput(String name) { @@ -483,7 +466,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil */ private Archive openArchive(File zipFileName, boolean useOptimizedZip) throws IOException { File origZipFileName = zipFileName; - if (!ignoreSymbolFile && searchPaths.isDefaultBootClassPathRtJar(zipFileName)) { + if (!ignoreSymbolFile && locations.isDefaultBootClassPathRtJar(zipFileName)) { File file = zipFileName.getParentFile().getParentFile(); // ${java.home} if (new File(file.getName()).equals(new File("jre"))) file = file.getParentFile(); @@ -770,7 +753,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil } else if (location == SOURCE_OUTPUT) { dir = (getSourceOutDir() != null ? getSourceOutDir() : getClassOutDir()); } else { - Iterable path = searchPaths.getPathForLocation(location); + Iterable path = locations.getLocation(location); dir = null; for (File f: path) { dir = f; @@ -805,64 +788,20 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil throws IOException { nullCheck(location); - searchPaths.lazy(); - - final File dir = location.isOutputLocation() ? getOutputDirectory(path) : null; - - if (location == CLASS_OUTPUT) - classOutDir = getOutputLocation(dir, D); - else if (location == SOURCE_OUTPUT) - sourceOutDir = getOutputLocation(dir, S); - else - searchPaths.setPathForLocation(location, path); - } - // where - private File getOutputDirectory(Iterable path) throws IOException { - if (path == null) - return null; - Iterator pathIter = path.iterator(); - if (!pathIter.hasNext()) - throw new IllegalArgumentException("empty path for directory"); - File dir = pathIter.next(); - if (pathIter.hasNext()) - throw new IllegalArgumentException("path too long for directory"); - if (!dir.exists()) - throw new FileNotFoundException(dir + ": does not exist"); - else if (!dir.isDirectory()) - throw new IOException(dir + ": not a directory"); - return dir; - } - - private File getOutputLocation(File dir, OptionName defaultOptionName) { - if (dir != null) - return dir; - String arg = options.get(defaultOptionName); - if (arg == null) - return null; - return new File(arg); + locations.setLocation(location, path); } public Iterable getLocation(Location location) { nullCheck(location); - searchPaths.lazy(); - if (location == CLASS_OUTPUT) { - return (getClassOutDir() == null ? null : List.of(getClassOutDir())); - } else if (location == SOURCE_OUTPUT) { - return (getSourceOutDir() == null ? null : List.of(getSourceOutDir())); - } else - return searchPaths.getPathForLocation(location); + return locations.getLocation(location); } private File getClassOutDir() { - if (classOutDir == uninited) - classOutDir = getOutputLocation(null, D); - return classOutDir; + return locations.getOutputLocation(CLASS_OUTPUT); } private File getSourceOutDir() { - if (sourceOutDir == uninited) - sourceOutDir = getOutputLocation(null, S); - return sourceOutDir; + return locations.getOutputLocation(SOURCE_OUTPUT); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java new file mode 100644 index 00000000000..8ef1eeef7f4 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java @@ -0,0 +1,769 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.file; + +import java.io.FileNotFoundException; +import java.util.Iterator; +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.zip.ZipFile; +import javax.tools.JavaFileManager.Location; +import javax.tools.StandardLocation; + +import com.sun.tools.javac.code.Lint; +import com.sun.tools.javac.main.OptionName; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.javac.util.Log; +import com.sun.tools.javac.util.Options; + +import javax.tools.JavaFileManager; +import static javax.tools.StandardLocation.*; +import static com.sun.tools.javac.main.OptionName.*; + +/** This class converts command line arguments, environment variables + * and system properties (in File.pathSeparator-separated String form) + * into a boot class path, user class path, and source path (in + * Collection form). + * + *

This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class Locations { + + /** The log to use for warning output */ + private Log log; + + /** Collection of command-line options */ + private Options options; + + /** Handler for -Xlint options */ + private Lint lint; + + /** Access to (possibly cached) file info */ + private FSInfo fsInfo; + + /** Whether to warn about non-existent path elements */ + private boolean warn; + + // TODO: remove need for this + private boolean inited = false; // TODO? caching bad? + + public Locations() { + initHandlers(); + } + + public void update(Log log, Options options, Lint lint, FSInfo fsInfo) { + this.log = log; + this.options = options; + this.lint = lint; + this.fsInfo = fsInfo; + } + + public Collection bootClassPath() { + return getLocation(PLATFORM_CLASS_PATH); + } + + public boolean isDefaultBootClassPath() { + BootClassPathLocationHandler h = + (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH); + return h.isDefault(); + } + + boolean isDefaultBootClassPathRtJar(File file) { + BootClassPathLocationHandler h = + (BootClassPathLocationHandler) getHandler(PLATFORM_CLASS_PATH); + return h.isDefaultRtJar(file); + } + + public Collection userClassPath() { + return getLocation(CLASS_PATH); + } + + public Collection sourcePath() { + Collection p = getLocation(SOURCE_PATH); + // TODO: this should be handled by the LocationHandler + return p == null || p.isEmpty() ? null : p; + } + + /** + * Split a path into its elements. Empty path elements will be ignored. + * @param path The path to be split + * @return The elements of the path + */ + private static Iterable getPathEntries(String path) { + return getPathEntries(path, null); + } + + /** + * Split a path into its elements. If emptyPathDefault is not null, all + * empty elements in the path, including empty elements at either end of + * the path, will be replaced with the value of emptyPathDefault. + * @param path The path to be split + * @param emptyPathDefault The value to substitute for empty path elements, + * or null, to ignore empty path elements + * @return The elements of the path + */ + private static Iterable getPathEntries(String path, File emptyPathDefault) { + ListBuffer entries = new ListBuffer(); + int start = 0; + while (start <= path.length()) { + int sep = path.indexOf(File.pathSeparatorChar, start); + if (sep == -1) + sep = path.length(); + if (start < sep) + entries.add(new File(path.substring(start, sep))); + else if (emptyPathDefault != null) + entries.add(emptyPathDefault); + start = sep + 1; + } + return entries; + } + + /** + * Utility class to help evaluate a path option. + * Duplicate entries are ignored, jar class paths can be expanded. + */ + private class Path extends LinkedHashSet { + private static final long serialVersionUID = 0; + + private boolean expandJarClassPaths = false; + private Set canonicalValues = new HashSet(); + + public Path expandJarClassPaths(boolean x) { + expandJarClassPaths = x; + return this; + } + + /** What to use when path element is the empty string */ + private File emptyPathDefault = null; + + public Path emptyPathDefault(File x) { + emptyPathDefault = x; + return this; + } + + public Path() { super(); } + + public Path addDirectories(String dirs, boolean warn) { + boolean prev = expandJarClassPaths; + expandJarClassPaths = true; + try { + if (dirs != null) + for (File dir : getPathEntries(dirs)) + addDirectory(dir, warn); + return this; + } finally { + expandJarClassPaths = prev; + } + } + + public Path addDirectories(String dirs) { + return addDirectories(dirs, warn); + } + + private void addDirectory(File dir, boolean warn) { + if (!dir.isDirectory()) { + if (warn) + log.warning(Lint.LintCategory.PATH, + "dir.path.element.not.found", dir); + return; + } + + File[] files = dir.listFiles(); + if (files == null) + return; + + for (File direntry : files) { + if (isArchive(direntry)) + addFile(direntry, warn); + } + } + + public Path addFiles(String files, boolean warn) { + if (files != null) { + addFiles(getPathEntries(files, emptyPathDefault), warn); + } + return this; + } + + public Path addFiles(String files) { + return addFiles(files, warn); + } + + public Path addFiles(Iterable files, boolean warn) { + if (files != null) { + for (File file: files) + addFile(file, warn); + } + return this; + } + + public Path addFiles(Iterable files) { + return addFiles(files, warn); + } + + public void addFile(File file, boolean warn) { + if (contains(file)) { + // discard duplicates + return; + } + + if (! fsInfo.exists(file)) { + /* No such file or directory exists */ + if (warn) { + log.warning(Lint.LintCategory.PATH, + "path.element.not.found", file); + } + super.add(file); + return; + } + + File canonFile = fsInfo.getCanonicalFile(file); + if (canonicalValues.contains(canonFile)) { + /* Discard duplicates and avoid infinite recursion */ + return; + } + + if (fsInfo.isFile(file)) { + /* File is an ordinary file. */ + if (!isArchive(file)) { + /* Not a recognized extension; open it to see if + it looks like a valid zip file. */ + try { + ZipFile z = new ZipFile(file); + z.close(); + if (warn) { + log.warning(Lint.LintCategory.PATH, + "unexpected.archive.file", file); + } + } catch (IOException e) { + // FIXME: include e.getLocalizedMessage in warning + if (warn) { + log.warning(Lint.LintCategory.PATH, + "invalid.archive.file", file); + } + return; + } + } + } + + /* Now what we have left is either a directory or a file name + conforming to archive naming convention */ + super.add(file); + canonicalValues.add(canonFile); + + if (expandJarClassPaths && fsInfo.isFile(file)) + addJarClassPath(file, warn); + } + + // Adds referenced classpath elements from a jar's Class-Path + // Manifest entry. In some future release, we may want to + // update this code to recognize URLs rather than simple + // filenames, but if we do, we should redo all path-related code. + private void addJarClassPath(File jarFile, boolean warn) { + try { + for (File f: fsInfo.getJarClassPath(jarFile)) { + addFile(f, warn); + } + } catch (IOException e) { + log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e)); + } + } + } + + /** + * Base class for handling support for the representation of Locations. + * Implementations are responsible for handling the interactions between + * the command line options for a location, and API access via setLocation. + * @see #initHandlers + * @see #getHandler + */ + protected abstract class LocationHandler { + final Location location; + final Set options; + + /** + * Create a handler. The location and options provide a way to map + * from a location or an option to the corresponding handler. + * @see #initHandlers + */ + protected LocationHandler(Location location, OptionName... options) { + this.location = location; + this.options = EnumSet.copyOf(Arrays.asList(options)); + } + + // TODO: TEMPORARY, while Options still used for command line options + void update(Options optionTable) { + for (OptionName o: options) { + String v = optionTable.get(o); + if (v != null) { + handleOption(o, v); + } + } + } + + /** @see JavaFileManager#handleOption. */ + abstract boolean handleOption(OptionName option, String value); + /** @see JavaFileManager#getLocation. */ + abstract Collection getLocation(); + /** @see JavaFileManager#setLocation. */ + abstract void setLocation(Iterable files) throws IOException; + } + + /** + * General purpose implementation for output locations, + * such as -d/CLASS_OUTPUT and -s/SOURCE_OUTPUT. + * All options are treated as equivalent (i.e. aliases.) + * The value is a single file, possibly null. + */ + private class OutputLocationHandler extends LocationHandler { + private File outputDir; + + OutputLocationHandler(Location location, OptionName... options) { + super(location, options); + } + + @Override + boolean handleOption(OptionName option, String value) { + if (!options.contains(option)) + return false; + + // TODO: could/should validate outputDir exists and is a directory + // need to decide how best to report issue for benefit of + // direct API call on JavaFileManager.handleOption(specifies IAE) + // vs. command line decoding. + outputDir = new File(value); + return true; + } + + @Override + Collection getLocation() { + return (outputDir == null) ? null : Collections.singleton(outputDir); + } + + @Override + void setLocation(Iterable files) throws IOException { + if (files == null) { + outputDir = null; + } else { + Iterator pathIter = files.iterator(); + if (!pathIter.hasNext()) + throw new IllegalArgumentException("empty path for directory"); + File dir = pathIter.next(); + if (pathIter.hasNext()) + throw new IllegalArgumentException("path too long for directory"); + if (!dir.exists()) + throw new FileNotFoundException(dir + ": does not exist"); + else if (!dir.isDirectory()) + throw new IOException(dir + ": not a directory"); + outputDir = dir; + } + } + } + + /** + * General purpose implementation for search path locations, + * such as -sourcepath/SOURCE_PATH and -processorPath/ANNOTATION_PROCESS_PATH. + * All options are treated as equivalent (i.e. aliases.) + * The value is an ordered set of files and/or directories. + */ + private class SimpleLocationHandler extends LocationHandler { + protected Collection searchPath; + + SimpleLocationHandler(Location location, OptionName... options) { + super(location, options); + } + + @Override + boolean handleOption(OptionName option, String value) { + if (!options.contains(option)) + return false; + searchPath = value == null ? null : + Collections.unmodifiableCollection(computePath(value)); + return true; + } + + protected Path computePath(String value) { + return new Path().addFiles(value); + } + + @Override + Collection getLocation() { + return searchPath; + } + + @Override + void setLocation(Iterable files) { + Path p; + if (files == null) { + p = computePath(null); + } else { + p = new Path().addFiles(files); + } + searchPath = Collections.unmodifiableCollection(p); + } + } + + /** + * Subtype of SimpleLocationHandler for -classpath/CLASS_PATH. + * If no value is given, a default is provided, based on system properties + * and other values. + */ + private class ClassPathLocationHandler extends SimpleLocationHandler { + ClassPathLocationHandler() { + super(StandardLocation.CLASS_PATH, + OptionName.CLASSPATH, OptionName.CP); + } + + @Override + Collection getLocation() { + lazy(); + return searchPath; + } + + @Override + protected Path computePath(String value) { + String cp = value; + + // CLASSPATH environment variable when run from `javac'. + if (cp == null) cp = System.getProperty("env.class.path"); + + // If invoked via a java VM (not the javac launcher), use the + // platform class path + if (cp == null && System.getProperty("application.home") == null) + cp = System.getProperty("java.class.path"); + + // Default to current working directory. + if (cp == null) cp = "."; + + return new Path() + .expandJarClassPaths(true) // Only search user jars for Class-Paths + .emptyPathDefault(new File(".")) // Empty path elt ==> current directory + .addFiles(cp); + } + + private void lazy() { + if (searchPath == null) + setLocation(null); + } + } + + /** + * Custom subtype of LocationHandler for PLATFORM_CLASS_PATH. + * Various options are supported for different components of the + * platform class path. + * Setting a value with setLocation overrides all existing option values. + * Setting any option overrides any value set with setLocation, and reverts + * to using default values for options that have not been set. + * Setting -bootclasspath or -Xbootclasspath overrides any existing + * value for -Xbootclasspath/p: and -Xbootclasspath/a:. + */ + private class BootClassPathLocationHandler extends LocationHandler { + private Collection searchPath; + final Map optionValues = new EnumMap(OptionName.class); + + /** + * rt.jar as found on the default bootclasspath. + * If the user specified a bootclasspath, null is used. + */ + private File defaultBootClassPathRtJar = null; + + /** + * Is bootclasspath the default? + */ + private boolean isDefaultBootClassPath; + + BootClassPathLocationHandler() { + super(StandardLocation.PLATFORM_CLASS_PATH, + OptionName.BOOTCLASSPATH, OptionName.XBOOTCLASSPATH, + OptionName.XBOOTCLASSPATH_PREPEND, + OptionName.XBOOTCLASSPATH_APPEND, + OptionName.ENDORSEDDIRS, OptionName.DJAVA_ENDORSED_DIRS, + OptionName.EXTDIRS, OptionName.DJAVA_EXT_DIRS); + } + + boolean isDefault() { + lazy(); + return isDefaultBootClassPath; + } + + boolean isDefaultRtJar(File file) { + lazy(); + return file.equals(defaultBootClassPathRtJar); + } + + @Override + boolean handleOption(OptionName option, String value) { + if (!options.contains(option)) + return false; + + option = canonicalize(option); + optionValues.put(option, value); + if (option == BOOTCLASSPATH) { + optionValues.remove(XBOOTCLASSPATH_PREPEND); + optionValues.remove(XBOOTCLASSPATH_APPEND); + } + searchPath = null; // reset to "uninitialized" + return true; + } + // where + // TODO: would be better if option aliasing was handled at a higher + // level + private OptionName canonicalize(OptionName option) { + switch (option) { + case XBOOTCLASSPATH: + return OptionName.BOOTCLASSPATH; + case DJAVA_ENDORSED_DIRS: + return OptionName.ENDORSEDDIRS; + case DJAVA_EXT_DIRS: + return OptionName.EXTDIRS; + default: + return option; + } + } + + @Override + Collection getLocation() { + lazy(); + return searchPath; + } + + @Override + void setLocation(Iterable files) { + if (files == null) { + searchPath = null; // reset to "uninitialized" + } else { + defaultBootClassPathRtJar = null; + isDefaultBootClassPath = false; + Path p = new Path().addFiles(files, false); + searchPath = Collections.unmodifiableCollection(p); + optionValues.clear(); + } + } + + Path computePath() { + defaultBootClassPathRtJar = null; + Path path = new Path(); + + String bootclasspathOpt = optionValues.get(BOOTCLASSPATH); + String endorseddirsOpt = optionValues.get(ENDORSEDDIRS); + String extdirsOpt = optionValues.get(EXTDIRS); + String xbootclasspathPrependOpt = optionValues.get(XBOOTCLASSPATH_PREPEND); + String xbootclasspathAppendOpt = optionValues.get(XBOOTCLASSPATH_APPEND); + + path.addFiles(xbootclasspathPrependOpt); + + if (endorseddirsOpt != null) + path.addDirectories(endorseddirsOpt); + else + path.addDirectories(System.getProperty("java.endorsed.dirs"), false); + + if (bootclasspathOpt != null) { + path.addFiles(bootclasspathOpt); + } else { + // Standard system classes for this compiler's release. + String files = System.getProperty("sun.boot.class.path"); + path.addFiles(files, false); + File rt_jar = new File("rt.jar"); + for (File file : getPathEntries(files)) { + if (new File(file.getName()).equals(rt_jar)) + defaultBootClassPathRtJar = file; + } + } + + path.addFiles(xbootclasspathAppendOpt); + + // Strictly speaking, standard extensions are not bootstrap + // classes, but we treat them identically, so we'll pretend + // that they are. + if (extdirsOpt != null) + path.addDirectories(extdirsOpt); + else + path.addDirectories(System.getProperty("java.ext.dirs"), false); + + isDefaultBootClassPath = + (xbootclasspathPrependOpt == null) && + (bootclasspathOpt == null) && + (xbootclasspathAppendOpt == null); + + return path; + } + + private void lazy() { + if (searchPath == null) + searchPath = Collections.unmodifiableCollection(computePath()); + } + } + + Map handlersForLocation; + Map handlersForOption; + + void initHandlers() { + handlersForLocation = new HashMap(); + handlersForOption = new EnumMap(OptionName.class); + + LocationHandler[] handlers = { + new BootClassPathLocationHandler(), + new ClassPathLocationHandler(), + new SimpleLocationHandler(StandardLocation.SOURCE_PATH, OptionName.SOURCEPATH), + new SimpleLocationHandler(StandardLocation.ANNOTATION_PROCESSOR_PATH, OptionName.PROCESSORPATH), + new OutputLocationHandler((StandardLocation.CLASS_OUTPUT), OptionName.D), + new OutputLocationHandler((StandardLocation.SOURCE_OUTPUT), OptionName.S) + }; + + for (LocationHandler h: handlers) { + handlersForLocation.put(h.location, h); + for (OptionName o: h.options) + handlersForOption.put(o, h); + } + } + + boolean handleOption(OptionName option, String value) { + LocationHandler h = handlersForOption.get(option); + return (h == null ? false : h.handleOption(option, value)); + } + + Collection getLocation(Location location) { + LocationHandler h = getHandler(location); + return (h == null ? null : h.getLocation()); + } + + File getOutputLocation(Location location) { + if (!location.isOutputLocation()) + throw new IllegalArgumentException(); + LocationHandler h = getHandler(location); + return ((OutputLocationHandler) h).outputDir; + } + + void setLocation(Location location, Iterable files) throws IOException { + LocationHandler h = getHandler(location); + if (h == null) { + if (location.isOutputLocation()) + h = new OutputLocationHandler(location); + else + h = new SimpleLocationHandler(location); + handlersForLocation.put(location, h); + } + h.setLocation(files); + } + + protected LocationHandler getHandler(Location location) { + location.getClass(); // null check + lazy(); + return handlersForLocation.get(location); + } + +// TOGO + protected void lazy() { + if (!inited) { + warn = lint.isEnabled(Lint.LintCategory.PATH); + + for (LocationHandler h: handlersForLocation.values()) { + h.update(options); + } + + inited = true; + } + } + + /** Is this the name of an archive file? */ + private boolean isArchive(File file) { + String n = file.getName().toLowerCase(); + return fsInfo.isFile(file) + && (n.endsWith(".jar") || n.endsWith(".zip")); + } + + /** + * Utility method for converting a search path string to an array + * of directory and JAR file URLs. + * + * Note that this method is called by apt and the DocletInvoker. + * + * @param path the search path string + * @return the resulting array of directory and JAR file URLs + */ + public static URL[] pathToURLs(String path) { + StringTokenizer st = new StringTokenizer(path, File.pathSeparator); + URL[] urls = new URL[st.countTokens()]; + int count = 0; + while (st.hasMoreTokens()) { + URL url = fileToURL(new File(st.nextToken())); + if (url != null) { + urls[count++] = url; + } + } + if (urls.length != count) { + URL[] tmp = new URL[count]; + System.arraycopy(urls, 0, tmp, 0, count); + urls = tmp; + } + return urls; + } + + /** + * Returns the directory or JAR file URL corresponding to the specified + * local file name. + * + * @param file the File object + * @return the resulting directory or JAR file URL, or null if unknown + */ + private static URL fileToURL(File file) { + String name; + try { + name = file.getCanonicalPath(); + } catch (IOException e) { + name = file.getAbsolutePath(); + } + name = name.replace(File.separatorChar, '/'); + if (!name.startsWith("/")) { + name = "/" + name; + } + // If the file does not exist, then assume that it's a directory + if (!file.isFile()) { + name = name + "/"; + } + try { + return new URL("file", "", name); + } catch (MalformedURLException e) { + throw new IllegalArgumentException(file.toString()); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java deleted file mode 100644 index 69a74cc79f5..00000000000 --- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java +++ /dev/null @@ -1,540 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.javac.file; - -import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.StringTokenizer; -import java.util.zip.ZipFile; -import javax.tools.JavaFileManager.Location; - -import com.sun.tools.javac.code.Lint; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Log; -import com.sun.tools.javac.util.Options; - -import static javax.tools.StandardLocation.*; -import static com.sun.tools.javac.main.OptionName.*; - -/** This class converts command line arguments, environment variables - * and system properties (in File.pathSeparator-separated String form) - * into a boot class path, user class path, and source path (in - * Collection form). - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Paths { - - /** The log to use for warning output */ - private Log log; - - /** Collection of command-line options */ - private Options options; - - /** Handler for -Xlint options */ - private Lint lint; - - /** Access to (possibly cached) file info */ - private FSInfo fsInfo; - - public Paths() { - pathsForLocation = new HashMap(16); - } - - public void update(Log log, Options options, Lint lint, FSInfo fsInfo) { - this.log = log; - this.options = options; - this.lint = lint; - this.fsInfo = fsInfo; - } - - /** Whether to warn about non-existent path elements */ - private boolean warn; - - private Map pathsForLocation; - - private boolean inited = false; // TODO? caching bad? - - /** - * rt.jar as found on the default bootclass path. If the user specified a - * bootclasspath, null is used. - */ - private File defaultBootClassPathRtJar = null; - - /** - * Is bootclasspath the default? - */ - private boolean isDefaultBootClassPath; - - Path getPathForLocation(Location location) { - Path path = pathsForLocation.get(location); - if (path == null) - setPathForLocation(location, null); - return pathsForLocation.get(location); - } - - void setPathForLocation(Location location, Iterable path) { - // TODO? if (inited) throw new IllegalStateException - // TODO: otherwise reset sourceSearchPath, classSearchPath as needed - Path p; - if (path == null) { - if (location == CLASS_PATH) - p = computeUserClassPath(); - else if (location == PLATFORM_CLASS_PATH) - p = computeBootClassPath(); // sets isDefaultBootClassPath - else if (location == ANNOTATION_PROCESSOR_PATH) - p = computeAnnotationProcessorPath(); - else if (location == SOURCE_PATH) - p = computeSourcePath(); - else - // no defaults for other paths - p = null; - } else { - if (location == PLATFORM_CLASS_PATH) { - defaultBootClassPathRtJar = null; - isDefaultBootClassPath = false; - } - p = new Path(); - for (File f: path) - p.addFile(f, warn); // TODO: is use of warn appropriate? - } - pathsForLocation.put(location, p); - } - - public boolean isDefaultBootClassPath() { - lazy(); - return isDefaultBootClassPath; - } - - protected void lazy() { - if (!inited) { - warn = lint.isEnabled(Lint.LintCategory.PATH); - - pathsForLocation.put(PLATFORM_CLASS_PATH, computeBootClassPath()); - pathsForLocation.put(CLASS_PATH, computeUserClassPath()); - pathsForLocation.put(SOURCE_PATH, computeSourcePath()); - - inited = true; - } - } - - public Collection bootClassPath() { - lazy(); - return Collections.unmodifiableCollection(getPathForLocation(PLATFORM_CLASS_PATH)); - } - public Collection userClassPath() { - lazy(); - return Collections.unmodifiableCollection(getPathForLocation(CLASS_PATH)); - } - public Collection sourcePath() { - lazy(); - Path p = getPathForLocation(SOURCE_PATH); - return p == null || p.size() == 0 - ? null - : Collections.unmodifiableCollection(p); - } - - boolean isDefaultBootClassPathRtJar(File file) { - return file.equals(defaultBootClassPathRtJar); - } - - /** - * Split a path into its elements. Empty path elements will be ignored. - * @param path The path to be split - * @return The elements of the path - */ - private static Iterable getPathEntries(String path) { - return getPathEntries(path, null); - } - - /** - * Split a path into its elements. If emptyPathDefault is not null, all - * empty elements in the path, including empty elements at either end of - * the path, will be replaced with the value of emptyPathDefault. - * @param path The path to be split - * @param emptyPathDefault The value to substitute for empty path elements, - * or null, to ignore empty path elements - * @return The elements of the path - */ - private static Iterable getPathEntries(String path, File emptyPathDefault) { - ListBuffer entries = new ListBuffer(); - int start = 0; - while (start <= path.length()) { - int sep = path.indexOf(File.pathSeparatorChar, start); - if (sep == -1) - sep = path.length(); - if (start < sep) - entries.add(new File(path.substring(start, sep))); - else if (emptyPathDefault != null) - entries.add(emptyPathDefault); - start = sep + 1; - } - return entries; - } - - private class Path extends LinkedHashSet { - private static final long serialVersionUID = 0; - - private boolean expandJarClassPaths = false; - private Set canonicalValues = new HashSet(); - - public Path expandJarClassPaths(boolean x) { - expandJarClassPaths = x; - return this; - } - - /** What to use when path element is the empty string */ - private File emptyPathDefault = null; - - public Path emptyPathDefault(File x) { - emptyPathDefault = x; - return this; - } - - public Path() { super(); } - - public Path addDirectories(String dirs, boolean warn) { - boolean prev = expandJarClassPaths; - expandJarClassPaths = true; - try { - if (dirs != null) - for (File dir : getPathEntries(dirs)) - addDirectory(dir, warn); - return this; - } finally { - expandJarClassPaths = prev; - } - } - - public Path addDirectories(String dirs) { - return addDirectories(dirs, warn); - } - - private void addDirectory(File dir, boolean warn) { - if (!dir.isDirectory()) { - if (warn) - log.warning(Lint.LintCategory.PATH, - "dir.path.element.not.found", dir); - return; - } - - File[] files = dir.listFiles(); - if (files == null) - return; - - for (File direntry : files) { - if (isArchive(direntry)) - addFile(direntry, warn); - } - } - - public Path addFiles(String files, boolean warn) { - if (files != null) { - for (File file : getPathEntries(files, emptyPathDefault)) - addFile(file, warn); - } - return this; - } - - public Path addFiles(String files) { - return addFiles(files, warn); - } - - public void addFile(File file, boolean warn) { - if (contains(file)) { - // discard duplicates - return; - } - - if (! fsInfo.exists(file)) { - /* No such file or directory exists */ - if (warn) { - log.warning(Lint.LintCategory.PATH, - "path.element.not.found", file); - } - super.add(file); - return; - } - - File canonFile = fsInfo.getCanonicalFile(file); - if (canonicalValues.contains(canonFile)) { - /* Discard duplicates and avoid infinite recursion */ - return; - } - - if (fsInfo.isFile(file)) { - /* File is an ordinary file. */ - if (!isArchive(file)) { - /* Not a recognized extension; open it to see if - it looks like a valid zip file. */ - try { - ZipFile z = new ZipFile(file); - z.close(); - if (warn) { - log.warning(Lint.LintCategory.PATH, - "unexpected.archive.file", file); - } - } catch (IOException e) { - // FIXME: include e.getLocalizedMessage in warning - if (warn) { - log.warning(Lint.LintCategory.PATH, - "invalid.archive.file", file); - } - return; - } - } - } - - /* Now what we have left is either a directory or a file name - conforming to archive naming convention */ - super.add(file); - canonicalValues.add(canonFile); - - if (expandJarClassPaths && fsInfo.isFile(file)) - addJarClassPath(file, warn); - } - - // Adds referenced classpath elements from a jar's Class-Path - // Manifest entry. In some future release, we may want to - // update this code to recognize URLs rather than simple - // filenames, but if we do, we should redo all path-related code. - private void addJarClassPath(File jarFile, boolean warn) { - try { - for (File f: fsInfo.getJarClassPath(jarFile)) { - addFile(f, warn); - } - } catch (IOException e) { - log.error("error.reading.file", jarFile, JavacFileManager.getMessage(e)); - } - } - } - - private Path computeBootClassPath() { - defaultBootClassPathRtJar = null; - Path path = new Path(); - - String bootclasspathOpt = options.get(BOOTCLASSPATH); - String endorseddirsOpt = options.get(ENDORSEDDIRS); - String extdirsOpt = options.get(EXTDIRS); - String xbootclasspathPrependOpt = options.get(XBOOTCLASSPATH_PREPEND); - String xbootclasspathAppendOpt = options.get(XBOOTCLASSPATH_APPEND); - - path.addFiles(xbootclasspathPrependOpt); - - if (endorseddirsOpt != null) - path.addDirectories(endorseddirsOpt); - else - path.addDirectories(System.getProperty("java.endorsed.dirs"), false); - - if (bootclasspathOpt != null) { - path.addFiles(bootclasspathOpt); - } else { - // Standard system classes for this compiler's release. - String files = System.getProperty("sun.boot.class.path"); - path.addFiles(files, false); - File rt_jar = new File("rt.jar"); - for (File file : getPathEntries(files)) { - if (new File(file.getName()).equals(rt_jar)) - defaultBootClassPathRtJar = file; - } - } - - path.addFiles(xbootclasspathAppendOpt); - - // Strictly speaking, standard extensions are not bootstrap - // classes, but we treat them identically, so we'll pretend - // that they are. - if (extdirsOpt != null) - path.addDirectories(extdirsOpt); - else - path.addDirectories(System.getProperty("java.ext.dirs"), false); - - isDefaultBootClassPath = - (xbootclasspathPrependOpt == null) && - (bootclasspathOpt == null) && - (xbootclasspathAppendOpt == null); - - return path; - } - - private Path computeUserClassPath() { - String cp = options.get(CLASSPATH); - - // CLASSPATH environment variable when run from `javac'. - if (cp == null) cp = System.getProperty("env.class.path"); - - // If invoked via a java VM (not the javac launcher), use the - // platform class path - if (cp == null && System.getProperty("application.home") == null) - cp = System.getProperty("java.class.path"); - - // Default to current working directory. - if (cp == null) cp = "."; - - return new Path() - .expandJarClassPaths(true) // Only search user jars for Class-Paths - .emptyPathDefault(new File(".")) // Empty path elt ==> current directory - .addFiles(cp); - } - - private Path computeSourcePath() { - String sourcePathArg = options.get(SOURCEPATH); - if (sourcePathArg == null) - return null; - - return new Path().addFiles(sourcePathArg); - } - - private Path computeAnnotationProcessorPath() { - String processorPathArg = options.get(PROCESSORPATH); - if (processorPathArg == null) - return null; - - return new Path().addFiles(processorPathArg); - } - - /** The actual effective locations searched for sources */ - private Path sourceSearchPath; - - public Collection sourceSearchPath() { - if (sourceSearchPath == null) { - lazy(); - Path sourcePath = getPathForLocation(SOURCE_PATH); - Path userClassPath = getPathForLocation(CLASS_PATH); - sourceSearchPath = sourcePath != null ? sourcePath : userClassPath; - } - return Collections.unmodifiableCollection(sourceSearchPath); - } - - /** The actual effective locations searched for classes */ - private Path classSearchPath; - - public Collection classSearchPath() { - if (classSearchPath == null) { - lazy(); - Path bootClassPath = getPathForLocation(PLATFORM_CLASS_PATH); - Path userClassPath = getPathForLocation(CLASS_PATH); - classSearchPath = new Path(); - classSearchPath.addAll(bootClassPath); - classSearchPath.addAll(userClassPath); - } - return Collections.unmodifiableCollection(classSearchPath); - } - - /** The actual effective locations for non-source, non-class files */ - private Path otherSearchPath; - - Collection otherSearchPath() { - if (otherSearchPath == null) { - lazy(); - Path userClassPath = getPathForLocation(CLASS_PATH); - Path sourcePath = getPathForLocation(SOURCE_PATH); - if (sourcePath == null) - otherSearchPath = userClassPath; - else { - otherSearchPath = new Path(); - otherSearchPath.addAll(userClassPath); - otherSearchPath.addAll(sourcePath); - } - } - return Collections.unmodifiableCollection(otherSearchPath); - } - - /** Is this the name of an archive file? */ - private boolean isArchive(File file) { - String n = file.getName().toLowerCase(); - return fsInfo.isFile(file) - && (n.endsWith(".jar") || n.endsWith(".zip")); - } - - /** - * Utility method for converting a search path string to an array - * of directory and JAR file URLs. - * - * Note that this method is called by apt and the DocletInvoker. - * - * @param path the search path string - * @return the resulting array of directory and JAR file URLs - */ - public static URL[] pathToURLs(String path) { - StringTokenizer st = new StringTokenizer(path, File.pathSeparator); - URL[] urls = new URL[st.countTokens()]; - int count = 0; - while (st.hasMoreTokens()) { - URL url = fileToURL(new File(st.nextToken())); - if (url != null) { - urls[count++] = url; - } - } - if (urls.length != count) { - URL[] tmp = new URL[count]; - System.arraycopy(urls, 0, tmp, 0, count); - urls = tmp; - } - return urls; - } - - /** - * Returns the directory or JAR file URL corresponding to the specified - * local file name. - * - * @param file the File object - * @return the resulting directory or JAR file URL, or null if unknown - */ - private static URL fileToURL(File file) { - String name; - try { - name = file.getCanonicalPath(); - } catch (IOException e) { - name = file.getAbsolutePath(); - } - name = name.replace(File.separatorChar, '/'); - if (!name.startsWith("/")) { - name = "/" + name; - } - // If the file does not exist, then assume that it's a directory - if (!file.isFile()) { - name = name + "/"; - } - try { - return new URL("file", "", name); - } catch (MalformedURLException e) { - throw new IllegalArgumentException(file.toString()); - } - } -} diff --git a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java index 5ed6334cb41..9a57d4a55d9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/nio/JavacPathFileManager.java @@ -169,7 +169,7 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan @Override public boolean isDefaultBootClassPath() { - return searchPaths.isDefaultBootClassPath(); + return locations.isDefaultBootClassPath(); } // @@ -227,13 +227,13 @@ public class JavacPathFileManager extends BaseFileManager implements PathFileMan if (locn instanceof StandardLocation) { switch ((StandardLocation) locn) { case CLASS_PATH: - files = searchPaths.userClassPath(); + files = locations.userClassPath(); break; case PLATFORM_CLASS_PATH: - files = searchPaths.bootClassPath(); + files = locations.bootClassPath(); break; case SOURCE_PATH: - files = searchPaths.sourcePath(); + files = locations.sourcePath(); break; case CLASS_OUTPUT: { String arg = options.get(D); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java index d393088c414..d3340fe32fd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/BaseFileManager.java @@ -52,7 +52,7 @@ import javax.tools.JavaFileObject.Kind; import com.sun.tools.javac.code.Lint; import com.sun.tools.javac.code.Source; import com.sun.tools.javac.file.FSInfo; -import com.sun.tools.javac.file.Paths; +import com.sun.tools.javac.file.Locations; import com.sun.tools.javac.main.JavacOption; import com.sun.tools.javac.main.OptionName; import com.sun.tools.javac.main.RecognizedOptions; @@ -67,7 +67,7 @@ public abstract class BaseFileManager { protected BaseFileManager(Charset charset) { this.charset = charset; byteBufferCache = new ByteBufferCache(); - searchPaths = createPaths(); + locations = createLocations(); } /** @@ -77,11 +77,11 @@ public abstract class BaseFileManager { log = Log.instance(context); options = Options.instance(context); classLoaderClass = options.get("procloader"); - searchPaths.update(log, options, Lint.instance(context), FSInfo.instance(context)); + locations.update(log, options, Lint.instance(context), FSInfo.instance(context)); } - protected Paths createPaths() { - return new Paths(); + protected Locations createLocations() { + return new Locations(); } /** @@ -98,7 +98,7 @@ public abstract class BaseFileManager { protected String classLoaderClass; - protected Paths searchPaths; + protected Locations locations; protected Source getSource() { String sourceName = options.get(OptionName.SOURCE); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java index 07402f90421..d9b2e69b9e4 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocletInvoker.java @@ -80,7 +80,7 @@ public class DocletInvoker { cpString = appendPath(System.getProperty("env.class.path"), cpString); cpString = appendPath(System.getProperty("java.class.path"), cpString); cpString = appendPath(docletPath, cpString); - URL[] urls = com.sun.tools.javac.file.Paths.pathToURLs(cpString); + URL[] urls = com.sun.tools.javac.file.Locations.pathToURLs(cpString); if (docletParentClassLoader == null) appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName)); else From b171ddacd069cb90efe26f34b66e2d37fa018612 Mon Sep 17 00:00:00 2001 From: Jim Holmlund Date: Tue, 25 Oct 2011 19:18:32 -0700 Subject: [PATCH 29/41] 7104905: Java SE build fails on call to CreateSymbols Reviewed-by: jjg --- .../src/share/classes/com/sun/tools/javac/file/Locations.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java index 8ef1eeef7f4..8ce5c4af18a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Locations.java @@ -327,7 +327,9 @@ public class Locations { */ protected LocationHandler(Location location, OptionName... options) { this.location = location; - this.options = EnumSet.copyOf(Arrays.asList(options)); + this.options = options.length == 0 ? + EnumSet.noneOf(OptionName.class): + EnumSet.copyOf(Arrays.asList(options)); } // TODO: TEMPORARY, while Options still used for command line options From 9181202876c7785e040f822615629b935149e9f7 Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Tue, 25 Oct 2011 20:15:41 -0700 Subject: [PATCH 30/41] 7099817: CMS: +FLSVerifyLists +FLSVerifyIndexTable asserts: odd slot non-empty, chunk not on free list Suitably weaken asserts that were in each case a tad too strong; fix up some loose uses of parameters in code related to size-indexed free list table. Reviewed-by: jmasa, brutisso, stefank --- .../compactibleFreeListSpace.cpp | 55 +++++++++++-------- .../compactibleFreeListSpace.hpp | 8 ++- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp index c989486cf76..34ef09fa449 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp @@ -62,7 +62,7 @@ void CompactibleFreeListSpace::set_cms_values() { MinChunkSize = numQuanta(sizeof(FreeChunk), MinObjAlignmentInBytes) * MinObjAlignment; assert(IndexSetStart == 0 && IndexSetStride == 0, "already set"); - IndexSetStart = MinObjAlignment; + IndexSetStart = (int) MinChunkSize; IndexSetStride = MinObjAlignment; } @@ -138,7 +138,7 @@ CompactibleFreeListSpace::CompactibleFreeListSpace(BlockOffsetSharedArray* bs, } else { _fitStrategy = FreeBlockStrategyNone; } - checkFreeListConsistency(); + check_free_list_consistency(); // Initialize locks for parallel case. @@ -1358,17 +1358,29 @@ FreeChunk* CompactibleFreeListSpace::getChunkFromGreater(size_t numWords) { ShouldNotReachHere(); } -bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) - const { +bool CompactibleFreeListSpace::verifyChunkInIndexedFreeLists(FreeChunk* fc) const { assert(fc->size() < IndexSetSize, "Size of chunk is too large"); return _indexedFreeList[fc->size()].verifyChunkInFreeLists(fc); } +bool CompactibleFreeListSpace::verify_chunk_is_linear_alloc_block(FreeChunk* fc) const { + assert((_smallLinearAllocBlock._ptr != (HeapWord*)fc) || + (_smallLinearAllocBlock._word_size == fc->size()), + "Linear allocation block shows incorrect size"); + return ((_smallLinearAllocBlock._ptr == (HeapWord*)fc) && + (_smallLinearAllocBlock._word_size == fc->size())); +} + +// Check if the purported free chunk is present either as a linear +// allocation block, the size-indexed table of (smaller) free blocks, +// or the larger free blocks kept in the binary tree dictionary. bool CompactibleFreeListSpace::verifyChunkInFreeLists(FreeChunk* fc) const { - if (fc->size() >= IndexSetSize) { - return dictionary()->verifyChunkInFreeLists(fc); - } else { + if (verify_chunk_is_linear_alloc_block(fc)) { + return true; + } else if (fc->size() < IndexSetSize) { return verifyChunkInIndexedFreeLists(fc); + } else { + return dictionary()->verifyChunkInFreeLists(fc); } } @@ -2495,7 +2507,8 @@ void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { FreeChunk* tail = _indexedFreeList[size].tail(); size_t num = _indexedFreeList[size].count(); size_t n = 0; - guarantee((size % 2 == 0) || fc == NULL, "Odd slots should be empty"); + guarantee(((size >= MinChunkSize) && (size % IndexSetStride == 0)) || fc == NULL, + "Slot should have been empty"); for (; fc != NULL; fc = fc->next(), n++) { guarantee(fc->size() == size, "Size inconsistency"); guarantee(fc->isFree(), "!free?"); @@ -2506,14 +2519,14 @@ void CompactibleFreeListSpace::verifyIndexedFreeList(size_t size) const { } #ifndef PRODUCT -void CompactibleFreeListSpace::checkFreeListConsistency() const { +void CompactibleFreeListSpace::check_free_list_consistency() const { assert(_dictionary->minSize() <= IndexSetSize, "Some sizes can't be allocated without recourse to" " linear allocation buffers"); assert(MIN_TREE_CHUNK_SIZE*HeapWordSize == sizeof(TreeChunk), "else MIN_TREE_CHUNK_SIZE is wrong"); - assert((IndexSetStride == 2 && IndexSetStart == 2) || - (IndexSetStride == 1 && IndexSetStart == 1), "just checking"); + assert((IndexSetStride == 2 && IndexSetStart == 4) || // 32-bit + (IndexSetStride == 1 && IndexSetStart == 3), "just checking"); // 64-bit assert((IndexSetStride != 2) || (MinChunkSize % 2 == 0), "Some for-loops may be incorrectly initialized"); assert((IndexSetStride != 2) || (IndexSetSize % 2 == 1), @@ -2688,33 +2701,27 @@ void CFLS_LAB::compute_desired_plab_size() { } } +// If this is changed in the future to allow parallel +// access, one would need to take the FL locks and, +// depending on how it is used, stagger access from +// parallel threads to reduce contention. void CFLS_LAB::retire(int tid) { // We run this single threaded with the world stopped; // so no need for locks and such. -#define CFLS_LAB_PARALLEL_ACCESS 0 NOT_PRODUCT(Thread* t = Thread::current();) assert(Thread::current()->is_VM_thread(), "Error"); - assert(CompactibleFreeListSpace::IndexSetStart == CompactibleFreeListSpace::IndexSetStride, - "Will access to uninitialized slot below"); -#if CFLS_LAB_PARALLEL_ACCESS - for (size_t i = CompactibleFreeListSpace::IndexSetSize - 1; - i > 0; - i -= CompactibleFreeListSpace::IndexSetStride) { -#else // CFLS_LAB_PARALLEL_ACCESS for (size_t i = CompactibleFreeListSpace::IndexSetStart; i < CompactibleFreeListSpace::IndexSetSize; i += CompactibleFreeListSpace::IndexSetStride) { -#endif // !CFLS_LAB_PARALLEL_ACCESS assert(_num_blocks[i] >= (size_t)_indexedFreeList[i].count(), "Can't retire more than what we obtained"); if (_num_blocks[i] > 0) { size_t num_retire = _indexedFreeList[i].count(); assert(_num_blocks[i] > num_retire, "Should have used at least one"); { -#if CFLS_LAB_PARALLEL_ACCESS - MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], - Mutex::_no_safepoint_check_flag); -#endif // CFLS_LAB_PARALLEL_ACCESS + // MutexLockerEx x(_cfls->_indexedFreeListParLocks[i], + // Mutex::_no_safepoint_check_flag); + // Update globals stats for num_blocks used _global_num_blocks[i] += (_num_blocks[i] - num_retire); _global_num_workers[i]++; diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp index 3f3643262df..8adfd667011 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp @@ -502,10 +502,14 @@ class CompactibleFreeListSpace: public CompactibleSpace { void verifyFreeLists() const PRODUCT_RETURN; void verifyIndexedFreeLists() const; void verifyIndexedFreeList(size_t size) const; - // verify that the given chunk is in the free lists. + // Verify that the given chunk is in the free lists: + // i.e. either the binary tree dictionary, the indexed free lists + // or the linear allocation block. bool verifyChunkInFreeLists(FreeChunk* fc) const; + // Verify that the given chunk is the linear allocation block + bool verify_chunk_is_linear_alloc_block(FreeChunk* fc) const; // Do some basic checks on the the free lists. - void checkFreeListConsistency() const PRODUCT_RETURN; + void check_free_list_consistency() const PRODUCT_RETURN; // Printing support void dump_at_safepoint_with_locks(CMSCollector* c, outputStream* st); From 868cfdb5f406eb840ca744ab3232f781ae579f6a Mon Sep 17 00:00:00 2001 From: Bengt Rutisson Date: Wed, 26 Oct 2011 08:44:53 +0200 Subject: [PATCH 31/41] 7102191: G1: assert(_min_desired_young_length <= initial_region_num) failed: Initial young gen size too small Initial_region_num actually not needed. Reviewed-by: tonyp, johnc --- .../share/vm/gc_implementation/g1/g1CollectorPolicy.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index b7fd0c190f7..68c70510fc1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -498,7 +498,6 @@ void G1CollectorPolicy::init() { initialize_gc_policy_counters(); G1YoungGenSizer sizer; - size_t initial_region_num = sizer.initial_young_region_num(); _min_desired_young_length = sizer.min_young_region_num(); _max_desired_young_length = sizer.max_young_region_num(); @@ -512,17 +511,14 @@ void G1CollectorPolicy::init() { } } - // GenCollectorPolicy guarantees that min <= initial <= max. - // Asserting here just to state that we rely on this property. assert(_min_desired_young_length <= _max_desired_young_length, "Invalid min/max young gen size values"); - assert(initial_region_num <= _max_desired_young_length, "Initial young gen size too large"); - assert(_min_desired_young_length <= initial_region_num, "Initial young gen size too small"); set_adaptive_young_list_length(_min_desired_young_length < _max_desired_young_length); if (adaptive_young_list_length()) { _young_list_fixed_length = 0; } else { - _young_list_fixed_length = initial_region_num; + assert(_min_desired_young_length == _max_desired_young_length, "Min and max young size differ"); + _young_list_fixed_length = _min_desired_young_length; } _free_regions_at_end_of_collection = _g1->free_regions(); update_young_list_target_length(); From b58a00d8055438246844e7f645db153090bd6953 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:24 -0700 Subject: [PATCH 32/41] Added tag jdk8-b11 for changeset 541e4b0cf4f9 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 46967b5b185..bb8cba99e8b 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -132,3 +132,4 @@ b910aac18c772b823b1f7da03e2c6528725cc6de jdk8-b05 fb1bc13260d76447e269e843859eb593fe2a8ab2 jdk8-b08 8adb70647b5af5273dfe6a540f07be667cd50216 jdk8-b09 a6c4c248e8fa350c35014fa94bab5ac1a1ac3299 jdk8-b10 +1defbc57940a56f0aa41e9dee87b71e8c8b71103 jdk8-b11 From 467fe2be8011dac36e2655e9223f03d6f68d4feb Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:26 -0700 Subject: [PATCH 33/41] Added tag jdk8-b11 for changeset 30a16214b365 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 13f844c008b..bd2e17921d4 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -132,3 +132,4 @@ cc1b599b986a37cb57de4584c5e58169766ca535 jdk8-b05 0d52b1c87aa8fdea7fdc9c4126ea58f95ca6b351 jdk8-b08 a891732c1a83082177ff7a4cf1506068d9cc0a47 jdk8-b09 cda87f7fefcee3b89742a57ce5ad9b03a54c210d jdk8-b10 +0199e4fef5cc2bd234c65b93220459ef7a3bb3b1 jdk8-b11 From d471bfae9b878d81038dfa15be4510a673c5f41b Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:31 -0700 Subject: [PATCH 34/41] Added tag jdk8-b11 for changeset 719fbe1902a0 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 8b3cab36b40..fd0ca9ba4ce 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -193,3 +193,4 @@ da883b9e6d3788057f9577e72712998ed82c9b7e hs23-b01 e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02 d815de2e85e511b7deab2a83cf80c0224d011da9 jdk8-b10 4d3850d9d326ac3a9bee2d867727e954322d014e hs23-b03 +4538caeef7b6cbd4302bebced805d65e68ccf301 jdk8-b11 From 96ca36886a7233c816802faa61f5da8465836549 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:37 -0700 Subject: [PATCH 35/41] Added tag jdk8-b11 for changeset 1c9f26d85678 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 7c209cbed58..e0ff678bbaa 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -132,3 +132,4 @@ c114306576dcc1cb871a48058b41bf7d87ce882a jdk8-b07 de4794dd69c48b08029d158a972993ff9d5627df jdk8-b08 93554324c014282571aeeb48552ad00d3fedb089 jdk8-b09 d21a4d5141c04bc9e88f2c0253121d449b66d667 jdk8-b10 +d1b7a4f6dd2065fdeafbcdfd9dcc0072da8c6881 jdk8-b11 From e0e7783359a9bb73e90246d6f5c48a83717c7477 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:38 -0700 Subject: [PATCH 36/41] Added tag jdk8-b11 for changeset df5d402bd8f5 --- jaxws/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxws/.hgtags b/jaxws/.hgtags index de87c6c7cc9..3eec004d4a8 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -132,3 +132,4 @@ acffff22a9465005e8eb206224fae9f2ea4fd469 jdk8-b06 1c9d4f59acf8f71477473c170239b43b2c9dee24 jdk8-b08 70172e57cf29efe271b068987eefb601c2a77780 jdk8-b09 8e7fdc8e3c758644ca6d0fd70bb255e9d2e64cda jdk8-b10 +a12ab897a249feb7859a6e6cd84b49411f4c06ac jdk8-b11 From 83c35d376a114c85fc6646032397a858a3d43626 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:42 -0700 Subject: [PATCH 37/41] Added tag jdk8-b11 for changeset 7116fbba4c13 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index ebca091558f..515e0f72fbc 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -132,3 +132,4 @@ bdb870cc269ef8b221d17a217be89092400b59d2 jdk8-b06 1c023bcd0c5a01ac07bc7eea728aafbb0d8991e9 jdk8-b08 f1ec21b8142168ff40f3278d2f6b5fe4bd5f3b26 jdk8-b09 4788745572ef2bde34924ef34e7e4d55ba07e979 jdk8-b10 +7ab0d613cd1a271a9763ffb894dc1f0a5b95a7e4 jdk8-b11 From 31ff82c1c8b27d1141f566a0da15dfe8fb0e1eee Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 27 Oct 2011 13:54:50 -0700 Subject: [PATCH 38/41] Added tag jdk8-b11 for changeset b44e4293ec86 --- langtools/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/langtools/.hgtags b/langtools/.hgtags index 9c596017a4a..06958e1b0c5 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -132,3 +132,4 @@ d2422276f9dabc848b7a079025719826d2f9a30f jdk8-b06 e8acc2d6c32f0c8321e642e1a86672a2e196a056 jdk8-b08 b7a7e47c8d3daf7822abf7c37e5179ccbbf53008 jdk8-b09 f6c783e18bdf4d46a0ab273868afebbf32600ff7 jdk8-b10 +4bf01f1c4e3464f378959d10f3983a0469181d94 jdk8-b11 From d61593bed3ebf2249b54ed6324473b2634a5d5f1 Mon Sep 17 00:00:00 2001 From: John Coomes Date: Fri, 28 Oct 2011 15:41:29 -0700 Subject: [PATCH 39/41] Added tag hs23-b04 for changeset 721977078d6e --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index fd0ca9ba4ce..46612cd8947 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -194,3 +194,4 @@ e4f412d2b75d2c797acff965aa2c420e3d358f09 hs23-b02 d815de2e85e511b7deab2a83cf80c0224d011da9 jdk8-b10 4d3850d9d326ac3a9bee2d867727e954322d014e hs23-b03 4538caeef7b6cbd4302bebced805d65e68ccf301 jdk8-b11 +6534482ff68ad79066dfe15dfb6d8905f09681bd hs23-b04 From f5a4ed3bccf59fae7861a100ffd9664315398619 Mon Sep 17 00:00:00 2001 From: "J. Duke" Date: Wed, 5 Jul 2017 17:53:51 +0200 Subject: [PATCH 40/41] Added tag jdk8-b11 for changeset cc1f5ce8e504 --- .hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags b/.hgtags index 8b7157fc99a..07ac4027b55 100644 --- a/.hgtags +++ b/.hgtags @@ -132,3 +132,4 @@ bc5710332b294676661103bb20d47d2ea3ba8def jdk8-b07 24ee504f80412770c6874836cd9e55b536427b1d jdk8-b08 fbf3cabc9e3bb1fcf710941d777cb0400505fbe6 jdk8-b09 f651ce87127980c58e3599daba964eba2f3b4026 jdk8-b10 +cc1f5ce8e504d350e0b0c28c5f84333f8d540132 jdk8-b11 From 7982aae1c43d44e6d9bafc3f853b54a35d9531ae Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 3 Nov 2011 10:32:29 -0700 Subject: [PATCH 41/41] Added tag jdk8-b12 for changeset 7e570cc378fb --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 515e0f72fbc..e1e7ba132b7 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -133,3 +133,4 @@ bdb870cc269ef8b221d17a217be89092400b59d2 jdk8-b06 f1ec21b8142168ff40f3278d2f6b5fe4bd5f3b26 jdk8-b09 4788745572ef2bde34924ef34e7e4d55ba07e979 jdk8-b10 7ab0d613cd1a271a9763ffb894dc1f0a5b95a7e4 jdk8-b11 +09fd2067f715e4505c44b01c301258a4e8f8964e jdk8-b12