aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDana Dahlstrom <dahlstrom@google.com>2020-01-30 12:00:00 -0800
committerDana Dahlstrom <dahlstrom@google.com>2020-02-10 12:00:00 -0800
commit48adcc45b3935045b1ff2013ecfd05e6f3bdb1cc (patch)
tree7e47ce0d2a402a9e765541e514aa969ef8325928
parente5752ae568d3c43497ae4f33d731fadf4ef165d4 (diff)
parent5b42bd7c94ffa67028549cac0264d79e24b2febd (diff)
downloadjdk8u_jdk-48adcc45b3935045b1ff2013ecfd05e6f3bdb1cc.tar.gz
Merge tag jb8u232-b1638.6
Change-Id: I5b42bd7c94ffa67028549cac0264d79e24b2febd
-rw-r--r--.hgtags21
-rw-r--r--THIRD_PARTY_README278
-rw-r--r--build.txt2
-rw-r--r--make/CopyIntoClasses.gmk4
-rw-r--r--make/Images.gmk4
-rw-r--r--make/Tools.gmk3
-rw-r--r--make/data/lsrdata/language-subtag-registry.txt (renamed from test/java/util/Locale/tools/language-subtag-registry.txt)1230
-rw-r--r--make/data/tzdata/VERSION2
-rw-r--r--make/data/tzdata/africa265
-rw-r--r--make/data/tzdata/antarctica14
-rw-r--r--make/data/tzdata/asia670
-rw-r--r--make/data/tzdata/australasia435
-rw-r--r--make/data/tzdata/backward3
-rw-r--r--make/data/tzdata/etcetera1
-rw-r--r--make/data/tzdata/europe300
-rw-r--r--make/data/tzdata/factory2
-rw-r--r--make/data/tzdata/iso3166.tab8
-rw-r--r--make/data/tzdata/leapseconds42
-rw-r--r--make/data/tzdata/northamerica329
-rw-r--r--make/data/tzdata/pacificnew2
-rw-r--r--make/data/tzdata/southamerica77
-rw-r--r--make/data/tzdata/systemv2
-rw-r--r--make/data/tzdata/zone.tab8
-rw-r--r--make/gensrc/GensrcLocaleDataMetaInfo.gmk12
-rw-r--r--make/lib/Awt2dLibraries.gmk10
-rw-r--r--make/lib/CoreLibraries.gmk16
-rw-r--r--make/lib/NetworkingLibraries.gmk2
-rw-r--r--make/mapfiles/launchers/mapfile-x865
-rw-r--r--make/mapfiles/libj2pkcs11/mapfile-vers2
-rw-r--r--make/mapfiles/libsunec/mapfile-vers3
-rw-r--r--make/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java282
-rw-r--r--src/macosx/native/java/util/SCDynamicStoreConfig.m5
-rw-r--r--src/macosx/native/sun/awt/JavaComponentAccessibility.m10
-rw-r--r--src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m12
-rw-r--r--src/share/classes/com/sun/crypto/provider/AESCrypt.java24
-rw-r--r--src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java37
-rw-r--r--src/share/classes/com/sun/crypto/provider/CipherFeedback.java15
-rw-r--r--src/share/classes/com/sun/crypto/provider/CounterMode.java7
-rw-r--r--src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java16
-rw-r--r--src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java38
-rw-r--r--src/share/classes/com/sun/crypto/provider/OutputFeedback.java11
-rw-r--r--src/share/classes/com/sun/crypto/provider/PBES1Core.java39
-rw-r--r--src/share/classes/com/sun/crypto/provider/PCBC.java17
-rw-r--r--src/share/classes/com/sun/crypto/provider/Preconditions.java345
-rw-r--r--src/share/classes/com/sun/crypto/provider/RangeUtil.java53
-rw-r--r--src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java12
-rw-r--r--src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java79
-rw-r--r--src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java33
-rw-r--r--src/share/classes/com/sun/jndi/ldap/BerDecoder.java12
-rw-r--r--src/share/classes/com/sun/jndi/ldap/Connection.java67
-rw-r--r--src/share/classes/com/sun/jndi/ldap/LdapRequest.java88
-rw-r--r--src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java12
-rw-r--r--src/share/classes/java/awt/Font.java6
-rw-r--r--src/share/classes/java/awt/Toolkit.java4
-rw-r--r--src/share/classes/java/io/FilePermission.java37
-rw-r--r--src/share/classes/java/io/LineNumberReader.java7
-rw-r--r--src/share/classes/java/io/ObjectStreamClass.java16
-rw-r--r--src/share/classes/java/lang/ClassLoader.java7
-rw-r--r--src/share/classes/java/lang/Throwable.java87
-rw-r--r--src/share/classes/java/lang/invoke/MethodHandleProxies.java56
-rw-r--r--src/share/classes/java/net/NetPermission.java11
-rw-r--r--src/share/classes/java/net/ServerSocket.java15
-rw-r--r--src/share/classes/java/net/Socket.java18
-rw-r--r--src/share/classes/java/net/SocksSocketImpl.java10
-rw-r--r--src/share/classes/java/net/URL.java32
-rw-r--r--src/share/classes/java/net/URLStreamHandler.java7
-rw-r--r--src/share/classes/java/security/AccessController.java8
-rw-r--r--src/share/classes/java/util/Collections.java58
-rw-r--r--src/share/classes/java/util/CurrencyData.properties24
-rw-r--r--src/share/classes/java/util/concurrent/CompletableFuture.java17
-rw-r--r--src/share/classes/java/util/regex/Pattern.java14
-rw-r--r--src/share/classes/java/util/stream/AbstractTask.java29
-rw-r--r--src/share/classes/java/util/stream/DoublePipeline.java30
-rw-r--r--src/share/classes/java/util/stream/ForEachOps.java5
-rw-r--r--src/share/classes/java/util/stream/IntPipeline.java30
-rw-r--r--src/share/classes/java/util/stream/LongPipeline.java30
-rw-r--r--src/share/classes/java/util/stream/ReferencePipeline.java99
-rw-r--r--src/share/classes/java/util/stream/SortedOps.java42
-rw-r--r--src/share/classes/java/util/stream/StreamSpliterators.java21
-rw-r--r--src/share/classes/javax/imageio/ImageIO.java46
-rw-r--r--src/share/classes/javax/net/ssl/SSLSessionContext.java50
-rw-r--r--src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java10
-rw-r--r--src/share/classes/javax/security/auth/kerberos/KerberosTicket.java20
-rw-r--r--src/share/classes/javax/swing/text/html/ImageView.java76
-rw-r--r--src/share/classes/sun/font/CMap.java22
-rw-r--r--src/share/classes/sun/font/FileFont.java2
-rw-r--r--src/share/classes/sun/font/Font2D.java8
-rw-r--r--src/share/classes/sun/font/FontFamily.java4
-rw-r--r--src/share/classes/sun/font/FontScaler.java6
-rw-r--r--src/share/classes/sun/font/FreetypeFontScaler.java24
-rw-r--r--src/share/classes/sun/font/GlyphList.java14
-rw-r--r--src/share/classes/sun/font/SunFontManager.java56
-rw-r--r--src/share/classes/sun/java2d/SunGraphics2D.java6
-rw-r--r--src/share/classes/sun/java2d/marlin/DDasher.java49
-rw-r--r--src/share/classes/sun/java2d/marlin/DHelpers.java2
-rw-r--r--src/share/classes/sun/java2d/marlin/DStroker.java15
-rw-r--r--src/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java37
-rw-r--r--src/share/classes/sun/java2d/marlin/Dasher.java49
-rw-r--r--src/share/classes/sun/java2d/marlin/Helpers.java2
-rw-r--r--src/share/classes/sun/java2d/marlin/Stroker.java15
-rw-r--r--src/share/classes/sun/java2d/marlin/TransformingPathConsumer2D.java37
-rw-r--r--src/share/classes/sun/java2d/marlin/Version.java2
-rw-r--r--src/share/classes/sun/misc/Launcher.java3
-rw-r--r--src/share/classes/sun/net/util/IPAddressUtil.java181
-rw-r--r--src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java21
-rw-r--r--src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java12
-rw-r--r--src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java7
-rw-r--r--src/share/classes/sun/net/www/protocol/jar/Handler.java15
-rw-r--r--src/share/classes/sun/print/services/javax.print.PrintServiceLookup2
-rw-r--r--src/share/classes/sun/print/services/javax.print.StreamPrintServiceFactory (renamed from src/solaris/classes/sun/print/services/javax.print.StreamPrintServiceFactory)0
-rw-r--r--src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java20
-rw-r--r--src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java27
-rw-r--r--src/share/classes/sun/rmi/transport/DGCImpl_Skel.java17
-rw-r--r--src/share/classes/sun/rmi/transport/DGCImpl_Stub.java50
-rw-r--r--src/share/classes/sun/rmi/transport/StreamRemoteCall.java22
-rw-r--r--src/share/classes/sun/security/ec/ECDHKeyAgreement.java162
-rw-r--r--src/share/classes/sun/security/ec/ECDSAOperations.java202
-rw-r--r--src/share/classes/sun/security/ec/ECDSASignature.java128
-rw-r--r--src/share/classes/sun/security/ec/ECKeyPairGenerator.java168
-rw-r--r--src/share/classes/sun/security/ec/ECOperations.java499
-rw-r--r--src/share/classes/sun/security/ec/ECPrivateKeyImpl.java70
-rw-r--r--src/share/classes/sun/security/ec/point/AffinePoint.java76
-rw-r--r--src/share/classes/sun/security/ec/point/ImmutablePoint.java32
-rw-r--r--src/share/classes/sun/security/ec/point/MutablePoint.java37
-rw-r--r--src/share/classes/sun/security/ec/point/Point.java45
-rw-r--r--src/share/classes/sun/security/ec/point/ProjectivePoint.java160
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5Context.java8
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java12
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java4
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java4
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java31
-rw-r--r--src/share/classes/sun/security/jgss/krb5/Krb5Util.java29
-rw-r--r--src/share/classes/sun/security/krb5/Credentials.java36
-rw-r--r--src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java15
-rw-r--r--src/share/classes/sun/security/krb5/Realm.java1
-rw-r--r--src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java32
-rw-r--r--src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java16
-rw-r--r--src/share/classes/sun/security/krb5/internal/ccache/Credentials.java20
-rw-r--r--src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java65
-rw-r--r--src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java105
-rw-r--r--src/share/classes/sun/security/pkcs11/P11Cipher.java124
-rw-r--r--src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java16
-rw-r--r--src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java16
-rw-r--r--src/share/classes/sun/security/pkcs11/P11Digest.java10
-rw-r--r--src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java14
-rw-r--r--src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java12
-rw-r--r--src/share/classes/sun/security/pkcs11/P11Key.java387
-rw-r--r--src/share/classes/sun/security/pkcs11/P11KeyAgreement.java15
-rw-r--r--src/share/classes/sun/security/pkcs11/P11KeyStore.java20
-rw-r--r--src/share/classes/sun/security/pkcs11/P11Mac.java117
-rw-r--r--src/share/classes/sun/security/pkcs11/P11RSACipher.java147
-rw-r--r--src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java23
-rw-r--r--src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java10
-rw-r--r--src/share/classes/sun/security/pkcs11/P11Signature.java101
-rw-r--r--src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java10
-rw-r--r--src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java7
-rw-r--r--src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java18
-rw-r--r--src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java42
-rw-r--r--src/share/classes/sun/security/provider/DigestBase.java24
-rw-r--r--src/share/classes/sun/security/provider/SHA.java20
-rw-r--r--src/share/classes/sun/security/provider/SHA2.java20
-rw-r--r--src/share/classes/sun/security/provider/SHA5.java19
-rw-r--r--src/share/classes/sun/security/ssl/EllipticCurvesExtension.java19
-rw-r--r--src/share/classes/sun/security/ssl/SSLContextImpl.java48
-rw-r--r--src/share/classes/sun/security/ssl/SSLSessionContextImpl.java25
-rw-r--r--src/share/classes/sun/security/ssl/SessionId.java7
-rw-r--r--src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java144
-rw-r--r--src/share/classes/sun/security/ssl/TrustStoreManager.java395
-rw-r--r--src/share/classes/sun/security/ssl/X509TrustManagerImpl.java127
-rw-r--r--src/share/classes/sun/security/util/ArrayUtil.java50
-rw-r--r--src/share/classes/sun/security/util/DerIndefLenConverter.java60
-rw-r--r--src/share/classes/sun/security/util/ECUtil.java2
-rw-r--r--src/share/classes/sun/security/util/HostnameChecker.java11
-rw-r--r--src/share/classes/sun/security/util/SecurityConstants.java6
-rw-r--r--src/share/classes/sun/security/util/SecurityProperties.java82
-rw-r--r--src/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java34
-rw-r--r--src/share/classes/sun/security/util/math/IntegerFieldModuloP.java115
-rw-r--r--src/share/classes/sun/security/util/math/IntegerModuloP.java205
-rw-r--r--src/share/classes/sun/security/util/math/MutableIntegerModuloP.java162
-rw-r--r--src/share/classes/sun/security/util/math/SmallValue.java38
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/FieldGen.jsh851
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java767
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java209
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java215
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java251
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java339
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java431
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java417
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/P256OrderField.java673
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/P384OrderField.java881
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/P521OrderField.java1377
-rw-r--r--src/share/classes/sun/security/util/math/intpoly/header.txt28
-rw-r--r--src/share/classes/sun/security/validator/TrustStoreUtil.java (renamed from src/share/classes/sun/security/validator/KeyStores.java)77
-rw-r--r--src/share/classes/sun/security/validator/Validator.java4
-rw-r--r--src/share/classes/sun/swing/SwingUtilities2.java24
-rw-r--r--src/share/classes/sun/text/resources/ar/FormatData_ar.java2
-rw-r--r--src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java2
-rw-r--r--src/share/classes/sun/text/resources/es/FormatData_es_PE.java17
-rw-r--r--src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java2
-rw-r--r--src/share/classes/sun/text/resources/ko/FormatData_ko.java1
-rw-r--r--src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java2
-rw-r--r--src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java2
-rw-r--r--src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java2
-rw-r--r--src/share/classes/sun/text/resources/th/FormatData_th.java2
-rw-r--r--src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java2
-rw-r--r--src/share/classes/sun/text/resources/zh/FormatData_zh.java1
-rw-r--r--src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java2
-rw-r--r--src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java2
-rw-r--r--src/share/classes/sun/util/calendar/ZoneInfoFile.java14
-rw-r--r--src/share/classes/sun/util/locale/LocaleEquivalentMaps.java214
-rw-r--r--src/share/classes/sun/util/resources/CurrencyNames.properties12
-rw-r--r--src/share/classes/sun/util/resources/TimeZoneNames.java7
-rw-r--r--src/share/classes/sun/util/resources/de/TimeZoneNames_de.java4
-rw-r--r--src/share/classes/sun/util/resources/es/CurrencyNames_es_VE.properties4
-rw-r--r--src/share/classes/sun/util/resources/es/TimeZoneNames_es.java4
-rw-r--r--src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java4
-rw-r--r--src/share/classes/sun/util/resources/it/TimeZoneNames_it.java4
-rw-r--r--src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java4
-rw-r--r--src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java4
-rw-r--r--src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java4
-rw-r--r--src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java4
-rw-r--r--src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java4
-rw-r--r--src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java4
-rw-r--r--src/share/lib/security/cacertsbin112860 -> 98310 bytes
-rw-r--r--src/share/lib/security/java.policy2
-rw-r--r--src/share/lib/security/java.security-aix29
-rw-r--r--src/share/lib/security/java.security-linux29
-rw-r--r--src/share/lib/security/java.security-macosx29
-rw-r--r--src/share/lib/security/java.security-solaris29
-rw-r--r--src/share/lib/security/java.security-windows29
-rw-r--r--src/share/native/common/jni_util.c55
-rw-r--r--src/share/native/sun/awt/giflib/dgif_lib.c122
-rw-r--r--src/share/native/sun/awt/giflib/gif_hash.h5
-rw-r--r--src/share/native/sun/awt/giflib/gif_lib.h14
-rw-r--r--src/share/native/sun/awt/giflib/gif_lib_private.h9
-rw-r--r--src/share/native/sun/awt/giflib/gifalloc.c18
-rw-r--r--src/share/native/sun/awt/giflib/openbsd-reallocarray.c6
-rw-r--r--src/share/native/sun/awt/libpng/CHANGES48
-rw-r--r--src/share/native/sun/awt/libpng/LICENSE177
-rw-r--r--src/share/native/sun/awt/libpng/README111
-rw-r--r--src/share/native/sun/awt/libpng/png.c53
-rw-r--r--src/share/native/sun/awt/libpng/png.h313
-rw-r--r--src/share/native/sun/awt/libpng/pngconf.h18
-rw-r--r--src/share/native/sun/awt/libpng/pngdebug.h6
-rw-r--r--src/share/native/sun/awt/libpng/pngerror.c12
-rw-r--r--src/share/native/sun/awt/libpng/pngget.c6
-rw-r--r--src/share/native/sun/awt/libpng/pnginfo.h6
-rw-r--r--src/share/native/sun/awt/libpng/pnglibconf.h15
-rw-r--r--src/share/native/sun/awt/libpng/pngmem.c6
-rw-r--r--src/share/native/sun/awt/libpng/pngpread.c16
-rw-r--r--src/share/native/sun/awt/libpng/pngpriv.h39
-rw-r--r--src/share/native/sun/awt/libpng/pngread.c38
-rw-r--r--src/share/native/sun/awt/libpng/pngrio.c6
-rw-r--r--src/share/native/sun/awt/libpng/pngrtran.c116
-rw-r--r--src/share/native/sun/awt/libpng/pngrutil.c39
-rw-r--r--src/share/native/sun/awt/libpng/pngset.c12
-rw-r--r--src/share/native/sun/awt/libpng/pngstruct.h12
-rw-r--r--src/share/native/sun/awt/libpng/pngtrans.c12
-rw-r--r--src/share/native/sun/font/DrawGlyphList.c12
-rw-r--r--src/share/native/sun/font/freetypeScaler.c157
-rw-r--r--src/share/native/sun/font/hb-jdk-font.cpp26
-rw-r--r--src/share/native/sun/font/layout/AlternateSubstSubtables.cpp12
-rw-r--r--src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp4
-rw-r--r--src/share/native/sun/font/layout/LigatureSubstSubtables.cpp4
-rw-r--r--src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp7
-rw-r--r--src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp7
-rw-r--r--src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp7
-rw-r--r--src/share/native/sun/font/layout/MorphTables.cpp6
-rw-r--r--src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp2
-rw-r--r--src/share/native/sun/font/layout/PairPositioningSubtables.cpp12
-rw-r--r--src/share/native/sun/font/layout/SegmentArrayProcessor.cpp2
-rw-r--r--src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp2
-rw-r--r--src/share/native/sun/font/layout/SegmentSingleProcessor.cpp2
-rw-r--r--src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp2
-rw-r--r--src/share/native/sun/font/layout/SimpleArrayProcessor.cpp2
-rw-r--r--src/share/native/sun/font/layout/SinglePositioningSubtables.cpp12
-rw-r--r--src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp12
-rw-r--r--src/share/native/sun/font/layout/SingleTableProcessor.cpp2
-rw-r--r--src/share/native/sun/java2d/cmm/lcms/cmsxform.c2
-rw-r--r--src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h2
-rw-r--r--src/share/native/sun/java2d/loops/LoopMacros.h8
-rw-r--r--src/share/native/sun/java2d/opengl/OGLBlitLoops.c42
-rw-r--r--src/share/native/sun/security/ec/ECC_JNI.cpp44
-rw-r--r--src/share/native/sun/security/ec/impl/ec.c18
-rw-r--r--src/share/native/sun/security/krb5/nativeccache.c44
-rw-r--r--src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c442
-rw-r--r--src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h1
-rw-r--r--src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h2
-rw-r--r--src/share/native/sun/security/smartcardio/pcsc.c6
-rw-r--r--src/solaris/classes/sun/awt/X11/InfoWindow.java25
-rw-r--r--src/solaris/classes/sun/awt/X11/XKeysym.java26
-rw-r--r--src/solaris/classes/sun/awt/X11/XMSelection.java10
-rw-r--r--src/solaris/classes/sun/awt/X11/XWindow.java9
-rw-r--r--src/solaris/classes/sun/awt/X11/genhash.awk45
-rw-r--r--src/solaris/classes/sun/awt/X11/keysym2ucs.h2758
-rw-r--r--src/solaris/classes/sun/font/XRGlyphCache.java3
-rw-r--r--src/solaris/classes/sun/font/XRTextRenderer.java3
-rw-r--r--src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java5
-rw-r--r--src/solaris/classes/sun/nio/fs/BsdFileStore.java20
-rw-r--r--src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java16
-rw-r--r--src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java2
-rw-r--r--src/solaris/classes/sun/print/CUPSPrinter.java4
-rw-r--r--src/solaris/classes/sun/print/IPPPrintService.java4
-rw-r--r--src/solaris/classes/sun/print/PrintServiceLookupProvider.java (renamed from src/solaris/classes/sun/print/UnixPrintServiceLookup.java)6
-rw-r--r--src/solaris/classes/sun/print/UnixPrintJob.java4
-rw-r--r--src/solaris/classes/sun/print/UnixPrintService.java58
-rw-r--r--src/solaris/classes/sun/print/services/javax.print.PrintServiceLookup2
-rw-r--r--src/solaris/native/java/io/canonicalize_md.c11
-rw-r--r--src/solaris/native/java/lang/java_props_macosx.c5
-rw-r--r--src/solaris/native/java/net/PlainDatagramSocketImpl.c1
-rw-r--r--src/solaris/native/sun/awt/awt_InputMethod.c7
-rw-r--r--src/solaris/native/sun/awt/gtk3_interface.c82
-rw-r--r--src/solaris/native/sun/awt/gtk3_interface.h4
-rw-r--r--src/solaris/native/sun/awt/multiVis.c97
-rw-r--r--src/solaris/native/sun/java2d/x11/X11FontScaler_md.c6
-rw-r--r--src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c23
-rw-r--r--src/solaris/native/sun/security/smartcardio/MUSCLE/COPYING75
-rw-r--r--src/solaris/native/sun/security/smartcardio/MUSCLE/pcsclite.h564
-rw-r--r--src/solaris/native/sun/security/smartcardio/MUSCLE/winscard.h131
-rw-r--r--src/solaris/native/sun/security/smartcardio/MUSCLE/wintypes.h115
-rw-r--r--src/solaris/native/sun/security/smartcardio/pcsc_md.h87
-rw-r--r--src/windows/classes/java/lang/ProcessImpl.java154
-rw-r--r--src/windows/classes/sun/awt/windows/WPrinterJob.java6
-rw-r--r--src/windows/classes/sun/net/www/protocol/file/Handler.java4
-rw-r--r--src/windows/classes/sun/net/www/protocol/file/UNCFileURLConnection.java52
-rw-r--r--src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java14
-rw-r--r--src/windows/classes/sun/print/PrintServiceLookupProvider.java (renamed from src/windows/classes/sun/print/Win32PrintServiceLookup.java)128
-rw-r--r--src/windows/classes/sun/print/services/javax.print.PrintServiceLookup2
-rw-r--r--src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory2
-rw-r--r--src/windows/classes/sun/security/krb5/internal/tools/Klist.java38
-rw-r--r--src/windows/native/sun/java2d/d3d/D3DContext.cpp4
-rw-r--r--src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c32
-rw-r--r--src/windows/native/sun/nio/ch/FileDispatcherImpl.c2
-rw-r--r--src/windows/native/sun/security/mscapi/security.cpp7
-rw-r--r--src/windows/native/sun/windows/WPrinterJob.cpp33
-rw-r--r--test/Makefile2
-rw-r--r--test/ProblemList.txt5
-rw-r--r--test/TEST.groups36
-rw-r--r--test/java/awt/BasicStroke/DashOffset.java239
-rw-r--r--test/java/awt/BasicStroke/DashScaleMinWidth.java100
-rw-r--r--test/java/awt/BasicStroke/DashZeroWidth.java98
-rw-r--r--test/java/awt/ComponentOrientation/BasicTest.java151
-rw-r--r--test/java/awt/ComponentOrientation/BorderTest.java117
-rw-r--r--test/java/awt/ComponentOrientation/FlowTest.java150
-rw-r--r--test/java/awt/ComponentOrientation/TestBundle.java46
-rw-r--r--test/java/awt/ComponentOrientation/TestBundle1.java49
-rw-r--r--test/java/awt/ComponentOrientation/TestBundle1_ar.java49
-rw-r--r--test/java/awt/ComponentOrientation/TestBundle_es.java46
-rw-r--r--test/java/awt/ComponentOrientation/TestBundle_iw.java48
-rw-r--r--test/java/awt/ComponentOrientation/WindowTest.java155
-rw-r--r--test/java/awt/FontClass/FontSize1Test.java56
-rw-r--r--test/java/awt/FontMetrics/MaxAdvanceIsMax.java143
-rw-r--r--test/java/awt/Headless/ThemeReaderCrashTest.java62
-rw-r--r--test/java/awt/font/TextLayout/FontGlyphCompare.java89
-rw-r--r--test/java/awt/im/InputContext/ReconnectTest.java253
-rw-r--r--test/java/awt/image/DrawImage/IncorrectManagedImageSourceOffset.java188
-rw-r--r--test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java65
-rw-r--r--test/java/awt/image/DrawImage/SimpleManagedImage.java196
-rw-r--r--test/java/awt/image/DrawImage/SimpleUnmanagedImage.java201
-rw-r--r--test/java/io/FilePermission/Invalid.java67
-rw-r--r--test/java/io/LineNumberReader/MarkSplitCRLF.java99
-rw-r--r--test/java/lang/ClassLoader/forNameLeak/ClassForName.java45
-rw-r--r--test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java123
-rw-r--r--test/java/lang/ClassLoader/forNameLeak/test.policy6
-rw-r--r--test/java/lang/invoke/MethodHandlesProxiesTest.java102
-rw-r--r--test/java/net/NetworkInterface/IPv4Only.java6
-rw-r--r--test/java/net/Socket/asyncClose/AsyncClose.java33
-rw-r--r--test/java/net/Socket/asyncClose/AsyncCloseTest.java19
-rw-r--r--test/java/net/Socket/asyncClose/DatagramSocket_receive.java68
-rw-r--r--test/java/net/Socket/asyncClose/Race.java57
-rw-r--r--test/java/net/Socket/asyncClose/ServerSocket_accept.java48
-rw-r--r--test/java/net/Socket/asyncClose/Socket_getInputStream_read.java76
-rw-r--r--test/java/net/Socket/asyncClose/Socket_getOutputStream_write.java62
-rw-r--r--test/java/net/Socks/SocksIPv6Test.java178
-rw-r--r--test/java/net/Socks/SocksServer.java34
-rw-r--r--test/java/net/ipv6tests/Tests.java16
-rw-r--r--test/java/net/ipv6tests/UdpTest.java5
-rw-r--r--test/java/nio/Buffer/Chars.java4
-rw-r--r--test/java/nio/channels/AsynchronousChannelGroup/Basic.java34
-rw-r--r--test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java2
-rw-r--r--test/java/nio/channels/AsynchronousChannelGroup/Restart.java2
-rw-r--r--test/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java211
-rw-r--r--test/java/nio/channels/Selector/ChangingInterests.java2
-rw-r--r--test/java/nio/file/FileStore/Basic.java51
-rw-r--r--test/java/nio/file/FileSystem/Basic.java47
-rw-r--r--test/java/rmi/testlibrary/TestSocketFactory.java20
-rw-r--r--test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java88
-rw-r--r--test/java/text/AttributedString/AttributedStringTest.java258
-rw-r--r--test/java/text/AttributedString/TestAttributedStringCtor.java55
-rw-r--r--test/java/text/AttributedString/getRunStartLimitTest.java116
-rw-r--r--test/java/text/BreakIterator/BreakIteratorTest.java1438
-rw-r--r--test/java/text/BreakIterator/Bug4533872.java261
-rw-r--r--test/java/text/BreakIterator/Bug4740757.java76
-rw-r--r--test/java/text/BreakIterator/Bug4912404.java41
-rw-r--r--test/java/text/BreakIterator/Bug4932583.java41
-rw-r--r--test/java/text/BreakIterator/Bug6513074.java122
-rw-r--r--test/java/text/BreakIterator/NewVSOld_th_TH.java86
-rw-r--r--test/java/text/BreakIterator/broken_th_TH.txt13
-rw-r--r--test/java/text/BreakIterator/test_th_TH.txt1
-rw-r--r--test/java/text/CharacterIterator/CharacterIteratorTest.java286
-rw-r--r--test/java/text/Collator/APITest.java318
-rw-r--r--test/java/text/Collator/Bug6271411.java194
-rw-r--r--test/java/text/Collator/CollationKeyTest.java41
-rw-r--r--test/java/text/Collator/CollationKeyTestImpl.java243
-rw-r--r--test/java/text/Collator/CollatorTest.java141
-rw-r--r--test/java/text/Collator/CurrencyCollate.java86
-rw-r--r--test/java/text/Collator/DanishTest.java215
-rw-r--r--test/java/text/Collator/DummyTest.java421
-rw-r--r--test/java/text/Collator/EnglishTest.java226
-rw-r--r--test/java/text/Collator/FinnishTest.java98
-rw-r--r--test/java/text/Collator/FrenchTest.java100
-rw-r--r--test/java/text/Collator/G7Test.java294
-rw-r--r--test/java/text/Collator/GermanTest.java111
-rw-r--r--test/java/text/Collator/IteratorTest.java291
-rw-r--r--test/java/text/Collator/JapaneseTest.java324
-rw-r--r--test/java/text/Collator/KoreanTest.java142
-rw-r--r--test/java/text/Collator/MonkeyTest.java149
-rw-r--r--test/java/text/Collator/Regression.java940
-rw-r--r--test/java/text/Collator/SpanishTest.java106
-rw-r--r--test/java/text/Collator/SurrogatesTest.java117
-rw-r--r--test/java/text/Collator/Test4401726.java98
-rw-r--r--test/java/text/Collator/ThaiTest.java156
-rw-r--r--test/java/text/Collator/TurkishTest.java118
-rw-r--r--test/java/text/Collator/VietnameseTest.java364
-rw-r--r--test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt44
-rw-r--r--test/java/text/Format/ChoiceFormat/Bug4185732Test.java117
-rw-r--r--test/java/text/Format/ChoiceFormat/Bug4387255.java69
-rw-r--r--test/java/text/Format/DateFormat/Bug4322313.java364
-rw-r--r--test/java/text/Format/DateFormat/Bug4407042.java132
-rw-r--r--test/java/text/Format/DateFormat/Bug4736959.java53
-rw-r--r--test/java/text/Format/DateFormat/Bug4845901.java64
-rw-r--r--test/java/text/Format/DateFormat/Bug6251817.java45
-rw-r--r--test/java/text/Format/DateFormat/Bug6335238.java163
-rw-r--r--test/java/text/Format/DateFormat/Bug6530336.java108
-rw-r--r--test/java/text/Format/DateFormat/DateFormatRegression.java1098
-rw-r--r--test/java/text/Format/DateFormat/DateFormatRoundTripTest.java727
-rw-r--r--test/java/text/Format/DateFormat/DateFormatSymbolsSerializationTest.java121
-rw-r--r--test/java/text/Format/DateFormat/DateFormatTest.java1207
-rw-r--r--test/java/text/Format/DateFormat/IntlTestDateFormat.java273
-rw-r--r--test/java/text/Format/DateFormat/IntlTestDateFormatAPI.java218
-rw-r--r--test/java/text/Format/DateFormat/IntlTestDateFormatSymbols.java206
-rw-r--r--test/java/text/Format/DateFormat/IntlTestSimpleDateFormatAPI.java188
-rw-r--r--test/java/text/Format/DateFormat/NonGregorianFormatTest.java216
-rw-r--r--test/java/text/Format/DateFormat/SDFserialized.ser.txt173
-rw-r--r--test/java/text/Format/DateFormat/TimeZoneNameTest.java152
-rw-r--r--test/java/text/Format/DateFormat/bug4097450.java71
-rw-r--r--test/java/text/Format/DateFormat/bug4099975.java41
-rw-r--r--test/java/text/Format/DateFormat/bug4117335.java83
-rw-r--r--test/java/text/Format/DateFormat/bug4358730.java84
-rw-r--r--test/java/text/Format/DateFormat/bug6271375.java61
-rw-r--r--test/java/text/Format/DateFormat/bug6317072.java81
-rw-r--r--test/java/text/Format/DateFormat/bug6412896.java50
-rw-r--r--test/java/text/Format/MessageFormat/Bug4185816.ser.txt58
-rw-r--r--test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt58
-rw-r--r--test/java/text/Format/MessageFormat/Bug4185816Test.java135
-rw-r--r--test/java/text/Format/MessageFormat/Bug6481179.java64
-rw-r--r--test/java/text/Format/MessageFormat/LargeMessageFormat.java121
-rw-r--r--test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java115
-rw-r--r--test/java/text/Format/MessageFormat/MessageRegression.java644
-rw-r--r--test/java/text/Format/MessageFormat/MessageTest.java102
-rw-r--r--test/java/text/Format/MessageFormat/bug4492719.java79
-rw-r--r--test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java134
-rw-r--r--test/java/text/Format/NumberFormat/BigDecimalFormat.java1044
-rw-r--r--test/java/text/Format/NumberFormat/BigDecimalParse.java709
-rw-r--r--test/java/text/Format/NumberFormat/Bug4208135.java127
-rw-r--r--test/java/text/Format/NumberFormat/Bug4833877.java464
-rw-r--r--test/java/text/Format/NumberFormat/Bug4838107.java248
-rw-r--r--test/java/text/Format/NumberFormat/Bug4944439.java111
-rw-r--r--test/java/text/Format/NumberFormat/Bug4990596.java59
-rw-r--r--test/java/text/Format/NumberFormat/Bug6278616.java69
-rw-r--r--test/java/text/Format/NumberFormat/CurrencyFormat.java141
-rw-r--r--test/java/text/Format/NumberFormat/CurrencySymbols.properties134
-rw-r--r--test/java/text/Format/NumberFormat/DFSDeserialization142.java56
-rw-r--r--test/java/text/Format/NumberFormat/DFSExponential.java87
-rw-r--r--test/java/text/Format/NumberFormat/DFSSerialization.java151
-rw-r--r--test/java/text/Format/NumberFormat/DFSSerialization142.java54
-rw-r--r--test/java/text/Format/NumberFormat/DecimalFormat.114.txt54
-rw-r--r--test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt39
-rw-r--r--test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt42
-rw-r--r--test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java255
-rw-r--r--test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java139
-rw-r--r--test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java220
-rw-r--r--test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt57
-rw-r--r--test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt57
-rw-r--r--test/java/text/Format/NumberFormat/NumberFormatRounding.java130
-rw-r--r--test/java/text/Format/NumberFormat/NumberRegression.java1824
-rw-r--r--test/java/text/Format/NumberFormat/NumberRoundTrip.java234
-rw-r--r--test/java/text/Format/NumberFormat/NumberTest.java411
-rw-r--r--test/java/text/Format/NumberFormat/PositionTest.java221
-rw-r--r--test/java/text/Format/NumberFormat/SerializationLoadTest.java84
-rw-r--r--test/java/text/Format/NumberFormat/SerializationSaveTest.java79
-rw-r--r--test/java/text/Format/NumberFormat/TestPeruCurrencyFormat.java47
-rw-r--r--test/java/text/Format/NumberFormat/TestgetPatternSeparator_ja.java44
-rw-r--r--test/java/text/Format/common/Bug4769840.java82
-rw-r--r--test/java/text/Format/common/Bug6215962.java161
-rw-r--r--test/java/text/Format/common/ChoiceFormat.ser.txt37
-rw-r--r--test/java/text/Format/common/DateFormat.Field.ser.txt32
-rw-r--r--test/java/text/Format/common/FormatIteratorTest.java440
-rw-r--r--test/java/text/Format/common/MessageFormat.Field.ser.txt32
-rw-r--r--test/java/text/Format/common/NumberFormat.Field.ser.txt31
-rw-r--r--test/java/text/Format/common/PParser.java274
-rw-r--r--test/java/text/Format/common/dateFormat.props333
-rw-r--r--test/java/text/Format/common/decimalFormat.props1280
-rw-r--r--test/java/text/Format/common/messageFormat.props520
-rw-r--r--test/java/text/testlib/HexDumpReader.java115
-rw-r--r--test/java/text/testlib/IntlTest.java266
-rw-r--r--test/java/time/test/java/time/format/TestNonIsoFormatter.java2
-rw-r--r--test/java/util/Calendar/BuddhistCalendarTest.java243
-rw-r--r--test/java/util/Calendar/Bug4302966.java42
-rw-r--r--test/java/util/Calendar/Bug4766302.java51
-rw-r--r--test/java/util/Calendar/Bug4851640.java59
-rw-r--r--test/java/util/Calendar/Bug4958050.java255
-rw-r--r--test/java/util/Calendar/Bug5078053.java100
-rw-r--r--test/java/util/Calendar/Bug6178071.java50
-rw-r--r--test/java/util/Calendar/Bug6234795.java97
-rw-r--r--test/java/util/Calendar/Bug6448234.java58
-rw-r--r--test/java/util/Calendar/CalendarLimitTest.java202
-rw-r--r--test/java/util/Calendar/CalendarRegression.java2496
-rw-r--r--test/java/util/Calendar/CalendarTest.java1102
-rw-r--r--test/java/util/Calendar/FieldStateTest.java216
-rw-r--r--test/java/util/Calendar/GregorianCutoverTest.java324
-rw-r--r--test/java/util/Calendar/JapanEraNameCompatTest.java144
-rw-r--r--test/java/util/Calendar/JulianTest.java52
-rw-r--r--test/java/util/Calendar/Koyomi.java289
-rw-r--r--test/java/util/Calendar/Limit.java64
-rw-r--r--test/java/util/Calendar/NonLenientTest.java221
-rw-r--r--test/java/util/Calendar/ResolutionTest.java111
-rw-r--r--test/java/util/Calendar/RollDayOfWeekTest.java137
-rw-r--r--test/java/util/Calendar/StampOverflow.java80
-rw-r--r--test/java/util/Calendar/ZoneOffsets.java231
-rw-r--r--test/java/util/Calendar/bug4028518.java56
-rw-r--r--test/java/util/Calendar/bug4100311.java47
-rw-r--r--test/java/util/Calendar/bug4243802.java93
-rw-r--r--test/java/util/Calendar/bug4316678.java69
-rw-r--r--test/java/util/Calendar/bug4372743.java133
-rw-r--r--test/java/util/Calendar/bug4401223.java91
-rw-r--r--test/java/util/Calendar/bug4409072.java683
-rw-r--r--test/java/util/Calendar/bug4514831.java95
-rw-r--r--test/java/util/Collections/NCopies.java56
-rw-r--r--test/java/util/Currency/ValidateISO4217.java11
-rw-r--r--test/java/util/Currency/tablea1.txt16
-rw-r--r--test/java/util/Date/Bug4955000.java144
-rw-r--r--test/java/util/Date/DateGregorianCalendarTest.java235
-rw-r--r--test/java/util/Date/DateRegression.java241
-rw-r--r--test/java/util/Date/DateTest.java236
-rw-r--r--test/java/util/Date/TZ.java58
-rw-r--r--test/java/util/Date/TimestampTest.java134
-rw-r--r--test/java/util/Locale/Bug8040211.java362
-rw-r--r--test/java/util/Locale/tools/EquivMapsGenerator.java249
-rw-r--r--test/java/util/Objects/CheckIndex.java299
-rw-r--r--test/java/util/TimeZone/Bug4322313.java228
-rw-r--r--test/java/util/TimeZone/Bug5097350.java63
-rw-r--r--test/java/util/TimeZone/DefaultTimeZoneTest.html74
-rw-r--r--test/java/util/TimeZone/DefaultTimeZoneTest.java108
-rw-r--r--test/java/util/TimeZone/HongKong.java64
-rw-r--r--test/java/util/TimeZone/IDTest.java121
-rw-r--r--test/java/util/TimeZone/TimeZoneBoundaryTest.java491
-rw-r--r--test/java/util/TimeZone/TimeZoneRegression.java995
-rw-r--r--test/java/util/TimeZone/TimeZoneTest.java736
-rw-r--r--test/java/util/TimeZone/TransitionTest.java287
-rw-r--r--test/java/util/TimeZone/UTCAliasTest.java52
-rw-r--r--test/java/util/TimeZone/bug4096952.java67
-rw-r--r--test/java/util/stream/test/org/openjdk/tests/java/util/stream/CustomFJPoolTest.java152
-rw-r--r--test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java82
-rw-r--r--test/java/util/zip/ZipFile/MultiThreadedReadTest.java39
-rw-r--r--test/javax/accessibility/SlowPanelIteration/SlowPanelIteration.java2
-rw-r--r--test/javax/crypto/Cipher/EmptyFinalBuffer.java85
-rw-r--r--test/javax/imageio/plugins/jpeg/JpegTablesOnlyReadTest.java66
-rw-r--r--test/javax/imageio/stream/NullStreamCheckTest.java202
-rw-r--r--test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java5
-rw-r--r--test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java4
-rw-r--r--test/javax/swing/SwingUtilities/TestTextPosInPrint.java244
-rw-r--r--test/javax/swing/text/html/8218674/TooltipImageTest.java76
-rw-r--r--test/javax/swing/text/html/8218674/circle.pngbin0 -> 1573 bytes
-rw-r--r--test/javax/xml/jaxp/transform/8207760/JDK8207760.java171
-rw-r--r--test/javax/xml/jaxp/transform/sort/SortTest.java126
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-english.out30
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xml46
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xsl40
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.out37
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xml52
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xsl39
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.out38
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xml53
-rw-r--r--test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xsl39
-rw-r--r--test/jb/java/awt/Font/font430.sh3
-rw-r--r--test/jbProblemsList.txt30
-rw-r--r--test/jbcommitProblemList.txt3
-rw-r--r--test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java504
-rw-r--r--test/lib/testlibrary/jdk/testlibrary/Convert.java84
-rw-r--r--test/lib/testlibrary/jdk/testlibrary/FileUtils.java37
-rw-r--r--test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java111
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java253
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java291
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java666
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java280
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/EntrustCA.java169
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java202
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/GoDaddyCA.java346
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java181
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java471
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/TeliaSoneraCA.java195
-rw-r--r--test/security/infra/java/security/cert/CertPathValidator/certification/ValidatePathWithParams.java354
-rw-r--r--test/sun/net/www/protocol/http/TestTransparentNTLM.java203
-rw-r--r--test/sun/nio/cs/MalformedSurrogates.java160
-rw-r--r--test/sun/security/ec/InvalidCurve.java61
-rw-r--r--test/sun/security/ec/SignatureDigestTruncate.java125
-rw-r--r--test/sun/security/lib/cacerts/VerifyCACerts.java355
-rw-r--r--test/sun/security/rsa/SpecTest.java78
-rw-r--r--test/sun/security/ssl/SSLContextImpl/DefautlCacheSize.java69
-rw-r--r--test/sun/security/ssl/SessionIdCollisionTest.java158
-rw-r--r--test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java21
-rw-r--r--test/sun/security/util/math/BigIntegerModuloP.java294
-rw-r--r--test/sun/security/util/math/TestIntegerModuloP.java393
-rw-r--r--test/sun/security/validator/EndEntityExtensionCheck.java6
-rw-r--r--test/sun/text/IntHashtable/Bug4170614Test.java191
-rw-r--r--test/sun/text/IntHashtable/Bug4170614Test.sh81
-rw-r--r--test/sun/text/IntHashtable/Bug4705389.java43
-rw-r--r--test/sun/text/resources/LocaleData20
-rw-r--r--test/sun/text/resources/LocaleDataTest.java4
-rw-r--r--test/sun/util/calendar/zi/TestZoneInfo310.java27
-rw-r--r--test/sun/util/calendar/zi/Zoneinfo.java13
-rw-r--r--test/sun/util/calendar/zi/tzdata/VERSION2
-rw-r--r--test/sun/util/calendar/zi/tzdata/africa109
-rw-r--r--test/sun/util/calendar/zi/tzdata/asia481
-rw-r--r--test/sun/util/calendar/zi/tzdata/australasia281
-rw-r--r--test/sun/util/calendar/zi/tzdata/backward3
-rw-r--r--test/sun/util/calendar/zi/tzdata/etcetera1
-rw-r--r--test/sun/util/calendar/zi/tzdata/europe4
-rw-r--r--test/sun/util/calendar/zi/tzdata/iso3166.tab8
-rw-r--r--test/sun/util/calendar/zi/tzdata/leapseconds11
-rw-r--r--test/sun/util/calendar/zi/tzdata/northamerica38
-rw-r--r--test/sun/util/calendar/zi/tzdata/zone.tab3
-rw-r--r--test/tools/launcher/RunpathTest.java6
-rw-r--r--testjbu/quality/text/BundledFontTest.java120
635 files changed, 70964 insertions, 7456 deletions
diff --git a/.hgtags b/.hgtags
index 89aadaf25a..3a84abdd2b 100644
--- a/.hgtags
+++ b/.hgtags
@@ -997,3 +997,24 @@ acab6dbdd0b55e524d50e9b1c4f12c90e2f424c5 jdk8u212-b02
ac2ef877d3e8062c1ce72757538daae6cad1118f jdk8u212-b03
01535393e060f2908b8733f2493344b636d1c515 jdk8u212-b04
ac2ef877d3e8062c1ce72757538daae6cad1118f jdk8u212-ga
+e880f2d161bf23a09f8c1a19861d7df7d2ed126f jdk8u222-b01
+78d1f9f2fec2cf65c712837553e9b0fbd07bd9a1 jdk8u222-b02
+7ecf0b6b46aea31bcf2641fcd526d9b211db2420 jdk8u222-b03
+8119ddcb3eecd4d3bd4aa6bde441f88d1fd6f999 jdk8u222-b04
+887c8314411dd461ec4b1e14cd6368ed3d9a7a3b jdk8u222-b05
+63b345c88831be5a690b857adfa84bd20ad376e1 jdk8u222-b06
+c7a97c9b7e5932d651eda37c8a907311818491d7 jdk8u222-b07
+0bb89d93d4d7da64d408a9888df21085e7bfb291 jdk8u222-b08
+0da125166b2bd35aac0d6222ba44535730e2713f jdk8u222-b09
+2a9bea6e5e03a53469abdcd2da268a312cc7b5b8 jdk8u222-b10
+2a9bea6e5e03a53469abdcd2da268a312cc7b5b8 jdk8u222-ga
+54dbc9006d379a3987bd55419a5ed0738012bc6b jdk8u232-b01
+6698d87704f40d6c639858484114ed1f751b32cd jdk8u232-b02
+60eca04567a6d214aa60dd16306f4854bd41b273 jdk8u232-b03
+3ef3348195ffeb3c268af4a43928f2f09c5fa83a jdk8u232-b04
+6d60b8cf1bd4a5fa371b1ddad9d186ff546b25f5 jdk8u232-b05
+5d57817931e1f5b6a460158342f132ea348e14ef jdk8u232-b06
+3560e0ebe876ce658c5261070fe728e47994210f jdk8u232-b07
+69c4f673b33e255599d2aa257fa50fd8b48b7b95 jdk8u232-b08
+5456f24496f43f72b0cf4f0db3a73ea49c33f94f jdk8u232-b09
+5456f24496f43f72b0cf4f0db3a73ea49c33f94f jdk8u232-ga
diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README
index 224735600a..7dc54a0572 100644
--- a/THIRD_PARTY_README
+++ b/THIRD_PARTY_README
@@ -1470,60 +1470,90 @@ included with JDK 8 and OpenJDK 8 source distributions.
-------------------------------------------------------------------------------
-%% This notice is provided with respect to libpng 1.6.35, which may be
+%% This notice is provided with respect to libpng 1.6.37, which may be
included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
-This copy of the libpng notices is provided for your convenience. In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+PNG Reference Library License version 2
+---------------------------------------
-If you modify libpng you may insert additional notices immediately following
-this sentence.
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-This code is released under the libpng license.
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement. In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
-libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you
+ use this software in a product, an acknowledgment in the product
+ documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
- Simon-Pierre Cadieux
- Eric S. Raymond
- Mans Rullgard
- Cosmin Truta
- Gilles Vollant
- James Yu
- Mandar Sahastrabuddhe
- Google Inc.
- Vadim Barkov
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
+ Gilles Vollant
+ James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
- There is no warranty against interference with your enjoyment of the
- library or against infringement. There is no warranty that our
- efforts or the library will fulfill any of your particular purposes
- or needs. This library is provided with all faults, and the entire
- risk of satisfactory quality, performance, accuracy, and effort is with
- the user.
+ There is no warranty against interference with your enjoyment of
+ the library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is
+ with the user.
Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners and
+files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
- Tom Lane
- Glenn Randers-Pehrson
- Willem van Schaik
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -1531,14 +1561,14 @@ and are distributed according to the same disclaimer and license as
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
- John Bowler
- Kevin Bracey
- Sam Bushell
- Magnus Holmgren
- Greg Roelofs
- Tom Tanner
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
-Some files in the "scripts" directory have other copyright owners
+Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -1547,39 +1577,38 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
- Andreas Dilger
- Dave Martindale
- Guy Eric Schalnat
- Paul Schmidt
- Tim Wegner
-
-The PNG Reference Library is supplied "AS IS". The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose. The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose. The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
+ 1. The origin of this source code must not be misrepresented.
- 3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products. If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products. If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
TRADEMARK:
@@ -1612,7 +1641,7 @@ July 15, 2018
-------------------------------------------------------------------------------
-%% This notice is provided with respect to GIFLIB 5.1.1 & libungif 4.1.3,
+%% This notice is provided with respect to GIFLIB 5.1.8 & libungif 4.1.3,
which may be included with JRE 8, JDK 8, and OpenJDK 8.
--- begin of LICENSE ---
@@ -1682,7 +1711,7 @@ which may be included with JRE 8, JDK 8, and OpenJDK 8 source distributions.
--- begin of LICENSE ---
Mesa 3-D graphics library
- Version: 4.1
+ Version: 5.0
Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
@@ -2101,13 +2130,13 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice
-------------------------------------------------------------------------------
-%% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1,
+%% This notice is provided with respect to PC/SC Lite v1.8.24,
which may be included with JRE 8, JDK 8, and OpenJDK 8 on Linux and Solaris.
--- begin of LICENSE ---
-Copyright (c) 1999-2004 David Corcoran <corcoran@linuxnet.com>
-Copyright (c) 1999-2004 Ludovic Rousseau <ludovic.rousseau (at) free.fr>
+Copyright (c) 1999-2003 David Corcoran <corcoran@linuxnet.com>
+Copyright (c) 2001-2011 Ludovic Rousseau <ludovic.rousseau@free.fr>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -2119,15 +2148,10 @@ are met:
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
-3. All advertising materials mentioning features or use of this software
- must display the following acknowledgement:
- This product includes software developed by:
- David Corcoran <corcoran@linuxnet.com>
- http://www.linuxnet.com (MUSCLE)
-4. The name of the author may not be used to endorse or promote products
+3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
-Changes to this license can be made only by the copyright author with
+Changes to this license can be made only by the copyright author with
explicit written consent.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -2797,61 +2821,8 @@ Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.
-___________________________
-The files in motif/lib/Xm/util included this copyright:mkdirhier.man,
-xmkmf.man, chownxterm.c, makeg.man, mergelib.cpp, lndir.man, makestrs.man,
-checktree.c, lndir.c, makestrs.c
-Copyright (c) 1993, 1994 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
-OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not
-be used in advertising or otherwise to promote the sale, use or other
-dealing in this Software without prior written authorization from the
-X Consortium.
-_____________________________
-Xmos_r.h:
-/*
-Copyright (c) 1996 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-*/
+--- end of LICENSE ---
_____________________________
Copyright notice for HPkeysym.h:
/*
@@ -2906,55 +2877,6 @@ consequential damages in connection with the furnishing,
performance, or use of this material.
*/
-_____________________________________
-Copyright notice in keysym2ucs.h:
-
-Copyright 1987, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
-
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-*/
--- end of LICENSE ---
@@ -3000,7 +2922,7 @@ included with JRE 8, JDK 8, and OpenJDK 8.
Apache Jakarta BCEL 5.1
Apache Jakarta Regexp 1.4
Apache Santuario XML Security for Java 1.5.4
- Apache Xalan-Java 2.7.1
+ Apache Xalan-Java 2.7.2
Apache Xerces Java 2.10.0
Apache XML Resolver 1.1
diff --git a/build.txt b/build.txt
index 5cc7dc2699..d2d30115a9 100644
--- a/build.txt
+++ b/build.txt
@@ -1 +1 @@
-8u212-b1586.4
+8u232-b1638.6
diff --git a/make/CopyIntoClasses.gmk b/make/CopyIntoClasses.gmk
index a7ad4007be..e093e9a954 100644
--- a/make/CopyIntoClasses.gmk
+++ b/make/CopyIntoClasses.gmk
@@ -195,9 +195,9 @@ OUT_SERVICES_FILES := $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \
$(shell $(PRINTF) "$(SRC_SERVICES_FILES)\n" | $(SED) -e 's|/[^ ]*/META-INF/services/||g'))
OUT_SERVICES_FILES_COLON := $(addsuffix :, $(OUT_SERVICES_FILES))
# Exception handling for print services with no META-INF directory
-SRC_SERVICES_FILES_PRINT = $(wildcard $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/*)
+SRC_SERVICES_FILES_PRINT = $(wildcard $(JDK_TOPDIR)/src/share/classes/sun/print/services/*)
OUT_SERVICES_FILES_PRINT = $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \
- $(patsubst $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/%, %, \
+ $(patsubst $(JDK_TOPDIR)/src/share/classes/sun/print/services/%, %, \
$(SRC_SERVICES_FILES_PRINT)))
OUT_SERVICES_FILES_PRINT_COLON = $(addsuffix :, $(OUT_SERVICES_FILES_PRINT))
RULES_SERVICES_PRINT = $(join $(OUT_SERVICES_FILES_PRINT_COLON), $(SRC_SERVICES_FILES_PRINT))
diff --git a/make/Images.gmk b/make/Images.gmk
index 06077dc3e0..3354d80800 100644
--- a/make/Images.gmk
+++ b/make/Images.gmk
@@ -125,7 +125,9 @@ ifeq ($(PROFILE), )
wsimport$(EXE_SUFFIX) \
schemagen$(EXE_SUFFIX) \
jsadebugd$(EXE_SUFFIX) \
- jhat$(EXE_SUFFIX)
+ jhat$(EXE_SUFFIX) \
+ clhsdb$(EXE_SUFFIX) \
+ hsdb$(EXE_SUFFIX)
endif
WINDOWS_JDK_BIN_FILES = \
diff --git a/make/Tools.gmk b/make/Tools.gmk
index afb9f86238..b03419a03f 100644
--- a/make/Tools.gmk
+++ b/make/Tools.gmk
@@ -123,6 +123,9 @@ TOOL_OSX_TOBIN = $(JAVA_SMALL) -Djava.awt.headless=true -cp $(JDK_OUTPUTDIR)/btc
TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \
build.tools.cldrconverter.CLDRConverter
+TOOL_GENERATELSREQUIVMAPS = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \
+ build.tools.generatelsrequivmaps.EquivMapsGenerator
+
TOOL_REMOVEMETHODS = $(JAVA_SMALL) -Xbootclasspath/p:$(LANGTOOLS_OUTPUTDIR)/dist/bootstrap/lib/javac.jar \
-cp '$(JDK_OUTPUTDIR)/btclasses$(PATH_SEP)$(JDK_OUTPUTDIR)' \
build.tools.classfile.RemoveMethods
diff --git a/test/java/util/Locale/tools/language-subtag-registry.txt b/make/data/lsrdata/language-subtag-registry.txt
index 916cb10138..9fea9cecd1 100644
--- a/test/java/util/Locale/tools/language-subtag-registry.txt
+++ b/make/data/lsrdata/language-subtag-registry.txt
@@ -1,4 +1,4 @@
-File-Date: 2013-09-23
+File-Date: 2019-04-03
%%
Type: language
Subtag: aa
@@ -106,6 +106,7 @@ Added: 2005-10-16
Type: language
Subtag: bn
Description: Bengali
+Description: Bangla
Added: 2005-10-16
Suppress-Script: Beng
%%
@@ -377,6 +378,7 @@ Subtag: hy
Description: Armenian
Added: 2005-10-16
Suppress-Script: Armn
+Comments: see also hyw
%%
Type: language
Subtag: hz
@@ -524,6 +526,7 @@ Suppress-Script: Latn
%%
Type: language
Subtag: km
+Description: Khmer
Description: Central Khmer
Added: 2005-10-16
Suppress-Script: Khmr
@@ -590,6 +593,7 @@ Suppress-Script: Latn
Type: language
Subtag: lg
Description: Ganda
+Description: Luganda
Added: 2005-10-16
%%
Type: language
@@ -792,6 +796,7 @@ Scope: macrolanguage
Type: language
Subtag: or
Description: Oriya (macrolanguage)
+Description: Odia (macrolanguage)
Added: 2005-10-16
Suppress-Script: Orya
Scope: macrolanguage
@@ -955,6 +960,7 @@ Subtag: sr
Description: Serbian
Added: 2005-10-16
Macrolanguage: sh
+Comments: see cnr for Montenegrin
%%
Type: language
Subtag: ss
@@ -1214,6 +1220,8 @@ Type: language
Subtag: aam
Description: Aramanik
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: aas
%%
Type: language
Subtag: aan
@@ -1527,6 +1535,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: add
+Description: Lidzonka
Description: Dzodinka
Added: 2009-07-29
%%
@@ -1580,6 +1589,8 @@ Type: language
Subtag: adp
Description: Adap
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: dz
%%
Type: language
Subtag: adq
@@ -1651,6 +1662,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: aee
+Description: Northeast Pashai
Description: Northeast Pashayi
Added: 2009-07-29
%%
@@ -1744,6 +1756,7 @@ Added: 2005-10-16
Type: language
Subtag: afi
Description: Akrukay
+Description: Chini
Added: 2009-07-29
%%
Type: language
@@ -2106,7 +2119,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: aja
-Description: Aja (Sudan)
+Description: Aja (South Sudan)
Added: 2009-07-29
%%
Type: language
@@ -2734,6 +2747,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: aot
+Description: Atong (India)
Description: A'tong
Added: 2009-07-29
%%
@@ -2933,6 +2947,11 @@ Description: Arhâ
Added: 2009-07-29
%%
Type: language
+Subtag: aqt
+Description: Angaité
+Added: 2014-02-28
+%%
+Type: language
Subtag: aqz
Description: Akuntsu
Added: 2010-03-11
@@ -3083,6 +3102,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: asf
+Description: Auslan
Description: Australian Sign Language
Added: 2009-07-29
%%
@@ -3252,7 +3272,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: ato
-Description: Atong
+Description: Atong (Cameroon)
Added: 2009-07-29
%%
Type: language
@@ -3332,8 +3352,10 @@ Added: 2009-07-29
%%
Type: language
Subtag: aue
-Description: =/Kx'au//'ein
+Description: ǂKxʼauǁʼein
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: ktz
%%
Type: language
Subtag: auf
@@ -4093,7 +4115,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: bcg
-Description: Baga Binari
+Description: Baga Pokur
Added: 2009-07-29
%%
Type: language
@@ -4224,7 +4246,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: bdh
-Description: Baka (Sudan)
+Description: Baka (South Sudan)
Added: 2009-07-29
%%
Type: language
@@ -4234,6 +4256,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: bdj
+Description: Bai (South Sudan)
Description: Bai
Added: 2009-07-29
%%
@@ -4452,6 +4475,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: bfc
+Description: Panyi Bai
Description: Northern Bai
Added: 2009-07-29
%%
@@ -4626,6 +4650,8 @@ Type: language
Subtag: bgm
Description: Baga Mboteni
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: bcg
%%
Type: language
Subtag: bgn
@@ -5274,7 +5300,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: blm
-Description: Beli (Sudan)
+Description: Beli (South Sudan)
Added: 2009-07-29
%%
Type: language
@@ -5315,6 +5341,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: blv
+Description: Kibala
Description: Bolo
Added: 2009-07-29
%%
@@ -5365,7 +5392,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: bmf
-Description: Bom
+Description: Bom-Kim
Added: 2009-07-29
%%
Type: language
@@ -5463,6 +5490,7 @@ Type: language
Subtag: bmy
Description: Bemba (Democratic Republic of Congo)
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: bmz
@@ -6265,6 +6293,7 @@ Type: language
Subtag: btl
Description: Bhatola
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: btm
@@ -6832,6 +6861,7 @@ Type: language
Subtag: bxx
Description: Borna (Democratic Republic of Congo)
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: bxz
@@ -6959,6 +6989,7 @@ Type: language
Subtag: byy
Description: Buya
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: byz
@@ -7250,6 +7281,7 @@ Type: language
Subtag: cbe
Description: Chipiajes
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: cbg
@@ -7260,6 +7292,7 @@ Type: language
Subtag: cbh
Description: Cagua
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: cbi
@@ -7292,6 +7325,12 @@ Description: Izora
Added: 2009-07-29
%%
Type: language
+Subtag: cbq
+Description: Tsucuba
+Description: Cuba
+Added: 2015-02-12
+%%
+Type: language
Subtag: cbr
Description: Cashibo-Cacataibo
Added: 2009-07-29
@@ -8047,6 +8086,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: cnh
+Description: Hakha Chin
Description: Haka Chin
Added: 2009-07-29
%%
@@ -8071,6 +8111,13 @@ Description: Con
Added: 2009-07-29
%%
Type: language
+Subtag: cnr
+Description: Montenegrin
+Added: 2018-01-23
+Macrolanguage: sh
+Comments: see sr for Serbian
+%%
+Type: language
Subtag: cns
Description: Central Asmat
Added: 2009-07-29
@@ -8206,6 +8253,8 @@ Type: language
Subtag: coy
Description: Coyaima
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: pij
%%
Type: language
Subtag: coz
@@ -8296,6 +8345,8 @@ Type: language
Subtag: cqu
Description: Chilean Quechua
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: quh
Macrolanguage: qu
%%
Type: language
@@ -8642,6 +8693,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: cug
+Description: Chungmboko
Description: Cung
Added: 2009-07-29
%%
@@ -8676,6 +8728,7 @@ Type: language
Subtag: cum
Description: Cumeral
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: cuo
@@ -8729,6 +8782,11 @@ Description: Tepeuxila Cuicatec
Added: 2009-07-29
%%
Type: language
+Subtag: cuy
+Description: Cuitlatec
+Added: 2018-03-08
+%%
+Type: language
Subtag: cvg
Description: Chug
Added: 2009-07-29
@@ -9296,8 +9354,9 @@ Macrolanguage: mwr
%%
Type: language
Subtag: dhg
-Description: Djangu
+Description: Dhangu-Djangu
Description: Dhangu
+Description: Djangu
Added: 2009-07-29
%%
Type: language
@@ -9754,6 +9813,12 @@ Description: Dzùùngoo
Added: 2009-07-29
%%
Type: language
+Subtag: dno
+Description: Ndrulo
+Description: Northern Lendu
+Added: 2018-10-28
+%%
+Type: language
Subtag: dnr
Description: Danaru
Added: 2009-07-29
@@ -9934,7 +9999,7 @@ Preferred-Value: khk
%%
Type: language
Subtag: dri
-Description: C'lela
+Description: C'Lela
Added: 2009-07-29
%%
Type: language
@@ -10066,12 +10131,18 @@ Description: Tomo Kan Dogon
Added: 2009-07-29
%%
Type: language
+Subtag: dtn
+Description: Daatsʼíin
+Added: 2016-05-30
+%%
+Type: language
Subtag: dto
Description: Tommo So Dogon
Added: 2012-08-12
%%
Type: language
Subtag: dtp
+Description: Kadazan Dusun
Description: Central Dusun
Added: 2009-07-29
%%
@@ -10152,6 +10223,8 @@ Type: language
Subtag: duj
Description: Dhuwal
Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see dwu, dwy
%%
Type: language
Subtag: duk
@@ -10226,7 +10299,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: duz
-Description: Duli
+Description: Duli-Gey
Added: 2009-07-29
%%
Type: language
@@ -10257,11 +10330,26 @@ Description: Dutton World Speedwords
Added: 2009-07-29
%%
Type: language
+Subtag: dwu
+Description: Dhuwal
+Added: 2016-05-30
+%%
+Type: language
Subtag: dww
Description: Dawawa
Added: 2009-07-29
%%
Type: language
+Subtag: dwy
+Description: Dhuwaya
+Added: 2016-05-30
+%%
+Type: language
+Subtag: dwz
+Description: Dewas Rai
+Added: 2018-10-28
+%%
+Type: language
Subtag: dya
Description: Dyan
Added: 2009-07-29
@@ -10320,6 +10408,7 @@ Type: language
Subtag: dzd
Description: Daza
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: dze
@@ -10613,6 +10702,7 @@ Type: language
Subtag: emo
Description: Emok
Added: 2009-07-29
+Deprecated: 2014-02-28
%%
Type: language
Subtag: emp
@@ -10676,6 +10766,11 @@ Description: Tundra Enets
Added: 2009-07-29
%%
Type: language
+Subtag: enl
+Description: Enlhet
+Added: 2014-02-28
+%%
+Type: language
Subtag: enm
Description: Middle English (1100-1500)
Added: 2005-10-16
@@ -10717,6 +10812,11 @@ Description: Enwan (Akwa Ibom State)
Added: 2009-07-29
%%
Type: language
+Subtag: enx
+Description: Enxet
+Added: 2014-02-28
+%%
+Type: language
Subtag: eot
Description: Beti (Côte d'Ivoire)
Added: 2009-07-29
@@ -10782,6 +10882,12 @@ Description: Ese Ejja
Added: 2009-07-29
%%
Type: language
+Subtag: esg
+Description: Aheri Gondi
+Added: 2016-05-30
+Macrolanguage: gon
+%%
+Type: language
Subtag: esh
Description: Eshtehardi
Added: 2009-07-29
@@ -10840,6 +10946,11 @@ Added: 2009-07-29
Scope: collection
%%
Type: language
+Subtag: esy
+Description: Eskayan
+Added: 2014-04-06
+%%
+Type: language
Subtag: etb
Description: Etebi
Added: 2009-07-29
@@ -11008,7 +11119,7 @@ Added: 2005-10-16
%%
Type: language
Subtag: fap
-Description: Palor
+Description: Paloor
Added: 2009-07-29
%%
Type: language
@@ -11158,6 +11269,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: fly
+Description: Flaaitaal
Description: Tsotsitaal
Added: 2009-07-29
%%
@@ -11172,6 +11284,11 @@ Description: Far Western Muria
Added: 2009-07-29
%%
Type: language
+Subtag: fnb
+Description: Fanbak
+Added: 2016-05-30
+%%
+Type: language
Subtag: fng
Description: Fanagalo
Added: 2009-07-29
@@ -11856,7 +11973,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: gek
-Description: Yiwom
+Description: Ywom
Added: 2009-07-29
%%
Type: language
@@ -11881,6 +11998,11 @@ Description: Geser-Gorom
Added: 2009-07-29
%%
Type: language
+Subtag: gev
+Description: Eviya
+Added: 2014-02-28
+%%
+Type: language
Subtag: gew
Description: Gera
Added: 2009-07-29
@@ -11912,8 +12034,10 @@ Added: 2009-07-29
%%
Type: language
Subtag: gfx
-Description: Mangetti Dune !Xung
+Description: Mangetti Dune ǃXung
Added: 2012-08-12
+Deprecated: 2015-02-12
+Preferred-Value: vaj
%%
Type: language
Subtag: gga
@@ -11954,19 +12078,22 @@ Type: language
Subtag: ggn
Description: Eastern Gurung
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: gvr
%%
Type: language
Subtag: ggo
Description: Southern Gondi
Added: 2009-07-29
-Macrolanguage: gon
+Deprecated: 2016-05-30
+Comments: see esg, wsg
%%
Type: language
Subtag: ggr
Description: Aghu Tharnggalu
Added: 2009-07-29
Deprecated: 2013-09-10
-Comments: see ggm, gtu, ikr
+Comments: see gtu, ikr
%%
Type: language
Subtag: ggt
@@ -12061,6 +12188,12 @@ Description: Gidar
Added: 2009-07-29
%%
Type: language
+Subtag: gie
+Description: Gaɓogbo
+Description: Guébie
+Added: 2017-02-23
+%%
+Type: language
Subtag: gig
Description: Goaria
Added: 2009-07-29
@@ -12163,6 +12296,11 @@ Description: Gonja
Added: 2009-07-29
%%
Type: language
+Subtag: gjr
+Description: Gurindji Kriol
+Added: 2016-05-30
+%%
+Type: language
Subtag: gju
Description: Gujari
Added: 2009-07-29
@@ -12174,6 +12312,11 @@ Description: Guya
Added: 2009-07-29
%%
Type: language
+Subtag: gkd
+Description: Magɨ (Madang Province)
+Added: 2018-03-08
+%%
+Type: language
Subtag: gke
Description: Ndai
Added: 2009-07-29
@@ -12195,6 +12338,11 @@ Added: 2009-07-29
Macrolanguage: kpe
%%
Type: language
+Subtag: gku
+Description: ǂUngkue
+Added: 2015-02-12
+%%
+Type: language
Subtag: glc
Description: Bon Gula
Added: 2009-07-29
@@ -12206,6 +12354,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: glh
+Description: Northwest Pashai
Description: Northwest Pashayi
Added: 2009-07-29
%%
@@ -12276,6 +12425,11 @@ Added: 2009-07-29
Scope: collection
%%
Type: language
+Subtag: gmg
+Description: Magɨyi
+Added: 2014-02-28
+%%
+Type: language
Subtag: gmh
Description: Middle High German (ca. 1050-1500)
Added: 2005-10-16
@@ -12374,8 +12528,13 @@ Description: Gooniyandi
Added: 2009-07-29
%%
Type: language
+Subtag: gnj
+Description: Ngen
+Added: 2018-03-08
+%%
+Type: language
Subtag: gnk
-Description: //Gana
+Description: ǁGana
Added: 2009-07-29
%%
Type: language
@@ -12729,6 +12888,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: gsn
+Description: Nema
Description: Gusan
Added: 2009-07-29
%%
@@ -12765,6 +12925,8 @@ Type: language
Subtag: gti
Description: Gbati-ri
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: nyc
%%
Type: language
Subtag: gtu
@@ -12878,6 +13040,8 @@ Type: language
Subtag: guv
Description: Gey
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: duz
%%
Type: language
Subtag: guw
@@ -12947,7 +13111,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: gvr
-Description: Western Gurung
+Description: Gurung
Added: 2009-07-29
%%
Type: language
@@ -13002,7 +13166,7 @@ Added: 2005-10-16
%%
Type: language
Subtag: gwj
-Description: /Gwi
+Description: ǀGwi
Added: 2009-07-29
%%
Type: language
@@ -13097,6 +13261,11 @@ Description: Guyanese Creole English
Added: 2009-07-29
%%
Type: language
+Subtag: gyo
+Description: Gyalsumdo
+Added: 2018-03-08
+%%
+Type: language
Subtag: gyr
Description: Guarayu
Added: 2009-07-29
@@ -13329,7 +13498,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: hgm
-Description: Hai//om
+Description: Haiǁom
Added: 2009-07-29
%%
Type: language
@@ -13456,6 +13625,11 @@ Description: Hunjara-Kaina Ke
Added: 2009-07-29
%%
Type: language
+Subtag: hkn
+Description: Mel-Khaonh
+Added: 2018-03-08
+%%
+Type: language
Subtag: hks
Description: Hong Kong Sign Language
Description: Heung Kong Sau Yue
@@ -13667,7 +13841,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: hnh
-Description: //Ani
+Description: ǁAni
Added: 2009-07-29
%%
Type: language
@@ -13815,6 +13989,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: hps
+Description: Hawai'i Sign Language (HSL)
Description: Hawai'i Pidgin Sign Language
Added: 2009-07-29
%%
@@ -13945,7 +14120,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: huc
-Description: =/Hua
+Description: ǂHua
Added: 2009-07-29
%%
Type: language
@@ -14107,6 +14282,12 @@ Description: Hya
Added: 2009-07-29
%%
Type: language
+Subtag: hyw
+Description: Western Armenian
+Added: 2018-03-08
+Comments: see also hy
+%%
+Type: language
Subtag: hyx
Description: Armenian (family)
Added: 2009-07-29
@@ -14126,6 +14307,7 @@ Type: language
Subtag: iap
Description: Iapama
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: iar
@@ -14158,6 +14340,11 @@ Description: Ibanag
Added: 2009-07-29
%%
Type: language
+Subtag: ibh
+Description: Bih
+Added: 2017-02-23
+%%
+Type: language
Subtag: ibi
Description: Ibilo
Added: 2009-07-29
@@ -14452,6 +14639,11 @@ Description: Ikaranggal
Added: 2013-09-10
%%
Type: language
+Subtag: iks
+Description: Inuit Sign Language
+Added: 2015-02-12
+%%
+Type: language
Subtag: ikt
Description: Inuinnaqtun
Description: Western Canadian Inuktitut
@@ -14507,6 +14699,13 @@ Type: language
Subtag: ill
Description: Iranun
Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see ilm, ilp
+%%
+Type: language
+Subtag: ilm
+Description: Iranun (Malaysia)
+Added: 2016-05-30
%%
Type: language
Subtag: ilo
@@ -14514,6 +14713,11 @@ Description: Iloko
Added: 2005-10-16
%%
Type: language
+Subtag: ilp
+Description: Iranun (Philippines)
+Added: 2016-05-30
+%%
+Type: language
Subtag: ils
Description: International Sign
Added: 2009-07-29
@@ -14544,6 +14748,7 @@ Type: language
Subtag: ime
Description: Imeraguen
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: imi
@@ -14705,6 +14910,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: iri
+Description: Rigwe
Description: Irigwe
Added: 2009-07-29
%%
@@ -14826,6 +15032,11 @@ Added: 2009-07-29
Scope: collection
%%
Type: language
+Subtag: itd
+Description: Southern Tidung
+Added: 2016-05-30
+%%
+Type: language
Subtag: ite
Description: Itene
Added: 2009-07-29
@@ -15177,6 +15388,8 @@ Type: language
Subtag: jeg
Description: Jeng
Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: oyb
%%
Type: language
Subtag: jeh
@@ -15331,11 +15544,21 @@ Description: Buyuan Jinuo
Added: 2009-07-29
%%
Type: language
+Subtag: jje
+Description: Jejueo
+Added: 2015-02-12
+%%
+Type: language
Subtag: jjr
Description: Bankal
Added: 2012-08-12
%%
Type: language
+Subtag: jka
+Description: Kaera
+Added: 2016-05-30
+%%
+Type: language
Subtag: jkm
Description: Mobwa Karen
Added: 2012-08-12
@@ -15471,6 +15694,11 @@ Description: Wojenaka
Added: 2009-07-29
%%
Type: language
+Subtag: jog
+Description: Jogi
+Added: 2015-05-27
+%%
+Type: language
Subtag: jor
Description: Jorá
Added: 2009-07-29
@@ -15711,6 +15939,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: kak
+Description: Kalanguya
Description: Kayapa Kallahan
Added: 2009-07-29
%%
@@ -15789,6 +16018,7 @@ Type: language
Subtag: kbf
Description: Kakauhua
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: kbg
@@ -16364,7 +16594,8 @@ Added: 2009-07-29
%%
Type: language
Subtag: kfr
-Description: Kachchi
+Description: Kachhi
+Description: Kutchi
Added: 2009-07-29
%%
Type: language
@@ -16421,11 +16652,15 @@ Type: language
Subtag: kgc
Description: Kasseng
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tdf
%%
Type: language
Subtag: kgd
Description: Kataang
Added: 2009-07-29
+Deprecated: 2017-02-23
+Comments: see ncq, sct
%%
Type: language
Subtag: kge
@@ -16890,6 +17125,11 @@ Description: Kashaya
Added: 2009-07-29
%%
Type: language
+Subtag: kjv
+Description: Kaikavian Literary Language
+Added: 2015-02-12
+%%
+Type: language
Subtag: kjx
Description: Ramopa
Added: 2009-07-29
@@ -17147,6 +17387,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: klw
+Description: Tado
Description: Lindu
Added: 2009-07-29
%%
@@ -17471,6 +17712,8 @@ Type: language
Subtag: koj
Description: Sara Dunjo
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: kwv
%%
Type: language
Subtag: kok
@@ -17528,6 +17771,7 @@ Type: language
Subtag: kox
Description: Coxima
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: koy
@@ -17862,6 +18106,8 @@ Type: language
Subtag: krm
Description: Krim
Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: bmf
%%
Type: language
Subtag: krn
@@ -17881,7 +18127,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: krr
-Description: Kru'ng 2
+Description: Krung
Added: 2009-07-29
%%
Type: language
@@ -18145,6 +18391,8 @@ Type: language
Subtag: ktr
Description: Kota Marudu Tinagas
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
%%
Type: language
Subtag: kts
@@ -18183,7 +18431,8 @@ Added: 2009-07-29
%%
Type: language
Subtag: ktz
-Description: Ju/'hoan
+Description: Juǀʼhoan
+Description: Juǀʼhoansi
Added: 2009-07-29
%%
Type: language
@@ -18203,7 +18452,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: kue
-Description: Kuman
+Description: Kuman (Papua New Guinea)
Added: 2009-07-29
%%
Type: language
@@ -18402,6 +18651,8 @@ Type: language
Subtag: kvs
Description: Kunggara
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: gdj
%%
Type: language
Subtag: kvt
@@ -18525,6 +18776,8 @@ Type: language
Subtag: kwq
Description: Kwak
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: yam
%%
Type: language
Subtag: kwr
@@ -18598,6 +18851,8 @@ Type: language
Subtag: kxe
Description: Kakihum
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: tvd
%%
Type: language
Subtag: kxf
@@ -18881,6 +19136,8 @@ Type: language
Subtag: kzj
Description: Coastal Kadazan
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
%%
Type: language
Subtag: kzk
@@ -18931,6 +19188,8 @@ Type: language
Subtag: kzt
Description: Tambunan Dusun
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
%%
Type: language
Subtag: kzu
@@ -19070,7 +19329,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: lay
-Description: Lama (Myanmar)
+Description: Lama Bai
Added: 2009-07-29
%%
Type: language
@@ -19208,6 +19467,7 @@ Added: 2009-07-29
Type: language
Subtag: lce
Description: Loncong
+Description: Sekak
Added: 2009-07-29
Macrolanguage: ms
%%
@@ -19352,6 +19612,8 @@ Type: language
Subtag: leg
Description: Lengua
Added: 2009-07-29
+Deprecated: 2014-02-28
+Comments: see enl, enx
%%
Type: language
Subtag: leh
@@ -19502,6 +19764,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: lgn
+Description: T'apo
Description: Opuuo
Added: 2009-07-29
%%
@@ -19624,6 +19887,8 @@ Type: language
Subtag: lii
Description: Lingkhim
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: raq
%%
Type: language
Subtag: lij
@@ -19987,6 +20252,8 @@ Type: language
Subtag: lmm
Description: Lamam
Added: 2009-07-29
+Deprecated: 2014-02-28
+Preferred-Value: rmx
%%
Type: language
Subtag: lmn
@@ -20096,7 +20363,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: lno
-Description: Lango (Sudan)
+Description: Lango (South Sudan)
Added: 2009-07-29
%%
Type: language
@@ -20216,7 +20483,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: lou
-Description: Louisiana Creole French
+Description: Louisiana Creole
Added: 2009-07-29
%%
Type: language
@@ -20362,6 +20629,7 @@ Type: language
Subtag: lsg
Description: Lyons Sign Language
Added: 2009-07-29
+Deprecated: 2018-03-08
%%
Type: language
Subtag: lsh
@@ -20428,6 +20696,11 @@ Added: 2010-03-11
Macrolanguage: lv
%%
Type: language
+Subtag: lth
+Description: Thur
+Added: 2017-02-23
+%%
+Type: language
Subtag: lti
Description: Leti (Indonesia)
Added: 2009-07-29
@@ -20628,6 +20901,11 @@ Description: Luwo
Added: 2009-07-29
%%
Type: language
+Subtag: lws
+Description: Malawian Sign Language
+Added: 2018-03-08
+%%
+Type: language
Subtag: lwt
Description: Lewotobi
Added: 2009-07-29
@@ -20682,6 +20960,7 @@ Type: language
Subtag: maa
Description: San Jerónimo Tecóatl Mazatec
Added: 2009-07-29
+Comments: see also pbm
%%
Type: language
Subtag: mab
@@ -21596,6 +21875,7 @@ Type: language
Subtag: mhh
Description: Maskoy Pidgin
Added: 2009-07-29
+Deprecated: 2014-02-28
%%
Type: language
Subtag: mhi
@@ -21821,6 +22101,11 @@ Added: 2009-07-29
Deprecated: 2011-08-16
%%
Type: language
+Subtag: mjb
+Description: Makalero
+Added: 2016-05-30
+%%
+Type: language
Subtag: mjc
Description: San Juan Colorado Mixtec
Added: 2009-07-29
@@ -23496,6 +23781,8 @@ Type: language
Subtag: mwj
Description: Maligo
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: vaj
%%
Type: language
Subtag: mwk
@@ -23569,11 +23856,13 @@ Type: language
Subtag: mwx
Description: Mediak
Added: 2009-07-29
+Deprecated: 2018-03-08
%%
Type: language
Subtag: mwy
Description: Mosiro
Added: 2009-07-29
+Deprecated: 2018-03-08
%%
Type: language
Subtag: mwz
@@ -23986,6 +24275,8 @@ Type: language
Subtag: nad
Description: Nijadali
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: xny
%%
Type: language
Subtag: nae
@@ -24052,6 +24343,7 @@ Added: 2005-10-16
%%
Type: language
Subtag: naq
+Description: Khoekhoe
Description: Nama (Namibia)
Added: 2009-07-29
%%
@@ -24067,6 +24359,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: nat
+Description: Ca̱hungwa̱rya̱
Description: Hungworo
Added: 2009-07-29
%%
@@ -24293,6 +24586,13 @@ Type: language
Subtag: ncp
Description: Ndaktup
Added: 2009-07-29
+Deprecated: 2018-03-08
+Preferred-Value: kdz
+%%
+Type: language
+Subtag: ncq
+Description: Northern Katang
+Added: 2017-02-23
%%
Type: language
Subtag: ncr
@@ -24631,7 +24931,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: ngh
-Description: N/u
+Description: Nǀu
Added: 2009-07-29
%%
Type: language
@@ -24692,6 +24992,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: ngt
+Description: Kriang
Description: Ngeq
Added: 2009-07-29
%%
@@ -25217,6 +25518,11 @@ Description: Nihali
Added: 2009-07-29
%%
Type: language
+Subtag: nlm
+Description: Mankiyali
+Added: 2018-03-08
+%%
+Type: language
Subtag: nln
Description: Durango Nahuatl
Added: 2009-07-29
@@ -25339,7 +25645,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: nmn
-Description: !Xóõ
+Description: ǃXóõ
Added: 2009-07-29
%%
Type: language
@@ -25385,6 +25691,7 @@ Added: 2009-07-29
Type: language
Subtag: nmw
Description: Nimoa
+Description: Rifao
Added: 2009-07-29
%%
Type: language
@@ -25516,6 +25823,8 @@ Type: language
Subtag: nnx
Description: Ngong
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: ngv
%%
Type: language
Subtag: nny
@@ -25696,6 +26005,11 @@ Description: Puimei Naga
Added: 2009-07-29
%%
Type: language
+Subtag: npx
+Description: Noipx
+Added: 2017-02-23
+%%
+Type: language
Subtag: npy
Description: Napu
Added: 2009-07-29
@@ -25711,6 +26025,11 @@ Description: Kura Ede Nago
Added: 2009-07-29
%%
Type: language
+Subtag: nql
+Description: Ngendelengo
+Added: 2017-02-23
+%%
+Type: language
Subtag: nqm
Description: Ndom
Added: 2009-07-29
@@ -25758,6 +26077,12 @@ Description: Southern Rengma Naga
Added: 2009-07-29
%%
Type: language
+Subtag: nrf
+Description: Jèrriais
+Description: Guernésiais
+Added: 2015-02-12
+%%
+Type: language
Subtag: nrg
Description: Narango
Added: 2009-07-29
@@ -25942,6 +26267,11 @@ Description: Nisenan
Added: 2009-07-29
%%
Type: language
+Subtag: ntd
+Description: Northern Tidung
+Added: 2016-05-30
+%%
+Type: language
Subtag: nte
Description: Nathembo
Added: 2009-07-29
@@ -25990,6 +26320,8 @@ Type: language
Subtag: nts
Description: Natagaimas
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: pij
%%
Type: language
Subtag: ntu
@@ -26267,6 +26599,11 @@ Description: Ngawun
Added: 2009-07-29
%%
Type: language
+Subtag: nxo
+Description: Ndambomo
+Added: 2015-02-12
+%%
+Type: language
Subtag: nxq
Description: Naxi
Added: 2011-08-16
@@ -26420,6 +26757,11 @@ Description: Njebi
Added: 2009-07-29
%%
Type: language
+Subtag: nzd
+Description: Nzadi
+Added: 2018-03-08
+%%
+Type: language
Subtag: nzi
Description: Nzima
Added: 2005-10-16
@@ -26788,6 +27130,16 @@ Description: Olrat
Added: 2009-07-29
%%
Type: language
+Subtag: olt
+Description: Old Lithuanian
+Added: 2014-02-28
+%%
+Type: language
+Subtag: olu
+Description: Kuvale
+Added: 2016-05-30
+%%
+Type: language
Subtag: oma
Description: Omaha-Ponca
Added: 2009-07-29
@@ -26806,6 +27158,7 @@ Type: language
Subtag: ome
Description: Omejes
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: omg
@@ -27089,6 +27442,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: ory
+Description: Odia (individual language)
Description: Oriya (individual language)
Added: 2012-08-12
Macrolanguage: or
@@ -27262,8 +27616,16 @@ Added: 2009-07-29
%%
Type: language
Subtag: oun
-Description: !O!ung
+Description: ǃOǃung
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: vaj
+%%
+Type: language
+Subtag: ovd
+Description: Elfdalian
+Description: Övdalian
+Added: 2016-06-16
%%
Type: language
Subtag: owi
@@ -27464,6 +27826,12 @@ Description: Mak (Nigeria)
Added: 2009-07-29
%%
Type: language
+Subtag: pbm
+Description: Puebla Mazatec
+Added: 2018-03-08
+Comments: see also maa
+%%
+Type: language
Subtag: pbn
Description: Kpasam
Added: 2009-07-29
@@ -27507,7 +27875,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: pby
-Description: Pyu
+Description: Pyu (Papua New Guinea)
Added: 2009-07-29
%%
Type: language
@@ -27763,6 +28131,11 @@ Added: 2009-07-29
Macrolanguage: ar
%%
Type: language
+Subtag: pgd
+Description: Gāndhārī
+Added: 2015-02-12
+%%
+Type: language
Subtag: pgg
Description: Pangwali
Added: 2009-07-29
@@ -27804,6 +28177,11 @@ Added: 2009-07-29
Deprecated: 2012-08-12
%%
Type: language
+Subtag: pgz
+Description: Papua New Guinean Sign Language
+Added: 2016-05-30
+%%
+Type: language
Subtag: pha
Description: Pa-Hng
Added: 2009-07-29
@@ -28157,6 +28535,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: pls
+Description: San Marcos Tlacoyalco Popoloca
Description: San Marcos Tlalcoyalco Popoloca
Added: 2009-07-29
%%
@@ -28205,6 +28584,8 @@ Type: language
Subtag: pmc
Description: Palumata
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: huw
%%
Type: language
Subtag: pmd
@@ -28285,6 +28666,8 @@ Type: language
Subtag: pmu
Description: Mirpur Panjabi
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: phr
Macrolanguage: lah
%%
Type: language
@@ -28440,6 +28823,7 @@ Type: language
Subtag: pod
Description: Ponares
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: poe
@@ -28536,6 +28920,8 @@ Type: language
Subtag: ppa
Description: Pao
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: bfy
%%
Type: language
Subtag: ppe
@@ -28637,6 +29023,7 @@ Type: language
Subtag: prb
Description: Lua'
Added: 2009-07-29
+Deprecated: 2017-02-23
%%
Type: language
Subtag: prc
@@ -28745,6 +29132,8 @@ Type: language
Subtag: pry
Description: Pray 3
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: prt
%%
Type: language
Subtag: prz
@@ -28779,11 +29168,13 @@ Added: 2009-07-29
%%
Type: language
Subtag: psh
+Description: Southwest Pashai
Description: Southwest Pashayi
Added: 2009-07-29
%%
Type: language
Subtag: psi
+Description: Southeast Pashai
Description: Southeast Pashayi
Added: 2009-07-29
%%
@@ -28879,6 +29270,11 @@ Description: Patep
Added: 2009-07-29
%%
Type: language
+Subtag: ptq
+Description: Pattapu
+Added: 2014-04-06
+%%
+Type: language
Subtag: ptr
Description: Piamatsina
Added: 2009-07-29
@@ -28957,6 +29353,7 @@ Type: language
Subtag: puk
Description: Pu Ko
Added: 2009-07-29
+Deprecated: 2017-02-23
%%
Type: language
Subtag: pum
@@ -29012,6 +29409,8 @@ Type: language
Subtag: puz
Description: Purum Naga
Added: 2009-07-29
+Deprecated: 2014-02-28
+Preferred-Value: pub
%%
Type: language
Subtag: pwa
@@ -29725,6 +30124,7 @@ Type: language
Subtag: rie
Description: Rien
Added: 2009-07-29
+Deprecated: 2017-02-23
%%
Type: language
Subtag: rif
@@ -29950,6 +30350,7 @@ Type: language
Subtag: rna
Description: Runa
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: rnd
@@ -30092,6 +30493,7 @@ Type: language
Subtag: rsi
Description: Rennellese Sign Language
Added: 2009-07-29
+Deprecated: 2017-02-23
%%
Type: language
Subtag: rsl
@@ -30099,6 +30501,11 @@ Description: Russian Sign Language
Added: 2009-07-29
%%
Type: language
+Subtag: rsm
+Description: Miriwoong Sign Language
+Added: 2016-05-30
+%%
+Type: language
Subtag: rtc
Description: Rungtu Chin
Added: 2012-08-12
@@ -30114,6 +30521,11 @@ Description: Rotuman
Added: 2009-07-29
%%
Type: language
+Subtag: rts
+Description: Yurats
+Added: 2015-02-12
+%%
+Type: language
Subtag: rtw
Description: Rathawi
Added: 2009-07-29
@@ -30247,6 +30659,11 @@ Description: Central Okinawan
Added: 2009-07-29
%%
Type: language
+Subtag: rzh
+Description: Rāziḥī
+Added: 2016-05-30
+%%
+Type: language
Subtag: saa
Description: Saba
Added: 2009-07-29
@@ -30317,6 +30734,8 @@ Type: language
Subtag: sap
Description: Sanapaná
Added: 2009-07-29
+Deprecated: 2014-02-28
+Comments: see aqt, spn
%%
Type: language
Subtag: saq
@@ -30395,6 +30814,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: sbf
+Description: Chabu
Description: Shabo
Added: 2009-07-29
%%
@@ -30557,6 +30977,7 @@ Added: 2005-10-16
%%
Type: language
Subtag: scp
+Description: Hyolmo
Description: Helambu Sherpa
Added: 2009-07-29
%%
@@ -30572,6 +30993,11 @@ Added: 2009-07-29
Macrolanguage: den
%%
Type: language
+Subtag: sct
+Description: Southern Katang
+Added: 2017-02-23
+%%
+Type: language
Subtag: scu
Description: Shumcho
Added: 2009-07-29
@@ -30926,6 +31352,7 @@ Type: language
Subtag: sgo
Description: Songa
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: sgp
@@ -31357,6 +31784,8 @@ Type: language
Subtag: skk
Description: Sok
Added: 2009-07-29
+Deprecated: 2017-02-23
+Preferred-Value: oyb
%%
Type: language
Subtag: skm
@@ -31385,6 +31814,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: skr
+Description: Saraiki
Description: Seraiki
Added: 2009-07-29
Macrolanguage: lah
@@ -31690,6 +32120,7 @@ Type: language
Subtag: snh
Description: Shinabo
Added: 2009-07-29
+Deprecated: 2017-02-23
%%
Type: language
Subtag: sni
@@ -31940,6 +32371,11 @@ Description: Akukem
Added: 2009-07-29
%%
Type: language
+Subtag: spn
+Description: Sanapaná
+Added: 2014-02-28
+%%
+Type: language
Subtag: spo
Description: Spokane
Added: 2009-07-29
@@ -32546,6 +32982,7 @@ Type: language
Subtag: svr
Description: Savara
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: svs
@@ -32688,6 +33125,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: sxg
+Description: Shuhi
Description: Shixing
Added: 2009-07-29
%%
@@ -32804,6 +33242,11 @@ Description: Kagate
Added: 2009-07-29
%%
Type: language
+Subtag: syx
+Description: Samay
+Added: 2015-02-12
+%%
+Type: language
Subtag: syy
Description: Al-Sayyid Bedouin Sign Language
Added: 2009-07-29
@@ -32854,6 +33297,11 @@ Description: Suabo
Added: 2009-07-29
%%
Type: language
+Subtag: szs
+Description: Solomon Islands Sign Language
+Added: 2017-02-23
+%%
+Type: language
Subtag: szv
Description: Isu (Fako Division)
Added: 2009-07-29
@@ -33289,6 +33737,11 @@ Description: Sur
Added: 2009-07-29
%%
Type: language
+Subtag: tdm
+Description: Taruma
+Added: 2016-05-30
+%%
+Type: language
Subtag: tdn
Description: Tondano
Added: 2009-07-29
@@ -33322,6 +33775,8 @@ Type: language
Subtag: tdu
Description: Tempasuk Dusun
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: dtp
%%
Type: language
Subtag: tdv
@@ -33457,6 +33912,11 @@ Description: Tulishi
Added: 2009-07-29
%%
Type: language
+Subtag: tez
+Description: Tetserret
+Added: 2018-03-08
+%%
+Type: language
Subtag: tfi
Description: Tofin Gbe
Added: 2009-07-29
@@ -33602,6 +34062,8 @@ Type: language
Subtag: thc
Description: Tai Hang Tong
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tpo
%%
Type: language
Subtag: thd
@@ -33694,6 +34156,8 @@ Type: language
Subtag: thx
Description: The
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: oyb
%%
Type: language
Subtag: thy
@@ -33720,6 +34184,8 @@ Type: language
Subtag: tid
Description: Tidong
Added: 2009-07-29
+Deprecated: 2016-05-30
+Comments: see itd, ntd
%%
Type: language
Subtag: tie
@@ -33963,6 +34429,11 @@ Description: Upper Necaxa Totonac
Added: 2009-07-29
%%
Type: language
+Subtag: tkv
+Description: Mur Pano
+Added: 2014-02-28
+%%
+Type: language
Subtag: tkw
Description: Teanu
Added: 2009-07-29
@@ -34010,7 +34481,7 @@ Added: 2009-07-29
Type: language
Subtag: tlh
Description: Klingon
-Description: tlhIngan-Hol
+Description: tlhIngan Hol
Added: 2005-10-16
%%
Type: language
@@ -34070,6 +34541,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: tlt
+Description: Sou Nama
Description: Teluti
Added: 2009-07-29
%%
@@ -34182,6 +34654,8 @@ Type: language
Subtag: tmp
Description: Tai Mène
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: tyj
%%
Type: language
Subtag: tmq
@@ -34253,6 +34727,8 @@ Type: language
Subtag: tne
Description: Tinoc Kallahan
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: kak
%%
Type: language
Subtag: tnf
@@ -34353,7 +34829,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: tnz
-Description: Tonga (Thailand)
+Description: Ten'edn
Added: 2009-07-29
%%
Type: language
@@ -34375,6 +34851,7 @@ Type: language
Subtag: toe
Description: Tomedes
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: tof
@@ -34796,6 +35273,8 @@ Type: language
Subtag: tsf
Description: Southwestern Tamang
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: taj
%%
Type: language
Subtag: tsg
@@ -35340,6 +35819,11 @@ Description: Ikpeng
Added: 2009-07-29
%%
Type: language
+Subtag: txj
+Description: Tarjumo
+Added: 2015-02-12
+%%
+Type: language
Subtag: txm
Description: Tomini
Added: 2009-07-29
@@ -35413,6 +35897,7 @@ Added: 2009-07-29
Type: language
Subtag: tyj
Description: Tai Do
+Description: Tai Yo
Added: 2009-07-29
%%
Type: language
@@ -35672,6 +36157,11 @@ Description: Ukhwejo
Added: 2009-07-29
%%
Type: language
+Subtag: ukk
+Description: Muak Sa-aak
+Added: 2017-02-23
+%%
+Type: language
Subtag: ukl
Description: Ukrainian Sign Language
Added: 2009-07-29
@@ -35902,6 +36392,8 @@ Type: language
Subtag: uok
Description: Uokha
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: ema
%%
Type: language
Subtag: upi
@@ -36177,7 +36669,9 @@ Added: 2005-10-16
%%
Type: language
Subtag: vaj
-Description: Vasekela Bushman
+Description: Sekele
+Description: Northwestern ǃKung
+Description: Vasekele
Added: 2009-07-29
%%
Type: language
@@ -36801,6 +37295,11 @@ Added: 2009-07-29
Macrolanguage: raj
%%
Type: language
+Subtag: wbs
+Description: West Bengal Sign Language
+Added: 2017-02-23
+%%
+Type: language
Subtag: wbt
Description: Wanman
Added: 2009-07-29
@@ -36981,6 +37480,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: wha
+Description: Sou Upaa
Description: Manusela
Added: 2009-07-29
%%
@@ -37551,6 +38051,12 @@ Description: Warembori
Added: 2009-07-29
%%
Type: language
+Subtag: wsg
+Description: Adilabad Gondi
+Added: 2016-05-30
+Macrolanguage: gon
+%%
+Type: language
Subtag: wsi
Description: Wusi
Added: 2009-07-29
@@ -37778,6 +38284,16 @@ Description: Kaimbé
Added: 2009-07-29
%%
Type: language
+Subtag: xaj
+Description: Ararandewára
+Added: 2014-02-28
+%%
+Type: language
+Subtag: xak
+Description: Máku
+Added: 2016-05-30
+%%
+Type: language
Subtag: xal
Description: Kalmyk
Description: Oirat
@@ -37785,7 +38301,7 @@ Added: 2005-10-16
%%
Type: language
Subtag: xam
-Description: /Xam
+Description: ǀXam
Added: 2009-07-29
%%
Type: language
@@ -37847,6 +38363,8 @@ Type: language
Subtag: xba
Description: Kamba (Brazil)
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: cax
%%
Type: language
Subtag: xbb
@@ -37917,6 +38435,7 @@ Type: language
Subtag: xbx
Description: Kabixí
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: xby
@@ -38020,6 +38539,11 @@ Description: Edomite
Added: 2009-07-29
%%
Type: language
+Subtag: xdo
+Description: Kwandu
+Added: 2017-02-23
+%%
+Type: language
Subtag: xdy
Description: Malayic Dayak
Added: 2009-07-29
@@ -38036,7 +38560,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: xeg
-Description: //Xegwi
+Description: ǁXegwi
Added: 2009-07-29
%%
Type: language
@@ -38116,6 +38640,7 @@ Added: 2009-07-29
%%
Type: language
Subtag: xgm
+Description: Dharumbal
Description: Guwinmal
Added: 2013-09-10
%%
@@ -38212,6 +38737,7 @@ Type: language
Subtag: xip
Description: Xipináwa
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: xir
@@ -38219,6 +38745,11 @@ Description: Xiriâna
Added: 2009-07-29
%%
Type: language
+Subtag: xis
+Description: Kisan
+Added: 2014-02-28
+%%
+Type: language
Subtag: xiv
Description: Indus Valley Language
Added: 2009-07-29
@@ -38277,6 +38808,8 @@ Type: language
Subtag: xkh
Description: Karahawyana
Added: 2009-07-29
+Deprecated: 2016-05-30
+Preferred-Value: waw
%%
Type: language
Subtag: xki
@@ -38890,6 +39423,8 @@ Type: language
Subtag: xsj
Description: Subi
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: suj
%%
Type: language
Subtag: xsl
@@ -39125,6 +39660,7 @@ Added: 2009-07-29
Type: language
Subtag: xuu
Description: Kxoe
+Description: Khwedam
Added: 2009-07-29
%%
Type: language
@@ -39539,6 +40075,7 @@ Type: language
Subtag: yds
Description: Yiddish Sign Language
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: yea
@@ -39638,6 +40175,11 @@ Description: Yagaria
Added: 2009-07-29
%%
Type: language
+Subtag: ygs
+Description: Yolŋu Sign Language
+Added: 2014-02-28
+%%
+Type: language
Subtag: ygu
Description: Yugul
Added: 2013-09-10
@@ -39664,6 +40206,11 @@ Description: Hlepho Phowa
Added: 2009-07-29
%%
Type: language
+Subtag: yhs
+Description: Yan-nhaŋu Sign Language
+Added: 2015-04-17
+%%
+Type: language
Subtag: yia
Description: Yinggarda
Added: 2009-07-29
@@ -39979,6 +40526,8 @@ Type: language
Subtag: ymt
Description: Mator-Taygi-Karagas
Added: 2009-07-29
+Deprecated: 2015-02-12
+Preferred-Value: mtm
%%
Type: language
Subtag: ymx
@@ -40014,6 +40563,7 @@ Type: language
Subtag: ynh
Description: Yangho
Added: 2009-07-29
+Deprecated: 2015-02-12
%%
Type: language
Subtag: ynk
@@ -40177,6 +40727,7 @@ Type: language
Subtag: yri
Description: Yarí
Added: 2009-07-29
+Deprecated: 2016-05-30
%%
Type: language
Subtag: yrk
@@ -40199,6 +40750,11 @@ Description: Yerong
Added: 2009-07-29
%%
Type: language
+Subtag: yro
+Description: Yaroamë
+Added: 2016-05-30
+%%
+Type: language
Subtag: yrs
Description: Yarsun
Added: 2009-07-29
@@ -40313,6 +40869,7 @@ Macrolanguage: jrb
Type: language
Subtag: yue
Description: Yue Chinese
+Description: Cantonese
Added: 2009-07-29
Macrolanguage: zh
%%
@@ -40380,6 +40937,8 @@ Type: language
Subtag: yuu
Description: Yugh
Added: 2009-07-29
+Deprecated: 2014-02-28
+Preferred-Value: yug
%%
Type: language
Subtag: yuw
@@ -40520,6 +41079,7 @@ Macrolanguage: zap
%%
Type: language
Subtag: zab
+Description: Western Tlacolula Valley Zapotec
Description: San Juan Guelavía Zapotec
Added: 2009-07-29
Macrolanguage: zap
@@ -41718,6 +42278,7 @@ Prefix: sgn
%%
Type: extlang
Subtag: asf
+Description: Auslan
Description: Australian Sign Language
Added: 2009-07-29
Preferred-Value: asf
@@ -42215,6 +42776,7 @@ Prefix: sgn
%%
Type: extlang
Subtag: hps
+Description: Hawai'i Sign Language (HSL)
Description: Hawai'i Pidgin Sign Language
Added: 2009-07-29
Preferred-Value: hps
@@ -42250,6 +42812,13 @@ Preferred-Value: icl
Prefix: sgn
%%
Type: extlang
+Subtag: iks
+Description: Inuit Sign Language
+Added: 2015-02-12
+Preferred-Value: iks
+Prefix: sgn
+%%
+Type: extlang
Subtag: ils
Description: International Sign
Added: 2009-07-29
@@ -42405,6 +42974,7 @@ Prefix: sgn
Type: extlang
Subtag: lce
Description: Loncong
+Description: Sekak
Added: 2009-07-29
Preferred-Value: lce
Prefix: ms
@@ -42437,6 +43007,7 @@ Type: extlang
Subtag: lsg
Description: Lyons Sign Language
Added: 2009-07-29
+Deprecated: 2018-03-08
Preferred-Value: lsg
Prefix: sgn
%%
@@ -42493,6 +43064,13 @@ Prefix: lv
Macrolanguage: lv
%%
Type: extlang
+Subtag: lws
+Description: Malawian Sign Language
+Added: 2018-03-08
+Preferred-Value: lws
+Prefix: sgn
+%%
+Type: extlang
Subtag: lzh
Description: Literary Chinese
Added: 2009-07-29
@@ -42725,6 +43303,13 @@ Prefix: ar
Macrolanguage: ar
%%
Type: extlang
+Subtag: pgz
+Description: Papua New Guinean Sign Language
+Added: 2016-05-30
+Preferred-Value: pgz
+Prefix: sgn
+%%
+Type: extlang
Subtag: pks
Description: Pakistan Sign Language
Added: 2009-07-29
@@ -42821,6 +43406,7 @@ Type: extlang
Subtag: rsi
Description: Rennellese Sign Language
Added: 2009-07-29
+Deprecated: 2017-02-23
Preferred-Value: rsi
Prefix: sgn
%%
@@ -42832,6 +43418,13 @@ Preferred-Value: rsl
Prefix: sgn
%%
Type: extlang
+Subtag: rsm
+Description: Miriwoong Sign Language
+Added: 2016-05-30
+Preferred-Value: rsm
+Prefix: sgn
+%%
+Type: extlang
Subtag: sdl
Description: Saudi Arabian Sign Language
Added: 2009-07-29
@@ -42964,6 +43557,13 @@ Preferred-Value: syy
Prefix: sgn
%%
Type: extlang
+Subtag: szs
+Description: Solomon Islands Sign Language
+Added: 2017-02-23
+Preferred-Value: szs
+Prefix: sgn
+%%
+Type: extlang
Subtag: tmw
Description: Temuan
Added: 2009-07-29
@@ -43114,6 +43714,13 @@ Preferred-Value: vsv
Prefix: sgn
%%
Type: extlang
+Subtag: wbs
+Description: West Bengal Sign Language
+Added: 2017-02-23
+Preferred-Value: wbs
+Prefix: sgn
+%%
+Type: extlang
Subtag: wuu
Description: Wu Chinese
Added: 2009-07-29
@@ -43154,10 +43761,25 @@ Type: extlang
Subtag: yds
Description: Yiddish Sign Language
Added: 2009-07-29
+Deprecated: 2015-02-12
Preferred-Value: yds
Prefix: sgn
%%
Type: extlang
+Subtag: ygs
+Description: Yolŋu Sign Language
+Added: 2014-02-28
+Preferred-Value: ygs
+Prefix: sgn
+%%
+Type: extlang
+Subtag: yhs
+Description: Yan-nhaŋu Sign Language
+Added: 2015-04-17
+Preferred-Value: yhs
+Prefix: sgn
+%%
+Type: extlang
Subtag: ysl
Description: Yugoslavian Sign Language
Added: 2009-07-29
@@ -43167,6 +43789,7 @@ Prefix: sgn
Type: extlang
Subtag: yue
Description: Yue Chinese
+Description: Cantonese
Added: 2009-07-29
Preferred-Value: yue
Prefix: zh
@@ -43211,6 +43834,11 @@ Prefix: ms
Macrolanguage: ms
%%
Type: script
+Subtag: Adlm
+Description: Adlam
+Added: 2014-12-11
+%%
+Type: script
Subtag: Afak
Description: Afaka
Added: 2011-01-07
@@ -43221,11 +43849,22 @@ Description: Caucasian Albanian
Added: 2012-11-01
%%
Type: script
+Subtag: Ahom
+Description: Ahom
+Description: Tai Ahom
+Added: 2013-12-02
+%%
+Type: script
Subtag: Arab
Description: Arabic
Added: 2005-10-16
%%
Type: script
+Subtag: Aran
+Description: Arabic (Nastaliq variant)
+Added: 2014-12-11
+%%
+Type: script
Subtag: Armi
Description: Imperial Aramaic
Added: 2007-12-05
@@ -43263,9 +43902,15 @@ Added: 2005-10-16
Type: script
Subtag: Beng
Description: Bengali
+Description: Bangla
Added: 2005-10-16
%%
Type: script
+Subtag: Bhks
+Description: Bhaiksuki
+Added: 2015-07-24
+%%
+Type: script
Subtag: Blis
Description: Blissymbols
Added: 2005-10-16
@@ -43331,8 +43976,13 @@ Description: Coptic
Added: 2005-10-16
%%
Type: script
+Subtag: Cpmn
+Description: Cypro-Minoan
+Added: 2017-08-13
+%%
+Type: script
Subtag: Cprt
-Description: Cypriot
+Description: Cypriot syllabary
Added: 2005-10-16
%%
Type: script
@@ -43352,6 +44002,11 @@ Description: Nagari
Added: 2005-10-16
%%
Type: script
+Subtag: Dogr
+Description: Dogra
+Added: 2017-01-13
+%%
+Type: script
Subtag: Dsrt
Description: Deseret
Description: Mormon
@@ -43384,6 +44039,11 @@ Description: Elbasan
Added: 2010-08-16
%%
Type: script
+Subtag: Elym
+Description: Elymaic
+Added: 2018-10-28
+%%
+Type: script
Subtag: Ethi
Description: Ethiopic
Description: Geʻez
@@ -43397,7 +44057,7 @@ Added: 2005-10-16
%%
Type: script
Subtag: Geor
-Description: Georgian (Mkhedruli)
+Description: Georgian (Mkhedruli and Mtavruli)
Added: 2005-10-16
%%
Type: script
@@ -43406,6 +44066,16 @@ Description: Glagolitic
Added: 2005-10-16
%%
Type: script
+Subtag: Gong
+Description: Gunjala Gondi
+Added: 2017-01-13
+%%
+Type: script
+Subtag: Gonm
+Description: Masaram Gondi
+Added: 2017-01-13
+%%
+Type: script
Subtag: Goth
Description: Gothic
Added: 2005-10-16
@@ -43431,6 +44101,11 @@ Description: Gurmukhi
Added: 2005-10-16
%%
Type: script
+Subtag: Hanb
+Description: Han with Bopomofo (alias for Han + Bopomofo)
+Added: 2016-02-08
+%%
+Type: script
Subtag: Hang
Description: Hangul
Description: Hangŭl
@@ -43462,6 +44137,11 @@ Description: Han (Traditional variant)
Added: 2005-10-16
%%
Type: script
+Subtag: Hatr
+Description: Hatran
+Added: 2013-12-02
+%%
+Type: script
Subtag: Hebr
Description: Hebrew
Added: 2005-10-16
@@ -43484,6 +44164,11 @@ Description: Pahawh Hmong
Added: 2005-10-16
%%
Type: script
+Subtag: Hmnp
+Description: Nyiakeng Puachue Hmong
+Added: 2017-08-13
+%%
+Type: script
Subtag: Hrkt
Description: Japanese syllabaries (alias for Hiragana + Katakana)
Added: 2005-10-16
@@ -43506,6 +44191,11 @@ Description: Old Italic (Etruscan, Oscan, etc.)
Added: 2005-10-16
%%
Type: script
+Subtag: Jamo
+Description: Jamo (alias for Jamo subset of Hangul)
+Added: 2016-02-08
+%%
+Type: script
Subtag: Java
Description: Javanese
Added: 2005-10-16
@@ -43546,6 +44236,16 @@ Description: Khojki
Added: 2011-08-16
%%
Type: script
+Subtag: Kitl
+Description: Khitan large script
+Added: 2014-12-11
+%%
+Type: script
+Subtag: Kits
+Description: Khitan small script
+Added: 2014-12-11
+%%
+Type: script
Subtag: Knda
Description: Kannada
Added: 2005-10-16
@@ -43592,6 +44292,11 @@ Description: Latin
Added: 2005-10-16
%%
Type: script
+Subtag: Leke
+Description: Leke
+Added: 2015-07-24
+%%
+Type: script
Subtag: Lepc
Description: Lepcha
Description: Róng
@@ -43639,6 +44344,11 @@ Description: Mahajani
Added: 2012-11-01
%%
Type: script
+Subtag: Maka
+Description: Makasar
+Added: 2017-01-13
+%%
+Type: script
Subtag: Mand
Description: Mandaic
Description: Mandaean
@@ -43650,13 +44360,25 @@ Description: Manichaean
Added: 2007-07-28
%%
Type: script
+Subtag: Marc
+Description: Marchen
+Added: 2014-12-11
+%%
+Type: script
Subtag: Maya
Description: Mayan hieroglyphs
Added: 2005-10-16
%%
Type: script
+Subtag: Medf
+Description: Medefaidrin
+Description: Oberi Okaime
+Description: Oberi Ɔkaimɛ
+Added: 2017-01-13
+%%
+Type: script
Subtag: Mend
-Description: Mende
+Description: Mende Kikakui
Added: 2010-04-10
%%
Type: script
@@ -43675,6 +44397,12 @@ Description: Malayalam
Added: 2005-10-16
%%
Type: script
+Subtag: Modi
+Description: Modi
+Description: Moḍī
+Added: 2013-12-02
+%%
+Type: script
Subtag: Mong
Description: Mongolian
Added: 2005-10-16
@@ -43701,12 +44429,22 @@ Description: Meetei
Added: 2007-01-26
%%
Type: script
+Subtag: Mult
+Description: Multani
+Added: 2013-12-02
+%%
+Type: script
Subtag: Mymr
Description: Myanmar
Description: Burmese
Added: 2005-10-16
%%
Type: script
+Subtag: Nand
+Description: Nandinagari
+Added: 2018-10-28
+%%
+Type: script
Subtag: Narb
Description: Old North Arabian
Description: Ancient North Arabian
@@ -43718,10 +44456,26 @@ Description: Nabataean
Added: 2010-04-10
%%
Type: script
+Subtag: Newa
+Description: Newa
+Description: Newar
+Description: Newari
+Description: Nepāla lipi
+Added: 2016-01-04
+%%
+Type: script
+Subtag: Nkdb
+Description: Naxi Dongba
+Description: na²¹ɕi³³ to³³ba²¹
+Description: Nakhi Tomba
+Added: 2017-08-13
+%%
+Type: script
Subtag: Nkgb
-Description: Nakhi Geba
-Description: 'Na-'Khi ²Ggŏ-¹baw
Description: Naxi Geba
+Description: na²¹ɕi³³ gʌ²¹ba²¹
+Description: 'Na-'Khi ²Ggŏ-¹baw
+Description: Nakhi Geba
Added: 2009-03-13
%%
Type: script
@@ -43757,9 +44511,15 @@ Added: 2009-07-30
Type: script
Subtag: Orya
Description: Oriya
+Description: Odia
Added: 2005-10-16
%%
Type: script
+Subtag: Osge
+Description: Osage
+Added: 2014-12-11
+%%
+Type: script
Subtag: Osma
Description: Osmanya
Added: 2005-10-16
@@ -43770,6 +44530,11 @@ Description: Palmyrene
Added: 2010-04-10
%%
Type: script
+Subtag: Pauc
+Description: Pau Cin Hau
+Added: 2013-12-02
+%%
+Type: script
Subtag: Perm
Description: Old Permic
Added: 2005-10-16
@@ -43800,6 +44565,11 @@ Description: Phoenician
Added: 2005-10-16
%%
Type: script
+Subtag: Piqd
+Description: Klingon (KLI pIqaD)
+Added: 2016-01-04
+%%
+Type: script
Subtag: Plrd
Description: Miao
Description: Pollard
@@ -43823,6 +44593,11 @@ Description: Kaganga
Added: 2006-10-17
%%
Type: script
+Subtag: Rohg
+Description: Hanifi Rohingya
+Added: 2017-12-13
+%%
+Type: script
Subtag: Roro
Description: Rongorongo
Added: 2005-10-16
@@ -43870,6 +44645,18 @@ Description: Śāradā
Added: 2011-01-07
%%
Type: script
+Subtag: Shui
+Description: Shuishu
+Added: 2017-08-13
+%%
+Type: script
+Subtag: Sidd
+Description: Siddham
+Description: Siddhaṃ
+Description: Siddhamātṛkā
+Added: 2013-12-02
+%%
+Type: script
Subtag: Sind
Description: Khudawadi
Description: Sindhi
@@ -43881,11 +44668,26 @@ Description: Sinhala
Added: 2005-10-16
%%
Type: script
+Subtag: Sogd
+Description: Sogdian
+Added: 2017-12-13
+%%
+Type: script
+Subtag: Sogo
+Description: Old Sogdian
+Added: 2017-12-13
+%%
+Type: script
Subtag: Sora
Description: Sora Sompeng
Added: 2011-01-07
%%
Type: script
+Subtag: Soyo
+Description: Soyombo
+Added: 2017-01-13
+%%
+Type: script
Subtag: Sund
Description: Sundanese
Added: 2006-07-21
@@ -44017,6 +44819,11 @@ Description: Varang Kshiti
Added: 2009-12-09
%%
Type: script
+Subtag: Wcho
+Description: Wancho
+Added: 2017-08-13
+%%
+Type: script
Subtag: Wole
Description: Woleai
Added: 2011-01-07
@@ -44037,6 +44844,14 @@ Description: Yi
Added: 2005-10-16
%%
Type: script
+Subtag: Zanb
+Description: Zanabazar Square
+Description: Zanabazarin Dörböljin Useg
+Description: Xewtee Dörböljin Bicig
+Description: Horizontal Square Script
+Added: 2017-01-13
+%%
+Type: script
Subtag: Zinh
Description: Code for inherited script
Added: 2009-04-03
@@ -44048,6 +44863,11 @@ Description: Mathematical notation
Added: 2007-12-05
%%
Type: script
+Subtag: Zsye
+Description: Symbols (Emoji variant)
+Added: 2016-01-04
+%%
+Type: script
Subtag: Zsym
Description: Symbols
Added: 2007-12-05
@@ -44360,6 +45180,7 @@ Added: 2005-10-16
%%
Type: region
Subtag: CV
+Description: Cabo Verde
Description: Cape Verde
Added: 2005-10-16
%%
@@ -44380,6 +45201,7 @@ Added: 2005-10-16
%%
Type: region
Subtag: CZ
+Description: Czechia
Description: Czech Republic
Added: 2005-10-16
%%
@@ -44471,6 +45293,11 @@ Description: European Union
Added: 2009-07-29
%%
Type: region
+Subtag: EZ
+Description: Eurozone
+Added: 2016-07-14
+%%
+Type: region
Subtag: FI
Description: Finland
Added: 2005-10-16
@@ -45218,6 +46045,8 @@ Added: 2005-10-16
%%
Type: region
Subtag: SZ
+Description: Eswatini
+Description: eSwatini
Description: Swaziland
Added: 2005-10-16
%%
@@ -45329,6 +46158,11 @@ Description: United States Minor Outlying Islands
Added: 2005-10-16
%%
Type: region
+Subtag: UN
+Description: United Nations
+Added: 2016-07-14
+%%
+Type: region
Subtag: US
Description: United States
Added: 2005-10-16
@@ -45594,6 +46428,11 @@ Description: Western Europe
Added: 2005-10-16
%%
Type: region
+Subtag: 202
+Description: Sub-Saharan Africa
+Added: 2017-04-18
+%%
+Type: region
Subtag: 419
Description: Latin America and the Caribbean
Added: 2005-10-16
@@ -45647,6 +46486,15 @@ Added: 2005-10-16
Prefix: de
%%
Type: variant
+Subtag: abl1943
+Description: Orthographic formulation of 1943 - Official in Brazil
+ (Formulário Ortográfico de 1943 - Oficial no Brasil)
+Added: 2015-05-06
+Prefix: pt-BR
+Comments: Denotes conventions established by the Academia Brasileira de
+ Letras in 1943 and generally used in Brazil until 2009
+%%
+Type: variant
Subtag: alalc97
Description: ALA-LC Romanization, 1997 edition
Added: 2009-12-09
@@ -45665,16 +46513,57 @@ Comments: Aluku dialect of the "Busi Nenge Tongo" English-based Creole
continuum in Eastern Suriname and Western French Guiana
%%
Type: variant
+Subtag: akuapem
+Description: Akuapem Twi
+Added: 2017-06-05
+Prefix: tw
+%%
+Type: variant
+Subtag: ao1990
+Description: Portuguese Language Orthographic Agreement of 1990 (Acordo
+ Ortográfico da Língua Portuguesa de 1990)
+Added: 2015-05-06
+Prefix: pt
+Prefix: gl
+Comments: Portuguese orthography conventions established in 1990 but
+ not brought into effect until 2009
+%%
+Type: variant
+Subtag: aranes
+Description: Aranese
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in the Val d'Aran
+%%
+Type: variant
Subtag: arevela
Description: Eastern Armenian
Added: 2006-09-18
+Deprecated: 2018-03-24
Prefix: hy
+Comments: Preferred tag is hy
%%
Type: variant
Subtag: arevmda
Description: Western Armenian
Added: 2006-09-18
+Deprecated: 2018-03-24
Prefix: hy
+Comments: Preferred tag is hyw
+%%
+Type: variant
+Subtag: asante
+Description: Asante Twi
+Description: Ashanti Twi
+Added: 2017-06-05
+Prefix: tw
+%%
+Type: variant
+Subtag: auvern
+Description: Auvergnat
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Auvergne
%%
Type: variant
Subtag: baku1926
@@ -45698,6 +46587,27 @@ Comments: Denotes alphabet used in Turkic republics/regions of the
Jaŋalif (Janalif).
%%
Type: variant
+Subtag: balanka
+Description: The Balanka dialect of Anii
+Added: 2014-02-15
+Prefix: blo
+Comments: Balanka is one of 19 Anii dialects.
+%%
+Type: variant
+Subtag: barla
+Description: The Barlavento dialect group of Kabuverdianu
+Prefix: kea
+Comments: Barlavento is one of the two main dialect groups of
+ Kabuverdianu.
+Added: 2013-12-10
+%%
+Type: variant
+Subtag: basiceng
+Description: Basic English
+Added: 2015-12-29
+Prefix: en
+%%
+Type: variant
Subtag: bauddha
Description: Buddhist Hybrid Sanskrit
Added: 2010-07-28
@@ -45723,9 +46633,9 @@ Subtag: bohoric
Description: Slovene in Bohorič alphabet
Added: 2012-06-27
Prefix: sl
-Comments: The subtag represents the alphabet codified by Adam Bohorič in
- 1584 and used from the first printed Slovene book and up to the mid-
- 19th century.
+Comments: The subtag represents the alphabet codified by Adam Bohorič
+ in 1584 and used from the first printed Slovene book and up to the
+ mid-19th century.
%%
Type: variant
Subtag: boont
@@ -45735,6 +46645,43 @@ Prefix: en
Comments: Jargon embedded in American English
%%
Type: variant
+Subtag: bornholm
+Description: Bornholmsk
+Added: 2019-03-27
+Prefix: da
+%%
+Type: variant
+Subtag: cisaup
+Description: Cisalpine
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in northwestern Italy
+%%
+Type: variant
+Subtag: colb1945
+Description: Portuguese-Brazilian Orthographic Convention of 1945
+ (Convenção Ortográfica Luso-Brasileira de 1945)
+Added: 2015-05-06
+Prefix: pt
+Comments: Portuguese orthography conventions established in 1945,
+ generally in effect until 2009. This reform was not ratified in
+ Brazil.
+%%
+Type: variant
+Subtag: cornu
+Description: Cornu-English
+Description: Cornish English
+Description: Anglo-Cornish
+Added: 2015-12-07
+Prefix: en
+%%
+Type: variant
+Subtag: creiss
+Description: Occitan variants of the Croissant area
+Added: 2018-04-22
+Prefix: oc
+%%
+Type: variant
Subtag: dajnko
Description: Slovene in Dajnko alphabet
Added: 2012-06-27
@@ -45744,6 +46691,14 @@ Comments: The subtag represents the alphabet codified by Peter Dajnko
Slovenia).
%%
Type: variant
+Subtag: ekavsk
+Description: Serbian with Ekavian pronunciation
+Prefix: sr
+Prefix: sr-Latn
+Prefix: sr-Cyrl
+Added: 2013-12-02
+%%
+Type: variant
Subtag: emodeng
Description: Early Modern English (1500-1700)
Added: 2012-02-05
@@ -45755,6 +46710,17 @@ Description: International Phonetic Alphabet
Added: 2006-12-11
%%
Type: variant
+Subtag: fonkirsh
+Description: Kirshenbaum Phonetic Alphabet
+Added: 2018-04-22
+%%
+Type: variant
+Subtag: fonnapa
+Description: North American Phonetic Alphabet
+Description: Americanist Phonetic Notation
+Added: 2016-06-24
+%%
+Type: variant
Subtag: fonupa
Description: Uralic Phonetic Alphabet
Added: 2006-12-11
@@ -45766,6 +46732,36 @@ Added: 2010-10-23
Comments: Indicates that the content is transcribed according to X-SAMPA
%%
Type: variant
+Subtag: gascon
+Description: Gascon
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Gascony
+%%
+Type: variant
+Subtag: grclass
+Description: Classical Occitan orthography
+Added: 2018-04-22
+Prefix: oc
+Comments: Classical written standard for Occitan developed in 1935 by
+ Alibèrt
+%%
+Type: variant
+Subtag: grital
+Description: Italian-inspired Occitan orthography
+Added: 2018-04-22
+Prefix: oc
+%%
+Type: variant
+Subtag: grmistr
+Description: Mistralian or Mistralian-inspired Occitan orthography
+Added: 2018-04-22
+Prefix: oc
+Comments: Written standard developed by Romanilha in 1853 and used by
+ Mistral and the Félibres, including derived standards such as Escolo
+ dóu Po, Escolo Gaston Febus, and others
+%%
+Type: variant
Subtag: hepburn
Description: Hepburn romanization
Added: 2009-10-01
@@ -45789,12 +46785,34 @@ Comments: Norwegian following Ivar Aasen's orthographical principles,
including modern usage.
%%
Type: variant
+Subtag: hsistemo
+Description: Standard H-system orthographic fallback for spelling
+ Esperanto
+Added: 2017-03-14
+Prefix: eo
+%%
+Type: variant
+Subtag: ijekavsk
+Description: Serbian with Ijekavian pronunciation
+Prefix: sr
+Prefix: sr-Latn
+Prefix: sr-Cyrl
+Added: 2013-12-02
+%%
+Type: variant
Subtag: itihasa
Description: Epic Sanskrit
Added: 2010-07-28
Prefix: sa
%%
Type: variant
+Subtag: ivanchov
+Description: Bulgarian in 1899 orthography
+Added: 2017-12-13
+Prefix: bg
+Comments: Bulgarian orthography introduced by Todor Ivanchov in 1899
+%%
+Type: variant
Subtag: jauer
Description: Jauer dialect of Romansh
Added: 2010-06-29
@@ -45816,6 +46834,14 @@ Added: 2008-10-14
Prefix: kw
%%
Type: variant
+Subtag: kociewie
+Description: The Kociewie dialect of Polish
+Added: 2014-11-27
+Prefix: pl
+Comments: The dialect of Kociewie is spoken in the region around
+ Starogard Gdański, Tczew and Świecie in northern Poland.
+%%
+Type: variant
Subtag: kscor
Description: Standard Cornish orthography of Revived Cornish
Description: Kernowek Standard
@@ -45829,6 +46855,20 @@ Added: 2010-07-28
Prefix: sa
%%
Type: variant
+Subtag: lemosin
+Description: Limousin
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Limousin
+%%
+Type: variant
+Subtag: lengadoc
+Description: Languedocien
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Languedoc
+%%
+Type: variant
Subtag: lipaw
Description: The Lipovaz dialect of Resian
Description: The Lipovec dialect of Resian
@@ -45876,6 +46916,19 @@ Added: 2005-10-16
Prefix: sl
%%
Type: variant
+Subtag: newfound
+Description: Newfoundland English
+Added: 2015-11-25
+Prefix: en-CA
+%%
+Type: variant
+Subtag: nicard
+Description: Niçard
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Nice
+%%
+Type: variant
Subtag: njiva
Description: The Gniva dialect of Resian
Description: The Njiva dialect of Resian
@@ -45906,6 +46959,33 @@ Comments: The dialect of Oseacco/Osojane is one of the four major local
dialects of Resian
%%
Type: variant
+Subtag: oxendict
+Description: Oxford English Dictionary spelling
+Added: 2015-04-17
+Prefix: en
+%%
+Type: variant
+Subtag: pahawh2
+Description: Pahawh Hmong Second Stage Reduced orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
+Subtag: pahawh3
+Description: Pahawh Hmong Third Stage Reduced orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
+Subtag: pahawh4
+Description: Pahawh Hmong Final Version orthography
+Added: 2017-01-13
+Prefix: mww
+Prefix: hnj
+%%
+Type: variant
Subtag: pamaka
Description: Pamaka dialect
Added: 2009-09-05
@@ -45935,6 +47015,13 @@ Added: 2006-12-11
Prefix: el
%%
Type: variant
+Subtag: provenc
+Description: Provençal
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in Provence
+%%
+Type: variant
Subtag: puter
Description: Puter idiom of Romansh
Added: 2010-06-29
@@ -45980,6 +47067,11 @@ Prefix: en
Comments: English Liverpudlian dialect known as 'Scouse'
%%
Type: variant
+Subtag: simple
+Description: Simplified form
+Added: 2015-12-29
+%%
+Type: variant
Subtag: solba
Description: The Stolvizza dialect of Resian
Description: The Solbica dialect of Resian
@@ -45989,6 +47081,22 @@ Comments: The dialect of Stolvizza/Solbica is one of the four major
local dialects of Resian
%%
Type: variant
+Subtag: sotav
+Description: The Sotavento dialect group of Kabuverdianu
+Prefix: kea
+Comments: Sotavento is one of the two main dialect groups of
+ Kabuverdianu.
+Added: 2013-12-10
+%%
+Type: variant
+Subtag: spanglis
+Description: Spanglish
+Added: 2017-02-23
+Prefix: en
+Prefix: es
+Comments: A variety of contact dialects of English and Spanish
+%%
+Type: variant
Subtag: surmiran
Description: Surmiran idiom of Romansh
Added: 2010-06-29
@@ -46041,6 +47149,16 @@ Added: 2010-04-10
Prefix: sco
%%
Type: variant
+Subtag: unifon
+Description: Unifon phonetic alphabet
+Added: 2013-10-02
+Prefix: en
+Prefix: hup
+Prefix: kyh
+Prefix: tol
+Prefix: yur
+%%
+Type: variant
Subtag: vaidika
Description: Vedic Sanskrit
Added: 2010-07-28
@@ -46065,11 +47183,25 @@ Comments: Vallader is one of the five traditional written standards or
"idioms" of the Romansh language.
%%
Type: variant
+Subtag: vivaraup
+Description: Vivaro-Alpine
+Added: 2018-04-22
+Prefix: oc
+Comments: Occitan variant spoken in northeastern Occitania
+%%
+Type: variant
Subtag: wadegile
Description: Wade-Giles romanization
Added: 2008-10-03
Prefix: zh-Latn
%%
+Type: variant
+Subtag: xsistemo
+Description: Standard X-system orthographic fallback for spelling
+ Esperanto
+Added: 2017-03-14
+Prefix: eo
+%%
Type: grandfathered
Tag: art-lojban
Description: Lojban
@@ -46081,11 +47213,15 @@ Type: grandfathered
Tag: cel-gaulish
Description: Gaulish
Added: 2001-05-25
+Deprecated: 2015-03-29
+Comments: see xcg, xga, xtg
%%
Type: grandfathered
Tag: en-GB-oed
Description: English, Oxford English Dictionary spelling
Added: 2003-07-09
+Deprecated: 2015-04-17
+Preferred-Value: en-GB-oxendict
%%
Type: grandfathered
Tag: i-ami
@@ -46110,6 +47246,7 @@ Type: grandfathered
Tag: i-enochian
Description: Enochian
Added: 2002-07-03
+Deprecated: 2015-03-29
%%
Type: grandfathered
Tag: i-hak
@@ -46226,6 +47363,7 @@ Tag: zh-min
Description: Min, Fuzhou, Hokkien, Amoy, or Taiwanese
Added: 1999-12-18
Deprecated: 2009-07-29
+Comments: see cdo, cpx, czo, mnp, nan
%%
Type: grandfathered
Tag: zh-min-nan
diff --git a/make/data/tzdata/VERSION b/make/data/tzdata/VERSION
index e3fa9222bc..1be80d5b5f 100644
--- a/make/data/tzdata/VERSION
+++ b/make/data/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2018g
+tzdata2019c
diff --git a/make/data/tzdata/africa b/make/data/tzdata/africa
index e2ffac25ec..5b344843a0 100644
--- a/make/data/tzdata/africa
+++ b/make/data/tzdata/africa
@@ -112,7 +112,7 @@ Rule Algeria 1980 only - Apr 25 0:00 1:00 S
Rule Algeria 1980 only - Oct 31 2:00 0 -
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
# more precise 0:09:21.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01
0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
0:00 Algeria WE%sT 1940 Feb 25 2:00
@@ -147,7 +147,7 @@ Zone Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:01
# For now, ignore that and follow the 1911-05-26 Portuguese decree
# (see Europe/Lisbon).
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Atlantic/Cape_Verde -1:34:04 - LMT 1912 Jan 01 2:00u # Praia
-2:00 - -02 1942 Sep
-2:00 1:00 -01 1945 Oct 15
@@ -158,7 +158,7 @@ Zone Atlantic/Cape_Verde -1:34:04 - LMT 1912 Jan 01 2:00u # Praia
# See Africa/Lagos.
# Chad
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Ndjamena 1:00:12 - LMT 1912 # N'Djamena
1:00 - WAT 1979 Oct 14
1:00 1:00 WAST 1980 Mar 8
@@ -174,7 +174,7 @@ Zone Africa/Ndjamena 1:00:12 - LMT 1912 # N'Djamena
# See Africa/Lagos.
# Côte d'Ivoire / Ivory Coast
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Abidjan -0:16:08 - LMT 1912
0:00 - GMT
Link Africa/Abidjan Africa/Bamako # Mali
@@ -379,7 +379,7 @@ Rule Egypt 2014 only - Jun 26 24:00 0 -
Rule Egypt 2014 only - Jul 31 24:00 1:00 S
Rule Egypt 2014 only - Sep lastThu 24:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
2:00 Egypt EE%sT
@@ -387,6 +387,11 @@ Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
# See Africa/Lagos.
# Eritrea
+# See Africa/Nairobi.
+
+# Eswatini (formerly Swaziland)
+# See Africa/Johannesburg.
+
# Ethiopia
# See Africa/Nairobi.
#
@@ -432,7 +437,7 @@ Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Ghana 1920 1942 - Sep 1 0:00 0:20 -
Rule Ghana 1920 1942 - Dec 31 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Accra -0:00:52 - LMT 1918
0:00 Ghana GMT/+0020
@@ -446,13 +451,13 @@ Zone Africa/Accra -0:00:52 - LMT 1918
# evidently confusing the date of the Portuguese decree
# (see Europe/Lisbon) with the date that it took effect.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Bissau -1:02:20 - LMT 1912 Jan 1 1:00u
-1:00 - -01 1975
0:00 - GMT
# Kenya
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Nairobi 2:27:16 - LMT 1928 Jul
3:00 - EAT 1930
2:30 - +0230 1940
@@ -487,7 +492,7 @@ Link Africa/Nairobi Indian/Mayotte
# Use the abbreviation "MMT" before 1972, as the more-accurate numeric
# abbreviation "-004430" would be one byte over the POSIX limit.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Monrovia -0:43:08 - LMT 1882
-0:43:08 - MMT 1919 Mar # Monrovia Mean Time
-0:44:30 - MMT 1972 Jan 7 # approximately MMT
@@ -537,7 +542,7 @@ Rule Libya 1997 only - Apr 4 0:00 1:00 S
Rule Libya 1997 only - Oct 4 0:00 0 -
Rule Libya 2013 only - Mar lastFri 1:00 1:00 S
Rule Libya 2013 only - Oct lastFri 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Tripoli 0:52:44 - LMT 1920
1:00 Libya CE%sT 1959
2:00 - EET 1982
@@ -647,7 +652,7 @@ Rule Mauritius 1982 only - Oct 10 0:00 1:00 -
Rule Mauritius 1983 only - Mar 21 0:00 0 -
Rule Mauritius 2008 only - Oct lastSun 2:00 1:00 -
Rule Mauritius 2009 only - Mar lastSun 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
4:00 Mauritius +04/+05
# Agalega Is, Rodriguez
@@ -870,8 +875,47 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
# From Mohamed Essedik Najd (2018-10-26):
# Today, a Moroccan government council approved the perpetual addition
# of 60 minutes to the regular Moroccan timezone.
-# From Brian Inglis (2018-10-26):
-# http://www.maroc.ma/fr/actualites/le-conseil-de-gouvernement-adopte-un-projet-de-decret-relatif-lheure-legale-stipulant-le
+# From Matt Johnson (2018-10-28):
+# http://www.sgg.gov.ma/Portals/1/BO/2018/BO_6720-bis_Ar.pdf
+#
+# From Maamar Abdelkader (2018-11-01):
+# We usually move clocks back the previous week end and come back to the +1
+# the week end after.... The government does not announce yet the decision
+# about this temporary change. But it s 99% sure that it will be the case,
+# as in previous years. An unofficial survey was done these days, showing
+# that 64% of asked people are ok for moving from +1 to +0 during Ramadan.
+# https://leconomiste.com/article/1035870-enquete-l-economiste-sunergia-64-des-marocains-plebiscitent-le-gmt-pendant-ramadan
+
+# From Naoufal Semlali (2019-04-16):
+# Morocco will be on GMT starting from Sunday, May 5th 2019 at 3am.
+# The switch to GMT+1 will occur on Sunday, June 9th 2019 at 2am....
+# http://fr.le360.ma/societe/voici-la-date-du-retour-a-lheure-legale-au-maroc-188222
+#
+# From Paul Eggert (2019-05-20):
+# This agrees with our 2018-11-01 guess that the Moroccan government
+# would continue the practice of falling back at 03:00 the last Sunday
+# before Ramadan, and of springing forward at 02:00 the first Sunday after
+# Ramadan, as this has been the practice since 2012. To implement this,
+# transition dates for 2019 through 2087 were determined by running the
+# following program under GNU Emacs 26.2.
+# (let ((islamic-year 1440))
+# (require 'cal-islam)
+# (while (< islamic-year 1511)
+# (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+# (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+# (sunday 0))
+# (while (/= sunday (mod (setq a (1- a)) 7)))
+# (while (/= sunday (mod b 7))
+# (setq b (1+ b)))
+# (setq a (calendar-gregorian-from-absolute a))
+# (setq b (calendar-gregorian-from-absolute b))
+# (insert
+# (format
+# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t-1:00\t-\n"
+# "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t0\t-\n")
+# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# (setq islamic-year (+ 1 islamic-year))))
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 -
@@ -903,7 +947,7 @@ Rule Morocco 2012 only - Aug 20 2:00 1:00 -
Rule Morocco 2012 only - Sep 30 3:00 0 -
Rule Morocco 2013 only - Jul 7 3:00 0 -
Rule Morocco 2013 only - Aug 10 2:00 1:00 -
-Rule Morocco 2013 2018 - Oct lastSun 3:00 0 -
+Rule Morocco 2013 2017 - Oct lastSun 3:00 0 -
Rule Morocco 2014 2018 - Mar lastSun 2:00 1:00 -
Rule Morocco 2014 only - Jun 28 3:00 0 -
Rule Morocco 2014 only - Aug 2 2:00 1:00 -
@@ -915,13 +959,159 @@ Rule Morocco 2017 only - May 21 3:00 0 -
Rule Morocco 2017 only - Jul 2 2:00 1:00 -
Rule Morocco 2018 only - May 13 3:00 0 -
Rule Morocco 2018 only - Jun 17 2:00 1:00 -
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Rule Morocco 2019 only - May 5 3:00 0 -
+Rule Morocco 2019 only - Jun 9 2:00 1:00 -
+Rule Morocco 2020 only - Apr 19 3:00 0 -
+Rule Morocco 2020 only - May 24 2:00 1:00 -
+Rule Morocco 2021 only - Apr 11 3:00 0 -
+Rule Morocco 2021 only - May 16 2:00 1:00 -
+Rule Morocco 2022 only - Mar 27 3:00 0 -
+Rule Morocco 2022 only - May 8 2:00 1:00 -
+Rule Morocco 2023 only - Mar 19 3:00 0 -
+Rule Morocco 2023 only - Apr 23 2:00 1:00 -
+Rule Morocco 2024 only - Mar 10 3:00 0 -
+Rule Morocco 2024 only - Apr 14 2:00 1:00 -
+Rule Morocco 2025 only - Feb 23 3:00 0 -
+Rule Morocco 2025 only - Apr 6 2:00 1:00 -
+Rule Morocco 2026 only - Feb 15 3:00 0 -
+Rule Morocco 2026 only - Mar 22 2:00 1:00 -
+Rule Morocco 2027 only - Feb 7 3:00 0 -
+Rule Morocco 2027 only - Mar 14 2:00 1:00 -
+Rule Morocco 2028 only - Jan 23 3:00 0 -
+Rule Morocco 2028 only - Feb 27 2:00 1:00 -
+Rule Morocco 2029 only - Jan 14 3:00 0 -
+Rule Morocco 2029 only - Feb 18 2:00 1:00 -
+Rule Morocco 2029 only - Dec 30 3:00 0 -
+Rule Morocco 2030 only - Feb 10 2:00 1:00 -
+Rule Morocco 2030 only - Dec 22 3:00 0 -
+Rule Morocco 2031 only - Jan 26 2:00 1:00 -
+Rule Morocco 2031 only - Dec 14 3:00 0 -
+Rule Morocco 2032 only - Jan 18 2:00 1:00 -
+Rule Morocco 2032 only - Nov 28 3:00 0 -
+Rule Morocco 2033 only - Jan 9 2:00 1:00 -
+Rule Morocco 2033 only - Nov 20 3:00 0 -
+Rule Morocco 2033 only - Dec 25 2:00 1:00 -
+Rule Morocco 2034 only - Nov 5 3:00 0 -
+Rule Morocco 2034 only - Dec 17 2:00 1:00 -
+Rule Morocco 2035 only - Oct 28 3:00 0 -
+Rule Morocco 2035 only - Dec 2 2:00 1:00 -
+Rule Morocco 2036 only - Oct 19 3:00 0 -
+Rule Morocco 2036 only - Nov 23 2:00 1:00 -
+Rule Morocco 2037 only - Oct 4 3:00 0 -
+Rule Morocco 2037 only - Nov 15 2:00 1:00 -
+Rule Morocco 2038 only - Sep 26 3:00 0 -
+Rule Morocco 2038 only - Oct 31 2:00 1:00 -
+Rule Morocco 2039 only - Sep 18 3:00 0 -
+Rule Morocco 2039 only - Oct 23 2:00 1:00 -
+Rule Morocco 2040 only - Sep 2 3:00 0 -
+Rule Morocco 2040 only - Oct 14 2:00 1:00 -
+Rule Morocco 2041 only - Aug 25 3:00 0 -
+Rule Morocco 2041 only - Sep 29 2:00 1:00 -
+Rule Morocco 2042 only - Aug 10 3:00 0 -
+Rule Morocco 2042 only - Sep 21 2:00 1:00 -
+Rule Morocco 2043 only - Aug 2 3:00 0 -
+Rule Morocco 2043 only - Sep 6 2:00 1:00 -
+Rule Morocco 2044 only - Jul 24 3:00 0 -
+Rule Morocco 2044 only - Aug 28 2:00 1:00 -
+Rule Morocco 2045 only - Jul 9 3:00 0 -
+Rule Morocco 2045 only - Aug 20 2:00 1:00 -
+Rule Morocco 2046 only - Jul 1 3:00 0 -
+Rule Morocco 2046 only - Aug 5 2:00 1:00 -
+Rule Morocco 2047 only - Jun 23 3:00 0 -
+Rule Morocco 2047 only - Jul 28 2:00 1:00 -
+Rule Morocco 2048 only - Jun 7 3:00 0 -
+Rule Morocco 2048 only - Jul 19 2:00 1:00 -
+Rule Morocco 2049 only - May 30 3:00 0 -
+Rule Morocco 2049 only - Jul 4 2:00 1:00 -
+Rule Morocco 2050 only - May 15 3:00 0 -
+Rule Morocco 2050 only - Jun 26 2:00 1:00 -
+Rule Morocco 2051 only - May 7 3:00 0 -
+Rule Morocco 2051 only - Jun 11 2:00 1:00 -
+Rule Morocco 2052 only - Apr 28 3:00 0 -
+Rule Morocco 2052 only - Jun 2 2:00 1:00 -
+Rule Morocco 2053 only - Apr 13 3:00 0 -
+Rule Morocco 2053 only - May 25 2:00 1:00 -
+Rule Morocco 2054 only - Apr 5 3:00 0 -
+Rule Morocco 2054 only - May 10 2:00 1:00 -
+Rule Morocco 2055 only - Mar 28 3:00 0 -
+Rule Morocco 2055 only - May 2 2:00 1:00 -
+Rule Morocco 2056 only - Mar 12 3:00 0 -
+Rule Morocco 2056 only - Apr 23 2:00 1:00 -
+Rule Morocco 2057 only - Mar 4 3:00 0 -
+Rule Morocco 2057 only - Apr 8 2:00 1:00 -
+Rule Morocco 2058 only - Feb 17 3:00 0 -
+Rule Morocco 2058 only - Mar 31 2:00 1:00 -
+Rule Morocco 2059 only - Feb 9 3:00 0 -
+Rule Morocco 2059 only - Mar 16 2:00 1:00 -
+Rule Morocco 2060 only - Feb 1 3:00 0 -
+Rule Morocco 2060 only - Mar 7 2:00 1:00 -
+Rule Morocco 2061 only - Jan 16 3:00 0 -
+Rule Morocco 2061 only - Feb 27 2:00 1:00 -
+Rule Morocco 2062 only - Jan 8 3:00 0 -
+Rule Morocco 2062 only - Feb 12 2:00 1:00 -
+Rule Morocco 2062 only - Dec 31 3:00 0 -
+Rule Morocco 2063 only - Feb 4 2:00 1:00 -
+Rule Morocco 2063 only - Dec 16 3:00 0 -
+Rule Morocco 2064 only - Jan 20 2:00 1:00 -
+Rule Morocco 2064 only - Dec 7 3:00 0 -
+Rule Morocco 2065 only - Jan 11 2:00 1:00 -
+Rule Morocco 2065 only - Nov 22 3:00 0 -
+Rule Morocco 2066 only - Jan 3 2:00 1:00 -
+Rule Morocco 2066 only - Nov 14 3:00 0 -
+Rule Morocco 2066 only - Dec 19 2:00 1:00 -
+Rule Morocco 2067 only - Nov 6 3:00 0 -
+Rule Morocco 2067 only - Dec 11 2:00 1:00 -
+Rule Morocco 2068 only - Oct 21 3:00 0 -
+Rule Morocco 2068 only - Dec 2 2:00 1:00 -
+Rule Morocco 2069 only - Oct 13 3:00 0 -
+Rule Morocco 2069 only - Nov 17 2:00 1:00 -
+Rule Morocco 2070 only - Oct 5 3:00 0 -
+Rule Morocco 2070 only - Nov 9 2:00 1:00 -
+Rule Morocco 2071 only - Sep 20 3:00 0 -
+Rule Morocco 2071 only - Oct 25 2:00 1:00 -
+Rule Morocco 2072 only - Sep 11 3:00 0 -
+Rule Morocco 2072 only - Oct 16 2:00 1:00 -
+Rule Morocco 2073 only - Aug 27 3:00 0 -
+Rule Morocco 2073 only - Oct 8 2:00 1:00 -
+Rule Morocco 2074 only - Aug 19 3:00 0 -
+Rule Morocco 2074 only - Sep 23 2:00 1:00 -
+Rule Morocco 2075 only - Aug 11 3:00 0 -
+Rule Morocco 2075 only - Sep 15 2:00 1:00 -
+Rule Morocco 2076 only - Jul 26 3:00 0 -
+Rule Morocco 2076 only - Sep 6 2:00 1:00 -
+Rule Morocco 2077 only - Jul 18 3:00 0 -
+Rule Morocco 2077 only - Aug 22 2:00 1:00 -
+Rule Morocco 2078 only - Jul 10 3:00 0 -
+Rule Morocco 2078 only - Aug 14 2:00 1:00 -
+Rule Morocco 2079 only - Jun 25 3:00 0 -
+Rule Morocco 2079 only - Jul 30 2:00 1:00 -
+Rule Morocco 2080 only - Jun 16 3:00 0 -
+Rule Morocco 2080 only - Jul 21 2:00 1:00 -
+Rule Morocco 2081 only - Jun 1 3:00 0 -
+Rule Morocco 2081 only - Jul 13 2:00 1:00 -
+Rule Morocco 2082 only - May 24 3:00 0 -
+Rule Morocco 2082 only - Jun 28 2:00 1:00 -
+Rule Morocco 2083 only - May 16 3:00 0 -
+Rule Morocco 2083 only - Jun 20 2:00 1:00 -
+Rule Morocco 2084 only - Apr 30 3:00 0 -
+Rule Morocco 2084 only - Jun 11 2:00 1:00 -
+Rule Morocco 2085 only - Apr 22 3:00 0 -
+Rule Morocco 2085 only - May 27 2:00 1:00 -
+Rule Morocco 2086 only - Apr 14 3:00 0 -
+Rule Morocco 2086 only - May 19 2:00 1:00 -
+Rule Morocco 2087 only - Mar 30 3:00 0 -
+Rule Morocco 2087 only - May 4 2:00 1:00 -
+# For dates after the somewhat-arbitrary cutoff of 2087, assume that
+# Morocco will no longer observe DST. At some point this table will
+# need to be extended, though quite possibly Morocco will change the
+# rules first.
+
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
0:00 Morocco +00/+01 1984 Mar 16
1:00 - +01 1986
- 0:00 Morocco +00/+01 2018 Oct 27
- 1:00 - +01
+ 0:00 Morocco +00/+01 2018 Oct 28 3:00
+ 0:00 Morocco +00/+01
# Western Sahara
#
@@ -936,8 +1126,8 @@ Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún
-1:00 - -01 1976 Apr 14
- 0:00 Morocco +00/+01 2018 Oct 27
- 1:00 - +01
+ 0:00 Morocco +00/+01 2018 Oct 28 3:00
+ 0:00 Morocco +00/+01
# Mozambique
#
@@ -946,7 +1136,7 @@ Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún
# https://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
# merely made it official?
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Maputo 2:10:20 - LMT 1903 Mar
2:00 - CAT
Link Africa/Maputo Africa/Blantyre # Malawi
@@ -1018,7 +1208,7 @@ Rule Namibia 1994 2017 - Sep Sun>=1 2:00 1:00 CAT
Rule Namibia 1995 2017 - Apr Sun>=1 2:00 0 WAT
# End of rearguard section.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8
1:30 - +0130 1903 Mar
2:00 - SAST 1942 Sep 20 2:00
@@ -1039,7 +1229,7 @@ Zone Africa/Windhoek 1:08:24 - LMT 1892 Feb 8
# See Africa/Lagos.
# Nigeria
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Lagos 0:13:36 - LMT 1919 Sep
1:00 - WAT
Link Africa/Lagos Africa/Bangui # Central African Republic
@@ -1053,7 +1243,7 @@ Link Africa/Lagos Africa/Niamey # Niger
Link Africa/Lagos Africa/Porto-Novo # Benin
# Réunion
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis
4:00 - +04
#
@@ -1094,16 +1284,26 @@ Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis
# the switch is from 01:00 to 02:00 ... [Decree No. 25/2017]
# http://www.mnec.gov.st/index.php/publicacoes/documentos/file/90-decreto-lei-n-25-2017
+# From Vadim Nasardinov (2018-12-29):
+# São Tomé and Príncipe is about to do the following on Jan 1, 2019:
+# https://www.stp-press.st/2018/12/05/governo-jesus-ja-decidiu-repor-hora-legal-sao-tomense/
+#
+# From Michael Deckers (2018-12-30):
+# https://www.legis-palop.org/download.jsp?idFile=102818
+# ... [The legal time of the country, which coincides with universal
+# coordinated time, will be restituted at 2 o'clock on day 1 of January, 2019.]
+
Zone Africa/Sao_Tome 0:26:56 - LMT 1884
-0:36:45 - LMT 1912 Jan 1 00:00u # Lisbon MT
0:00 - GMT 2018 Jan 1 01:00
- 1:00 - WAT
+ 1:00 - WAT 2019 Jan 1 02:00
+ 0:00 - GMT
# Senegal
# See Africa/Abidjan.
# Seychelles
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria
4:00 - +04
# From Paul Eggert (2001-05-30):
@@ -1123,12 +1323,12 @@ Zone Indian/Mahe 3:41:48 - LMT 1906 Jun # Victoria
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule SA 1942 1943 - Sep Sun>=15 2:00 1:00 -
Rule SA 1943 1944 - Mar Sun>=15 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8
1:30 - SAST 1903 Mar
2:00 SA SAST
Link Africa/Johannesburg Africa/Maseru # Lesotho
-Link Africa/Johannesburg Africa/Mbabane # Swaziland
+Link Africa/Johannesburg Africa/Mbabane # Eswatini
#
# Marion and Prince Edward Is
# scientific station since 1947
@@ -1158,21 +1358,18 @@ Rule Sudan 1970 only - May 1 0:00 1:00 S
Rule Sudan 1970 1985 - Oct 15 0:00 0 -
Rule Sudan 1971 only - Apr 30 0:00 1:00 S
Rule Sudan 1972 1985 - Apr lastSun 0:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Khartoum 2:10:08 - LMT 1931
2:00 Sudan CA%sT 2000 Jan 15 12:00
3:00 - EAT 2017 Nov 1
2:00 - CAT
# South Sudan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Juba 2:06:28 - LMT 1931
2:00 Sudan CA%sT 2000 Jan 15 12:00
3:00 - EAT
-# Swaziland
-# See Africa/Johannesburg.
-
# Tanzania
# See Africa/Nairobi.
@@ -1274,7 +1471,7 @@ Rule Tunisia 2006 2008 - Oct lastSun 2:00s 0 -
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
# more precise 0:09:21.
# Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Africa/Tunis 0:40:44 - LMT 1881 May 12
0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
1:00 Tunisia CE%sT
diff --git a/make/data/tzdata/antarctica b/make/data/tzdata/antarctica
index d98afed9b8..6239f837e9 100644
--- a/make/data/tzdata/antarctica
+++ b/make/data/tzdata/antarctica
@@ -36,7 +36,7 @@
# for information.
# Unless otherwise specified, we have no time zone information.
-# FORMAT is '-00' and GMTOFF is 0 for locations while uninhabited.
+# FORMAT is '-00' and STDOFF is 0 for locations while uninhabited.
# Argentina - year-round bases
# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -93,7 +93,7 @@
# Australian Antarctica Division informed us that Casey changed time
# zone to UTC+11 in "the morning of 22nd October 2016".
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - -00 1969
8:00 - +08 2009 Oct 18 2:00
11:00 - +11 2010 Mar 5 2:00
@@ -165,7 +165,7 @@ Zone Antarctica/Mawson 0 - -00 1954 Feb 13
# St Paul Island - near Amsterdam, uninhabited
# fishing stations operated variously 1819/1931
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
5:00 - +05
#
@@ -176,7 +176,7 @@ Zone Indian/Kerguelen 0 - -00 1950 # Port-aux-Français
# Another base at Port-Martin, 50km east, began operation in 1947.
# It was destroyed by fire on 1952-01-14.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/DumontDUrville 0 - -00 1947
10:00 - +10 1952 Jan 14
0 - -00 1956 Nov
@@ -204,7 +204,7 @@ Zone Antarctica/DumontDUrville 0 - -00 1947
# Syowa station, which is the first antarctic station of Japan,
# was established on 1957-01-29. Since Syowa station is still the main
# station of Japan, it's appropriate for the principal location.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Syowa 0 - -00 1957 Jan 29
3:00 - +03
# See:
@@ -254,7 +254,7 @@ Rule Troll 2005 max - Mar lastSun 1:00u 2:00 +02
#Rule Troll 2004 max - Nov 7 1:00u 0:00 +00
# Remove the following line when uncommenting the above '#Rule' lines.
Rule Troll 2004 max - Oct lastSun 1:00u 0:00 +00
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Troll 0 - -00 2005 Feb 12
0:00 Troll %s
@@ -328,7 +328,7 @@ Zone Antarctica/Vostok 0 - -00 1957 Dec 16
# From Paul Eggert (2002-10-22)
# <http://webexhibits.org/daylightsaving/g.html> says Rothera is -03 all year.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Rothera 0 - -00 1976 Dec 1
-3:00 - -03
diff --git a/make/data/tzdata/asia b/make/data/tzdata/asia
index 9847e91f4f..f6c463b0db 100644
--- a/make/data/tzdata/asia
+++ b/make/data/tzdata/asia
@@ -31,7 +31,7 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2018-06-19):
+# From Paul Eggert (2019-07-11):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -70,13 +70,13 @@
# 7:00 WIB west Indonesia (Waktu Indonesia Barat)
# 8:00 WITA central Indonesia (Waktu Indonesia Tengah)
# 8:00 CST China
-# 8:00 PST PDT* Philippine Standard Time
+# 8:00 HKT HKST Hong Kong (HKWT* for Winter Time in late 1941)
+# 8:00 PST PDT* Philippines
# 8:30 KST KDT Korea when at +0830
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
# 9:00 JST JDT Japan
# 9:00 KST KDT Korea when at +09
-# 9:30 ACST Australian Central Standard Time
-# *I invented the abbreviation PDT; see "Philippines" below.
+# *I invented the abbreviations HKWT and PDT; see below.
# Otherwise, these tables typically use numeric abbreviations like +03
# and +0330 for integer hour and minute UT offsets. Although earlier
# editions invented alphabetic time zone abbreviations for every
@@ -107,7 +107,7 @@ Rule RussiaAsia 1985 2010 - Mar lastSun 2:00s 1:00 -
Rule RussiaAsia 1996 2010 - Oct lastSun 2:00s 0 -
# Afghanistan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Kabul 4:36:48 - LMT 1890
4:00 - +04 1945
4:30 - +0430
@@ -140,7 +140,7 @@ Zone Asia/Kabul 4:36:48 - LMT 1890
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Armenia 2011 only - Mar lastSun 2:00s 1:00 -
Rule Armenia 2011 only - Oct lastSun 2:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
3:00 - +03 1957 Mar
4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
@@ -166,7 +166,7 @@ Zone Asia/Yerevan 2:58:00 - LMT 1924 May 2
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Azer 1997 2015 - Mar lastSun 4:00 1:00 -
Rule Azer 1997 2015 - Oct lastSun 5:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Baku 3:19:24 - LMT 1924 May 2
3:00 - +03 1957 Mar
4:00 RussiaAsia +04/+05 1991 Mar 31 2:00s
@@ -254,7 +254,7 @@ Zone Asia/Baku 3:19:24 - LMT 1924 May 2
Rule Dhaka 2009 only - Jun 19 23:00 1:00 -
Rule Dhaka 2009 only - Dec 31 24:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Dhaka 6:01:40 - LMT 1890
5:53:20 - HMT 1941 Oct # Howrah Mean Time?
6:30 - +0630 1942 May 15
@@ -264,7 +264,7 @@ Zone Asia/Dhaka 6:01:40 - LMT 1890
6:00 Dhaka +06/+07
# Bhutan
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Thimphu 5:58:36 - LMT 1947 Aug 15 # or Thimbu
5:30 - +0530 1987 Oct
6:00 - +06
@@ -275,13 +275,13 @@ Zone Asia/Thimphu 5:58:36 - LMT 1947 Aug 15 # or Thimbu
# We have no information as to when standard time was introduced;
# assume it occurred in 1907, the same year as Mauritius (which
# then contained the Chagos Archipelago).
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Chagos 4:49:40 - LMT 1907
5:00 - +05 1996
6:00 - +06
# Brunei
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
7:30 - +0730 1933
8:00 - +08
@@ -296,7 +296,7 @@ Zone Asia/Brunei 7:39:40 - LMT 1926 Mar # Bandar Seri Begawan
# of Greenwich." This refers to the period before Burma's transition to +0630,
# a transition for which Shanks is the only source.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Yangon 6:24:47 - LMT 1880 # or Rangoon
6:24:47 - RMT 1920 # Rangoon local time
6:30 - +0630 1942 May
@@ -584,7 +584,7 @@ Rule PRC 1987 1991 - Apr Sun>=11 2:00 1:00 D
# that the sort of users who prefer Asia/Urumqi now typically ignored the
# +08 mandate back then.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Beijing time, used throughout China; represented by Shanghai.
Zone Asia/Shanghai 8:05:43 - LMT 1901
8:00 Shang C%sT 1949 May 28
@@ -609,23 +609,132 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# obtained from
# http://www.hko.gov.hk/gts/time/Summertime.htm
-# From Arthur David Olson (2009-10-28):
+# From Phake Nick (2018-10-27):
+# According to Singaporean newspaper
+# http://eresources.nlb.gov.sg/newspapers/Digitised/Article/singfreepresswk19041102-1.2.37
+# the day that Hong Kong start using GMT+8 should be Oct 30, 1904.
+#
+# From Paul Eggert (2018-11-17):
+# Hong Kong had a time ball near the Marine Police Station, Tsim Sha Tsui.
+# "The ball was raised manually each day and dropped at exactly 1pm
+# (except on Sundays and Government holidays)."
+# Dyson AD. From Time Ball to Atomic Clock. Hong Kong Government. 1983.
+# <https://www.hko.gov.hk/publica/gen_pub/timeball_atomic_clock.pdf>
+# "From 1904 October 30 the time-ball at Hong Kong has been dropped by order
+# of the Governor of the Colony at 17h 0m 0s G.M.T., which is 23m 18s.14 in
+# advance of 1h 0m 0s of Hong Kong mean time."
+# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc.
+# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382
+#
+# From Joseph Myers (2018-11-18):
+# An astronomer before 1925 referring to GMT would have been using the old
+# astronomical convention where the day started at noon, not midnight.
+#
+# From Steve Allen (2018-11-17):
+# Meteorological Observations made at the Hongkong Observatory in the year 1904
+# page 4 <https://books.google.com/books?id=kgw5AQAAMAAJ&pg=RA4-PA4>
+# ... the log of drop times in Table II shows that on Sunday 1904-10-30 the
+# ball was dropped. So that looks like a special case drop for the sake
+# of broadcasting the new local time.
+#
+# From Phake Nick (2018-11-18):
+# According to The Hong Kong Weekly Press, 1904-10-29, p.324, the
+# governor of Hong Kong at the time stated that "We are further desired to
+# make it known that the change will be effected by firing the gun and by the
+# dropping of the Ball at 23min. 18sec. before one."
+# From Paul Eggert (2018-11-18):
+# See <https://mmis.hkpl.gov.hk> for this; unfortunately Flash is required.
+
+# From Phake Nick (2018-10-26):
+# I went to check microfilm records stored at Hong Kong Public Library....
+# on September 30 1941, according to Ta Kung Pao (Hong Kong edition), it was
+# stated that fallback would occur on the next day (the 1st)'s "03:00 am (Hong
+# Kong Time 04:00 am)" and the clock will fall back for a half hour. (03:00
+# probably refer to the time commonly used in mainland China at the time given
+# the paper's background) ... the sunrise/sunset time given by South China
+# Morning Post for October 1st was indeed moved by half an hour compares to
+# before. After that, in December, the battle to capture Hong Kong started and
+# the library doesn't seems to have any record stored about press during that
+# period of time. Some media resumed publication soon after that within the
+# same month, but there were not much information about time there. Later they
+# started including a radio program guide when they restored radio service,
+# explicitly mentioning it use Tokyo standard time, and later added a note
+# saying it's half an hour ahead of the old Hong Kong standard time, and it
+# also seems to indicate that Hong Kong was not using GMT+8 when it was
+# captured by Japan.
+#
+# Image of related sections on newspaper:
+# * 1941-09-30, Ta Kung Pao (Hong Kong), "Winter Time start tomorrow".
+# https://i.imgur.com/6waY51Z.jpg (Chinese)
+# * 1941-09-29, South China Morning Post, Information on sunrise/sunset
+# time and other things for September 30 and October 1.
+# https://i.imgur.com/kCiUR78.jpg
+# * 1942-02-05. The Hong Kong News, Radio Program Guide.
+# https://i.imgur.com/eVvDMzS.jpg
+# * 1941-06-14. Hong Kong Daily Press, Daylight Saving from 3am Tomorrow.
+# https://i.imgur.com/05KkvtC.png
+# * 1941-09-30, Hong Kong Daily Press, Winter Time Warning.
+# https://i.imgur.com/dge4kFJ.png
+
+# From Paul Eggert (2019-07-11):
+# "Hong Kong winter time" is considered to be daylight saving.
+# "Hong Kong had adopted daylight saving on June 15 as a wartime measure,
+# clocks moving forward one hour until October 1, when they would be put back
+# by just half an hour for 'Hong Kong Winter time', so that daylight saving
+# operated year round." -- Low Z. The longest day: when wartime Hong Kong
+# introduced daylight saving. South China Morning Post. 2019-06-28.
+# https://www.scmp.com/magazines/post-magazine/short-reads/article/3016281/longest-day-when-wartime-hong-kong-introduced
+
+# From P Chan (2018-12-31):
+# * According to the Hong Kong Daylight-Saving Regulations, 1941, the
+# 1941 spring-forward transition was at 03:00.
+# http://sunzi.lib.hku.hk/hkgro/view/g1941/304271.pdf
+# http://sunzi.lib.hku.hk/hkgro/view/g1941/305516.pdf
+# * According to some articles from South China Morning Post, +08 was
+# resumed on 1945-11-18 at 02:00.
+# https://i.imgur.com/M2IsZ3c.png
+# https://i.imgur.com/iOPqrVo.png
+# https://i.imgur.com/fffcGDs.png
+# * Some newspapers ... said the 1946 spring-forward transition was on
+# 04-21 at 00:00. The Kung Sheung Evening News 1946-04-20 (Chinese)
+# https://i.imgur.com/ZSzent0.png
+# https://mmis.hkpl.gov.hk///c/portal/cover?c=QF757YsWv5%2FH7zGe%2FKF%2BFLYsuqGhRBfe p.4
+# The Kung Sheung Daily News 1946-04-21 (Chinese)
+# https://i.imgur.com/7ecmRlcm.png
+# https://mmis.hkpl.gov.hk///c/portal/cover?c=QF757YsWv5%2BQBGt1%2BwUj5qG2GqtwR3Wh p.4
+# * According to the Summer Time Ordinance (1946), the fallback
+# transitions between 1946 and 1952 were at 03:30 Standard Time (+08)
+# http://oelawhk.lib.hku.hk/archive/files/bb74b06a74d5294620a15de560ab33c6.pdf
+# * Some other laws and regulations related to DST from 1953 to 1979
+# Summer Time Ordinance 1953
+# https://i.imgur.com/IOlJMav.jpg
+# Summer Time (Amendment) Ordinance 1965
+# https://i.imgur.com/8rofeLa.jpg
+# Interpretation and General Clauses Ordinance (1966)
+# https://i.imgur.com/joy3msj.jpg
+# Emergency (Summer Time) Regulation 1973 <https://i.imgur.com/OpRWrKz.jpg>
+# Interpretation and General Clauses (Amendment) Ordinance 1977
+# https://i.imgur.com/RaNqnc4.jpg
+# Resolution of the Legislative Council passed on 9 May 1979
+# https://www.legco.gov.hk/yr78-79/english/lc_sitg/hansard/h790509.pdf#page=39
+
+# From Paul Eggert (2019-05-31):
# Here are the dates given at
-# http://www.hko.gov.hk/gts/time/Summertime.htm
-# as of 2009-10-28:
+# https://www.hko.gov.hk/gts/time/Summertime.htm
+# as of 2014-06-19:
# Year Period
-# 1941 1 Apr to 30 Sep
+# 1941 15 Jun to 30 Sep
# 1942 Whole year
# 1943 Whole year
# 1944 Whole year
# 1945 Whole year
# 1946 20 Apr to 1 Dec
-# 1947 13 Apr to 30 Dec
+# 1947 13 Apr to 30 Nov
# 1948 2 May to 31 Oct
# 1949 3 Apr to 30 Oct
# 1950 2 Apr to 29 Oct
# 1951 1 Apr to 28 Oct
-# 1952 6 Apr to 25 Oct
+# 1952 6 Apr to 2 Nov
# 1953 5 Apr to 1 Nov
# 1954 21 Mar to 31 Oct
# 1955 20 Mar to 6 Nov
@@ -654,37 +763,31 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# 1978 Nil
# 1979 13 May to 21 Oct
# 1980 to Now Nil
-# The page does not give start or end times of day.
-# The page does not give a start date for 1942.
-# The page does not givw an end date for 1945.
-# The Japanese occupation of Hong Kong began on 1941-12-25.
-# The Japanese surrender of Hong Kong was signed 1945-09-15.
-# For lack of anything better, use start of those days as the transition times.
+# The page does not give times of day for transitions,
+# or dates for the 1942 and 1945 transitions.
+# The Japanese occupation of Hong Kong began 1941-12-25.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule HK 1941 only - Apr 1 3:30 1:00 S
-Rule HK 1941 only - Sep 30 3:30 0 -
-Rule HK 1946 only - Apr 20 3:30 1:00 S
-Rule HK 1946 only - Dec 1 3:30 0 -
-Rule HK 1947 only - Apr 13 3:30 1:00 S
-Rule HK 1947 only - Dec 30 3:30 0 -
-Rule HK 1948 only - May 2 3:30 1:00 S
-Rule HK 1948 1951 - Oct lastSun 3:30 0 -
-Rule HK 1952 only - Oct 25 3:30 0 -
+Rule HK 1946 only - Apr 21 0:00 1:00 S
+Rule HK 1946 only - Dec 1 3:30s 0 -
+Rule HK 1947 only - Apr 13 3:30s 1:00 S
+Rule HK 1947 only - Nov 30 3:30s 0 -
+Rule HK 1948 only - May 2 3:30s 1:00 S
+Rule HK 1948 1952 - Oct Sun>=28 3:30s 0 -
Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S
-Rule HK 1953 only - Nov 1 3:30 0 -
+Rule HK 1953 1964 - Oct Sun>=31 3:30 0 -
Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
-Rule HK 1954 only - Oct 31 3:30 0 -
-Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
Rule HK 1965 1976 - Apr Sun>=16 3:30 1:00 S
Rule HK 1965 1976 - Oct Sun>=16 3:30 0 -
Rule HK 1973 only - Dec 30 3:30 1:00 S
-Rule HK 1979 only - May Sun>=8 3:30 1:00 S
-Rule HK 1979 only - Oct Sun>=16 3:30 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
- 8:00 HK HK%sT 1941 Dec 25
- 9:00 - JST 1945 Sep 15
+Rule HK 1979 only - May 13 3:30 1:00 S
+Rule HK 1979 only - Oct 21 3:30 0 -
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 0:36:42
+ 8:00 - HKT 1941 Jun 15 3:00
+ 8:00 1:00 HKST 1941 Oct 1 4:00
+ 8:00 0:30 HKWT 1941 Dec 25
+ 9:00 - JST 1945 Nov 18 2:00
8:00 HK HK%sT
###############################################################################
@@ -808,7 +911,7 @@ Rule Taiwan 1974 1975 - Oct 1 0:00 0 S
Rule Taiwan 1979 only - Jul 1 0:00 1:00 D
Rule Taiwan 1979 only - Oct 1 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Taipei or Taibei or T'ai-pei
Zone Asia/Taipei 8:06:00 - LMT 1896 Jan 1
8:00 - CST 1937 Oct 1
@@ -946,7 +1049,7 @@ Rule Macau 1975 1976 - Apr Sun>=16 03:30 1:00 D
Rule Macau 1979 only - May 13 03:30 1:00 D
Rule Macau 1979 only - Oct Sun>=16 03:30 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Macau 7:34:10 - LMT 1904 Oct 30
8:00 - CST 1941 Dec 21 23:00
9:00 Macau +09/+10 1945 Sep 30 24:00
@@ -985,7 +1088,7 @@ Rule Cyprus 1977 only - Sep 25 0:00 0 -
Rule Cyprus 1978 only - Oct 2 0:00 0 -
Rule Cyprus 1979 1997 - Sep lastSun 0:00 0 -
Rule Cyprus 1981 1998 - Mar lastSun 0:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Nicosia 2:13:28 - LMT 1921 Nov 14
2:00 Cyprus EE%sT 1998 Sep
2:00 EUAsia EE%sT
@@ -1034,7 +1137,7 @@ Link Asia/Nicosia Europe/Nicosia
# Byalokoz 1919 says Georgia was 2:59:11.
# Go with Byalokoz.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Tbilisi 2:59:11 - LMT 1880
2:59:11 - TBMT 1924 May 2 # Tbilisi Mean Time
3:00 - +03 1957 Mar
@@ -1071,7 +1174,7 @@ Zone Asia/Tbilisi 2:59:11 - LMT 1880
# which will be permanent, with no seasonal adjustment, will happen at
# midnight on Saturday, September 16.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Dili 8:22:20 - LMT 1912 Jan 1
8:00 - +08 1942 Feb 21 23:00
9:00 - +09 1976 May 3
@@ -1080,6 +1183,16 @@ Zone Asia/Dili 8:22:20 - LMT 1912 Jan 1
# India
+# British astronomer Henry Park Hollis disliked India Standard Time's offset:
+# "A new time system has been proposed for India, Further India, and Burmah.
+# The scheme suggested is that the times of the meridians 5½ and 6½ hours
+# east of Greenwich should be adopted in these territories. No reason is
+# given why hourly meridians five hours and six hours east should not be
+# chosen; a plan which would bring the time of India into harmony with
+# that of almost the whole of the civilised world."
+# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc.
+# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382
+
# From Ian P. Beacock, in "A brief history of (modern) time", The Atlantic
# https://www.theatlantic.com/technology/archive/2015/12/the-creation-of-modern-time/421419/
# (2015-12-22):
@@ -1127,7 +1240,7 @@ Zone Asia/Dili 8:22:20 - LMT 1912 Jan 1
# time for 1870-1941. Shanks is our only (and dubious) source for the
# 1941-1945 data.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Kolkata 5:53:28 - LMT 1854 Jun 28 # Kolkata
5:53:20 - HMT 1870 # Howrah Mean Time?
5:21:10 - MMT 1906 Jan 1 # Madras local time
@@ -1179,7 +1292,7 @@ Zone Asia/Kolkata 5:53:28 - LMT 1854 Jun 28 # Kolkata
# WITA - +08 - Waktu Indonesia Tengah (Indonesia central time)
# WIT - +09 - Waktu Indonesia Timur (Indonesia eastern time)
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Java, Sumatra
Zone Asia/Jakarta 7:07:12 - LMT 1867 Aug 10
# Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
@@ -1250,12 +1363,65 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
# leap year calculation involved. There has never been any serious
# plan to change that law....
#
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2018-11-30):
# Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter.
-# I used Ed Reingold's cal-persia in GNU Emacs 21.2 to check Persian dates,
-# stopping after 2037 when 32-bit time_t's overflow.
-# That cal-persia used Birashk's approximation, which disagrees with the solar
-# calendar predictions for the year 2025, so I corrected those dates by hand.
+# I used the following code in GNU Emacs 26.1 to generate the "Rule Iran"
+# lines from 2008 through 2087. Emacs 26.1 uses Ed Reingold's
+# cal-persia implementation of Birashk's approximation, which in the
+# 2008-2087 range disagrees with the astronomical Persian calendar
+# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058), so
+# the following code special-cases those years. See Table 15.1, page 264, of:
+# Edward M. Reingold and Nachum Dershowitz, Calendrical Calculations:
+# The Ultimate Edition, Cambridge University Press (2018).
+# https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition
+# Page 258, footnote 2, of this book says there is some dispute over what will
+# happen in 2091 (and some other years after that), so this code
+# stops in 2087, as 2088 and 2089 agree with the "max" rule below.
+# (cl-loop
+# initially (require 'cal-persia)
+# with first-persian-year = 1387
+# with last-persian-year = 1466
+# ;; Exceptional years in the above range,
+# ;; from Reingold & Dershowitz Table 15.1, page 264:
+# with exceptional-persian-years = '(1404 1437)
+# with range-start = nil
+# for persian-year from first-persian-year to last-persian-year
+# do
+# (let*
+# ((exceptional-year-offset
+# (if (member persian-year exceptional-persian-years) 1 0))
+# (beg-dst-absolute
+# (+ (calendar-persian-to-absolute (list 1 1 persian-year))
+# exceptional-year-offset))
+# (end-dst-absolute
+# (+ (calendar-persian-to-absolute (list 6 30 persian-year))
+# exceptional-year-offset))
+# (next-year-beg-dst-absolute
+# (+ (calendar-persian-to-absolute (list 1 1 (1+ persian-year)))
+# (if (member (1+ persian-year) exceptional-persian-years) 1 0)))
+# (beg-dst (calendar-gregorian-from-absolute beg-dst-absolute))
+# (end-dst (calendar-gregorian-from-absolute end-dst-absolute))
+# (next-year-beg-dst (calendar-gregorian-from-absolute
+# next-year-beg-dst-absolute))
+# (year (calendar-extract-year beg-dst))
+# (range-end (if range-start year "only")))
+# (setq range-start (or range-start year))
+# (when (or (/= (calendar-extract-day beg-dst)
+# (calendar-extract-day next-year-beg-dst))
+# (= persian-year last-persian-year))
+# (insert
+# (format
+# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t1:00\t-\n"
+# range-start range-end
+# (calendar-month-name (calendar-extract-month beg-dst) t)
+# (calendar-extract-day beg-dst)))
+# (insert
+# (format
+# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t0\t-\n"
+# range-start range-end
+# (calendar-month-name (calendar-extract-month end-dst) t)
+# (calendar-extract-day end-dst)))
+# (setq range-start nil))))
#
# From Oscar van Vlijmen (2005-03-30), writing about future
# discrepancies between cal-persia and the Iranian calendar:
@@ -1290,63 +1456,115 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
# thirtieth day of Shahrivar.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Iran 1978 1980 - Mar 21 0:00 1:00 -
-Rule Iran 1978 only - Oct 21 0:00 0 -
-Rule Iran 1979 only - Sep 19 0:00 0 -
-Rule Iran 1980 only - Sep 23 0:00 0 -
-Rule Iran 1991 only - May 3 0:00 1:00 -
-Rule Iran 1992 1995 - Mar 22 0:00 1:00 -
-Rule Iran 1991 1995 - Sep 22 0:00 0 -
-Rule Iran 1996 only - Mar 21 0:00 1:00 -
-Rule Iran 1996 only - Sep 21 0:00 0 -
-Rule Iran 1997 1999 - Mar 22 0:00 1:00 -
-Rule Iran 1997 1999 - Sep 22 0:00 0 -
-Rule Iran 2000 only - Mar 21 0:00 1:00 -
-Rule Iran 2000 only - Sep 21 0:00 0 -
-Rule Iran 2001 2003 - Mar 22 0:00 1:00 -
-Rule Iran 2001 2003 - Sep 22 0:00 0 -
-Rule Iran 2004 only - Mar 21 0:00 1:00 -
-Rule Iran 2004 only - Sep 21 0:00 0 -
-Rule Iran 2005 only - Mar 22 0:00 1:00 -
-Rule Iran 2005 only - Sep 22 0:00 0 -
-Rule Iran 2008 only - Mar 21 0:00 1:00 -
-Rule Iran 2008 only - Sep 21 0:00 0 -
-Rule Iran 2009 2011 - Mar 22 0:00 1:00 -
-Rule Iran 2009 2011 - Sep 22 0:00 0 -
-Rule Iran 2012 only - Mar 21 0:00 1:00 -
-Rule Iran 2012 only - Sep 21 0:00 0 -
-Rule Iran 2013 2015 - Mar 22 0:00 1:00 -
-Rule Iran 2013 2015 - Sep 22 0:00 0 -
-Rule Iran 2016 only - Mar 21 0:00 1:00 -
-Rule Iran 2016 only - Sep 21 0:00 0 -
-Rule Iran 2017 2019 - Mar 22 0:00 1:00 -
-Rule Iran 2017 2019 - Sep 22 0:00 0 -
-Rule Iran 2020 only - Mar 21 0:00 1:00 -
-Rule Iran 2020 only - Sep 21 0:00 0 -
-Rule Iran 2021 2023 - Mar 22 0:00 1:00 -
-Rule Iran 2021 2023 - Sep 22 0:00 0 -
-Rule Iran 2024 only - Mar 21 0:00 1:00 -
-Rule Iran 2024 only - Sep 21 0:00 0 -
-Rule Iran 2025 2027 - Mar 22 0:00 1:00 -
-Rule Iran 2025 2027 - Sep 22 0:00 0 -
-Rule Iran 2028 2029 - Mar 21 0:00 1:00 -
-Rule Iran 2028 2029 - Sep 21 0:00 0 -
-Rule Iran 2030 2031 - Mar 22 0:00 1:00 -
-Rule Iran 2030 2031 - Sep 22 0:00 0 -
-Rule Iran 2032 2033 - Mar 21 0:00 1:00 -
-Rule Iran 2032 2033 - Sep 21 0:00 0 -
-Rule Iran 2034 2035 - Mar 22 0:00 1:00 -
-Rule Iran 2034 2035 - Sep 22 0:00 0 -
-#
-# The following rules are approximations starting in the year 2038.
-# These are the best post-2037 approximations available, given the
-# restrictions of a single rule using a Gregorian-based data format.
+Rule Iran 1978 1980 - Mar 20 24:00 1:00 -
+Rule Iran 1978 only - Oct 20 24:00 0 -
+Rule Iran 1979 only - Sep 18 24:00 0 -
+Rule Iran 1980 only - Sep 22 24:00 0 -
+Rule Iran 1991 only - May 2 24:00 1:00 -
+Rule Iran 1992 1995 - Mar 21 24:00 1:00 -
+Rule Iran 1991 1995 - Sep 21 24:00 0 -
+Rule Iran 1996 only - Mar 20 24:00 1:00 -
+Rule Iran 1996 only - Sep 20 24:00 0 -
+Rule Iran 1997 1999 - Mar 21 24:00 1:00 -
+Rule Iran 1997 1999 - Sep 21 24:00 0 -
+Rule Iran 2000 only - Mar 20 24:00 1:00 -
+Rule Iran 2000 only - Sep 20 24:00 0 -
+Rule Iran 2001 2003 - Mar 21 24:00 1:00 -
+Rule Iran 2001 2003 - Sep 21 24:00 0 -
+Rule Iran 2004 only - Mar 20 24:00 1:00 -
+Rule Iran 2004 only - Sep 20 24:00 0 -
+Rule Iran 2005 only - Mar 21 24:00 1:00 -
+Rule Iran 2005 only - Sep 21 24:00 0 -
+Rule Iran 2008 only - Mar 20 24:00 1:00 -
+Rule Iran 2008 only - Sep 20 24:00 0 -
+Rule Iran 2009 2011 - Mar 21 24:00 1:00 -
+Rule Iran 2009 2011 - Sep 21 24:00 0 -
+Rule Iran 2012 only - Mar 20 24:00 1:00 -
+Rule Iran 2012 only - Sep 20 24:00 0 -
+Rule Iran 2013 2015 - Mar 21 24:00 1:00 -
+Rule Iran 2013 2015 - Sep 21 24:00 0 -
+Rule Iran 2016 only - Mar 20 24:00 1:00 -
+Rule Iran 2016 only - Sep 20 24:00 0 -
+Rule Iran 2017 2019 - Mar 21 24:00 1:00 -
+Rule Iran 2017 2019 - Sep 21 24:00 0 -
+Rule Iran 2020 only - Mar 20 24:00 1:00 -
+Rule Iran 2020 only - Sep 20 24:00 0 -
+Rule Iran 2021 2023 - Mar 21 24:00 1:00 -
+Rule Iran 2021 2023 - Sep 21 24:00 0 -
+Rule Iran 2024 only - Mar 20 24:00 1:00 -
+Rule Iran 2024 only - Sep 20 24:00 0 -
+Rule Iran 2025 2027 - Mar 21 24:00 1:00 -
+Rule Iran 2025 2027 - Sep 21 24:00 0 -
+Rule Iran 2028 2029 - Mar 20 24:00 1:00 -
+Rule Iran 2028 2029 - Sep 20 24:00 0 -
+Rule Iran 2030 2031 - Mar 21 24:00 1:00 -
+Rule Iran 2030 2031 - Sep 21 24:00 0 -
+Rule Iran 2032 2033 - Mar 20 24:00 1:00 -
+Rule Iran 2032 2033 - Sep 20 24:00 0 -
+Rule Iran 2034 2035 - Mar 21 24:00 1:00 -
+Rule Iran 2034 2035 - Sep 21 24:00 0 -
+Rule Iran 2036 2037 - Mar 20 24:00 1:00 -
+Rule Iran 2036 2037 - Sep 20 24:00 0 -
+Rule Iran 2038 2039 - Mar 21 24:00 1:00 -
+Rule Iran 2038 2039 - Sep 21 24:00 0 -
+Rule Iran 2040 2041 - Mar 20 24:00 1:00 -
+Rule Iran 2040 2041 - Sep 20 24:00 0 -
+Rule Iran 2042 2043 - Mar 21 24:00 1:00 -
+Rule Iran 2042 2043 - Sep 21 24:00 0 -
+Rule Iran 2044 2045 - Mar 20 24:00 1:00 -
+Rule Iran 2044 2045 - Sep 20 24:00 0 -
+Rule Iran 2046 2047 - Mar 21 24:00 1:00 -
+Rule Iran 2046 2047 - Sep 21 24:00 0 -
+Rule Iran 2048 2049 - Mar 20 24:00 1:00 -
+Rule Iran 2048 2049 - Sep 20 24:00 0 -
+Rule Iran 2050 2051 - Mar 21 24:00 1:00 -
+Rule Iran 2050 2051 - Sep 21 24:00 0 -
+Rule Iran 2052 2053 - Mar 20 24:00 1:00 -
+Rule Iran 2052 2053 - Sep 20 24:00 0 -
+Rule Iran 2054 2055 - Mar 21 24:00 1:00 -
+Rule Iran 2054 2055 - Sep 21 24:00 0 -
+Rule Iran 2056 2057 - Mar 20 24:00 1:00 -
+Rule Iran 2056 2057 - Sep 20 24:00 0 -
+Rule Iran 2058 2059 - Mar 21 24:00 1:00 -
+Rule Iran 2058 2059 - Sep 21 24:00 0 -
+Rule Iran 2060 2062 - Mar 20 24:00 1:00 -
+Rule Iran 2060 2062 - Sep 20 24:00 0 -
+Rule Iran 2063 only - Mar 21 24:00 1:00 -
+Rule Iran 2063 only - Sep 21 24:00 0 -
+Rule Iran 2064 2066 - Mar 20 24:00 1:00 -
+Rule Iran 2064 2066 - Sep 20 24:00 0 -
+Rule Iran 2067 only - Mar 21 24:00 1:00 -
+Rule Iran 2067 only - Sep 21 24:00 0 -
+Rule Iran 2068 2070 - Mar 20 24:00 1:00 -
+Rule Iran 2068 2070 - Sep 20 24:00 0 -
+Rule Iran 2071 only - Mar 21 24:00 1:00 -
+Rule Iran 2071 only - Sep 21 24:00 0 -
+Rule Iran 2072 2074 - Mar 20 24:00 1:00 -
+Rule Iran 2072 2074 - Sep 20 24:00 0 -
+Rule Iran 2075 only - Mar 21 24:00 1:00 -
+Rule Iran 2075 only - Sep 21 24:00 0 -
+Rule Iran 2076 2078 - Mar 20 24:00 1:00 -
+Rule Iran 2076 2078 - Sep 20 24:00 0 -
+Rule Iran 2079 only - Mar 21 24:00 1:00 -
+Rule Iran 2079 only - Sep 21 24:00 0 -
+Rule Iran 2080 2082 - Mar 20 24:00 1:00 -
+Rule Iran 2080 2082 - Sep 20 24:00 0 -
+Rule Iran 2083 only - Mar 21 24:00 1:00 -
+Rule Iran 2083 only - Sep 21 24:00 0 -
+Rule Iran 2084 2086 - Mar 20 24:00 1:00 -
+Rule Iran 2084 2086 - Sep 20 24:00 0 -
+Rule Iran 2087 only - Mar 21 24:00 1:00 -
+Rule Iran 2087 only - Sep 21 24:00 0 -
+#
+# The following rules are approximations starting in the year 2088.
+# These are the best post-2088 approximations available, given the
+# restrictions of a single rule using ordinary Gregorian dates.
# At some point this table will need to be extended, though quite
# possibly Iran will change the rules first.
-Rule Iran 2036 max - Mar 21 0:00 1:00 -
-Rule Iran 2036 max - Sep 21 0:00 0 -
+Rule Iran 2088 max - Mar 20 24:00 1:00 -
+Rule Iran 2088 max - Sep 20 24:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Tehran 3:25:44 - LMT 1916
3:25:44 - TMT 1946 # Tehran Mean Time
3:30 - +0330 1977 Nov
@@ -1391,7 +1609,7 @@ Rule Iraq 1986 1990 - Mar lastSun 1:00s 1:00 -
#
Rule Iraq 1991 2007 - Apr 1 3:00s 1:00 -
Rule Iraq 1991 2007 - Oct 1 3:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Baghdad 2:57:40 - LMT 1890
2:57:36 - BMT 1918 # Baghdad Mean Time?
3:00 - +03 1982 May
@@ -1456,6 +1674,24 @@ Rule Zion 1974 only - Jul 7 0:00 1:00 D
Rule Zion 1974 only - Oct 13 0:00 0 S
Rule Zion 1975 only - Apr 20 0:00 1:00 D
Rule Zion 1975 only - Aug 31 0:00 0 S
+
+# From Alois Treindl (2019-03-06):
+# http://www.moin.gov.il/Documents/שעון%20קיץ/clock-50-years-7-2014.pdf
+# From Isaac Starkman (2019-03-06):
+# Summer time was in that period in 1980 and 1984, see
+# https://www.ynet.co.il/articles/0,7340,L-3951073,00.html
+# You can of course read it in translation.
+# I checked the local newspapers for that years.
+# It started on midnight and end at 01.00 am.
+# From Paul Eggert (2019-03-06):
+# Also see this thread about the moin.gov.il URL:
+# https://mm.icann.org/pipermail/tz/2018-November/027194.html
+Rule Zion 1980 only - Aug 2 0:00 1:00 D
+Rule Zion 1980 only - Sep 13 1:00 0 S
+Rule Zion 1984 only - May 5 0:00 1:00 D
+Rule Zion 1984 only - Aug 25 1:00 0 S
+
+# From Shanks & Pottenger:
Rule Zion 1985 only - Apr 14 0:00 1:00 D
Rule Zion 1985 only - Sep 15 0:00 0 S
Rule Zion 1986 only - May 18 0:00 1:00 D
@@ -1578,32 +1814,15 @@ Rule Zion 2004 only - Sep 22 1:00 0 S
#
# ftp://ftp.cs.huji.ac.il/pub/tz/announcements/2005+beyond.ps
-# From Paul Eggert (2012-10-26):
-# I used Ephraim Silverberg's dst-israel.el program
-# <ftp://ftp.cs.huji.ac.il/pub/tz/software/dst-israel.el> (2005-02-20)
-# along with Ed Reingold's cal-hebrew in GNU Emacs 21.4,
-# to generate the transitions from 2005 through 2012.
-# (I replaced "lastFri" with "Fri>=26" by hand.)
-# The spring transitions all correspond to the following Rule:
-#
-# Rule Zion 2005 2012 - Mar Fri>=26 2:00 1:00 D
-#
-# but older zic implementations (e.g., Solaris 8) do not support
-# "Fri>=26" to mean April 1 in years like 2005, so for now we list the
-# springtime transitions explicitly.
-
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Zion 2005 only - Apr 1 2:00 1:00 D
+Rule Zion 2005 2012 - Apr Fri<=1 2:00 1:00 D
Rule Zion 2005 only - Oct 9 2:00 0 S
-Rule Zion 2006 2010 - Mar Fri>=26 2:00 1:00 D
Rule Zion 2006 only - Oct 1 2:00 0 S
Rule Zion 2007 only - Sep 16 2:00 0 S
Rule Zion 2008 only - Oct 5 2:00 0 S
Rule Zion 2009 only - Sep 27 2:00 0 S
Rule Zion 2010 only - Sep 12 2:00 0 S
-Rule Zion 2011 only - Apr 1 2:00 1:00 D
Rule Zion 2011 only - Oct 2 2:00 0 S
-Rule Zion 2012 only - Mar Fri>=26 2:00 1:00 D
Rule Zion 2012 only - Sep 23 2:00 0 S
# From Ephraim Silverberg (2013-06-27):
@@ -1619,7 +1838,7 @@ Rule Zion 2012 only - Sep 23 2:00 0 S
Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D
Rule Zion 2013 max - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Jerusalem 2:20:54 - LMT 1880
2:20:40 - JMT 1918 # Jerusalem Mean Time?
2:00 Zion I%sT
@@ -1711,10 +1930,12 @@ Rule Japan 1950 1951 - May Sat>=1 24:00 1:00 D
# Central Time (UT+9). The adoption began on Oct 1, 1937.
# https://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Tokyo 9:18:59 - LMT 1887 Dec 31 15:00u
9:00 Japan J%sT
-# Since 1938, all Japanese possessions have been like Asia/Tokyo.
+# Since 1938, all Japanese possessions have been like Asia/Tokyo,
+# except that Truk (Chuuk), Ponape (Pohnpei), and Jaluit (Kosrae) did not
+# switch from +10 to +09 until 1941-04-01; see the 'australasia' file.
# Jordan
#
@@ -1812,7 +2033,7 @@ Rule Jordan 2006 2011 - Oct lastFri 0:00s 0 -
Rule Jordan 2013 only - Dec 20 0:00 0 -
Rule Jordan 2014 max - Mar lastThu 24:00 1:00 S
Rule Jordan 2014 max - Oct lastFri 0:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Amman 2:23:44 - LMT 1931
2:00 Jordan EE%sT
@@ -1853,8 +2074,8 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# text.
#
# According to Izvestia newspaper No. 68 (23334) from 1991-03-20
-# (page 6; available at http://libinfo.org/newsr/newsr2574.djvu via
-# http://libinfo.org/index.php?id=58564) on 1991-03-31 at 2:00 during
+# -- page 6; available at http://libinfo.org/newsr/newsr2574.djvu via
+# http://libinfo.org/index.php?id=58564 -- on 1991-03-31 at 2:00 during
# transition to "summer" time:
# Republic of Georgia, Latvian SSR, Lithuanian SSR, SSR Moldova,
# Estonian SSR; Komi ASSR; Kaliningrad oblast; Nenets autonomous okrug
@@ -1870,7 +2091,7 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# Apparently there were last minute changes. Apparently Kazakh act No. 170
# was one of such changes.
#
-# https://ru.wikipedia.org/wiki/Декретное время
+# https://ru.wikipedia.org/wiki/Декретное_время
# claims that Sovetskaya Rossiya newspaper on 1991-03-29 published that
# Nenets autonomous okrug, Komi and Kazakhstan (excluding Uralsk oblast)
# were to not move clocks and Uralsk oblast was to move clocks
@@ -2004,10 +2225,12 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# and in Byalokoz) lists Ural river (plus 10 versts on its left bank) in
# the third time belt (before 1930 this means +03).
-# From Paul Eggert (2016-12-06):
-# The tables below reflect Golosunov's remarks, with exceptions as noted.
+# From Alexander Konzurovski (2018-12-20):
+# Qyzyolrda Region (Asia/Qyzylorda) is changing its time zone from
+# UTC+6 to UTC+5 effective December 21st, 2018. The legal document is
+# located here: http://adilet.zan.kz/rus/docs/P1800000817 (russian language).
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
#
# Almaty (formerly Alma-Ata), representing most locations in Kazakhstan
# This includes KZ-AKM, KZ-ALA, KZ-ALM, KZ-AST, KZ-BAY, KZ-VOS, KZ-ZHA,
@@ -2019,8 +2242,6 @@ Zone Asia/Almaty 5:07:48 - LMT 1924 May 2 # or Alma-Ata
6:00 RussiaAsia +06/+07 2004 Oct 31 2:00s
6:00 - +06
# Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.) (KZ-KZY)
-# This currently includes Qostanay (aka Kostanay, Kustanay) (KZ-KUS);
-# see comments below.
Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Apr 1
@@ -2031,21 +2252,22 @@ Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
5:00 RussiaAsia +05/+06 1992 Jan 19 2:00s
6:00 RussiaAsia +06/+07 1992 Mar 29 2:00s
5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
- 6:00 - +06
-# The following zone is like Asia/Qyzylorda except for being one
-# hour earlier from 1991-09-29 to 1992-03-29. The 1991/2 rules for
-# Qostanay are unclear partly because of the 1997 Turgai
-# reorganization, so this zone is commented out for now.
-#Zone Asia/Qostanay 4:14:20 - LMT 1924 May 2
-# 4:00 - +04 1930 Jun 21
-# 5:00 - +05 1981 Apr 1
-# 5:00 1:00 +06 1981 Oct 1
-# 6:00 - +06 1982 Apr 1
-# 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
-# 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
-# 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
-# 6:00 - +06
+ 6:00 - +06 2018 Dec 21 0:00
+ 5:00 - +05
#
+# Qostanay (aka Kostanay, Kustanay) (KZ-KUS)
+# The 1991/2 rules are unclear partly because of the 1997 Turgai
+# reorganization.
+Zone Asia/Qostanay 4:14:28 - LMT 1924 May 2
+ 4:00 - +04 1930 Jun 21
+ 5:00 - +05 1981 Apr 1
+ 5:00 1:00 +06 1981 Oct 1
+ 6:00 - +06 1982 Apr 1
+ 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
+ 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
+ 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
+ 6:00 - +06
+
# Aqtöbe (aka Aktobe, formerly Aktyubinsk) (KZ-AKT)
Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
@@ -2110,7 +2332,7 @@ Rule Kyrgyz 1992 1996 - Apr Sun>=7 0:00s 1:00 -
Rule Kyrgyz 1992 1996 - Sep lastSun 0:00 0 -
Rule Kyrgyz 1997 2005 - Mar lastSun 2:30 1:00 -
Rule Kyrgyz 1997 2004 - Oct lastSun 2:30 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
5:00 - +05 1930 Jun 21
6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
@@ -2139,21 +2361,43 @@ Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
# started at June 1 in that year. For another example, the article in
# 1988 said that DST started at 2:00 AM in that year.
+# From Phake Nick (2018-10-27):
+# 1. According to official announcement from Korean government, the DST end
+# date in South Korea should be
+# 1955-09-08 without specifying time
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027977557
+# 1956-09-29 without specifying time
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027978341
+# 1957-09-21 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027979690#3
+# 1958-09-20 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027981189
+# 1959-09-19 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027982974#2
+# 1960-09-17 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0028044104
+# ...
+# 2.... https://namu.wiki/w/대한민국%20표준시 ... [says]
+# when Korea was using GMT+8:30 as standard time, the international
+# aviation/marine/meteorological industry in the country refused to
+# follow and continued to use GMT+9:00 for interoperability.
+
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule ROK 1948 only - Jun 1 0:00 1:00 D
-Rule ROK 1948 only - Sep 13 0:00 0 S
-Rule ROK 1949 only - Apr 3 0:00 1:00 D
-Rule ROK 1949 1951 - Sep Sun>=8 0:00 0 S
-Rule ROK 1950 only - Apr 1 0:00 1:00 D
-Rule ROK 1951 only - May 6 0:00 1:00 D
-Rule ROK 1955 only - May 5 0:00 1:00 D
-Rule ROK 1955 only - Sep 9 0:00 0 S
-Rule ROK 1956 only - May 20 0:00 1:00 D
-Rule ROK 1956 only - Sep 30 0:00 0 S
-Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
-Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
-Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
-Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
+Rule ROK 1948 only - Jun 1 0:00 1:00 D
+Rule ROK 1948 only - Sep 12 24:00 0 S
+Rule ROK 1949 only - Apr 3 0:00 1:00 D
+Rule ROK 1949 1951 - Sep Sat>=7 24:00 0 S
+Rule ROK 1950 only - Apr 1 0:00 1:00 D
+Rule ROK 1951 only - May 6 0:00 1:00 D
+Rule ROK 1955 only - May 5 0:00 1:00 D
+Rule ROK 1955 only - Sep 8 24:00 0 S
+Rule ROK 1956 only - May 20 0:00 1:00 D
+Rule ROK 1956 only - Sep 29 24:00 0 S
+Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
+Rule ROK 1957 1960 - Sep Sat>=17 24:00 0 S
+Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
+Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
# From Paul Eggert (2016-08-23):
# The Korean Wikipedia entry gives the following sources for UT offsets:
@@ -2203,11 +2447,11 @@ Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
# The BBC reported that the transition was from 23:30 to 24:00 today.
# https://www.bbc.com/news/world-asia-44010705
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
8:30 - KST 1912 Jan 1
9:00 - JST 1945 Sep 8
- 9:00 - KST 1954 Mar 21
+ 9:00 ROK K%sT 1954 Mar 21
8:30 ROK K%sT 1961 Aug 10
9:00 ROK K%sT
Zone Asia/Pyongyang 8:23:00 - LMT 1908 Apr 1
@@ -2252,7 +2496,7 @@ Rule Lebanon 1992 only - Oct 4 0:00 0 -
Rule Lebanon 1993 max - Mar lastSun 0:00 1:00 S
Rule Lebanon 1993 1998 - Sep lastSun 0:00 0 -
Rule Lebanon 1999 max - Oct lastSun 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Beirut 2:22:00 - LMT 1880
2:00 Lebanon EE%sT
@@ -2264,7 +2508,7 @@ Rule NBorneo 1935 1941 - Dec 14 0:00 0 -
# peninsular Malaysia
# taken from Mok Ly Yng (2003-10-30)
# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Kuala_Lumpur 6:46:46 - LMT 1901 Jan 1
6:55:25 - SMT 1905 Jun 1 # Singapore M.T.
7:00 - +07 1933 Jan 1
@@ -2278,7 +2522,7 @@ Zone Asia/Kuala_Lumpur 6:46:46 - LMT 1901 Jan 1
# From Paul Eggert (2014-08-12):
# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
# and 1982 transition dates are from Mok Ly Yng.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Kuching 7:21:20 - LMT 1926 Mar
7:30 - +0730 1933
8:00 NBorneo +08/+0820 1942 Feb 16
@@ -2286,7 +2530,7 @@ Zone Asia/Kuching 7:21:20 - LMT 1926 Mar
8:00 - +08
# Maldives
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Maldives 4:54:00 - LMT 1880 # Malé
4:54:00 - MMT 1960 # Malé Mean Time
5:00 - +05
@@ -2429,7 +2673,7 @@ Rule Mongol 2002 2006 - Mar lastSat 2:00 1:00 -
Rule Mongol 2015 2016 - Mar lastSat 2:00 1:00 -
Rule Mongol 2015 2016 - Sep lastSat 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
Zone Asia/Hovd 6:06:36 - LMT 1905 Aug
6:00 - +06 1978
@@ -2447,7 +2691,7 @@ Zone Asia/Choibalsan 7:38:00 - LMT 1905 Aug
8:00 Mongol +08/+09
# Nepal
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Kathmandu 5:41:16 - LMT 1920
5:30 - +0530 1986
5:45 - +0545
@@ -2597,7 +2841,7 @@ Rule Pakistan 2008 only - Jun 1 0:00 1:00 S
Rule Pakistan 2008 2009 - Nov 1 0:00 0 -
Rule Pakistan 2009 only - Apr 15 0:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Karachi 4:28:12 - LMT 1907
5:30 - +0530 1942 Sep
5:30 1:00 +0630 1945 Oct 15
@@ -2882,9 +3126,23 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# the official website, though the decree did not specify the exact
# time of the time shift.
# http://www.palestinecabinet.gov.ps/Website/AR/NDecrees/ViewFile.ashx?ID=e7a42ab7-ee23-435a-b9c8-a4f7e81f3817
+
+# From Even Scharning (2019-03-23):
+# http://pnn.ps/news/401130
+# http://palweather.ps/ar/node/50136.html
#
-# From Paul Eggert (2018-03-16):
-# For 2016 on, predict spring transitions on March's fourth Saturday at 01:00.
+# From Sharif Mustafa (2019-03-26):
+# The Palestinian cabinet announced today that the switch to DST will
+# be on Fri Mar 29th 2019 by advancing the clock by 60 minutes.
+# The decree signing date is Mar 12th but it was not published till today.
+# The decree does not specify the exact time of switch.
+# http://palestinecabinet.gov.ps/Website/AR/NDecrees/ViewFile.ashx?ID=e54e9ea1-50ee-4137-84df-0d6c78da259b
+#
+# From Even Scharning (2019-04-10):
+# Our source in Palestine said it happened Friday 29 at 00:00 local time....
+#
+# From Paul Eggert (2019-04-10):
+# For now, guess spring-ahead transitions are March's last Friday at 00:00.
# From Sharef Mustafa (2018-03-16):
# Palestine summer time will start on Mar 24th 2018 by advancing the
@@ -2925,10 +3183,11 @@ Rule Palestine 2012 only - Sep 21 1:00 0 -
Rule Palestine 2013 only - Sep Fri>=21 0:00 0 -
Rule Palestine 2014 2015 - Oct Fri>=21 0:00 0 -
Rule Palestine 2015 only - Mar lastFri 24:00 1:00 S
-Rule Palestine 2016 max - Mar Sat>=22 1:00 1:00 S
+Rule Palestine 2016 2018 - Mar Sat>=24 1:00 1:00 S
Rule Palestine 2016 max - Oct lastSat 1:00 0 -
+Rule Palestine 2019 max - Mar lastFri 0:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
2:00 Zion EET/EEST 1948 May 15
2:00 EgyptAsia EE%sT 1967 Jun 5
@@ -2953,6 +3212,11 @@ Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
# no information
# Philippines
+
+# From Paul Eggert (2018-11-18):
+# The Spanish initially used American (west-of-Greenwich) time.
+# It is unknown what time Manila kept when the British occupied it from
+# 1762-10-06 through 1764-04; for now assume it kept American time.
# On 1844-08-16, Narciso Clavería, governor-general of the
# Philippines, issued a proclamation announcing that 1844-12-30 was to
# be immediately followed by 1845-01-01; see R.H. van Gent's
@@ -2997,7 +3261,7 @@ Rule Phil 1954 only - Apr 12 0:00 1:00 D
Rule Phil 1954 only - Jul 1 0:00 0 S
Rule Phil 1978 only - Mar 22 0:00 1:00 D
Rule Phil 1978 only - Sep 21 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Manila -15:56:00 - LMT 1844 Dec 31
8:04:00 - LMT 1899 May 11
8:00 Phil P%sT 1942 May
@@ -3005,7 +3269,7 @@ Zone Asia/Manila -15:56:00 - LMT 1844 Dec 31
8:00 Phil P%sT
# Qatar
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha
4:00 - +04 1972 Jun
3:00 - +03
@@ -3038,8 +3302,8 @@ Link Asia/Qatar Asia/Bahrain
# going to run on Higgins Time.' And so, until last year, it did." See:
# Antar E. Dinner at When? Saudi Aramco World, 1969 March/April. 2-3.
# http://archive.aramcoworld.com/issue/196902/dinner.at.when.htm
-# newspapers.com says a similar story about Higgins was published in the Port
-# Angeles (WA) Evening News, 1965-03-10, page 5, but I lack access to the text.
+# Also see: Antar EN. Arabian flying is confusing.
+# Port Angeles (WA) Evening News. 1965-03-10. page 3.
#
# The TZ database cannot represent quasi-solar time; airline time is the best
# we can do. The 1946 foreign air news digest of the U.S. Civil Aeronautics
@@ -3053,7 +3317,7 @@ Link Asia/Qatar Asia/Bahrain
# the country. Presumably this is documenting airline time. Ignore this,
# as it's before our 1970 cutoff.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Riyadh 3:06:52 - LMT 1947 Mar 14
3:00 - +03
Link Asia/Riyadh Asia/Aden # Yemen
@@ -3062,7 +3326,7 @@ Link Asia/Riyadh Asia/Kuwait
# Singapore
# taken from Mok Ly Yng (2003-10-30)
# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
6:55:25 - SMT 1905 Jun 1 # Singapore M.T.
7:00 - +07 1933 Jan 1
@@ -3126,7 +3390,7 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1
# even worse. For now, let's use a numeric abbreviation; we can
# switch to "SLST" if it catches on.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Colombo 5:19:24 - LMT 1880
5:19:32 - MMT 1906 # Moratuwa Mean Time
5:30 - +0530 1942 Jan 5
@@ -3296,13 +3560,13 @@ Rule Syria 2010 2011 - Apr Fri>=1 0:00 1:00 S
Rule Syria 2012 max - Mar lastFri 0:00 1:00 S
Rule Syria 2009 max - Oct lastFri 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
2:00 Syria EE%sT
# Tajikistan
# From Shanks & Pottenger.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
5:00 - +05 1930 Jun 21
6:00 RussiaAsia +06/+07 1991 Mar 31 2:00s
@@ -3310,7 +3574,7 @@ Zone Asia/Dushanbe 4:35:12 - LMT 1924 May 2
5:00 - +05
# Thailand
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Bangkok 6:42:04 - LMT 1880
6:42:04 - BMT 1920 Apr # Bangkok Mean Time
7:00 - +07
@@ -3319,7 +3583,7 @@ Link Asia/Bangkok Asia/Vientiane # Laos
# Turkmenistan
# From Shanks & Pottenger.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad
4:00 - +04 1930 Jun 21
5:00 RussiaAsia +05/+06 1991 Mar 31 2:00
@@ -3327,14 +3591,14 @@ Zone Asia/Ashgabat 3:53:32 - LMT 1924 May 2 # or Ashkhabad
5:00 - +05
# United Arab Emirates
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Dubai 3:41:12 - LMT 1920
4:00 - +04
Link Asia/Dubai Asia/Muscat # Oman
# Uzbekistan
# Byalokoz 1919 says Uzbekistan was 4:27:53.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Samarkand 4:27:53 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Apr 1
@@ -3382,7 +3646,7 @@ Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2
# and in South Vietnam in particular (after 1954):
# To 07:00 on 1911-05-01.
# To 08:00 on 1942-12-31 at 23:00.
-# To 09:00 in 1945-03-14 at 23:00.
+# To 09:00 on 1945-03-14 at 23:00.
# To 07:00 on 1945-09-02 in Vietnam.
# To 08:00 on 1947-04-01 in French-controlled Indochina.
# To 07:00 on 1955-07-01 in South Vietnam.
@@ -3400,7 +3664,7 @@ Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2
# Lê Thành Lân: "Lịch hai thế kỷ (1802-2010) và các lịch vĩnh cửu",
# NXB Thuận Hoá, Huế, 1995.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1
7:06:30 - PLMT 1911 May 1 # Phù Liễn MT
7:00 - +07 1942 Dec 31 23:00
@@ -3412,5 +3676,17 @@ Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1
8:00 - +08 1975 Jun 13
7:00 - +07
+# From Paul Eggert (2019-02-19):
+#
+# The Ho Chi Minh entry suffices for most purposes as it agrees with all of
+# Vietnam since 1975-06-13. Presumably clocks often changed in south Vietnam
+# in the early 1970s as locations changed hands during the war; however the
+# details are unknown and would likely be too voluminous for this database.
+#
+# For timestamps in north Vietnam back to 1970 (the tzdb cutoff),
+# use Asia/Bangkok; see the VN entries in the file zone1970.tab.
+# For timestamps before 1970, see Asia/Hanoi in the file 'backzone'.
+
+
# Yemen
# See Asia/Riyadh.
diff --git a/make/data/tzdata/australasia b/make/data/tzdata/australasia
index 82e88c51e9..e66d5ca4d7 100644
--- a/make/data/tzdata/australasia
+++ b/make/data/tzdata/australasia
@@ -48,7 +48,7 @@ Rule Aus 1943 only - Oct 3 2:00 1:00 D
# says W Australia didn't use DST in 1943/1944. Ignore Whitman's claim that
# 1944/1945 was just like 1943/1944.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Northern Territory
Zone Australia/Darwin 8:43:20 - LMT 1895 Feb
9:00 - ACST 1899 May
@@ -125,7 +125,7 @@ Rule AS 2006 only - Apr 2 2:00s 0 S
Rule AS 2007 only - Mar lastSun 2:00s 0 S
Rule AS 2008 max - Apr Sun>=1 2:00s 0 S
Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Australia/Adelaide 9:14:20 - LMT 1895 Feb
9:00 - ACST 1899 May
9:30 Aus AC%sT 1971
@@ -157,7 +157,7 @@ Rule AT 2001 max - Oct Sun>=1 2:00s 1:00 D
Rule AT 2006 only - Apr Sun>=1 2:00s 0 S
Rule AT 2007 only - Mar lastSun 2:00s 0 S
Rule AT 2008 max - Apr Sun>=1 2:00s 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Australia/Hobart 9:49:16 - LMT 1895 Sep
10:00 - AEST 1916 Oct 1 2:00
10:00 1:00 AEDT 1917 Feb
@@ -185,7 +185,7 @@ Rule AV 2006 only - Apr Sun>=1 2:00s 0 S
Rule AV 2007 only - Mar lastSun 2:00s 0 S
Rule AV 2008 max - Apr Sun>=1 2:00s 0 S
Rule AV 2008 max - Oct Sun>=1 2:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Australia/Melbourne 9:39:52 - LMT 1895 Feb
10:00 Aus AE%sT 1971
10:00 AV AE%sT
@@ -208,7 +208,7 @@ Rule AN 2006 only - Apr Sun>=1 2:00s 0 S
Rule AN 2007 only - Mar lastSun 2:00s 0 S
Rule AN 2008 max - Apr Sun>=1 2:00s 0 S
Rule AN 2008 max - Oct Sun>=1 2:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Australia/Sydney 10:04:52 - LMT 1895 Feb
10:00 Aus AE%sT 1971
10:00 AN AE%sT
@@ -279,14 +279,14 @@ Zone Antarctica/Macquarie 0 - -00 1899 Nov
11:00 - +11
# Christmas
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Christmas 7:02:52 - LMT 1895 Feb
7:00 - +07
# Cocos (Keeling) Is
# These islands were ruled by the Ross family from about 1830 to 1978.
# We don't know when standard time was introduced; for now, we guess 1900.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Indian/Cocos 6:27:40 - LMT 1900
6:30 - +0630
@@ -390,13 +390,18 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# From Raymond Kumar (2018-07-13):
# http://www.fijitimes.com/government-approves-2018-daylight-saving/
# ... The daylight saving period will end at 3am on Sunday January 13, 2019.
-#
-# From Paul Eggert (2018-07-15):
-# For now, guess DST from 02:00 the first Sunday in November to 03:00
-# the first Sunday on or after January 13. January transitions reportedly
+
+# From Paul Eggert (2019-08-06):
+# Today Raymond Kumar reported the Government of Fiji Gazette Supplement No. 27
+# (2019-08-02) said that Fiji observes DST "commencing at 2.00 am on
+# Sunday, 10 November 2019 and ending at 3.00 am on Sunday, 12 January 2020."
+# For now, guess DST from 02:00 the second Sunday in November to 03:00
+# the first Sunday on or after January 12. January transitions reportedly
# depend on when school terms start. Although the guess is ad hoc, it matches
-# transitions since late 2014 and seems more likely to match future
-# practice than guessing no DST.
+# transitions planned this year and seems more likely to match future practice
+# than guessing no DST.
+# From Michael Deckers (2019-08-06):
+# https://www.laws.gov.fj/LawsAsMade/downloadfile/848
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 -
@@ -407,14 +412,15 @@ Rule Fiji 2010 2013 - Oct Sun>=21 2:00 1:00 -
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 -
Rule Fiji 2014 only - Jan Sun>=18 2:00 0 -
-Rule Fiji 2014 max - Nov Sun>=1 2:00 1:00 -
-Rule Fiji 2015 max - Jan Sun>=13 3:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Rule Fiji 2014 2018 - Nov Sun>=1 2:00 1:00 -
+Rule Fiji 2015 max - Jan Sun>=12 3:00 0 -
+Rule Fiji 2019 max - Nov Sun>=8 2:00 1:00 -
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva
12:00 Fiji +12/+13
# French Polynesia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Gambier -8:59:48 - LMT 1912 Oct # Rikitea
-9:00 - -09
Zone Pacific/Marquesas -9:18:00 - LMT 1912 Oct
@@ -425,15 +431,49 @@ Zone Pacific/Tahiti -9:58:16 - LMT 1912 Oct # Papeete
# it is uninhabited.
# Guam
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# http://guamlegislature.com/Public_Laws_5th/PL05-025.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-59-7-Guam-Daylight-Savings-Time-May-6-1959.pdf
+Rule Guam 1959 only - Jun 27 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-61-5-Revocation-of-Daylight-Saving-Time-and-Restoratio.pdf
+Rule Guam 1961 only - Jan 29 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-67-13-Guam-Daylight-Savings-Time.pdf
+Rule Guam 1967 only - Sep 1 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-69-2-Repeal-of-Guam-Daylight-Saving-Time.pdf
+Rule Guam 1969 only - Jan 26 0:01 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-69-10-Guam-Daylight-Saving-Time.pdf
+Rule Guam 1969 only - Jun 22 2:00 1:00 D
+Rule Guam 1969 only - Aug 31 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-70-10-Guam-Daylight-Saving-Time.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-70-30-End-of-Guam-Daylight-Saving-Time.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-71-5-Guam-Daylight-Savings-Time.pdf
+Rule Guam 1970 1971 - Apr lastSun 2:00 1:00 D
+Rule Guam 1970 1971 - Sep Sun>=1 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-73-28.-Guam-Day-light-Saving-Time.pdf
+Rule Guam 1973 only - Dec 16 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-74-7-Guam-Daylight-Savings-Time-Rescinded.pdf
+Rule Guam 1974 only - Feb 24 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-76-13-Daylight-Savings-Time.pdf
+Rule Guam 1976 only - May 26 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-76-25-Revocation-of-E.O.-76-13.pdf
+Rule Guam 1976 only - Aug 22 2:01 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-77-4-Daylight-Savings-Time.pdf
+Rule Guam 1977 only - Apr 24 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-77-18-Guam-Standard-Time.pdf
+Rule Guam 1977 only - Aug 28 2:00 0 S
+
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31
9:39:00 - LMT 1901 # Agana
- 10:00 - GST 2000 Dec 23 # Guam
+ 10:00 - GST 1941 Dec 10 # Guam
+ 9:00 - +09 1944 Jul 31
+ 10:00 Guam G%sT 2000 Dec 23
10:00 - ChST # Chamorro Standard Time
Link Pacific/Guam Pacific/Saipan # N Mariana Is
# Kiribati
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Tarawa 11:32:04 - LMT 1901 # Bairiki
12:00 - +12
Zone Pacific/Enderbury -11:24:20 - LMT 1901
@@ -449,32 +489,57 @@ Zone Pacific/Kiritimati -10:29:20 - LMT 1901
# See Pacific/Guam.
# Marshall Is
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Majuro 11:24:48 - LMT 1901
- 11:00 - +11 1969 Oct
- 12:00 - +12
-Zone Pacific/Kwajalein 11:09:20 - LMT 1901
- 11:00 - +11 1969 Oct
- -12:00 - -12 1993 Aug 20
- 12:00 - +12
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Pacific/Majuro 11:24:48 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1944 Jan 30
+ 11:00 - +11 1969 Oct
+ 12:00 - +12
+Zone Pacific/Kwajalein 11:09:20 - LMT 1901
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1944 Feb 6
+ 11:00 - +11 1969 Oct
+ -12:00 - -12 1993 Aug 20 24:00
+ 12:00 - +12
# Micronesia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Chuuk 10:07:08 - LMT 1901
- 10:00 - +10
-Zone Pacific/Pohnpei 10:32:52 - LMT 1901 # Kolonia
- 11:00 - +11
-Zone Pacific/Kosrae 10:51:56 - LMT 1901
- 11:00 - +11 1969 Oct
- 12:00 - +12 1999
- 11:00 - +11
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Pacific/Chuuk -13:52:52 - LMT 1844 Dec 31
+ 10:07:08 - LMT 1901
+ 10:00 - +10 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 10:00 - +10
+Zone Pacific/Pohnpei -13:27:08 - LMT 1844 Dec 31 # Kolonia
+ 10:32:52 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 11:00 - +11
+Zone Pacific/Kosrae -13:08:04 - LMT 1844 Dec 31
+ 10:51:56 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 11:00 - +11 1969 Oct
+ 12:00 - +12 1999
+ 11:00 - +11
# Nauru
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe
- 11:30 - +1130 1942 Mar 15
- 9:00 - +09 1944 Aug 15
- 11:30 - +1130 1979 May
+ 11:30 - +1130 1942 Aug 29
+ 9:00 - +09 1945 Sep 8
+ 11:30 - +1130 1979 Feb 10 2:00
12:00 - +12
# New Caledonia
@@ -484,7 +549,7 @@ Rule NC 1978 1979 - Feb 27 0:00 0 -
Rule NC 1996 only - Dec 1 2:00s 1:00 -
# Shanks & Pottenger say the following was at 2:00; go with IATA.
Rule NC 1997 only - Mar 2 2:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Noumea 11:05:48 - LMT 1912 Jan 13 # Nouméa
11:00 NC +11/+12
@@ -523,7 +588,7 @@ Rule NZ 2007 max - Sep lastSun 2:00s 1:00 D
Rule Chatham 2007 max - Sep lastSun 2:45s 1:00 -
Rule NZ 2008 max - Apr Sun>=1 2:00s 0 S
Rule Chatham 2008 max - Apr Sun>=1 2:45s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Auckland 11:39:04 - LMT 1868 Nov 2
11:30 NZ NZ%sT 1946 Jan 1
12:00 NZ NZ%sT
@@ -549,7 +614,7 @@ Link Pacific/Auckland Antarctica/McMurdo
Rule Cook 1978 only - Nov 12 0:00 0:30 -
Rule Cook 1979 1991 - Mar Sun>=1 0:00 0 -
Rule Cook 1979 1990 - Oct lastSun 0:00 0:30 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Rarotonga -10:39:04 - LMT 1901 # Avarua
-10:30 - -1030 1978 Nov 12
-10:00 Cook -10/-0930
@@ -558,28 +623,30 @@ Zone Pacific/Rarotonga -10:39:04 - LMT 1901 # Avarua
# Niue
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Niue -11:19:40 - LMT 1901 # Alofi
-11:20 - -1120 1951
-11:30 - -1130 1978 Oct 1
-11:00 - -11
# Norfolk
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston
11:12 - +1112 1951
- 11:30 - +1130 1974 Oct 27 02:00
- 11:30 1:00 +1230 1975 Mar 2 02:00
- 11:30 - +1130 2015 Oct 4 02:00
- 11:00 - +11
+ 11:30 - +1130 1974 Oct 27 02:00s
+ 11:30 1:00 +1230 1975 Mar 2 02:00s
+ 11:30 - +1130 2015 Oct 4 02:00s
+ 11:00 - +11 2019 Jul
+ 11:00 AN +11/+12
# Palau (Belau)
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Palau 8:57:56 - LMT 1901 # Koror
- 9:00 - +09
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Pacific/Palau -15:02:04 - LMT 1844 Dec 31 # Koror
+ 8:57:56 - LMT 1901
+ 9:00 - +09
# Papua New Guinea
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Port_Moresby 9:48:40 - LMT 1880
9:48:32 - PMMT 1895 # Port Moresby Mean Time
10:00 - +10
@@ -609,7 +676,7 @@ Zone Pacific/Bougainville 10:22:16 - LMT 1880
11:00 - +11
# Pitcairn
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Pitcairn -8:40:20 - LMT 1901 # Adamstown
-8:30 - -0830 1998 Apr 27 0:00
-8:00 - -08
@@ -694,7 +761,7 @@ Rule WS 2011 only - Apr Sat>=1 4:00 0 -
Rule WS 2011 only - Sep lastSat 3:00 1 -
Rule WS 2012 max - Apr Sun>=1 4:00 0 -
Rule WS 2012 max - Sep lastSun 3:00 1 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Apia 12:33:04 - LMT 1892 Jul 5
-11:26:56 - LMT 1911
-11:30 - -1130 1950
@@ -703,7 +770,7 @@ Zone Pacific/Apia 12:33:04 - LMT 1892 Jul 5
# Solomon Is
# excludes Bougainville, for which see Papua New Guinea
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct # Honiara
11:00 - +11
@@ -726,7 +793,7 @@ Zone Pacific/Guadalcanal 10:39:48 - LMT 1912 Oct # Honiara
# was "11 hours slow on G.M.T." Go with Thorsen and assume Shanks & Pottenger
# are off by an hour starting in 1901.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Fakaofo -11:24:56 - LMT 1901
-11:00 - -11 2011 Dec 30
13:00 - +13
@@ -739,14 +806,14 @@ Rule Tonga 2000 2001 - Nov Sun>=1 2:00 1:00 -
Rule Tonga 2001 2002 - Jan lastSun 2:00 0 -
Rule Tonga 2016 only - Nov Sun>=1 2:00 1:00 -
Rule Tonga 2017 only - Jan Sun>=15 3:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Tongatapu 12:19:20 - LMT 1901
12:20 - +1220 1941
13:00 - +13 1999
13:00 Tonga +13/+14
# Tuvalu
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Funafuti 11:56:52 - LMT 1901
12:00 - +12
@@ -807,7 +874,7 @@ Zone Pacific/Funafuti 11:56:52 - LMT 1901
# uninhabited since World War II; was probably like Pacific/Kiritimati
# Wake
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Wake 11:06:28 - LMT 1901
12:00 - +12
@@ -820,12 +887,12 @@ Rule Vanuatu 1984 only - Oct 23 0:00 1:00 -
Rule Vanuatu 1985 1991 - Sep Sun>=23 0:00 1:00 -
Rule Vanuatu 1992 1993 - Jan Sun>=23 0:00 0 -
Rule Vanuatu 1992 only - Oct Sun>=23 0:00 1:00 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Efate 11:13:16 - LMT 1912 Jan 13 # Vila
11:00 Vanuatu +11/+12
# Wallis and Futuna
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Wallis 12:15:20 - LMT 1901
12:00 - +12
@@ -838,7 +905,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2017-02-10):
+# From Paul Eggert (2018-11-18):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -863,6 +930,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
+# I invented the abbreviation marked "*".
# The following abbreviations are from other sources.
# Corrections are welcome!
# std dst
@@ -870,7 +938,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# 8:00 AWST AWDT Western Australia
# 9:30 ACST ACDT Central Australia
# 10:00 AEST AEDT Eastern Australia
-# 10:00 GST Guam through 2000
+# 10:00 GST GDT* Guam through 2000
# 10:00 ChST Chamorro
# 11:30 NZMT NZST New Zealand through 1945
# 12:00 NZST NZDT New Zealand 1946-present
@@ -1210,6 +1278,22 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# in WA or its introduction in SA had anything to do with the genesis
# of this time zone. My hunch is that it's been around since well
# before 1975. I remember seeing it noted on road maps decades ago.
+#
+# From Gilmore Davidson (2019-04-08):
+# https://www.abc.net.au/news/2019-04-08/this-remote-stretch-of-desert-has-its-own-custom-time-zone/10981000
+# ... include[s] a rough description of the geographical boundaries...
+# "The time zone exists for about 340 kilometres and takes in the tiny
+# roadhouse communities of Cocklebiddy, Madura, Eucla and Border Village."
+# ... and an indication that the zone has definitely been in existence
+# since before the 1970 cut-off of the database ...
+# From Paul Eggert (2019-05-17):
+# That ABC Esperance story by Christien de Garis also says:
+# Although the Central Western Time Zone is not officially recognised (your
+# phones won't automatically change), there is a sign instructing you which
+# way to wind your clocks 45 minutes and scrawled underneath one of them in
+# Texta is the word: 'Why'?
+# "Good question," Mr Pike said.
+# "I don't even know that, and it's been going for over 50 years."
# From Paul Eggert (2006-12-15):
# For lack of better info, assume the tradition dates back to the
@@ -1528,6 +1612,42 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
###############################################################################
+# Bonin (Ogasawara) Islands and Marcus Island (Minami-Tori-shima)
+
+# From Wakaba (2019-01-28) via Phake Nick:
+# National Diet Library of Japan has several reports by Japanese Government
+# officers that describe the time used in islands when they visited there.
+# According to them (and other sources such as newspapers), standard time UTC
+# + 10 (JST + 1) and DST UTC + 11 (JST + 2) was used until its return to Japan
+# at 1968-06-26 00:00 JST. The exact periods of DST are still unknown.
+# I guessed Guam, Mariana, and Bonin and Marcus districts might have
+# synchronized their DST periods, but reports imply they had their own
+# decisions, i.e. there were three or more different time zones....
+#
+# https://wiki.suikawiki.org/n/小笠原諸島の標準時
+
+# From Phake Nick (2019-02-12):
+# Because their last time change to return to Japanese time when they returned
+# to Japanese rule was right before 1970, ... per the current tz database
+# rule, the information doesn't warrant creation of a new timezone for Bonin
+# Islands itself and is thus as an anecdotal note for interest purpose only.
+# ... [The abovementioned link] described some special timekeeping phenomenon
+# regarding Marcus island, another remote island currently owned by Japanese
+# in the same administrative unit as Bonin Islands. Many reports claim that
+# the American coastal guard on the American quarter of the island use its own
+# coastal guard time, and most sources describe the time as UTC+11, being two
+# hours faster than JST used by some Japanese personnel on the island. Some
+# sites describe it as same as Wake Island/Guam time although it would be
+# incorrect to be same as Guam. And then in a few Japanese governmental
+# report from 1980s (from National Institute of Information and Communications
+# Technology) regarding the construction of VLBI facility on the Marcus
+# Island, it claimed that there are three time standards being used on the
+# island at the time which include not just JST (UTC+9) or [US]CG time
+# (UTC+11) but also a JMSDF time (UTC+10) (Japan Maritime Self-Defense
+# Force). Unfortunately there are no other sources that mentioned such time
+# and there are also no information on things like how the time was used.
+
+
# Fiji
# Howse writes (p 153) that in 1879 the British governor of Fiji
@@ -1569,28 +1689,70 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Kwajalein
-# In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
-# I wonder what happened in Kwajalein, where there was NO Friday,
-# 1993-08-20. Thursday night at midnight Kwajalein switched sides with
-# respect to the International Date Line, to rejoin its fellow islands,
-# going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink.
+# From an AP article (1993-08-22):
+# "The nearly 3,000 Americans living on this remote Pacific atoll have a good
+# excuse for not remembering Saturday night: there wasn't one. Residents were
+# going to bed Friday night and waking up Sunday morning because at midnight
+# -- 8 A.M. Eastern daylight time on Saturday -- Kwajalein was jumping from
+# one side of the international date line to the other."
+# "In Marshall Islands, Friday is followed by Sunday", NY Times. 1993-08-22.
+# https://www.nytimes.com/1993/08/22/world/in-marshall-islands-friday-is-followed-by-sunday.html
+
+# From Phake Nick (2018-10-27):
+# <https://wiki.suikawiki.org/n/南洋群島の標準時> ... pointed out that
+# currently tzdata say Pacific/Kwajalein switched from GMT+11 to GMT-12 in
+# 1969 October without explanation, however an 1993 article from NYT say it
+# synchorized its day with US mainland about 40 years ago and thus the switch
+# should occur at around 1950s instead.
+#
+# From Paul Eggert (2018-11-18):
+# The NYT (actually, AP) article is vague and possibly wrong about this.
+# The article says the earlier switch was "40 years ago when the United States
+# Army established a missile test range here". However, the Kwajalein Test
+# Center was established on 1960-10-01 and was run by the US Navy. It was
+# transferred to the US Army on 1964-07-01. See "Seize the High Ground"
+# <https://history.army.mil/html/books/070/70-88-1/cmhPub_70-88-1.pdf>.
+# Given that Shanks was right on the money about the 1993 change, I'm inclined
+# to take Shanks's word for the 1969 change unless we find better evidence.
# N Mariana Is, Guam
+# From Phake Nick (2018-10-27):
+# Guam Island was briefly annexed by Japan during ... year 1941-1944 ...
+# however there are no detailed information about what time it use during that
+# period. It would probably be reasonable to assume Guam use GMT+9 during
+# that period of time like the surrounding area.
+
+# From Paul Eggert (2018-11-18):
# Howse writes (p 153) "The Spaniards, on the other hand, reached the
# Philippines and the Ladrones from America," and implies that the Ladrones
# (now called the Marianas) kept American date for quite some time.
# For now, we assume the Ladrones switched at the same time as the Philippines;
# see Asia/Manila.
-
+#
+# Use 1941-12-10 and 1944-07-31 for Guam WWII transitions, as the rough start
+# and end of Japanese control of Agana. We don't know whether the Northern
+# Marianas followed Guam's DST rules from 1959 through 1977; for now, assume
+# they did as that avoids the need for a separate zone due to our 1970 cutoff.
+#
# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time,
# under the name "Chamorro Standard Time". There is no official abbreviation,
# but Congressman Robert A. Underwood, author of the bill that became law,
# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
+# See also the commentary for Micronesia.
+
+
+# Marshall Is
+# See the commentary for Micronesia.
-# Micronesia
+
+# Micronesia (and nearby)
+
+# From Paul Eggert (2018-11-18):
+# Like the Ladrones (see Guam commentary), assume the Spanish East Indies
+# kept American time until the Philippines switched at the end of 1844.
# Alan Eugene Davis writes (1996-03-16),
# "I am certain, having lived there for the past decade, that 'Truk'
@@ -1606,6 +1768,95 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# that Truk and Yap are UT +10, and Ponape and Kosrae are +11.
# We don't know when Kosrae switched from +12; assume January 1 for now.
+# From Phake Nick (2018-10-27):
+#
+# From a Japanese wiki site https://wiki.suikawiki.org/n/南洋群島の標準時
+# ...
+# For "Southern Islands" (modern region of Mariana + Palau + Federation of
+# Micronesia + Marshall Islands):
+#
+# A 1906 Japanese magazine shown the Caroline Islands and Mariana Islands
+# who was occupied by Germany at the time as GMT+10, together with the like
+# of German New Guinea. However there is a marking saying it have not been
+# implemented (yet). No further information after that were found.
+#
+# Japan invaded those islands in 1914, and records shows that they were
+# instructed to use JST at the time.
+#
+# 1915 January telecommunication record on the Jaluit Atoll shows they use
+# the meridian of 170E as standard time (GMT+11:20), which is similar to the
+# longitude of the atoll.
+# 1915 February record say the 170E standard time is to be used until
+# February 9 noon, and after February 9 noon they are to use JST.
+# However these are time used within the Japanese Military at the time and
+# probably does not reflect the time used by local resident at the time (that
+# is if they keep their own time back then)
+#
+# In January 1919 the occupying force issued a command that split the area
+# into three different timezone with meridian of 135E, 150E, 165E (JST+0, +1,
+# +2), and the command was to become effective from February 1 of the same
+# year. Despite the target of the command is still only for the occupying
+# force itself, further publication have described the time as the standard
+# time for the occupied area and thus it can probably be seen as such.
+# * Area that use meridian of 135E: Palau and Yap civil administration area
+# (Southern Islands Western Standard Time)
+# * Area that use meridian of 150E: Truk (Chuuk) and Saipan civil
+# administration area (Southern Islands Central Standard Time)
+# * Area that use meridian of 165E: Ponape (Pohnpei) and Jaluit civil
+# administration area (Southern Islands Eastern Standard Time).
+# * In the next few years Japanese occupation of those islands have been
+# formalized via League of Nation Mandate (South Pacific Mandate) and formal
+# governance structure have been established, these district [become
+# subprefectures] and timezone classification have been inherited as standard
+# time of the area.
+# * Saipan subprefecture include Mariana islands (exclude Guam which was
+# occupied by America at the time), Palau and Yap subprefecture rule the
+# Western Caroline Islands with 137E longitude as border, Truk and Ponape
+# subprefecture rule the Eastern Caroline Islands with 154E as border, Ponape
+# subprefecture also rule part of Marshall Islands to the west of 164E
+# starting from (1918?) and Jaluit subprefecture rule the rest of the
+# Marshall Islands.
+#
+# And then in year 1937, an announcement was made to change the time in the
+# area into 2 timezones:
+# * Area that use meridian of 135E: area administered by Palau, Yap and
+# Saipan subprefecture (Southern Islands Western Standard Time)
+# * Area that use meridian of 150E: area administered by Truk (Chuuk),
+# Ponape (Pohnpei) and Jaluit subprefecture (Southern Islands Eastern
+# Standard Time)
+#
+# Another announcement issued in 1941 say that on April 1 that year,
+# standard time of the Southern Islands would be changed to use the meridian
+# of 135E (GMT+9), and thus abolishing timezone different within the area.
+#
+# Then Pacific theater of WWII started and Japan slowly lose control on the
+# island. The webpage I linked above contain no information during this
+# period of time....
+#
+# After the end of WWII, in 1946 February, a document written by the
+# (former?) Japanese military personnel describe there are 3 hours time
+# different between Caroline islands time/Wake island time and the Chungking
+# time, which would mean the time being used there at the time was GMT+10.
+#
+# After that, the area become Trust Territories of the Pacific Islands
+# under American administration from year 1947. The site listed some
+# American/International books/maps/publications about time used in those
+# area during this period of time but they doesn't seems to be reliable
+# information so it would be the best if someone know where can more reliable
+# information can be found.
+#
+#
+# From Paul Eggert (2018-11-18):
+#
+# For the above, use vague dates like "1914" and "1945" for transitions that
+# plausibly exist but for which the details are not known. The information
+# for Wake is too sketchy to act on.
+#
+# The 1906 GMT+10 info about German-controlled islands might not have been
+# done, so omit it from the data for now.
+#
+# The Jaluit info governs Kwajalein.
+
# Midway
@@ -1623,6 +1874,29 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# started DST on June 3. Possibly DST was observed other years
# in Midway, but we have no record of it.
+# Nauru
+
+# From Phake Nick (2018-10-31):
+# Currently, the tz database say Nauru use LMT until 1921, and then
+# switched to GMT+11:30 for the next two decades.
+# However, a number of timezone map published in America/Japan back then
+# showed its timezone as GMT+11 per https://wiki.suikawiki.org/n/ナウルの標準時
+# And it would also be nice if the 1921 transition date could be sourced.
+# ...
+# The "Nauru Standard Time Act 1978 Time Change"
+# http://ronlaw.gov.nr/nauru_lpms/files/gazettes/4b23a17d2030150404db7a5fa5872f52.pdf#page=3
+# based on "Nauru Standard Time Act 1978 Time Change"
+# http://www.paclii.org/nr/legis/num_act/nsta1978207/ defined that "Nauru
+# Alternative Time" (GMT+12) should be in effect from 1979 Feb.
+#
+# From Paul Eggert (2018-11-19):
+# The 1921-01-15 introduction of standard time is in Shanks; it is also in
+# "Standard Time Throughout the World", US National Bureau of Standards (1935),
+# page 3, which does not give the UT offset. In response to a comment by
+# Phake Nick I set the Nauru time of occupation by Japan to
+# 1942-08-29/1945-09-08 by using dates from:
+# https://en.wikipedia.org/wiki/Japanese_occupation_of_Nauru
+
# Norfolk
# From Alexander Krivenyshev (2015-09-23):
@@ -1631,12 +1905,24 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# ... at 12.30 am (by legal time in New South Wales) on 4 October 2015.
# http://www.norfolkisland.gov.nf/nia/MediaRelease/Media%20Release%20Norfolk%20Island%20Standard%20Time%20Change.pdf
-# From Paul Eggert (2015-09-23):
+# From Paul Eggert (2019-08-28):
# Transitions before 2015 are from timeanddate.com, which consulted
# the Norfolk Island Museum and the Australian Bureau of Meteorology's
# Norfolk Island station, and found no record of Norfolk observing DST
# other than in 1974/5. See:
# https://www.timeanddate.com/time/australia/norfolk-island.html
+# However, disagree with timeanddate about the 1975-03-02 transition;
+# timeanddate has 02:00 but 02:00s corresponds to what the NSW law said
+# (thanks to Michael Deckers).
+
+# Norfolk started observing Australian DST in spring 2019.
+# From Kyle Czech (2019-08-13):
+# https://www.legislation.gov.au/Details/F2018L01702
+# From Michael Deckers (2019-08-14):
+# https://www.legislation.gov.au/Details/F2019C00010
+
+# Palau
+# See commentary for Micronesia.
# Pitcairn
@@ -1802,6 +2088,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# From Paul Eggert (2003-03-23):
# We have no other report of DST in Wake Island, so omit this info for now.
+# See also the commentary for Micronesia.
+
+
###############################################################################
# The International Date Line
diff --git a/make/data/tzdata/backward b/make/data/tzdata/backward
index f30f30e511..2a41a98010 100644
--- a/make/data/tzdata/backward
+++ b/make/data/tzdata/backward
@@ -100,6 +100,7 @@ Link Pacific/Easter Chile/EasterIsland
Link America/Havana Cuba
Link Africa/Cairo Egypt
Link Europe/Dublin Eire
+Link Etc/UTC Etc/UCT
Link Europe/London Europe/Belfast
Link Europe/Chisinau Europe/Tiraspol
Link Europe/London GB
@@ -134,7 +135,7 @@ Link Asia/Taipei ROC
Link Asia/Seoul ROK
Link Asia/Singapore Singapore
Link Europe/Istanbul Turkey
-Link Etc/UCT UCT
+Link Etc/UTC UCT
Link America/Anchorage US/Alaska
Link America/Adak US/Aleutian
Link America/Phoenix US/Arizona
diff --git a/make/data/tzdata/etcetera b/make/data/tzdata/etcetera
index db5937879e..7c7eab1f6a 100644
--- a/make/data/tzdata/etcetera
+++ b/make/data/tzdata/etcetera
@@ -42,7 +42,6 @@
Zone Etc/GMT 0 - GMT
Zone Etc/UTC 0 - UTC
-Zone Etc/UCT 0 - UCT
# The following link uses older naming conventions,
# but it belongs here, not in the file 'backward',
diff --git a/make/data/tzdata/europe b/make/data/tzdata/europe
index e434b7e9fc..5c49a4a77b 100644
--- a/make/data/tzdata/europe
+++ b/make/data/tzdata/europe
@@ -145,7 +145,7 @@
# position is 51° 28' 30" N, 0° 18' 45" W. The longitude should
# be within about ±2". The Ordnance Survey grid reference is TQ172761.
#
-# [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
+# [This yields STDOFF = -0:01:15 for London LMT in the 18th century.]
# From Paul Eggert (1993-11-18):
#
@@ -523,7 +523,7 @@ Rule GB-Eire 1990 1995 - Oct Sun>=22 1:00u 0 GMT
#
# Use Europe/London for Jersey, Guernsey, and the Isle of Man.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/London -0:01:15 - LMT 1847 Dec 1 0:00s
0:00 GB-Eire %s 1968 Oct 27
1:00 - BST 1971 Oct 31 2:00u
@@ -561,7 +561,7 @@ Link Europe/London Europe/Isle_of_Man
#Rule Eire 1990 1995 - Oct Sun>=22 1:00u -1:00 -
#Rule Eire 1996 max - Oct lastSun 1:00u -1:00 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Dublin -0:25:00 - LMT 1880 Aug 2
-0:25:21 - DMT 1916 May 21 2:00s
-0:25:21 1:00 IST 1916 Oct 1 2:00s
@@ -760,7 +760,7 @@ Rule Russia 1996 2010 - Oct lastSun 2:00s 0 -
# These are for backward compatibility with older versions.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone WET 0:00 EU WE%sT
Zone CET 1:00 C-Eur CE%sT
Zone MET 1:00 C-Eur ME%sT
@@ -820,14 +820,14 @@ Rule Albania 1982 only - Oct 3 0:00 0 -
Rule Albania 1983 only - Apr 18 0:00 1:00 S
Rule Albania 1983 only - Oct 1 0:00 0 -
Rule Albania 1984 only - Apr 1 0:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Tirane 1:19:20 - LMT 1914
1:00 - CET 1940 Jun 16
1:00 Albania CE%sT 1984 Jul
1:00 EU CE%sT
# Andorra
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Andorra 0:06:04 - LMT 1901
0:00 - WET 1946 Sep 30
1:00 - CET 1985 Mar 31 2:00
@@ -844,16 +844,21 @@ Zone Europe/Andorra 0:06:04 - LMT 1901
# Shanks & Pottenger give 02:00, the BEV 00:00. Go with the BEV,
# and guess 02:00 for 1945-04-12.
+# From Alois Triendl (2019-07-22):
+# In 1946 the end of DST was on Monday, 7 October 1946, at 3:00 am.
+# Shanks had this right. Source: Die Weltpresse, 5. Oktober 1946, page 5.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Austria 1920 only - Apr 5 2:00s 1:00 S
Rule Austria 1920 only - Sep 13 2:00s 0 -
Rule Austria 1946 only - Apr 14 2:00s 1:00 S
-Rule Austria 1946 1948 - Oct Sun>=1 2:00s 0 -
+Rule Austria 1946 only - Oct 7 2:00s 0 -
+Rule Austria 1947 1948 - Oct Sun>=1 2:00s 0 -
Rule Austria 1947 only - Apr 6 2:00s 1:00 S
Rule Austria 1948 only - Apr 18 2:00s 1:00 S
Rule Austria 1980 only - Apr 6 0:00 1:00 S
Rule Austria 1980 only - Sep 28 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Vienna 1:05:21 - LMT 1893 Apr
1:00 C-Eur CE%sT 1920
1:00 Austria CE%sT 1940 Apr 1 2:00s
@@ -885,7 +890,7 @@ Zone Europe/Vienna 1:05:21 - LMT 1893 Apr
# Belarussian government decided against changing to winter time....
# http://eng.belta.by/all_news/society/Belarus-decides-against-adjusting-time-in-Russias-wake_i_76335.html
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Minsk 1:50:16 - LMT 1880
1:50 - MMT 1924 May 2 # Minsk Mean Time
2:00 - EET 1930 Jun 21
@@ -898,15 +903,35 @@ Zone Europe/Minsk 1:50:16 - LMT 1880
# Belgium
#
-# From Paul Eggert (1997-07-02):
+# From Michael Deckers (2019-08-25):
+# The exposition in the web page
+# https://www.bestor.be/wiki/index.php/Voyager_dans_le_temps._L%E2%80%99introduction_de_la_norme_de_Greenwich_en_Belgique
+# gives several contemporary sources from which one can conclude that
+# the switch in Europe/Brussels on 1892-05-01 was from 00:17:30 to 00:00:00.
+#
+# From Paul Eggert (2019-08-28):
+# This quote helps explain the late-1914 situation:
+# In early November 1914, the Germans imposed the time zone used in central
+# Europe and forced the inhabitants to set their watches and public clocks
+# sixty minutes ahead. Many were reluctant to accept "German time" and
+# continued to use "Belgian time" among themselves. Reflecting the spirit of
+# resistance that arose in the population, a song made fun of this change....
+# The song ended:
+# Putting your clock forward
+# Will but hasten the happy hour
+# When we kick out the Boches!
+# See: Pluvinage G. Brussels on German time. Cahiers Bruxellois -
+# Brusselse Cahiers. 2014;XLVI(1E):15-38.
+# https://www.cairn.info/revue-cahiers-bruxellois-2014-1E-page-15.htm
+#
+# Entries from 1914 through 1917 are taken from "De tijd in België"
+# <https://www.astro.oma.be/GENERAL/INFO/nli001a.html>.
# Entries from 1918 through 1991 are taken from:
# Annuaire de L'Observatoire Royal de Belgique,
# Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
# (Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
# pp 8-9.
-# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
-# Moniteur Belge, Samedi 30 Avril 1892, N.121.
-# Thanks to Pascal Delmoitie for these references.
+# Thanks to Pascal Delmoitie for the 1918/1991 references.
# The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
# Assume Brussels switched to WET in 1918 when the armistice took effect.
#
@@ -949,9 +974,9 @@ Rule Belgium 1945 only - Apr 2 2:00s 1:00 S
Rule Belgium 1945 only - Sep 16 2:00s 0 -
Rule Belgium 1946 only - May 19 2:00s 1:00 S
Rule Belgium 1946 only - Oct 7 2:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Brussels 0:17:30 - LMT 1880
- 0:17:30 - BMT 1892 May 1 12:00 # Brussels MT
+ 0:17:30 - BMT 1892 May 1 00:17:30
0:00 - WET 1914 Nov 8
1:00 - CET 1916 May 1 0:00
1:00 C-Eur CE%sT 1918 Nov 11 11:00u
@@ -976,7 +1001,7 @@ Rule Bulg 1979 only - Oct 1 1:00 0 -
Rule Bulg 1980 1982 - Apr Sat>=1 23:00 1:00 S
Rule Bulg 1980 only - Sep 29 1:00 0 -
Rule Bulg 1981 only - Sep 27 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Sofia 1:33:16 - LMT 1880
1:56:56 - IMT 1894 Nov 30 # Istanbul MT?
2:00 - EET 1942 Nov 2 3:00
@@ -1009,7 +1034,7 @@ Rule Czech 1946 only - May 6 2:00s 1:00 S
Rule Czech 1946 1949 - Oct Sun>=1 2:00s 0 -
Rule Czech 1947 1948 - Apr Sun>=15 2:00s 1:00 S
Rule Czech 1949 only - Apr 9 2:00s 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Prague 0:57:44 - LMT 1850
0:57:44 - PMT 1891 Oct # Prague Mean Time
1:00 C-Eur CE%sT 1945 May 9
@@ -1071,7 +1096,7 @@ Rule Denmark 1947 only - Aug 10 2:00s 0 -
Rule Denmark 1948 only - May 9 2:00s 1:00 S
Rule Denmark 1948 only - Aug 8 2:00s 0 -
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Copenhagen 0:50:20 - LMT 1890
0:50:20 - CMT 1894 Jan 1 # Copenhagen MT
1:00 Denmark CE%sT 1942 Nov 2 2:00s
@@ -1168,7 +1193,7 @@ Rule Thule 1993 2006 - Oct lastSun 2:00 0 S
Rule Thule 2007 max - Mar Sun>=8 2:00 1:00 D
Rule Thule 2007 max - Nov Sun>=1 2:00 0 S
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Danmarkshavn -1:14:40 - LMT 1916 Jul 28
-3:00 - -03 1980 Apr 6 2:00
-3:00 EU -03/-02 1996
@@ -1234,7 +1259,7 @@ Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik air base
# From Urmet Jänes (2002-03-28):
# The legislative reference is Government decree No. 84 on 2002-02-21.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Tallinn 1:39:00 - LMT 1880
1:39:00 - TMT 1918 Feb # Tallinn Mean Time
1:00 C-Eur CE%sT 1919 Jul
@@ -1297,7 +1322,7 @@ Rule Finland 1981 1982 - Sep lastSun 3:00 0 -
# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
# round to nearest.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Helsinki 1:39:49 - LMT 1878 May 31
1:39:49 - HMT 1921 May # Helsinki Mean Time
2:00 Finland EE%sT 1983
@@ -1387,7 +1412,7 @@ Rule France 1976 only - Sep 26 1:00 0 -
# but Howse quotes the actual French legislation as saying 0:09:21.
# Go with Howse. Howse writes that the time in France was officially based
# on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15 0:01
0:09:21 - PMT 1911 Mar 11 0:01 # Paris MT
# Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
@@ -1435,7 +1460,7 @@ Rule SovietZone 1945 only - May 24 2:00 2:00 M # Midsummer
Rule SovietZone 1945 only - Sep 24 3:00 1:00 S
Rule SovietZone 1945 only - Nov 18 2:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Berlin 0:53:28 - LMT 1893 Apr
1:00 C-Eur CE%sT 1945 May 24 2:00
1:00 SovietZone CE%sT 1946
@@ -1463,7 +1488,7 @@ Link Europe/Zurich Europe/Busingen
# is in Europe. Our reference location Tbilisi is in the Asian part.
# Gibraltar
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Gibraltar -0:21:24 - LMT 1880 Aug 2 0:00s
0:00 GB-Eire %s 1957 Apr 14 2:00
1:00 - CET 1982
@@ -1494,7 +1519,7 @@ Rule Greece 1979 only - Apr 1 9:00 1:00 S
Rule Greece 1979 only - Sep 29 2:00 0 -
Rule Greece 1980 only - Apr 1 0:00 1:00 S
Rule Greece 1980 only - Sep 28 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Athens 1:34:52 - LMT 1895 Sep 14
1:34:52 - AMT 1916 Jul 28 0:01 # Athens MT
2:00 Greece EE%sT 1941 Apr 30
@@ -1531,7 +1556,7 @@ Rule Hungary 1956 only - Sep lastSun 0:00 0 -
Rule Hungary 1957 only - Jun Sun>=1 1:00 1:00 S
Rule Hungary 1957 only - Sep lastSun 3:00 0 -
Rule Hungary 1980 only - Apr 6 1:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Budapest 1:16:20 - LMT 1890 Oct
1:00 C-Eur CE%sT 1918
1:00 Hungary CE%sT 1941 Apr 8
@@ -1592,7 +1617,7 @@ Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 -
Rule Iceland 1949 only - Oct 30 1:00s 0 -
Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 -
Rule Iceland 1967 only - Oct 29 1:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Atlantic/Reykjavik -1:28 - LMT 1908
-1:00 Iceland -01/+00 1968 Apr 7 1:00s
0:00 - GMT
@@ -1606,6 +1631,25 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# But these events all occurred before the 1970 cutoff,
# so record only the time in Rome.
#
+# From Stephen Trainor (2019-05-06):
+# http://www.ac-ilsestante.it/MERIDIANE/ora_legale/ORA_LEGALE_ESTIVA_IN_ITALIA.htm
+# ... the [1866] law went into effect on 12 December 1866, rather than
+# the date of the decree (22 Sep 1866)
+# https://web.archive.org/web/20070824155341/http://www.iav.it/planetario/didastro/didastro/english.htm
+# ... "In Italy in 1866 there were 6 railway times (Torino, Verona, Firenze,
+# Roma, Napoli, Palermo). On that year it was decided to unify them, adopting
+# the average time of Rome (even if this city was not yet part of the
+# kingdom). On the 12th December 1866, on the starting of the winter time
+# table, it took effect in the railways, the post office and the telegraph,
+# not only for the internal service but also for the public.... Milano set
+# the public watches on the Rome time on the same day (12th December 1866),
+# Torino and Bologna on the 1st January 1867, Venezia the 1st May 1880 and the
+# last city was Cagliari in 1886."
+#
+# From Luigi Rosa (2019-05-07):
+# this is the scan of the decree:
+# http://www.radiomarconi.com/marconi/filopanti/1866c.jpg
+#
# From Michael Deckers (2016-10-24):
# http://www.ac-ilsestante.it/MERIDIANE/ora_legale quotes a law of 1893-08-10
# ... [translated as] "The preceding dispositions will enter into
@@ -1616,6 +1660,7 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# The authoritative source for time in Italy is the national metrological
# institute, which has a summary page of historical DST data at
# http://www.inrim.it/res/tf/ora_legale_i.shtml
+# [now at http://oldsite.inrim.it/res/tf/ora_legale_i.shtml as of 2017]
# (2016-10-24):
# http://www.renzobaldini.it/le-ore-legali-in-italia/
# has still different data for 1944. It divides Italy in two, as
@@ -1630,6 +1675,13 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
# Starting at hour three on the date 1944-09-17 standard time will be resumed.
#
+# From Alois Triendl (2019-07-02):
+# I spent 6 Euros to buy two archive copies of Il Messaggero, a Roman paper,
+# for 1 and 2 April 1944. The edition of 2 April has this note: "Tonight at 2
+# am, put forward the clock by one hour. Remember that in the night between
+# today and Monday the 'ora legale' will come in force again." That makes it
+# clear that in Rome the change was on Monday, 3 April 1944 at 2 am.
+#
# From Paul Eggert (2016-10-27):
# Go with INRiM for DST rules, except as corrected by Inglis for 1944
# for the Kingdom of Italy. This is consistent with Renzo Baldini.
@@ -1679,8 +1731,8 @@ Rule Italy 1976 only - May 30 0:00s 1:00 S
Rule Italy 1977 1979 - May Sun>=22 0:00s 1:00 S
Rule Italy 1978 only - Oct 1 0:00s 0 -
Rule Italy 1979 only - Sep 30 0:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Europe/Rome 0:49:56 - LMT 1866 Sep 22
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
+Zone Europe/Rome 0:49:56 - LMT 1866 Dec 12
0:49:56 - RMT 1893 Oct 31 23:49:56 # Rome Mean
1:00 Italy CE%sT 1943 Sep 10
1:00 C-Eur CE%sT 1944 Jun 4
@@ -1755,7 +1807,7 @@ Rule Latvia 1989 1996 - Sep lastSun 2:00s 0 -
# Byalokoz 1919 says Latvia was 1:36:34.
# Go with Byalokoz.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Riga 1:36:34 - LMT 1880
1:36:34 - RMT 1918 Apr 15 2:00 # Riga MT
1:36:34 1:00 LST 1918 Sep 16 3:00 # Latvian ST
@@ -1777,15 +1829,10 @@ Zone Europe/Riga 1:36:34 - LMT 1880
# From Paul Eggert (2013-09-09):
# Shanks & Pottenger say Vaduz is like Zurich.
-# From Alois Treindl (2013-09-18):
-# http://www.eliechtensteinensia.li/LIJ/1978/1938-1978/1941.pdf
-# ... confirms on p. 6 that Liechtenstein followed Switzerland in 1941 and 1942.
-# I ... translate only the last two paragraphs:
-# ... during second world war, in the years 1941 and 1942, Liechtenstein
-# introduced daylight saving time, adapting to Switzerland. From 1943 on
-# central European time was in force throughout the year.
-# From a report of the duke's government to the high council,
-# regarding the introduction of a time law, of 31 May 1977.
+# From Alois Treindl (2019-07-04):
+# I was able to access the online archive of the Vaduz paper Vaterland ...
+# I could confirm from the paper that Liechtenstein did in fact follow
+# the same DST in 1941 and 1942 as Switzerland did.
Link Europe/Zurich Europe/Vaduz
@@ -1825,7 +1872,7 @@ Link Europe/Zurich Europe/Vaduz
# http://www.lrvk.lt/nut/11/n1749.htm
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Vilnius 1:41:16 - LMT 1880
1:24:00 - WMT 1917 # Warsaw Mean Time
1:35:36 - KMT 1919 Oct 10 # Kaunas Mean Time
@@ -1869,7 +1916,7 @@ Rule Lux 1926 only - Apr 17 23:00 1:00 S
Rule Lux 1927 only - Apr 9 23:00 1:00 S
Rule Lux 1928 only - Apr 14 23:00 1:00 S
Rule Lux 1929 only - Apr 20 23:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
1:00 Lux CE%sT 1918 Nov 25
0:00 Lux WE%sT 1929 Oct 6 2:00s
@@ -1878,7 +1925,7 @@ Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
1:00 Belgium CE%sT 1977
1:00 EU CE%sT
-# Macedonia
+# North Macedonia
# See Europe/Belgrade.
# Malta
@@ -1894,7 +1941,7 @@ Rule Malta 1974 only - Sep 16 0:00s 0 -
Rule Malta 1975 1979 - Apr Sun>=15 2:00 1:00 S
Rule Malta 1975 1980 - Sep Sun>=15 2:00 0 -
Rule Malta 1980 only - Mar 31 2:00 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
1:00 Italy CE%sT 1973 Mar 31
1:00 Malta CE%sT 1981
@@ -1963,7 +2010,7 @@ Zone Europe/Malta 0:58:04 - LMT 1893 Nov 2 0:00s # Valletta
Rule Moldova 1997 max - Mar lastSun 2:00 1:00 S
Rule Moldova 1997 max - Oct lastSun 3:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Chisinau 1:55:20 - LMT 1880
1:55 - CMT 1918 Feb 15 # Chisinau MT
1:44:24 - BMT 1931 Jul 24 # Bucharest MT
@@ -1979,7 +2026,7 @@ Zone Europe/Chisinau 1:55:20 - LMT 1880
# Monaco
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
# more precise 0:09:21.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
0:09:21 - PMT 1911 Mar 11 # Paris Mean Time
0:00 France WE%sT 1945 Sep 16 3:00
@@ -2054,8 +2101,8 @@ Rule Neth 1945 only - Apr 2 2:00s 1:00 S
Rule Neth 1945 only - Sep 16 2:00s 0 -
#
# Amsterdam Mean Time was +00:19:32.13, but the .13 is omitted
-# below because the current format requires GMTOFF to be an integer.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# below because the current format requires STDOFF to be an integer.
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Amsterdam 0:19:32 - LMT 1835
0:19:32 Neth %s 1937 Jul 1
0:20 Neth +0020/+0120 1940 May 16 0:00
@@ -2074,7 +2121,7 @@ Rule Norway 1945 only - Oct 1 2:00s 0 -
Rule Norway 1959 1964 - Mar Sun>=15 2:00s 1:00 S
Rule Norway 1959 1965 - Sep Sun>=15 2:00s 0 -
Rule Norway 1965 only - Apr 25 2:00s 1:00 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Oslo 0:43:00 - LMT 1895 Jan 1
1:00 Norway CE%sT 1940 Aug 10 23:00
1:00 C-Eur CE%sT 1945 Apr 2 2:00
@@ -2165,7 +2212,7 @@ Rule Poland 1959 1961 - Oct Sun>=1 1:00s 0 -
Rule Poland 1960 only - Apr 3 1:00s 1:00 S
Rule Poland 1961 1964 - May lastSun 1:00s 1:00 S
Rule Poland 1962 1964 - Sep lastSun 1:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Warsaw 1:24:00 - LMT 1880
1:24:00 - WMT 1915 Aug 5 # Warsaw Mean Time
1:00 C-Eur CE%sT 1918 Sep 16 3:00
@@ -2270,7 +2317,7 @@ Rule Port 1980 only - Mar lastSun 0:00s 1:00 S
Rule Port 1981 1982 - Mar lastSun 1:00s 1:00 S
Rule Port 1983 only - Mar lastSun 2:00s 1:00 S
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Lisbon -0:36:45 - LMT 1884
-0:36:45 - LMT 1912 Jan 1 0:00u # Lisbon MT
0:00 Port WE%sT 1966 Apr 3 2:00
@@ -2329,7 +2376,7 @@ Rule Romania 1980 only - Apr 5 23:00 1:00 S
Rule Romania 1980 only - Sep lastSun 1:00 0 -
Rule Romania 1991 1993 - Mar lastSun 0:00s 1:00 S
Rule Romania 1991 1993 - Sep lastSun 0:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
1:44:24 - BMT 1931 Jul 24 # Bucharest MT
2:00 Romania EE%sT 1981 Mar 29 2:00s
@@ -2493,6 +2540,12 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# Europe/Kaliningrad covers...
# 39 RU-KGD Kaliningrad Oblast
+# From Paul Eggert (2019-07-25):
+# Although Shanks lists 1945-01-01 as the date for transition from
+# +01/+02 to +02/+03, more likely this is a placeholder. Guess that
+# the transition occurred at 1945-04-10 00:00, which is about when
+# Königsberg surrendered to Soviet troops. (Thanks to Alois Triendl.)
+
# From Paul Eggert (2016-03-18):
# The 1989 transition is from USSR act No. 227 (1989-03-14).
@@ -2509,8 +2562,8 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# Moscow on 1991-11-03, switched to Moscow-1 on 1992-01-19.
Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
- 1:00 C-Eur CE%sT 1945
- 2:00 Poland CE%sT 1946
+ 1:00 C-Eur CE%sT 1945 Apr 10
+ 2:00 Poland EE%sT 1946 Apr 7
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
3:00 - +03 2014 Oct 26 2:00s
@@ -3368,7 +3421,7 @@ Zone Asia/Anadyr 11:49:56 - LMT 1924 May 2
# See Europe/Rome.
# Serbia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Belgrade 1:22:00 - LMT 1884
1:00 - CET 1941 Apr 18 23:00
1:00 C-Eur CE%sT 1945
@@ -3382,7 +3435,7 @@ Zone Europe/Belgrade 1:22:00 - LMT 1884
Link Europe/Belgrade Europe/Ljubljana # Slovenia
Link Europe/Belgrade Europe/Podgorica # Montenegro
Link Europe/Belgrade Europe/Sarajevo # Bosnia and Herzegovina
-Link Europe/Belgrade Europe/Skopje # Macedonia
+Link Europe/Belgrade Europe/Skopje # North Macedonia
Link Europe/Belgrade Europe/Zagreb # Croatia
# Slovakia
@@ -3474,7 +3527,7 @@ Rule SpainAfrica 1976 only - Aug 1 0:00 0 -
Rule SpainAfrica 1977 only - Sep 28 0:00 0 -
Rule SpainAfrica 1978 only - Jun 1 0:00 1:00 S
Rule SpainAfrica 1978 only - Aug 4 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Madrid -0:14:44 - LMT 1900 Dec 31 23:45:16
0:00 Spain WE%sT 1940 Mar 16 23:00
1:00 Spain CE%sT 1979
@@ -3542,7 +3595,7 @@ Zone Atlantic/Canary -1:01:36 - LMT 1922 Mar # Las Palmas de Gran C.
#
# Source: The newspaper "Dagens Nyheter", 1916-10-01, page 7 upper left.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Stockholm 1:12:12 - LMT 1879 Jan 1
1:00:14 - SET 1900 Jan 1 # Swedish Time
1:00 - CET 1916 May 14 23:00
@@ -3645,7 +3698,7 @@ Zone Europe/Stockholm 1:12:12 - LMT 1879 Jan 1
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Swiss 1941 1942 - May Mon>=1 1:00 1:00 S
Rule Swiss 1941 1942 - Oct Mon>=1 2:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
0:29:46 - BMT 1894 Jun # Bern Mean Time
1:00 Swiss CE%sT 1981
@@ -3653,20 +3706,75 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Turkey
+# From Alois Treindl (2019-08-12):
+# http://www.astrolojidergisi.com/yazsaati.htm has researched the time zone
+# history of Turkey, based on newspaper archives and official documents.
+# From Paul Eggert (2019-08-28):
+# That source (Oya Vulaş, "Türkiye'de Yaz Saati Uygulamaları")
+# is used for 1940/1972, where it seems more reliable than our other
+# sources.
+
+# From Kıvanç Yazan (2019-08-12):
+# http://www.resmigazete.gov.tr/arsiv/14539.pdf#page=24
+# 1973-06-03 01:00 -> 02:00, 1973-11-04 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/14829.pdf#page=1
+# 1974-03-31 02:00 -> 03:00, 1974-11-03 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15161.pdf#page=1
+# 1975-03-22 02:00 -> 03:00, 1975-11-02 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15535_1.pdf#page=1
+# 1976-03-21 02:00 -> 03:00, 1976-10-31 02:00 -> 01:00
+#
+# http://www.resmigazete.gov.tr/arsiv/15778.pdf#page=5
+# 1977-04-03 02:00 -> 03:00, 1977-10-16 02:00 -> 01:00,
+# 1978-04-02 02:00 -> 03:00 (not applied, see below)
+# 1978-10-15 02:00 -> 01:00 (not applied, see below)
+# 1979-04-01 02:00 -> 03:00 (not applied, see below)
+# 1979-10-14 02:00 -> 01:00 (not applied, see below)
+#
+# http://www.resmigazete.gov.tr/arsiv/16245.pdf#page=17
+# This cancels the previous decision, and repeats it only for 1978.
+# 1978-04-02 02:00 -> 03:00, 1978-10-15 02:00 -> 01:00
+# (not applied due to standard TZ change below)
+#
+# http://www.resmigazete.gov.tr/arsiv/16331.pdf#page=3
+# This decision changes the default longitude for Turkish time zone from 30
+# degrees East to 45 degrees East. This means a standard TZ change, from +2
+# to +3. This is published & applied on 1978-06-29. At that time, Turkey was
+# already on summer time (already on 45E). Hence, this new law just meant an
+# "continuous summer time". Note that this was reversed in a few years.
+#
+# http://www.resmigazete.gov.tr/arsiv/18119_1.pdf#page=1
+# 1983-07-31 02:00 -> 03:00 (note that this jumps TZ to +4)
+# 1983-10-02 02:00 -> 01:00 (back to +3)
+#
+# http://www.resmigazete.gov.tr/arsiv/18561.pdf (page 1 and 34)
+# At this time, Turkey is still on +3 with no spring-forward on early
+# 1984. This decision is published on 10/31/1984. Page 1 declares
+# the decision of reverting the "default longitude change". So the
+# standard time should go back to +3 (30E). And page 34 explains when
+# that will happen: 1984-11-01 02:00 -> 01:00. You can think of this
+# as "end of continuous summer time, change of standard time zone".
+#
+# http://www.resmigazete.gov.tr/arsiv/18713.pdf#page=1
+# 1985-04-20 01:00 -> 02:00, 1985-09-28 02:00 -> 01:00
+
# From Kıvanç Yazan (2016-09-25):
# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
# no exceptions.
# 2) 1994's lastSun was overridden with Mar 20 ...
# Here are official papers:
-# http://www.resmigazete.gov.tr/arsiv/19032.pdf - page 2 for 1986
-# http://www.resmigazete.gov.tr/arsiv/19400.pdf - page 4 for 1987
-# http://www.resmigazete.gov.tr/arsiv/19752.pdf - page 15 for 1988
-# http://www.resmigazete.gov.tr/arsiv/20102.pdf - page 6 for 1989
-# http://www.resmigazete.gov.tr/arsiv/20464.pdf - page 1 for 1990 - 1992
-# http://www.resmigazete.gov.tr/arsiv/21531.pdf - page 15 for 1993 - 1995
-# http://www.resmigazete.gov.tr/arsiv/21879.pdf - page 1 for overriding 1994
-# http://www.resmigazete.gov.tr/arsiv/22588.pdf - page 1 for 1996, 1997
-# http://www.resmigazete.gov.tr/arsiv/23286.pdf - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf#page=2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf#page=4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf#page=15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf#page=6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf#page=1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf#page=15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf#page=1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf#page=1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf#page=10 for 1998 - 2000
# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2 - for 2001
# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2 - for 2002-2006
# From Paul Eggert (2016-09-25):
@@ -3750,56 +3858,46 @@ Rule Turkey 1922 only - Oct 8 0:00 0 -
Rule Turkey 1924 only - May 13 0:00 1:00 S
Rule Turkey 1924 1925 - Oct 1 0:00 0 -
Rule Turkey 1925 only - May 1 0:00 1:00 S
-Rule Turkey 1940 only - Jun 30 0:00 1:00 S
-Rule Turkey 1940 only - Oct 5 0:00 0 -
+Rule Turkey 1940 only - Jul 1 0:00 1:00 S
+Rule Turkey 1940 only - Oct 6 0:00 0 -
Rule Turkey 1940 only - Dec 1 0:00 1:00 S
Rule Turkey 1941 only - Sep 21 0:00 0 -
Rule Turkey 1942 only - Apr 1 0:00 1:00 S
-# Whitman omits the next two transition and gives 1945 Oct 1;
-# go with Shanks & Pottenger.
-Rule Turkey 1942 only - Nov 1 0:00 0 -
-Rule Turkey 1945 only - Apr 2 0:00 1:00 S
Rule Turkey 1945 only - Oct 8 0:00 0 -
Rule Turkey 1946 only - Jun 1 0:00 1:00 S
Rule Turkey 1946 only - Oct 1 0:00 0 -
Rule Turkey 1947 1948 - Apr Sun>=16 0:00 1:00 S
-Rule Turkey 1947 1950 - Oct Sun>=2 0:00 0 -
+Rule Turkey 1947 1951 - Oct Sun>=2 0:00 0 -
Rule Turkey 1949 only - Apr 10 0:00 1:00 S
-Rule Turkey 1950 only - Apr 19 0:00 1:00 S
+Rule Turkey 1950 only - Apr 16 0:00 1:00 S
Rule Turkey 1951 only - Apr 22 0:00 1:00 S
-Rule Turkey 1951 only - Oct 8 0:00 0 -
+# DST for 15 months; unusual but we'll let it pass.
Rule Turkey 1962 only - Jul 15 0:00 1:00 S
-Rule Turkey 1962 only - Oct 8 0:00 0 -
+Rule Turkey 1963 only - Oct 30 0:00 0 -
Rule Turkey 1964 only - May 15 0:00 1:00 S
Rule Turkey 1964 only - Oct 1 0:00 0 -
-Rule Turkey 1970 1972 - May Sun>=2 0:00 1:00 S
-Rule Turkey 1970 1972 - Oct Sun>=2 0:00 0 -
Rule Turkey 1973 only - Jun 3 1:00 1:00 S
-Rule Turkey 1973 only - Nov 4 3:00 0 -
+Rule Turkey 1973 1976 - Oct Sun>=31 2:00 0 -
Rule Turkey 1974 only - Mar 31 2:00 1:00 S
-Rule Turkey 1974 only - Nov 3 5:00 0 -
-Rule Turkey 1975 only - Mar 30 0:00 1:00 S
-Rule Turkey 1975 1976 - Oct lastSun 0:00 0 -
-Rule Turkey 1976 only - Jun 1 0:00 1:00 S
-Rule Turkey 1977 1978 - Apr Sun>=1 0:00 1:00 S
-Rule Turkey 1977 only - Oct 16 0:00 0 -
-Rule Turkey 1979 1980 - Apr Sun>=1 3:00 1:00 S
-Rule Turkey 1979 1982 - Oct Mon>=11 0:00 0 -
-Rule Turkey 1981 1982 - Mar lastSun 3:00 1:00 S
-Rule Turkey 1983 only - Jul 31 0:00 1:00 S
-Rule Turkey 1983 only - Oct 2 0:00 0 -
-Rule Turkey 1985 only - Apr 20 0:00 1:00 S
-Rule Turkey 1985 only - Sep 28 0:00 0 -
+Rule Turkey 1975 only - Mar 22 2:00 1:00 S
+Rule Turkey 1976 only - Mar 21 2:00 1:00 S
+Rule Turkey 1977 1978 - Apr Sun>=1 2:00 1:00 S
+Rule Turkey 1977 1978 - Oct Sun>=15 2:00 0 -
+Rule Turkey 1978 only - Jun 29 0:00 0 -
+Rule Turkey 1983 only - Jul 31 2:00 1:00 S
+Rule Turkey 1983 only - Oct 2 2:00 0 -
+Rule Turkey 1985 only - Apr 20 1:00s 1:00 S
+Rule Turkey 1985 only - Sep 28 1:00s 0 -
Rule Turkey 1986 1993 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1986 1995 - Sep lastSun 1:00s 0 -
Rule Turkey 1994 only - Mar 20 1:00s 1:00 S
Rule Turkey 1995 2006 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 Oct # Istanbul Mean Time?
- 2:00 Turkey EE%sT 1978 Oct 15
- 3:00 Turkey +03/+04 1985 Apr 20
+ 2:00 Turkey EE%sT 1978 Jun 29
+ 3:00 Turkey +03/+04 1984 Nov 1 2:00
2:00 Turkey EE%sT 2007
2:00 EU EE%sT 2011 Mar 27 1:00u
2:00 - EET 2011 Mar 28 1:00u
@@ -3892,16 +3990,8 @@ Link Europe/Istanbul Asia/Istanbul # Istanbul is in both continents.
# controversial, and some day "Kyiv" may become substantially more popular in
# English; in the meantime, stick with the traditional English "Kiev" as that
# means less disruption for our users.
-#
-# Anyway, none of the common English-language spellings (Kiev, Kyiv, Kieff,
-# Kijeff, Kijev, Kiyef, Kiyeff) do justice to the common pronunciation in
-# Ukrainian, namely [ˈkɪjiu̯] (IPA). This pronunciation has nothing like an
-# English "v" or "f", and instead trails off with what an English-speaker
-# would call a demure "oo" sound, and it would would be better anglicized as
-# "Kuiyu". Here's a sound file, if you would like to do as the Kuiyuvians do:
-# https://commons.wikimedia.org/wiki/File:Uk-Київ.ogg
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# This represents most of Ukraine. See above for the spelling of "Kiev".
Zone Europe/Kiev 2:02:04 - LMT 1880
2:02:04 - KMT 1924 May 2 # Kiev Mean Time
diff --git a/make/data/tzdata/factory b/make/data/tzdata/factory
index 6ef6bca0b8..a05346a301 100644
--- a/make/data/tzdata/factory
+++ b/make/data/tzdata/factory
@@ -31,5 +31,5 @@
# time zone abbreviation "-00", indicating that the actual time zone
# is unknown.
-# Zone NAME GMTOFF RULES FORMAT
+# Zone NAME STDOFF RULES FORMAT
Zone Factory 0 - -00
diff --git a/make/data/tzdata/iso3166.tab b/make/data/tzdata/iso3166.tab
index 38a3a1ed52..544b3034c1 100644
--- a/make/data/tzdata/iso3166.tab
+++ b/make/data/tzdata/iso3166.tab
@@ -32,8 +32,8 @@
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
-# ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1
-# http://isotc.iso.org/livelink/livelink/Open/16944257
+# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1
+# https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists.
# This is not the same as the English name in the ISO 3166 tables.
@@ -189,7 +189,7 @@ ME Montenegro
MF St Martin (French)
MG Madagascar
MH Marshall Islands
-MK Macedonia
+MK North Macedonia
ML Mali
MM Myanmar (Burma)
MN Mongolia
@@ -258,7 +258,7 @@ ST Sao Tome & Principe
SV El Salvador
SX St Maarten (Dutch)
SY Syria
-SZ Swaziland
+SZ Eswatini (Swaziland)
TC Turks & Caicos Is
TD Chad
TF French Southern & Antarctic Lands
diff --git a/make/data/tzdata/leapseconds b/make/data/tzdata/leapseconds
index 8b539e6ef4..753cd8e430 100644
--- a/make/data/tzdata/leapseconds
+++ b/make/data/tzdata/leapseconds
@@ -26,33 +26,39 @@
# This file is in the public domain.
# This file is generated automatically from the data in the public-domain
-# leap-seconds.list file, which can be copied from
+# NIST format leap-seconds.list file, which can be copied from
# <ftp://ftp.nist.gov/pub/time/leap-seconds.list>
-# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>
-# or <ftp://tycho.usno.navy.mil/pub/ntp/leap-seconds.list>.
+# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>.
# For more about leap-seconds.list, please see
# The NTP Timescale and Leap Seconds
# <https://www.eecis.udel.edu/~mills/leap.html>.
-# The International Earth Rotation and Reference Systems Service
+# The rules for leap seconds are specified in Annex 1 (Time scales) of:
+# Standard-frequency and time-signal emissions.
+# International Telecommunication Union - Radiocommunication Sector
+# (ITU-R) Recommendation TF.460-6 (02/2002)
+# <https://www.itu.int/rec/R-REC-TF.460-6-200202-I/>.
+# The International Earth Rotation and Reference Systems Service (IERS)
# periodically uses leap seconds to keep UTC to within 0.9 s of UT1
-# (which measures the true angular orientation of the earth in space)
+# (a proxy for Earth's angle in space as measured by astronomers)
# and publishes leap second data in a copyrighted file
# <https://hpiers.obspm.fr/iers/bul/bulc/Leap_Second.dat>.
# See: Levine J. Coordinated Universal Time and the leap second.
# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995
# <https://ieeexplore.ieee.org/document/7909995>.
-# There were no leap seconds before 1972, because the official mechanism
-# accounting for the discrepancy between atomic time and the earth's rotation
-# did not exist.
-# The correction (+ or -) is made at the given time, so lines
-# will typically look like:
-# Leap YEAR MON DAY 23:59:60 + R/S
-# or
-# Leap YEAR MON DAY 23:59:59 - R/S
+# There were no leap seconds before 1972, as no official mechanism
+# accounted for the discrepancy between atomic time (TAI) and the earth's
+# rotation. The first ("1 Jan 1972") data line in leap-seconds.list
+# does not denote a leap second; it denotes the start of the current definition
+# of UTC.
-# If the leap second is Rolling (R) the given time is local time (unused here).
+# All leap-seconds are Stationary (S) at the given UTC time.
+# The correction (+ or -) is made at the given time, so in the unlikely
+# event of a negative leap second, a line would look like this:
+# Leap YEAR MON DAY 23:59:59 - S
+# Typical lines look like this:
+# Leap YEAR MON DAY 23:59:60 + S
Leap 1972 Jun 30 23:59:60 + S
Leap 1972 Dec 31 23:59:60 + S
Leap 1973 Dec 31 23:59:60 + S
@@ -82,8 +88,8 @@ Leap 2015 Jun 30 23:59:60 + S
Leap 2016 Dec 31 23:59:60 + S
# POSIX timestamps for the data in this file:
-#updated 1467936000
-#expires 1561680000
+#updated 1467936000 (2016-07-08 00:00:00 UTC)
+#expires 1593302400 (2020-06-28 00:00:00 UTC)
-# Updated through IERS Bulletin C56
-# File expires on: 28 June 2019
+# Updated through IERS Bulletin C58
+# File expires on: 28 June 2020
diff --git a/make/data/tzdata/northamerica b/make/data/tzdata/northamerica
index 297a10a384..0135ef16cd 100644
--- a/make/data/tzdata/northamerica
+++ b/make/data/tzdata/northamerica
@@ -116,10 +116,33 @@
# was the first nationwide legal time standard, and apparently
# time was just called "Standard Time" or "Daylight Saving Time".
-# From Arthur David Olson:
-# US Daylight Saving Time ended on the last Sunday of *October* in 1974.
-# See, for example, the front page of the Saturday, 1974-10-26
-# and Sunday, 1974-10-27 editions of the Washington Post.
+# From Paul Eggert (2019-06-04):
+# Here is the legal basis for the US federal rules.
+# * Public Law 65-106 (1918-03-19) implemented standard and daylight saving
+# time for the first time across the US, springing forward on March's last
+# Sunday and falling back on October's last Sunday.
+# https://www.loc.gov/law/help/statutes-at-large/65th-congress/session-2/c65s2ch24.pdf
+# * Public Law 66-40 (1919-08-20) repealed DST on October 1919's last Sunday.
+# https://www.loc.gov/law/help/statutes-at-large/66th-congress/session-1/c66s1ch51.pdf
+# * Public Law 77-403 (1942-01-20) started wartime DST on 1942-02-09.
+# https://www.loc.gov/law/help/statutes-at-large/77th-congress/session-2/c77s2ch7.pdf
+# * Public Law 79-187 (1945-09-25) ended wartime DST on 1945-09-30.
+# https://www.loc.gov/law/help/statutes-at-large/79th-congress/session-1/c79s1ch388.pdf
+# * Public Law 89-387 (1966-04-13) reinstituted a national standard for DST,
+# from April's last Sunday to October's last Sunday, effective 1967.
+# https://www.govinfo.gov/content/pkg/STATUTE-80/pdf/STATUTE-80-Pg107.pdf
+# * Public Law 93-182 (1973-12-15) moved the 1974 spring-forward to 01-06.
+# https://www.govinfo.gov/content/pkg/STATUTE-87/pdf/STATUTE-87-Pg707.pdf
+# * Public Law 93-434 (1974-10-05) moved the 1975 spring-forward to
+# February's last Sunday.
+# https://www.govinfo.gov/content/pkg/STATUTE-88/pdf/STATUTE-88-Pg1209.pdf
+# * Public Law 99-359 (1986-07-08) moved the spring-forward to April's first
+# Sunday.
+# https://www.govinfo.gov/content/pkg/STATUTE-100/pdf/STATUTE-100-Pg764.pdf
+# * Public Law 109-58 (2005-08-08), effective 2007, moved the spring-forward
+# to March's second Sunday and the fall-back to November's first Sunday.
+# https://www.govinfo.gov/content/pkg/PLAW-109publ58/pdf/PLAW-109publ58.pdf
+# All transitions are at 02:00 local time.
# From Arthur David Olson:
# Before the Uniform Time Act of 1966 took effect in 1967, observance of
@@ -175,11 +198,11 @@ Rule US 1918 1919 - Mar lastSun 2:00 1:00 D
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
-Rule US 1945 only - Sep lastSun 2:00 0 S
+Rule US 1945 only - Sep 30 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
-Rule US 1975 only - Feb 23 2:00 1:00 D
+Rule US 1975 only - Feb lastSun 2:00 1:00 D
Rule US 1976 1986 - Apr lastSun 2:00 1:00 D
Rule US 1987 2006 - Apr Sun>=1 2:00 1:00 D
Rule US 2007 max - Mar Sun>=8 2:00 1:00 D
@@ -196,7 +219,7 @@ Rule US 2007 max - Nov Sun>=1 2:00 0 S
# increase the chances that they'll actually get compiled and to
# avoid the need to duplicate the US rules in another file.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone EST -5:00 - EST
Zone MST -7:00 - MST
Zone HST -10:00 - HST
@@ -353,7 +376,7 @@ Rule NYC 1920 only - Oct lastSun 2:00 0 S
Rule NYC 1921 1966 - Apr lastSun 2:00 1:00 D
Rule NYC 1921 1954 - Sep lastSun 2:00 0 S
Rule NYC 1955 1966 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
-5:00 US E%sT 1920
-5:00 NYC E%sT 1942
@@ -406,6 +429,31 @@ Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
# From Paul Eggert (2015-12-25):
# Assume this practice predates 1970, so Fort Pierre can use America/Chicago.
+# From Paul Eggert (2015-04-06):
+# In 1950s Nashville a public clock had dueling faces, one for conservatives
+# and the other for liberals; the two sides didn't agree about the time of day.
+# I haven't found a photo of this clock, nor have I tracked down the TIME
+# magazine report cited below, but here's the story as told by the late
+# American journalist John Seigenthaler, who was there:
+#
+# "The two [newspaper] owners held strongly contrasting political and
+# ideological views. Evans was a New South liberal, Stahlman an Old South
+# conservative, and their two papers frequently clashed editorially, often on
+# the same day.... In the 1950s as the state legislature was grappling with
+# the question of whether to approve daylight saving time for the entire state,
+# TIME magazine reported:
+#
+# "'The Nashville Banner and The Nashville Tennessean rarely agree on anything
+# but the time of day - and last week they couldn't agree on that.'
+#
+# "It was all too true. The clock on the front of the building had two faces -
+# The Tennessean side of the building facing west, the other, east. When it
+# was high noon Banner time, it was 11 a.m. Tennessean time."
+#
+# Seigenthaler J. For 100 years, Tennessean had it covered.
+# The Tennessean 2007-05-11, republished 2015-04-06.
+# https://www.tennessean.com/story/insider/extras/2015/04/06/archives-seigenthaler-for-100-years-the-tennessean-had-it-covered/25348545/
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Chicago 1920 only - Jun 13 2:00 1:00 D
Rule Chicago 1920 1921 - Oct lastSun 2:00 0 S
@@ -413,7 +461,7 @@ Rule Chicago 1921 only - Mar lastSun 2:00 1:00 D
Rule Chicago 1922 1966 - Apr lastSun 2:00 1:00 D
Rule Chicago 1922 1954 - Sep lastSun 2:00 0 S
Rule Chicago 1955 1966 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Chicago -5:50:36 - LMT 1883 Nov 18 12:09:24
-6:00 US C%sT 1920
-6:00 Chicago C%sT 1936 Mar 1 2:00
@@ -481,7 +529,7 @@ Rule Denver 1920 only - Oct lastSun 2:00 0 S
Rule Denver 1921 only - May 22 2:00 0 S
Rule Denver 1965 1966 - Apr lastSun 2:00 1:00 D
Rule Denver 1965 1966 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Denver -6:59:56 - LMT 1883 Nov 18 12:00:04
-7:00 US M%sT 1920
-7:00 Denver M%sT 1942
@@ -534,7 +582,7 @@ Rule CA 1949 only - Jan 1 2:00 0 S
Rule CA 1950 1966 - Apr lastSun 1:00 1:00 D
Rule CA 1950 1961 - Sep lastSun 2:00 0 S
Rule CA 1962 1966 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02
-8:00 US P%sT 1946
-8:00 CA P%sT 1967
@@ -622,7 +670,27 @@ Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02
# between AKST and AKDT from now on....
# https://www.krbd.org/2015/10/30/annette-island-times-they-are-a-changing/
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# From Ryan Stanley (2018-11-06):
+# The Metlakatla community in Alaska has decided not to change its
+# clock back an hour starting on November 4th, 2018 (day before yesterday).
+# They will be gmtoff=-28800 year-round.
+# https://www.facebook.com/141055983004923/photos/pb.141055983004923.-2207520000.1541465673./569081370202380/
+
+# From Paul Eggert (2018-12-16):
+# In a 2018-12-11 special election, Metlakatla voted to go back to
+# Alaska time (including daylight saving time) starting next year.
+# https://www.krbd.org/2018/12/12/metlakatla-to-follow-alaska-standard-time-allow-liquor-sales/
+#
+# From Ryan Stanley (2019-01-11):
+# The community will be changing back on the 20th of this month...
+# From Tim Parenti (2019-01-11):
+# Per an announcement on the Metlakatla community's official Facebook page, the
+# "fall back" will be on Sunday 2019-01-20 at 02:00:
+# https://www.facebook.com/141055983004923/photos/607150969728753/
+# So they won't be waiting for Alaska to join them on 2019-03-10, but will
+# rather change their clocks twice in seven weeks.
+
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Juneau 15:02:19 - LMT 1867 Oct 19 15:33:32
-8:57:41 - LMT 1900 Aug 20 12:00
-8:00 - PST 1942
@@ -648,6 +716,8 @@ Zone America/Metlakatla 15:13:42 - LMT 1867 Oct 19 15:44:55
-8:00 - PST 1969
-8:00 US P%sT 1983 Oct 30 2:00
-8:00 - PST 2015 Nov 1 2:00
+ -9:00 US AK%sT 2018 Nov 4 2:00
+ -8:00 - PST 2019 Jan 20 2:00
-9:00 US AK%sT
Zone America/Yakutat 14:41:05 - LMT 1867 Oct 19 15:12:18
-9:18:55 - LMT 1900 Aug 20 12:00
@@ -740,7 +810,7 @@ Zone America/Adak 12:13:22 - LMT 1867 Oct 19 12:44:35
# Note that 1933-05-21 was a Sunday.
# We're left to guess the time of day when Act 163 was approved; guess noon.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00
-10:30 - HST 1933 Apr 30 2:00
-10:30 1:00 HDT 1933 May 21 12:00
@@ -770,7 +840,7 @@ Zone Pacific/Honolulu -10:31:26 - LMT 1896 Jan 13 12:00
# Shanks says the 1944 experiment came to an end on 1944-03-17.
# Go with the Arizona State Library instead.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Phoenix -7:28:18 - LMT 1883 Nov 18 11:31:42
-7:00 US M%sT 1944 Jan 1 0:01
-7:00 - MST 1944 Apr 1 0:01
@@ -796,7 +866,7 @@ Zone America/Phoenix -7:28:18 - LMT 1883 Nov 18 11:31:42
# quarter of Idaho county) and eastern Oregon (most of Malheur County)
# switched four weeks late in 1974.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Boise -7:44:49 - LMT 1883 Nov 18 12:15:11
-8:00 US P%sT 1923 May 13 2:00
-7:00 US M%sT 1974
@@ -808,6 +878,22 @@ Zone America/Boise -7:44:49 - LMT 1883 Nov 18 12:15:11
# For a map of Indiana's time zone regions, see:
# https://en.wikipedia.org/wiki/Time_in_Indiana
#
+# From Paul Eggert (2018-11-30):
+# A brief but entertaining history of time in Indiana describes a 1949 debate
+# in the Indiana House where city legislators (who favored "fast time")
+# tussled with farm legislators (who didn't) over a bill to outlaw DST:
+# "Lacking enough votes, the city faction tries to filibuster until time runs
+# out on the session at midnight, but rural champion Rep. Herbert Copeland,
+# R-Madison, leans over the gallery railing and forces the official clock
+# back to 9 p.m., breaking it in the process. The clock sticks on 9 as the
+# debate rages on into the night. The filibuster finally dies out and the
+# bill passes, while outside the chamber, clocks read 3:30 a.m. In the end,
+# it doesn't matter which side won. The law has no enforcement powers and
+# is simply ignored by fast-time communities."
+# How Indiana went from 'God's time' to split zones and daylight-saving.
+# Indianapolis Star. 2018-11-27 14:58 -05.
+# https://www.indystar.com/story/news/politics/2018/11/27/indianapolis-indiana-time-zone-history-central-eastern-daylight-savings-time/2126300002/
+#
# From Paul Eggert (2007-08-17):
# Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
# with the following exceptions:
@@ -852,7 +938,7 @@ Zone America/Boise -7:44:49 - LMT 1883 Nov 18 12:15:11
Rule Indianapolis 1941 only - Jun 22 2:00 1:00 D
Rule Indianapolis 1941 1954 - Sep lastSun 2:00 0 S
Rule Indianapolis 1946 1954 - Apr lastSun 2:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
-6:00 US C%sT 1920
-6:00 Indianapolis C%sT 1942
@@ -872,7 +958,7 @@ Rule Marengo 1951 only - Apr lastSun 2:00 1:00 D
Rule Marengo 1951 only - Sep lastSun 2:00 0 S
Rule Marengo 1954 1960 - Apr lastSun 2:00 1:00 D
Rule Marengo 1954 1960 - Sep lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Marengo -5:45:23 - LMT 1883 Nov 18 12:14:37
-6:00 US C%sT 1951
-6:00 Marengo C%sT 1961 Apr 30 2:00
@@ -896,7 +982,7 @@ Rule Vincennes 1956 1963 - Apr lastSun 2:00 1:00 D
Rule Vincennes 1960 only - Oct lastSun 2:00 0 S
Rule Vincennes 1961 only - Sep lastSun 2:00 0 S
Rule Vincennes 1962 1963 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Vincennes -5:50:07 - LMT 1883 Nov 18 12:09:53
-6:00 US C%sT 1946
-6:00 Vincennes C%sT 1964 Apr 26 2:00
@@ -907,21 +993,21 @@ Zone America/Indiana/Vincennes -5:50:07 - LMT 1883 Nov 18 12:09:53
-5:00 US E%sT
#
# Perry County, Indiana, switched from eastern to central time in April 2006.
+# From Alois Triendl (2019-07-09):
+# The Indianapolis News, Friday 27 October 1967 states that Perry County
+# returned to CST. It went again to EST on 27 April 1969, as documented by the
+# Indianapolis star of Saturday 26 April.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
-Rule Perry 1946 only - Apr lastSun 2:00 1:00 D
-Rule Perry 1946 only - Sep lastSun 2:00 0 S
-Rule Perry 1953 1954 - Apr lastSun 2:00 1:00 D
-Rule Perry 1953 1959 - Sep lastSun 2:00 0 S
Rule Perry 1955 only - May 1 0:00 1:00 D
+Rule Perry 1955 1960 - Sep lastSun 2:00 0 S
Rule Perry 1956 1963 - Apr lastSun 2:00 1:00 D
-Rule Perry 1960 only - Oct lastSun 2:00 0 S
-Rule Perry 1961 only - Sep lastSun 2:00 0 S
-Rule Perry 1962 1963 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Rule Perry 1961 1963 - Oct lastSun 2:00 0 S
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Tell_City -5:47:03 - LMT 1883 Nov 18 12:12:57
-6:00 US C%sT 1946
-6:00 Perry C%sT 1964 Apr 26 2:00
- -5:00 - EST 1969
+ -5:00 - EST 1967 Oct 29 2:00
+ -6:00 US C%sT 1969 Apr 27 2:00
-5:00 US E%sT 1971
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
@@ -933,7 +1019,7 @@ Rule Pike 1955 only - May 1 0:00 1:00 D
Rule Pike 1955 1960 - Sep lastSun 2:00 0 S
Rule Pike 1956 1964 - Apr lastSun 2:00 1:00 D
Rule Pike 1961 1964 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Petersburg -5:49:07 - LMT 1883 Nov 18 12:10:53
-6:00 US C%sT 1955
-6:00 Pike C%sT 1965 Apr 25 2:00
@@ -955,7 +1041,7 @@ Rule Starke 1947 1954 - Sep lastSun 2:00 0 S
Rule Starke 1955 1956 - Oct lastSun 2:00 0 S
Rule Starke 1957 1958 - Sep lastSun 2:00 0 S
Rule Starke 1959 1961 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Knox -5:46:30 - LMT 1883 Nov 18 12:13:30
-6:00 US C%sT 1947
-6:00 Starke C%sT 1962 Apr 29 2:00
@@ -971,7 +1057,7 @@ Rule Pulaski 1946 1960 - Apr lastSun 2:00 1:00 D
Rule Pulaski 1946 1954 - Sep lastSun 2:00 0 S
Rule Pulaski 1955 1956 - Oct lastSun 2:00 0 S
Rule Pulaski 1957 1960 - Sep lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Winamac -5:46:25 - LMT 1883 Nov 18 12:13:35
-6:00 US C%sT 1946
-6:00 Pulaski C%sT 1961 Apr 30 2:00
@@ -982,7 +1068,7 @@ Zone America/Indiana/Winamac -5:46:25 - LMT 1883 Nov 18 12:13:35
-5:00 US E%sT
#
# Switzerland County, Indiana, did not observe DST from 1973 through 2005.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Vevay -5:40:16 - LMT 1883 Nov 18 12:19:44
-6:00 US C%sT 1954 Apr 25 2:00
-5:00 - EST 1969
@@ -997,17 +1083,28 @@ Zone America/Indiana/Vevay -5:40:16 - LMT 1883 Nov 18 12:19:44
# clear how this matched civil time in Louisville, so for now continue
# to assume Louisville switched at noon new local time, like New York.
#
+# From Michael Deckers (2019-08-06):
+# From the contemporary source given by Alois Treindl,
+# the switch in Louisville on 1946-04-28 was on 00:01
+# From Paul Eggert (2019-08-26):
+# That source was the Louisville Courier-Journal, 1946-04-27, p 4.
+# Shanks gives 02:00 for all 20th-century transition times in Louisville.
+# Evidently this is wrong for spring 1946. Although also likely wrong
+# for other dates, we have no data.
+#
# Part of Kentucky left its clocks alone in 1974.
# This also includes Clark, Floyd, and Harrison counties in Indiana.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Louisville 1921 only - May 1 2:00 1:00 D
Rule Louisville 1921 only - Sep 1 2:00 0 S
-Rule Louisville 1941 1961 - Apr lastSun 2:00 1:00 D
+Rule Louisville 1941 only - Apr lastSun 2:00 1:00 D
Rule Louisville 1941 only - Sep lastSun 2:00 0 S
+Rule Louisville 1946 only - Apr lastSun 0:01 1:00 D
Rule Louisville 1946 only - Jun 2 2:00 0 S
+Rule Louisville 1950 1961 - Apr lastSun 2:00 1:00 D
Rule Louisville 1950 1955 - Sep lastSun 2:00 0 S
-Rule Louisville 1956 1960 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+Rule Louisville 1956 1961 - Oct lastSun 2:00 0 S
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Kentucky/Louisville -5:43:02 - LMT 1883 Nov 18 12:16:58
-6:00 US C%sT 1921
-6:00 Louisville C%sT 1942
@@ -1096,29 +1193,32 @@ Zone America/Kentucky/Monticello -5:39:24 - LMT 1883 Nov 18 12:20:36
# one hour in 1914." This change is not in Shanks. We have no more
# info, so omit this for now.
#
-# From Paul Eggert (2017-07-26):
-# Although Shanks says Detroit observed DST in 1967 from 06-14 00:01
-# until 10-29 00:01, I now see multiple reports that this is incorrect.
-# For example, according to a 50-year anniversary report about the 1967
-# Detroit riots and a major-league doubleheader on 1967-07-23, "By the time
-# the last fly ball of the doubleheader settled into the glove of leftfielder
-# Lenny Green, it was after 7 p.m. Detroit did not observe daylight saving
-# time, so light was already starting to fail. Twilight was made even deeper
-# by billowing columns of smoke that ascended in an unbroken wall north of the
-# ballpark." See: Dow B. Detroit '67: As violence unfolded, Tigers played two
-# at home vs. Yankees. Detroit Free Press 2017-07-23.
-# https://www.freep.com/story/sports/mlb/tigers/2017/07/23/detroit-tigers-1967-riot-new-york-yankees/499951001/
+# From Paul Eggert (2019-07-06):
+# Due to a complicated set of legal maneuvers, in 1967 Michigan did
+# not start daylight saving time when the rest of the US did.
+# Instead, it began DST on Jun 14 at 00:01. This was big news:
+# the Detroit Free Press reported it at the top of Page 1 on
+# 1967-06-14, in an article "State Adjusting to Switch to Fast Time"
+# by Gary Blonston, above an article about Thurgood Marshall's
+# confirmation to the US Supreme Court. Although Shanks says Detroit
+# observed DST until 1967-10-29 00:01, that time of day seems to be
+# incorrect, as the Free Press later said DST ended in Michigan at the
+# same time as the rest of the US. Also, although Shanks reports no DST in
+# Detroit in 1968, it did observe DST that year; in the November 1968
+# election Michigan voters narrowly repealed DST, effective 1969.
#
# Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Detroit 1948 only - Apr lastSun 2:00 1:00 D
Rule Detroit 1948 only - Sep lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Detroit -5:32:11 - LMT 1905
-6:00 - CST 1915 May 15 2:00
-5:00 - EST 1942
-5:00 US E%sT 1946
- -5:00 Detroit E%sT 1973
+ -5:00 Detroit E%sT 1967 Jun 14 0:01
+ -5:00 US E%sT 1969
+ -5:00 - EST 1973
-5:00 US E%sT 1975
-5:00 - EST 1975 Apr 27 2:00
-5:00 US E%sT
@@ -1130,7 +1230,7 @@ Rule Menominee 1946 only - Apr lastSun 2:00 1:00 D
Rule Menominee 1946 only - Sep lastSun 2:00 0 S
Rule Menominee 1966 only - Apr lastSun 2:00 1:00 D
Rule Menominee 1966 only - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
-6:00 US C%sT 1946
-6:00 Menominee C%sT 1969 Apr 27 2:00
@@ -1167,6 +1267,12 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
#
# Other sources occasionally used include:
#
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
+# <https://www.jstor.org/stable/1774359>.
+#
+# Pearce C. The Great Daylight Saving Time Controversy.
+# Australian Ebook Publisher. 2017. ISBN 978-1-925516-96-8.
+#
# Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
# which I found in the UCLA library.
@@ -1175,9 +1281,6 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
# <http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
# [PDF] (1914-03)
#
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# <https://www.jstor.org/stable/1774359>.
-#
# See the 'europe' file for Greenland.
# Canada
@@ -1364,7 +1467,7 @@ Rule StJohns 2007 2011 - Mar Sun>=8 0:01 1:00 D
Rule StJohns 2007 2010 - Nov Sun>=1 0:01 0 S
#
# St John's has an apostrophe, but Posix file names can't have apostrophes.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/St_Johns -3:30:52 - LMT 1884
-3:30:52 StJohns N%sT 1918
-3:30:52 Canada N%sT 1919
@@ -1377,7 +1480,7 @@ Zone America/St_Johns -3:30:52 - LMT 1884
# most of east Labrador
# The name 'Happy Valley-Goose Bay' is too long; use 'Goose Bay'.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Goose_Bay -4:01:40 - LMT 1884 # Happy Valley-Goose Bay
-3:30:52 - NST 1918
-3:30:52 Canada N%sT 1919
@@ -1451,7 +1554,7 @@ Rule Halifax 1956 1959 - Apr lastSun 2:00 1:00 D
Rule Halifax 1956 1959 - Sep lastSun 2:00 0 S
Rule Halifax 1962 1973 - Apr lastSun 2:00 1:00 D
Rule Halifax 1962 1973 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Halifax -4:14:24 - LMT 1902 Jun 15
-4:00 Halifax A%sT 1918
-4:00 Canada A%sT 1919
@@ -1489,7 +1592,7 @@ Rule Moncton 1946 1956 - Sep lastSun 2:00 0 S
Rule Moncton 1957 1972 - Oct lastSun 2:00 0 S
Rule Moncton 1993 2006 - Apr Sun>=1 0:01 1:00 D
Rule Moncton 1993 2006 - Oct lastSun 0:01 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Moncton -4:19:08 - LMT 1883 Dec 9
-5:00 - EST 1902 Jun 15
-4:00 Canada A%sT 1933
@@ -1518,7 +1621,7 @@ Zone America/Moncton -4:19:08 - LMT 1883 Dec 9
# For lack of better info, guess this practice began around 1970, contra to
# Shanks & Pottenger who have this region observing AST/ADT.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Blanc-Sablon -3:48:28 - LMT 1884
-4:00 Canada A%sT 1970
-4:00 - AST
@@ -1686,19 +1789,10 @@ Rule Toronto 1922 1923 - May Sun>=8 2:00 1:00 D
# was meant.
Rule Toronto 1922 1926 - Sep Sun>=15 2:00 0 S
Rule Toronto 1924 1927 - May Sun>=1 2:00 1:00 D
-# The 1927-to-1939 rules can be expressed more simply as
-# Rule Toronto 1927 1937 - Sep Sun>=25 2:00 0 S
-# Rule Toronto 1928 1937 - Apr Sun>=25 2:00 1:00 D
-# Rule Toronto 1938 1940 - Apr lastSun 2:00 1:00 D
-# Rule Toronto 1938 1939 - Sep lastSun 2:00 0 S
-# The rules below avoid use of Sun>=25
-# (which pre-2004 versions of zic cannot handle).
-Rule Toronto 1927 1932 - Sep lastSun 2:00 0 S
-Rule Toronto 1928 1931 - Apr lastSun 2:00 1:00 D
-Rule Toronto 1932 only - May 1 2:00 1:00 D
-Rule Toronto 1933 1940 - Apr lastSun 2:00 1:00 D
-Rule Toronto 1933 only - Oct 1 2:00 0 S
-Rule Toronto 1934 1939 - Sep lastSun 2:00 0 S
+Rule Toronto 1927 1937 - Sep Sun>=25 2:00 0 S
+Rule Toronto 1928 1937 - Apr Sun>=25 2:00 1:00 D
+Rule Toronto 1938 1940 - Apr lastSun 2:00 1:00 D
+Rule Toronto 1938 1939 - Sep lastSun 2:00 0 S
Rule Toronto 1945 1946 - Sep lastSun 2:00 0 S
Rule Toronto 1946 only - Apr lastSun 2:00 1:00 D
Rule Toronto 1947 1949 - Apr lastSun 0:00 1:00 D
@@ -1731,7 +1825,7 @@ Rule Toronto 1957 1973 - Oct lastSun 2:00 0 S
# War,... [t]he cities agreed to implement DST during the summer
# months for the remainder of the war years.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Toronto -5:17:32 - LMT 1895
-5:00 Canada E%sT 1919
-5:00 Toronto E%sT 1942 Feb 9 2:00s
@@ -1806,7 +1900,7 @@ Rule Winn 1963 only - Sep 22 2:00 0 S
Rule Winn 1966 1986 - Apr lastSun 2:00s 1:00 D
Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S
Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Winnipeg -6:28:36 - LMT 1887 Jul 16
-6:00 Winn C%sT 2006
-6:00 Canada C%sT
@@ -1828,6 +1922,12 @@ Zone America/Winnipeg -6:28:36 - LMT 1887 Jul 16
# Willett (1914-03) notes that DST "has been in operation ... in the
# City of Moose Jaw, Saskatchewan, for one year."
+# From Paul Eggert (2019-07-25):
+# Pearce's book says Regina observed DST in 1914-1917. No dates and times,
+# unfortunately. It also says that in 1914 Saskatoon observed DST
+# from 1 June to 6 July, and that DST was also tried out in Davidson,
+# Melfort, and Prince Albert.
+
# From Paul Eggert (2006-03-22):
# Shanks & Pottenger say that since 1970 this region has mostly been as Regina.
# Some western towns (e.g. Swift Current) switched from MST/MDT to CST in 1972.
@@ -1890,7 +1990,7 @@ Rule Swift 1957 only - Oct lastSun 2:00 0 S
Rule Swift 1959 1961 - Apr lastSun 2:00 1:00 D
Rule Swift 1959 only - Oct lastSun 2:00 0 S
Rule Swift 1960 1961 - Sep lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Regina -6:58:36 - LMT 1905 Sep
-7:00 Regina M%sT 1960 Apr lastSun 2:00
-6:00 - CST
@@ -1903,6 +2003,19 @@ Zone America/Swift_Current -7:11:20 - LMT 1905 Sep
# Alberta
+# From Alois Triendl (2019-07-19):
+# There was no DST in Alberta in 1967... Calgary Herald, 29 April 1967.
+# 1969, no DST, from Edmonton Journal 18 April 1969
+#
+# From Paul Eggert (2019-07-25):
+# Pearce's book says that Alberta's 1948 Daylight Saving Act required
+# Mountain Standard Time without DST, and that "anyone who broke that law
+# could be fined up to $25 and costs". There seems to be no record of
+# anybody paying the fine. The law was not changed until an August 1971
+# plebiscite reinstituted DST in 1972. This story is also mentioned in:
+# Boyer JP. Forcing Choice: The Risky Reward of Referendums. Dundum. 2017.
+# ISBN 978-1459739123.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Edm 1918 1919 - Apr Sun>=8 2:00 1:00 D
Rule Edm 1918 only - Oct 27 2:00 0 S
@@ -1915,13 +2028,9 @@ Rule Edm 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule Edm 1945 only - Sep lastSun 2:00 0 S
Rule Edm 1947 only - Apr lastSun 2:00 1:00 D
Rule Edm 1947 only - Sep lastSun 2:00 0 S
-Rule Edm 1967 only - Apr lastSun 2:00 1:00 D
-Rule Edm 1967 only - Oct lastSun 2:00 0 S
-Rule Edm 1969 only - Apr lastSun 2:00 1:00 D
-Rule Edm 1969 only - Oct lastSun 2:00 0 S
Rule Edm 1972 1986 - Apr lastSun 2:00 1:00 D
Rule Edm 1972 2006 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Edmonton -7:33:52 - LMT 1906 Sep
-7:00 Edm M%sT 1987
-7:00 Canada M%sT
@@ -2001,8 +2110,20 @@ Zone America/Edmonton -7:33:52 - LMT 1906 Sep
# been on MST (-0700) like Dawson Creek since it advanced its clocks on
# 2015-03-08.
#
-# From Paul Eggert (2015-09-23):
+# From Paul Eggert (2019-07-25):
# Shanks says Fort Nelson did not observe DST in 1946, unlike Vancouver.
+# Alois Triendl confirmed this on 07-22, citing the 1946-04-27 Vancouver Daily
+# Province. He also cited the 1946-09-28 Victoria Daily Times, which said
+# that Vancouver, Victoria, etc. "change at midnight Saturday"; for now,
+# guess they meant 02:00 Sunday since 02:00 was common practice in Vancouver.
+#
+# Early Vancouver, Volume Four, by Major J.S. Matthews, V.D., 2011 edition
+# says that a 1922 plebiscite adopted DST, but a 1923 plebiscite rejected it.
+# http://former.vancouver.ca/ctyclerk/archives/digitized/EarlyVan/SearchEarlyVan/Vol4pdf/MatthewsEarlyVancouverVol4_DaylightSavings.pdf
+# A catalog entry for a newspaper clipping seems to indicate that Vancouver
+# observed DST in 1941 from 07-07 through 09-27; see
+# https://searcharchives.vancouver.ca/daylight-saving-1918-starts-again-july-7-1941-start-d-s-sept-27-end-of-d-s-1941
+# We have no further details, so omit them for now.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Vanc 1918 only - Apr 14 2:00 1:00 D
@@ -2011,10 +2132,10 @@ Rule Vanc 1942 only - Feb 9 2:00 1:00 W # War
Rule Vanc 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule Vanc 1945 only - Sep 30 2:00 0 S
Rule Vanc 1946 1986 - Apr lastSun 2:00 1:00 D
-Rule Vanc 1946 only - Oct 13 2:00 0 S
+Rule Vanc 1946 only - Sep 29 2:00 0 S
Rule Vanc 1947 1961 - Sep lastSun 2:00 0 S
Rule Vanc 1962 2006 - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Vancouver -8:12:28 - LMT 1884
-8:00 Vanc P%sT 1987
-8:00 Canada P%sT
@@ -2085,7 +2206,7 @@ Zone America/Creston -7:46:04 - LMT 1884
# varying the manner of reckoning standard time.
#
# * Yukon Territory Commissioner's Order 1966-20 Interpretation Ordinance
-# http://? - no online source found
+# [no online source found]
#
# * Standard Time and Time Zones in Canada; Thomson, Malcolm M.; JRASC,
# Vol. 64, pp.129-162; June 1970; SAO/NASA Astrophysics Data System (ADS)
@@ -2118,7 +2239,7 @@ Zone America/Creston -7:46:04 - LMT 1884
# to say eight hours behind Greenwich Time.
#
# * O.I.C. 1980/02 INTERPRETATION ACT
-# http://? - no online source found
+# [no online source found]
#
# * Yukon Daylight Saving Time, YOIC 1987/56
# https://www.canlii.org/en/yk/laws/regu/yoic-1987-56/latest/yoic-1987-56.html
@@ -2334,7 +2455,7 @@ Rule NT_YK 1965 only - Oct lastSun 2:00 0 S
Rule NT_YK 1980 1986 - Apr lastSun 2:00 1:00 D
Rule NT_YK 1980 2006 - Oct lastSun 2:00 0 S
Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# aka Panniqtuuq
Zone America/Pangnirtung 0 - -00 1921 # trading post est.
-4:00 NT_YK A%sT 1995 Apr Sun>=1 2:00
@@ -2481,7 +2602,7 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20
# From Paul Eggert (2001-03-03):
#
-# http://www.latimes.com/news/nation/20010303/t000018766.html
+# https://www.latimes.com/archives/la-xpm-2001-mar-03-mn-32561-story.html
# James F. Smith writes in today's LA Times
# * Sonora will continue to observe standard time.
# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
@@ -2608,7 +2729,7 @@ Rule Mexico 2001 only - May Sun>=1 2:00 1:00 D
Rule Mexico 2001 only - Sep lastSun 2:00 0 S
Rule Mexico 2002 max - Apr Sun>=1 2:00 1:00 D
Rule Mexico 2002 max - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
# Quintana Roo; represented by Cancún
Zone America/Cancun -5:47:04 - LMT 1922 Jan 1 0:12:56
-6:00 - CST 1981 Dec 23
@@ -2801,7 +2922,7 @@ Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 0:11:56
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Bahamas 1964 1975 - Oct lastSun 2:00 0 S
Rule Bahamas 1964 1975 - Apr lastSun 2:00 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Nassau -5:09:30 - LMT 1912 Mar 2
-5:00 Bahamas E%sT 1976
-5:00 US E%sT
@@ -2816,7 +2937,7 @@ Rule Barb 1977 1978 - Oct Sun>=1 2:00 0 S
Rule Barb 1978 1980 - Apr Sun>=15 2:00 1:00 D
Rule Barb 1979 only - Sep 30 2:00 0 S
Rule Barb 1980 only - Sep 25 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Barbados -3:58:29 - LMT 1924 # Bridgetown
-3:58:29 - BMT 1932 # Bridgetown Mean Time
-4:00 Barb A%sT
@@ -2830,7 +2951,7 @@ Rule Belize 1973 only - Dec 5 0:00 1:00 CDT
Rule Belize 1974 only - Feb 9 0:00 0 CST
Rule Belize 1982 only - Dec 18 0:00 1:00 CDT
Rule Belize 1983 only - Feb 12 0:00 0 CST
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Belize -5:52:48 - LMT 1912 Apr
-6:00 Belize %s
@@ -2847,7 +2968,7 @@ Zone America/Belize -5:52:48 - LMT 1912 Apr
# Friday, the same thing will happen in Bermuda.
# http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Atlantic/Bermuda -4:19:18 - LMT 1930 Jan 1 2:00 # Hamilton
-4:00 - AST 1974 Apr 28 2:00
-4:00 Canada A%sT 1976
@@ -2869,7 +2990,7 @@ Rule CR 1991 1992 - Jan Sat>=15 0:00 1:00 D
Rule CR 1991 only - Jul 1 0:00 0 S
Rule CR 1992 only - Mar 15 0:00 0 S
# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Costa_Rica -5:36:13 - LMT 1890 # San José
-5:36:13 - SJMT 1921 Jan 15 # San José Mean Time
-6:00 CR C%sT
@@ -3075,7 +3196,7 @@ Rule Cuba 2012 only - Apr 1 0:00s 1:00 D
Rule Cuba 2012 max - Nov Sun>=1 0:00s 0 S
Rule Cuba 2013 max - Mar Sun>=8 0:00s 1:00 D
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Havana -5:29:28 - LMT 1890
-5:29:36 - HMT 1925 Jul 19 12:00 # Havana MT
-5:00 Cuba C%sT
@@ -3110,7 +3231,7 @@ Rule DR 1969 1973 - Oct lastSun 0:00 0:30 -0430
Rule DR 1970 only - Feb 21 0:00 0 EST
Rule DR 1971 only - Jan 20 0:00 0 EST
Rule DR 1972 1974 - Jan 21 0:00 0 EST
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Santo_Domingo -4:39:36 - LMT 1890
-4:40 - SDMT 1933 Apr 1 12:00 # S. Dom. MT
-5:00 DR %s 1974 Oct 27
@@ -3125,7 +3246,7 @@ Rule Salv 1987 1988 - May Sun>=1 0:00 1:00 D
Rule Salv 1987 1988 - Sep lastSun 0:00 0 S
# There are too many San Salvadors elsewhere, so use America/El_Salvador
# instead of America/San_Salvador.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/El_Salvador -5:56:48 - LMT 1921 # San Salvador
-6:00 Salv C%sT
@@ -3158,7 +3279,7 @@ Rule Guat 1991 only - Mar 23 0:00 1:00 D
Rule Guat 1991 only - Sep 7 0:00 0 S
Rule Guat 2006 only - Apr 30 0:00 1:00 D
Rule Guat 2006 only - Oct 1 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Guatemala -6:02:04 - LMT 1918 Oct 5
-6:00 Guat C%sT
@@ -3244,7 +3365,7 @@ Rule Haiti 2012 2015 - Mar Sun>=8 2:00 1:00 D
Rule Haiti 2012 2015 - Nov Sun>=1 2:00 0 S
Rule Haiti 2017 max - Mar Sun>=8 2:00 1:00 D
Rule Haiti 2017 max - Nov Sun>=1 2:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Port-au-Prince -4:49:20 - LMT 1890
-4:49 - PPMT 1917 Jan 24 12:00 # P-a-P MT
-5:00 Haiti E%sT
@@ -3283,7 +3404,7 @@ Rule Hond 1987 1988 - May Sun>=1 0:00 1:00 D
Rule Hond 1987 1988 - Sep lastSun 0:00 0 S
Rule Hond 2006 only - May Sun>=1 0:00 1:00 D
Rule Hond 2006 only - Aug Mon>=1 0:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Tegucigalpa -5:48:52 - LMT 1921 Apr
-6:00 Hond C%sT
#
@@ -3304,7 +3425,7 @@ Zone America/Tegucigalpa -5:48:52 - LMT 1921 Apr
# Neita L. The politician in all of us. Jamaica Observer 2014-09-20
# http://www.jamaicaobserver.com/columns/The-politician-in-all-of-us_17573647
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Jamaica -5:07:10 - LMT 1890 # Kingston
-5:07:10 - KMT 1912 Feb # Kingston Mean Time
-5:00 - EST 1974
@@ -3312,7 +3433,7 @@ Zone America/Jamaica -5:07:10 - LMT 1890 # Kingston
-5:00 - EST
# Martinique
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Martinique -4:04:20 - LMT 1890 # Fort-de-France
-4:04:20 - FFMT 1911 May # Fort-de-France MT
-4:00 - AST 1980 Apr 6
@@ -3376,7 +3497,7 @@ Rule Nic 2005 only - Apr 10 0:00 1:00 D
Rule Nic 2005 only - Oct Sun>=1 0:00 0 S
Rule Nic 2006 only - Apr 30 2:00 1:00 D
Rule Nic 2006 only - Oct Sun>=1 1:00 0 S
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Managua -5:45:08 - LMT 1890
-5:45:12 - MMT 1934 Jun 23 # Managua Mean Time?
-6:00 - CST 1973 May
@@ -3388,7 +3509,7 @@ Zone America/Managua -5:45:08 - LMT 1890
-6:00 Nic C%sT
# Panama
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Panama -5:18:08 - LMT 1890
-5:19:36 - CMT 1908 Apr 22 # Colón Mean Time
-5:00 - EST
@@ -3396,7 +3517,7 @@ Link America/Panama America/Cayman
# Puerto Rico
# There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12:00 # San Juan
-4:00 - AST 1942 May 3
-4:00 US A%sT 1946
@@ -3408,7 +3529,7 @@ Zone America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12:00 # San Juan
# St Pierre and Miquelon
# There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Miquelon -3:44:40 - LMT 1911 May 15 # St Pierre
-4:00 - AST 1980 May
-3:00 - -03 1987
@@ -3454,7 +3575,7 @@ Zone America/Miquelon -3:44:40 - LMT 1911 May 15 # St Pierre
# by March 2018 for TCI. Magnetic Media. 2017-08-25.
# http://magneticmediatv.com/2017/08/time-change-back-by-march-2018-for-tci/
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Grand_Turk -4:44:32 - LMT 1890
-5:07:10 - KMT 1912 Feb # Kingston Mean Time
-5:00 - EST 1979
diff --git a/make/data/tzdata/pacificnew b/make/data/tzdata/pacificnew
index 020b599bf0..f19a876372 100644
--- a/make/data/tzdata/pacificnew
+++ b/make/data/tzdata/pacificnew
@@ -44,7 +44,7 @@
## Rule Twilite XXXX max uspres Nov Sun>=7 2:00 0 S
## Rule Twilite XXXX max nonpres Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+# Zone NAME STDOFF RULES/SAVE FORMAT [UNTIL]
## Zone America/Los_Angeles-PET -8:00 US P%sT XXXX
## -8:00 Twilite P%sT
diff --git a/make/data/tzdata/southamerica b/make/data/tzdata/southamerica
index 3f016479a7..51795f7621 100644
--- a/make/data/tzdata/southamerica
+++ b/make/data/tzdata/southamerica
@@ -419,7 +419,7 @@ Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 -
# plus is that this silences a zic complaint that there's no POSIX TZ
# setting for timestamps past 2038.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
#
# Buenos Aires (BA), Capital Federal (CF),
Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
@@ -600,7 +600,7 @@ Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
Link America/Curacao America/Aruba
# Bolivia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/La_Paz -4:32:36 - LMT 1890
-4:32:36 - CMT 1931 Oct 15 # Calamarca MT
-4:32:36 1:00 BST 1932 Mar 21 # Bolivia ST
@@ -943,14 +943,13 @@ Rule Brazil 2012 only - Feb Sun>=22 0:00 0 -
# removed Tocantins.
Rule Brazil 2013 2014 - Feb Sun>=15 0:00 0 -
Rule Brazil 2015 only - Feb Sun>=22 0:00 0 -
-Rule Brazil 2016 2022 - Feb Sun>=15 0:00 0 -
+Rule Brazil 2016 2019 - Feb Sun>=15 0:00 0 -
# From Steffen Thorsen (2017-12-18):
# According to many media sources, next year's DST start in Brazil will move to
-# the first Sunday of November, and it will stay like that for the years after.
+# the first Sunday of November
# ... https://www.timeanddate.com/news/time/brazil-delays-dst-2018.html
# From Steffen Thorsen (2017-12-20):
# http://www.planalto.gov.br/ccivil_03/_ato2015-2018/2017/decreto/D9242.htm
-#
# From Fábio Gomes (2018-10-04):
# The Brazilian president just announced a new change on this year DST.
# It was scheduled to start on November 4th and it was changed to November 18th.
@@ -958,22 +957,21 @@ Rule Brazil 2016 2022 - Feb Sun>=15 0:00 0 -
# The Brazilian government just announced that the change in DST was
# canceled.... Maybe the president Michel Temer also woke up one hour
# earlier today. :)
-Rule Brazil 2018 max - Nov Sun>=1 0:00 1:00 -
-Rule Brazil 2023 only - Feb Sun>=22 0:00 0 -
-Rule Brazil 2024 2025 - Feb Sun>=15 0:00 0 -
-Rule Brazil 2026 only - Feb Sun>=22 0:00 0 -
-Rule Brazil 2027 2033 - Feb Sun>=15 0:00 0 -
-Rule Brazil 2034 only - Feb Sun>=22 0:00 0 -
-Rule Brazil 2035 2036 - Feb Sun>=15 0:00 0 -
-Rule Brazil 2037 only - Feb Sun>=22 0:00 0 -
-# From Arthur David Olson (2008-09-29):
-# The next is wrong in some years but is better than nothing.
-Rule Brazil 2038 max - Feb Sun>=15 0:00 0 -
-
-# The latest ruleset listed above says that the following states observe DST:
+Rule Brazil 2018 only - Nov Sun>=1 0:00 1:00 -
+# The last ruleset listed above says that the following states observed DST:
# DF, ES, GO, MG, MS, MT, PR, RJ, RS, SC, SP.
+#
+# From Steffen Thorsen (2019-04-05):
+# According to multiple sources the Brazilian president wants to get rid of DST.
+# https://gmconline.com.br/noticias/politica/bolsonaro-horario-de-verao-deve-acabar-este-ano
+# https://g1.globo.com/economia/noticia/2019/04/05/governo-anuncia-fim-do-horario-de-verao.ghtml
+# From Marcus Diniz (2019-04-25):
+# Brazil no longer has DST changes - decree signed today
+# https://g1.globo.com/politica/noticia/2019/04/25/bolsonaro-assina-decreto-que-acaba-com-o-horario-de-verao.ghtml
+# From Daniel Soares de Oliveira (2019-04-26):
+# http://www.planalto.gov.br/ccivil_03/_Ato2019-2022/2019/Decreto/D9772.htm
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
#
# Fernando de Noronha (administratively part of PE)
Zone America/Noronha -2:09:40 - LMT 1914
@@ -1255,14 +1253,8 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# From Juan Correa (2016-12-04):
# Magallanes region ... will keep DST (UTC -3) all year round....
# http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx
-#
# From Deborah Goldsmith (2017-01-19):
# http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf
-# From Paul Eggert (2017-01-19):
-# The above says the Magallanes change expires 2019-05-11 at 24:00,
-# so in theory, they will revert to -04/-03 after that, which means
-# they will switch from -03 to -04 one hour after Santiago does that day.
-# For now, assume that they will not revert.
# From Juan Correa (2018-08-13):
# As of moments ago, the Ministry of Energy in Chile has announced the new
@@ -1281,6 +1273,13 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# https://twitter.com/MinEnergia/status/1029009354001973248
# "We will keep the new time policy unchanged for at least the next 4 years."
# So we extend the new rules on Saturdays at 24:00 mainland time indefinitely.
+# From Juan Correa (2019-02-04):
+# http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf
+# From Paul Eggert (2019-09-01):
+# The above says the Magallanes exception expires 2022-04-02 at 24:00,
+# so in theory, they will revert to -04/-03 after that.
+# For now, assume that they will not revert,
+# since they have extended the expiration date once already.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Chile 1927 1931 - Sep 1 0:00 1:00 -
@@ -1321,7 +1320,7 @@ Rule Chile 2019 max - Apr Sun>=2 3:00u 0 -
Rule Chile 2019 max - Sep Sun>=2 4:00u 1:00 -
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Santiago -4:42:46 - LMT 1890
-4:42:46 - SMT 1910 Jan 10 # Santiago Mean Time
-5:00 - -05 1916 Jul 1
@@ -1370,7 +1369,7 @@ Zone Pacific/Easter -7:17:28 - LMT 1890
# Palmer has followed Chile. Prior to that, before the Falklands War,
# Palmer used to be supplied from Argentina.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Antarctica/Palmer 0 - -00 1965
-4:00 Arg -04/-03 1969 Oct 5
-3:00 Arg -03/-02 1982 May
@@ -1385,7 +1384,7 @@ Zone Antarctica/Palmer 0 - -00 1965
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule CO 1992 only - May 3 0:00 1:00 -
Rule CO 1993 only - Apr 4 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Bogota -4:56:16 - LMT 1884 Mar 13
-4:56:16 - BMT 1914 Nov 23 # Bogotá Mean Time
-5:00 CO -05/-04
@@ -1410,7 +1409,7 @@ Zone America/Bogota -4:56:16 - LMT 1884 Mar 13
# Netherlands as Kingdom Islands. This won't affect their time zones
# though, as far as we know.
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Curacao -4:35:47 - LMT 1912 Feb 12 # Willemstad
-4:30 - -0430 1965
-4:00 - AST
@@ -1446,7 +1445,7 @@ Link America/Curacao America/Kralendijk # Caribbean Netherlands
Rule Ecuador 1992 only - Nov 28 0:00 1:00 -
Rule Ecuador 1993 only - Feb 5 0:00 0 -
#
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Guayaquil -5:19:20 - LMT 1890
-5:14:00 - QMT 1931 # Quito Mean Time
-5:00 Ecuador -05/-04
@@ -1549,7 +1548,7 @@ Rule Falk 1985 2000 - Sep Sun>=9 0:00 1:00 -
Rule Falk 1986 2000 - Apr Sun>=16 0:00 0 -
Rule Falk 2001 2010 - Apr Sun>=15 2:00 0 -
Rule Falk 2001 2010 - Sep Sun>=1 2:00 1:00 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Atlantic/Stanley -3:51:24 - LMT 1890
-3:51:24 - SMT 1912 Mar 12 # Stanley Mean Time
-4:00 Falk -04/-03 1983 May
@@ -1558,13 +1557,13 @@ Zone Atlantic/Stanley -3:51:24 - LMT 1890
-3:00 - -03
# French Guiana
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Cayenne -3:29:20 - LMT 1911 Jul
-4:00 - -04 1967 Oct
-3:00 - -03
# Guyana
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Guyana -3:52:40 - LMT 1915 Mar # Georgetown
-3:45 - -0345 1975 Jul 31
-3:00 - -03 1991
@@ -1658,7 +1657,7 @@ Rule Para 2010 2012 - Apr Sun>=8 0:00 0 -
# http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
Rule Para 2013 max - Mar Sun>=22 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Asuncion -3:50:40 - LMT 1890
-3:50:40 - AMT 1931 Oct 10 # Asunción Mean Time
-4:00 - -04 1972 Oct
@@ -1687,13 +1686,13 @@ Rule Peru 1990 only - Apr 1 0:00 0 -
# IATA is ambiguous for 1993/1995; go with Shanks & Pottenger.
Rule Peru 1994 only - Jan 1 0:00 1:00 -
Rule Peru 1994 only - Apr 1 0:00 0 -
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Lima -5:08:12 - LMT 1890
-5:08:36 - LMT 1908 Jul 28 # Lima Mean Time?
-5:00 Peru -05/-04
# South Georgia
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken
-2:00 - -02
@@ -1701,7 +1700,7 @@ Zone Atlantic/South_Georgia -2:26:08 - LMT 1890 # Grytviken
# uninhabited; scientific personnel have wintered
# Suriname
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Paramaribo -3:40:40 - LMT 1911
-3:40:52 - PMT 1935 # Paramaribo Mean Time
-3:40:36 - PMT 1945 Oct # The capital moved?
@@ -1709,7 +1708,7 @@ Zone America/Paramaribo -3:40:40 - LMT 1911
-3:00 - -03
# Trinidad and Tobago
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Port_of_Spain -4:06:04 - LMT 1912 Mar 2
-4:00 - AST
@@ -1980,7 +1979,7 @@ Zone America/Montevideo -3:44:51 - LMT 1908 Jun 10
# ... published in the official Gazette [2016-04-18], here:
# http://historico.tsj.gob.ve/gaceta_ext/abril/1842016/E-1842016-4551.pdf
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
+# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Caracas -4:27:44 - LMT 1890
-4:27:40 - CMT 1912 Feb 12 # Caracas Mean Time?
-4:30 - -0430 1965 Jan 1 0:00
diff --git a/make/data/tzdata/systemv b/make/data/tzdata/systemv
index 63a48e8c3e..9525ec4717 100644
--- a/make/data/tzdata/systemv
+++ b/make/data/tzdata/systemv
@@ -46,7 +46,7 @@ Rule SystemV 1975 only - Oct lastSun 2:00 0 S
Rule SystemV 1976 max - Apr lastSun 2:00 1:00 D
Rule SystemV 1976 max - Oct lastSun 2:00 0 S
-# Zone NAME GMTOFF RULES/SAVE FORMAT [UNTIL]
+# Zone NAME STDOFF RULES/SAVE FORMAT [UNTIL]
## Zone SystemV/AST4ADT -4:00 SystemV A%sT
## Zone SystemV/EST5EDT -5:00 SystemV E%sT
## Zone SystemV/CST6CDT -6:00 SystemV C%sT
diff --git a/make/data/tzdata/zone.tab b/make/data/tzdata/zone.tab
index 2a985868d2..8020ca0425 100644
--- a/make/data/tzdata/zone.tab
+++ b/make/data/tzdata/zone.tab
@@ -262,6 +262,7 @@ KW +2920+04759 Asia/Kuwait
KY +1918-08123 America/Cayman
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau
KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev
@@ -354,10 +355,13 @@ RO +4426+02606 Europe/Bucharest
RS +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
-RU +4457+03406 Europe/Simferopol MSK+00 - Crimea
-RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
+# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
+# Put it in RU section and list as UA. See "territorial claims" above.
+# Programs should use zone1970.tab instead; see above.
+UA +4457+03406 Europe/Simferopol MSK+00 - Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
+RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
diff --git a/make/gensrc/GensrcLocaleDataMetaInfo.gmk b/make/gensrc/GensrcLocaleDataMetaInfo.gmk
index d449ad82b2..6e4a001f9c 100644
--- a/make/gensrc/GensrcLocaleDataMetaInfo.gmk
+++ b/make/gensrc/GensrcLocaleDataMetaInfo.gmk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, 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
@@ -125,3 +125,13 @@ $(GENSRC_CRBC_DST): $(JDK_TOPDIR)/src/share/classes/sun/util/CoreResourceBundleC
GENSRC_LOCALEDATAMETAINFO += $(GENSRC_CRBC_DST)
###
+
+GENSRC_LSREQUIVMAPS_DST := $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/LocaleEquivalentMaps.java
+
+$(GENSRC_LSREQUIVMAPS_DST): $(JDK_TOPDIR)/make/data/lsrdata/language-subtag-registry.txt
+ $(MKDIR) -p $(@D)
+ $(TOOL_GENERATELSREQUIVMAPS) $< $@
+
+GENSRC_LOCALEDATAMETAINFO += $(GENSRC_LSREQUIVMAPS_DST)
+
+###
diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk
index 15d523747e..75fb8e4605 100644
--- a/make/lib/Awt2dLibraries.gmk
+++ b/make/lib/Awt2dLibraries.gmk
@@ -873,12 +873,9 @@ endif
ifeq ($(OPENJDK_TARGET_OS), solaris)
HARFBUZZ_CFLAGS += -DHAVE_SOLARIS_ATOMIC_OPS
endif
-ifeq ($(OPENJDK_TARGET_OS), macosx)
- HARFBUZZ_CFLAGS += -DHAVE_CORETEXT
-endif
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- LIBFONTMANAGER_EXCLUDE_FILES += harfbuzz/hb-coretext.cpp
-endif
+
+LIBFONTMANAGER_EXCLUDE_FILES += harfbuzz/hb-coretext.cpp
+
# hb-ft.cc is not presently needed, and requires freetype 2.4.2 or later.
LIBFONTMANAGER_EXCLUDE_FILES += harfbuzz/hb-ft.cpp
@@ -1186,6 +1183,7 @@ ifndef BUILD_HEADLESS_ONLY
endif
LIBSPLASHSCREEN_CFLAGS := -DSPLASHSCREEN -DPNG_NO_MMX_CODE \
+ -DPNG_ARM_NEON_OPT=0 -DPNG_ARM_NEON_IMPLEMENTATION=0 \
$(foreach dir, $(LIBSPLASHSCREEN_DIRS), -I$(dir))
ifeq ($(OPENJDK_TARGET_OS), macosx)
diff --git a/make/lib/CoreLibraries.gmk b/make/lib/CoreLibraries.gmk
index 6696f30ec9..c8e4815e11 100644
--- a/make/lib/CoreLibraries.gmk
+++ b/make/lib/CoreLibraries.gmk
@@ -36,12 +36,13 @@ ifeq ($(OPENJDK_TARGET_OS), solaris)
BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
endif
-ifeq ($(OPENJDK_TARGET_OS), linux)
- ifeq ($(OPENJDK_TARGET_CPU), ppc64)
- BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
- else ifeq ($(OPENJDK_TARGET_CPU), ppc64le)
- BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
- endif
+
+# If FDLIBM_CFLAGS is non-empty we know that we can optimize
+# fdlibm when adding those extra C flags. Currently GCC only.
+LIBFDLIBM_CFLAGS :=
+ifneq ($(FDLIBM_CFLAGS), )
+ BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
+ LIBFDLIBM_CFLAGS := $(FDLIBM_CFLAGS)
endif
ifneq ($(OPENJDK_TARGET_OS), macosx)
@@ -60,8 +61,7 @@ ifneq ($(OPENJDK_TARGET_OS), macosx)
-I$(JDK_TOPDIR)/src/share/native/java/lang/fdlibm/include, \
CFLAGS_windows_debug := -DLOGGING, \
CFLAGS_aix := -qfloat=nomaf, \
- CFLAGS_linux_ppc64 := -mno-fused-madd -fno-strict-aliasing, \
- CFLAGS_linux_ppc64le := -ffp-contract=off, \
+ CFLAGS_linux := $(LIBFDLIBM_CFLAGS), \
ARFLAGS := $(ARFLAGS), \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libfdlibm, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
diff --git a/make/lib/NetworkingLibraries.gmk b/make/lib/NetworkingLibraries.gmk
index 47006d0b87..347c323763 100644
--- a/make/lib/NetworkingLibraries.gmk
+++ b/make/lib/NetworkingLibraries.gmk
@@ -75,7 +75,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
LDFLAGS_SUFFIX_linux := $(LIBDL) -ljvm -lpthread -ljava, \
LDFLAGS_SUFFIX_aix := $(LIBDL) -ljvm -ljava,\
LDFLAGS_SUFFIX_windows := ws2_32.lib jvm.lib secur32.lib iphlpapi.lib \
- delayimp.lib urlmon.lib $(WIN_JAVA_LIB) advapi32.lib \
+ delayimp.lib $(WIN_JAVA_LIB) advapi32.lib \
-DELAYLOAD:secur32.dll -DELAYLOAD:iphlpapi.dll, \
VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/windows/resource/version.rc, \
RC_FLAGS := $(RC_FLAGS) \
diff --git a/make/mapfiles/launchers/mapfile-x86 b/make/mapfiles/launchers/mapfile-x86
index dcda7f9495..5951e8e496 100644
--- a/make/mapfiles/launchers/mapfile-x86
+++ b/make/mapfiles/launchers/mapfile-x86
@@ -42,6 +42,11 @@ SUNWprivate_1.1 {
__fsr;
__fsr_init_value;
__longdouble_used;
+ # Needs to be global rather than local. Note that _IO_stdin_used
+ # is exported by crt1.o. If it were using 'local' scope instead,
+ # glibc would use a legacy implementation of libio, which isn't
+ # what we want
+ _IO_stdin_used;
local:
*;
diff --git a/make/mapfiles/libj2pkcs11/mapfile-vers b/make/mapfiles/libj2pkcs11/mapfile-vers
index 6ca76c0704..8f01cdef35 100644
--- a/make/mapfiles/libj2pkcs11/mapfile-vers
+++ b/make/mapfiles/libj2pkcs11/mapfile-vers
@@ -32,6 +32,8 @@ SUNWprivate_1.1 {
Java_sun_security_pkcs11_wrapper_PKCS11_finalizeLibrary;
Java_sun_security_pkcs11_wrapper_PKCS11_connect;
Java_sun_security_pkcs11_wrapper_PKCS11_disconnect;
+ Java_sun_security_pkcs11_wrapper_PKCS11_getNativeKeyInfo;
+ Java_sun_security_pkcs11_wrapper_PKCS11_createNativeKey;
Java_sun_security_pkcs11_wrapper_PKCS11_C_1Initialize;
Java_sun_security_pkcs11_wrapper_PKCS11_C_1Finalize;
Java_sun_security_pkcs11_wrapper_PKCS11_C_1GetInfo;
diff --git a/make/mapfiles/libsunec/mapfile-vers b/make/mapfiles/libsunec/mapfile-vers
index 3295322638..7ba855202c 100644
--- a/make/mapfiles/libsunec/mapfile-vers
+++ b/make/mapfiles/libsunec/mapfile-vers
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2017, 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,6 +27,7 @@
SUNWprivate_1.1 {
global:
+ Java_sun_security_ec_ECKeyPairGenerator_isCurveSupported;
Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair;
Java_sun_security_ec_ECDSASignature_signDigest;
Java_sun_security_ec_ECDSASignature_verifySignedDigest;
diff --git a/make/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java b/make/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java
new file mode 100644
index 0000000000..c693eedc24
--- /dev/null
+++ b/make/src/classes/build/tools/generatelsrequivmaps/EquivMapsGenerator.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2012, 2017, 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.
+ */
+
+package build.tools.generatelsrequivmaps;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.TreeMap;
+
+/**
+ * This tool reads the IANA Language Subtag Registry data file downloaded from
+ * http://www.iana.org/assignments/language-subtag-registry, which is specified
+ * in the command line and generates a .java source file as specified in
+ * command line. The generated .java source file contains equivalent language
+ * maps. These equivalent language maps are used by LocaleMatcher.java
+ * for the locale matching mechanism specified in RFC 4647 "Matching of Language
+ * Tags".
+ */
+public class EquivMapsGenerator {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length != 2) {
+ System.err.println("Usage: java EquivMapsGenerator"
+ + " language-subtag-registry.txt LocaleEquivalentMaps.java");
+ System.exit(1);
+ }
+ readLSRfile(args[0]);
+ generateEquivalentMap();
+ generateSourceCode(args[1]);
+ }
+
+ private static String LSRrevisionDate;
+ private static Map<String, StringBuilder> initialLanguageMap =
+ new TreeMap<>();
+ private static Map<String, StringBuilder> initialRegionVariantMap =
+ new TreeMap<>();
+
+ private static Map<String, String> sortedLanguageMap1 = new TreeMap<>();
+ private static Map<String, String[]> sortedLanguageMap2 = new TreeMap<>();
+ private static Map<String, String> sortedRegionVariantMap =
+ new TreeMap<>();
+
+ private static void readLSRfile(String filename) throws Exception {
+ String type = null;
+ String tag = null;
+ String preferred = null;
+
+ for (String line : Files.readAllLines(Paths.get(filename),
+ Charset.forName("UTF-8"))) {
+ line = line.toLowerCase(Locale.ROOT);
+ int index = line.indexOf(' ')+1;
+ if (line.startsWith("file-date:")) {
+ LSRrevisionDate = line.substring(index);
+ } else if (line.startsWith("type:")) {
+ type = line.substring(index);
+ } else if (line.startsWith("tag:") || line.startsWith("subtag:")) {
+ tag = line.substring(index);
+ } else if (line.startsWith("preferred-value:")
+ && !type.equals("extlang")) {
+ preferred = line.substring(index);
+ processDeprecatedData(type, tag, preferred);
+ } else if (line.equals("%%")) {
+ type = null;
+ tag = null;
+ }
+ }
+ }
+
+ private static void processDeprecatedData(String type,
+ String tag,
+ String preferred) {
+ StringBuilder sb;
+ if (type.equals("region") || type.equals("variant")) {
+ if (!initialRegionVariantMap.containsKey(preferred)) {
+ sb = new StringBuilder("-");
+ sb.append(preferred);
+ sb.append(",-");
+ sb.append(tag);
+ initialRegionVariantMap.put("-"+preferred, sb);
+ } else {
+ throw new RuntimeException("New case, need implementation."
+ + " A region/variant subtag \"" + preferred
+ + "\" is registered for more than one subtags.");
+ }
+ } else { // language, grandfahered, and redundant
+ if (!initialLanguageMap.containsKey(preferred)) {
+ sb = new StringBuilder(preferred);
+ sb.append(',');
+ sb.append(tag);
+ initialLanguageMap.put(preferred, sb);
+ } else {
+ sb = initialLanguageMap.get(preferred);
+ sb.append(',');
+ sb.append(tag);
+ initialLanguageMap.put(preferred, sb);
+ }
+ }
+ }
+
+ private static void generateEquivalentMap() {
+ String[] subtags;
+ for (String preferred : initialLanguageMap.keySet()) {
+ subtags = initialLanguageMap.get(preferred).toString().split(",");
+
+ if (subtags.length == 2) {
+ sortedLanguageMap1.put(subtags[0], subtags[1]);
+ sortedLanguageMap1.put(subtags[1], subtags[0]);
+ } else if (subtags.length > 2) {
+ for (int i = 0; i < subtags.length; i++) {
+ sortedLanguageMap2.put(subtags[i], createLangArray(i, subtags));
+ }
+ } else {
+ throw new RuntimeException("New case, need implementation."
+ + " A language subtag \"" + preferred
+ + "\" is registered for more than two subtags. ");
+ }
+ }
+
+ for (String preferred : initialRegionVariantMap.keySet()) {
+ subtags =
+ initialRegionVariantMap.get(preferred).toString().split(",");
+
+ sortedRegionVariantMap.put(subtags[0], subtags[1]);
+ sortedRegionVariantMap.put(subtags[1], subtags[0]);
+ }
+
+ }
+
+ /* create the array of subtags excluding the subtag at index location */
+ private static String[] createLangArray(int index, String[] subtags) {
+ List<String> list = new ArrayList<>();
+ for (int i = 0; i < subtags.length; i++) {
+ if (i != index) {
+ list.add(subtags[i]);
+ }
+ }
+ return list.toArray(new String[list.size()]);
+ }
+
+ private static String generateValuesString(String[] values) {
+ String outputStr = "";
+ for (int i = 0; i < values.length; i++) {
+ if (i != values.length - 1) {
+ outputStr = outputStr + "\"" + values[i] + "\", ";
+ } else {
+ outputStr = outputStr + "\"" + values[i] + "\"";
+ }
+
+ }
+ return outputStr;
+ }
+
+ private static final String COPYRIGHT = "/*\n"
+ + " * Copyright (c) 2012, %d, Oracle and/or its affiliates. All rights reserved.\n"
+ + " * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n"
+ + " *\n"
+ + " * This code is free software; you can redistribute it and/or modify it\n"
+ + " * under the terms of the GNU General Public License version 2 only, as\n"
+ + " * published by the Free Software Foundation. Oracle designates this\n"
+ + " * particular file as subject to the \"Classpath\" exception as provided\n"
+ + " * by Oracle in the LICENSE file that accompanied this code.\n"
+ + " *\n"
+ + " * This code is distributed in the hope that it will be useful, but WITHOUT\n"
+ + " * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n"
+ + " * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n"
+ + " * version 2 for more details (a copy is included in the LICENSE file that\n"
+ + " * accompanied this code).\n"
+ + " *\n"
+ + " * You should have received a copy of the GNU General Public License version\n"
+ + " * 2 along with this work; if not, write to the Free Software Foundation,\n"
+ + " * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n"
+ + " *\n"
+ + " * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n"
+ + " * or visit www.oracle.com if you need additional information or have any\n"
+ + " * questions.\n"
+ + "*/\n\n";
+
+ private static final String headerText =
+ "package sun.util.locale;\n\n"
+ + "import java.util.HashMap;\n"
+ + "import java.util.Map;\n\n"
+ + "final class LocaleEquivalentMaps {\n\n"
+ + " static final Map<String, String> singleEquivMap;\n"
+ + " static final Map<String, String[]> multiEquivsMap;\n"
+ + " static final Map<String, String> regionVariantEquivMap;\n\n"
+ + " static {\n"
+ + " singleEquivMap = new HashMap<>();\n"
+ + " multiEquivsMap = new HashMap<>();\n"
+ + " regionVariantEquivMap = new HashMap<>();\n\n"
+ + " // This is an auto-generated file and should not be manually edited.\n";
+
+ private static final String footerText =
+ " }\n\n"
+ + "}";
+
+ private static String getOpenJDKCopyright() {
+ int year = Calendar.getInstance(TimeZone
+ .getTimeZone("America/Los_Angeles")).get(Calendar.YEAR);
+ return String.format(Locale.US, COPYRIGHT, year);
+ }
+
+ /**
+ * The input lsr data file is in UTF-8, so theoretically for the characters
+ * beyond US-ASCII, the generated Java String literals need to be Unicode
+ * escaped (\\uXXXX) while writing to a file. But as of now, there is not
+ * the case since we don't use "description", "comment" or alike.
+ */
+ private static void generateSourceCode(String fileName) {
+
+ try (BufferedWriter writer = Files.newBufferedWriter(
+ Paths.get(fileName), StandardCharsets.UTF_8)) {
+ writer.write(getOpenJDKCopyright());
+ writer.write(headerText
+ + " // LSR Revision: " + LSRrevisionDate);
+ writer.newLine();
+
+ for (String key : sortedLanguageMap1.keySet()) {
+ String value = sortedLanguageMap1.get(key);
+ writer.write(" singleEquivMap.put(\""
+ + key + "\", \"" + value + "\");");
+ writer.newLine();
+ }
+
+ writer.newLine();
+ for (String key : sortedLanguageMap2.keySet()) {
+ String[] values = sortedLanguageMap2.get(key);
+
+ if (values.length >= 2) {
+ writer.write(" multiEquivsMap.put(\""
+ + key + "\", new String[] {"
+ + generateValuesString(values) + "});");
+ writer.newLine();
+ }
+ }
+
+ writer.newLine();
+ for (String key : sortedRegionVariantMap.keySet()) {
+ String value = sortedRegionVariantMap.get(key);
+ writer.write(" regionVariantEquivMap.put(\""
+ + key + "\", \"" + value + "\");");
+ writer.newLine();
+ }
+
+ writer.write(footerText);
+ } catch (IOException ex) {
+ ex.printStackTrace(System.err);
+ System.exit(1);
+ }
+
+ }
+
+}
diff --git a/src/macosx/native/java/util/SCDynamicStoreConfig.m b/src/macosx/native/java/util/SCDynamicStoreConfig.m
index d3f838871a..4ea43635d4 100644
--- a/src/macosx/native/java/util/SCDynamicStoreConfig.m
+++ b/src/macosx/native/java/util/SCDynamicStoreConfig.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -102,7 +102,8 @@ NSDictionary *realmConfigsForRealms(SCDynamicStoreRef store, NSArray *realms) {
for (NSString *realm in realms) {
CFTypeRef realmInfo = SCDynamicStoreCopyValue(store, (CFStringRef) [NSString stringWithFormat:@"Kerberos:%@", realm]);
- if (CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) {
+ if (realmInfo == NULL || CFGetTypeID(realmInfo) != CFDictionaryGetTypeID()) {
+ if (realmInfo) CFRelease(realmInfo);
return nil;
}
diff --git a/src/macosx/native/sun/awt/JavaComponentAccessibility.m b/src/macosx/native/sun/awt/JavaComponentAccessibility.m
index 09eee74d16..3a6498629e 100644
--- a/src/macosx/native/sun/awt/JavaComponentAccessibility.m
+++ b/src/macosx/native/sun/awt/JavaComponentAccessibility.m
@@ -325,15 +325,15 @@ static NSObject *sAttributeNamesLOCK = nil;
}
JavaComponentAccessibility *child = [self createWithParent:parent accessible:jchild role:childJavaRole index:childIndex withEnv:env withView:parent->fView];
-
+
(*env)->DeleteLocalRef(env, jchild);
(*env)->DeleteLocalRef(env, jchildJavaRole);
-
+
[children addObject:child];
childIndex++;
}
(*env)->DeleteLocalRef(env, jchildrenAndRoles);
-
+
return children;
}
@@ -1170,7 +1170,7 @@ static NSObject *sAttributeNamesLOCK = nil;
// Need to handle popupmenus differently.
//
// At least for now don't handle combo box menus.
- // This may change when later fixing issues which currently
+ // This may change when later fixing issues which currently
// exist for combo boxes, but for now the following is only
// for JPopupMenus, not for combobox menus.
id parent = [self parent];
@@ -1352,7 +1352,7 @@ static NSObject *sAttributeNamesLOCK = nil;
NSWindow* hostWindow = [[self->fView window] retain];
jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop)
[hostWindow release];
-
+
if (focused != NULL) {
if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) {
value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView];
diff --git a/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m b/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m
index d235dbc586..b2c240c149 100644
--- a/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m
+++ b/src/macosx/native/sun/awt/splashscreen/splashscreen_sys.m
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -188,7 +188,7 @@ SplashInitPlatform(Splash * splash) {
splash->maskRequired = 0;
-
+
//TODO: the following is too much of a hack but should work in 90% cases.
// besides we don't use device-dependant drawing, so probably
// that's very fine indeed
@@ -255,9 +255,11 @@ void
SplashRedrawWindow(Splash * splash) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
- SplashUpdateScreenData(splash);
-
[JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){
+ // drop the reference to the old view and image
+ [splash->window setContentView: nil];
+ SplashUpdateScreenData(splash);
+
// NSDeviceRGBColorSpace vs. NSCalibratedRGBColorSpace ?
NSBitmapImageRep * rep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes: (unsigned char**)&splash->screenData
@@ -285,7 +287,7 @@ SplashRedrawWindow(Splash * splash) {
size.height /= scaleFactor;
[image setSize: size];
}
-
+
NSImageView * view = [[NSImageView alloc] init];
[view setImage: image];
diff --git a/src/share/classes/com/sun/crypto/provider/AESCrypt.java b/src/share/classes/com/sun/crypto/provider/AESCrypt.java
index c85f715e96..c74f609f3a 100644
--- a/src/share/classes/com/sun/crypto/provider/AESCrypt.java
+++ b/src/share/classes/com/sun/crypto/provider/AESCrypt.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -346,7 +346,15 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
* Encrypt exactly one block of plaintext.
*/
void encryptBlock(byte[] in, int inOffset,
- byte[] out, int outOffset)
+ byte[] out, int outOffset) {
+ // Array bound checks are done in caller code, i.e.
+ // FeedbackCipher.encrypt/decrypt(...) to improve performance.
+ implEncryptBlock(in, inOffset, out, outOffset);
+ }
+
+ // Encryption operation. Possibly replaced with a compiler intrinsic.
+ private void implEncryptBlock(byte[] in, int inOffset,
+ byte[] out, int outOffset)
{
int keyOffset = 0;
int t0 = ((in[inOffset++] ) << 24 |
@@ -412,12 +420,19 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
out[outOffset ] = (byte)(S[(t2 ) & 0xFF] ^ (tt ));
}
-
/**
* Decrypt exactly one block of plaintext.
*/
void decryptBlock(byte[] in, int inOffset,
- byte[] out, int outOffset)
+ byte[] out, int outOffset) {
+ // Array bound checks are done in caller code, i.e.
+ // FeedbackCipher.encrypt/decrypt(...) to improve performance.
+ implDecryptBlock(in, inOffset, out, outOffset);
+ }
+
+ // Decrypt operation. Possibly replaced with a compiler intrinsic.
+ private void implDecryptBlock(byte[] in, int inOffset,
+ byte[] out, int outOffset)
{
int keyOffset = 4;
int t0 = ((in[inOffset++] ) << 24 |
@@ -572,7 +587,6 @@ final class AESCrypt extends SymmetricCipher implements AESConstants
out[outOffset ] = (byte)(Si[(a0 ) & 0xFF] ^ (t1 ));
}
-
/**
* Expand a user-supplied key material into a session key.
*
diff --git a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java
index 1d33117dd5..dc4c89465e 100644
--- a/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java
+++ b/src/share/classes/com/sun/crypto/provider/CipherBlockChaining.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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,7 +27,7 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
-
+import java.util.Objects;
/**
* This class represents ciphers in cipher block chaining (CBC) mode.
@@ -138,18 +138,24 @@ class CipherBlockChaining extends FeedbackCipher {
* @return the length of the encrypted data
*/
int encrypt(byte[] plain, int plainOffset, int plainLen,
- byte[] cipher, int cipherOffset)
- {
+ byte[] cipher, int cipherOffset) {
if (plainLen <= 0) {
return plainLen;
}
- if ((plainLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(plainLen, blockSize);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+ return implEncrypt(plain, plainOffset, plainLen,
+ cipher, cipherOffset);
+ }
+
+ private int implEncrypt(byte[] plain, int plainOffset, int plainLen,
+ byte[] cipher, int cipherOffset)
+ {
int endIndex = plainOffset + plainLen;
for (; plainOffset < endIndex;
- plainOffset+=blockSize, cipherOffset += blockSize) {
+ plainOffset += blockSize, cipherOffset += blockSize) {
for (int i = 0; i < blockSize; i++) {
k[i] = (byte)(plain[i + plainOffset] ^ r[i]);
}
@@ -182,14 +188,19 @@ class CipherBlockChaining extends FeedbackCipher {
* @return the length of the decrypted data
*/
int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
- byte[] plain, int plainOffset)
- {
+ byte[] plain, int plainOffset) {
if (cipherLen <= 0) {
return cipherLen;
}
- if ((cipherLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(cipherLen, blockSize);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen);
+ return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset);
+ }
+
+ private int implDecrypt(byte[] cipher, int cipherOffset, int cipherLen,
+ byte[] plain, int plainOffset)
+ {
int endIndex = cipherOffset + cipherLen;
for (; cipherOffset < endIndex;
diff --git a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java
index 84b527efe5..bbdf316281 100644
--- a/src/share/classes/com/sun/crypto/provider/CipherFeedback.java
+++ b/src/share/classes/com/sun/crypto/provider/CipherFeedback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -149,9 +149,9 @@ final class CipherFeedback extends FeedbackCipher {
*/
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
- if ((plainLen % numBytes) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(plainLen, numBytes);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
int nShift = blockSize - numBytes;
int loopCount = plainLen / numBytes;
@@ -225,9 +225,10 @@ final class CipherFeedback extends FeedbackCipher {
*/
int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
byte[] plain, int plainOffset) {
- if ((cipherLen % numBytes) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+
+ RangeUtil.blockSizeCheck(cipherLen, numBytes);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen);
int nShift = blockSize - numBytes;
int loopCount = cipherLen / numBytes;
diff --git a/src/share/classes/com/sun/crypto/provider/CounterMode.java b/src/share/classes/com/sun/crypto/provider/CounterMode.java
index b810b8ff8c..aea9336c9a 100644
--- a/src/share/classes/com/sun/crypto/provider/CounterMode.java
+++ b/src/share/classes/com/sun/crypto/provider/CounterMode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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,7 +27,6 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
-
/**
* This class represents ciphers in counter (CTR) mode.
*
@@ -173,6 +172,10 @@ final class CounterMode extends FeedbackCipher {
if (len == 0) {
return 0;
}
+
+ RangeUtil.nullAndBoundsCheck(in, inOff, len);
+ RangeUtil.nullAndBoundsCheck(out, outOff, len);
+
int result = len;
while (len-- > 0) {
if (used >= blockSize) {
diff --git a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java
index 334e4245e2..c0c53ac943 100644
--- a/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java
+++ b/src/share/classes/com/sun/crypto/provider/ElectronicCodeBook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -112,9 +112,10 @@ final class ElectronicCodeBook extends FeedbackCipher {
* @return the length of the encrypted data
*/
int encrypt(byte[] in, int inOff, int len, byte[] out, int outOff) {
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(len, blockSize);
+ RangeUtil.nullAndBoundsCheck(in, inOff, len);
+ RangeUtil.nullAndBoundsCheck(out, outOff, len);
+
for (int i = len; i >= blockSize; i -= blockSize) {
embeddedCipher.encryptBlock(in, inOff, out, outOff);
inOff += blockSize;
@@ -141,9 +142,10 @@ final class ElectronicCodeBook extends FeedbackCipher {
* @return the length of the decrypted data
*/
int decrypt(byte[] in, int inOff, int len, byte[] out, int outOff) {
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(len, blockSize);
+ RangeUtil.nullAndBoundsCheck(in, inOff, len);
+ RangeUtil.nullAndBoundsCheck(out, outOff, len);
+
for (int i = len; i >= blockSize; i -= blockSize) {
embeddedCipher.decryptBlock(in, inOff, out, outOff);
inOff += blockSize;
diff --git a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
index cdb22d1217..542337c78c 100644
--- a/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
+++ b/src/share/classes/com/sun/crypto/provider/GaloisCounterMode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@ import java.security.*;
import javax.crypto.*;
import static com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE;
+
/**
* This class represents ciphers in GaloisCounter (GCM) mode.
*
@@ -406,8 +407,8 @@ final class GaloisCounterMode extends FeedbackCipher {
/**
* Performs encryption operation.
*
- * <p>The input plain text <code>in</code>, starting at <code>inOff</code>
- * and ending at <code>(inOff + len - 1)</code>, is encrypted. The result
+ * <p>The input plain text <code>in</code>, starting at <code>inOfs</code>
+ * and ending at <code>(inOfs + len - 1)</code>, is encrypted. The result
* is stored in <code>out</code>, starting at <code>outOfs</code>.
*
* @param in the buffer with the input data to be encrypted
@@ -422,15 +423,18 @@ final class GaloisCounterMode extends FeedbackCipher {
int encrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
checkDataLength(processed, len);
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(len, blockSize);
processAAD();
+
if (len > 0) {
+ RangeUtil.nullAndBoundsCheck(in, inOfs, len);
+ RangeUtil.nullAndBoundsCheck(out, outOfs, len);
+
gctrPAndC.update(in, inOfs, len, out, outOfs);
processed += len;
ghashAllToS.update(out, outOfs, len);
}
+
return len;
}
@@ -450,7 +454,10 @@ final class GaloisCounterMode extends FeedbackCipher {
throw new ShortBufferException
("Can't fit both data and tag into one buffer");
}
- if (out.length - outOfs < (len + tagLenBytes)) {
+ try {
+ RangeUtil.nullAndBoundsCheck(out, outOfs,
+ (len + tagLenBytes));
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
@@ -458,6 +465,8 @@ final class GaloisCounterMode extends FeedbackCipher {
processAAD();
if (len > 0) {
+ RangeUtil.nullAndBoundsCheck(in, inOfs, len);
+
doLastBlock(in, inOfs, len, out, outOfs, true);
}
@@ -493,15 +502,14 @@ final class GaloisCounterMode extends FeedbackCipher {
int decrypt(byte[] in, int inOfs, int len, byte[] out, int outOfs) {
checkDataLength(ibuffer.size(), len);
- if ((len % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(len, blockSize);
processAAD();
if (len > 0) {
// store internally until decryptFinal is called because
// spec mentioned that only return recovered data after tag
// is successfully verified
+ RangeUtil.nullAndBoundsCheck(in, inOfs, len);
ibuffer.write(in, inOfs, len);
}
return 0;
@@ -530,22 +538,28 @@ final class GaloisCounterMode extends FeedbackCipher {
if (len < tagLenBytes) {
throw new AEADBadTagException("Input too short - need tag");
}
+
// do this check here can also catch the potential integer overflow
// scenario for the subsequent output buffer capacity check.
checkDataLength(ibuffer.size(), (len - tagLenBytes));
- if (out.length - outOfs < ((ibuffer.size() + len) - tagLenBytes)) {
+ try {
+ RangeUtil.nullAndBoundsCheck(out, outOfs,
+ (ibuffer.size() + len) - tagLenBytes);
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
throw new ShortBufferException("Output buffer too small");
}
processAAD();
+ RangeUtil.nullAndBoundsCheck(in, inOfs, len);
+
// get the trailing tag bytes from 'in'
byte[] tag = new byte[tagLenBytes];
System.arraycopy(in, inOfs + len - tagLenBytes, tag, 0, tagLenBytes);
len -= tagLenBytes;
- if (len != 0) {
+ if (len > 0) {
ibuffer.write(in, inOfs, len);
}
diff --git a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
index 47d9d63c93..2039fab075 100644
--- a/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
+++ b/src/share/classes/com/sun/crypto/provider/OutputFeedback.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -148,10 +148,10 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ RangeUtil.blockSizeCheck(plainLen, numBytes);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
- if ((plainLen % numBytes) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
int nShift = blockSize - numBytes;
int loopCount = plainLen / numBytes;
@@ -189,6 +189,9 @@ final class OutputFeedback extends FeedbackCipher {
*/
int encryptFinal(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset) {
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int oddBytes = plainLen % numBytes;
int len = encrypt(plain, plainOffset, (plainLen - oddBytes),
cipher, cipherOffset);
diff --git a/src/share/classes/com/sun/crypto/provider/PBES1Core.java b/src/share/classes/com/sun/crypto/provider/PBES1Core.java
index 54bd4eb67e..f634a639c1 100644
--- a/src/share/classes/com/sun/crypto/provider/PBES1Core.java
+++ b/src/share/classes/com/sun/crypto/provider/PBES1Core.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -268,17 +268,20 @@ final class PBES1Core {
if (algo.equals("DES")) {
// P || S (password concatenated with salt)
- byte[] concat = new byte[Math.addExact(passwdBytes.length, salt.length)];
- System.arraycopy(passwdBytes, 0, concat, 0, passwdBytes.length);
- System.arraycopy(salt, 0, concat, passwdBytes.length, salt.length);
-
- // digest P || S with c iterations
- byte[] toBeHashed = concat;
- for (int i = 0; i < iCount; i++) {
+ md.update(passwdBytes);
+ md.update(salt);
+ // digest P || S with iCount iterations
+ // first iteration
+ byte[] toBeHashed = md.digest(); // this resets the digest
+ // remaining (iCount - 1) iterations
+ for (int i = 1; i < iCount; ++i) {
md.update(toBeHashed);
- toBeHashed = md.digest(); // this resets the digest
+ try {
+ md.digest(toBeHashed, 0, toBeHashed.length);
+ } catch (DigestException e) {
+ throw new ProviderException("Internal error", e);
+ }
}
- Arrays.fill(concat, (byte)0x00);
result = toBeHashed;
} else if (algo.equals("DESede")) {
// if the 2 salt halves are the same, invert one of them
@@ -305,13 +308,19 @@ final class PBES1Core {
result = new byte[DESedeKeySpec.DES_EDE_KEY_LEN +
DESConstants.DES_BLOCK_SIZE];
for (i = 0; i < 2; i++) {
- toBeHashed = new byte[salt.length/2];
- System.arraycopy(salt, i*(salt.length/2), toBeHashed, 0,
- toBeHashed.length);
- for (int j=0; j < iCount; j++) {
+ // first iteration
+ md.update(salt, i * (salt.length / 2), salt.length / 2);
+ md.update(passwdBytes);
+ toBeHashed = md.digest();
+ // remaining (iCount - 1) iterations
+ for (int j = 1; j < iCount; ++j) {
md.update(toBeHashed);
md.update(passwdBytes);
- toBeHashed = md.digest();
+ try {
+ md.digest(toBeHashed, 0, toBeHashed.length);
+ } catch (DigestException e) {
+ throw new ProviderException("Internal error", e);
+ }
}
System.arraycopy(toBeHashed, 0, result, i*16,
toBeHashed.length);
diff --git a/src/share/classes/com/sun/crypto/provider/PCBC.java b/src/share/classes/com/sun/crypto/provider/PCBC.java
index fd99bb0cbd..d2b4a2c65b 100644
--- a/src/share/classes/com/sun/crypto/provider/PCBC.java
+++ b/src/share/classes/com/sun/crypto/provider/PCBC.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -28,7 +28,6 @@ package com.sun.crypto.provider;
import java.security.InvalidKeyException;
import java.security.ProviderException;
-
/**
* This class represents ciphers in Plaintext Cipher Block Chaining (PCBC)
* mode.
@@ -136,9 +135,10 @@ final class PCBC extends FeedbackCipher {
int encrypt(byte[] plain, int plainOffset, int plainLen,
byte[] cipher, int cipherOffset)
{
- if ((plainLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(plainLen, blockSize);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, plainLen);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, plainLen);
+
int i;
int endIndex = plainOffset + plainLen;
@@ -176,9 +176,10 @@ final class PCBC extends FeedbackCipher {
int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
byte[] plain, int plainOffset)
{
- if ((cipherLen % blockSize) != 0) {
- throw new ProviderException("Internal error in input buffering");
- }
+ RangeUtil.blockSizeCheck(cipherLen, blockSize);
+ RangeUtil.nullAndBoundsCheck(cipher, cipherOffset, cipherLen);
+ RangeUtil.nullAndBoundsCheck(plain, plainOffset, cipherLen);
+
int i;
int endIndex = cipherOffset + cipherLen;
diff --git a/src/share/classes/com/sun/crypto/provider/Preconditions.java b/src/share/classes/com/sun/crypto/provider/Preconditions.java
new file mode 100644
index 0000000000..163d57f965
--- /dev/null
+++ b/src/share/classes/com/sun/crypto/provider/Preconditions.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2016, 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.crypto.provider;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+
+/**
+ * Utility methods to check if state or arguments are correct.
+ *
+ */
+public class Preconditions {
+
+ /**
+ * Maps out-of-bounds values to a runtime exception.
+ *
+ * @param checkKind the kind of bounds check, whose name may correspond
+ * to the name of one of the range check methods, checkIndex,
+ * checkFromToIndex, checkFromIndexSize
+ * @param args the out-of-bounds arguments that failed the range check.
+ * If the checkKind corresponds a the name of a range check method
+ * then the bounds arguments are those that can be passed in order
+ * to the method.
+ * @param oobef the exception formatter that when applied with a checkKind
+ * and a list out-of-bounds arguments returns a runtime exception.
+ * If {@code null} then, it is as if an exception formatter was
+ * supplied that returns {@link IndexOutOfBoundsException} for any
+ * given arguments.
+ * @return the runtime exception
+ */
+ private static RuntimeException outOfBounds(
+ BiFunction<String, List<Integer>, ? extends RuntimeException> oobef,
+ String checkKind,
+ Integer... args) {
+ List<Integer> largs = Collections.unmodifiableList(Arrays.asList(args));
+ RuntimeException e = oobef == null
+ ? null : oobef.apply(checkKind, largs);
+ return e == null
+ ? new IndexOutOfBoundsException(outOfBoundsMessage(checkKind, largs)) : e;
+ }
+
+ private static RuntimeException outOfBoundsCheckIndex(
+ BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+ int index, int length) {
+ return outOfBounds(oobe, "checkIndex", index, length);
+ }
+
+ private static RuntimeException outOfBoundsCheckFromToIndex(
+ BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+ int fromIndex, int toIndex, int length) {
+ return outOfBounds(oobe, "checkFromToIndex", fromIndex, toIndex, length);
+ }
+
+ private static RuntimeException outOfBoundsCheckFromIndexSize(
+ BiFunction<String, List<Integer>, ? extends RuntimeException> oobe,
+ int fromIndex, int size, int length) {
+ return outOfBounds(oobe, "checkFromIndexSize", fromIndex, size, length);
+ }
+
+ /**
+ * Returns an out-of-bounds exception formatter from an given exception
+ * factory. The exception formatter is a function that formats an
+ * out-of-bounds message from its arguments and applies that message to the
+ * given exception factory to produce and relay an exception.
+ *
+ * <p>The exception formatter accepts two arguments: a {@code String}
+ * describing the out-of-bounds range check that failed, referred to as the
+ * <em>check kind</em>; and a {@code List<Integer>} containing the
+ * out-of-bound integer values that failed the check. The list of
+ * out-of-bound values is not modified.
+ *
+ * <p>Three check kinds are supported {@code checkIndex},
+ * {@code checkFromToIndex} and {@code checkFromIndexSize} corresponding
+ * respectively to the specified application of an exception formatter as an
+ * argument to the out-of-bounds range check methods
+ * {@link #checkIndex(int, int, BiFunction) checkIndex},
+ * {@link #checkFromToIndex(int, int, int, BiFunction) checkFromToIndex}, and
+ * {@link #checkFromIndexSize(int, int, int, BiFunction) checkFromIndexSize}.
+ * Thus a supported check kind corresponds to a method name and the
+ * out-of-bound integer values correspond to method argument values, in
+ * order, preceding the exception formatter argument (similar in many
+ * respects to the form of arguments required for a reflective invocation of
+ * such a range check method).
+ *
+ * <p>Formatter arguments conforming to such supported check kinds will
+ * produce specific exception messages describing failed out-of-bounds
+ * checks. Otherwise, more generic exception messages will be produced in
+ * any of the following cases: the check kind is supported but fewer
+ * or more out-of-bounds values are supplied, the check kind is not
+ * supported, the check kind is {@code null}, or the list of out-of-bound
+ * values is {@code null}.
+ *
+ * @apiNote
+ * This method produces an out-of-bounds exception formatter that can be
+ * passed as an argument to any of the supported out-of-bounds range check
+ * methods declared by {@code Objects}. For example, a formatter producing
+ * an {@code ArrayIndexOutOfBoundsException} may be produced and stored on a
+ * {@code static final} field as follows:
+ * <pre>{@code
+ * static final
+ * BiFunction<String, List<Integer>, ArrayIndexOutOfBoundsException> AIOOBEF =
+ * outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new);
+ * }</pre>
+ * The formatter instance {@code AIOOBEF} may be passed as an argument to an
+ * out-of-bounds range check method, such as checking if an {@code index}
+ * is within the bounds of a {@code limit}:
+ * <pre>{@code
+ * checkIndex(index, limit, AIOOBEF);
+ * }</pre>
+ * If the bounds check fails then the range check method will throw an
+ * {@code ArrayIndexOutOfBoundsException} with an appropriate exception
+ * message that is a produced from {@code AIOOBEF} as follows:
+ * <pre>{@code
+ * AIOOBEF.apply("checkIndex", List.of(index, limit));
+ * }</pre>
+ *
+ * @param f the exception factory, that produces an exception from a message
+ * where the message is produced and formatted by the returned
+ * exception formatter. If this factory is stateless and side-effect
+ * free then so is the returned formatter.
+ * Exceptions thrown by the factory are relayed to the caller
+ * of the returned formatter.
+ * @param <X> the type of runtime exception to be returned by the given
+ * exception factory and relayed by the exception formatter
+ * @return the out-of-bounds exception formatter
+ */
+ public static <X extends RuntimeException>
+ BiFunction<String, List<Integer>, X> outOfBoundsExceptionFormatter(Function<String, X> f) {
+ // Use anonymous class to avoid bootstrap issues if this method is
+ // used early in startup
+ return new BiFunction<String, List<Integer>, X>() {
+ @Override
+ public X apply(String checkKind, List<Integer> args) {
+ return f.apply(outOfBoundsMessage(checkKind, args));
+ }
+ };
+ }
+
+ private static String outOfBoundsMessage(String checkKind, List<Integer> args) {
+ if (checkKind == null && args == null) {
+ return String.format("Range check failed");
+ } else if (checkKind == null) {
+ return String.format("Range check failed: %s", args);
+ } else if (args == null) {
+ return String.format("Range check failed: %s", checkKind);
+ }
+
+ int argSize = 0;
+ switch (checkKind) {
+ case "checkIndex":
+ argSize = 2;
+ break;
+ case "checkFromToIndex":
+ case "checkFromIndexSize":
+ argSize = 3;
+ break;
+ default:
+ }
+
+ // Switch to default if fewer or more arguments than required are supplied
+ switch ((args.size() != argSize) ? "" : checkKind) {
+ case "checkIndex":
+ return String.format("Index %d out-of-bounds for length %d",
+ args.get(0), args.get(1));
+ case "checkFromToIndex":
+ return String.format("Range [%d, %d) out-of-bounds for length %d",
+ args.get(0), args.get(1), args.get(2));
+ case "checkFromIndexSize":
+ return String.format("Range [%d, %<d + %d) out-of-bounds for length %d",
+ args.get(0), args.get(1), args.get(2));
+ default:
+ return String.format("Range check failed: %s %s", checkKind, args);
+ }
+ }
+
+ /**
+ * Checks if the {@code index} is within the bounds of the range from
+ * {@code 0} (inclusive) to {@code length} (exclusive).
+ *
+ * <p>The {@code index} is defined to be out-of-bounds if any of the
+ * following inequalities is true:
+ * <ul>
+ * <li>{@code index < 0}</li>
+ * <li>{@code index >= length}</li>
+ * <li>{@code length < 0}, which is implied from the former inequalities</li>
+ * </ul>
+ *
+ * <p>If the {@code index} is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkIndex};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code index} and {@code length}.
+ *
+ * @param <X> the type of runtime exception to throw if the arguments are
+ * out-of-bounds
+ * @param index the index
+ * @param length the upper-bound (exclusive) of the range
+ * @param oobef the exception formatter that when applied with this
+ * method name and out-of-bounds arguments returns a runtime
+ * exception. If {@code null} or returns {@code null} then, it is as
+ * if an exception formatter produced from an invocation of
+ * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+ * instead (though it may be more efficient).
+ * Exceptions thrown by the formatter are relayed to the caller.
+ * @return {@code index} if it is within bounds of the range
+ * @throws X if the {@code index} is out-of-bounds and the exception
+ * formatter is non-{@code null}
+ * @throws IndexOutOfBoundsException if the {@code index} is out-of-bounds
+ * and the exception formatter is {@code null}
+ * @since 9
+ *
+ * @implNote
+ * This method is made intrinsic in optimizing compilers to guide them to
+ * perform unsigned comparisons of the index and length when it is known the
+ * length is a non-negative value (such as that of an array length or from
+ * the upper bound of a loop)
+ */
+ public static <X extends RuntimeException>
+ int checkIndex(int index, int length,
+ BiFunction<String, List<Integer>, X> oobef) {
+ if (index < 0 || index >= length)
+ throw outOfBoundsCheckIndex(oobef, index, length);
+ return index;
+ }
+
+ /**
+ * Checks if the sub-range from {@code fromIndex} (inclusive) to
+ * {@code toIndex} (exclusive) is within the bounds of range from {@code 0}
+ * (inclusive) to {@code length} (exclusive).
+ *
+ * <p>The sub-range is defined to be out-of-bounds if any of the following
+ * inequalities is true:
+ * <ul>
+ * <li>{@code fromIndex < 0}</li>
+ * <li>{@code fromIndex > toIndex}</li>
+ * <li>{@code toIndex > length}</li>
+ * <li>{@code length < 0}, which is implied from the former inequalities</li>
+ * </ul>
+ *
+ * <p>If the sub-range is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkFromToIndex};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code fromIndex}, {@code toIndex}, and {@code length}.
+ *
+ * @param <X> the type of runtime exception to throw if the arguments are
+ * out-of-bounds
+ * @param fromIndex the lower-bound (inclusive) of the sub-range
+ * @param toIndex the upper-bound (exclusive) of the sub-range
+ * @param length the upper-bound (exclusive) the range
+ * @param oobef the exception formatter that when applied with this
+ * method name and out-of-bounds arguments returns a runtime
+ * exception. If {@code null} or returns {@code null} then, it is as
+ * if an exception formatter produced from an invocation of
+ * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+ * instead (though it may be more efficient).
+ * Exceptions thrown by the formatter are relayed to the caller.
+ * @return {@code fromIndex} if the sub-range within bounds of the range
+ * @throws X if the sub-range is out-of-bounds and the exception factory
+ * function is non-{@code null}
+ * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+ * the exception factory function is {@code null}
+ * @since 9
+ */
+ public static <X extends RuntimeException>
+ int checkFromToIndex(int fromIndex, int toIndex, int length,
+ BiFunction<String, List<Integer>, X> oobef) {
+ if (fromIndex < 0 || fromIndex > toIndex || toIndex > length)
+ throw outOfBoundsCheckFromToIndex(oobef, fromIndex, toIndex, length);
+ return fromIndex;
+ }
+
+ /**
+ * Checks if the sub-range from {@code fromIndex} (inclusive) to
+ * {@code fromIndex + size} (exclusive) is within the bounds of range from
+ * {@code 0} (inclusive) to {@code length} (exclusive).
+ *
+ * <p>The sub-range is defined to be out-of-bounds if any of the following
+ * inequalities is true:
+ * <ul>
+ * <li>{@code fromIndex < 0}</li>
+ * <li>{@code size < 0}</li>
+ * <li>{@code fromIndex + size > length}, taking into account integer overflow</li>
+ * <li>{@code length < 0}, which is implied from the former inequalities</li>
+ * </ul>
+ *
+ * <p>If the sub-range is out-of-bounds, then a runtime exception is
+ * thrown that is the result of applying the following arguments to the
+ * exception formatter: the name of this method, {@code checkFromIndexSize};
+ * and an unmodifiable list integers whose values are, in order, the
+ * out-of-bounds arguments {@code fromIndex}, {@code size}, and
+ * {@code length}.
+ *
+ * @param <X> the type of runtime exception to throw if the arguments are
+ * out-of-bounds
+ * @param fromIndex the lower-bound (inclusive) of the sub-interval
+ * @param size the size of the sub-range
+ * @param length the upper-bound (exclusive) of the range
+ * @param oobef the exception formatter that when applied with this
+ * method name and out-of-bounds arguments returns a runtime
+ * exception. If {@code null} or returns {@code null} then, it is as
+ * if an exception formatter produced from an invocation of
+ * {@code outOfBoundsExceptionFormatter(IndexOutOfBounds::new)} is used
+ * instead (though it may be more efficient).
+ * Exceptions thrown by the formatter are relayed to the caller.
+ * @return {@code fromIndex} if the sub-range within bounds of the range
+ * @throws X if the sub-range is out-of-bounds and the exception factory
+ * function is non-{@code null}
+ * @throws IndexOutOfBoundsException if the sub-range is out-of-bounds and
+ * the exception factory function is {@code null}
+ * @since 9
+ */
+ public static <X extends RuntimeException>
+ int checkFromIndexSize(int fromIndex, int size, int length,
+ BiFunction<String, List<Integer>, X> oobef) {
+ if ((length | fromIndex | size) < 0 || size > length - fromIndex)
+ throw outOfBoundsCheckFromIndexSize(oobef, fromIndex, size, length);
+ return fromIndex;
+ }
+}
diff --git a/src/share/classes/com/sun/crypto/provider/RangeUtil.java b/src/share/classes/com/sun/crypto/provider/RangeUtil.java
new file mode 100644
index 0000000000..ea4983811e
--- /dev/null
+++ b/src/share/classes/com/sun/crypto/provider/RangeUtil.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018, 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.crypto.provider;
+
+import java.util.List;
+import java.util.function.BiFunction;
+import java.security.*;
+
+/**
+ * This class holds the various utility methods for range checks.
+ */
+
+final class RangeUtil {
+
+ private static final BiFunction<String, List<Integer>,
+ ArrayIndexOutOfBoundsException> AIOOBE_SUPPLIER =
+ Preconditions.outOfBoundsExceptionFormatter
+ (ArrayIndexOutOfBoundsException::new);
+
+ public static void blockSizeCheck(int len, int blockSize) {
+ if ((len % blockSize) != 0) {
+ throw new ProviderException("Internal error in input buffering");
+ }
+ }
+
+ public static void nullAndBoundsCheck(byte[] array, int offset, int len) {
+ // NPE is thrown when array is null
+ Preconditions.checkFromIndexSize(offset, len, array.length, AIOOBE_SUPPLIER);
+ }
+}
diff --git a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
index 5c93d89e0e..8f58f5b3e6 100644
--- a/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
+++ b/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -374,7 +374,10 @@ public class JPEGImageReader extends ImageReader {
// And set current image since we've read it now
currentImage = 0;
}
- if (seekForwardOnly) {
+ // If the image positions list is empty as in the case of a tables-only
+ // stream, then attempting to access the element at index
+ // imagePositions.size() - 1 will cause an IndexOutOfBoundsException.
+ if (seekForwardOnly && !imagePositions.isEmpty()) {
Long pos = (Long) imagePositions.get(imagePositions.size()-1);
iis.flushBefore(pos.longValue());
}
@@ -491,6 +494,11 @@ public class JPEGImageReader extends ImageReader {
if (!tablesOnlyChecked) {
checkTablesOnly();
}
+ // If the image positions list is empty as in the case of a tables-only
+ // stream, then no image data can be read.
+ if (imagePositions.isEmpty()) {
+ throw new IIOException("No image data present to read");
+ }
if (imageIndex < imagePositions.size()) {
iis.seek(((Long)(imagePositions.get(imageIndex))).longValue());
} else {
diff --git a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
index c5e700d687..e81d341d74 100644
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java
@@ -535,6 +535,34 @@ class GTKPainter extends SynthPainter {
}
}
+ private int getBrightness(Color c) {
+ return Math.max(c.getRed(), Math.max(c.getGreen(), c.getBlue()));
+ }
+
+ private int getMaxColorDiff(Color c1, Color c2) {
+ return Math.max(Math.abs(c1.getRed() - c2.getRed()),
+ Math.max(Math.abs(c1.getGreen() - c2.getGreen()),
+ Math.abs(c1.getBlue() - c2.getBlue())));
+ }
+
+ private int scaleColorComponent(int color, double scaleFactor) {
+ return (int)(color + color * scaleFactor);
+ }
+ private Color deriveColor(Color originalColor, int originalBrightness,
+ int targetBrightness) {
+ int r, g, b;
+ if (originalBrightness == 0) {
+ r = g = b = targetBrightness;
+ } else {
+ double scaleFactor = (targetBrightness - originalBrightness)
+ / originalBrightness ;
+ r = scaleColorComponent(originalColor.getRed(), scaleFactor);
+ g = scaleColorComponent(originalColor.getGreen(), scaleFactor);
+ b = scaleColorComponent(originalColor.getBlue(), scaleFactor);
+ }
+ return new Color(r, g, b);
+ }
+
//
// MENU
//
@@ -551,6 +579,57 @@ class GTKPainter extends SynthPainter {
int gtkState = GTKLookAndFeel.synthStateToGTKState(
context.getRegion(), context.getComponentState());
if (gtkState == SynthConstants.MOUSE_OVER) {
+ if (GTKLookAndFeel.is3() && context.getRegion() == Region.MENU) {
+ GTKStyle style = (GTKStyle)context.getStyle();
+ Color highlightColor = style.getGTKColor(
+ GTKEngine.WidgetType.MENU_ITEM.ordinal(),
+ gtkState, ColorType.BACKGROUND.getID());
+ Color backgroundColor = style.getGTKColor(
+ GTKEngine.WidgetType.MENU_BAR.ordinal(),
+ SynthConstants.ENABLED, ColorType.BACKGROUND.getID());
+
+ int minBrightness = 0, maxBrightness = 255;
+ int minBrightnessDifference = 100;
+ int actualBrightnessDifference =
+ getMaxColorDiff(highlightColor, backgroundColor);
+ if (actualBrightnessDifference < minBrightnessDifference) {
+ int highlightBrightness =
+ getBrightness(highlightColor);
+ int backgroundBrightness =
+ getBrightness(backgroundColor);
+ int originalHighlightBrightness =
+ highlightBrightness;
+ if (highlightBrightness >= backgroundBrightness) {
+ if (backgroundBrightness + minBrightnessDifference <=
+ maxBrightness) {
+ highlightBrightness =
+ backgroundBrightness +
+ minBrightnessDifference;
+ } else {
+ highlightBrightness =
+ backgroundBrightness -
+ minBrightnessDifference;
+ }
+ } else {
+ if (backgroundBrightness - minBrightnessDifference >=
+ minBrightness) {
+ highlightBrightness =
+ backgroundBrightness -
+ minBrightnessDifference;
+ } else {
+ highlightBrightness =
+ backgroundBrightness +
+ minBrightnessDifference;
+ }
+ }
+
+ g.setColor(deriveColor(highlightColor,
+ originalHighlightBrightness,
+ highlightBrightness));
+ g.fillRect(x, y, w, h);
+ return;
+ }
+ }
Region id = Region.MENU_ITEM;
synchronized (UNIXToolkit.GTK_LOCK) {
if (! ENGINE.paintCachedImage(g, x, y, w, h, id)) {
diff --git a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java
index 6a469b1d4d..54b5dd3329 100644
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java
+++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java
@@ -201,6 +201,14 @@ class GTKStyle extends SynthStyle implements GTKConstants {
return getGTKColor(null, state, type);
}
+ Color getGTKColor(int widgetType, int state, int colorType) {
+ synchronized (sun.awt.UNIXToolkit.GTK_LOCK) {
+ int rgb = nativeGetColorForState(widgetType, state,
+ colorType);
+ return new ColorUIResource(rgb);
+ }
+ }
+
/**
* Returns the color for the specified state.
*
@@ -735,7 +743,8 @@ class GTKStyle extends SynthStyle implements GTKConstants {
region == Region.TOOL_BAR_DRAG_WINDOW ||
region == Region.TOOL_TIP ||
region == Region.TREE ||
- region == Region.VIEWPORT) {
+ region == Region.VIEWPORT ||
+ region == Region.TEXT_PANE) {
return true;
}
if (!GTKLookAndFeel.is3()) {
@@ -743,8 +752,7 @@ class GTKStyle extends SynthStyle implements GTKConstants {
region == Region.FORMATTED_TEXT_FIELD ||
region == Region.PASSWORD_FIELD ||
region == Region.SPINNER ||
- region == Region.TEXT_FIELD ||
- region == Region.TEXT_PANE) {
+ region == Region.TEXT_FIELD) {
return true;
}
}
@@ -1166,13 +1174,24 @@ class GTKStyle extends SynthStyle implements GTKConstants {
ICONS_MAP = new HashMap<String, GTKStockIcon>();
ICONS_MAP.put("FileChooser.cancelIcon", new GTKStockIcon("gtk-cancel", 4));
ICONS_MAP.put("FileChooser.okIcon", new GTKStockIcon("gtk-ok", 4));
- ICONS_MAP.put("OptionPane.errorIcon", new GTKStockIcon("gtk-dialog-error", 6));
- ICONS_MAP.put("OptionPane.informationIcon", new GTKStockIcon("gtk-dialog-info", 6));
- ICONS_MAP.put("OptionPane.warningIcon", new GTKStockIcon("gtk-dialog-warning", 6));
- ICONS_MAP.put("OptionPane.questionIcon", new GTKStockIcon("gtk-dialog-question", 6));
ICONS_MAP.put("OptionPane.yesIcon", new GTKStockIcon("gtk-yes", 4));
ICONS_MAP.put("OptionPane.noIcon", new GTKStockIcon("gtk-no", 4));
ICONS_MAP.put("OptionPane.cancelIcon", new GTKStockIcon("gtk-cancel", 4));
ICONS_MAP.put("OptionPane.okIcon", new GTKStockIcon("gtk-ok", 4));
+
+ //check whether the gtk version is >= 3.10 as the Icon names were
+ //changed from this version
+ UNIXToolkit tk = (UNIXToolkit)Toolkit.getDefaultToolkit();
+ if (tk.checkGtkVersion(3, 10, 0)) {
+ ICONS_MAP.put("OptionPane.errorIcon", new GTKStockIcon("dialog-error", 6));
+ ICONS_MAP.put("OptionPane.informationIcon", new GTKStockIcon("dialog-information", 6));
+ ICONS_MAP.put("OptionPane.warningIcon", new GTKStockIcon("dialog-warning", 6));
+ ICONS_MAP.put("OptionPane.questionIcon", new GTKStockIcon("dialog-question", 6));
+ } else {
+ ICONS_MAP.put("OptionPane.errorIcon", new GTKStockIcon("gtk-dialog-error", 6));
+ ICONS_MAP.put("OptionPane.informationIcon", new GTKStockIcon("gtk-dialog-info", 6));
+ ICONS_MAP.put("OptionPane.warningIcon", new GTKStockIcon("gtk-dialog-warning", 6));
+ ICONS_MAP.put("OptionPane.questionIcon", new GTKStockIcon("gtk-dialog-question", 6));
+ }
}
}
diff --git a/src/share/classes/com/sun/jndi/ldap/BerDecoder.java b/src/share/classes/com/sun/jndi/ldap/BerDecoder.java
index 9feefb47fe..58a64154f1 100644
--- a/src/share/classes/com/sun/jndi/ldap/BerDecoder.java
+++ b/src/share/classes/com/sun/jndi/ldap/BerDecoder.java
@@ -186,12 +186,16 @@ public final class BerDecoder extends Ber {
*</pre></blockquote>
*/
private int parseIntWithTag(int tag) throws DecodeException {
-
-
if (parseByte() != tag) {
+ // Ber could have been reset;
+ String s;
+ if (offset > 0) {
+ s = Integer.toString(buf[offset - 1] & 0xff);
+ } else {
+ s = "Empty tag";
+ }
throw new DecodeException("Encountered ASN.1 tag " +
- Integer.toString(buf[offset - 1] & 0xff) +
- " (expected tag " + Integer.toString(tag) + ")");
+ s + " (expected tag " + Integer.toString(tag) + ")");
}
int len = parseLength();
diff --git a/src/share/classes/com/sun/jndi/ldap/Connection.java b/src/share/classes/com/sun/jndi/ldap/Connection.java
index 0c059f5bfa..43e83c12b5 100644
--- a/src/share/classes/com/sun/jndi/ldap/Connection.java
+++ b/src/share/classes/com/sun/jndi/ldap/Connection.java
@@ -453,65 +453,29 @@ public final class Connection implements Runnable {
/**
* Reads a reply; waits until one is ready.
*/
- BerDecoder readReply(LdapRequest ldr)
- throws IOException, NamingException {
+ BerDecoder readReply(LdapRequest ldr) throws IOException, NamingException {
BerDecoder rber;
- // Track down elapsed time to workaround spurious wakeups
- long elapsedMilli = 0;
- long elapsedNano = 0;
-
- while (((rber = ldr.getReplyBer()) == null) &&
- (readTimeout <= 0 || elapsedMilli < readTimeout))
- {
- try {
- // If socket closed, don't even try
- synchronized (this) {
- if (sock == null) {
- throw new ServiceUnavailableException(host + ":" + port +
- "; socket closed");
- }
- }
- synchronized (ldr) {
- // check if condition has changed since our last check
- rber = ldr.getReplyBer();
- if (rber == null) {
- if (readTimeout > 0) { // Socket read timeout is specified
- long beginNano = System.nanoTime();
-
- // will be woken up before readTimeout if reply is
- // available
- ldr.wait(readTimeout - elapsedMilli);
- elapsedNano += (System.nanoTime() - beginNano);
- elapsedMilli += elapsedNano / 1000_000;
- elapsedNano %= 1000_000;
-
- } else {
- // no timeout is set so we wait infinitely until
- // a response is received
- // https://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
- ldr.wait();
- }
- } else {
- break;
- }
- }
- } catch (InterruptedException ex) {
- throw new InterruptedNamingException(
- "Interrupted during LDAP operation");
- }
+ try {
+ // if no timeout is set so we wait infinitely until
+ // a response is received
+ // http://docs.oracle.com/javase/8/docs/technotes/guides/jndi/jndi-ldap.html#PROP
+ rber = ldr.getReplyBer(readTimeout);
+ } catch (InterruptedException ex) {
+ throw new InterruptedNamingException(
+ "Interrupted during LDAP operation");
}
- if ((rber == null) && (elapsedMilli >= readTimeout)) {
+ if (rber == null) {
abandonRequest(ldr, null);
- throw new NamingException("LDAP response read timed out, timeout used:"
+ throw new NamingException(
+ "LDAP response read timed out, timeout used:"
+ readTimeout + "ms." );
}
return rber;
}
-
////////////////////////////////////////////////////////////////////////////
//
// Methods to add, find, delete, and abandon requests made to server
@@ -705,14 +669,11 @@ public final class Connection implements Runnable {
if (nparent) {
LdapRequest ldr = pendingRequests;
while (ldr != null) {
-
- synchronized (ldr) {
- ldr.notify();
+ ldr.close();
ldr = ldr.next;
}
}
}
- }
if (nparent) {
parent.processConnectionClosure();
}
@@ -800,7 +761,7 @@ public final class Connection implements Runnable {
* the safest thing to do is to shut it down.
*/
- private Object pauseLock = new Object(); // lock for reader to wait on while paused
+ private final Object pauseLock = new Object(); // lock for reader to wait on while paused
private boolean paused = false; // paused state of reader
/*
diff --git a/src/share/classes/com/sun/jndi/ldap/LdapRequest.java b/src/share/classes/com/sun/jndi/ldap/LdapRequest.java
index 23347ac5dc..ddea9d40b8 100644
--- a/src/share/classes/com/sun/jndi/ldap/LdapRequest.java
+++ b/src/share/classes/com/sun/jndi/ldap/LdapRequest.java
@@ -29,55 +29,52 @@ import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import javax.naming.CommunicationException;
+import java.util.concurrent.TimeUnit;
final class LdapRequest {
- LdapRequest next; // Set/read in synchronized Connection methods
- int msgId; // read-only
+ private final static BerDecoder EOF = new BerDecoder(new byte[]{}, -1, 0);
- private int gotten = 0;
- private BlockingQueue<BerDecoder> replies;
- private int highWatermark = -1;
- private boolean cancelled = false;
- private boolean pauseAfterReceipt = false;
- private boolean completed = false;
+ LdapRequest next; // Set/read in synchronized Connection methods
+ final int msgId; // read-only
- LdapRequest(int msgId, boolean pause) {
- this(msgId, pause, -1);
- }
+ private final BlockingQueue<BerDecoder> replies;
+ private volatile boolean cancelled;
+ private volatile boolean closed;
+ private volatile boolean completed;
+ private final boolean pauseAfterReceipt;
LdapRequest(int msgId, boolean pause, int replyQueueCapacity) {
this.msgId = msgId;
this.pauseAfterReceipt = pause;
if (replyQueueCapacity == -1) {
- this.replies = new LinkedBlockingQueue<BerDecoder>();
+ this.replies = new LinkedBlockingQueue<>();
} else {
- this.replies =
- new LinkedBlockingQueue<BerDecoder>(replyQueueCapacity);
- highWatermark = (replyQueueCapacity * 80) / 100; // 80% capacity
+ this.replies = new LinkedBlockingQueue<>(8 * replyQueueCapacity / 10);
}
}
- synchronized void cancel() {
+ void cancel() {
cancelled = true;
+ replies.offer(EOF);
+ }
- // Unblock reader of pending request
- // Should only ever have atmost one waiter
- notify();
+ synchronized void close() {
+ closed = true;
+ replies.offer(EOF);
+ }
+
+ private boolean isClosed() {
+ return closed && (replies.size() == 0 || replies.peek() == EOF);
}
synchronized boolean addReplyBer(BerDecoder ber) {
- if (cancelled) {
+ // check the closed boolean value here as we don't want anything
+ // to be added to the queue after close() has been called.
+ if (cancelled || closed) {
return false;
}
- // Add a new reply to the queue of unprocessed replies.
- try {
- replies.put(ber);
- } catch (InterruptedException e) {
- // ignore
- }
-
// peek at the BER buffer to check if it is a SearchResultDone PDU
try {
ber.parseSeq(null);
@@ -88,33 +85,38 @@ final class LdapRequest {
}
ber.reset();
- notify(); // notify anyone waiting for reply
- /*
- * If a queue capacity has been set then trigger a pause when the
- * queue has filled to 80% capacity. Later, when the queue has drained
- * then the reader gets unpaused.
- */
- if (highWatermark != -1 && replies.size() >= highWatermark) {
- return true; // trigger the pause
+ // Add a new reply to the queue of unprocessed replies.
+ try {
+ replies.put(ber);
+ } catch (InterruptedException e) {
+ // ignore
}
+
return pauseAfterReceipt;
}
- synchronized BerDecoder getReplyBer() throws CommunicationException {
+ BerDecoder getReplyBer(long millis) throws CommunicationException,
+ InterruptedException {
+ if (cancelled) {
+ throw new CommunicationException("Request: " + msgId +
+ " cancelled");
+ }
+ if (isClosed()) {
+ return null;
+ }
+
+ BerDecoder result = millis > 0 ?
+ replies.poll(millis, TimeUnit.MILLISECONDS) : replies.take();
+
if (cancelled) {
throw new CommunicationException("Request: " + msgId +
" cancelled");
}
- /*
- * Remove a reply if the queue is not empty.
- * poll returns null if queue is empty.
- */
- BerDecoder reply = replies.poll();
- return reply;
+ return result == EOF ? null : result;
}
- synchronized boolean hasSearchCompleted() {
+ boolean hasSearchCompleted() {
return completed;
}
}
diff --git a/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java b/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
index 8539a266ee..8547363b18 100644
--- a/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
+++ b/src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -668,7 +668,11 @@ public class Krb5LoginModule implements LoginModule {
// check to renew credentials
if (!isCurrent(cred)) {
if (renewTGT) {
- cred = renewCredentials(cred);
+ Credentials newCred = renewCredentials(cred);
+ if (newCred != null) {
+ newCred.setProxy(cred.getProxy());
+ }
+ cred = newCred;
} else {
// credentials have expired
cred = null;
@@ -1074,6 +1078,10 @@ public class Krb5LoginModule implements LoginModule {
// create Kerberos Ticket
if (isInitiator) {
kerbTicket = Krb5Util.credsToTicket(cred);
+ if (cred.getProxy() != null) {
+ KerberosSecrets.getJavaxSecurityAuthKerberosAccess()
+ .kerberosTicketSetProxy(kerbTicket,Krb5Util.credsToTicket(cred.getProxy()));
+ }
}
if (storeKey && encKeys != null) {
diff --git a/src/share/classes/java/awt/Font.java b/src/share/classes/java/awt/Font.java
index bdc9ca6345..a261e68359 100644
--- a/src/share/classes/java/awt/Font.java
+++ b/src/share/classes/java/awt/Font.java
@@ -1752,6 +1752,7 @@ public class Font implements java.io.Serializable
// value is the default.
if (fRequestedAttributes != null) {
+ try {
values = getAttributeValues(); // init
AttributeValues extras =
AttributeValues.fromSerializableHashtable(fRequestedAttributes);
@@ -1761,10 +1762,13 @@ public class Font implements java.io.Serializable
values = getAttributeValues().merge(extras);
this.nonIdentityTx = values.anyNonDefault(EXTRA_MASK);
this.hasLayoutAttributes = values.anyNonDefault(LAYOUT_MASK);
-
+ } catch (Throwable t) {
+ throw new IOException(t);
+ } finally {
fRequestedAttributes = null; // don't need it any more
}
}
+ }
/**
* Returns the number of glyphs in this <code>Font</code>. Glyph codes
diff --git a/src/share/classes/java/awt/Toolkit.java b/src/share/classes/java/awt/Toolkit.java
index ef4d4ab850..d58a9baa68 100644
--- a/src/share/classes/java/awt/Toolkit.java
+++ b/src/share/classes/java/awt/Toolkit.java
@@ -1674,9 +1674,7 @@ public abstract class Toolkit {
// ensure that the proper libraries are loaded
loadLibraries();
initAssistiveTechnologies();
- if (!GraphicsEnvironment.isHeadless()) {
- initIDs();
- }
+ initIDs();
}
/**
diff --git a/src/share/classes/java/io/FilePermission.java b/src/share/classes/java/io/FilePermission.java
index c15e78c9bc..3e0f7d871c 100644
--- a/src/share/classes/java/io/FilePermission.java
+++ b/src/share/classes/java/io/FilePermission.java
@@ -25,12 +25,16 @@
package java.io;
+import java.net.URI;
+import java.nio.file.InvalidPathException;
import java.security.*;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;
import java.util.Collections;
+
+import sun.nio.fs.DefaultFileSystemProvider;
import sun.security.util.SecurityConstants;
/**
@@ -152,6 +156,8 @@ public final class FilePermission extends Permission implements Serializable {
private transient String cpath;
+ private transient boolean invalid; // whether input path is invalid
+
// static Strings used by init(int mask)
private static final char RECURSIVE_CHAR = '-';
private static final char WILD_CHAR = '*';
@@ -174,6 +180,14 @@ public final class FilePermission extends Permission implements Serializable {
private static final long serialVersionUID = 7930732926638008763L;
/**
+ * Always use the internal default file system, in case it was modified
+ * with java.nio.file.spi.DefaultFileSystemProvider.
+ */
+ private static final java.nio.file.FileSystem builtInFS =
+ DefaultFileSystemProvider.create()
+ .getFileSystem(URI.create("file:///"));
+
+ /**
* initialize a FilePermission object. Common to all constructors.
* Also called during de-serialization.
*
@@ -199,6 +213,20 @@ public final class FilePermission extends Permission implements Serializable {
return;
}
+ // Validate path by platform's default file system
+ // Note: this check does not apply during FilePermission
+ // class initialization.
+ if (builtInFS != null) {
+ try {
+ String name = cpath.endsWith("*") ?
+ cpath.substring(0, cpath.length() - 1) + "-" : cpath;
+ builtInFS.getPath(new File(name).getPath());
+ } catch (InvalidPathException ipe) {
+ invalid = true;
+ return;
+ }
+ }
+
// store only the canonical cpath if possible
cpath = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
@@ -335,6 +363,12 @@ public final class FilePermission extends Permission implements Serializable {
* @return the effective mask
*/
boolean impliesIgnoreMask(FilePermission that) {
+ if (this == that) {
+ return true;
+ }
+ if (this.invalid || that.invalid) {
+ return false;
+ }
if (this.directory) {
if (this.recursive) {
// make sure that.path is longer then path so
@@ -395,6 +429,9 @@ public final class FilePermission extends Permission implements Serializable {
FilePermission that = (FilePermission) obj;
+ if (this.invalid || that.invalid) {
+ return false;
+ }
return (this.mask == that.mask) &&
this.cpath.equals(that.cpath) &&
(this.directory == that.directory) &&
diff --git a/src/share/classes/java/io/LineNumberReader.java b/src/share/classes/java/io/LineNumberReader.java
index 29884fdaa6..8cd6c14596 100644
--- a/src/share/classes/java/io/LineNumberReader.java
+++ b/src/share/classes/java/io/LineNumberReader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -259,6 +259,11 @@ public class LineNumberReader extends BufferedReader {
*/
public void mark(int readAheadLimit) throws IOException {
synchronized (lock) {
+ // If the most recently read character is '\r', then increment the
+ // read ahead limit as in this case if the next character is '\n',
+ // two characters would actually be read by the next read().
+ if (skipLF)
+ readAheadLimit++;
super.mark(readAheadLimit);
markedLineNumber = lineNumber;
markedSkipLF = skipLF;
diff --git a/src/share/classes/java/io/ObjectStreamClass.java b/src/share/classes/java/io/ObjectStreamClass.java
index bcbbea2611..a2181c6095 100644
--- a/src/share/classes/java/io/ObjectStreamClass.java
+++ b/src/share/classes/java/io/ObjectStreamClass.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -2371,7 +2371,7 @@ public class ObjectStreamClass implements Serializable {
*/
private static class FieldReflectorKey extends WeakReference<Class<?>> {
- private final String sigs;
+ private final String[] sigs;
private final int hash;
private final boolean nullClass;
@@ -2380,13 +2380,13 @@ public class ObjectStreamClass implements Serializable {
{
super(cl, queue);
nullClass = (cl == null);
- StringBuilder sbuf = new StringBuilder();
- for (int i = 0; i < fields.length; i++) {
+ sigs = new String[2 * fields.length];
+ for (int i = 0, j = 0; i < fields.length; i++) {
ObjectStreamField f = fields[i];
- sbuf.append(f.getName()).append(f.getSignature());
+ sigs[j++] = f.getName();
+ sigs[j++] = f.getSignature();
}
- sigs = sbuf.toString();
- hash = System.identityHashCode(cl) + sigs.hashCode();
+ hash = System.identityHashCode(cl) + Arrays.hashCode(sigs);
}
public int hashCode() {
@@ -2404,7 +2404,7 @@ public class ObjectStreamClass implements Serializable {
return (nullClass ? other.nullClass
: ((referent = get()) != null) &&
(referent == other.get())) &&
- sigs.equals(other.sigs);
+ Arrays.equals(sigs, other.sigs);
} else {
return false;
}
diff --git a/src/share/classes/java/lang/ClassLoader.java b/src/share/classes/java/lang/ClassLoader.java
index 842af56143..2e98092f63 100644
--- a/src/share/classes/java/lang/ClassLoader.java
+++ b/src/share/classes/java/lang/ClassLoader.java
@@ -255,9 +255,6 @@ public abstract class ClassLoader {
new ProtectionDomain(new CodeSource(null, (Certificate[]) null),
null, this, null);
- // The initiating protection domains for all classes loaded by this loader
- private final Set<ProtectionDomain> domains;
-
// Invoked by the VM to record every loaded class with this loader.
void addClass(Class<?> c) {
classes.addElement(c);
@@ -281,14 +278,11 @@ public abstract class ClassLoader {
if (ParallelLoaders.isRegistered(this.getClass())) {
parallelLockMap = new ConcurrentHashMap<>();
package2certs = new ConcurrentHashMap<>();
- domains =
- Collections.synchronizedSet(new HashSet<ProtectionDomain>());
assertionLock = new Object();
} else {
// no finer-grained lock; lock on the classloader instance
parallelLockMap = null;
package2certs = new Hashtable<>();
- domains = new HashSet<>();
assertionLock = this;
}
}
@@ -505,7 +499,6 @@ public abstract class ClassLoader {
}, new AccessControlContext(new ProtectionDomain[] {pd}));
}
}
- domains.add(pd);
}
/**
diff --git a/src/share/classes/java/lang/Throwable.java b/src/share/classes/java/lang/Throwable.java
index 4b9e2ad041..34440fa2c5 100644
--- a/src/share/classes/java/lang/Throwable.java
+++ b/src/share/classes/java/lang/Throwable.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, 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
@@ -24,8 +24,9 @@
*/
package java.lang;
-import java.io.*;
-import java.util.*;
+
+import java.io.*;
+import java.util.*;
/**
* The {@code Throwable} class is the superclass of all errors and
@@ -912,25 +913,37 @@ public class Throwable implements Serializable {
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject(); // read in all fields
- if (suppressedExceptions != null) {
- List<Throwable> suppressed = null;
- if (suppressedExceptions.isEmpty()) {
- // Use the sentinel for a zero-length list
- suppressed = SUPPRESSED_SENTINEL;
- } else { // Copy Throwables to new list
- suppressed = new ArrayList<>(1);
- for (Throwable t : suppressedExceptions) {
+
+ // Set suppressed exceptions and stack trace elements fields
+ // to marker values until the contents from the serial stream
+ // are validated.
+ List<Throwable> candidateSuppressedExceptions = suppressedExceptions;
+ suppressedExceptions = SUPPRESSED_SENTINEL;
+
+ StackTraceElement[] candidateStackTrace = stackTrace;
+ stackTrace = UNASSIGNED_STACK.clone();
+
+ if (candidateSuppressedExceptions != null) {
+ int suppressedSize = validateSuppressedExceptionsList(candidateSuppressedExceptions);
+ if (suppressedSize > 0) { // Copy valid Throwables to new list
+ List<Throwable> suppList = new ArrayList<Throwable>(Math.min(100, suppressedSize));
+
+ for (Throwable t : candidateSuppressedExceptions) {
// Enforce constraints on suppressed exceptions in
// case of corrupt or malicious stream.
if (t == null)
throw new NullPointerException(NULL_CAUSE_MESSAGE);
if (t == this)
throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE);
- suppressed.add(t);
+ suppList.add(t);
}
+ // If there are any invalid suppressed exceptions,
+ // implicitly use the sentinel value assigned earlier.
+ suppressedExceptions = suppList;
}
- suppressedExceptions = suppressed;
- } // else a null suppressedExceptions field remains null
+ } else {
+ suppressedExceptions = null;
+ }
/*
* For zero-length stack traces, use a clone of
@@ -941,25 +954,41 @@ public class Throwable implements Serializable {
* the stackTrace needs to be constructed from the information
* in backtrace.
*/
- if (stackTrace != null) {
- if (stackTrace.length == 0) {
- stackTrace = UNASSIGNED_STACK.clone();
- } else if (stackTrace.length == 1 &&
+ if (candidateStackTrace != null) {
+ // Work from a clone of the candidateStackTrace to ensure
+ // consistency of checks.
+ candidateStackTrace = candidateStackTrace.clone();
+ if (candidateStackTrace.length >= 1) {
+ if (candidateStackTrace.length == 1 &&
// Check for the marker of an immutable stack trace
- SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(stackTrace[0])) {
- stackTrace = null;
- } else { // Verify stack trace elements are non-null.
- for(StackTraceElement ste : stackTrace) {
- if (ste == null)
- throw new NullPointerException("null StackTraceElement in serial stream. ");
+ SentinelHolder.STACK_TRACE_ELEMENT_SENTINEL.equals(candidateStackTrace[0])) {
+ stackTrace = null;
+ } else { // Verify stack trace elements are non-null.
+ for (StackTraceElement ste : candidateStackTrace) {
+ if (ste == null)
+ throw new NullPointerException("null StackTraceElement in serial stream.");
+ }
+ stackTrace = candidateStackTrace;
}
}
+ }
+ // A null stackTrace field in the serial form can result from
+ // an exception serialized without that field in older JDK
+ // releases; treat such exceptions as having empty stack
+ // traces by leaving stackTrace assigned to a clone of
+ // UNASSIGNED_STACK.
+ }
+
+ private int validateSuppressedExceptionsList(List<Throwable> deserSuppressedExceptions)
+ throws IOException {
+ if (Object.class.getClassLoader() != deserSuppressedExceptions.getClass().getClassLoader()) {
+ throw new StreamCorruptedException("List implementation not on the bootclasspath.");
} else {
- // A null stackTrace field in the serial form can result
- // from an exception serialized without that field in
- // older JDK releases; treat such exceptions as having
- // empty stack traces.
- stackTrace = UNASSIGNED_STACK.clone();
+ int size = deserSuppressedExceptions.size();
+ if (size < 0) {
+ throw new StreamCorruptedException("Negative list size reported.");
+ }
+ return size;
}
}
diff --git a/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
index d549b63254..878581a25c 100644
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -30,6 +30,8 @@ import java.security.AccessController;
import java.security.PrivilegedAction;
import sun.invoke.WrapperInstance;
import java.util.ArrayList;
+import java.util.concurrent.ConcurrentHashMap;
+
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
@@ -50,8 +52,10 @@ public class MethodHandleProxies {
* A single-method interface is an interface which declares a uniquely named method.
* When determining the uniquely named method of a single-method interface,
* the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
- * are disregarded. For example, {@link java.util.Comparator} is a single-method interface,
- * even though it re-declares the {@code Object.equals} method.
+ * are disregarded as are any default (non-abstract) methods.
+ * For example, {@link java.util.Comparator} is a single-method interface,
+ * even though it re-declares the {@code Object.equals} method and also
+ * declares default methods, such as {@code Comparator.reverse}.
* <p>
* The interface must be public. No additional access checks are performed.
* <p>
@@ -175,6 +179,8 @@ public class MethodHandleProxies {
checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
}
+ final ConcurrentHashMap<Method, MethodHandle> defaultMethodMap =
+ hasDefaultMethods(intfc) ? new ConcurrentHashMap<>() : null;
final InvocationHandler ih = new InvocationHandler() {
private Object getArg(String name) {
if ((Object)name == "getWrapperInstanceTarget") return target;
@@ -190,6 +196,9 @@ public class MethodHandleProxies {
return getArg(method.getName());
if (isObjectMethod(method))
return callObjectMethod(proxy, method, args);
+ if (isDefaultMethod(method)) {
+ return callDefaultMethod(defaultMethodMap, proxy, intfc, method, args);
+ }
throw newInternalError("bad proxy method: "+method);
}
};
@@ -319,4 +328,45 @@ public class MethodHandleProxies {
if (uniqueName == null) return null;
return methods.toArray(new Method[methods.size()]);
}
+
+ private static
+ boolean isDefaultMethod(Method m) {
+ return !Modifier.isAbstract(m.getModifiers());
+ }
+
+ private static
+ boolean hasDefaultMethods(Class<?> intfc) {
+ for (Method m : intfc.getMethods()) {
+ if (!isObjectMethod(m) &&
+ !Modifier.isAbstract(m.getModifiers())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static
+ Object callDefaultMethod(ConcurrentHashMap<Method, MethodHandle> defaultMethodMap,
+ Object self, Class<?> intfc, Method m, Object[] args) throws Throwable {
+ assert(isDefaultMethod(m) && !isObjectMethod(m)) : m;
+
+ // Lazily compute the associated method handle from the method
+ MethodHandle dmh = defaultMethodMap.computeIfAbsent(m, mk -> {
+ try {
+ // Look up the default method for special invocation thereby
+ // avoiding recursive invocation back to the proxy
+ MethodHandle mh = MethodHandles.Lookup.IMPL_LOOKUP.findSpecial(
+ intfc, mk.getName(),
+ MethodType.methodType(mk.getReturnType(), mk.getParameterTypes()),
+ self.getClass());
+ return mh.asSpreader(Object[].class, mk.getParameterCount());
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ // The method is known to exist and should be accessible, this
+ // method would not be called unless the invokeinterface to the
+ // default (public) method passed access control checks
+ throw new InternalError(e);
+ }
+ });
+ return dmh.invoke(self, args);
+ }
}
diff --git a/src/share/classes/java/net/NetPermission.java b/src/share/classes/java/net/NetPermission.java
index 9178f34872..2cda1bcdad 100644
--- a/src/share/classes/java/net/NetPermission.java
+++ b/src/share/classes/java/net/NetPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -151,6 +151,15 @@ have access to. Thus it might be able to trick the system into
creating a ProtectionDomain/CodeSource for a class even though
that class really didn't come from that location.</td>
* </tr>
+ *
+ * <tr>
+ * <th scope="row">setSocketImpl</th>
+ * <td>The ability to create a sub-class of Socket or ServerSocket with a
+ * user specified SocketImpl.</td>
+ * <td>Malicious user-defined SocketImpls can change the behavior of
+ * Socket and ServerSocket in surprising ways, by virtue of their
+ * ability to access the protected fields of SocketImpl.</td>
+ * </tr>
* </table>
*
* @see java.security.BasicPermission
diff --git a/src/share/classes/java/net/ServerSocket.java b/src/share/classes/java/net/ServerSocket.java
index 2ee3420d54..6dd0496223 100644
--- a/src/share/classes/java/net/ServerSocket.java
+++ b/src/share/classes/java/net/ServerSocket.java
@@ -31,6 +31,8 @@ import java.nio.channels.ServerSocketChannel;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
+import sun.security.util.SecurityConstants;
+
/**
* This class implements server sockets. A server socket waits for
* requests to come in over the network. It performs some operation
@@ -71,12 +73,25 @@ class ServerSocket implements java.io.Closeable {
/**
* Package-private constructor to create a ServerSocket associated with
* the given SocketImpl.
+ *
+ * @throws SecurityException if a security manager is set and
+ * its {@code checkPermission} method doesn't allow
+ * {@code NetPermission("setSocketImpl")}.
*/
ServerSocket(SocketImpl impl) {
+ checkPermission();
this.impl = impl;
impl.setServerSocket(this);
}
+ private static Void checkPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+ }
+ return null;
+ }
+
/**
* Creates an unbound server socket.
*
diff --git a/src/share/classes/java/net/Socket.java b/src/share/classes/java/net/Socket.java
index ff841fc0fb..eed64378b5 100644
--- a/src/share/classes/java/net/Socket.java
+++ b/src/share/classes/java/net/Socket.java
@@ -25,6 +25,8 @@
package java.net;
+import sun.security.util.SecurityConstants;
+
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
@@ -159,9 +161,14 @@ class Socket implements java.io.Closeable {
*
* @exception SocketException if there is an error in the underlying protocol,
* such as a TCP error.
+ *
+ * @throws SecurityException if {@code impl} is non-null and a security manager is set
+ * and its {@code checkPermission} method doesn't allow {@code NetPermission("setSocketImpl")}.
+ *
* @since JDK1.1
*/
protected Socket(SocketImpl impl) throws SocketException {
+ checkPermission(impl);
this.impl = impl;
if (impl != null) {
checkOldImpl();
@@ -169,6 +176,17 @@ class Socket implements java.io.Closeable {
}
}
+ private static Void checkPermission(SocketImpl impl) {
+ if (impl == null) {
+ return null;
+ }
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(SecurityConstants.SET_SOCKETIMPL_PERMISSION);
+ }
+ return null;
+ }
+
/**
* Creates a stream socket and connects it to the specified port
* number on the named host.
diff --git a/src/share/classes/java/net/SocksSocketImpl.java b/src/share/classes/java/net/SocksSocketImpl.java
index dd89283fbd..3d162ec829 100644
--- a/src/share/classes/java/net/SocksSocketImpl.java
+++ b/src/share/classes/java/net/SocksSocketImpl.java
@@ -118,7 +118,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
private int readSocksReply(InputStream in, byte[] data, long deadlineMillis) throws IOException {
int len = data.length;
int received = 0;
- for (int attempts = 0; received < len && attempts < 3; attempts++) {
+ while (received < len) {
int count;
try {
count = ((SocketInputStream)in).read(data, received, len - received, remainingMillis(deadlineMillis));
@@ -520,7 +520,11 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case DOMAIN_NAME:
- len = data[1];
+ byte[] lenByte = new byte[1];
+ i = readSocksReply(in, lenByte, deadlineMillis);
+ if (i != 1)
+ throw new SocketException("Reply from SOCKS server badly formatted");
+ len = lenByte[0] & 0xFF;
byte[] host = new byte[len];
i = readSocksReply(in, host, deadlineMillis);
if (i != len)
@@ -531,7 +535,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts {
throw new SocketException("Reply from SOCKS server badly formatted");
break;
case IPV6:
- len = data[1];
+ len = 16;
addr = new byte[len];
i = readSocksReply(in, addr, deadlineMillis);
if (i != len)
diff --git a/src/share/classes/java/net/URL.java b/src/share/classes/java/net/URL.java
index 919825adbb..bbe87b6272 100644
--- a/src/share/classes/java/net/URL.java
+++ b/src/share/classes/java/net/URL.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@ import java.io.ObjectStreamField;
import java.io.ObjectInputStream.GetField;
import java.util.Hashtable;
import java.util.StringTokenizer;
+import sun.net.util.IPAddressUtil;
import sun.security.util.SecurityConstants;
/**
@@ -414,13 +415,29 @@ public final class URL implements java.io.Serializable {
}
ref = parts.getRef();
- // Note: we don't do validation of the URL here. Too risky to change
+ // Note: we don't do full validation of the URL here. Too risky to change
// right now, but worth considering for future reference. -br
if (handler == null &&
(handler = getURLStreamHandler(protocol)) == null) {
throw new MalformedURLException("unknown protocol: " + protocol);
}
this.handler = handler;
+ if (host != null && isBuiltinStreamHandler(handler)) {
+ String s = IPAddressUtil.checkExternalForm(this);
+ if (s != null) {
+ throw new MalformedURLException(s);
+ }
+ }
+ if ("jar".equalsIgnoreCase(protocol)) {
+ if (handler instanceof sun.net.www.protocol.jar.Handler) {
+ // URL.openConnection() would throw a confusing exception
+ // so generate a better exception here instead.
+ String s = ((sun.net.www.protocol.jar.Handler) handler).checkNestedProtocol(file);
+ if (s != null) {
+ throw new MalformedURLException(s);
+ }
+ }
+ }
}
/**
@@ -943,7 +960,12 @@ public final class URL implements java.io.Serializable {
* @since 1.5
*/
public URI toURI() throws URISyntaxException {
- return new URI (toString());
+ URI uri = new URI(toString());
+ if (authority != null && isBuiltinStreamHandler(handler)) {
+ String s = IPAddressUtil.checkAuthority(this);
+ if (s != null) throw new URISyntaxException(authority, s);
+ }
+ return uri;
}
/**
@@ -1400,6 +1422,10 @@ public final class URL implements java.io.Serializable {
return replacementURL;
}
+ boolean isBuiltinStreamHandler(URLStreamHandler handler) {
+ return isBuiltinStreamHandler(handler.getClass().getName());
+ }
+
private boolean isBuiltinStreamHandler(String handlerClassName) {
return (handlerClassName.startsWith(BUILTIN_HANDLERS_PREFIX));
}
diff --git a/src/share/classes/java/net/URLStreamHandler.java b/src/share/classes/java/net/URLStreamHandler.java
index 513055982c..cbdf02a5ee 100644
--- a/src/share/classes/java/net/URLStreamHandler.java
+++ b/src/share/classes/java/net/URLStreamHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, 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
@@ -532,12 +532,15 @@ public abstract class URLStreamHandler {
* @see java.net.URL#set(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String)
* @since 1.3
*/
- protected void setURL(URL u, String protocol, String host, int port,
+ protected void setURL(URL u, String protocol, String host, int port,
String authority, String userInfo, String path,
String query, String ref) {
if (this != u.handler) {
throw new SecurityException("handler for url different from " +
"this handler");
+ } else if (host != null && u.isBuiltinStreamHandler(this)) {
+ String s = IPAddressUtil.checkHostString(host);
+ if (s != null) throw new IllegalArgumentException(s);
}
// ensure that no one can reset the protocol on a given URL.
u.set(u.getProtocol(), host, port, authority, userInfo, path, query, ref);
diff --git a/src/share/classes/java/security/AccessController.java b/src/share/classes/java/security/AccessController.java
index 36408a8d63..00e084ca96 100644
--- a/src/share/classes/java/security/AccessController.java
+++ b/src/share/classes/java/security/AccessController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -425,7 +425,8 @@ public final class AccessController {
throw new NullPointerException("null permissions parameter");
}
Class <?> caller = Reflection.getCallerClass();
- return AccessController.doPrivileged(action, createWrapper(null,
+ DomainCombiner dc = (context == null) ? null : context.getCombiner();
+ return AccessController.doPrivileged(action, createWrapper(dc,
caller, parent, context, perms));
}
@@ -710,7 +711,8 @@ public final class AccessController {
throw new NullPointerException("null permissions parameter");
}
Class <?> caller = Reflection.getCallerClass();
- return AccessController.doPrivileged(action, createWrapper(null, caller, parent, context, perms));
+ DomainCombiner dc = (context == null) ? null : context.getCombiner();
+ return AccessController.doPrivileged(action, createWrapper(dc, caller, parent, context, perms));
}
diff --git a/src/share/classes/java/util/Collections.java b/src/share/classes/java/util/Collections.java
index 4dbdf8a5b4..3ab4c5ec06 100644
--- a/src/share/classes/java/util/Collections.java
+++ b/src/share/classes/java/util/Collections.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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,6 +25,7 @@
package java.util;
import java.io.Serializable;
+import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
@@ -37,6 +38,7 @@ import java.util.function.UnaryOperator;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import sun.misc.SharedSecrets;
/**
* This class consists exclusively of static methods that operate on or return
@@ -457,7 +459,7 @@ public class Collections {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
- Object arr[] = list.toArray();
+ Object[] arr = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
@@ -5060,6 +5062,53 @@ public class Collections {
return new CopiesList<>(toIndex - fromIndex, element);
}
+ @Override
+ public int hashCode() {
+ if (n == 0) return 1;
+ // hashCode of n repeating elements is 31^n + elementHash * Sum(31^k, k = 0..n-1)
+ // this implementation completes in O(log(n)) steps taking advantage of
+ // 31^(2*n) = (31^n)^2 and Sum(31^k, k = 0..(2*n-1)) = Sum(31^k, k = 0..n-1) * (31^n + 1)
+ int pow = 31;
+ int sum = 1;
+ for (int i = Integer.numberOfLeadingZeros(n) + 1; i < Integer.SIZE; i++) {
+ sum *= pow + 1;
+ pow *= pow;
+ if ((n << i) < 0) {
+ pow *= 31;
+ sum = sum * 31 + 1;
+ }
+ }
+ return pow + sum * (element == null ? 0 : element.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (o instanceof CopiesList) {
+ CopiesList<?> other = (CopiesList<?>) o;
+ return n == other.n && (n == 0 || eq(element, other.element));
+ }
+ if (!(o instanceof List))
+ return false;
+
+ int remaining = n;
+ E e = element;
+ Iterator<?> itr = ((List<?>) o).iterator();
+ if (e == null) {
+ while (itr.hasNext() && remaining-- > 0) {
+ if (itr.next() != null)
+ return false;
+ }
+ } else {
+ while (itr.hasNext() && remaining-- > 0) {
+ if (!e.equals(itr.next()))
+ return false;
+ }
+ }
+ return remaining == 0 && !itr.hasNext();
+ }
+
// Override default methods in Collection
@Override
public Stream<E> stream() {
@@ -5075,6 +5124,11 @@ public class Collections {
public Spliterator<E> spliterator() {
return stream().spliterator();
}
+
+ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+ ois.defaultReadObject();
+ SharedSecrets.getJavaOISAccess().checkArray(ois, Object[].class, n);
+ }
}
/**
diff --git a/src/share/classes/java/util/CurrencyData.properties b/src/share/classes/java/util/CurrencyData.properties
index df077cd602..75e19efbd8 100644
--- a/src/share/classes/java/util/CurrencyData.properties
+++ b/src/share/classes/java/util/CurrencyData.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@ formatVersion=2
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
-dataVersion=162
+dataVersion=169
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -46,14 +46,14 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036
HRK191-HTG332-HUF348-IDR360-IEP372-ILS376-INR356-IQD368-IRR364-ISK352-\
ITL380-JMD388-JOD400-JPY392-KES404-KGS417-KHR116-KMF174-KPW408-KRW410-\
KWD414-KYD136-KZT398-LAK418-LBP422-LKR144-LRD430-LSL426-LTL440-LUF442-\
- LVL428-LYD434-MAD504-MDL498-MGA969-MGF450-MKD807-MMK104-MNT496-MOP446-MRO478-\
+ LVL428-LYD434-MAD504-MDL498-MGA969-MGF450-MKD807-MMK104-MNT496-MOP446-MRO478-MRU929-\
MTL470-MUR480-MVR462-MWK454-MXN484-MXV979-MYR458-MZM508-MZN943-NAD516-NGN566-\
NIO558-NLG528-NOK578-NPR524-NZD554-OMR512-PAB590-PEN604-PGK598-PHP608-\
PKR586-PLN985-PTE620-PYG600-QAR634-ROL946-RON946-RSD941-RUB643-RUR810-RWF646-SAR682-\
SBD090-SCR690-SDD736-SDG938-SEK752-SGD702-SHP654-SIT705-SKK703-SLL694-SOS706-\
- SRD968-SRG740-SSP728-STD678-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\
+ SRD968-SRG740-SSP728-STD678-STN930-SVC222-SYP760-SZL748-THB764-TJS972-TMM795-TMT934-TND788-TOP776-\
TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\
- UYU858-UZS860-VEB862-VEF937-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
+ UYU858-UZS860-VEB862-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\
XBB956-XBC957-XBD958-XCD951-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\
XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWL932-\
ZWN942-ZWR935
@@ -195,7 +195,7 @@ CU=CUP
CW=ANG
# CYPRUS
CY=EUR
-# CZECH REPUBLIC (THE)
+# CZECHIA
CZ=CZK
# DENMARK
DK=DKK
@@ -323,7 +323,7 @@ KG=KGS
# LAO PEOPLE'S DEMOCRATIC REPUBLIC (THE)
LA=LAK
# LATVIA
-LV=LVL;2013-12-31-22-00-00;EUR
+LV=EUR
# LEBANON
LB=LBP
# LESOTHO
@@ -335,7 +335,7 @@ LY=LYD
# LIECHTENSTEIN
LI=CHF
# LITHUANIA
-LT=LTL;2014-12-31-22-00-00;EUR
+LT=EUR
# LUXEMBOURG
LU=EUR
# MACAU
@@ -359,7 +359,7 @@ MH=USD
# MARTINIQUE
MQ=EUR
# MAURITANIA
-MR=MRO
+MR=MRU
# MAURITIUS
MU=MUR
# MAYOTTE
@@ -469,7 +469,7 @@ SM=EUR
# SOUTH SUDAN
SS=SSP
# SAO TOME AND PRINCIPE
-ST=STD
+ST=STN
# SAUDI ARABIA
SA=SAR
# SENEGAL
@@ -508,7 +508,7 @@ SR=SRD
SJ=NOK
# Sint Maarten (Dutch part)
SX=ANG
-# SWAZILAND
+# ESWATINI
SZ=SZL
# SWEDEN
SE=SEK
@@ -563,7 +563,7 @@ UZ=UZS
# VANUATU
VU=VUV
# VENEZUELA (BOLIVARIAN REPUBLIC OF)
-VE=VEF
+VE=VES
# VIET NAM
VN=VND
# VIRGIN ISLANDS, BRITISH
diff --git a/src/share/classes/java/util/concurrent/CompletableFuture.java b/src/share/classes/java/util/concurrent/CompletableFuture.java
index 955daabedc..d645bb4c39 100644
--- a/src/share/classes/java/util/concurrent/CompletableFuture.java
+++ b/src/share/classes/java/util/concurrent/CompletableFuture.java
@@ -421,6 +421,20 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
static final int ASYNC = 1;
static final int NESTED = -1;
+ /**
+ * Spins before blocking in waitingGet.
+ * There is no need to spin on uniprocessors.
+ *
+ * Call to Runtime.availableProcessors is expensive, cache the value here.
+ * This unfortunately relies on the number of available CPUs during first
+ * initialization. This affects the case when MP system would report only
+ * one CPU available at startup, initialize SPINS to 0, and then make more
+ * CPUs online. This would incur some performance penalty due to less spins
+ * than would otherwise happen.
+ */
+ private static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
+ 1 << 8 : 0);
+
/* ------------- Base Completion classes and operations -------------- */
@SuppressWarnings("serial")
@@ -1709,8 +1723,7 @@ public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
Object r;
while ((r = result) == null) {
if (spins < 0)
- spins = (Runtime.getRuntime().availableProcessors() > 1) ?
- 1 << 8 : 0; // Use brief spin-wait on multiprocessors
+ spins = SPINS;
else if (spins > 0) {
if (ThreadLocalRandom.nextSecondarySeed() >= 0)
--spins;
diff --git a/src/share/classes/java/util/regex/Pattern.java b/src/share/classes/java/util/regex/Pattern.java
index 009a46e6f6..7434390122 100644
--- a/src/share/classes/java/util/regex/Pattern.java
+++ b/src/share/classes/java/util/regex/Pattern.java
@@ -1348,7 +1348,11 @@ public final class Pattern
localCount = 0;
if (pattern.length() > 0) {
- compile();
+ try {
+ compile();
+ } catch (StackOverflowError soe) {
+ throw error("Stack overflow during pattern compilation");
+ }
} else {
root = new Start(lastAccept);
matchRoot = lastAccept;
@@ -1905,6 +1909,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
int ch = temp[cursor++];
while (ch != 0 && !isLineSeparator(ch))
ch = temp[cursor++];
+ if (ch == 0 && cursor > patternLength) {
+ cursor = patternLength;
+ ch = temp[cursor++];
+ }
return ch;
}
@@ -1915,6 +1923,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
int ch = temp[++cursor];
while (ch != 0 && !isLineSeparator(ch))
ch = temp[++cursor];
+ if (ch == 0 && cursor > patternLength) {
+ cursor = patternLength;
+ ch = temp[cursor];
+ }
return ch;
}
diff --git a/src/share/classes/java/util/stream/AbstractTask.java b/src/share/classes/java/util/stream/AbstractTask.java
index 33de7d5c52..8c5be49aff 100644
--- a/src/share/classes/java/util/stream/AbstractTask.java
+++ b/src/share/classes/java/util/stream/AbstractTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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,6 +27,7 @@ package java.util.stream;
import java.util.Spliterator;
import java.util.concurrent.CountedCompleter;
import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinWorkerThread;
/**
* Abstract base class for most fork-join tasks used to implement stream ops.
@@ -88,13 +89,7 @@ abstract class AbstractTask<P_IN, P_OUT, R,
K extends AbstractTask<P_IN, P_OUT, R, K>>
extends CountedCompleter<R> {
- /**
- * Default target factor of leaf tasks for parallel decomposition.
- * To allow load balancing, we over-partition, currently to approximately
- * four tasks per processor, which enables others to help out
- * if leaf tasks are uneven or some processors are otherwise busy.
- */
- static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
+ private static final int LEAF_TARGET = ForkJoinPool.getCommonPoolParallelism() << 2;
/** The pipeline helper, common to all tasks in a computation */
protected final PipelineHelper<P_OUT> helper;
@@ -157,6 +152,22 @@ abstract class AbstractTask<P_IN, P_OUT, R,
}
/**
+ * Default target of leaf tasks for parallel decomposition.
+ * To allow load balancing, we over-partition, currently to approximately
+ * four tasks per processor, which enables others to help out
+ * if leaf tasks are uneven or some processors are otherwise busy.
+ */
+ public static int getLeafTarget() {
+ Thread t = Thread.currentThread();
+ if (t instanceof ForkJoinWorkerThread) {
+ return ((ForkJoinWorkerThread) t).getPool().getParallelism() << 2;
+ }
+ else {
+ return LEAF_TARGET;
+ }
+ }
+
+ /**
* Constructs a new node of type T whose parent is the receiver; must call
* the AbstractTask(T, Spliterator) constructor with the receiver and the
* provided Spliterator.
@@ -181,7 +192,7 @@ abstract class AbstractTask<P_IN, P_OUT, R,
* @return suggested target leaf size
*/
public static long suggestTargetSize(long sizeEstimate) {
- long est = sizeEstimate / LEAF_TARGET;
+ long est = sizeEstimate / getLeafTarget();
return est > 0L ? est : 1L;
}
diff --git a/src/share/classes/java/util/stream/DoublePipeline.java b/src/share/classes/java/util/stream/DoublePipeline.java
index 3e9cddbd32..ce626640d0 100644
--- a/src/share/classes/java/util/stream/DoublePipeline.java
+++ b/src/share/classes/java/util/stream/DoublePipeline.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -260,6 +260,12 @@ abstract class DoublePipeline<E_IN>
@Override
Sink<Double> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedDouble<Double>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
+ DoubleConsumer downstreamAsDouble = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -268,11 +274,27 @@ abstract class DoublePipeline<E_IN>
@Override
public void accept(double t) {
try (DoubleStream result = mapper.apply(t)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(i -> downstream.accept(i));
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsDouble);
+ }
+ else {
+ Spliterator.OfDouble s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsDouble));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ // If this method is called then an operation within the stream
+ // pipeline is short-circuiting (see AbstractPipeline.copyInto).
+ // Note that we cannot differentiate between an upstream or
+ // downstream operation
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
diff --git a/src/share/classes/java/util/stream/ForEachOps.java b/src/share/classes/java/util/stream/ForEachOps.java
index b527f054f4..38d63e929d 100644
--- a/src/share/classes/java/util/stream/ForEachOps.java
+++ b/src/share/classes/java/util/stream/ForEachOps.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -28,7 +28,6 @@ import java.util.Objects;
import java.util.Spliterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountedCompleter;
-import java.util.concurrent.ForkJoinTask;
import java.util.function.Consumer;
import java.util.function.DoubleConsumer;
import java.util.function.IntConsumer;
@@ -378,7 +377,7 @@ final class ForEachOps {
this.spliterator = spliterator;
this.targetSize = AbstractTask.suggestTargetSize(spliterator.estimateSize());
// Size map to avoid concurrent re-sizes
- this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.LEAF_TARGET << 1));
+ this.completionMap = new ConcurrentHashMap<>(Math.max(16, AbstractTask.getLeafTarget() << 1));
this.action = action;
this.leftPredecessor = null;
}
diff --git a/src/share/classes/java/util/stream/IntPipeline.java b/src/share/classes/java/util/stream/IntPipeline.java
index 313045f96c..3f809ea4cc 100644
--- a/src/share/classes/java/util/stream/IntPipeline.java
+++ b/src/share/classes/java/util/stream/IntPipeline.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -296,6 +296,12 @@ abstract class IntPipeline<E_IN>
@Override
Sink<Integer> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedInt<Integer>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
+ IntConsumer downstreamAsInt = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -304,11 +310,27 @@ abstract class IntPipeline<E_IN>
@Override
public void accept(int t) {
try (IntStream result = mapper.apply(t)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(i -> downstream.accept(i));
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsInt);
+ }
+ else {
+ Spliterator.OfInt s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsInt));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ // If this method is called then an operation within the stream
+ // pipeline is short-circuiting (see AbstractPipeline.copyInto).
+ // Note that we cannot differentiate between an upstream or
+ // downstream operation
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
diff --git a/src/share/classes/java/util/stream/LongPipeline.java b/src/share/classes/java/util/stream/LongPipeline.java
index fab01a2111..02318175af 100644
--- a/src/share/classes/java/util/stream/LongPipeline.java
+++ b/src/share/classes/java/util/stream/LongPipeline.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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
@@ -277,6 +277,12 @@ abstract class LongPipeline<E_IN>
@Override
Sink<Long> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedLong<Long>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
+ LongConsumer downstreamAsLong = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -285,11 +291,27 @@ abstract class LongPipeline<E_IN>
@Override
public void accept(long t) {
try (LongStream result = mapper.apply(t)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(i -> downstream.accept(i));
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsLong);
+ }
+ else {
+ Spliterator.OfLong s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsLong));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ // If this method is called then an operation within the stream
+ // pipeline is short-circuiting (see AbstractPipeline.copyInto).
+ // Note that we cannot differentiate between an upstream or
+ // downstream operation
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
diff --git a/src/share/classes/java/util/stream/ReferencePipeline.java b/src/share/classes/java/util/stream/ReferencePipeline.java
index 8f5da0e55e..abb435466b 100644
--- a/src/share/classes/java/util/stream/ReferencePipeline.java
+++ b/src/share/classes/java/util/stream/ReferencePipeline.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -251,12 +251,14 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public final <R> Stream<R> flatMap(Function<? super P_OUT, ? extends Stream<? extends R>> mapper) {
Objects.requireNonNull(mapper);
- // We can do better than this, by polling cancellationRequested when stream is infinite
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
return new Sink.ChainedReference<P_OUT, R>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -265,11 +267,27 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public void accept(P_OUT u) {
try (Stream<? extends R> result = mapper.apply(u)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(downstream);
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstream);
+ }
+ else {
+ Spliterator<? extends R> s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstream));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ // If this method is called then an operation within the stream
+ // pipeline is short-circuiting (see AbstractPipeline.copyInto).
+ // Note that we cannot differentiate between an upstream or
+ // downstream operation
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
@@ -278,13 +296,17 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public final IntStream flatMapToInt(Function<? super P_OUT, ? extends IntStream> mapper) {
Objects.requireNonNull(mapper);
- // We can do better than this, by polling cancellationRequested when stream is infinite
return new IntPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Integer> sink) {
return new Sink.ChainedReference<P_OUT, Integer>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
IntConsumer downstreamAsInt = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -293,11 +315,23 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public void accept(P_OUT u) {
try (IntStream result = mapper.apply(u)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(downstreamAsInt);
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsInt);
+ }
+ else {
+ Spliterator.OfInt s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsInt));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
@@ -306,13 +340,17 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public final DoubleStream flatMapToDouble(Function<? super P_OUT, ? extends DoubleStream> mapper) {
Objects.requireNonNull(mapper);
- // We can do better than this, by polling cancellationRequested when stream is infinite
return new DoublePipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT | StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Double> sink) {
return new Sink.ChainedReference<P_OUT, Double>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
DoubleConsumer downstreamAsDouble = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -321,11 +359,23 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public void accept(P_OUT u) {
try (DoubleStream result = mapper.apply(u)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(downstreamAsDouble);
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsDouble);
+ }
+ else {
+ Spliterator.OfDouble s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsDouble));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
@@ -340,7 +390,12 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedReference<P_OUT, Long>(sink) {
+ // true if cancellationRequested() has been called
+ boolean cancellationRequestedCalled;
+
+ // cache the consumer to avoid creation on every accepted element
LongConsumer downstreamAsLong = downstream::accept;
+
@Override
public void begin(long size) {
downstream.begin(-1);
@@ -349,11 +404,23 @@ abstract class ReferencePipeline<P_IN, P_OUT>
@Override
public void accept(P_OUT u) {
try (LongStream result = mapper.apply(u)) {
- // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
- if (result != null)
- result.sequential().forEach(downstreamAsLong);
+ if (result != null) {
+ if (!cancellationRequestedCalled) {
+ result.sequential().forEach(downstreamAsLong);
+ }
+ else {
+ Spliterator.OfLong s = result.sequential().spliterator();
+ do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstreamAsLong));
+ }
+ }
}
}
+
+ @Override
+ public boolean cancellationRequested() {
+ cancellationRequestedCalled = true;
+ return downstream.cancellationRequested();
+ }
};
}
};
diff --git a/src/share/classes/java/util/stream/SortedOps.java b/src/share/classes/java/util/stream/SortedOps.java
index 592b609cad..31e806dd56 100644
--- a/src/share/classes/java/util/stream/SortedOps.java
+++ b/src/share/classes/java/util/stream/SortedOps.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -304,7 +304,8 @@ final class SortedOps {
private static abstract class AbstractRefSortingSink<T> extends Sink.ChainedReference<T, T> {
protected final Comparator<? super T> comparator;
// @@@ could be a lazy final value, if/when support is added
- protected boolean cancellationWasRequested;
+ // true if cancellationRequested() has been called
+ protected boolean cancellationRequestedCalled;
AbstractRefSortingSink(Sink<? super T> downstream, Comparator<? super T> comparator) {
super(downstream);
@@ -319,7 +320,11 @@ final class SortedOps {
*/
@Override
public final boolean cancellationRequested() {
- cancellationWasRequested = true;
+ // If this method is called then an operation within the stream
+ // pipeline is short-circuiting (see AbstractPipeline.copyInto).
+ // Note that we cannot differentiate between an upstream or
+ // downstream operation
+ cancellationRequestedCalled = true;
return false;
}
}
@@ -347,7 +352,7 @@ final class SortedOps {
public void end() {
Arrays.sort(array, 0, offset, comparator);
downstream.begin(offset);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (int i = 0; i < offset; i++)
downstream.accept(array[i]);
}
@@ -386,7 +391,7 @@ final class SortedOps {
public void end() {
list.sort(comparator);
downstream.begin(list.size());
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
list.forEach(downstream::accept);
}
else {
@@ -409,7 +414,8 @@ final class SortedOps {
* Abstract {@link Sink} for implementing sort on int streams.
*/
private static abstract class AbstractIntSortingSink extends Sink.ChainedInt<Integer> {
- protected boolean cancellationWasRequested;
+ // true if cancellationRequested() has been called
+ protected boolean cancellationRequestedCalled;
AbstractIntSortingSink(Sink<? super Integer> downstream) {
super(downstream);
@@ -417,7 +423,7 @@ final class SortedOps {
@Override
public final boolean cancellationRequested() {
- cancellationWasRequested = true;
+ cancellationRequestedCalled = true;
return false;
}
}
@@ -444,7 +450,7 @@ final class SortedOps {
public void end() {
Arrays.sort(array, 0, offset);
downstream.begin(offset);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (int i = 0; i < offset; i++)
downstream.accept(array[i]);
}
@@ -484,7 +490,7 @@ final class SortedOps {
int[] ints = b.asPrimitiveArray();
Arrays.sort(ints);
downstream.begin(ints.length);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (int anInt : ints)
downstream.accept(anInt);
}
@@ -507,7 +513,8 @@ final class SortedOps {
* Abstract {@link Sink} for implementing sort on long streams.
*/
private static abstract class AbstractLongSortingSink extends Sink.ChainedLong<Long> {
- protected boolean cancellationWasRequested;
+ // true if cancellationRequested() has been called
+ protected boolean cancellationRequestedCalled;
AbstractLongSortingSink(Sink<? super Long> downstream) {
super(downstream);
@@ -515,7 +522,7 @@ final class SortedOps {
@Override
public final boolean cancellationRequested() {
- cancellationWasRequested = true;
+ cancellationRequestedCalled = true;
return false;
}
}
@@ -542,7 +549,7 @@ final class SortedOps {
public void end() {
Arrays.sort(array, 0, offset);
downstream.begin(offset);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (int i = 0; i < offset; i++)
downstream.accept(array[i]);
}
@@ -582,7 +589,7 @@ final class SortedOps {
long[] longs = b.asPrimitiveArray();
Arrays.sort(longs);
downstream.begin(longs.length);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (long aLong : longs)
downstream.accept(aLong);
}
@@ -605,7 +612,8 @@ final class SortedOps {
* Abstract {@link Sink} for implementing sort on long streams.
*/
private static abstract class AbstractDoubleSortingSink extends Sink.ChainedDouble<Double> {
- protected boolean cancellationWasRequested;
+ // true if cancellationRequested() has been called
+ protected boolean cancellationRequestedCalled;
AbstractDoubleSortingSink(Sink<? super Double> downstream) {
super(downstream);
@@ -613,7 +621,7 @@ final class SortedOps {
@Override
public final boolean cancellationRequested() {
- cancellationWasRequested = true;
+ cancellationRequestedCalled = true;
return false;
}
}
@@ -640,7 +648,7 @@ final class SortedOps {
public void end() {
Arrays.sort(array, 0, offset);
downstream.begin(offset);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (int i = 0; i < offset; i++)
downstream.accept(array[i]);
}
@@ -680,7 +688,7 @@ final class SortedOps {
double[] doubles = b.asPrimitiveArray();
Arrays.sort(doubles);
downstream.begin(doubles.length);
- if (!cancellationWasRequested) {
+ if (!cancellationRequestedCalled) {
for (double aDouble : doubles)
downstream.accept(aDouble);
}
diff --git a/src/share/classes/java/util/stream/StreamSpliterators.java b/src/share/classes/java/util/stream/StreamSpliterators.java
index 67683425bf..42ad027f70 100644
--- a/src/share/classes/java/util/stream/StreamSpliterators.java
+++ b/src/share/classes/java/util/stream/StreamSpliterators.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -28,6 +28,7 @@ import java.util.Comparator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
@@ -897,7 +898,7 @@ class StreamSpliterators {
* Note: The source spliterator may report {@code ORDERED} since that
* spliterator be the result of a previous pipeline stage that was
* collected to a {@code Node}. It is the order of the pipeline stage
- * that governs whether the this slice spliterator is to be used or not.
+ * that governs whether this slice spliterator is to be used or not.
*/
static abstract class UnorderedSliceSpliterator<T, T_SPLITR extends Spliterator<T>> {
static final int CHUNK_SIZE = 1 << 7;
@@ -905,6 +906,7 @@ class StreamSpliterators {
// The spliterator to slice
protected final T_SPLITR s;
protected final boolean unlimited;
+ protected final int chunkSize;
private final long skipThreshold;
private final AtomicLong permits;
@@ -912,6 +914,8 @@ class StreamSpliterators {
this.s = s;
this.unlimited = limit < 0;
this.skipThreshold = limit >= 0 ? limit : 0;
+ this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE,
+ ((skip + limit) / AbstractTask.getLeafTarget()) + 1) : CHUNK_SIZE;
this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
}
@@ -921,6 +925,7 @@ class StreamSpliterators {
this.unlimited = parent.unlimited;
this.permits = parent.permits;
this.skipThreshold = parent.skipThreshold;
+ this.chunkSize = parent.chunkSize;
}
/**
@@ -1029,13 +1034,13 @@ class StreamSpliterators {
PermitStatus permitStatus;
while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
if (permitStatus == PermitStatus.MAYBE_MORE) {
- // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+ // Optimistically traverse elements up to a threshold of chunkSize
if (sb == null)
- sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE);
+ sb = new ArrayBuffer.OfRef<>(chunkSize);
else
sb.reset();
long permitsRequested = 0;
- do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE);
+ do { } while (s.tryAdvance(sb) && ++permitsRequested < chunkSize);
if (permitsRequested == 0)
return;
sb.forEach(action, acquirePermits(permitsRequested));
@@ -1102,15 +1107,15 @@ class StreamSpliterators {
PermitStatus permitStatus;
while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
if (permitStatus == PermitStatus.MAYBE_MORE) {
- // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+ // Optimistically traverse elements up to a threshold of chunkSize
if (sb == null)
- sb = bufferCreate(CHUNK_SIZE);
+ sb = bufferCreate(chunkSize);
else
sb.reset();
@SuppressWarnings("unchecked")
T_CONS sbc = (T_CONS) sb;
long permitsRequested = 0;
- do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE);
+ do { } while (s.tryAdvance(sbc) && ++permitsRequested < chunkSize);
if (permitsRequested == 0)
return;
sb.forEach(action, acquirePermits(permitsRequested));
diff --git a/src/share/classes/javax/imageio/ImageIO.java b/src/share/classes/javax/imageio/ImageIO.java
index d660ffdc51..13d623f2b7 100644
--- a/src/share/classes/javax/imageio/ImageIO.java
+++ b/src/share/classes/javax/imageio/ImageIO.java
@@ -1291,7 +1291,8 @@ public final class ImageIO {
*
* @exception IllegalArgumentException if <code>input</code> is
* <code>null</code>.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(File input) throws IOException {
if (input == null) {
@@ -1341,7 +1342,8 @@ public final class ImageIO {
*
* @exception IllegalArgumentException if <code>input</code> is
* <code>null</code>.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(InputStream input) throws IOException {
if (input == null) {
@@ -1349,6 +1351,9 @@ public final class ImageIO {
}
ImageInputStream stream = createImageInputStream(input);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageInputStream!");
+ }
BufferedImage bi = read(stream);
if (bi == null) {
stream.close();
@@ -1381,7 +1386,8 @@ public final class ImageIO {
*
* @exception IllegalArgumentException if <code>input</code> is
* <code>null</code>.
- * @exception IOException if an error occurs during reading.
+ * @exception IOException if an error occurs during reading or when not
+ * able to create required ImageInputStream.
*/
public static BufferedImage read(URL input) throws IOException {
if (input == null) {
@@ -1395,6 +1401,14 @@ public final class ImageIO {
throw new IIOException("Can't get input stream from URL!", e);
}
ImageInputStream stream = createImageInputStream(istream);
+ if (stream == null) {
+ /* close the istream when stream is null so that if user has
+ * given filepath as URL he can delete it, otherwise stream will
+ * be open to that file and he will not be able to delete it.
+ */
+ istream.close();
+ throw new IIOException("Can't create an ImageInputStream!");
+ }
BufferedImage bi;
try {
bi = read(stream);
@@ -1507,7 +1521,8 @@ public final class ImageIO {
*
* @exception IllegalArgumentException if any parameter is
* <code>null</code>.
- * @exception IOException if an error occurs during writing.
+ * @exception IOException if an error occurs during writing or when not
+ * able to create required ImageOutputStream.
*/
public static boolean write(RenderedImage im,
String formatName,
@@ -1515,7 +1530,6 @@ public final class ImageIO {
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
- ImageOutputStream stream = null;
ImageWriter writer = getWriter(im, formatName);
if (writer == null) {
@@ -1525,13 +1539,11 @@ public final class ImageIO {
return false;
}
- try {
- output.delete();
- stream = createImageOutputStream(output);
- } catch (IOException e) {
- throw new IIOException("Can't create output stream!", e);
+ output.delete();
+ ImageOutputStream stream = createImageOutputStream(output);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageOutputStream!");
}
-
try {
return doWrite(im, writer, stream);
} finally {
@@ -1559,7 +1571,8 @@ public final class ImageIO {
*
* @exception IllegalArgumentException if any parameter is
* <code>null</code>.
- * @exception IOException if an error occurs during writing.
+ * @exception IOException if an error occurs during writing or when not
+ * able to create required ImageOutputStream.
*/
public static boolean write(RenderedImage im,
String formatName,
@@ -1567,13 +1580,10 @@ public final class ImageIO {
if (output == null) {
throw new IllegalArgumentException("output == null!");
}
- ImageOutputStream stream = null;
- try {
- stream = createImageOutputStream(output);
- } catch (IOException e) {
- throw new IIOException("Can't create output stream!", e);
+ ImageOutputStream stream = createImageOutputStream(output);
+ if (stream == null) {
+ throw new IIOException("Can't create an ImageOutputStream!");
}
-
try {
return doWrite(im, getWriter(im, formatName), stream);
} finally {
diff --git a/src/share/classes/javax/net/ssl/SSLSessionContext.java b/src/share/classes/javax/net/ssl/SSLSessionContext.java
index b6f6fb6df4..6361f6bc56 100644
--- a/src/share/classes/javax/net/ssl/SSLSessionContext.java
+++ b/src/share/classes/javax/net/ssl/SSLSessionContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -87,10 +87,17 @@ public interface SSLSessionContext {
* A check for sessions exceeding the timeout is made immediately whenever
* the timeout limit is changed for this <code>SSLSessionContext</code>.
*
+ * @apiNote Note that the JDK Implementation uses default values for both
+ * the session cache size and timeout. See
+ * {@code getSessionCacheSize} and {@code getSessionTimeout} for
+ * more information. Applications should consider their
+ * performance requirements and override the defaults if necessary.
+ *
* @param seconds the new session timeout limit in seconds; zero means
- * there is no limit.
+ * there is no limit.
+ *
+ * @throws IllegalArgumentException if the timeout specified is {@code < 0}.
*
- * @exception IllegalArgumentException if the timeout specified is {@code < 0}.
* @see #getSessionTimeout
*/
public void setSessionTimeout(int seconds)
@@ -109,33 +116,50 @@ public interface SSLSessionContext {
* whenever the timeout limit is changed for this
* <code>SSLSessionContext</code>.
*
+ * @implNote The JDK implementation returns the session timeout as set by
+ * the {@code setSessionTimeout} method, or if not set, a default
+ * value of 86400 seconds (24 hours).
+ *
* @return the session timeout limit in seconds; zero means there is no
- * limit.
+ * limit.
+ *
* @see #setSessionTimeout
*/
public int getSessionTimeout();
/**
- * Sets the size of the cache used for storing
- * <code>SSLSession</code> objects grouped under this
- * <code>SSLSessionContext</code>.
+ * Sets the size of the cache used for storing <code>SSLSession</code>
+ * objects grouped under this <code>SSLSessionContext</code>.
+ *
+ * @apiNote Note that the JDK Implementation uses default values for both
+ * the session cache size and timeout. See
+ * {@code getSessionCacheSize} and {@code getSessionTimeout} for
+ * more information. Applications should consider their
+ * performance requirements and override the defaults if necessary.
*
* @param size the new session cache size limit; zero means there is no
- * limit.
- * @exception IllegalArgumentException if the specified size is {@code < 0}.
+ * limit.
+ *
+ * @throws IllegalArgumentException if the specified size is {@code < 0}.
+ *
* @see #getSessionCacheSize
*/
public void setSessionCacheSize(int size)
throws IllegalArgumentException;
/**
- * Returns the size of the cache used for storing
- * <code>SSLSession</code> objects grouped under this
- * <code>SSLSessionContext</code>.
+ * Returns the size of the cache used for storing <code>SSLSession</code>
+ * objects grouped under this <code>SSLSessionContext</code>.
+ *
+ * @implNote The JDK implementation returns the cache size as set by
+ * the {@code setSessionCacheSize} method, or if not set, the
+ * value of the {@systemProperty javax.net.ssl.sessionCacheSize}
+ * system property. If neither is set, it returns a default
+ * value of 20480.
*
* @return size of the session cache; zero means there is no size limit.
+ *
* @see #setSessionCacheSize
*/
public int getSessionCacheSize();
-
}
diff --git a/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java b/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java
index 9630c72eac..71cc0aa50e 100644
--- a/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java
+++ b/src/share/classes/javax/security/auth/kerberos/JavaxSecurityAuthKerberosAccessImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -26,8 +26,6 @@
package javax.security.auth.kerberos;
import sun.security.krb5.JavaxSecurityAuthKerberosAccess;
-import sun.security.krb5.EncryptionKey;
-import sun.security.krb5.PrincipalName;
class JavaxSecurityAuthKerberosAccessImpl
implements JavaxSecurityAuthKerberosAccess {
@@ -35,4 +33,10 @@ class JavaxSecurityAuthKerberosAccessImpl
KeyTab ktab) {
return ktab.takeSnapshot();
}
+ public KerberosTicket kerberosTicketGetProxy(KerberosTicket t) {
+ return t.proxy;
+ }
+ public void kerberosTicketSetProxy(KerberosTicket t, KerberosTicket p) {
+ t.proxy = p;
+ }
}
diff --git a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
index 21fd23324c..0327f04db5 100644
--- a/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
+++ b/src/share/classes/javax/security/auth/kerberos/KerberosTicket.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,11 +29,13 @@ import java.io.*;
import java.util.Date;
import java.util.Arrays;
import java.net.InetAddress;
+import java.util.Objects;
import javax.crypto.SecretKey;
import javax.security.auth.Refreshable;
import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
+
import sun.misc.HexDumpEncoder;
import sun.security.krb5.EncryptionKey;
import sun.security.krb5.Asn1Exception;
@@ -190,9 +192,14 @@ public class KerberosTicket implements Destroyable, Refreshable,
* @serial
*/
-
private InetAddress[] clientAddresses;
+ /**
+ * Evidence ticket if proxy_impersonator. This field can be accessed
+ * by KerberosSecrets. It's serialized.
+ */
+ KerberosTicket proxy = null;
+
private transient boolean destroyed = false;
/**
@@ -662,6 +669,7 @@ public class KerberosTicket implements Destroyable, Refreshable,
"Renew Till = " + String.valueOf(renewTill) + "\n" +
"Client Addresses " +
(clientAddresses == null ? " Null " : caddrBuf.toString() +
+ (proxy == null ? "" : "\nwith a proxy ticket") +
"\n"));
}
@@ -699,6 +707,10 @@ public class KerberosTicket implements Destroyable, Refreshable,
// clientAddress may be null, the array's hashCode is 0
result = result * 37 + Arrays.hashCode(clientAddresses);
+
+ if (proxy != null) {
+ result = result * 37 + proxy.hashCode();
+ }
return result * 37 + Arrays.hashCode(flags);
}
@@ -764,6 +776,10 @@ public class KerberosTicket implements Destroyable, Refreshable,
return false;
}
+ if (!Objects.equals(proxy, otherTicket.proxy)) {
+ return false;
+ }
+
return true;
}
diff --git a/src/share/classes/javax/swing/text/html/ImageView.java b/src/share/classes/javax/swing/text/html/ImageView.java
index 70fc1fb43c..427bbf181c 100644
--- a/src/share/classes/javax/swing/text/html/ImageView.java
+++ b/src/share/classes/javax/swing/text/html/ImageView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -28,6 +28,7 @@ import java.awt.Rectangle;
import java.awt.Image;
import java.awt.Container;
import java.awt.Color;
+import java.awt.Dimension;
import java.awt.Shape;
import java.awt.Graphics;
import java.awt.Toolkit;
@@ -764,6 +765,20 @@ public class ImageView extends View {
newState |= HEIGHT_FLAG;
}
+ /*
+ If synchronous loading flag is set, then make sure that the image is
+ scaled appropriately.
+ Otherwise, the ImageHandler::imageUpdate takes care of scaling the image
+ appropriately.
+ */
+ if (getLoadsSynchronously()) {
+ Dimension d = adjustWidthHeight(image.getWidth(imageObserver),
+ image.getHeight(imageObserver));
+ newWidth = d.width;
+ newHeight = d.height;
+ newState |= (WIDTH_FLAG | HEIGHT_FLAG);
+ }
+
// Make sure the image starts loading:
if ((newState & (WIDTH_FLAG | HEIGHT_FLAG)) != 0) {
Toolkit.getDefaultToolkit().prepareImage(newImage, newWidth,
@@ -867,6 +882,40 @@ public class ImageView extends View {
}
}
+ private Dimension adjustWidthHeight(int newWidth, int newHeight) {
+ Dimension d = new Dimension();
+ double proportion = 0.0;
+ final int specifiedWidth = getIntAttr(HTML.Attribute.WIDTH, -1);
+ final int specifiedHeight = getIntAttr(HTML.Attribute.HEIGHT, -1);
+ /**
+ * If either of the attributes are not specified, then calculate the
+ * proportion for the specified dimension wrt actual value, and then
+ * apply the same proportion to the unspecified dimension as well,
+ * so that the aspect ratio of the image is maintained.
+ */
+ if (specifiedWidth != -1 && specifiedHeight != -1) {
+ newWidth = specifiedWidth;
+ newHeight = specifiedHeight;
+ } else if (specifiedWidth != -1 ^ specifiedHeight != -1) {
+ if (specifiedWidth <= 0) {
+ proportion = specifiedHeight / ((double)newHeight);
+ newWidth = (int)(proportion * newWidth);
+ newHeight = specifiedHeight;
+ }
+
+ if (specifiedHeight <= 0) {
+ proportion = specifiedWidth / ((double)newWidth);
+ newHeight = (int)(proportion * newHeight);
+ newWidth = specifiedWidth;
+ }
+ }
+
+ d.width = newWidth;
+ d.height = newHeight;
+
+ return d;
+ }
+
/**
* ImageHandler implements the ImageObserver to correctly update the
* display as new parts of the image become available.
@@ -931,28 +980,11 @@ public class ImageView extends View {
* specified HTML attributes.
*/
if (((flags & ImageObserver.HEIGHT) != 0) &&
- ((flags & ImageObserver.WIDTH) != 0)) {
- double proportion = 0.0;
- final int specifiedWidth = getIntAttr(HTML.Attribute.WIDTH, -1);
- final int specifiedHeight = getIntAttr(HTML.Attribute.HEIGHT, -1);
- /**
- * If either of the attributes are not specified, then calculate the
- * proportion for the specified dimension wrt actual value, and then
- * apply the same proportion to the unspecified dimension as well,
- * so that the aspect ratio of the image is maintained.
- */
- if (specifiedWidth != -1 ^ specifiedHeight != -1) {
- if (specifiedWidth <= 0) {
- proportion = specifiedHeight / ((double)newHeight);
- newWidth = (int)(proportion * newWidth);
- }
-
- if (specifiedHeight <= 0) {
- proportion = specifiedWidth / ((double)newWidth);
- newHeight = (int)(proportion * newHeight);
- }
+ ((flags & ImageObserver.WIDTH) != 0)) {
+ Dimension d = adjustWidthHeight(newWidth, newHeight);
+ newWidth = d.width;
+ newHeight = d.height;
changed |= 3;
- }
}
synchronized(ImageView.this) {
if ((changed & 1) == 1 && (state & HEIGHT_FLAG) == 0) {
diff --git a/src/share/classes/sun/font/CMap.java b/src/share/classes/sun/font/CMap.java
index 410280cf14..25108b8bf1 100644
--- a/src/share/classes/sun/font/CMap.java
+++ b/src/share/classes/sun/font/CMap.java
@@ -130,7 +130,7 @@ abstract class CMap {
static final char noSuchChar = (char)0xfffd;
static final int SHORTMASK = 0x0000ffff;
- static final int INTMASK = 0xffffffff;
+ static final int INTMASK = 0x7fffffff;
static final char[][] converterMaps = new char[7][];
@@ -885,7 +885,11 @@ abstract class CMap {
bbuffer.position(12);
bbuffer.get(is32);
- nGroups = bbuffer.getInt();
+ nGroups = bbuffer.getInt() & INTMASK;
+ // A map group record is three uint32's making for 12 bytes total
+ if (bbuffer.remaining() < (12 * (long)nGroups)) {
+ throw new RuntimeException("Format 8 table exceeded");
+ }
startCharCode = new int[nGroups];
endCharCode = new int[nGroups];
startGlyphID = new int[nGroups];
@@ -913,9 +917,13 @@ abstract class CMap {
CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) {
+ bbuffer.position(offset+12);
firstCode = bbuffer.getInt() & INTMASK;
entryCount = bbuffer.getInt() & INTMASK;
- bbuffer.position(offset+20);
+ // each glyph is a uint16, so 2 bytes per value.
+ if (bbuffer.remaining() < (2 * (long)entryCount)) {
+ throw new RuntimeException("Format 10 table exceeded");
+ }
CharBuffer buffer = bbuffer.asCharBuffer();
glyphIdArray = new char[entryCount];
for (int i=0; i< entryCount; i++) {
@@ -955,11 +963,15 @@ abstract class CMap {
throw new RuntimeException("xlat array for cmap fmt=12");
}
- numGroups = buffer.getInt(offset+12);
+ buffer.position(offset+12);
+ numGroups = buffer.getInt() & INTMASK;
+ // A map group record is three uint32's making for 12 bytes total
+ if (buffer.remaining() < (12 * (long)numGroups)) {
+ throw new RuntimeException("Format 12 table exceeded");
+ }
startCharCode = new long[numGroups];
endCharCode = new long[numGroups];
startGlyphID = new int[numGroups];
- buffer.position(offset+16);
buffer = buffer.slice();
IntBuffer ibuffer = buffer.asIntBuffer();
for (int i=0; i<numGroups; i++) {
diff --git a/src/share/classes/sun/font/FileFont.java b/src/share/classes/sun/font/FileFont.java
index b7ebbda890..57f6e3d512 100644
--- a/src/share/classes/sun/font/FileFont.java
+++ b/src/share/classes/sun/font/FileFont.java
@@ -175,7 +175,7 @@ public abstract class FileFont extends PhysicalFont {
}
}
if (scaler != null) {
- scaler.dispose();
+ scaler.disposeScaler();
}
scaler = FontScaler.getNullScaler();
}
diff --git a/src/share/classes/sun/font/Font2D.java b/src/share/classes/sun/font/Font2D.java
index 678c2a4256..3856bc54f7 100644
--- a/src/share/classes/sun/font/Font2D.java
+++ b/src/share/classes/sun/font/Font2D.java
@@ -56,17 +56,19 @@ public abstract class Font2D {
public static final int NATIVE_RANK = 5;
public static final int UNKNOWN_RANK = 6;
public static final int DEFAULT_RANK = 4;
+ public static final int IDEA_RANK = 7;
private static final String[] boldNames = {
- "bold", "demibold", "demi-bold", "demi bold", "negreta", "demi", };
+ "bold", "demibold", "demi-bold", "demi bold", "negreta", "demi", "black", "coder-b"};
private static final String[] italicNames = {
- "italic", "cursiva", "oblique", "inclined", };
+ "italic", "cursiva", "oblique", "inclined", "-it", "-lightit", "coder-i"};
private static final String[] boldItalicNames = {
"bolditalic", "bold-italic", "bold italic",
"boldoblique", "bold-oblique", "bold oblique",
- "demibold italic", "negreta cursiva","demi oblique", };
+ "demibold italic", "negreta cursiva","demi oblique",
+ "-boldit", "-blackit", "coder-bi"};
private static final FontRenderContext DEFAULT_FRC =
new FontRenderContext(null, false, false);
diff --git a/src/share/classes/sun/font/FontFamily.java b/src/share/classes/sun/font/FontFamily.java
index a0d8032494..322510f971 100644
--- a/src/share/classes/sun/font/FontFamily.java
+++ b/src/share/classes/sun/font/FontFamily.java
@@ -219,11 +219,11 @@ public class FontFamily {
case Font.PLAIN:
case Font.ITALIC:
return (newWeight <= Font2D.FWEIGHT_NORMAL &&
- newWeight > currFont.getWeight());
+ newWeight >= currFont.getWeight());
case Font.BOLD:
case Font.BOLD|Font.ITALIC:
- return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <
+ return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <=
Math.abs(currFont.getWeight() - Font2D.FWEIGHT_BOLD));
default:
diff --git a/src/share/classes/sun/font/FontScaler.java b/src/share/classes/sun/font/FontScaler.java
index 61e53d36b3..2c7cf6daf7 100644
--- a/src/share/classes/sun/font/FontScaler.java
+++ b/src/share/classes/sun/font/FontScaler.java
@@ -194,6 +194,12 @@ public abstract class FontScaler implements DisposerRecord {
scaler context objects! */
public void dispose() {}
+ /**
+ * Used when the native resources held by the scaler need
+ * to be released before the 2D disposer runs.
+ */
+ public void disposeScaler() {}
+
/* At the moment these 3 methods are needed for Type1 fonts only.
* For Truetype fonts we extract required info outside of scaler
* on java layer.
diff --git a/src/share/classes/sun/font/FreetypeFontScaler.java b/src/share/classes/sun/font/FreetypeFontScaler.java
index dadca159fa..e55ba1fd7d 100644
--- a/src/share/classes/sun/font/FreetypeFontScaler.java
+++ b/src/share/classes/sun/font/FreetypeFontScaler.java
@@ -182,6 +182,9 @@ class FreetypeFontScaler extends FontScaler {
return getLayoutTableCacheNative(nativeScaler);
}
+ /* This method should not be called directly, in case
+ * it is being invoked from a thread with a native context.
+ */
public synchronized void dispose() {
if (nativeScaler != 0L) {
disposeNativeScaler(font.get(), nativeScaler);
@@ -189,6 +192,21 @@ class FreetypeFontScaler extends FontScaler {
}
}
+ public synchronized void disposeScaler() {
+ if (nativeScaler != 0L) {
+ /*
+ * The current thread may be calling this method from the context
+ * of a JNI up-call. It will hold the native lock from the
+ * original down-call so can directly enter dispose and free
+ * the resources. So we need to schedule the disposal to happen
+ * only once we've returned from native. So by running the dispose
+ * on another thread which does nothing except that disposal we
+ * are sure that this is safe.
+ */
+ new Thread(null, () -> dispose(), "free scaler", 0).start();
+ }
+ }
+
synchronized int getNumGlyphs() throws FontScalerException {
if (nativeScaler != 0L) {
return getNumGlyphsNative(nativeScaler);
@@ -225,7 +243,7 @@ class FreetypeFontScaler extends FontScaler {
return getUnitsPerEMNative(nativeScaler);
}
- long createScalerContext(double[] matrix,
+ synchronized long createScalerContext(double[] matrix,
int aa, int fm, float boldness, float italic,
boolean disableHinting) {
if (nativeScaler != 0L) {
@@ -255,7 +273,7 @@ class FreetypeFontScaler extends FontScaler {
private native GeneralPath getGlyphVectorOutlineNative(Font2D font,
long pScalerContext, long pScaler,
int[] glyphs, int numGlyphs, float x, float y);
- native Point2D.Float getGlyphPointNative(Font2D font,
+ private native Point2D.Float getGlyphPointNative(Font2D font,
long pScalerContext, long pScaler, int glyphCode, int ptNumber);
private native long getLayoutTableCacheNative(long pScaler);
@@ -268,7 +286,7 @@ class FreetypeFontScaler extends FontScaler {
private native long getUnitsPerEMNative(long pScaler);
- native long createScalerContextNative(long pScaler, double[] matrix,
+ private native long createScalerContextNative(long pScaler, double[] matrix,
int aa, int fm, float boldness, float italic);
/* Freetype scaler context does not contain any pointers that
diff --git a/src/share/classes/sun/font/GlyphList.java b/src/share/classes/sun/font/GlyphList.java
index ad61f3d1a0..825efd4fc1 100644
--- a/src/share/classes/sun/font/GlyphList.java
+++ b/src/share/classes/sun/font/GlyphList.java
@@ -328,6 +328,14 @@ public final class GlyphList {
*/
public void setGlyphIndex(int i) {
glyphindex = i;
+ if (images[i] == 0L) {
+ metrics[0] = (int)gposx;
+ metrics[1] = (int)gposy;
+ metrics[2] = 0;
+ metrics[3] = 0;
+ metrics[4] = 0;
+ return;
+ }
float gx =
StrikeCache.unsafe.getFloat(images[i]+StrikeCache.topLeftXOffset);
float gy =
@@ -366,6 +374,9 @@ public final class GlyphList {
graybits = new byte[len];
}
}
+ if (images[glyphindex] == 0L) {
+ return graybits;
+ }
long pixelDataAddress =
StrikeCache.unsafe.getAddress(images[glyphindex] +
StrikeCache.pixelDataOffset);
@@ -484,6 +495,9 @@ public final class GlyphList {
char gw, gh;
float gx, gy, gx0, gy0, gx1, gy1;
for (int i=0; i<len; i++) {
+ if (images[i] == 0L) {
+ continue;
+ }
gx = StrikeCache.unsafe.getFloat(images[i]+xOffset);
gy = StrikeCache.unsafe.getFloat(images[i]+yOffset);
gw = StrikeCache.unsafe.getChar(images[i]+wOffset);
diff --git a/src/share/classes/sun/font/SunFontManager.java b/src/share/classes/sun/font/SunFontManager.java
index 4e9298a0fb..02f7c33c8b 100644
--- a/src/share/classes/sun/font/SunFontManager.java
+++ b/src/share/classes/sun/font/SunFontManager.java
@@ -81,6 +81,27 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
}
}
+ private static class TTFilterIdea extends TTFilter {
+ final private boolean positive;
+ final private HashSet<String> ideaSet;
+
+ public TTFilterIdea(boolean positive, HashSet<String> ideaSet) {
+ this.positive = positive;
+ this.ideaSet = ideaSet;
+ }
+
+ @Override
+ public boolean accept(File dir, String name) {
+ if (super.accept(dir, name)) {
+ if (ideaSet.contains(name))
+ return positive;
+ else
+ return !positive;
+ }
+ return false;
+ }
+ }
+
private static class T1Filter implements FilenameFilter {
public boolean accept(File dir,String name) {
if (noType1Font) {
@@ -189,6 +210,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
boolean loadedAllFontFiles = false;
HashMap<String,String> jreFontMap;
HashSet<String> jreBundledFontFiles;
+ HashSet<String> ideaFontSet;
String[] jreOtherFontFiles;
boolean noOtherJREFontFiles = false; // initial assumption.
@@ -223,6 +245,8 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
private static final FilenameFilter ttFilter = new TTFilter();
private static final FilenameFilter t1Filter = new T1Filter();
+ private FilenameFilter ttFilterIdea;
+ private FilenameFilter ttFilterJre;
private Font[] allFonts;
private String[] allFamilies; // cache for default locale only
private Locale lastDefaultLocale;
@@ -317,6 +341,23 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
jreFontMap.put("Roboto light", "Roboto-Light.ttf");
jreFontMap.put("Roboto thin", "Roboto-Thin.ttf");
+ ideaFontSet = new HashSet<>();
+ ideaFontSet.add("FiraCode-Bold.ttf");
+ ideaFontSet.add("FiraCode-Light.ttf");
+ ideaFontSet.add("FiraCode-Medium.ttf");
+ ideaFontSet.add("FiraCode-Retina.ttf");
+ ideaFontSet.add("FiraCode-Regular.ttf");
+ ideaFontSet.add("SourceCodePro-BoldIt.ttf");
+ ideaFontSet.add("SourceCodePro-Regular.ttf");
+ ideaFontSet.add("SourceCodePro-Bold.ttf");
+ ideaFontSet.add("SourceCodePro-It.ttf");
+ ideaFontSet.add("Inconsolata.ttf");
+ ideaFontSet.add("Roboto-Light.ttf");
+ ideaFontSet.add("Roboto-Thin.ttf");
+
+ ttFilterIdea = new TTFilterIdea(true, ideaFontSet);
+ ttFilterJre = new TTFilterIdea(false, ideaFontSet);
+
for (String ffile : jreFontMap.values()) {
jreBundledFontFiles.add(ffile);
}
@@ -412,8 +453,7 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
/* Linux font configuration uses these fonts */
registerFontDir(jreFontDirName);
}
- registerFontsInDir(jreFontDirName, true, Font2D.JRE_RANK,
- true, false);
+ registerJREFonts();
/* Create the font configuration and get any font path
* that might be specified.
@@ -3337,6 +3377,18 @@ public abstract class SunFontManager implements FontSupport, FontManagerForSGE {
defer, resolveSymLinks);
}
+ protected void registerJREFonts() {
+ File pathFile = new File(jreFontDirName);
+ addDirFonts(jreFontDirName, pathFile, ttFilterIdea,
+ FONTFORMAT_TRUETYPE, true,
+ Font2D.IDEA_RANK,
+ true, false);
+ addDirFonts(jreFontDirName, pathFile, ttFilterJre,
+ FONTFORMAT_TRUETYPE, true,
+ Font2D.JRE_RANK,
+ true, false);
+ }
+
protected void registerFontDir(String path) {
}
diff --git a/src/share/classes/sun/java2d/SunGraphics2D.java b/src/share/classes/sun/java2d/SunGraphics2D.java
index 39eeca1bda..b37f53907d 100644
--- a/src/share/classes/sun/java2d/SunGraphics2D.java
+++ b/src/share/classes/sun/java2d/SunGraphics2D.java
@@ -3021,7 +3021,8 @@ public final class SunGraphics2D
if (data == null) {
throw new NullPointerException("char data is null");
}
- if (offset < 0 || length < 0 || offset + length > data.length) {
+ if (offset < 0 || length < 0 || offset + length < length ||
+ offset + length > data.length) {
throw new ArrayIndexOutOfBoundsException("bad offset/length");
}
if (font.hasLayoutAttributes()) {
@@ -3053,7 +3054,8 @@ public final class SunGraphics2D
if (data == null) {
throw new NullPointerException("byte data is null");
}
- if (offset < 0 || length < 0 || offset + length > data.length) {
+ if (offset < 0 || length < 0 || offset + length < length ||
+ offset + length > data.length) {
throw new ArrayIndexOutOfBoundsException("bad offset/length");
}
/* Byte data is interpreted as 8-bit ASCII. Re-use drawChars loops */
diff --git a/src/share/classes/sun/java2d/marlin/DDasher.java b/src/share/classes/sun/java2d/marlin/DDasher.java
index cb1ce79ee4..98d540f026 100644
--- a/src/share/classes/sun/java2d/marlin/DDasher.java
+++ b/src/share/classes/sun/java2d/marlin/DDasher.java
@@ -47,6 +47,8 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
static final double CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01 initial
static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
+ static final double EPS = 1e-6d;
+
// More than 24 bits of mantissa means we can no longer accurately
// measure the number of times cycled through the dash array so we
// punt and override the phase to just be 0 past that point.
@@ -361,7 +363,7 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -416,13 +418,13 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
boolean _dashOn = dashOn;
double _phase = phase;
- double leftInThisDashSegment, d;
+ double leftInThisDashSegment, rem;
while (true) {
- d = _dash[_idx];
- leftInThisDashSegment = d - _phase;
+ leftInThisDashSegment = _dash[_idx] - _phase;
+ rem = len - leftInThisDashSegment;
- if (len <= leftInThisDashSegment) {
+ if (rem <= EPS) {
_curCurvepts[0] = x1;
_curCurvepts[1] = y1;
@@ -431,8 +433,8 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
// Advance phase within current dash segment
_phase += len;
- // TODO: compare double values using epsilon:
- if (len == leftInThisDashSegment) {
+ // compare values using epsilon:
+ if (Math.abs(rem) <= EPS) {
_phase = 0.0d;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -440,17 +442,12 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
break;
}
- if (_phase == 0.0d) {
- _curCurvepts[0] = cx0 + d * cx;
- _curCurvepts[1] = cy0 + d * cy;
- } else {
- _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
- _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
- }
+ _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
+ _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
goTo(_curCurvepts, 0, 4, _dashOn);
- len -= leftInThisDashSegment;
+ len = rem;
// Advance to next dash segment
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -506,18 +503,18 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
_dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
}
- double leftInThisDashSegment, d;
+ double leftInThisDashSegment, rem;
while (true) {
- d = _dash[_idx];
- leftInThisDashSegment = d - _phase;
+ leftInThisDashSegment = _dash[_idx] - _phase;
+ rem = len - leftInThisDashSegment;
- if (len <= leftInThisDashSegment) {
+ if (rem <= EPS) {
// Advance phase within current dash segment
_phase += len;
- // TODO: compare double values using epsilon:
- if (len == leftInThisDashSegment) {
+ // compare values using epsilon:
+ if (Math.abs(rem) <= EPS) {
_phase = 0.0d;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -525,7 +522,7 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
break;
}
- len -= leftInThisDashSegment;
+ len = rem;
// Advance to next dash segment
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -579,7 +576,9 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
_phase += _li.lastSegLen();
- if (_phase >= _dash[_idx]) {
+
+ // compare values using epsilon:
+ if (_phase + EPS >= _dash[_idx]) {
_phase = 0.0d;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -938,7 +937,7 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1024,7 +1023,7 @@ final class DDasher implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
diff --git a/src/share/classes/sun/java2d/marlin/DHelpers.java b/src/share/classes/sun/java2d/marlin/DHelpers.java
index 6136e3f60a..cb9f9449c0 100644
--- a/src/share/classes/sun/java2d/marlin/DHelpers.java
+++ b/src/share/classes/sun/java2d/marlin/DHelpers.java
@@ -243,7 +243,7 @@ final class DHelpers implements MarlinConst {
final double y12 = pts[3] - pts[1];
// if the curve is already parallel to either axis we gain nothing
// from rotating it.
- if ((y12 != 0.0d && x12 != 0.0d)) {
+ if ((y12 != 0.0d) && (x12 != 0.0d)) {
// we rotate it so that the first vector in the control polygon is
// parallel to the x-axis. This will ensure that rotated quarter
// circles won't be subdivided.
diff --git a/src/share/classes/sun/java2d/marlin/DStroker.java b/src/share/classes/sun/java2d/marlin/DStroker.java
index 5fecec848a..bd14b8fe44 100644
--- a/src/share/classes/sun/java2d/marlin/DStroker.java
+++ b/src/share/classes/sun/java2d/marlin/DStroker.java
@@ -540,7 +540,7 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -634,6 +634,9 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
emitReverse();
this.prev = CLOSE;
+ this.cx0 = sx0;
+ this.cy0 = sy0;
+ this.cOutCode = sOutCode;
if (opened) {
// do not emit close
@@ -668,7 +671,9 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
// i.e. if caps must be drawn or not ?
// Solution: use the ClosedPathDetector before Stroker to determine
// if the path is a closed path or not
- if (!rdrCtx.closedPath) {
+ if (rdrCtx.closedPath) {
+ emitReverse();
+ } else {
if (outcode == 0) {
// current point = end's cap:
if (capStyle == CAP_ROUND) {
@@ -693,8 +698,6 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
}
}
}
- } else {
- emitReverse();
}
emitClose();
}
@@ -1058,7 +1061,7 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1206,7 +1209,7 @@ final class DStroker implements DPathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
diff --git a/src/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java b/src/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java
index 353f9defe7..17667295f4 100644
--- a/src/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java
+++ b/src/share/classes/sun/java2d/marlin/DTransformingPathConsumer2D.java
@@ -530,6 +530,9 @@ final class DTransformingPathConsumer2D {
private boolean outside = false;
+ // The starting point of the path
+ private double sx0, sy0;
+
// The current point (TODO stupid repeated info)
private double cx0, cy0;
@@ -630,17 +633,26 @@ final class DTransformingPathConsumer2D {
finishPath();
out.closePath();
+
+ // back to starting point:
+ this.cOutCode = DHelpers.outcode(sx0, sy0, clipRect);
+ this.cx0 = sx0;
+ this.cy0 = sy0;
}
@Override
public void moveTo(final double x0, final double y0) {
finishPath();
- this.cOutCode = DHelpers.outcode(x0, y0, clipRect);
- this.outside = false;
out.moveTo(x0, y0);
+
+ // update starting point:
+ this.cOutCode = DHelpers.outcode(x0, y0, clipRect);
this.cx0 = x0;
this.cy0 = y0;
+
+ this.sx0 = x0;
+ this.sy0 = y0;
}
@Override
@@ -655,7 +667,7 @@ final class DTransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -754,7 +766,7 @@ final class DTransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -816,7 +828,7 @@ final class DTransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1153,13 +1165,13 @@ final class DTransformingPathConsumer2D {
@Override
public void moveTo(double x0, double y0) {
- log("moveTo (" + x0 + ", " + y0 + ')');
+ log("p.moveTo(" + x0 + ", " + y0 + ");");
out.moveTo(x0, y0);
}
@Override
public void lineTo(double x1, double y1) {
- log("lineTo (" + x1 + ", " + y1 + ')');
+ log("p.lineTo(" + x1 + ", " + y1 + ");");
out.lineTo(x1, y1);
}
@@ -1168,25 +1180,26 @@ final class DTransformingPathConsumer2D {
double x2, double y2,
double x3, double y3)
{
- log("curveTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ") P3(" + x3 + ", " + y3 + ')');
+ log("p.curveTo(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ", " + x3 + ", " + y3 + ");");
out.curveTo(x1, y1, x2, y2, x3, y3);
}
@Override
- public void quadTo(double x1, double y1, double x2, double y2) {
- log("quadTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ')');
+ public void quadTo(double x1, double y1,
+ double x2, double y2) {
+ log("p.quadTo(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ");");
out.quadTo(x1, y1, x2, y2);
}
@Override
public void closePath() {
- log("closePath");
+ log("p.closePath();");
out.closePath();
}
@Override
public void pathDone() {
- log("pathDone");
+ log("p.pathDone();");
out.pathDone();
}
diff --git a/src/share/classes/sun/java2d/marlin/Dasher.java b/src/share/classes/sun/java2d/marlin/Dasher.java
index c28311bb2a..c69fe09f20 100644
--- a/src/share/classes/sun/java2d/marlin/Dasher.java
+++ b/src/share/classes/sun/java2d/marlin/Dasher.java
@@ -48,6 +48,8 @@ final class Dasher implements PathConsumer2D, MarlinConst {
static final float CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01
static final float MIN_T_INC = 1.0f / (1 << REC_LIMIT);
+ static final float EPS = 1e-6f;
+
// More than 24 bits of mantissa means we can no longer accurately
// measure the number of times cycled through the dash array so we
// punt and override the phase to just be 0 past that point.
@@ -362,7 +364,7 @@ final class Dasher implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -417,13 +419,13 @@ final class Dasher implements PathConsumer2D, MarlinConst {
boolean _dashOn = dashOn;
float _phase = phase;
- float leftInThisDashSegment, d;
+ float leftInThisDashSegment, rem;
while (true) {
- d = _dash[_idx];
- leftInThisDashSegment = d - _phase;
+ leftInThisDashSegment = _dash[_idx] - _phase;
+ rem = len - leftInThisDashSegment;
- if (len <= leftInThisDashSegment) {
+ if (rem <= EPS) {
_curCurvepts[0] = x1;
_curCurvepts[1] = y1;
@@ -432,8 +434,8 @@ final class Dasher implements PathConsumer2D, MarlinConst {
// Advance phase within current dash segment
_phase += len;
- // TODO: compare float values using epsilon:
- if (len == leftInThisDashSegment) {
+ // compare values using epsilon:
+ if (Math.abs(rem) <= EPS) {
_phase = 0.0f;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -441,17 +443,12 @@ final class Dasher implements PathConsumer2D, MarlinConst {
break;
}
- if (_phase == 0.0f) {
- _curCurvepts[0] = cx0 + d * cx;
- _curCurvepts[1] = cy0 + d * cy;
- } else {
- _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
- _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
- }
+ _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
+ _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
goTo(_curCurvepts, 0, 4, _dashOn);
- len -= leftInThisDashSegment;
+ len = rem;
// Advance to next dash segment
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -507,18 +504,18 @@ final class Dasher implements PathConsumer2D, MarlinConst {
_dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
}
- float leftInThisDashSegment, d;
+ float leftInThisDashSegment, rem;
while (true) {
- d = _dash[_idx];
- leftInThisDashSegment = d - _phase;
+ leftInThisDashSegment = _dash[_idx] - _phase;
+ rem = len - leftInThisDashSegment;
- if (len <= leftInThisDashSegment) {
+ if (rem <= EPS) {
// Advance phase within current dash segment
_phase += len;
- // TODO: compare float values using epsilon:
- if (len == leftInThisDashSegment) {
+ // compare values using epsilon:
+ if (Math.abs(rem) <= EPS) {
_phase = 0.0f;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -526,7 +523,7 @@ final class Dasher implements PathConsumer2D, MarlinConst {
break;
}
- len -= leftInThisDashSegment;
+ len = rem;
// Advance to next dash segment
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -580,7 +577,9 @@ final class Dasher implements PathConsumer2D, MarlinConst {
goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
_phase += _li.lastSegLen();
- if (_phase >= _dash[_idx]) {
+
+ // compare values using epsilon:
+ if (_phase + EPS >= _dash[_idx]) {
_phase = 0.0f;
_idx = (_idx + 1) % _dashLen;
_dashOn = !_dashOn;
@@ -939,7 +938,7 @@ final class Dasher implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1025,7 +1024,7 @@ final class Dasher implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
diff --git a/src/share/classes/sun/java2d/marlin/Helpers.java b/src/share/classes/sun/java2d/marlin/Helpers.java
index 513d287e1a..2043ab3ce6 100644
--- a/src/share/classes/sun/java2d/marlin/Helpers.java
+++ b/src/share/classes/sun/java2d/marlin/Helpers.java
@@ -251,7 +251,7 @@ final class Helpers implements MarlinConst {
final float y12 = pts[3] - pts[1];
// if the curve is already parallel to either axis we gain nothing
// from rotating it.
- if ((y12 != 0.0f && x12 != 0.0f)) {
+ if ((y12 != 0.0f) && (x12 != 0.0f)) {
// we rotate it so that the first vector in the control polygon is
// parallel to the x-axis. This will ensure that rotated quarter
// circles won't be subdivided.
diff --git a/src/share/classes/sun/java2d/marlin/Stroker.java b/src/share/classes/sun/java2d/marlin/Stroker.java
index 1e18941a0c..255e0fe0ae 100644
--- a/src/share/classes/sun/java2d/marlin/Stroker.java
+++ b/src/share/classes/sun/java2d/marlin/Stroker.java
@@ -542,7 +542,7 @@ final class Stroker implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -636,6 +636,9 @@ final class Stroker implements PathConsumer2D, MarlinConst {
emitReverse();
this.prev = CLOSE;
+ this.cx0 = sx0;
+ this.cy0 = sy0;
+ this.cOutCode = sOutCode;
if (opened) {
// do not emit close
@@ -670,7 +673,9 @@ final class Stroker implements PathConsumer2D, MarlinConst {
// i.e. if caps must be drawn or not ?
// Solution: use the ClosedPathDetector before Stroker to determine
// if the path is a closed path or not
- if (!rdrCtx.closedPath) {
+ if (rdrCtx.closedPath) {
+ emitReverse();
+ } else {
if (outcode == 0) {
// current point = end's cap:
if (capStyle == CAP_ROUND) {
@@ -695,8 +700,6 @@ final class Stroker implements PathConsumer2D, MarlinConst {
}
}
}
- } else {
- emitReverse();
}
emitClose();
}
@@ -1060,7 +1063,7 @@ final class Stroker implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1208,7 +1211,7 @@ final class Stroker implements PathConsumer2D, MarlinConst {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
diff --git a/src/share/classes/sun/java2d/marlin/TransformingPathConsumer2D.java b/src/share/classes/sun/java2d/marlin/TransformingPathConsumer2D.java
index fb4c34f0a2..f8af398eef 100644
--- a/src/share/classes/sun/java2d/marlin/TransformingPathConsumer2D.java
+++ b/src/share/classes/sun/java2d/marlin/TransformingPathConsumer2D.java
@@ -531,6 +531,9 @@ final class TransformingPathConsumer2D {
private boolean outside = false;
+ // The starting point of the path
+ private float sx0, sy0;
+
// The current point (TODO stupid repeated info)
private float cx0, cy0;
@@ -631,17 +634,26 @@ final class TransformingPathConsumer2D {
finishPath();
out.closePath();
+
+ // back to starting point:
+ this.cOutCode = Helpers.outcode(sx0, sy0, clipRect);
+ this.cx0 = sx0;
+ this.cy0 = sy0;
}
@Override
public void moveTo(final float x0, final float y0) {
finishPath();
- this.cOutCode = Helpers.outcode(x0, y0, clipRect);
- this.outside = false;
out.moveTo(x0, y0);
+
+ // update starting point:
+ this.cOutCode = Helpers.outcode(x0, y0, clipRect);
this.cx0 = x0;
this.cy0 = y0;
+
+ this.sx0 = x0;
+ this.sy0 = y0;
}
@Override
@@ -656,7 +668,7 @@ final class TransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -755,7 +767,7 @@ final class TransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -817,7 +829,7 @@ final class TransformingPathConsumer2D {
// basic rejection criteria:
if (sideCode == 0) {
- // ovelap clip:
+ // overlap clip:
if (subdivide) {
// avoid reentrance
subdivide = false;
@@ -1154,13 +1166,13 @@ final class TransformingPathConsumer2D {
@Override
public void moveTo(float x0, float y0) {
- log("moveTo (" + x0 + ", " + y0 + ')');
+ log("p.moveTo(" + x0 + ", " + y0 + ");");
out.moveTo(x0, y0);
}
@Override
public void lineTo(float x1, float y1) {
- log("lineTo (" + x1 + ", " + y1 + ')');
+ log("p.lineTo(" + x1 + ", " + y1 + ");");
out.lineTo(x1, y1);
}
@@ -1169,25 +1181,26 @@ final class TransformingPathConsumer2D {
float x2, float y2,
float x3, float y3)
{
- log("curveTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ") P3(" + x3 + ", " + y3 + ')');
+ log("p.curveTo(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ", " + x3 + ", " + y3 + ");");
out.curveTo(x1, y1, x2, y2, x3, y3);
}
@Override
- public void quadTo(float x1, float y1, float x2, float y2) {
- log("quadTo P1(" + x1 + ", " + y1 + ") P2(" + x2 + ", " + y2 + ')');
+ public void quadTo(float x1, float y1,
+ float x2, float y2) {
+ log("p.quadTo(" + x1 + ", " + y1 + ", " + x2 + ", " + y2 + ");");
out.quadTo(x1, y1, x2, y2);
}
@Override
public void closePath() {
- log("closePath");
+ log("p.closePath();");
out.closePath();
}
@Override
public void pathDone() {
- log("pathDone");
+ log("p.pathDone();");
out.pathDone();
}
diff --git a/src/share/classes/sun/java2d/marlin/Version.java b/src/share/classes/sun/java2d/marlin/Version.java
index 5a6976f4db..1be473616c 100644
--- a/src/share/classes/sun/java2d/marlin/Version.java
+++ b/src/share/classes/sun/java2d/marlin/Version.java
@@ -27,7 +27,7 @@ package sun.java2d.marlin;
public final class Version {
- private static final String VERSION = "marlin-0.9.3-Unsafe-OpenJDK";
+ private static final String VERSION = "marlin-0.9.3.1-Unsafe-OpenJDK";
public static String getVersion() {
return VERSION;
diff --git a/src/share/classes/sun/misc/Launcher.java b/src/share/classes/sun/misc/Launcher.java
index aab1951665..bea4004556 100644
--- a/src/share/classes/sun/misc/Launcher.java
+++ b/src/share/classes/sun/misc/Launcher.java
@@ -85,6 +85,9 @@ public class Launcher {
// Finally, install a security manager if requested
String s = System.getProperty("java.security.manager");
if (s != null) {
+ // init FileSystem machinery before SecurityManager installation
+ sun.nio.fs.DefaultFileSystemProvider.create();
+
SecurityManager sm = null;
if ("".equals(s) || "default".equals(s)) {
sm = new java.lang.SecurityManager();
diff --git a/src/share/classes/sun/net/util/IPAddressUtil.java b/src/share/classes/sun/net/util/IPAddressUtil.java
index 6aa98c8f8d..2bcd2c0781 100644
--- a/src/share/classes/sun/net/util/IPAddressUtil.java
+++ b/src/share/classes/sun/net/util/IPAddressUtil.java
@@ -25,6 +25,9 @@
package sun.net.util;
+import java.net.URL;
+import java.util.Arrays;
+
public class IPAddressUtil {
private final static int INADDR4SZ = 4;
private final static int INADDR16SZ = 16;
@@ -287,4 +290,182 @@ public class IPAddressUtil {
}
return false;
}
+
+ // See java.net.URI for more details on how to generate these
+ // masks.
+ //
+ // square brackets
+ private static final long L_IPV6_DELIMS = 0x0L; // "[]"
+ private static final long H_IPV6_DELIMS = 0x28000000L; // "[]"
+ // RFC 3986 gen-delims
+ private static final long L_GEN_DELIMS = 0x8400800800000000L; // ":/?#[]@"
+ private static final long H_GEN_DELIMS = 0x28000001L; // ":/?#[]@"
+ // These gen-delims can appear in authority
+ private static final long L_AUTH_DELIMS = 0x400000000000000L; // "@[]:"
+ private static final long H_AUTH_DELIMS = 0x28000001L; // "@[]:"
+ // colon is allowed in userinfo
+ private static final long L_COLON = 0x400000000000000L; // ":"
+ private static final long H_COLON = 0x0L; // ":"
+ // slash should be encoded in authority
+ private static final long L_SLASH = 0x800000000000L; // "/"
+ private static final long H_SLASH = 0x0L; // "/"
+ // backslash should always be encoded
+ private static final long L_BACKSLASH = 0x0L; // "\"
+ private static final long H_BACKSLASH = 0x10000000L; // "\"
+ // ASCII chars 0-31 + 127 - various controls + CRLF + TAB
+ private static final long L_NON_PRINTABLE = 0xffffffffL;
+ private static final long H_NON_PRINTABLE = 0x8000000000000000L;
+ // All of the above
+ private static final long L_EXCLUDE = 0x84008008ffffffffL;
+ private static final long H_EXCLUDE = 0x8000000038000001L;
+
+ private static final char[] OTHERS = {
+ 8263,8264,8265,8448,8449,8453,8454,10868,
+ 65109,65110,65119,65131,65283,65295,65306,65311,65312
+ };
+
+ // Tell whether the given character is found by the given mask pair
+ public static boolean match(char c, long lowMask, long highMask) {
+ if (c < 64)
+ return ((1L << c) & lowMask) != 0;
+ if (c < 128)
+ return ((1L << (c - 64)) & highMask) != 0;
+ return false; // other non ASCII characters are not filtered
+ }
+
+ // returns -1 if the string doesn't contain any characters
+ // from the mask, the index of the first such character found
+ // otherwise.
+ public static int scan(String s, long lowMask, long highMask) {
+ int i = -1, len;
+ if (s == null || (len = s.length()) == 0) return -1;
+ boolean match = false;
+ while (++i < len && !(match = match(s.charAt(i), lowMask, highMask)));
+ if (match) return i;
+ return -1;
+ }
+
+ public static int scan(String s, long lowMask, long highMask, char[] others) {
+ int i = -1, len;
+ if (s == null || (len = s.length()) == 0) return -1;
+ boolean match = false;
+ char c, c0 = others[0];
+ while (++i < len && !(match = match((c=s.charAt(i)), lowMask, highMask))) {
+ if (c >= c0 && (Arrays.binarySearch(others, c) > -1)) {
+ match = true; break;
+ }
+ }
+ if (match) return i;
+
+ return -1;
+ }
+
+ private static String describeChar(char c) {
+ if (c < 32 || c == 127) {
+ if (c == '\n') return "LF";
+ if (c == '\r') return "CR";
+ return "control char (code=" + (int)c + ")";
+ }
+ if (c == '\\') return "'\\'";
+ return "'" + c + "'";
+ }
+
+ private static String checkUserInfo(String str) {
+ // colon is permitted in user info
+ int index = scan(str, L_EXCLUDE & ~L_COLON,
+ H_EXCLUDE & ~H_COLON);
+ if (index >= 0) {
+ return "Illegal character found in user-info: "
+ + describeChar(str.charAt(index));
+ }
+ return null;
+ }
+
+ private static String checkHost(String str) {
+ int index;
+ if (str.startsWith("[") && str.endsWith("]")) {
+ str = str.substring(1, str.length() - 1);
+ if (isIPv6LiteralAddress(str)) {
+ index = str.indexOf('%');
+ if (index >= 0) {
+ index = scan(str = str.substring(index),
+ L_NON_PRINTABLE | L_IPV6_DELIMS,
+ H_NON_PRINTABLE | H_IPV6_DELIMS);
+ if (index >= 0) {
+ return "Illegal character found in IPv6 scoped address: "
+ + describeChar(str.charAt(index));
+ }
+ }
+ return null;
+ }
+ return "Unrecognized IPv6 address format";
+ } else {
+ index = scan(str, L_EXCLUDE, H_EXCLUDE);
+ if (index >= 0) {
+ return "Illegal character found in host: "
+ + describeChar(str.charAt(index));
+ }
+ }
+ return null;
+ }
+
+ private static String checkAuth(String str) {
+ int index = scan(str,
+ L_EXCLUDE & ~L_AUTH_DELIMS,
+ H_EXCLUDE & ~H_AUTH_DELIMS);
+ if (index >= 0) {
+ return "Illegal character found in authority: "
+ + describeChar(str.charAt(index));
+ }
+ return null;
+ }
+
+ // check authority of hierarchical URL. Appropriate for
+ // HTTP-like protocol handlers
+ public static String checkAuthority(URL url) {
+ String s, u, h;
+ if (url == null) return null;
+ if ((s = checkUserInfo(u = url.getUserInfo())) != null) {
+ return s;
+ }
+ if ((s = checkHost(h = url.getHost())) != null) {
+ return s;
+ }
+ if (h == null && u == null) {
+ return checkAuth(url.getAuthority());
+ }
+ return null;
+ }
+
+ // minimal syntax checks - deeper check may be performed
+ // by the appropriate protocol handler
+ public static String checkExternalForm(URL url) {
+ String s;
+ if (url == null) return null;
+ int index = scan(s = url.getUserInfo(),
+ L_NON_PRINTABLE | L_SLASH,
+ H_NON_PRINTABLE | H_SLASH);
+ if (index >= 0) {
+ return "Illegal character found in authority: "
+ + describeChar(s.charAt(index));
+ }
+ if ((s = checkHostString(url.getHost())) != null) {
+ return s;
+ }
+ return null;
+ }
+
+ public static String checkHostString(String host) {
+ if (host == null) return null;
+ int index = scan(host,
+ L_NON_PRINTABLE | L_SLASH,
+ H_NON_PRINTABLE | H_SLASH,
+ OTHERS);
+ if (index >= 0) {
+ return "Illegal character found in host: "
+ + describeChar(host.charAt(index));
+ }
+ return null;
+ }
+
}
diff --git a/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
index e560abf9c2..582687ba46 100644
--- a/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
+++ b/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@ import java.io.BufferedInputStream;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
import java.io.FileNotFoundException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.SocketPermission;
import java.net.UnknownHostException;
@@ -47,6 +48,7 @@ import java.util.StringTokenizer;
import java.util.Iterator;
import java.security.Permission;
import sun.net.NetworkClient;
+import sun.net.util.IPAddressUtil;
import sun.net.www.MessageHeader;
import sun.net.www.MeteredStream;
import sun.net.www.URLConnection;
@@ -155,6 +157,21 @@ public class FtpURLConnection extends URLConnection {
}
}
+ static URL checkURL(URL u) throws IllegalArgumentException {
+ if (u != null) {
+ if (u.toExternalForm().indexOf('\n') > -1) {
+ Exception mfue = new MalformedURLException("Illegal character in URL");
+ throw new IllegalArgumentException(mfue.getMessage(), mfue);
+ }
+ }
+ String s = IPAddressUtil.checkAuthority(u);
+ if (s != null) {
+ Exception mfue = new MalformedURLException(s);
+ throw new IllegalArgumentException(mfue.getMessage(), mfue);
+ }
+ return u;
+ }
+
/**
* Creates an FtpURLConnection from a URL.
*
@@ -168,7 +185,7 @@ public class FtpURLConnection extends URLConnection {
* Same as FtpURLconnection(URL) with a per connection proxy specified
*/
FtpURLConnection(URL url, Proxy p) {
- super(url);
+ super(checkURL(url));
instProxy = p;
host = url.getHost();
port = url.getPort();
diff --git a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
index 4c5ec78fca..f00060effa 100644
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
+++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, 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
@@ -66,6 +66,7 @@ import java.util.HashSet;
import java.util.HashMap;
import java.util.Set;
import sun.net.*;
+import sun.net.util.IPAddressUtil;
import sun.net.www.*;
import sun.net.www.http.HttpClient;
import sun.net.www.http.PosterOutputStream;
@@ -850,8 +851,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
throw new MalformedURLException("Illegal character in URL");
}
}
+ String s = IPAddressUtil.checkAuthority(u);
+ if (s != null) {
+ throw new MalformedURLException(s);
+ }
return u;
}
+
protected HttpURLConnection(URL u, Proxy p, Handler handler)
throws IOException {
super(checkURL(u));
@@ -2139,6 +2145,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
} while (retryTunnel < maxRedirects);
if (retryTunnel >= maxRedirects || (respCode != HTTP_OK)) {
+ if (respCode != HTTP_PROXY_AUTH) {
+ // remove all but authenticate responses
+ responses.reset();
+ }
throw new IOException("Unable to tunnel through proxy."+
" Proxy returns \"" +
statusLine + "\"");
diff --git a/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
index e43a36310a..0186e24725 100644
--- a/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
+++ b/src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
@@ -45,6 +45,7 @@ import java.security.Permission;
import java.security.Principal;
import java.util.Map;
import java.util.List;
+import sun.net.util.IPAddressUtil;
import sun.net.www.http.HttpClient;
/**
@@ -86,6 +87,10 @@ public class HttpsURLConnectionImpl
throw new MalformedURLException("Illegal character in URL");
}
}
+ String s = IPAddressUtil.checkAuthority(u);
+ if (s != null) {
+ throw new MalformedURLException(s);
+ }
return u;
}
// For both copies of the file, uncomment one line and comment the other
@@ -333,7 +338,7 @@ public class HttpsURLConnectionImpl
* @param key the keyword by which the request is known
* (e.g., "<code>accept</code>").
* @param value the value associated with it.
- * @see #getRequestProperties(java.lang.String)
+ * @see #getRequestProperty(java.lang.String)
* @since 1.4
*/
public void addRequestProperty(String key, String value) {
diff --git a/src/share/classes/sun/net/www/protocol/jar/Handler.java b/src/share/classes/sun/net/www/protocol/jar/Handler.java
index 8e9f8e3a35..4a3ae7e8ae 100644
--- a/src/share/classes/sun/net/www/protocol/jar/Handler.java
+++ b/src/share/classes/sun/net/www/protocol/jar/Handler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -121,6 +121,13 @@ public class Handler extends java.net.URLStreamHandler {
return h;
}
+ public String checkNestedProtocol(String spec) {
+ if (spec.regionMatches(true, 0, "jar:", 0, 4)) {
+ return "Nested JAR URLs are not supported";
+ } else {
+ return null;
+ }
+ }
@Override
@SuppressWarnings("deprecation")
@@ -147,6 +154,12 @@ public class Handler extends java.net.URLStreamHandler {
}
spec = spec.substring(start, limit);
+ String exceptionMessage = checkNestedProtocol(spec);
+ if (exceptionMessage != null) {
+ // NPE will be transformed into MalformedURLException by the caller
+ throw new NullPointerException(exceptionMessage);
+ }
+
if (absoluteSpec) {
file = parseAbsoluteSpec(spec);
} else if (!refOnly) {
diff --git a/src/share/classes/sun/print/services/javax.print.PrintServiceLookup b/src/share/classes/sun/print/services/javax.print.PrintServiceLookup
new file mode 100644
index 0000000000..bbeb657da4
--- /dev/null
+++ b/src/share/classes/sun/print/services/javax.print.PrintServiceLookup
@@ -0,0 +1,2 @@
+# Provider for Java Print Service
+sun.print.PrintServiceLookupProvider
diff --git a/src/solaris/classes/sun/print/services/javax.print.StreamPrintServiceFactory b/src/share/classes/sun/print/services/javax.print.StreamPrintServiceFactory
index b1bf88d80c..b1bf88d80c 100644
--- a/src/solaris/classes/sun/print/services/javax.print.StreamPrintServiceFactory
+++ b/src/share/classes/sun/print/services/javax.print.StreamPrintServiceFactory
diff --git a/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java
index 6807a328b1..c0a06f1f01 100644
--- a/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java
+++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Skel.java
@@ -27,13 +27,8 @@
package sun.rmi.registry;
import java.io.IOException;
-import java.io.InputStream;
-import java.rmi.AccessException;
-import java.rmi.server.RemoteCall;
-import sun.rmi.transport.Connection;
import sun.rmi.transport.StreamRemoteCall;
-import sun.rmi.transport.tcp.TCPConnection;
/**
* Skeleton to dispatch RegistryImpl methods.
@@ -56,7 +51,7 @@ public final class RegistryImpl_Skel
return operations.clone();
}
- public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
+ public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall remoteCall, int opnum, long hash)
throws java.lang.Exception {
if (opnum < 0) {
if (hash == 7583982177005850366L) {
@@ -78,6 +73,7 @@ public final class RegistryImpl_Skel
}
sun.rmi.registry.RegistryImpl server = (sun.rmi.registry.RegistryImpl) obj;
+ StreamRemoteCall call = (StreamRemoteCall) remoteCall;
switch (opnum) {
case 0: // bind(String, Remote)
{
@@ -90,7 +86,8 @@ public final class RegistryImpl_Skel
java.io.ObjectInput in = call.getInputStream();
$param_String_1 = (java.lang.String) in.readObject();
$param_Remote_2 = (java.rmi.Remote) in.readObject();
- } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
@@ -123,7 +120,8 @@ public final class RegistryImpl_Skel
try {
java.io.ObjectInput in = call.getInputStream();
$param_String_1 = (java.lang.String) in.readObject();
- } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
@@ -149,7 +147,8 @@ public final class RegistryImpl_Skel
java.io.ObjectInput in = call.getInputStream();
$param_String_1 = (java.lang.String) in.readObject();
$param_Remote_2 = (java.rmi.Remote) in.readObject();
- } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | java.lang.ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
@@ -172,7 +171,8 @@ public final class RegistryImpl_Skel
try {
java.io.ObjectInput in = call.getInputStream();
$param_String_1 = (java.lang.String) in.readObject();
- } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
diff --git a/src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java b/src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java
index f857486914..9f82b61331 100644
--- a/src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java
+++ b/src/share/classes/sun/rmi/registry/RegistryImpl_Stub.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -24,6 +24,11 @@
*/
package sun.rmi.registry;
+
+import java.io.IOException;
+
+import sun.rmi.transport.StreamRemoteCall;
+
/**
* Stubs to invoke RegistryImpl remote methods.
* Originally generated from RMIC but frozen to match RegistryImpl_Skel.
@@ -57,7 +62,7 @@ public final class RegistryImpl_Stub
public void bind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2)
throws java.rmi.AccessException, java.rmi.AlreadyBoundException, java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall(this, operations, 0, interfaceHash);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_String_1);
@@ -82,15 +87,14 @@ public final class RegistryImpl_Stub
public java.lang.String[] list()
throws java.rmi.AccessException, java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall(this, operations, 1, interfaceHash);
ref.invoke(call);
java.lang.String[] $result;
try {
java.io.ObjectInput in = call.getInputStream();
$result = (java.lang.String[]) in.readObject();
- } catch (java.io.IOException e) {
- throw new java.rmi.UnmarshalException("error unmarshalling return", e);
- } catch (java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling return", e);
} finally {
ref.done(call);
@@ -109,7 +113,7 @@ public final class RegistryImpl_Stub
public java.rmi.Remote lookup(java.lang.String $param_String_1)
throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 2, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall(this, operations, 2, interfaceHash);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_String_1);
@@ -121,9 +125,8 @@ public final class RegistryImpl_Stub
try {
java.io.ObjectInput in = call.getInputStream();
$result = (java.rmi.Remote) in.readObject();
- } catch (java.io.IOException e) {
- throw new java.rmi.UnmarshalException("error unmarshalling return", e);
- } catch (java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling return", e);
} finally {
ref.done(call);
@@ -144,7 +147,7 @@ public final class RegistryImpl_Stub
public void rebind(java.lang.String $param_String_1, java.rmi.Remote $param_Remote_2)
throws java.rmi.AccessException, java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 3, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall(this, operations, 3, interfaceHash);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_String_1);
@@ -167,7 +170,7 @@ public final class RegistryImpl_Stub
public void unbind(java.lang.String $param_String_1)
throws java.rmi.AccessException, java.rmi.NotBoundException, java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 4, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall(this, operations, 4, interfaceHash);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_String_1);
diff --git a/src/share/classes/sun/rmi/transport/DGCImpl_Skel.java b/src/share/classes/sun/rmi/transport/DGCImpl_Skel.java
index f991a6e053..1b413cffc1 100644
--- a/src/share/classes/sun/rmi/transport/DGCImpl_Skel.java
+++ b/src/share/classes/sun/rmi/transport/DGCImpl_Skel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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,6 +25,8 @@
package sun.rmi.transport;
+import java.io.IOException;
+
/**
* Skeleton to dispatch DGC methods.
* Originally generated by RMIC but frozen to match the stubs.
@@ -43,12 +45,13 @@ public final class DGCImpl_Skel
return operations.clone();
}
- public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall call, int opnum, long hash)
+ public void dispatch(java.rmi.Remote obj, java.rmi.server.RemoteCall remoteCall, int opnum, long hash)
throws java.lang.Exception {
if (hash != interfaceHash)
throw new java.rmi.server.SkeletonMismatchException("interface hash mismatch");
sun.rmi.transport.DGCImpl server = (sun.rmi.transport.DGCImpl) obj;
+ StreamRemoteCall call = (StreamRemoteCall) remoteCall;
switch (opnum) {
case 0: // clean(ObjID[], long, VMID, boolean)
{
@@ -62,9 +65,8 @@ public final class DGCImpl_Skel
$param_long_2 = in.readLong();
$param_VMID_3 = (java.rmi.dgc.VMID) in.readObject();
$param_boolean_4 = in.readBoolean();
- } catch (java.io.IOException e) {
- throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
- } catch (java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
@@ -88,9 +90,8 @@ public final class DGCImpl_Skel
$param_arrayOf_ObjID_1 = (java.rmi.server.ObjID[]) in.readObject();
$param_long_2 = in.readLong();
$param_Lease_3 = (java.rmi.dgc.Lease) in.readObject();
- } catch (java.io.IOException e) {
- throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
- } catch (java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling arguments", e);
} finally {
call.releaseInputStream();
diff --git a/src/share/classes/sun/rmi/transport/DGCImpl_Stub.java b/src/share/classes/sun/rmi/transport/DGCImpl_Stub.java
index 11b862c636..7c402ae83c 100644
--- a/src/share/classes/sun/rmi/transport/DGCImpl_Stub.java
+++ b/src/share/classes/sun/rmi/transport/DGCImpl_Stub.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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,16 +25,15 @@
package sun.rmi.transport;
-import java.io.ObjectInputStream;
+import sun.rmi.transport.tcp.TCPConnection;
+
+import java.io.IOException;
import java.rmi.dgc.Lease;
import java.rmi.dgc.VMID;
import java.rmi.server.UID;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import java.util.ArrayList;
import sun.misc.ObjectInputFilter;
-import sun.rmi.server.UnicastRef;
-import sun.rmi.transport.tcp.TCPConnection;
/**
* Stubs to invoke DGC remote methods.
@@ -72,7 +71,9 @@ public final class DGCImpl_Stub
public void clean(java.rmi.server.ObjID[] $param_arrayOf_ObjID_1, long $param_long_2, java.rmi.dgc.VMID $param_VMID_3, boolean $param_boolean_4)
throws java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 0, interfaceHash);
+ StreamRemoteCall call = (StreamRemoteCall)ref.newCall((java.rmi.server.RemoteObject) this,
+ operations, 0, interfaceHash);
+ call.setObjectInputFilter(DGCImpl_Stub::leaseFilter);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_arrayOf_ObjID_1);
@@ -97,7 +98,10 @@ public final class DGCImpl_Stub
public java.rmi.dgc.Lease dirty(java.rmi.server.ObjID[] $param_arrayOf_ObjID_1, long $param_long_2, java.rmi.dgc.Lease $param_Lease_3)
throws java.rmi.RemoteException {
try {
- java.rmi.server.RemoteCall call = ref.newCall((java.rmi.server.RemoteObject) this, operations, 1, interfaceHash);
+ StreamRemoteCall call =
+ (StreamRemoteCall)ref.newCall((java.rmi.server.RemoteObject) this,
+ operations, 1, interfaceHash);
+ call.setObjectInputFilter(DGCImpl_Stub::leaseFilter);
try {
java.io.ObjectOutput out = call.getOutputStream();
out.writeObject($param_arrayOf_ObjID_1);
@@ -108,26 +112,17 @@ public final class DGCImpl_Stub
}
ref.invoke(call);
java.rmi.dgc.Lease $result;
- Connection connection = ((StreamRemoteCall) call).getConnection();
+ Connection connection = call.getConnection();
try {
java.io.ObjectInput in = call.getInputStream();
- if (in instanceof ObjectInputStream) {
- /**
- * Set a filter on the stream for the return value.
- */
- ObjectInputStream ois = (ObjectInputStream) in;
- AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
- ObjectInputFilter.Config.setObjectInputFilter(ois, DGCImpl_Stub::leaseFilter);
- return null;
- });
- }
$result = (java.rmi.dgc.Lease) in.readObject();
- } catch (java.io.IOException | java.lang.ClassNotFoundException e) {
+ } catch (ClassCastException | IOException | ClassNotFoundException e) {
if (connection instanceof TCPConnection) {
// Modified to prevent re-use of the connection after an exception
((TCPConnection) connection).getChannel().free(connection, false);
}
+ call.discardPendingRefs();
throw new java.rmi.UnmarshalException("error unmarshalling return", e);
} finally {
ref.done(call);
@@ -146,6 +141,10 @@ public final class DGCImpl_Stub
* ObjectInputFilter to filter DGCClient return value (a Lease).
* The list of acceptable classes is very short and explicit.
* The depth and array sizes are limited.
+ * <p>
+ * The filter must accept normal and exception returns.
+ * A DGC server may throw exceptions that may have a cause
+ * and suppressed exceptions.
*
* @param filterInfo access to class, arrayLength, etc.
* @return {@link ObjectInputFilter.Status#ALLOWED} if allowed,
@@ -172,7 +171,16 @@ public final class DGCImpl_Stub
}
return (clazz == UID.class ||
clazz == VMID.class ||
- clazz == Lease.class)
+ clazz == Lease.class ||
+ (Throwable.class.isAssignableFrom(clazz) &&
+ clazz.getClassLoader() ==
+ Object.class.getClassLoader()) ||
+ clazz == StackTraceElement.class ||
+ clazz == ArrayList.class || // for suppressed exceptions, if any
+ clazz == Object.class ||
+ clazz.getName().equals("java.util.Collections$UnmodifiableList") ||
+ clazz.getName().equals("java.util.Collections$UnmodifiableCollection") ||
+ clazz.getName().equals("java.util.Collections$UnmodifiableRandomAccessList"))
? ObjectInputFilter.Status.ALLOWED
: ObjectInputFilter.Status.REJECTED;
}
diff --git a/src/share/classes/sun/rmi/transport/StreamRemoteCall.java b/src/share/classes/sun/rmi/transport/StreamRemoteCall.java
index d0a0ced040..cb71f7478a 100644
--- a/src/share/classes/sun/rmi/transport/StreamRemoteCall.java
+++ b/src/share/classes/sun/rmi/transport/StreamRemoteCall.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,10 @@ import java.rmi.MarshalException;
import java.rmi.UnmarshalException;
import java.rmi.server.ObjID;
import java.rmi.server.RemoteCall;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import sun.misc.ObjectInputFilter;
import sun.rmi.runtime.Log;
import sun.rmi.server.UnicastRef;
import sun.rmi.transport.tcp.TCPEndpoint;
@@ -50,6 +54,7 @@ public class StreamRemoteCall implements RemoteCall {
private ConnectionInputStream in = null;
private ConnectionOutputStream out = null;
private Connection conn;
+ private ObjectInputFilter filter = null;
private boolean resultStarted = false;
private Exception serverException = null;
@@ -123,6 +128,13 @@ public class StreamRemoteCall implements RemoteCall {
}
}
+ public void setObjectInputFilter(ObjectInputFilter filter) {
+ if (in != null) {
+ throw new IllegalStateException("set filter must occur before calling getInputStream");
+ }
+ this.filter = filter;
+ }
+
/**
* Get the InputStream the stub/skeleton should get results/arguments
* from.
@@ -132,6 +144,12 @@ public class StreamRemoteCall implements RemoteCall {
Transport.transportLog.log(Log.VERBOSE, "getting input stream");
in = new ConnectionInputStream(conn.getInputStream());
+ if (filter != null) {
+ AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+ ObjectInputFilter.Config.setObjectInputFilter(in, filter);
+ return null;
+ });
+ }
}
return in;
}
@@ -251,6 +269,7 @@ public class StreamRemoteCall implements RemoteCall {
try {
ex = in.readObject();
} catch (Exception e) {
+ discardPendingRefs();
throw new UnmarshalException("Error unmarshaling return", e);
}
@@ -259,6 +278,7 @@ public class StreamRemoteCall implements RemoteCall {
if (ex instanceof Exception) {
exceptionReceivedFromServer((Exception) ex);
} else {
+ discardPendingRefs();
throw new UnmarshalException("Return type not Exception");
}
// Exception is thrown before fallthrough can occur
diff --git a/src/share/classes/sun/security/ec/ECDHKeyAgreement.java b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
index fbb2838f62..b17d6994c2 100644
--- a/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
+++ b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, 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,14 +25,19 @@
package sun.security.ec;
+import java.math.*;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
+import java.util.Optional;
import javax.crypto.*;
import javax.crypto.spec.*;
+import sun.security.util.ArrayUtil;
import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
/**
* KeyAgreement implementation for ECDH.
@@ -44,8 +49,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
// private key, if initialized
private ECPrivateKey privateKey;
- // encoded public point, non-null between doPhase() & generateSecret() only
- private byte[] publicValue;
+ // public key, non-null between doPhase() & generateSecret() only
+ private ECPublicKey publicKey;
// length of the secret to be derived
private int secretLen;
@@ -65,7 +70,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
("Key must be instance of PrivateKey");
}
privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
- publicValue = null;
+ publicKey = null;
}
// see JCE spec
@@ -87,7 +92,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
if (privateKey == null) {
throw new IllegalStateException("Not initialized");
}
- if (publicValue != null) {
+ if (publicKey != null) {
throw new IllegalStateException("Phase already executed");
}
if (!lastPhase) {
@@ -99,40 +104,72 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
("Key must be a PublicKey with algorithm EC");
}
- ECPublicKey ecKey = (ECPublicKey)key;
- ECParameterSpec params = ecKey.getParams();
+ this.publicKey = (ECPublicKey) key;
- if (ecKey instanceof ECPublicKeyImpl) {
- publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
- } else { // instanceof ECPublicKey
- publicValue =
- ECUtil.encodePoint(ecKey.getW(), params.getCurve());
- }
+ ECParameterSpec params = publicKey.getParams();
int keyLenBits = params.getCurve().getField().getFieldSize();
secretLen = (keyLenBits + 7) >> 3;
return null;
}
- // see JCE spec
- @Override
- protected byte[] engineGenerateSecret() throws IllegalStateException {
- if ((privateKey == null) || (publicValue == null)) {
- throw new IllegalStateException("Not initialized correctly");
+ private static void validateCoordinate(BigInteger c, BigInteger mod) {
+ if (c.compareTo(BigInteger.ZERO) < 0) {
+ throw new ProviderException("invalid coordinate");
}
- byte[] s = privateKey.getS().toByteArray();
- byte[] encodedParams = // DER OID
- ECUtil.encodeECParameterSpec(null, privateKey.getParams());
+ if (c.compareTo(mod) >= 0) {
+ throw new ProviderException("invalid coordinate");
+ }
+ }
- try {
+ /*
+ * Check whether a public key is valid. Throw ProviderException
+ * if it is not valid or could not be validated.
+ */
+ private static void validate(ECOperations ops, ECPublicKey key) {
- return deriveKey(s, publicValue, encodedParams);
+ // ensure that integers are in proper range
+ BigInteger x = key.getW().getAffineX();
+ BigInteger y = key.getW().getAffineY();
- } catch (GeneralSecurityException e) {
- throw new ProviderException("Could not derive key", e);
+ BigInteger p = ops.getField().getSize();
+ validateCoordinate(x, p);
+ validateCoordinate(y, p);
+
+ // ensure the point is on the curve
+ EllipticCurve curve = key.getParams().getCurve();
+ BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
+ .multiply(x)).add(curve.getB()).mod(p);
+ BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
+ if (!rhs.equals(lhs)) {
+ throw new ProviderException("point is not on curve");
+ }
+
+ // check the order of the point
+ ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
+ ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
+ AffinePoint affP = new AffinePoint(xElem, yElem);
+ byte[] order = key.getParams().getOrder().toByteArray();
+ ArrayUtil.reverse(order);
+ Point product = ops.multiply(affP, order);
+ if (!ops.isNeutral(product)) {
+ throw new ProviderException("point has incorrect order");
+ }
+
+ }
+
+ // see JCE spec
+ @Override
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ if ((privateKey == null) || (publicKey == null)) {
+ throw new IllegalStateException("Not initialized correctly");
}
+ Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
+ return resultOpt.orElseGet(
+ () -> deriveKeyNative(privateKey, publicKey)
+ );
}
// see JCE spec
@@ -141,7 +178,8 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
offset) throws IllegalStateException, ShortBufferException {
if (offset + secretLen > sharedSecret.length) {
throw new ShortBufferException("Need " + secretLen
- + " bytes, only " + (sharedSecret.length - offset) + " available");
+ + " bytes, only " + (sharedSecret.length - offset)
+ + " available");
}
byte[] secret = engineGenerateSecret();
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
@@ -163,6 +201,78 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
}
+ private static
+ Optional<byte[]> deriveKeyImpl(ECPrivateKey priv, ECPublicKey pubKey) {
+
+ ECParameterSpec ecSpec = priv.getParams();
+ EllipticCurve curve = ecSpec.getCurve();
+ Optional<ECOperations> opsOpt = ECOperations.forParameters(ecSpec);
+ if (!opsOpt.isPresent()) {
+ return Optional.empty();
+ }
+ ECOperations ops = opsOpt.get();
+ if (! (priv instanceof ECPrivateKeyImpl)) {
+ return Optional.empty();
+ }
+ ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) priv;
+ byte[] sArr = privImpl.getArrayS();
+
+ // to match the native implementation, validate the public key here
+ // and throw ProviderException if it is invalid
+ validate(ops, pubKey);
+
+ IntegerFieldModuloP field = ops.getField();
+ // convert s array into field element and multiply by the cofactor
+ MutableIntegerModuloP scalar = field.getElement(sArr).mutable();
+ SmallValue cofactor =
+ field.getSmallValue(priv.getParams().getCofactor());
+ scalar.setProduct(cofactor);
+ int keySize = (curve.getField().getFieldSize() + 7) / 8;
+ byte[] privArr = scalar.asByteArray(keySize);
+
+ ImmutableIntegerModuloP x =
+ field.getElement(pubKey.getW().getAffineX());
+ ImmutableIntegerModuloP y =
+ field.getElement(pubKey.getW().getAffineY());
+ AffinePoint affPub = new AffinePoint(x, y);
+ Point product = ops.multiply(affPub, privArr);
+ if (ops.isNeutral(product)) {
+ throw new ProviderException("Product is zero");
+ }
+ AffinePoint affProduct = product.asAffine();
+
+ byte[] result = affProduct.getX().asByteArray(keySize);
+ ArrayUtil.reverse(result);
+
+ return Optional.of(result);
+ }
+
+ private static
+ byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
+
+ ECParameterSpec params = privateKey.getParams();
+ byte[] s = privateKey.getS().toByteArray();
+ byte[] encodedParams = // DER OID
+ ECUtil.encodeECParameterSpec(null, params);
+
+ byte[] publicValue;
+ if (publicKey instanceof ECPublicKeyImpl) {
+ ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
+ publicValue = ecPub.getEncodedPublicValue();
+ } else { // instanceof ECPublicKey
+ publicValue =
+ ECUtil.encodePoint(publicKey.getW(), params.getCurve());
+ }
+
+ try {
+ return deriveKey(s, publicValue, encodedParams);
+
+ } catch (GeneralSecurityException e) {
+ throw new ProviderException("Could not derive key", e);
+ }
+ }
+
+
/**
* Generates a secret key using the public and private keys.
*
diff --git a/src/share/classes/sun/security/ec/ECDSAOperations.java b/src/share/classes/sun/security/ec/ECDSAOperations.java
new file mode 100644
index 0000000000..3c2f9eb524
--- /dev/null
+++ b/src/share/classes/sun/security/ec/ECDSAOperations.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2018, 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.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.ArrayUtil;
+import sun.security.util.math.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
+
+import java.security.ProviderException;
+import java.security.spec.*;
+import java.util.Optional;
+
+public class ECDSAOperations {
+
+ public static class Seed {
+ private final byte[] seedValue;
+
+ public Seed(byte[] seedValue) {
+ this.seedValue = seedValue;
+ }
+
+ public byte[] getSeedValue() {
+ return seedValue;
+ }
+ }
+
+ public static class Nonce {
+ private final byte[] nonceValue;
+
+ public Nonce(byte[] nonceValue) {
+ this.nonceValue = nonceValue;
+ }
+
+ public byte[] getNonceValue() {
+ return nonceValue;
+ }
+ }
+
+ private final ECOperations ecOps;
+ private final AffinePoint basePoint;
+
+ public ECDSAOperations(ECOperations ecOps, ECPoint basePoint) {
+ this.ecOps = ecOps;
+ this.basePoint = toAffinePoint(basePoint, ecOps.getField());
+ }
+
+ public ECOperations getEcOperations() {
+ return ecOps;
+ }
+
+ public AffinePoint basePointMultiply(byte[] scalar) {
+ return ecOps.multiply(basePoint, scalar).asAffine();
+ }
+
+ public static AffinePoint toAffinePoint(ECPoint point,
+ IntegerFieldModuloP field) {
+
+ ImmutableIntegerModuloP affineX = field.getElement(point.getAffineX());
+ ImmutableIntegerModuloP affineY = field.getElement(point.getAffineY());
+ return new AffinePoint(affineX, affineY);
+ }
+
+ public static
+ Optional<ECDSAOperations> forParameters(ECParameterSpec ecParams) {
+ Optional<ECOperations> curveOps =
+ ECOperations.forParameters(ecParams);
+ return curveOps.map(
+ ops -> new ECDSAOperations(ops, ecParams.getGenerator())
+ );
+ }
+
+ /**
+ *
+ * Sign a digest using the provided private key and seed.
+ * IMPORTANT: The private key is a scalar represented using a
+ * little-endian byte array. This is backwards from the conventional
+ * representation in ECDSA. The routines that produce and consume this
+ * value uses little-endian, so this deviation from convention removes
+ * the requirement to swap the byte order. The returned signature is in
+ * the conventional byte order.
+ *
+ * @param privateKey the private key scalar as a little-endian byte array
+ * @param digest the digest to be signed
+ * @param seed the seed that will be used to produce the nonce. This object
+ * should contain an array that is at least 64 bits longer than
+ * the number of bits required to represent the group order.
+ * @return the ECDSA signature value
+ * @throws IntermediateValueException if the signature cannot be produced
+ * due to an unacceptable intermediate or final value. If this
+ * exception is thrown, then the caller should discard the nonnce and
+ * try again with an entirely new nonce value.
+ */
+ public byte[] signDigest(byte[] privateKey, byte[] digest, Seed seed)
+ throws IntermediateValueException {
+
+ byte[] nonceArr = ecOps.seedToScalar(seed.getSeedValue());
+
+ Nonce nonce = new Nonce(nonceArr);
+ return signDigest(privateKey, digest, nonce);
+ }
+
+ /**
+ *
+ * Sign a digest using the provided private key and nonce.
+ * IMPORTANT: The private key and nonce are scalars represented by a
+ * little-endian byte array. This is backwards from the conventional
+ * representation in ECDSA. The routines that produce and consume these
+ * values use little-endian, so this deviation from convention removes
+ * the requirement to swap the byte order. The returned signature is in
+ * the conventional byte order.
+ *
+ * @param privateKey the private key scalar as a little-endian byte array
+ * @param digest the digest to be signed
+ * @param nonce the nonce object containing a little-endian scalar value.
+ * @return the ECDSA signature value
+ * @throws IntermediateValueException if the signature cannot be produced
+ * due to an unacceptable intermediate or final value. If this
+ * exception is thrown, then the caller should discard the nonnce and
+ * try again with an entirely new nonce value.
+ */
+ public byte[] signDigest(byte[] privateKey, byte[] digest, Nonce nonce)
+ throws IntermediateValueException {
+
+ IntegerFieldModuloP orderField = ecOps.getOrderField();
+ int orderBits = orderField.getSize().bitLength();
+ if (orderBits % 8 != 0 && orderBits < digest.length * 8) {
+ // This implementation does not support truncating digests to
+ // a length that is not a multiple of 8.
+ throw new ProviderException("Invalid digest length");
+ }
+
+ byte[] k = nonce.getNonceValue();
+ // check nonce length
+ int length = (orderField.getSize().bitLength() + 7) / 8;
+ if (k.length != length) {
+ throw new ProviderException("Incorrect nonce length");
+ }
+
+ MutablePoint R = ecOps.multiply(basePoint, k);
+ IntegerModuloP r = R.asAffine().getX();
+ // put r into the correct field by fully reducing to an array
+ byte[] temp = new byte[length];
+ r.asByteArray(temp);
+ r = orderField.getElement(temp);
+ // store r in result
+ r.asByteArray(temp);
+ byte[] result = new byte[2 * length];
+ ArrayUtil.reverse(temp);
+ System.arraycopy(temp, 0, result, 0, length);
+ // compare r to 0
+ if (ECOperations.allZero(temp)) {
+ throw new IntermediateValueException();
+ }
+
+ IntegerModuloP dU = orderField.getElement(privateKey);
+ int lengthE = Math.min(length, digest.length);
+ byte[] E = new byte[lengthE];
+ System.arraycopy(digest, 0, E, 0, lengthE);
+ ArrayUtil.reverse(E);
+ IntegerModuloP e = orderField.getElement(E);
+ IntegerModuloP kElem = orderField.getElement(k);
+ IntegerModuloP kInv = kElem.multiplicativeInverse();
+ MutableIntegerModuloP s = r.mutable();
+ s.setProduct(dU).setSum(e).setProduct(kInv);
+ // store s in result
+ s.asByteArray(temp);
+ ArrayUtil.reverse(temp);
+ System.arraycopy(temp, 0, result, length, length);
+ // compare s to 0
+ if (ECOperations.allZero(temp)) {
+ throw new IntermediateValueException();
+ }
+
+ return result;
+
+ }
+
+}
diff --git a/src/share/classes/sun/security/ec/ECDSASignature.java b/src/share/classes/sun/security/ec/ECDSASignature.java
index ccd5a02956..03aceae374 100644
--- a/src/share/classes/sun/security/ec/ECDSASignature.java
+++ b/src/share/classes/sun/security/ec/ECDSASignature.java
@@ -32,9 +32,11 @@ import java.math.BigInteger;
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
+import java.util.Optional;
import sun.security.jca.JCAUtil;
import sun.security.util.*;
+import static sun.security.ec.ECOperations.IntermediateValueException;
/**
* ECDSA signature implementation. This class currently supports the
@@ -113,7 +115,7 @@ abstract class ECDSASignature extends SignatureSpi {
// Stores the precomputed message digest value.
@Override
protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
+ throws SignatureException {
if (offset >= precomputedDigest.length) {
offset = RAW_ECDSA_MAX + 1;
return;
@@ -138,7 +140,7 @@ abstract class ECDSASignature extends SignatureSpi {
}
@Override
- protected void resetDigest(){
+ protected void resetDigest() {
offset = 0;
}
@@ -167,7 +169,7 @@ abstract class ECDSASignature extends SignatureSpi {
// Nested class for SHA224withECDSA signatures
public static final class SHA224 extends ECDSASignature {
public SHA224() {
- super("SHA-224");
+ super("SHA-224");
}
}
@@ -195,7 +197,7 @@ abstract class ECDSASignature extends SignatureSpi {
// initialize for verification. See JCA doc
@Override
protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException {
+ throws InvalidKeyException {
this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
// Should check that the supplied key is appropriate for signature
@@ -207,14 +209,14 @@ abstract class ECDSASignature extends SignatureSpi {
// initialize for signing. See JCA doc
@Override
protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException {
+ throws InvalidKeyException {
engineInitSign(privateKey, null);
}
// initialize for signing. See JCA doc
@Override
protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
- throws InvalidKeyException {
+ throws InvalidKeyException {
this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
// Should check that the supplied key is appropriate for signature
@@ -254,7 +256,7 @@ abstract class ECDSASignature extends SignatureSpi {
// update the signature with the plaintext data. See JCA doc
@Override
protected void engineUpdate(byte[] b, int off, int len)
- throws SignatureException {
+ throws SignatureException {
messageDigest.update(b, off, len);
needsReset = true;
}
@@ -271,20 +273,67 @@ abstract class ECDSASignature extends SignatureSpi {
needsReset = true;
}
- // sign the data and return the signature. See JCA doc
- @Override
- protected byte[] engineSign() throws SignatureException {
+ private byte[] signDigestImpl(ECDSAOperations ops, int seedBits,
+ byte[] digest, ECPrivateKeyImpl privImpl, SecureRandom random)
+ throws SignatureException {
+
+ byte[] seedBytes = new byte[(seedBits + 7) / 8];
+ byte[] s = privImpl.getArrayS();
+
+ // Attempt to create the signature in a loop that uses new random input
+ // each time. The chance of failure is very small assuming the
+ // implementation derives the nonce using extra bits
+ int numAttempts = 128;
+ for (int i = 0; i < numAttempts; i++) {
+ random.nextBytes(seedBytes);
+ ECDSAOperations.Seed seed = new ECDSAOperations.Seed(seedBytes);
+ try {
+ return ops.signDigest(s, digest, seed);
+ } catch (IntermediateValueException ex) {
+ // try again in the next iteration
+ }
+ }
+
+ throw new SignatureException("Unable to produce signature after "
+ + numAttempts + " attempts");
+ }
+
+
+ private Optional<byte[]> signDigestImpl(ECPrivateKey privateKey,
+ byte[] digest, SecureRandom random) throws SignatureException {
+
+ if (! (privateKey instanceof ECPrivateKeyImpl)) {
+ return Optional.empty();
+ }
+ ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) privateKey;
+ ECParameterSpec params = privateKey.getParams();
+
+ // seed is the key size + 64 bits
+ int seedBits = params.getOrder().bitLength() + 64;
+ Optional<ECDSAOperations> opsOpt =
+ ECDSAOperations.forParameters(params);
+ if (!opsOpt.isPresent()) {
+ return Optional.empty();
+ } else {
+ byte[] sig = signDigestImpl(opsOpt.get(), seedBits, digest,
+ privImpl, random);
+ return Optional.of(sig);
+ }
+ }
+
+ private byte[] signDigestNative(ECPrivateKey privateKey, byte[] digest,
+ SecureRandom random) throws SignatureException {
+
byte[] s = privateKey.getS().toByteArray();
ECParameterSpec params = privateKey.getParams();
+
// DER OID
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
- int keySize = params.getCurve().getField().getFieldSize();
+ int orderLength = params.getOrder().bitLength();
+
+ // seed is twice the order length (in bytes) plus 1
+ byte[] seed = new byte[(((orderLength + 7) >> 3) + 1) * 2];
- // seed is twice the key size (in bytes) plus 1
- byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
- if (random == null) {
- random = JCAUtil.getSecureRandom();
- }
random.nextBytes(seed);
// random bits needed for timing countermeasures
@@ -293,14 +342,33 @@ abstract class ECDSASignature extends SignatureSpi {
timingArgument |= 1;
try {
- return encodeSignature(
- signDigest(getDigestValue(), s, encodedParams, seed,
- timingArgument));
+ return signDigest(digest, s, encodedParams, seed,
+ timingArgument);
} catch (GeneralSecurityException e) {
throw new SignatureException("Could not sign data", e);
}
}
+ // sign the data and return the signature. See JCA doc
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+
+ if (random == null) {
+ random = JCAUtil.getSecureRandom();
+ }
+
+ byte[] digest = getDigestValue();
+ Optional<byte[]> sigOpt = signDigestImpl(privateKey, digest, random);
+ byte[] sig;
+ if (sigOpt.isPresent()) {
+ sig = sigOpt.get();
+ } else {
+ sig = signDigestNative(privateKey, digest, random);
+ }
+
+ return encodeSignature(sig);
+ }
+
// verify the data and return the result. See JCA doc
@Override
protected boolean engineVerify(byte[] signature) throws SignatureException {
@@ -311,7 +379,7 @@ abstract class ECDSASignature extends SignatureSpi {
byte[] encodedParams = ECUtil.encodeECParameterSpec(null, params);
if (publicKey instanceof ECPublicKeyImpl) {
- w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
+ w = ((ECPublicKeyImpl) publicKey).getEncodedPublicValue();
} else { // instanceof ECPublicKey
w = ECUtil.encodePoint(publicKey.getW(), params.getCurve());
}
@@ -330,7 +398,7 @@ abstract class ECDSASignature extends SignatureSpi {
@Override
@Deprecated
protected void engineSetParameter(String param, Object value)
- throws InvalidParameterException {
+ throws InvalidParameterException {
throw new UnsupportedOperationException("setParameter() not supported");
}
@@ -338,7 +406,7 @@ abstract class ECDSASignature extends SignatureSpi {
@Override
@Deprecated
protected Object engineGetParameter(String param)
- throws InvalidParameterException {
+ throws InvalidParameterException {
throw new UnsupportedOperationException("getParameter() not supported");
}
@@ -358,7 +426,7 @@ abstract class ECDSASignature extends SignatureSpi {
out.putInteger(r);
out.putInteger(s);
DerValue result =
- new DerValue(DerValue.tag_Sequence, out.toByteArray());
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
return result.toByteArray();
@@ -391,9 +459,9 @@ abstract class ECDSASignature extends SignatureSpi {
// r and s each occupy half the array
byte[] result = new byte[k << 1];
System.arraycopy(rBytes, 0, result, k - rBytes.length,
- rBytes.length);
+ rBytes.length);
System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
- sBytes.length);
+ sBytes.length);
return result;
} catch (Exception e) {
@@ -433,13 +501,13 @@ abstract class ECDSASignature extends SignatureSpi {
* @return byte[] the signature.
*/
private static native byte[] signDigest(byte[] digest, byte[] s,
- byte[] encodedParams, byte[] seed, int timing)
- throws GeneralSecurityException;
+ byte[] encodedParams, byte[] seed, int timing)
+ throws GeneralSecurityException;
/**
* Verifies the signed digest using the public key.
*
- * @param signedDigest the signature to be verified. It is encoded
+ * @param signature the signature to be verified. It is encoded
* as a concatenation of the key's R and S values.
* @param digest the digest to be used.
* @param w the public key's W point (in uncompressed form).
@@ -448,6 +516,6 @@ abstract class ECDSASignature extends SignatureSpi {
* @return boolean true if the signature is successfully verified.
*/
private static native boolean verifySignedDigest(byte[] signature,
- byte[] digest, byte[] w, byte[] encodedParams)
- throws GeneralSecurityException;
+ byte[] digest, byte[] w, byte[] encodedParams)
+ throws GeneralSecurityException;
}
diff --git a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
index 72c0994664..f8eacdad33 100644
--- a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
+++ b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2018, 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,20 +25,23 @@
package sun.security.ec;
+import java.io.IOException;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Optional;
import sun.security.ec.NamedCurve;
-import sun.security.ec.ECParameters;
-import sun.security.ec.ECPrivateKeyImpl;
-import sun.security.ec.ECPublicKeyImpl;
import sun.security.jca.JCAUtil;
import sun.security.util.ECUtil;
+import sun.security.util.math.*;
+import sun.security.ec.point.*;
import static sun.security.util.SecurityProviderConstants.DEF_EC_KEY_SIZE;
+import static sun.security.ec.ECOperations.IntermediateValueException;
/**
* EC keypair generator.
@@ -86,17 +89,19 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException {
+ ECParameterSpec ecSpec = null;
+
if (params instanceof ECParameterSpec) {
- this.params = ECUtil.getECParameterSpec(null,
- (ECParameterSpec)params);
- if (this.params == null) {
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ ecSpec = ECUtil.getECParameterSpec(null, ecParams);
+ if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
"Unsupported curve: " + params);
}
} else if (params instanceof ECGenParameterSpec) {
- String name = ((ECGenParameterSpec)params).getName();
- this.params = ECUtil.getECParameterSpec(null, name);
- if (this.params == null) {
+ String name = ((ECGenParameterSpec) params).getName();
+ ecSpec = ECUtil.getECParameterSpec(null, name);
+ if (ecSpec == null) {
throw new InvalidAlgorithmParameterException(
"Unknown curve name: " + name);
}
@@ -104,48 +109,130 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
throw new InvalidAlgorithmParameterException(
"ECParameterSpec or ECGenParameterSpec required for EC");
}
- this.keySize =
- ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
+
+ // Not all known curves are supported by the native implementation
+ ensureCurveIsSupported(ecSpec);
+ this.params = ecSpec;
+
+ this.keySize = ecSpec.getCurve().getField().getFieldSize();
this.random = random;
}
+ private static void ensureCurveIsSupported(ECParameterSpec ecSpec)
+ throws InvalidAlgorithmParameterException {
+
+ AlgorithmParameters ecParams = ECUtil.getECParameters(null);
+ byte[] encodedParams;
+ try {
+ ecParams.init(ecSpec);
+ encodedParams = ecParams.getEncoded();
+ } catch (InvalidParameterSpecException ex) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported curve: " + ecSpec.toString());
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ if (!isCurveSupported(encodedParams)) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported curve: " + ecParams.toString());
+ }
+ }
+
// generate the keypair. See JCA doc
@Override
public KeyPair generateKeyPair() {
- byte[] encodedParams =
- ECUtil.encodeECParameterSpec(null, (ECParameterSpec)params);
-
- // seed is twice the key size (in bytes) plus 1
- byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
if (random == null) {
random = JCAUtil.getSecureRandom();
}
- random.nextBytes(seed);
try {
+ Optional<KeyPair> kp = generateKeyPairImpl(random);
+ if (kp.isPresent()) {
+ return kp.get();
+ }
+ return generateKeyPairNative(random);
+ } catch (Exception ex) {
+ throw new ProviderException(ex);
+ }
+ }
- Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
-
- // The 'params' object supplied above is equivalent to the native
- // one so there is no need to fetch it.
- // keyBytes[0] is the encoding of the native private key
- BigInteger s = new BigInteger(1, (byte[])keyBytes[0]);
+ private byte[] generatePrivateScalar(SecureRandom random,
+ ECOperations ecOps, int seedSize) {
+ // Attempt to create the private scalar in a loop that uses new random
+ // input each time. The chance of failure is very small assuming the
+ // implementation derives the nonce using extra bits
+ int numAttempts = 128;
+ byte[] seedArr = new byte[seedSize];
+ for (int i = 0; i < numAttempts; i++) {
+ random.nextBytes(seedArr);
+ try {
+ return ecOps.seedToScalar(seedArr);
+ } catch (IntermediateValueException ex) {
+ // try again in the next iteration
+ }
+ }
- PrivateKey privateKey =
- new ECPrivateKeyImpl(s, (ECParameterSpec)params);
+ throw new ProviderException("Unable to produce private key after "
+ + numAttempts + " attempts");
+ }
- // keyBytes[1] is the encoding of the native public key
- ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
- ((ECParameterSpec)params).getCurve());
- PublicKey publicKey =
- new ECPublicKeyImpl(w, (ECParameterSpec)params);
+ private Optional<KeyPair> generateKeyPairImpl(SecureRandom random)
+ throws InvalidKeyException {
- return new KeyPair(publicKey, privateKey);
+ ECParameterSpec ecParams = (ECParameterSpec) params;
- } catch (Exception e) {
- throw new ProviderException(e);
+ Optional<ECOperations> opsOpt = ECOperations.forParameters(ecParams);
+ if (!opsOpt.isPresent()) {
+ return Optional.empty();
}
+ ECOperations ops = opsOpt.get();
+ IntegerFieldModuloP field = ops.getField();
+ int numBits = ecParams.getOrder().bitLength();
+ int seedBits = numBits + 64;
+ int seedSize = (seedBits + 7) / 8;
+ byte[] privArr = generatePrivateScalar(random, ops, seedSize);
+
+ ECPoint genPoint = ecParams.getGenerator();
+ ImmutableIntegerModuloP x = field.getElement(genPoint.getAffineX());
+ ImmutableIntegerModuloP y = field.getElement(genPoint.getAffineY());
+ AffinePoint affGen = new AffinePoint(x, y);
+ Point pub = ops.multiply(affGen, privArr);
+ AffinePoint affPub = pub.asAffine();
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(privArr, ecParams);
+
+ ECPoint w = new ECPoint(affPub.getX().asBigInteger(),
+ affPub.getY().asBigInteger());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+ return Optional.of(new KeyPair(publicKey, privateKey));
+ }
+
+ private KeyPair generateKeyPairNative(SecureRandom random)
+ throws Exception {
+
+ ECParameterSpec ecParams = (ECParameterSpec) params;
+ byte[] encodedParams = ECUtil.encodeECParameterSpec(null, ecParams);
+
+ // seed is twice the key size (in bytes) plus 1
+ byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
+ random.nextBytes(seed);
+ Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
+
+ // The 'params' object supplied above is equivalent to the native
+ // one so there is no need to fetch it.
+ // keyBytes[0] is the encoding of the native private key
+ BigInteger s = new BigInteger(1, (byte[]) keyBytes[0]);
+
+ PrivateKey privateKey = new ECPrivateKeyImpl(s, ecParams);
+
+ // keyBytes[1] is the encoding of the native public key
+ byte[] pubKey = (byte[]) keyBytes[1];
+ ECPoint w = ECUtil.decodePoint(pubKey, ecParams.getCurve());
+ PublicKey publicKey = new ECPublicKeyImpl(w, ecParams);
+
+ return new KeyPair(publicKey, privateKey);
}
private void checkKeySize(int keySize) throws InvalidParameterException {
@@ -160,6 +247,19 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
this.keySize = keySize;
}
+ /**
+ * Checks whether the curve in the encoded parameters is supported by the
+ * native implementation. Some curve operations will be performed by the
+ * Java implementation, but not all of them. So native support is still
+ * required for all curves.
+ *
+ * @param encodedParams encoded parameters in the same form accepted
+ * by generateECKeyPair
+ * @return true if and only if generateECKeyPair will succeed for
+ * the supplied parameters
+ */
+ private static native boolean isCurveSupported(byte[] encodedParams);
+
/*
* Generates the keypair and returns a 2-element array of encoding bytes.
* The first one is for the private key, the second for the public key.
diff --git a/src/share/classes/sun/security/ec/ECOperations.java b/src/share/classes/sun/security/ec/ECOperations.java
new file mode 100644
index 0000000000..d0027f1059
--- /dev/null
+++ b/src/share/classes/sun/security/ec/ECOperations.java
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2018, 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.ec;
+
+import sun.security.ec.point.*;
+import sun.security.util.math.*;
+import sun.security.util.math.intpoly.*;
+
+import java.math.BigInteger;
+import java.security.ProviderException;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.EllipticCurve;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+/*
+ * Elliptic curve point arithmetic for prime-order curves where a=-3.
+ * Formulas are derived from "Complete addition formulas for prime order
+ * elliptic curves" by Renes, Costello, and Batina.
+ */
+
+public class ECOperations {
+
+ /*
+ * An exception indicating a problem with an intermediate value produced
+ * by some part of the computation. For example, the signing operation
+ * will throw this exception to indicate that the r or s value is 0, and
+ * that the signing operation should be tried again with a different nonce.
+ */
+ static class IntermediateValueException extends Exception {
+ private static final long serialVersionUID = 1;
+ }
+
+ static final Map<BigInteger, IntegerFieldModuloP> fields;
+
+ static final Map<BigInteger, IntegerFieldModuloP> orderFields;
+
+ static {
+ Map<BigInteger, IntegerFieldModuloP> map = new HashMap<>();
+ map.put(IntegerPolynomialP256.MODULUS, new IntegerPolynomialP256());
+ map.put(IntegerPolynomialP384.MODULUS, new IntegerPolynomialP384());
+ map.put(IntegerPolynomialP521.MODULUS, new IntegerPolynomialP521());
+ fields = Collections.unmodifiableMap(map);
+ map = new HashMap<>();
+ map.put(P256OrderField.MODULUS, new P256OrderField());
+ map.put(P384OrderField.MODULUS, new P384OrderField());
+ map.put(P521OrderField.MODULUS, new P521OrderField());
+ orderFields = Collections.unmodifiableMap(map);
+ }
+
+ public static Optional<ECOperations> forParameters(ECParameterSpec params) {
+
+ EllipticCurve curve = params.getCurve();
+ if (!(curve.getField() instanceof ECFieldFp)) {
+ return Optional.empty();
+ }
+ ECFieldFp primeField = (ECFieldFp) curve.getField();
+
+ BigInteger three = BigInteger.valueOf(3);
+ if (!primeField.getP().subtract(curve.getA()).equals(three)) {
+ return Optional.empty();
+ }
+ IntegerFieldModuloP field = fields.get(primeField.getP());
+ if (field == null) {
+ return Optional.empty();
+ }
+
+ IntegerFieldModuloP orderField = orderFields.get(params.getOrder());
+ if (orderField == null) {
+ return Optional.empty();
+ }
+
+ ImmutableIntegerModuloP b = field.getElement(curve.getB());
+ ECOperations ecOps = new ECOperations(b, orderField);
+ return Optional.of(ecOps);
+ }
+
+ final ImmutableIntegerModuloP b;
+ final SmallValue one;
+ final SmallValue two;
+ final SmallValue three;
+ final SmallValue four;
+ final ProjectivePoint.Immutable neutral;
+ private final IntegerFieldModuloP orderField;
+
+ public ECOperations(IntegerModuloP b, IntegerFieldModuloP orderField) {
+ this.b = b.fixed();
+ this.orderField = orderField;
+
+ this.one = b.getField().getSmallValue(1);
+ this.two = b.getField().getSmallValue(2);
+ this.three = b.getField().getSmallValue(3);
+ this.four = b.getField().getSmallValue(4);
+
+ IntegerFieldModuloP field = b.getField();
+ this.neutral = new ProjectivePoint.Immutable(field.get0(),
+ field.get1(), field.get0());
+ }
+
+ public IntegerFieldModuloP getField() {
+ return b.getField();
+ }
+ public IntegerFieldModuloP getOrderField() {
+ return orderField;
+ }
+
+ protected ProjectivePoint.Immutable getNeutral() {
+ return neutral;
+ }
+
+ public boolean isNeutral(Point p) {
+ ProjectivePoint<?> pp = (ProjectivePoint<?>) p;
+
+ IntegerModuloP z = pp.getZ();
+
+ IntegerFieldModuloP field = z.getField();
+ int byteLength = (field.getSize().bitLength() + 7) / 8;
+ byte[] zBytes = z.asByteArray(byteLength);
+ return allZero(zBytes);
+ }
+
+ byte[] seedToScalar(byte[] seedBytes)
+ throws IntermediateValueException {
+
+ // Produce a nonce from the seed using FIPS 186-4,section B.5.1:
+ // Per-Message Secret Number Generation Using Extra Random Bits
+ // or
+ // Produce a scalar from the seed using FIPS 186-4, section B.4.1:
+ // Key Pair Generation Using Extra Random Bits
+
+ // To keep the implementation simple, sample in the range [0,n)
+ // and throw IntermediateValueException in the (unlikely) event
+ // that the result is 0.
+
+ // Get 64 extra bits and reduce in to the nonce
+ int seedBits = orderField.getSize().bitLength() + 64;
+ if (seedBytes.length * 8 < seedBits) {
+ throw new ProviderException("Incorrect seed length: " +
+ seedBytes.length * 8 + " < " + seedBits);
+ }
+
+ // input conversion only works on byte boundaries
+ // clear high-order bits of last byte so they don't influence nonce
+ int lastByteBits = seedBits % 8;
+ if (lastByteBits != 0) {
+ int lastByteIndex = seedBits / 8;
+ byte mask = (byte) (0xFF >>> (8 - lastByteBits));
+ seedBytes[lastByteIndex] &= mask;
+ }
+
+ int seedLength = (seedBits + 7) / 8;
+ IntegerModuloP scalarElem =
+ orderField.getElement(seedBytes, 0, seedLength, (byte) 0);
+ int scalarLength = (orderField.getSize().bitLength() + 7) / 8;
+ byte[] scalarArr = new byte[scalarLength];
+ scalarElem.asByteArray(scalarArr);
+ if (ECOperations.allZero(scalarArr)) {
+ throw new IntermediateValueException();
+ }
+ return scalarArr;
+ }
+
+ /*
+ * Compare all values in the array to 0 without branching on any value
+ *
+ */
+ public static boolean allZero(byte[] arr) {
+ byte acc = 0;
+ for (int i = 0; i < arr.length; i++) {
+ acc |= arr[i];
+ }
+ return acc == 0;
+ }
+
+ /*
+ * 4-bit branchless array lookup for projective points.
+ */
+ private void lookup4(ProjectivePoint.Immutable[] arr, int index,
+ ProjectivePoint.Mutable result, IntegerModuloP zero) {
+
+ for (int i = 0; i < 16; i++) {
+ int xor = index ^ i;
+ int bit3 = (xor & 0x8) >>> 3;
+ int bit2 = (xor & 0x4) >>> 2;
+ int bit1 = (xor & 0x2) >>> 1;
+ int bit0 = (xor & 0x1);
+ int inverse = bit0 | bit1 | bit2 | bit3;
+ int set = 1 - inverse;
+
+ ProjectivePoint.Immutable pi = arr[i];
+ result.conditionalSet(pi, set);
+ }
+ }
+
+ private void double4(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+ MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+ MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+ for (int i = 0; i < 4; i++) {
+ setDouble(p, t0, t1, t2, t3, t4);
+ }
+ }
+
+ /**
+ * Multiply an affine point by a scalar and return the result as a mutable
+ * point.
+ *
+ * @param affineP the point
+ * @param s the scalar as a little-endian array
+ * @return the product
+ */
+ public MutablePoint multiply(AffinePoint affineP, byte[] s) {
+
+ // 4-bit windowed multiply with branchless lookup.
+ // The mixed addition is faster, so it is used to construct the array
+ // at the beginning of the operation.
+
+ IntegerFieldModuloP field = affineP.getX().getField();
+ ImmutableIntegerModuloP zero = field.get0();
+ // temporaries
+ MutableIntegerModuloP t0 = zero.mutable();
+ MutableIntegerModuloP t1 = zero.mutable();
+ MutableIntegerModuloP t2 = zero.mutable();
+ MutableIntegerModuloP t3 = zero.mutable();
+ MutableIntegerModuloP t4 = zero.mutable();
+
+ ProjectivePoint.Mutable result = new ProjectivePoint.Mutable(field);
+ result.getY().setValue(field.get1().mutable());
+
+ ProjectivePoint.Immutable[] pointMultiples =
+ new ProjectivePoint.Immutable[16];
+ // 0P is neutral---same as initial result value
+ pointMultiples[0] = result.fixed();
+
+ ProjectivePoint.Mutable ps = new ProjectivePoint.Mutable(field);
+ ps.setValue(affineP);
+ // 1P = P
+ pointMultiples[1] = ps.fixed();
+
+ // the rest are calculated using mixed point addition
+ for (int i = 2; i < 16; i++) {
+ setSum(ps, affineP, t0, t1, t2, t3, t4);
+ pointMultiples[i] = ps.fixed();
+ }
+
+ ProjectivePoint.Mutable lookupResult = ps.mutable();
+
+ for (int i = s.length - 1; i >= 0; i--) {
+
+ double4(result, t0, t1, t2, t3, t4);
+
+ int high = (0xFF & s[i]) >>> 4;
+ lookup4(pointMultiples, high, lookupResult, zero);
+ setSum(result, lookupResult, t0, t1, t2, t3, t4);
+
+ double4(result, t0, t1, t2, t3, t4);
+
+ int low = 0xF & s[i];
+ lookup4(pointMultiples, low, lookupResult, zero);
+ setSum(result, lookupResult, t0, t1, t2, t3, t4);
+ }
+
+ return result;
+
+ }
+
+ /*
+ * Point double
+ */
+ private void setDouble(ProjectivePoint.Mutable p, MutableIntegerModuloP t0,
+ MutableIntegerModuloP t1, MutableIntegerModuloP t2,
+ MutableIntegerModuloP t3, MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setSquare();
+ t1.setValue(p.getY()).setSquare();
+ t2.setValue(p.getZ()).setSquare();
+ t3.setValue(p.getX()).setProduct(p.getY());
+ t4.setValue(p.getY()).setProduct(p.getZ());
+
+ t3.setSum(t3);
+ p.getZ().setProduct(p.getX());
+
+ p.getZ().setProduct(two);
+
+ p.getY().setValue(t2).setProduct(b);
+ p.getY().setDifference(p.getZ());
+
+ p.getX().setValue(p.getY()).setProduct(two);
+ p.getY().setSum(p.getX());
+ p.getY().setReduced();
+ p.getX().setValue(t1).setDifference(p.getY());
+
+ p.getY().setSum(t1);
+ p.getY().setProduct(p.getX());
+ p.getX().setProduct(t3);
+
+ t3.setValue(t2).setProduct(two);
+ t2.setSum(t3);
+ p.getZ().setProduct(b);
+
+ t2.setReduced();
+ p.getZ().setDifference(t2);
+ p.getZ().setDifference(t0);
+ t3.setValue(p.getZ()).setProduct(two);
+ p.getZ().setReduced();
+ p.getZ().setSum(t3);
+ t0.setProduct(three);
+
+ t0.setDifference(t2);
+ t0.setProduct(p.getZ());
+ p.getY().setSum(t0);
+
+ t4.setSum(t4);
+ p.getZ().setProduct(t4);
+
+ p.getX().setDifference(p.getZ());
+ p.getZ().setValue(t4).setProduct(t1);
+
+ p.getZ().setProduct(four);
+
+ }
+
+ /*
+ * Mixed point addition. This method constructs new temporaries each time
+ * it is called. For better efficiency, the method that reuses temporaries
+ * should be used if more than one sum will be computed.
+ */
+ public void setSum(MutablePoint p, AffinePoint p2) {
+
+ IntegerModuloP zero = p.getField().get0();
+ MutableIntegerModuloP t0 = zero.mutable();
+ MutableIntegerModuloP t1 = zero.mutable();
+ MutableIntegerModuloP t2 = zero.mutable();
+ MutableIntegerModuloP t3 = zero.mutable();
+ MutableIntegerModuloP t4 = zero.mutable();
+ setSum((ProjectivePoint.Mutable) p, p2, t0, t1, t2, t3, t4);
+
+ }
+
+ /*
+ * Mixed point addition
+ */
+ private void setSum(ProjectivePoint.Mutable p, AffinePoint p2,
+ MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+ MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+ MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setProduct(p2.getX());
+ t1.setValue(p.getY()).setProduct(p2.getY());
+ t3.setValue(p2.getX()).setSum(p2.getY());
+ t4.setValue(p.getX()).setSum(p.getY());
+ p.getX().setReduced();
+ t3.setProduct(t4);
+ t4.setValue(t0).setSum(t1);
+
+ t3.setDifference(t4);
+ t4.setValue(p2.getY()).setProduct(p.getZ());
+ t4.setSum(p.getY());
+
+ p.getY().setValue(p2.getX()).setProduct(p.getZ());
+ p.getY().setSum(p.getX());
+ t2.setValue(p.getZ());
+ p.getZ().setProduct(b);
+
+ p.getX().setValue(p.getY()).setDifference(p.getZ());
+ p.getX().setReduced();
+ p.getZ().setValue(p.getX()).setProduct(two);
+ p.getX().setSum(p.getZ());
+
+ p.getZ().setValue(t1).setDifference(p.getX());
+ p.getX().setSum(t1);
+ p.getY().setProduct(b);
+
+ t1.setValue(t2).setProduct(two);
+ t2.setSum(t1);
+ t2.setReduced();
+ p.getY().setDifference(t2);
+
+ p.getY().setDifference(t0);
+ p.getY().setReduced();
+ t1.setValue(p.getY()).setProduct(two);
+ p.getY().setSum(t1);
+
+ t1.setValue(t0).setProduct(two);
+ t0.setSum(t1);
+ t0.setDifference(t2);
+
+ t1.setValue(t4).setProduct(p.getY());
+ t2.setValue(t0).setProduct(p.getY());
+ p.getY().setValue(p.getX()).setProduct(p.getZ());
+
+ p.getY().setSum(t2);
+ p.getX().setProduct(t3);
+ p.getX().setDifference(t1);
+
+ p.getZ().setProduct(t4);
+ t1.setValue(t3).setProduct(t0);
+ p.getZ().setSum(t1);
+
+ }
+
+ /*
+ * Projective point addition
+ */
+ private void setSum(ProjectivePoint.Mutable p, ProjectivePoint.Mutable p2,
+ MutableIntegerModuloP t0, MutableIntegerModuloP t1,
+ MutableIntegerModuloP t2, MutableIntegerModuloP t3,
+ MutableIntegerModuloP t4) {
+
+ t0.setValue(p.getX()).setProduct(p2.getX());
+ t1.setValue(p.getY()).setProduct(p2.getY());
+ t2.setValue(p.getZ()).setProduct(p2.getZ());
+
+ t3.setValue(p.getX()).setSum(p.getY());
+ t4.setValue(p2.getX()).setSum(p2.getY());
+ t3.setProduct(t4);
+
+ t4.setValue(t0).setSum(t1);
+ t3.setDifference(t4);
+ t4.setValue(p.getY()).setSum(p.getZ());
+
+ p.getY().setValue(p2.getY()).setSum(p2.getZ());
+ t4.setProduct(p.getY());
+ p.getY().setValue(t1).setSum(t2);
+
+ t4.setDifference(p.getY());
+ p.getX().setSum(p.getZ());
+ p.getY().setValue(p2.getX()).setSum(p2.getZ());
+
+ p.getX().setProduct(p.getY());
+ p.getY().setValue(t0).setSum(t2);
+ p.getY().setAdditiveInverse().setSum(p.getX());
+ p.getY().setReduced();
+
+ p.getZ().setValue(t2).setProduct(b);
+ p.getX().setValue(p.getY()).setDifference(p.getZ());
+ p.getZ().setValue(p.getX()).setProduct(two);
+
+ p.getX().setSum(p.getZ());
+ p.getX().setReduced();
+ p.getZ().setValue(t1).setDifference(p.getX());
+ p.getX().setSum(t1);
+
+ p.getY().setProduct(b);
+ t1.setValue(t2).setSum(t2);
+ t2.setSum(t1);
+ t2.setReduced();
+
+ p.getY().setDifference(t2);
+ p.getY().setDifference(t0);
+ p.getY().setReduced();
+ t1.setValue(p.getY()).setSum(p.getY());
+
+ p.getY().setSum(t1);
+ t1.setValue(t0).setProduct(two);
+ t0.setSum(t1);
+
+ t0.setDifference(t2);
+ t1.setValue(t4).setProduct(p.getY());
+ t2.setValue(t0).setProduct(p.getY());
+
+ p.getY().setValue(p.getX()).setProduct(p.getZ());
+ p.getY().setSum(t2);
+ p.getX().setProduct(t3);
+
+ p.getX().setDifference(t1);
+ p.getZ().setProduct(t4);
+ t1.setValue(t3).setProduct(t0);
+
+ p.getZ().setSum(t1);
+
+ }
+}
diff --git a/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java b/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java
index 552a15d82e..bb12cb8283 100644
--- a/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java
+++ b/src/share/classes/sun/security/ec/ECPrivateKeyImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -64,6 +64,7 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
private static final long serialVersionUID = 88695385615075129L;
private BigInteger s; // private value
+ private byte[] arrayS; // private value as a little-endian array
private ECParameterSpec params;
/**
@@ -81,13 +82,25 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
throws InvalidKeyException {
this.s = s;
this.params = params;
- // generate the encoding
+ makeEncoding(s);
+
+ }
+
+ ECPrivateKeyImpl(byte[] s, ECParameterSpec params)
+ throws InvalidKeyException {
+ this.arrayS = s.clone();
+ this.params = params;
+ makeEncoding(s);
+ }
+
+ private void makeEncoding(byte[] s) throws InvalidKeyException {
algid = new AlgorithmId
- (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+ (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
try {
DerOutputStream out = new DerOutputStream();
out.putInteger(1); // version 1
- byte[] privBytes = ECUtil.trimZeroes(s.toByteArray());
+ byte[] privBytes = s.clone();
+ ArrayUtil.reverse(privBytes);
out.putOctetString(privBytes);
DerValue val =
new DerValue(DerValue.tag_Sequence, out.toByteArray());
@@ -98,6 +111,31 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
}
}
+ private void makeEncoding(BigInteger s) throws InvalidKeyException {
+ algid = new AlgorithmId
+ (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params));
+ try {
+ byte[] sArr = s.toByteArray();
+ // convert to fixed-length array
+ int numOctets = (params.getOrder().bitLength() + 7) / 8;
+ byte[] sOctets = new byte[numOctets];
+ int inPos = Math.max(sArr.length - sOctets.length, 0);
+ int outPos = Math.max(sOctets.length - sArr.length, 0);
+ int length = Math.min(sArr.length, sOctets.length);
+ System.arraycopy(sArr, inPos, sOctets, outPos, length);
+
+ DerOutputStream out = new DerOutputStream();
+ out.putInteger(1); // version 1
+ out.putOctetString(sOctets);
+ DerValue val =
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
+ key = val.toByteArray();
+ } catch (IOException exc) {
+ // should never occur
+ throw new InvalidKeyException(exc);
+ }
+ }
+
// see JCA doc
public String getAlgorithm() {
return "EC";
@@ -105,9 +143,26 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
// see JCA doc
public BigInteger getS() {
+ if (s == null) {
+ byte[] arrCopy = arrayS.clone();
+ ArrayUtil.reverse(arrCopy);
+ s = new BigInteger(1, arrCopy);
+ }
return s;
}
+ public byte[] getArrayS() {
+ if (arrayS == null) {
+ byte[] arr = getS().toByteArray();
+ ArrayUtil.reverse(arr);
+ int byteLength = (params.getOrder().bitLength() + 7) / 8;
+ arrayS = new byte[byteLength];
+ int length = Math.min(byteLength, arr.length);
+ System.arraycopy(arr, 0, arrayS, 0, length);
+ }
+ return arrayS.clone();
+ }
+
// see JCA doc
public ECParameterSpec getParams() {
return params;
@@ -129,12 +184,13 @@ public final class ECPrivateKeyImpl extends PKCS8Key implements ECPrivateKey {
throw new IOException("Version must be 1");
}
byte[] privData = data.getOctetString();
- s = new BigInteger(1, privData);
+ ArrayUtil.reverse(privData);
+ arrayS = privData;
while (data.available() != 0) {
DerValue value = data.getDerValue();
- if (value.isContextSpecific((byte)0)) {
+ if (value.isContextSpecific((byte) 0)) {
// ignore for now
- } else if (value.isContextSpecific((byte)1)) {
+ } else if (value.isContextSpecific((byte) 1)) {
// ignore for now
} else {
throw new InvalidKeyException("Unexpected value: " + value);
diff --git a/src/share/classes/sun/security/ec/point/AffinePoint.java b/src/share/classes/sun/security/ec/point/AffinePoint.java
new file mode 100644
index 0000000000..a8b74bdd4c
--- /dev/null
+++ b/src/share/classes/sun/security/ec/point/AffinePoint.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2018, 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.ec.point;
+
+import sun.security.util.math.ImmutableIntegerModuloP;
+
+import java.util.Objects;
+
+/**
+ * Elliptic curve point represented using affine coordinates (x, y). This class
+ * is not part of the sun.security.ec.point.Point hierarchy because it is not
+ * used to hold intermediate values during point arithmetic, and so it does not
+ * have a mutable form.
+ */
+public class AffinePoint {
+
+ private final ImmutableIntegerModuloP x;
+ private final ImmutableIntegerModuloP y;
+
+ public AffinePoint(ImmutableIntegerModuloP x, ImmutableIntegerModuloP y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public ImmutableIntegerModuloP getX() {
+ return x;
+ }
+
+ public ImmutableIntegerModuloP getY() {
+ return y;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof AffinePoint)) {
+ return false;
+ }
+ AffinePoint p = (AffinePoint) obj;
+ boolean xEquals = x.asBigInteger().equals(p.x.asBigInteger());
+ boolean yEquals = y.asBigInteger().equals(p.y.asBigInteger());
+ return xEquals && yEquals;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + x.asBigInteger().toString() + "," +
+ y.asBigInteger().toString() + ")";
+ }
+}
diff --git a/src/share/classes/sun/security/ec/point/ImmutablePoint.java b/src/share/classes/sun/security/ec/point/ImmutablePoint.java
new file mode 100644
index 0000000000..7f6c6b3059
--- /dev/null
+++ b/src/share/classes/sun/security/ec/point/ImmutablePoint.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2018, 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.ec.point;
+
+/**
+ * An interface for immutable points on an elliptic curve over a finite field.
+ */
+public interface ImmutablePoint extends Point {
+}
diff --git a/src/share/classes/sun/security/ec/point/MutablePoint.java b/src/share/classes/sun/security/ec/point/MutablePoint.java
new file mode 100644
index 0000000000..cb714ac5a0
--- /dev/null
+++ b/src/share/classes/sun/security/ec/point/MutablePoint.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018, 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.ec.point;
+
+/**
+ * An interface for mutable points on an elliptic curve over a finite field.
+ */
+public interface MutablePoint extends Point {
+
+ MutablePoint setValue(AffinePoint p);
+ MutablePoint setValue(Point p);
+ MutablePoint conditionalSet(Point p, int set);
+
+}
diff --git a/src/share/classes/sun/security/ec/point/Point.java b/src/share/classes/sun/security/ec/point/Point.java
new file mode 100644
index 0000000000..b28bd9df73
--- /dev/null
+++ b/src/share/classes/sun/security/ec/point/Point.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, 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.ec.point;
+
+import sun.security.util.math.IntegerFieldModuloP;
+
+/**
+ * A base interface for points on an elliptic curve over a finite field.
+ * Implementations may use different representations for points, and this
+ * interface creates a common API for manipulating points. This API has no
+ * methods for point arithmetic, which depends on group structure and curve
+ * parameters in addition to point representation.
+ */
+public interface Point {
+
+ IntegerFieldModuloP getField();
+ AffinePoint asAffine();
+
+ ImmutablePoint fixed();
+ MutablePoint mutable();
+
+}
diff --git a/src/share/classes/sun/security/ec/point/ProjectivePoint.java b/src/share/classes/sun/security/ec/point/ProjectivePoint.java
new file mode 100644
index 0000000000..587f1c72b3
--- /dev/null
+++ b/src/share/classes/sun/security/ec/point/ProjectivePoint.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2018, 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.ec.point;
+
+import sun.security.util.math.*;
+
+/**
+ * Elliptic curve point in projective coordinates (X, Y, Z) where
+ * an affine point (x, y) is represented using any (X, Y, Z) s.t.
+ * x = X/Z and y = Y/Z.
+ */
+public abstract class ProjectivePoint
+ <T extends IntegerModuloP> implements Point {
+
+ protected final T x;
+ protected final T y;
+ protected final T z;
+
+ protected ProjectivePoint(T x, T y, T z) {
+
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ @Override
+ public IntegerFieldModuloP getField() {
+ return this.x.getField();
+ }
+
+ @Override
+ public Immutable fixed() {
+ return new Immutable(x.fixed(), y.fixed(), z.fixed());
+ }
+
+ @Override
+ public Mutable mutable() {
+ return new Mutable(x.mutable(), y.mutable(), z.mutable());
+ }
+
+ public T getX() {
+ return x;
+ }
+
+ public T getY() {
+ return y;
+ }
+
+ public T getZ() {
+ return z;
+ }
+
+ public AffinePoint asAffine() {
+ IntegerModuloP zInv = z.multiplicativeInverse();
+ return new AffinePoint(x.multiply(zInv), y.multiply(zInv));
+ }
+
+ public static class Immutable
+ extends ProjectivePoint<ImmutableIntegerModuloP>
+ implements ImmutablePoint {
+
+ public Immutable(ImmutableIntegerModuloP x,
+ ImmutableIntegerModuloP y,
+ ImmutableIntegerModuloP z) {
+ super(x, y, z);
+ }
+ }
+
+ public static class Mutable
+ extends ProjectivePoint<MutableIntegerModuloP>
+ implements MutablePoint {
+
+ public Mutable(MutableIntegerModuloP x,
+ MutableIntegerModuloP y,
+ MutableIntegerModuloP z) {
+ super(x, y, z);
+ }
+
+ public Mutable(IntegerFieldModuloP field) {
+ super(field.get0().mutable(),
+ field.get0().mutable(),
+ field.get0().mutable());
+ }
+
+ @Override
+ public Mutable conditionalSet(Point p, int set) {
+ if (!(p instanceof ProjectivePoint)) {
+ throw new RuntimeException("Incompatible point");
+ }
+ @SuppressWarnings("unchecked")
+ ProjectivePoint<IntegerModuloP> pp =
+ (ProjectivePoint<IntegerModuloP>) p;
+ return conditionalSet(pp, set);
+ }
+
+ private <T extends IntegerModuloP>
+ Mutable conditionalSet(ProjectivePoint<T> pp, int set) {
+
+ x.conditionalSet(pp.x, set);
+ y.conditionalSet(pp.y, set);
+ z.conditionalSet(pp.z, set);
+
+ return this;
+ }
+
+ @Override
+ public Mutable setValue(AffinePoint p) {
+ x.setValue(p.getX());
+ y.setValue(p.getY());
+ z.setValue(p.getX().getField().get1());
+
+ return this;
+ }
+
+ @Override
+ public Mutable setValue(Point p) {
+ if (!(p instanceof ProjectivePoint)) {
+ throw new RuntimeException("Incompatible point");
+ }
+ @SuppressWarnings("unchecked")
+ ProjectivePoint<IntegerModuloP> pp =
+ (ProjectivePoint<IntegerModuloP>) p;
+ return setValue(pp);
+ }
+
+ private <T extends IntegerModuloP>
+ Mutable setValue(ProjectivePoint<T> pp) {
+
+ x.setValue(pp.x);
+ y.setValue(pp.y);
+ z.setValue(pp.z);
+
+ return this;
+ }
+
+ }
+
+}
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5Context.java b/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
index e7c9d6f397..a0658d0eac 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5Context.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -614,6 +614,8 @@ class Krb5Context implements GSSContextSpi {
if (myCred == null) {
myCred = Krb5InitCredential.getInstance(caller, myName,
GSSCredential.DEFAULT_LIFETIME);
+ myCred = Krb5ProxyCredential.tryImpersonation(
+ caller, (Krb5InitCredential)myCred);
} else if (!myCred.isInitiatorCredential()) {
throw new GSSException(errorCode, -1,
"No TGT available");
@@ -651,8 +653,8 @@ class Krb5Context implements GSSContextSpi {
// highly consider just calling:
// Subject.getSubject
// SubjectComber.find
- // instead of Krb5Util.getTicket
- return Krb5Util.getTicket(
+ // instead of Krb5Util.getServiceTicket
+ return Krb5Util.getServiceTicket(
GSSCaller.CALLER_UNKNOWN,
// since it's useSubjectCredsOnly here,
// don't worry about the null
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java b/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java
index cdfbe172ee..daefbbcbda 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5InitCredential.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -55,6 +55,7 @@ public class Krb5InitCredential
private Krb5NameElement name;
private Credentials krb5Credentials;
+ public KerberosTicket proxyTicket;
private Krb5InitCredential(Krb5NameElement name,
byte[] asn1Encoding,
@@ -153,7 +154,7 @@ public class Krb5InitCredential
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
}
- return new Krb5InitCredential(name,
+ Krb5InitCredential result = new Krb5InitCredential(name,
tgt.getEncoded(),
tgt.getClient(),
tgt.getServer(),
@@ -165,6 +166,9 @@ public class Krb5InitCredential
tgt.getEndTime(),
tgt.getRenewTill(),
tgt.getClientAddresses());
+ result.proxyTicket = KerberosSecrets.getJavaxSecurityAuthKerberosAccess().
+ kerberosTicketGetProxy(tgt);
+ return result;
}
static Krb5InitCredential getInstance(Krb5NameElement name,
@@ -334,9 +338,9 @@ public class Krb5InitCredential
public KerberosTicket run() throws Exception {
// It's OK to use null as serverPrincipal. TGT is almost
// the first ticket for a principal and we use list.
- return Krb5Util.getTicket(
+ return Krb5Util.getInitialTicket(
realCaller,
- clientPrincipal, null, acc);
+ clientPrincipal, acc);
}});
} catch (PrivilegedActionException e) {
GSSException ge =
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java b/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java
index ffae2cdc2f..4c6f839b19 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5MechFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -120,6 +120,8 @@ public final class Krb5MechFactory implements MechanismFactory {
usage == GSSCredential.INITIATE_AND_ACCEPT) {
credElement = Krb5InitCredential.getInstance
(caller, (Krb5NameElement) name, initLifetime);
+ credElement = Krb5ProxyCredential.tryImpersonation(
+ caller, (Krb5InitCredential)credElement);
checkInitCredPermission
((Krb5NameElement) credElement.getName());
} else if (usage == GSSCredential.ACCEPT_ONLY) {
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java b/src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java
index 8d2c1af99c..37d0b77bbb 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5NameElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -144,7 +144,7 @@ public class Krb5NameElement
return new Krb5NameElement(principalName, gssNameStr, gssNameType);
}
- static Krb5NameElement getInstance(PrincipalName principalName) {
+ public static Krb5NameElement getInstance(PrincipalName principalName) {
return new Krb5NameElement(principalName,
principalName.getName(),
Krb5MechFactory.NT_GSS_KRB5_PRINCIPAL);
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java b/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java
index 4c5690b394..8fbe93a576 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5ProxyCredential.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -26,10 +26,17 @@
package sun.security.jgss.krb5;
import org.ietf.jgss.*;
+import sun.security.jgss.GSSCaller;
import sun.security.jgss.spi.*;
-import java.util.Date;
+
+import java.io.IOException;
+
+import sun.security.krb5.Credentials;
+import sun.security.krb5.KrbException;
import sun.security.krb5.internal.Ticket;
+import javax.security.auth.kerberos.KerberosTicket;
+
/**
* Implements the krb5 proxy credential element used in constrained
* delegation. It is used in both impersonation (where there is no Kerberos 5
@@ -112,4 +119,24 @@ public class Krb5ProxyCredential
throw new GSSException(GSSException.FAILURE, -1,
"Only an initiate credentials can impersonate");
}
+
+ // Try to see if a default credential should act as an impersonator.
+ static Krb5CredElement tryImpersonation(GSSCaller caller,
+ Krb5InitCredential initiator) throws GSSException {
+
+ try {
+ KerberosTicket proxy = initiator.proxyTicket;
+ if (proxy != null) {
+ Credentials proxyCreds = Krb5Util.ticketToCreds(proxy);
+ return new Krb5ProxyCredential(initiator,
+ Krb5NameElement.getInstance(proxyCreds.getClient()),
+ proxyCreds.getTicket());
+ } else {
+ return initiator;
+ }
+ } catch (KrbException | IOException e) {
+ throw new GSSException(GSSException.DEFECTIVE_CREDENTIAL, -1,
+ "Cannot create proxy credential");
+ }
+ }
}
diff --git a/src/share/classes/sun/security/jgss/krb5/Krb5Util.java b/src/share/classes/sun/security/jgss/krb5/Krb5Util.java
index 31b54b7255..8f79df1e67 100644
--- a/src/share/classes/sun/security/jgss/krb5/Krb5Util.java
+++ b/src/share/classes/sun/security/jgss/krb5/Krb5Util.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -139,11 +139,8 @@ public class Krb5Util {
/**
* Retrieves the ticket corresponding to the client/server principal
* pair from the Subject in the specified AccessControlContext.
- * If the ticket can not be found in the Subject, and if
- * useSubjectCredsOnly is false, then obtain ticket from
- * a LoginContext.
*/
- static KerberosTicket getTicket(GSSCaller caller,
+ static KerberosTicket getServiceTicket(GSSCaller caller,
String clientPrincipal, String serverPrincipal,
AccessControlContext acc) throws LoginException {
@@ -153,11 +150,31 @@ public class Krb5Util {
SubjectComber.find(accSubj, serverPrincipal, clientPrincipal,
KerberosTicket.class);
+ return ticket;
+ }
+
+ /**
+ * Retrieves the initial TGT corresponding to the client principal
+ * from the Subject in the specified AccessControlContext.
+ * If the ticket can not be found in the Subject, and if
+ * useSubjectCredsOnly is false, then obtain ticket from
+ * a LoginContext.
+ */
+ static KerberosTicket getInitialTicket(GSSCaller caller,
+ String clientPrincipal,
+ AccessControlContext acc) throws LoginException {
+
+ // Try to get ticket from acc's Subject
+ Subject accSubj = Subject.getSubject(acc);
+ KerberosTicket ticket =
+ SubjectComber.find(accSubj, null, clientPrincipal,
+ KerberosTicket.class);
+
// Try to get ticket from Subject obtained from GSSUtil
if (ticket == null && !GSSUtil.useSubjectCredsOnly(caller)) {
Subject subject = GSSUtil.login(caller, GSSUtil.GSS_KRB5_MECH_OID);
ticket = SubjectComber.find(subject,
- serverPrincipal, clientPrincipal, KerberosTicket.class);
+ null, clientPrincipal, KerberosTicket.class);
}
return ticket;
}
diff --git a/src/share/classes/sun/security/krb5/Credentials.java b/src/share/classes/sun/security/krb5/Credentials.java
index 80095ac94d..3fe2953071 100644
--- a/src/share/classes/sun/security/krb5/Credentials.java
+++ b/src/share/classes/sun/security/krb5/Credentials.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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,13 +56,23 @@ public class Credentials {
KerberosTime endTime;
KerberosTime renewTill;
HostAddresses cAddr;
- EncryptionKey serviceKey;
AuthorizationData authzData;
private static boolean DEBUG = Krb5.DEBUG;
private static CredentialsCache cache;
static boolean alreadyLoaded = false;
private static boolean alreadyTried = false;
+ private Credentials proxy = null;
+
+ public Credentials getProxy() {
+ return proxy;
+ }
+
+ public Credentials setProxy(Credentials proxy) {
+ this.proxy = proxy;
+ return this;
+ }
+
// Read native ticket with session key type in the given list
private static native Credentials acquireDefaultNativeCreds(int[] eTypes);
@@ -336,20 +346,19 @@ public class Credentials {
return null;
}
- sun.security.krb5.internal.ccache.Credentials tgtCred =
- ccache.getDefaultCreds();
+ Credentials tgtCred = ccache.getInitialCreds();
if (tgtCred == null) {
return null;
}
- if (EType.isSupported(tgtCred.getEType())) {
- return tgtCred.setKrbCreds();
+ if (EType.isSupported(tgtCred.key.getEType())) {
+ return tgtCred;
} else {
if (DEBUG) {
System.out.println(
">>> unsupported key type found the default TGT: " +
- tgtCred.getEType());
+ tgtCred.key.getEType());
}
return null;
}
@@ -384,20 +393,19 @@ public class Credentials {
cache = CredentialsCache.getInstance();
}
if (cache != null) {
- sun.security.krb5.internal.ccache.Credentials temp =
- cache.getDefaultCreds();
+ Credentials temp = cache.getInitialCreds();
if (temp != null) {
if (DEBUG) {
System.out.println(">>> KrbCreds found the default ticket"
+ " granting ticket in credential cache.");
}
- if (EType.isSupported(temp.getEType())) {
- result = temp.setKrbCreds();
+ if (EType.isSupported(temp.key.getEType())) {
+ result = temp;
} else {
if (DEBUG) {
System.out.println(
">>> unsupported key type found the default TGT: " +
- temp.getEType());
+ temp.key.getEType());
}
}
}
@@ -474,10 +482,6 @@ public class Credentials {
return cache;
}
- public EncryptionKey getServiceKey() {
- return serviceKey;
- }
-
/*
* Prints out debug info.
*/
diff --git a/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java b/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java
index 501e6b309a..84ca79bc9b 100644
--- a/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java
+++ b/src/share/classes/sun/security/krb5/JavaxSecurityAuthKerberosAccess.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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,8 @@
package sun.security.krb5;
+import javax.security.auth.kerberos.KerberosTicket;
import javax.security.auth.kerberos.KeyTab;
-import sun.security.krb5.EncryptionKey;
-import sun.security.krb5.PrincipalName;
/**
* An unsafe tunnel to get non-public access to classes in the
@@ -39,4 +38,14 @@ public interface JavaxSecurityAuthKerberosAccess {
*/
public sun.security.krb5.internal.ktab.KeyTab keyTabTakeSnapshot(
KeyTab ktab);
+
+ /**
+ * Returns the proxy for a KerberosTicket.
+ */
+ public KerberosTicket kerberosTicketGetProxy(KerberosTicket t);
+
+ /**
+ * Sets the proxy for a KerberosTicket.
+ */
+ public void kerberosTicketSetProxy(KerberosTicket t, KerberosTicket p);
}
diff --git a/src/share/classes/sun/security/krb5/Realm.java b/src/share/classes/sun/security/krb5/Realm.java
index b1295e7945..2cf7bbfadf 100644
--- a/src/share/classes/sun/security/krb5/Realm.java
+++ b/src/share/classes/sun/security/krb5/Realm.java
@@ -188,7 +188,6 @@ public class Realm implements Cloneable {
return false;
for (int i = 0; i < name.length(); i++) {
if (name.charAt(i) == '/' ||
- name.charAt(i) == ':' ||
name.charAt(i) == '\0') {
return false;
}
diff --git a/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java b/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java
index a15e4aac7b..c7d9d2adef 100644
--- a/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java
+++ b/src/share/classes/sun/security/krb5/internal/ccache/CCacheInputStream.java
@@ -325,16 +325,13 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
}
/**
- * Reads the next cred in stream.
- * @return the next cred, null if ticket or second_ticket unparseable.
+ * Reads the next cred or config entry in stream.
+ * @return the next cred or config entry, null if data unparseable.
*
- * Note: MIT krb5 1.8.1 might generate a config entry with server principal
- * X-CACHECONF:/krb5_ccache_conf_data/fast_avail/krbtgt/REALM@REALM. The
- * entry is used by KDC to inform the client that it support certain
- * features. Its ticket is not a valid krb5 ticket and thus this method
- * returns null.
+ * When data is unparseable, this method makes sure the correct number of
+ * bytes are consumed so it's safe to start reading the next element.
*/
- Credentials readCred(int version) throws IOException,RealmException, KrbApErrException, Asn1Exception {
+ Object readCred(int version) throws IOException,RealmException, KrbApErrException, Asn1Exception {
PrincipalName cpname = null;
try {
cpname = readPrincipal(version);
@@ -396,12 +393,23 @@ public class CCacheInputStream extends KrbDataInputStream implements FileCCacheC
}
try {
+ if (spname.getRealmString().equals("X-CACHECONF:")) {
+ String[] nameParts = spname.getNameStrings();
+ if (nameParts[0].equals("krb5_ccache_conf_data")) {
+ return new CredentialsCache.ConfigEntry(nameParts[1],
+ nameParts.length > 2 ? new PrincipalName(nameParts[2]) : null,
+ ticketData);
+ }
+ }
return new Credentials(cpname, spname, key, authtime, starttime,
- endtime, renewTill, skey, tFlags,
- addrs, auData,
- ticketData != null ? new Ticket(ticketData) : null,
- ticketData2 != null ? new Ticket(ticketData2) : null);
+ endtime, renewTill, skey, tFlags,
+ addrs, auData,
+ ticketData != null ? new Ticket(ticketData) : null,
+ ticketData2 != null ? new Ticket(ticketData2) : null);
} catch (Exception e) { // If any of new Ticket(*) fails.
+ if (DEBUG) {
+ e.printStackTrace(System.out);
+ }
return null;
}
}
diff --git a/src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java b/src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java
index dcc15e76d7..cde9712bf3 100644
--- a/src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java
+++ b/src/share/classes/sun/security/krb5/internal/ccache/CCacheOutputStream.java
@@ -31,7 +31,6 @@
package sun.security.krb5.internal.ccache;
import java.io.IOException;
-import java.io.FileOutputStream;
import java.io.OutputStream;
import sun.security.krb5.internal.util.KrbDataOutputStream;
import sun.security.krb5.*;
@@ -98,6 +97,21 @@ public class CCacheOutputStream extends KrbDataOutputStream implements FileCCach
writeTicket(creds.secondTicket);
}
+ public void addConfigEntry(PrincipalName cname, CredentialsCache.ConfigEntry e)
+ throws IOException {
+ cname.writePrincipal(this);
+ e.getSName().writePrincipal(this);
+ write16(0); write16(0); write32(0);
+ write32(0); write32(0); write32(0); write32(0);
+ write8(0);
+ write32(0);
+ write32(0);
+ write32(0);
+ write32(e.getData().length);
+ write(e.getData());
+ write32(0);
+ }
+
void writeTicket(Ticket t) throws IOException, Asn1Exception {
if (t == null) {
write32(0);
diff --git a/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java b/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java
index 7128545a25..c62e6293ff 100644
--- a/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java
+++ b/src/share/classes/sun/security/krb5/internal/ccache/Credentials.java
@@ -169,6 +169,18 @@ public class Credentials {
return sname;
}
+ public Ticket getTicket() throws RealmException {
+ return ticket;
+ }
+
+ public PrincipalName getServicePrincipal2() throws RealmException {
+ return secondTicket == null ? null : secondTicket.sname;
+ }
+
+ public PrincipalName getClientPrincipal() throws RealmException {
+ return cname;
+ }
+
public sun.security.krb5.Credentials setKrbCreds() {
// Note: We will not pass authorizationData to s.s.k.Credentials. The
// field in that class will be passed to Krb5Context as the return
@@ -208,7 +220,15 @@ public class Credentials {
return key.getEType();
}
+ public EncryptionKey getKey() {
+ return key;
+ }
+
public int getTktEType() {
return ticket.encPart.getEType();
}
+
+ public int getTktEType2() {
+ return (secondTicket == null) ? 0 : secondTicket.encPart.getEType();
+ }
}
diff --git a/src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java b/src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java
index 8c61ed395c..9489b92389 100644
--- a/src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java
+++ b/src/share/classes/sun/security/krb5/internal/ccache/CredentialsCache.java
@@ -32,14 +32,9 @@ package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
-import java.util.StringTokenizer;
-import java.util.Vector;
+
+import java.util.List;
import java.io.IOException;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
/**
* CredentialsCache stores credentials(tickets, session keys, etc) in a semi-permanent store
@@ -120,6 +115,62 @@ public abstract class CredentialsCache {
public abstract void save() throws IOException, KrbException;
public abstract Credentials[] getCredsList();
public abstract Credentials getDefaultCreds();
+ public abstract sun.security.krb5.Credentials getInitialCreds();
public abstract Credentials getCreds(PrincipalName sname);
public abstract Credentials getCreds(LoginOptions options, PrincipalName sname);
+ public abstract void addConfigEntry(ConfigEntry e);
+ public abstract List<ConfigEntry> getConfigEntries();
+
+ public ConfigEntry getConfigEntry(String name) {
+ List<ConfigEntry> entries = getConfigEntries();
+ if (entries != null) {
+ for (ConfigEntry e : entries) {
+ if (e.getName().equals(name)) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static class ConfigEntry {
+
+ public ConfigEntry(String name, PrincipalName princ, byte[] data) {
+ this.name = name;
+ this.princ = princ;
+ this.data = data;
+ }
+
+ private final String name;
+ private final PrincipalName princ;
+ private final byte[] data; // not worth cloning
+
+ public String getName() {
+ return name;
+ }
+
+ public PrincipalName getPrinc() {
+ return princ;
+ }
+
+ public byte[] getData() {
+ return data;
+ }
+
+ @Override
+ public String toString() {
+ return name + (princ != null ? ("." + princ) : "")
+ + ": " + new String(data);
+ }
+
+ public PrincipalName getSName() {
+ try {
+ return new PrincipalName("krb5_ccache_conf_data/" + name
+ + (princ != null ? ("/" + princ) : "")
+ + "@X-CACHECONF:");
+ } catch (RealmException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
}
diff --git a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java
index a682dddcba..91828292d7 100644
--- a/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java
+++ b/src/share/classes/sun/security/krb5/internal/ccache/FileCredentialsCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,12 @@ package sun.security.krb5.internal.ccache;
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
+import sun.security.util.SecurityProperties;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import java.io.IOException;
@@ -182,9 +188,13 @@ public class FileCredentialsCache extends CredentialsCache
primaryPrincipal = p;
credentialsList = new Vector<Credentials>();
while (cis.available() > 0) {
- Credentials cred = cis.readCred(version);
+ Object cred = cis.readCred(version);
if (cred != null) {
- credentialsList.addElement(cred);
+ if (cred instanceof Credentials) {
+ credentialsList.addElement((Credentials)cred);
+ } else {
+ addConfigEntry((CredentialsCache.ConfigEntry)cred);
+ }
}
}
}
@@ -255,6 +265,9 @@ public class FileCredentialsCache extends CredentialsCache
cos.addCreds(tmp[i]);
}
}
+ for (ConfigEntry e : getConfigEntries()) {
+ cos.addConfigEntry(primaryPrincipal, e);
+ }
}
}
@@ -307,6 +320,17 @@ public class FileCredentialsCache extends CredentialsCache
}
}
+ private List<ConfigEntry> configEntries = new ArrayList<>();
+
+ @Override
+ public void addConfigEntry(ConfigEntry e) {
+ configEntries.add(e);
+ }
+
+ @Override
+ public List<ConfigEntry> getConfigEntries() {
+ return Collections.unmodifiableList(configEntries);
+ }
/**
* Gets a credentials for a specified service.
@@ -326,6 +350,81 @@ public class FileCredentialsCache extends CredentialsCache
return null;
}
+ public sun.security.krb5.Credentials getInitialCreds() {
+
+ Credentials defaultCreds = getDefaultCreds();
+ if (defaultCreds == null) {
+ return null;
+ }
+ sun.security.krb5.Credentials tgt = defaultCreds.setKrbCreds();
+
+ CredentialsCache.ConfigEntry entry = getConfigEntry("proxy_impersonator");
+ if (entry == null) {
+ if (DEBUG) {
+ System.out.println("get normal credential");
+ }
+ return tgt;
+ }
+
+ boolean force;
+ String prop = SecurityProperties.privilegedGetOverridable(
+ "jdk.security.krb5.default.initiate.credential");
+ if (prop == null) {
+ prop = "always-impersonate";
+ }
+ switch (prop) {
+ case "no-impersonate": // never try impersonation
+ if (DEBUG) {
+ System.out.println("get normal credential");
+ }
+ return tgt;
+ case "try-impersonate":
+ force = false;
+ break;
+ case "always-impersonate":
+ force = true;
+ break;
+ default:
+ throw new RuntimeException(
+ "Invalid jdk.security.krb5.default.initiate.credential");
+ }
+
+ try {
+ PrincipalName service = new PrincipalName(
+ new String(entry.getData(), StandardCharsets.UTF_8));
+ if (!tgt.getClient().equals(service)) {
+ if (DEBUG) {
+ System.out.println("proxy_impersonator does not match service name");
+ }
+ return force ? null : tgt;
+ }
+ PrincipalName client = getPrimaryPrincipal();
+ Credentials proxy = null;
+ for (Credentials c : getCredsList()) {
+ if (c.getClientPrincipal().equals(client)
+ && c.getServicePrincipal().equals(service)) {
+ proxy = c;
+ break;
+ }
+ }
+ if (proxy == null) {
+ if (DEBUG) {
+ System.out.println("Cannot find evidence ticket in ccache");
+ }
+ return force ? null : tgt;
+ }
+ if (DEBUG) {
+ System.out.println("Get proxied credential");
+ }
+ return tgt.setProxy(proxy.setKrbCreds());
+ } catch (KrbException e) {
+ if (DEBUG) {
+ System.out.println("Impersonation with ccache failed");
+ }
+ return force ? null : tgt;
+ }
+ }
+
public Credentials getDefaultCreds() {
Credentials[] list = getCredsList();
if (list == null) {
diff --git a/src/share/classes/sun/security/pkcs11/P11Cipher.java b/src/share/classes/sun/security/pkcs11/P11Cipher.java
index 3d3f5a17c6..bf726360ec 100644
--- a/src/share/classes/sun/security/pkcs11/P11Cipher.java
+++ b/src/share/classes/sun/security/pkcs11/P11Cipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -344,7 +344,7 @@ final class P11Cipher extends CipherSpi {
private void implInit(int opmode, Key key, byte[] iv,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- cancelOperation();
+ reset(true);
if (fixedKeySize != -1 && key.getEncoded().length != fixedKeySize) {
throw new InvalidKeyException("Key size is invalid");
}
@@ -400,58 +400,83 @@ final class P11Cipher extends CipherSpi {
}
}
- private void cancelOperation() {
- if (initialized == false) {
+ // reset the states to the pre-initialized values
+ // need to be called after doFinal or prior to re-init
+ private void reset(boolean doCancel) {
+ if (!initialized) {
return;
}
initialized = false;
- if ((session == null) || (token.explicitCancel == false)) {
- return;
- }
- // cancel operation by finishing it
- int bufLen = doFinalLength(0);
- byte[] buffer = new byte[bufLen];
try {
- if (encrypt) {
- token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
- } else {
- token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ if (session == null) {
+ return;
+ }
+ if (doCancel && token.explicitCancel) {
+ cancelOperation();
}
- } catch (PKCS11Exception e) {
- throw new ProviderException("Cancel failed", e);
} finally {
- reset();
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
+ bytesBuffered = 0;
+ padBufferLen = 0;
+ }
+ }
+
+ private void cancelOperation() {
+ token.ensureValid();
+ if (session.hasObjects() == false) {
+ session = token.killSession(session);
+ return;
+ } else {
+ try {
+ // cancel operation by finishing it
+ int bufLen = doFinalLength(0);
+ byte[] buffer = new byte[bufLen];
+ if (encrypt) {
+ token.p11.C_EncryptFinal(session.id(), 0, buffer, 0, bufLen);
+ } else {
+ token.p11.C_DecryptFinal(session.id(), 0, buffer, 0, bufLen);
+ }
+ } catch (PKCS11Exception e) {
+ throw new ProviderException("Cancel failed", e);
+ }
}
}
private void ensureInitialized() throws PKCS11Exception {
- if (initialized == false) {
+ if (!initialized) {
initialize();
}
}
private void initialize() throws PKCS11Exception {
- if (session == null) {
- session = token.getOpSession();
+ if (p11Key == null) {
+ throw new ProviderException(
+ "Operation cannot be performed without"
+ + " calling engineInit first");
}
- CK_MECHANISM mechParams = (blockMode == MODE_CTR?
- new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
- new CK_MECHANISM(mechanism, iv));
-
+ token.ensureValid();
+ long p11KeyID = p11Key.getKeyID();
try {
+ if (session == null) {
+ session = token.getOpSession();
+ }
+ CK_MECHANISM mechParams = (blockMode == MODE_CTR?
+ new CK_MECHANISM(mechanism, new CK_AES_CTR_PARAMS(iv)) :
+ new CK_MECHANISM(mechanism, iv));
if (encrypt) {
- token.p11.C_EncryptInit(session.id(), mechParams, p11Key.keyID);
+ token.p11.C_EncryptInit(session.id(), mechParams, p11KeyID);
} else {
- token.p11.C_DecryptInit(session.id(), mechParams, p11Key.keyID);
+ token.p11.C_DecryptInit(session.id(), mechParams, p11KeyID);
}
- } catch (PKCS11Exception ex) {
- // release session when initialization failed
+ } catch (PKCS11Exception e) {
+ p11Key.releaseKeyID();
session = token.releaseSession(session);
- throw ex;
+ throw e;
}
+ initialized = true;
bytesBuffered = 0;
padBufferLen = 0;
- initialized = true;
}
// if update(inLen) is called, how big does the output buffer have to be?
@@ -482,16 +507,6 @@ final class P11Cipher extends CipherSpi {
return result;
}
- // reset the states to the pre-initialized values
- private void reset() {
- initialized = false;
- bytesBuffered = 0;
- padBufferLen = 0;
- if (session != null) {
- session = token.releaseSession(session);
- }
- }
-
// see JCE spec
protected byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
try {
@@ -610,7 +625,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -728,7 +743,7 @@ final class P11Cipher extends CipherSpi {
throw (ShortBufferException)
(new ShortBufferException().initCause(e));
}
- reset();
+ reset(false);
throw new ProviderException("update() failed", e);
}
}
@@ -740,6 +755,7 @@ final class P11Cipher extends CipherSpi {
if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
int k = 0;
@@ -753,7 +769,12 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
0, out, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(), 0,
@@ -762,20 +783,24 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
System.arraycopy(padBuffer, 0, out, outOfs, k);
} else {
k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
outLen);
+ doCancel = false;
}
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
@@ -788,6 +813,7 @@ final class P11Cipher extends CipherSpi {
throw new ShortBufferException();
}
+ boolean doCancel = true;
try {
ensureInitialized();
@@ -818,7 +844,13 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_EncryptFinal(session.id(),
outAddr, outArray, (outOfs + k), (outLen - k));
+ doCancel = false;
} else {
+ // Special handling to match SunJCE provider behavior
+ if (bytesBuffered == 0 && padBufferLen == 0) {
+ return 0;
+ }
+
if (paddingObj != null) {
if (padBufferLen != 0) {
k = token.p11.C_DecryptUpdate(session.id(),
@@ -828,6 +860,8 @@ final class P11Cipher extends CipherSpi {
}
k += token.p11.C_DecryptFinal(session.id(),
0, padBuffer, k, padBuffer.length - k);
+ doCancel = false;
+
int actualPadLen = paddingObj.unpad(padBuffer, k);
k -= actualPadLen;
outArray = padBuffer;
@@ -835,6 +869,7 @@ final class P11Cipher extends CipherSpi {
} else {
k = token.p11.C_DecryptFinal(session.id(),
outAddr, outArray, outOfs, outLen);
+ doCancel = false;
}
}
if ((!encrypt && paddingObj != null) ||
@@ -846,10 +881,11 @@ final class P11Cipher extends CipherSpi {
}
return k;
} catch (PKCS11Exception e) {
+ doCancel = false;
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
- reset();
+ reset(doCancel);
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
index 7bc5f149ef..381569435e 100644
--- a/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
+++ b/src/share/classes/sun/security/pkcs11/P11DHKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -221,7 +221,12 @@ final class P11DHKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_PRIME),
new CK_ATTRIBUTE(CKA_BASE),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
KeySpec spec = new DHPublicKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger(),
@@ -243,7 +248,12 @@ final class P11DHKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_PRIME),
new CK_ATTRIBUTE(CKA_BASE),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
KeySpec spec = new DHPrivateKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger(),
diff --git a/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
index d9550cb330..9263fc857f 100644
--- a/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
+++ b/src/share/classes/sun/security/pkcs11/P11DSAKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -218,7 +218,12 @@ final class P11DSAKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_SUBPRIME),
new CK_ATTRIBUTE(CKA_BASE),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
KeySpec spec = new DSAPublicKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger(),
@@ -242,7 +247,12 @@ final class P11DSAKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_SUBPRIME),
new CK_ATTRIBUTE(CKA_BASE),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
KeySpec spec = new DSAPrivateKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger(),
diff --git a/src/share/classes/sun/security/pkcs11/P11Digest.java b/src/share/classes/sun/security/pkcs11/P11Digest.java
index 2dc66d2368..3e8bd10f6a 100644
--- a/src/share/classes/sun/security/pkcs11/P11Digest.java
+++ b/src/share/classes/sun/security/pkcs11/P11Digest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -140,7 +140,8 @@ final class P11Digest extends MessageDigestSpi implements Cloneable {
token.ensureValid();
if (session != null) {
- if (state == S_INIT && token.explicitCancel == true) {
+ if (state == S_INIT && token.explicitCancel == true
+ && session.hasObjects() == false) {
session = token.killSession(session);
} else {
session = token.releaseSession(session);
@@ -250,6 +251,7 @@ final class P11Digest extends MessageDigestSpi implements Cloneable {
}
fetchSession();
+ long p11KeyID = p11Key.getKeyID();
try {
if (state == S_BUFFERED) {
token.p11.C_DigestInit(session.id(), mechanism);
@@ -260,10 +262,12 @@ final class P11Digest extends MessageDigestSpi implements Cloneable {
token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs);
bufOfs = 0;
}
- token.p11.C_DigestKey(session.id(), p11Key.keyID);
+ token.p11.C_DigestKey(session.id(), p11KeyID);
} catch (PKCS11Exception e) {
engineReset();
throw new ProviderException("update(SecretKey) failed", e);
+ } finally {
+ p11Key.releaseKeyID();
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java b/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
index ac2b7e3082..52b56ef42b 100644
--- a/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
+++ b/src/share/classes/sun/security/pkcs11/P11ECDHKeyAgreement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -120,6 +120,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
throw new IllegalStateException("Not initialized correctly");
}
Session session = null;
+ long privKeyID = privateKey.getKeyID();
try {
session = token.getOpSession();
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -131,8 +132,8 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
attributes = token.getAttributes
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
long keyID = token.p11.C_DeriveKey(session.id(),
- new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
- attributes);
+ new CK_MECHANISM(mechanism, ckParams), privKeyID,
+ attributes);
attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_VALUE)
};
@@ -143,6 +144,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
} catch (PKCS11Exception e) {
throw new ProviderException("Could not derive key", e);
} finally {
+ privateKey.releaseKeyID();
publicValue = null;
token.releaseSession(session);
}
@@ -182,6 +184,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
}
long keyType = CKK_GENERIC_SECRET;
Session session = null;
+ long privKeyID = privateKey.getKeyID();
try {
session = token.getObjSession();
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -193,8 +196,8 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
attributes = token.getAttributes
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
long keyID = token.p11.C_DeriveKey(session.id(),
- new CK_MECHANISM(mechanism, ckParams), privateKey.keyID,
- attributes);
+ new CK_MECHANISM(mechanism, ckParams), privKeyID,
+ attributes);
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_VALUE_LEN),
};
@@ -206,6 +209,7 @@ final class P11ECDHKeyAgreement extends KeyAgreementSpi {
} catch (PKCS11Exception e) {
throw new InvalidKeyException("Could not derive key", e);
} finally {
+ privateKey.releaseKeyID();
publicValue = null;
token.releaseSession(session);
}
diff --git a/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
index 494ab00f0d..ed1b84e96c 100644
--- a/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
+++ b/src/share/classes/sun/security/pkcs11/P11ECKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, 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
@@ -290,13 +290,16 @@ final class P11ECKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_EC_POINT),
new CK_ATTRIBUTE(CKA_EC_PARAMS),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
ECPoint point = decodePoint(attributes[0].getByteArray(), params.getCurve());
return keySpec.cast(new ECPublicKeySpec(point, params));
} catch (IOException e) {
throw new InvalidKeySpecException("Could not parse key", e);
+ } finally {
+ key.releaseKeyID();
}
} else { // X.509 handled in superclass
throw new InvalidKeySpecException("Only ECPublicKeySpec and "
@@ -312,13 +315,16 @@ final class P11ECKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_VALUE),
new CK_ATTRIBUTE(CKA_EC_PARAMS),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
ECParameterSpec params = decodeParameters(attributes[1].getByteArray());
return keySpec.cast(
new ECPrivateKeySpec(attributes[0].getBigInteger(), params));
} catch (IOException e) {
throw new InvalidKeySpecException("Could not parse key", e);
+ } finally {
+ key.releaseKeyID();
}
} else { // PKCS#8 handled in superclass
throw new InvalidKeySpecException("Only ECPrivateKeySpec "
diff --git a/src/share/classes/sun/security/pkcs11/P11Key.java b/src/share/classes/sun/security/pkcs11/P11Key.java
index c56483a6dd..a07e2082fa 100644
--- a/src/share/classes/sun/security/pkcs11/P11Key.java
+++ b/src/share/classes/sun/security/pkcs11/P11Key.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@ import java.io.*;
import java.lang.ref.*;
import java.math.BigInteger;
import java.util.*;
-
import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;
@@ -43,11 +42,15 @@ import sun.security.rsa.RSAPublicKeyImpl;
import sun.security.internal.interfaces.TlsMasterSecret;
import sun.security.pkcs11.wrapper.*;
+
+import static sun.security.pkcs11.TemplateManager.O_GENERATE;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
import sun.security.util.DerValue;
import sun.security.util.Length;
+import sun.security.jca.JCAUtil;
+
/**
* Key implementation classes.
*
@@ -79,23 +82,38 @@ abstract class P11Key implements Key, Length {
// algorithm name, returned by getAlgorithm(), etc.
final String algorithm;
- // key id
- final long keyID;
-
// effective key length of the key, e.g. 56 for a DES key
final int keyLength;
// flags indicating whether the key is a token object, sensitive, extractable
final boolean tokenObject, sensitive, extractable;
- // phantom reference notification clean up for session keys
- private final SessionKeyRef sessionKeyRef;
+ private final NativeKeyHolder keyIDHolder;
+
+ private static final boolean DISABLE_NATIVE_KEYS_EXTRACTION;
+
+ /**
+ * {@systemProperty sun.security.pkcs11.disableKeyExtraction} property
+ * indicating whether or not cryptographic keys within tokens are
+ * extracted to a Java byte array for memory management purposes.
+ *
+ * Key extraction affects NSS PKCS11 library only.
+ *
+ */
+ static {
+ PrivilegedAction<String> getKeyExtractionProp =
+ () -> System.getProperty(
+ "sun.security.pkcs11.disableKeyExtraction", "false");
+ String disableKeyExtraction =
+ AccessController.doPrivileged(getKeyExtractionProp);
+ DISABLE_NATIVE_KEYS_EXTRACTION =
+ "true".equalsIgnoreCase(disableKeyExtraction);
+ }
P11Key(String type, Session session, long keyID, String algorithm,
int keyLength, CK_ATTRIBUTE[] attributes) {
this.type = type;
this.token = session.token;
- this.keyID = keyID;
this.algorithm = algorithm;
this.keyLength = keyLength;
boolean tokenObject = false;
@@ -115,11 +133,21 @@ abstract class P11Key implements Key, Length {
this.tokenObject = tokenObject;
this.sensitive = sensitive;
this.extractable = extractable;
- if (tokenObject == false) {
- sessionKeyRef = new SessionKeyRef(this, keyID, session);
- } else {
- sessionKeyRef = null;
- }
+ char[] tokenLabel = this.token.tokenInfo.label;
+ boolean isNSS = (tokenLabel[0] == 'N' && tokenLabel[1] == 'S'
+ && tokenLabel[2] == 'S');
+ boolean extractKeyInfo = (!DISABLE_NATIVE_KEYS_EXTRACTION && isNSS &&
+ extractable && !tokenObject);
+ this.keyIDHolder = new NativeKeyHolder(this, keyID, session, extractKeyInfo,
+ tokenObject);
+ }
+
+ public long getKeyID() {
+ return keyIDHolder.getKeyID();
+ }
+
+ public void releaseKeyID() {
+ keyIDHolder.releaseKeyID();
}
// see JCA spec
@@ -204,8 +232,7 @@ abstract class P11Key implements Key, Length {
token.ensureValid();
String s1 = token.provider.getName() + " " + algorithm + " " + type
+ " key, " + keyLength + " bits";
- s1 += " (id " + keyID + ", "
- + (tokenObject ? "token" : "session") + " object";
+ s1 += (tokenObject ? "token" : "session") + " object";
if (isPublic()) {
s1 += ")";
} else {
@@ -237,12 +264,15 @@ abstract class P11Key implements Key, Length {
void fetchAttributes(CK_ATTRIBUTE[] attributes) {
Session tempSession = null;
+ long keyID = this.getKeyID();
try {
tempSession = token.getOpSession();
- token.p11.C_GetAttributeValue(tempSession.id(), keyID, attributes);
+ token.p11.C_GetAttributeValue(tempSession.id(), keyID,
+ attributes);
} catch (PKCS11Exception e) {
throw new ProviderException(e);
} finally {
+ this.releaseKeyID();
token.releaseSession(tempSession);
}
}
@@ -289,7 +319,8 @@ abstract class P11Key implements Key, Length {
new CK_ATTRIBUTE(CKA_SENSITIVE),
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
});
- return new P11SecretKey(session, keyID, algorithm, keyLength, attributes);
+ return new P11SecretKey(session, keyID, algorithm, keyLength,
+ attributes);
}
static SecretKey masterSecretKey(Session session, long keyID, String algorithm,
@@ -299,8 +330,9 @@ abstract class P11Key implements Key, Length {
new CK_ATTRIBUTE(CKA_SENSITIVE),
new CK_ATTRIBUTE(CKA_EXTRACTABLE),
});
- return new P11TlsMasterSecretKey
- (session, keyID, algorithm, keyLength, attributes, major, minor);
+ return new P11TlsMasterSecretKey(
+ session, keyID, algorithm, keyLength, attributes, major,
+ minor);
}
// we assume that all components of public keys are always accessible
@@ -308,17 +340,17 @@ abstract class P11Key implements Key, Length {
int keyLength, CK_ATTRIBUTE[] attributes) {
switch (algorithm) {
case "RSA":
- return new P11RSAPublicKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11RSAPublicKey(session, keyID, algorithm,
+ keyLength, attributes);
case "DSA":
- return new P11DSAPublicKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11DSAPublicKey(session, keyID, algorithm,
+ keyLength, attributes);
case "DH":
- return new P11DHPublicKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11DHPublicKey(session, keyID, algorithm,
+ keyLength, attributes);
case "EC":
- return new P11ECPublicKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11ECPublicKey(session, keyID, algorithm,
+ keyLength, attributes);
default:
throw new ProviderException
("Unknown public key algorithm " + algorithm);
@@ -355,21 +387,21 @@ abstract class P11Key implements Key, Length {
crtKey = false;
}
if (crtKey) {
- return new P11RSAPrivateKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11RSAPrivateKey(session, keyID, algorithm,
+ keyLength, attributes);
} else {
- return new P11RSAPrivateNonCRTKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11RSAPrivateNonCRTKey(session, keyID,
+ algorithm, keyLength, attributes);
}
case "DSA":
- return new P11DSAPrivateKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11DSAPrivateKey(session, keyID, algorithm,
+ keyLength, attributes);
case "DH":
- return new P11DHPrivateKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11DHPrivateKey(session, keyID, algorithm,
+ keyLength, attributes);
case "EC":
- return new P11ECPrivateKey
- (session, keyID, algorithm, keyLength, attributes);
+ return new P11ECPrivateKey(session, keyID, algorithm,
+ keyLength, attributes);
default:
throw new ProviderException
("Unknown private key algorithm " + algorithm);
@@ -423,17 +455,19 @@ abstract class P11Key implements Key, Length {
b = encoded;
if (b == null) {
Session tempSession = null;
+ long keyID = this.getKeyID();
try {
tempSession = token.getOpSession();
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_VALUE),
};
token.p11.C_GetAttributeValue
- (tempSession.id(), keyID, attributes);
+ (tempSession.id(), keyID, attributes);
b = attributes[0].getByteArray();
} catch (PKCS11Exception e) {
throw new ProviderException(e);
} finally {
+ this.releaseKeyID();
token.releaseSession(tempSession);
}
encoded = b;
@@ -1091,17 +1125,207 @@ abstract class P11Key implements Key, Length {
}
}
+final class NativeKeyHolder {
+
+ private static long nativeKeyWrapperKeyID = 0;
+ private static CK_MECHANISM nativeKeyWrapperMechanism = null;
+ private static long nativeKeyWrapperRefCount = 0;
+ private static Session nativeKeyWrapperSession = null;
+
+ private final P11Key p11Key;
+ private final byte[] nativeKeyInfo;
+ private boolean wrapperKeyUsed;
+
+ // destroyed and recreated when refCount toggles to 1
+ private long keyID;
+
+ // phantom reference notification clean up for session keys
+ private SessionKeyRef ref;
+
+ private int refCount;
+
+ private static void createNativeKeyWrapper(Token token)
+ throws PKCS11Exception {
+ assert(nativeKeyWrapperKeyID == 0);
+ assert(nativeKeyWrapperRefCount == 0);
+ assert(nativeKeyWrapperSession == null);
+ // Create a global wrapping/unwrapping key
+ CK_ATTRIBUTE[] wrappingAttributes = token.getAttributes(O_GENERATE,
+ CKO_SECRET_KEY, CKK_AES, new CK_ATTRIBUTE[] {
+ new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
+ new CK_ATTRIBUTE(CKA_VALUE_LEN, 256 >> 3)});
+ Session s = null;
+ try {
+ s = token.getObjSession();
+ nativeKeyWrapperKeyID = token.p11.C_GenerateKey(
+ s.id(), new CK_MECHANISM(CKM_AES_KEY_GEN),
+ wrappingAttributes);
+ nativeKeyWrapperSession = s;
+ nativeKeyWrapperSession.addObject();
+ byte[] iv = new byte[16];
+ JCAUtil.getSecureRandom().nextBytes(iv);
+ nativeKeyWrapperMechanism = new CK_MECHANISM(CKM_AES_CBC_PAD, iv);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ }
+
+ private static void deleteNativeKeyWrapper() {
+ Token token = nativeKeyWrapperSession.token;
+ if (token.isValid()) {
+ Session s = null;
+ try {
+ s = token.getOpSession();
+ token.p11.C_DestroyObject(s.id(), nativeKeyWrapperKeyID);
+ nativeKeyWrapperSession.removeObject();
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
+ }
+ nativeKeyWrapperKeyID = 0;
+ nativeKeyWrapperMechanism = null;
+ nativeKeyWrapperSession = null;
+ }
+
+ static void decWrapperKeyRef() {
+ synchronized(NativeKeyHolder.class) {
+ assert(nativeKeyWrapperKeyID != 0);
+ assert(nativeKeyWrapperRefCount > 0);
+ nativeKeyWrapperRefCount--;
+ if (nativeKeyWrapperRefCount == 0) {
+ deleteNativeKeyWrapper();
+ }
+ }
+ }
+
+ NativeKeyHolder(P11Key p11Key, long keyID, Session keySession,
+ boolean extractKeyInfo, boolean isTokenObject) {
+ this.p11Key = p11Key;
+ this.keyID = keyID;
+ this.refCount = -1;
+ byte[] ki = null;
+ if (isTokenObject) {
+ this.ref = null;
+ } else {
+ // Try extracting key info, if any error, disable it
+ Token token = p11Key.token;
+ if (extractKeyInfo) {
+ try {
+ if (p11Key.sensitive) {
+ // p11Key native key information has to be wrapped
+ synchronized(NativeKeyHolder.class) {
+ if (nativeKeyWrapperKeyID == 0) {
+ createNativeKeyWrapper(token);
+ }
+ // If a wrapper-key was successfully created or
+ // already exists, increment its reference
+ // counter to keep it alive while native key
+ // information is being held.
+ if (nativeKeyWrapperKeyID != 0) {
+ nativeKeyWrapperRefCount++;
+ wrapperKeyUsed = true;
+ }
+ }
+ }
+ Session opSession = null;
+ try {
+ opSession = token.getOpSession();
+ ki = p11Key.token.p11.getNativeKeyInfo(opSession.id(),
+ keyID, nativeKeyWrapperKeyID,
+ nativeKeyWrapperMechanism);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(opSession);
+ }
+ } catch (PKCS11Exception e) {
+ // best effort
+ }
+ }
+ this.ref = new SessionKeyRef(p11Key, keyID, wrapperKeyUsed,
+ keySession);
+ }
+ this.nativeKeyInfo = ((ki == null || ki.length == 0)? null : ki);
+ }
+
+ long getKeyID() throws ProviderException {
+ if (this.nativeKeyInfo != null) {
+ synchronized(this.nativeKeyInfo) {
+ if (this.refCount == -1) {
+ this.refCount = 0;
+ }
+ int cnt = (this.refCount)++;
+ if (keyID == 0) {
+ if (cnt != 0) {
+ throw new RuntimeException(
+ "Error: null keyID with non-zero refCount " + cnt);
+ }
+ Token token = p11Key.token;
+ // Create keyID using nativeKeyInfo
+ Session session = null;
+ try {
+ session = token.getObjSession();
+ this.keyID = token.p11.createNativeKey(session.id(),
+ nativeKeyInfo, nativeKeyWrapperKeyID,
+ nativeKeyWrapperMechanism);
+ this.ref.registerNativeKey(this.keyID, session);
+ } catch (PKCS11Exception e) {
+ this.refCount--;
+ throw new ProviderException("Error recreating native key", e);
+ } finally {
+ token.releaseSession(session);
+ }
+ } else {
+ if (cnt < 0) {
+ throw new RuntimeException("ERROR: negative refCount");
+ }
+ }
+ }
+ }
+ return keyID;
+ }
+
+ void releaseKeyID() {
+ if (this.nativeKeyInfo != null) {
+ synchronized(this.nativeKeyInfo) {
+ if (this.refCount == -1) {
+ throw new RuntimeException("Error: miss match getKeyID call");
+ }
+ int cnt = --(this.refCount);
+ if (cnt == 0) {
+ // destroy
+ if (this.keyID == 0) {
+ throw new RuntimeException("ERROR: null keyID can't be destroyed");
+ }
+
+ // destroy
+ this.keyID = 0;
+ this.ref.removeNativeKey();
+ } else {
+ if (cnt < 0) {
+ // should never happen as we start count at 1 and pair get/release calls
+ throw new RuntimeException("wrong refCount value: " + cnt);
+ }
+ }
+ }
+ }
+ }
+}
+
/*
* NOTE: Must use PhantomReference here and not WeakReference
* otherwise the key maybe cleared before other objects which
* still use these keys during finalization such as SSLSocket.
*/
-final class SessionKeyRef extends PhantomReference<P11Key>
- implements Comparable<SessionKeyRef> {
+final class SessionKeyRef extends PhantomReference<P11Key> {
private static ReferenceQueue<P11Key> refQueue =
new ReferenceQueue<P11Key>();
- private static Set<SessionKeyRef> refList =
- Collections.synchronizedSortedSet(new TreeSet<SessionKeyRef>());
+ private static Set<SessionKeyRef> refSet =
+ Collections.synchronizedSet(new HashSet<SessionKeyRef>());
static ReferenceQueue<P11Key> referenceQueue() {
return refQueue;
@@ -1115,42 +1339,71 @@ final class SessionKeyRef extends PhantomReference<P11Key>
}
}
- // handle to the native key
+ // handle to the native key and the session it is generated under
private long keyID;
private Session session;
+ private boolean wrapperKeyUsed;
- SessionKeyRef(P11Key key , long keyID, Session session) {
- super(key, refQueue);
- this.keyID = keyID;
- this.session = session;
- this.session.addObject();
- refList.add(this);
+ SessionKeyRef(P11Key p11Key, long keyID, boolean wrapperKeyUsed,
+ Session session) {
+ super(p11Key, refQueue);
+ if (session == null) {
+ throw new ProviderException("key must be associated with a session");
+ }
+ registerNativeKey(keyID, session);
+ this.wrapperKeyUsed = wrapperKeyUsed;
+
+ refSet.add(this);
// TBD: run at some interval and not every time?
drainRefQueueBounded();
}
- private void dispose() {
- refList.remove(this);
- if (session.token.isValid()) {
- Session newSession = null;
- try {
- newSession = session.token.getOpSession();
- session.token.p11.C_DestroyObject(newSession.id(), keyID);
- } catch (PKCS11Exception e) {
- // ignore
- } finally {
- this.clear();
- session.token.releaseSession(newSession);
- session.removeObject();
+ void registerNativeKey(long newKeyID, Session newSession) {
+ assert(newKeyID != 0);
+ assert(newSession != null);
+ updateNativeKey(newKeyID, newSession);
+ }
+
+ void removeNativeKey() {
+ assert(session != null);
+ updateNativeKey(0, null);
+ }
+
+ private void updateNativeKey(long newKeyID, Session newSession) {
+ if (newKeyID == 0) {
+ assert(newSession == null);
+ Token token = session.token;
+ // If the token is still valid, try to remove the key object
+ if (token.isValid()) {
+ Session s = null;
+ try {
+ s = token.getOpSession();
+ token.p11.C_DestroyObject(s.id(), this.keyID);
+ } catch (PKCS11Exception e) {
+ // best effort
+ } finally {
+ token.releaseSession(s);
+ }
}
+ session.removeObject();
+ } else {
+ newSession.addObject();
}
+ keyID = newKeyID;
+ session = newSession;
}
- public int compareTo(SessionKeyRef other) {
- if (this.keyID == other.keyID) {
- return 0;
- } else {
- return (this.keyID < other.keyID) ? -1 : 1;
+ // Called when the GC disposes a p11Key
+ void dispose() {
+ if (wrapperKeyUsed) {
+ // Wrapper-key no longer needed for
+ // p11Key native key information
+ NativeKeyHolder.decWrapperKeyRef();
+ }
+ if (keyID != 0) {
+ removeNativeKey();
}
+ refSet.remove(this);
+ this.clear();
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java b/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
index 2ae655ae60..a6db3c8e4d 100644
--- a/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
+++ b/src/share/classes/sun/security/pkcs11/P11KeyAgreement.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -201,6 +201,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
throw new IllegalStateException("Not initialized correctly");
}
Session session = null;
+ long privKeyID = privateKey.getKeyID();
try {
session = token.getOpSession();
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -210,8 +211,9 @@ final class P11KeyAgreement extends KeyAgreementSpi {
attributes = token.getAttributes
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, attributes);
long keyID = token.p11.C_DeriveKey(session.id(),
- new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
- attributes);
+ new CK_MECHANISM(mechanism, publicValue), privKeyID,
+ attributes);
+
attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_VALUE)
};
@@ -237,6 +239,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
} catch (PKCS11Exception e) {
throw new ProviderException("Could not derive key", e);
} finally {
+ privateKey.releaseKeyID();
publicValue = null;
token.releaseSession(session);
}
@@ -325,6 +328,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
}
long keyType = CKK_GENERIC_SECRET;
Session session = null;
+ long privKeyID = privateKey.getKeyID();
try {
session = token.getObjSession();
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
@@ -334,8 +338,8 @@ final class P11KeyAgreement extends KeyAgreementSpi {
attributes = token.getAttributes
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
long keyID = token.p11.C_DeriveKey(session.id(),
- new CK_MECHANISM(mechanism, publicValue), privateKey.keyID,
- attributes);
+ new CK_MECHANISM(mechanism, publicValue), privKeyID,
+ attributes);
CK_ATTRIBUTE[] lenAttributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_VALUE_LEN),
};
@@ -359,6 +363,7 @@ final class P11KeyAgreement extends KeyAgreementSpi {
} catch (PKCS11Exception e) {
throw new InvalidKeyException("Could not derive key", e);
} finally {
+ privateKey.releaseKeyID();
publicValue = null;
token.releaseSession(session);
}
diff --git a/src/share/classes/sun/security/pkcs11/P11KeyStore.java b/src/share/classes/sun/security/pkcs11/P11KeyStore.java
index e5b8fa8d80..aee9542537 100644
--- a/src/share/classes/sun/security/pkcs11/P11KeyStore.java
+++ b/src/share/classes/sun/security/pkcs11/P11KeyStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -1486,6 +1486,7 @@ final class P11KeyStore extends KeyStoreSpi {
}
}
+ // retrieves the native key handle and either update it directly or make a copy
private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
throws PKCS11Exception {
@@ -1493,23 +1494,22 @@ final class P11KeyStore extends KeyStoreSpi {
// if session key, convert to token key.
Session session = null;
+ long keyID = key.getKeyID();
try {
session = token.getOpSession();
if (key.tokenObject == true) {
-
// token key - set new CKA_ID
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_ID, alias) };
token.p11.C_SetAttributeValue
- (session.id(), key.keyID, attrs);
+ (session.id(), keyID, attrs);
if (debug != null) {
debug.println("updateP11Pkey set new alias [" +
alias +
"] for key entry");
}
} else {
-
// session key - convert to token key and set CKA_ID
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
@@ -1519,7 +1519,8 @@ final class P11KeyStore extends KeyStoreSpi {
if (attribute != null) {
attrs = addAttribute(attrs, attribute);
}
- token.p11.C_CopyObject(session.id(), key.keyID, attrs);
+ // creates a new token key with the desired CKA_ID
+ token.p11.C_CopyObject(session.id(), keyID, attrs);
if (debug != null) {
debug.println("updateP11Pkey copied private session key " +
"for [" +
@@ -1529,6 +1530,7 @@ final class P11KeyStore extends KeyStoreSpi {
}
} finally {
token.releaseSession(session);
+ key.releaseKeyID();
}
}
@@ -1895,10 +1897,12 @@ final class P11KeyStore extends KeyStoreSpi {
return attrs;
}
String alg = privateKey.getAlgorithm();
- if (id && alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
+ if (alg.equals("RSA") && (publicKey instanceof RSAPublicKey)) {
+ if (id) {
+ BigInteger n = ((RSAPublicKey)publicKey).getModulus();
+ attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
+ }
// CKA_NETSCAPE_DB not needed for RSA public keys
- BigInteger n = ((RSAPublicKey)publicKey).getModulus();
- attrs[0] = new CK_ATTRIBUTE(CKA_ID, sha1(getMagnitude(n)));
} else if (alg.equals("DSA") && (publicKey instanceof DSAPublicKey)) {
BigInteger y = ((DSAPublicKey)publicKey).getY();
if (id) {
diff --git a/src/share/classes/sun/security/pkcs11/P11Mac.java b/src/share/classes/sun/security/pkcs11/P11Mac.java
index 2b0cbbcdf5..56d0b1c70c 100644
--- a/src/share/classes/sun/security/pkcs11/P11Mac.java
+++ b/src/share/classes/sun/security/pkcs11/P11Mac.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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,7 +25,6 @@
package sun.security.pkcs11;
-import java.util.*;
import java.nio.ByteBuffer;
import java.security.*;
@@ -54,27 +53,12 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
*/
final class P11Mac extends MacSpi {
- /* unitialized, all fields except session have arbitrary values */
- private final static int S_UNINIT = 1;
-
- /* session initialized, no data processed yet */
- private final static int S_RESET = 2;
-
- /* session initialized, data processed */
- private final static int S_UPDATE = 3;
-
- /* transitional state after doFinal() before we go to S_UNINIT */
- private final static int S_DOFINAL = 4;
-
// token instance
private final Token token;
// algorithm name
private final String algorithm;
- // mechanism id
- private final long mechanism;
-
// mechanism object
private final CK_MECHANISM ckMechanism;
@@ -87,8 +71,8 @@ final class P11Mac extends MacSpi {
// associated session, if any
private Session session;
- // state, one of S_* above
- private int state;
+ // initialization status
+ private boolean initialized;
// one byte buffer for the update(byte) method, initialized on demand
private byte[] oneByte;
@@ -98,7 +82,6 @@ final class P11Mac extends MacSpi {
super();
this.token = token;
this.algorithm = algorithm;
- this.mechanism = mechanism;
Long params = null;
switch ((int)mechanism) {
case (int)CKM_MD5_HMAC:
@@ -131,47 +114,65 @@ final class P11Mac extends MacSpi {
throw new ProviderException("Unknown mechanism: " + mechanism);
}
ckMechanism = new CK_MECHANISM(mechanism, params);
- state = S_UNINIT;
- initialize();
}
- private void ensureInitialized() throws PKCS11Exception {
- token.ensureValid();
- if (state == S_UNINIT) {
- initialize();
+ // reset the states to the pre-initialized values
+ private void reset(boolean doCancel) {
+ if (!initialized) {
+ return;
+ }
+ initialized = false;
+ try {
+ if (session == null) {
+ return;
+ }
+ if (doCancel && token.explicitCancel) {
+ cancelOperation();
+ }
+ } finally {
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
}
}
private void cancelOperation() {
token.ensureValid();
- if (state == S_UNINIT) {
- return;
- }
- state = S_UNINIT;
- if ((session == null) || (token.explicitCancel == false)) {
+ if (session.hasObjects() == false) {
+ session = token.killSession(session);
return;
+ } else {
+ try {
+ token.p11.C_SignFinal(session.id(), 0);
+ } catch (PKCS11Exception e) {
+ throw new ProviderException("Cancel failed", e);
+ }
}
- try {
- token.p11.C_SignFinal(session.id(), 0);
- } catch (PKCS11Exception e) {
- throw new ProviderException("Cancel failed", e);
+ }
+
+ private void ensureInitialized() throws PKCS11Exception {
+ if (!initialized) {
+ initialize();
}
}
private void initialize() throws PKCS11Exception {
- if (state == S_RESET) {
- return;
- }
- if (session == null) {
- session = token.getOpSession();
+ if (p11Key == null) {
+ throw new ProviderException(
+ "Operation cannot be performed without calling engineInit first");
}
- if (p11Key != null) {
- token.p11.C_SignInit
- (session.id(), ckMechanism, p11Key.keyID);
- state = S_RESET;
- } else {
- state = S_UNINIT;
+ token.ensureValid();
+ long p11KeyID = p11Key.getKeyID();
+ try {
+ if (session == null) {
+ session = token.getOpSession();
+ }
+ token.p11.C_SignInit(session.id(), ckMechanism, p11KeyID);
+ } catch (PKCS11Exception e) {
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
+ throw e;
}
+ initialized = true;
}
// see JCE spec
@@ -181,18 +182,7 @@ final class P11Mac extends MacSpi {
// see JCE spec
protected void engineReset() {
- // the framework insists on calling reset() after doFinal(),
- // but we prefer to take care of reinitialization ourselves
- if (state == S_DOFINAL) {
- state = S_UNINIT;
- return;
- }
- cancelOperation();
- try {
- initialize();
- } catch (PKCS11Exception e) {
- throw new ProviderException("reset() failed, ", e);
- }
+ reset(true);
}
// see JCE spec
@@ -202,7 +192,7 @@ final class P11Mac extends MacSpi {
throw new InvalidAlgorithmParameterException
("Parameters not supported");
}
- cancelOperation();
+ reset(true);
p11Key = P11SecretKeyFactory.convertKey(token, key, algorithm);
try {
initialize();
@@ -215,13 +205,12 @@ final class P11Mac extends MacSpi {
protected byte[] engineDoFinal() {
try {
ensureInitialized();
- byte[] mac = token.p11.C_SignFinal(session.id(), 0);
- state = S_DOFINAL;
- return mac;
+ return token.p11.C_SignFinal(session.id(), 0);
} catch (PKCS11Exception e) {
+ reset(true);
throw new ProviderException("doFinal() failed", e);
} finally {
- session = token.releaseSession(session);
+ reset(false);
}
}
@@ -239,7 +228,6 @@ final class P11Mac extends MacSpi {
try {
ensureInitialized();
token.p11.C_SignUpdate(session.id(), 0, b, ofs, len);
- state = S_UPDATE;
} catch (PKCS11Exception e) {
throw new ProviderException("update() failed", e);
}
@@ -261,7 +249,6 @@ final class P11Mac extends MacSpi {
int ofs = byteBuffer.position();
token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len);
byteBuffer.position(ofs + len);
- state = S_UPDATE;
} catch (PKCS11Exception e) {
throw new ProviderException("update() failed", e);
}
diff --git a/src/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
index 7b2b98a315..2584399187 100644
--- a/src/share/classes/sun/security/pkcs11/P11RSACipher.java
+++ b/src/share/classes/sun/security/pkcs11/P11RSACipher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -195,7 +195,7 @@ final class P11RSACipher extends CipherSpi {
}
private void implInit(int opmode, Key key) throws InvalidKeyException {
- cancelOperation();
+ reset(true);
p11Key = P11KeyFactory.convertKey(token, key, algorithm);
boolean encrypt;
if (opmode == Cipher.ENCRYPT_MODE) {
@@ -240,80 +240,105 @@ final class P11RSACipher extends CipherSpi {
}
}
- private void cancelOperation() {
- token.ensureValid();
- if (initialized == false) {
+ // reset the states to the pre-initialized values
+ private void reset(boolean doCancel) {
+ if (!initialized) {
return;
}
initialized = false;
- if ((session == null) || (token.explicitCancel == false)) {
- return;
+ try {
+ if (session == null) {
+ return;
+ }
+ if (doCancel && token.explicitCancel) {
+ cancelOperation();
+ }
+ } finally {
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
}
+ }
+
+ // should only called by reset as this method does not update other
+ // state variables such as "initialized"
+ private void cancelOperation() {
+ token.ensureValid();
if (session.hasObjects() == false) {
session = token.killSession(session);
return;
+ } else {
+ try {
+ PKCS11 p11 = token.p11;
+ int inLen = maxInputSize;
+ int outLen = buffer.length;
+ long sessId = session.id();
+ switch (mode) {
+ case MODE_ENCRYPT:
+ p11.C_Encrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
+ break;
+ case MODE_DECRYPT:
+ p11.C_Decrypt(sessId, buffer, 0, inLen, buffer, 0, outLen);
+ break;
+ case MODE_SIGN:
+ byte[] tmpBuffer = new byte[maxInputSize];
+ p11.C_Sign(sessId, tmpBuffer);
+ break;
+ case MODE_VERIFY:
+ p11.C_VerifyRecover(sessId, buffer, 0, inLen, buffer,
+ 0, outLen);
+ break;
+ default:
+ throw new ProviderException("internal error");
+ }
+ } catch (PKCS11Exception e) {
+ // XXX ensure this always works, ignore error
+ }
+ }
+ }
+
+ private void ensureInitialized() throws PKCS11Exception {
+ token.ensureValid();
+ if (!initialized) {
+ initialize();
}
+ }
+
+ private void initialize() throws PKCS11Exception {
+ if (p11Key == null) {
+ throw new ProviderException(
+ "Operation cannot be performed without " +
+ "calling engineInit first");
+ }
+ long keyID = p11Key.getKeyID();
try {
+ if (session == null) {
+ session = token.getOpSession();
+ }
PKCS11 p11 = token.p11;
- int inLen = maxInputSize;
- int outLen = buffer.length;
+ CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
switch (mode) {
case MODE_ENCRYPT:
- p11.C_Encrypt
- (session.id(), buffer, 0, inLen, buffer, 0, outLen);
+ p11.C_EncryptInit(session.id(), ckMechanism, keyID);
break;
case MODE_DECRYPT:
- p11.C_Decrypt
- (session.id(), buffer, 0, inLen, buffer, 0, outLen);
+ p11.C_DecryptInit(session.id(), ckMechanism, keyID);
break;
case MODE_SIGN:
- byte[] tmpBuffer = new byte[maxInputSize];
- p11.C_Sign
- (session.id(), tmpBuffer);
+ p11.C_SignInit(session.id(), ckMechanism, keyID);
break;
case MODE_VERIFY:
- p11.C_VerifyRecover
- (session.id(), buffer, 0, inLen, buffer, 0, outLen);
+ p11.C_VerifyRecoverInit(session.id(), ckMechanism, keyID);
break;
default:
- throw new ProviderException("internal error");
+ throw new AssertionError("internal error");
}
+ bufOfs = 0;
+ initialized = true;
} catch (PKCS11Exception e) {
- // XXX ensure this always works, ignore error
- }
- }
-
- private void ensureInitialized() throws PKCS11Exception {
- token.ensureValid();
- if (initialized == false) {
- initialize();
- }
- }
-
- private void initialize() throws PKCS11Exception {
- if (session == null) {
- session = token.getOpSession();
- }
- PKCS11 p11 = token.p11;
- CK_MECHANISM ckMechanism = new CK_MECHANISM(mechanism);
- switch (mode) {
- case MODE_ENCRYPT:
- p11.C_EncryptInit(session.id(), ckMechanism, p11Key.keyID);
- break;
- case MODE_DECRYPT:
- p11.C_DecryptInit(session.id(), ckMechanism, p11Key.keyID);
- break;
- case MODE_SIGN:
- p11.C_SignInit(session.id(), ckMechanism, p11Key.keyID);
- break;
- case MODE_VERIFY:
- p11.C_VerifyRecoverInit(session.id(), ckMechanism, p11Key.keyID);
- break;
- default:
- throw new AssertionError("internal error");
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
+ throw e;
}
- bufOfs = 0;
- initialized = true;
}
private void implUpdate(byte[] in, int inOfs, int inLen) {
@@ -376,8 +401,7 @@ final class P11RSACipher extends CipherSpi {
throw (BadPaddingException)new BadPaddingException
("doFinal() failed").initCause(e);
} finally {
- initialized = false;
- session = token.releaseSession(session);
+ reset(false);
}
}
@@ -451,13 +475,17 @@ final class P11RSACipher extends CipherSpi {
}
}
Session s = null;
+ long p11KeyID = p11Key.getKeyID();
+ long sKeyID = sKey.getKeyID();
try {
s = token.getOpSession();
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
- p11Key.keyID, sKey.keyID);
+ p11KeyID, sKeyID);
} catch (PKCS11Exception e) {
throw new InvalidKeyException("wrap() failed", e);
} finally {
+ p11Key.releaseKeyID();
+ sKey.releaseKeyID();
token.releaseSession(s);
}
}
@@ -516,6 +544,7 @@ final class P11RSACipher extends CipherSpi {
} else {
Session s = null;
SecretKey secretKey = null;
+ long p11KeyID = p11Key.getKeyID();
try {
try {
s = token.getObjSession();
@@ -526,9 +555,10 @@ final class P11RSACipher extends CipherSpi {
};
attributes = token.getAttributes(
O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
+
long keyID = token.p11.C_UnwrapKey(s.id(),
- new CK_MECHANISM(mechanism), p11Key.keyID,
- wrappedKey, attributes);
+ new CK_MECHANISM(mechanism), p11KeyID,
+ wrappedKey, attributes);
secretKey = P11Key.secretKey(s, keyID,
algorithm, 48 << 3, attributes);
} catch (PKCS11Exception e) {
@@ -552,6 +582,7 @@ final class P11RSACipher extends CipherSpi {
return secretKey;
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(s);
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
index 6c36de165b..0fc06a7334 100644
--- a/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
+++ b/src/share/classes/sun/security/pkcs11/P11RSAKeyFactory.java
@@ -262,7 +262,12 @@ final class P11RSAKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_MODULUS),
new CK_ATTRIBUTE(CKA_PUBLIC_EXPONENT),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
KeySpec spec = new RSAPublicKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger()
@@ -288,7 +293,13 @@ final class P11RSAKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_EXPONENT_2),
new CK_ATTRIBUTE(CKA_COEFFICIENT),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
+
KeySpec spec = new RSAPrivateCrtKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger(),
@@ -306,7 +317,13 @@ final class P11RSAKeyFactory extends P11KeyFactory {
new CK_ATTRIBUTE(CKA_MODULUS),
new CK_ATTRIBUTE(CKA_PRIVATE_EXPONENT),
};
- token.p11.C_GetAttributeValue(session[0].id(), key.keyID, attributes);
+ long keyID = key.getKeyID();
+ try {
+ token.p11.C_GetAttributeValue(session[0].id(), keyID, attributes);
+ } finally {
+ key.releaseKeyID();
+ }
+
KeySpec spec = new RSAPrivateKeySpec(
attributes[0].getBigInteger(),
attributes[1].getBigInteger()
diff --git a/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java b/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
index f4306b3a9a..e6ed887419 100644
--- a/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
+++ b/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -146,20 +146,24 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
P11Key p11Key = (P11Key)key;
if (p11Key.token == token) {
if (extraAttrs != null) {
+ P11Key newP11Key = null;
Session session = null;
+ long p11KeyID = p11Key.getKeyID();
try {
session = token.getObjSession();
long newKeyID = token.p11.C_CopyObject(session.id(),
- p11Key.keyID, extraAttrs);
- p11Key = (P11Key) (P11Key.secretKey(session,
+ p11KeyID, extraAttrs);
+ newP11Key = (P11Key) (P11Key.secretKey(session,
newKeyID, p11Key.algorithm, p11Key.keyLength,
extraAttrs));
} catch (PKCS11Exception p11e) {
throw new InvalidKeyException
("Cannot duplicate the PKCS11 key", p11e);
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(session);
}
+ p11Key = newP11Key;
}
return p11Key;
}
diff --git a/src/share/classes/sun/security/pkcs11/P11Signature.java b/src/share/classes/sun/security/pkcs11/P11Signature.java
index adfc63348c..af152d8153 100644
--- a/src/share/classes/sun/security/pkcs11/P11Signature.java
+++ b/src/share/classes/sun/security/pkcs11/P11Signature.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -237,27 +237,33 @@ final class P11Signature extends SignatureSpi {
this.md = md;
}
- private void ensureInitialized() {
- token.ensureValid();
- if (initialized == false) {
- initialize();
- }
- }
+ // reset the states to the pre-initialized values
+ private void reset(boolean doCancel) {
- private void cancelOperation() {
- token.ensureValid();
- if (initialized == false) {
+ if (!initialized) {
return;
}
initialized = false;
- if ((session == null) || (token.explicitCancel == false)) {
- return;
+ try {
+ if (session == null) {
+ return;
+ }
+ if (doCancel && token.explicitCancel) {
+ cancelOperation();
+ }
+ } finally {
+ p11Key.releaseKeyID();
+ session = token.releaseSession(session);
}
+ }
+
+ private void cancelOperation() {
+
+ token.ensureValid();
if (session.hasObjects() == false) {
session = token.killSession(session);
return;
- }
- try {
+ } else {
// "cancel" operation by finishing it
// XXX make sure all this always works correctly
if (mode == M_SIGN) {
@@ -277,8 +283,8 @@ final class P11Signature extends SignatureSpi {
throw new ProviderException("cancel failed", e);
}
} else { // M_VERIFY
+ byte[] signature;
try {
- byte[] signature;
if (keyAlgorithm.equals("DSA")) {
signature = new byte[40];
} else {
@@ -296,31 +302,48 @@ final class P11Signature extends SignatureSpi {
token.p11.C_Verify(session.id(), digest, signature);
}
} catch (PKCS11Exception e) {
- // will fail since the signature is incorrect
- // XXX check error code
+ long errorCode = e.getErrorCode();
+ if ((errorCode == CKR_SIGNATURE_INVALID) ||
+ (errorCode == CKR_SIGNATURE_LEN_RANGE)) {
+ // expected since signature is incorrect
+ return;
+ }
+ throw new ProviderException("cancel failed", e);
}
}
- } finally {
- session = token.releaseSession(session);
+ }
+ }
+
+ private void ensureInitialized() {
+
+ if (!initialized) {
+ initialize();
}
}
// assumes current state is initialized == false
private void initialize() {
+
+ if (p11Key == null) {
+ throw new ProviderException(
+ "Operation cannot be performed without " +
+ "calling engineInit first");
+ }
+ long keyID = p11Key.getKeyID();
try {
+ token.ensureValid();
if (session == null) {
session = token.getOpSession();
}
if (mode == M_SIGN) {
token.p11.C_SignInit(session.id(),
- new CK_MECHANISM(mechanism), p11Key.keyID);
+ new CK_MECHANISM(mechanism), keyID);
} else {
token.p11.C_VerifyInit(session.id(),
- new CK_MECHANISM(mechanism), p11Key.keyID);
+ new CK_MECHANISM(mechanism), keyID);
}
- initialized = true;
} catch (PKCS11Exception e) {
- // release session when initialization failed
+ p11Key.releaseKeyID();
session = token.releaseSession(session);
throw new ProviderException("Initialization failed", e);
}
@@ -330,6 +353,7 @@ final class P11Signature extends SignatureSpi {
md.reset();
}
}
+ initialized = true;
}
private void checkKeySize(String keyAlgo, Key key)
@@ -412,6 +436,7 @@ final class P11Signature extends SignatureSpi {
// see JCA spec
protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException {
+
if (publicKey == null) {
throw new InvalidKeyException("Key must not be null");
}
@@ -419,7 +444,7 @@ final class P11Signature extends SignatureSpi {
if (publicKey != p11Key) {
checkKeySize(keyAlgorithm, publicKey);
}
- cancelOperation();
+ reset(true);
mode = M_VERIFY;
p11Key = P11KeyFactory.convertKey(token, publicKey, keyAlgorithm);
initialize();
@@ -428,6 +453,7 @@ final class P11Signature extends SignatureSpi {
// see JCA spec
protected void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException {
+
if (privateKey == null) {
throw new InvalidKeyException("Key must not be null");
}
@@ -435,7 +461,7 @@ final class P11Signature extends SignatureSpi {
if (privateKey != p11Key) {
checkKeySize(keyAlgorithm, privateKey);
}
- cancelOperation();
+ reset(true);
mode = M_SIGN;
p11Key = P11KeyFactory.convertKey(token, privateKey, keyAlgorithm);
initialize();
@@ -468,6 +494,7 @@ final class P11Signature extends SignatureSpi {
// see JCA spec
protected void engineUpdate(byte[] b, int ofs, int len)
throws SignatureException {
+
ensureInitialized();
if (len == 0) {
return;
@@ -486,8 +513,7 @@ final class P11Signature extends SignatureSpi {
}
bytesProcessed += len;
} catch (PKCS11Exception e) {
- initialized = false;
- session = token.releaseSession(session);
+ reset(false);
throw new ProviderException(e);
}
break;
@@ -510,6 +536,7 @@ final class P11Signature extends SignatureSpi {
// see JCA spec
protected void engineUpdate(ByteBuffer byteBuffer) {
+
ensureInitialized();
int len = byteBuffer.remaining();
if (len <= 0) {
@@ -535,8 +562,7 @@ final class P11Signature extends SignatureSpi {
bytesProcessed += len;
byteBuffer.position(ofs + len);
} catch (PKCS11Exception e) {
- initialized = false;
- session = token.releaseSession(session);
+ reset(false);
throw new ProviderException("Update failed", e);
}
break;
@@ -553,13 +579,16 @@ final class P11Signature extends SignatureSpi {
bytesProcessed += len;
break;
default:
+ reset(false);
throw new ProviderException("Internal error");
}
}
// see JCA spec
protected byte[] engineSign() throws SignatureException {
+
ensureInitialized();
+ boolean doCancel = true;
try {
byte[] signature;
if (type == T_UPDATE) {
@@ -596,22 +625,25 @@ final class P11Signature extends SignatureSpi {
signature = token.p11.C_Sign(session.id(), data);
}
}
+ doCancel = false;
+
if (keyAlgorithm.equals("RSA") == false) {
return dsaToASN1(signature);
} else {
return signature;
}
} catch (PKCS11Exception e) {
+ doCancel = false;
throw new ProviderException(e);
} finally {
- initialized = false;
- session = token.releaseSession(session);
+ reset(doCancel);
}
}
// see JCA spec
protected boolean engineVerify(byte[] signature) throws SignatureException {
ensureInitialized();
+ boolean doCancel = true;
try {
if (keyAlgorithm.equals("DSA")) {
signature = asn1ToDSA(signature);
@@ -651,8 +683,10 @@ final class P11Signature extends SignatureSpi {
token.p11.C_Verify(session.id(), data, signature);
}
}
+ doCancel = false;
return true;
} catch (PKCS11Exception e) {
+ doCancel = false;
long errorCode = e.getErrorCode();
if (errorCode == CKR_SIGNATURE_INVALID) {
return false;
@@ -667,10 +701,7 @@ final class P11Signature extends SignatureSpi {
}
throw new ProviderException(e);
} finally {
- // XXX we should not release the session if we abort above
- // before calling C_Verify
- initialized = false;
- session = token.releaseSession(session);
+ reset(doCancel);
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java b/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
index 7cc1ec8166..f6848278c3 100644
--- a/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
+++ b/src/share/classes/sun/security/pkcs11/P11TlsKeyMaterialGenerator.java
@@ -173,9 +173,13 @@ public final class P11TlsKeyMaterialGenerator extends KeyGeneratorSpi {
}
attributes = token.getAttributes
(O_GENERATE, CKO_SECRET_KEY, keyType, attributes);
- // the returned keyID is a dummy, ignore
- long keyID = token.p11.C_DeriveKey(session.id(),
- ckMechanism, p11Key.keyID, attributes);
+ long p11KeyID = p11Key.getKeyID();
+ try {
+ token.p11.C_DeriveKey(session.id(),
+ ckMechanism, p11KeyID, attributes);
+ } finally {
+ p11Key.releaseKeyID();
+ }
CK_SSL3_KEY_MAT_OUT out = null;
if (params instanceof CK_SSL3_KEY_MAT_PARAMS) {
diff --git a/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java b/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
index 6e4970d509..aae68854f3 100644
--- a/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
+++ b/src/share/classes/sun/security/pkcs11/P11TlsMasterSecretGenerator.java
@@ -147,12 +147,13 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
}
Session session = null;
+ long p11KeyID = p11Key.getKeyID();
try {
session = token.getObjSession();
CK_ATTRIBUTE[] attributes = token.getAttributes(O_GENERATE,
CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
long keyID = token.p11.C_DeriveKey(session.id(),
- ckMechanism, p11Key.keyID, attributes);
+ ckMechanism, p11KeyID, attributes);
int major, minor;
if (ckVersion == null) {
major = -1;
@@ -161,12 +162,12 @@ public final class P11TlsMasterSecretGenerator extends KeyGeneratorSpi {
major = ckVersion.major;
minor = ckVersion.minor;
}
- SecretKey key = P11Key.masterSecretKey(session, keyID,
+ return P11Key.masterSecretKey(session, keyID,
"TlsMasterSecret", 48 << 3, attributes, major, minor);
- return key;
} catch (Exception e) {
throw new ProviderException("Could not generate key", e);
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(session);
}
}
diff --git a/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java b/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
index 4a143d7901..d3ad925ea1 100644
--- a/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
+++ b/src/share/classes/sun/security/pkcs11/P11TlsPrfGenerator.java
@@ -143,34 +143,36 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
Functions.getHashMechId(spec.getPRFHashAlg()),
spec.getOutputLength(), ulServerOrClient);
Session session = null;
+ long keyID = p11Key.getKeyID();
try {
session = token.getOpSession();
token.p11.C_SignInit(session.id(),
- new CK_MECHANISM(mechanism, params), p11Key.keyID);
+ new CK_MECHANISM(mechanism, params), keyID);
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
byte[] out = token.p11.C_SignFinal
(session.id(), spec.getOutputLength());
- k = new SecretKeySpec(out, "TlsPrf");
+ return new SecretKeySpec(out, "TlsPrf");
} catch (PKCS11Exception e) {
throw new ProviderException("Could not calculate PRF", e);
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(session);
}
} else {
throw new ProviderException("Only Finished message authentication code"+
" generation supported for TLS 1.2.");
}
- return k;
}
byte[] label = P11Util.getBytesUTF8(spec.getLabel());
if (mechanism == CKM_NSS_TLS_PRF_GENERAL) {
Session session = null;
+ long keyID = p11Key.getKeyID();
try {
session = token.getOpSession();
token.p11.C_SignInit
- (session.id(), new CK_MECHANISM(mechanism), p11Key.keyID);
+ (session.id(), new CK_MECHANISM(mechanism), keyID);
token.p11.C_SignUpdate(session.id(), 0, label, 0, label.length);
token.p11.C_SignUpdate(session.id(), 0, seed, 0, seed.length);
byte[] out = token.p11.C_SignFinal
@@ -179,6 +181,7 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
} catch (PKCS11Exception e) {
throw new ProviderException("Could not calculate PRF", e);
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(session);
}
}
@@ -189,15 +192,16 @@ final class P11TlsPrfGenerator extends KeyGeneratorSpi {
CK_TLS_PRF_PARAMS params = new CK_TLS_PRF_PARAMS(seed, label, out);
Session session = null;
+ long keyID = p11Key.getKeyID();
try {
session = token.getOpSession();
- long keyID = token.p11.C_DeriveKey(session.id(),
- new CK_MECHANISM(mechanism, params), p11Key.keyID, null);
- // ignore keyID, returned PRF bytes are in 'out'
+ token.p11.C_DeriveKey(session.id(),
+ new CK_MECHANISM(mechanism, params), keyID, null);
return new SecretKeySpec(out, "TlsPrf");
} catch (PKCS11Exception e) {
throw new ProviderException("Could not calculate PRF", e);
} finally {
+ p11Key.releaseKeyID();
token.releaseSession(session);
}
}
diff --git a/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
index c5799b44ab..50ee726254 100644
--- a/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
+++ b/src/share/classes/sun/security/pkcs11/wrapper/PKCS11.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@@ -1288,6 +1288,46 @@ public class PKCS11 {
******************************************************************************/
/**
+ * getNativeKeyInfo gets the key object attributes and values as an opaque
+ * byte array to be used in createNativeKey method.
+ * (Key management)
+ *
+ * @param hSession the session's handle
+ * @param hKey key's handle
+ * @param hWrappingKey key handle for wrapping the extracted sensitive keys.
+ * -1 if not used.
+ * @param pWrappingMech mechanism for wrapping the extracted sensitive keys
+ * @return an opaque byte array containing the key object attributes
+ * and values
+ * @exception PKCS11Exception If an internal PKCS#11 function returns other
+ * value than CKR_OK.
+ * @preconditions
+ * @postconditions
+ */
+ public native byte[] getNativeKeyInfo(long hSession, long hKey,
+ long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
+
+ /**
+ * createNativeKey creates a key object with attributes and values
+ * specified by parameter as an opaque byte array.
+ * (Key management)
+ *
+ * @param hSession the session's handle
+ * @param keyInfo opaque byte array containing key object attributes
+ * and values
+ * @param hWrappingKey key handle for unwrapping the extracted sensitive keys.
+ * -1 if not used.
+ * @param pWrappingMech mechanism for unwrapping the extracted sensitive keys
+ * @return key object handle
+ * @exception PKCS11Exception If an internal PKCS#11 function returns other
+ * value than CKR_OK.
+ * @preconditions
+ * @postconditions
+ */
+ public native long createNativeKey(long hSession, byte[] keyInfo,
+ long hWrappingKey, CK_MECHANISM pWrappingMech) throws PKCS11Exception;
+
+ /**
* C_GenerateKey generates a secret key, creating a new key
* object.
* (Key management)
diff --git a/src/share/classes/sun/security/provider/DigestBase.java b/src/share/classes/sun/security/provider/DigestBase.java
index c3ac4ac36f..89b1d77f31 100644
--- a/src/share/classes/sun/security/provider/DigestBase.java
+++ b/src/share/classes/sun/security/provider/DigestBase.java
@@ -29,6 +29,7 @@ import java.security.MessageDigestSpi;
import java.security.DigestException;
import java.security.ProviderException;
import java.util.Arrays;
+import java.util.Objects;
/**
* Common base message digest implementation for the Sun provider.
@@ -137,12 +138,35 @@ abstract class DigestBase extends MessageDigestSpi implements Cloneable {
// compress complete blocks
private int implCompressMultiBlock(byte[] b, int ofs, int limit) {
+ implCompressMultiBlockCheck(b, ofs, limit);
+ return implCompressMultiBlock0(b, ofs, limit);
+ }
+
+ private int implCompressMultiBlock0(byte[] b, int ofs, int limit) {
for (; ofs <= limit; ofs += blockSize) {
implCompress(b, ofs);
}
return ofs;
}
+ private void implCompressMultiBlockCheck(byte[] b, int ofs, int limit) {
+ if (limit < 0) {
+ return; // not an error because implCompressMultiBlockImpl won't execute if limit < 0
+ // and an exception is thrown if ofs < 0.
+ }
+
+ Objects.requireNonNull(b);
+
+ if (ofs < 0 || ofs >= b.length) {
+ throw new ArrayIndexOutOfBoundsException(ofs);
+ }
+
+ int endIndex = (limit / blockSize) * blockSize + blockSize - 1;
+ if (endIndex >= b.length) {
+ throw new ArrayIndexOutOfBoundsException(endIndex);
+ }
+ }
+
// reset this object. See JCA doc.
protected final void engineReset() {
if (bytesProcessed == 0) {
diff --git a/src/share/classes/sun/security/provider/SHA.java b/src/share/classes/sun/security/provider/SHA.java
index 24dc0b2897..dfa477adf2 100644
--- a/src/share/classes/sun/security/provider/SHA.java
+++ b/src/share/classes/sun/security/provider/SHA.java
@@ -27,6 +27,8 @@ package sun.security.provider;
import java.util.Arrays;
+import java.util.Objects;
+
import static sun.security.provider.ByteArrayAccess.*;
/**
@@ -123,8 +125,26 @@ public final class SHA extends DigestBase {
* "old" NIST Secure Hash Algorithm.
*/
void implCompress(byte[] buf, int ofs) {
+ implCompressCheck(buf, ofs);
+ implCompress0(buf, ofs);
+ }
+
+ private void implCompressCheck(byte[] buf, int ofs) {
+ Objects.requireNonNull(buf);
+
+ // The checks performed by the method 'b2iBig64'
+ // are sufficient for the case when the method
+ // 'implCompressImpl' is replaced with a compiler
+ // intrinsic.
b2iBig64(buf, ofs, W);
+ }
+ // The method 'implCompressImpl seems not to use its parameters.
+ // The method can, however, be replaced with a compiler intrinsic
+ // that operates directly on the array 'buf' (starting from
+ // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs'
+ // must be passed as parameter to the method.
+ private void implCompress0(byte[] buf, int ofs) {
// The first 16 ints have the byte stream, compute the rest of
// the buffer
for (int t = 16; t <= 79; t++) {
diff --git a/src/share/classes/sun/security/provider/SHA2.java b/src/share/classes/sun/security/provider/SHA2.java
index 6f34c8d55d..25f13d0736 100644
--- a/src/share/classes/sun/security/provider/SHA2.java
+++ b/src/share/classes/sun/security/provider/SHA2.java
@@ -27,6 +27,8 @@ package sun.security.provider;
import java.util.Arrays;
+import java.util.Objects;
+
import static sun.security.provider.ByteArrayAccess.*;
/**
@@ -193,8 +195,26 @@ abstract class SHA2 extends DigestBase {
* Process the current block to update the state variable state.
*/
void implCompress(byte[] buf, int ofs) {
+ implCompressCheck(buf, ofs);
+ implCompress0(buf, ofs);
+ }
+
+ private void implCompressCheck(byte[] buf, int ofs) {
+ Objects.requireNonNull(buf);
+
+ // The checks performed by the method 'b2iBig64'
+ // are sufficient for the case when the method
+ // 'implCompressImpl' is replaced with a compiler
+ // intrinsic.
b2iBig64(buf, ofs, W);
+ }
+ // The method 'implCompressImpl' seems not to use its parameters.
+ // The method can, however, be replaced with a compiler intrinsic
+ // that operates directly on the array 'buf' (starting from
+ // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs'
+ // must be passed as parameter to the method.
+ private void implCompress0(byte[] buf, int ofs) {
// The first 16 ints are from the byte stream, compute the rest of
// the W[]'s
for (int t = 16; t < ITERATION; t++) {
diff --git a/src/share/classes/sun/security/provider/SHA5.java b/src/share/classes/sun/security/provider/SHA5.java
index 90c12526d8..ceba1fc2b2 100644
--- a/src/share/classes/sun/security/provider/SHA5.java
+++ b/src/share/classes/sun/security/provider/SHA5.java
@@ -26,6 +26,7 @@
package sun.security.provider;
import java.util.Arrays;
+import java.util.Objects;
import static sun.security.provider.ByteArrayAccess.*;
@@ -209,8 +210,26 @@ abstract class SHA5 extends DigestBase {
* "old" NIST Secure Hash Algorithm.
*/
final void implCompress(byte[] buf, int ofs) {
+ implCompressCheck(buf, ofs);
+ implCompress0(buf, ofs);
+ }
+
+ private void implCompressCheck(byte[] buf, int ofs) {
+ Objects.requireNonNull(buf);
+
+ // The checks performed by the method 'b2iBig128'
+ // are sufficient for the case when the method
+ // 'implCompressImpl' is replaced with a compiler
+ // intrinsic.
b2lBig128(buf, ofs, W);
+ }
+ // The method 'implCompressImpl' seems not to use its parameters.
+ // The method can, however, be replaced with a compiler intrinsic
+ // that operates directly on the array 'buf' (starting from
+ // offset 'ofs') and not on array 'W', therefore 'buf' and 'ofs'
+ // must be passed as parameter to the method.
+ private final void implCompress0(byte[] buf, int ofs) {
// The first 16 longs are from the byte stream, compute the rest of
// the W[]'s
for (int t = 16; t < ITERATION; t++) {
diff --git a/src/share/classes/sun/security/ssl/EllipticCurvesExtension.java b/src/share/classes/sun/security/ssl/EllipticCurvesExtension.java
index edaf8e211e..70aa79ddd0 100644
--- a/src/share/classes/sun/security/ssl/EllipticCurvesExtension.java
+++ b/src/share/classes/sun/security/ssl/EllipticCurvesExtension.java
@@ -168,20 +168,11 @@ final class EllipticCurvesExtension extends HelloExtension {
"contains no supported elliptic curves");
}
} else { // default curves
- int[] ids;
- if (requireFips) {
- ids = new int[] {
- // only NIST curves in FIPS mode
- 23, 24, 25, 9, 10, 11, 12, 13, 14,
- };
- } else {
- ids = new int[] {
- // NIST curves first
- 23, 24, 25, 9, 10, 11, 12, 13, 14,
- // non-NIST curves
- 22,
- };
- }
+ int[] ids = new int[] {
+ // The three widely-used NIST curves:
+ // secp256r1, secp384r1 & secp521r1
+ 23, 24, 25
+ };
idList = new ArrayList<>(ids.length);
for (int curveId : ids) {
diff --git a/src/share/classes/sun/security/ssl/SSLContextImpl.java b/src/share/classes/sun/security/ssl/SSLContextImpl.java
index 74176346c8..4753b02fff 100644
--- a/src/share/classes/sun/security/ssl/SSLContextImpl.java
+++ b/src/share/classes/sun/security/ssl/SSLContextImpl.java
@@ -873,12 +873,20 @@ public abstract class SSLContextImpl extends SSLContextSpi {
}
private static TrustManager[] getTrustManagers() throws Exception {
- KeyStore ks =
- TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
-
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(ks);
+ TrustManagerFactory.getDefaultAlgorithm());
+ if ("SunJSSE".equals(tmf.getProvider().getName())) {
+ // The implementation will load the default KeyStore
+ // automatically. Cached trust materials may be used
+ // for performance improvement.
+ tmf.init((KeyStore)null);
+ } else {
+ // Use the explicitly specified KeyStore for third party's
+ // TrustManagerFactory implementation.
+ KeyStore ks = TrustStoreManager.getTrustedKeyStore();
+ tmf.init(ks);
+ }
+
return tmf.getTrustManagers();
}
@@ -1106,8 +1114,9 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
checkAdditionalTrust(chain, authType, engine, false);
}
- private void checkAdditionalTrust(X509Certificate[] chain, String authType,
- Socket socket, boolean isClient) throws CertificateException {
+ private void checkAdditionalTrust(X509Certificate[] chain,
+ String authType, Socket socket,
+ boolean checkClientTrusted) throws CertificateException {
if (socket != null && socket.isConnected() &&
socket instanceof SSLSocket) {
@@ -1121,9 +1130,8 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
String identityAlg = sslSocket.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- X509TrustManagerImpl.checkIdentity(
- hostname, chain[0], identityAlg);
+ X509TrustManagerImpl.checkIdentity(session, chain,
+ identityAlg, checkClientTrusted);
}
// try the best to check the algorithm constraints
@@ -1147,12 +1155,13 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(sslSocket, true);
}
- checkAlgorithmConstraints(chain, constraints, isClient);
+ checkAlgorithmConstraints(chain, constraints, checkClientTrusted);
}
}
- private void checkAdditionalTrust(X509Certificate[] chain, String authType,
- SSLEngine engine, boolean isClient) throws CertificateException {
+ private void checkAdditionalTrust(X509Certificate[] chain,
+ String authType, SSLEngine engine,
+ boolean checkClientTrusted) throws CertificateException {
if (engine != null) {
SSLSession session = engine.getHandshakeSession();
if (session == null) {
@@ -1163,9 +1172,8 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
String identityAlg = engine.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- X509TrustManagerImpl.checkIdentity(
- hostname, chain[0], identityAlg);
+ X509TrustManagerImpl.checkIdentity(session, chain,
+ identityAlg, checkClientTrusted);
}
// try the best to check the algorithm constraints
@@ -1189,12 +1197,13 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
constraints = new SSLAlgorithmConstraints(engine, true);
}
- checkAlgorithmConstraints(chain, constraints, isClient);
+ checkAlgorithmConstraints(chain, constraints, checkClientTrusted);
}
}
private void checkAlgorithmConstraints(X509Certificate[] chain,
- AlgorithmConstraints constraints, boolean isClient) throws CertificateException {
+ AlgorithmConstraints constraints,
+ boolean checkClientTrusted) throws CertificateException {
try {
// Does the certificate chain end with a trusted certificate?
@@ -1214,7 +1223,8 @@ final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
if (checkedLength >= 0) {
AlgorithmChecker checker =
new AlgorithmChecker(constraints, null,
- (isClient ? Validator.VAR_TLS_CLIENT : Validator.VAR_TLS_SERVER));
+ (checkClientTrusted ? Validator.VAR_TLS_CLIENT :
+ Validator.VAR_TLS_SERVER));
checker.init(false);
for (int i = checkedLength; i >= 0; i--) {
Certificate cert = chain[i];
diff --git a/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java b/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java
index 51fac9bc6e..d728821717 100644
--- a/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java
+++ b/src/share/classes/sun/security/ssl/SSLSessionContextImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,10 +33,13 @@ import java.util.Locale;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
+import sun.security.action.GetIntegerAction;
import sun.security.util.Cache;
final class SSLSessionContextImpl implements SSLSessionContext {
+ private final static int DEFAULT_MAX_CACHE_SIZE = 20480;
+
private Cache<SessionId, SSLSessionImpl> sessionCache;
// session cache, session id as key
private Cache<String, SSLSessionImpl> sessionHostPortCache;
@@ -197,21 +200,19 @@ final class SSLSessionContextImpl implements SSLSessionContext {
}
private int getDefaultCacheLimit() {
- int cacheLimit = 0;
try {
- String s = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(
- "javax.net.ssl.sessionCacheSize");
- }
- });
- cacheLimit = (s != null) ? Integer.valueOf(s).intValue() : 0;
+ int defaultCacheLimit =
+ java.security.AccessController.doPrivileged(
+ new GetIntegerAction("javax.net.ssl.sessionCacheSize",
+ DEFAULT_MAX_CACHE_SIZE)).intValue();
+
+ if (defaultCacheLimit >= 0) {
+ return defaultCacheLimit;
+ }
} catch (Exception e) {
}
- return (cacheLimit > 0) ? cacheLimit : 0;
+ return DEFAULT_MAX_CACHE_SIZE;
}
boolean isTimedout(SSLSession sess) {
diff --git a/src/share/classes/sun/security/ssl/SessionId.java b/src/share/classes/sun/security/ssl/SessionId.java
index 063e86d520..21a46c042d 100644
--- a/src/share/classes/sun/security/ssl/SessionId.java
+++ b/src/share/classes/sun/security/ssl/SessionId.java
@@ -27,6 +27,7 @@
package sun.security.ssl;
import java.security.SecureRandom;
+import java.util.Arrays;
import javax.net.ssl.SSLProtocolException;
/**
@@ -91,11 +92,7 @@ class SessionId
@Override
public int hashCode ()
{
- int retval = 0;
-
- for (int i = 0; i < sessionId.length; i++)
- retval += sessionId [i];
- return retval;
+ return Arrays.hashCode(sessionId);
}
/** Returns true if the parameter is the same session ID */
diff --git a/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java b/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java
index 8b598c333f..94b5acf383 100644
--- a/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java
+++ b/src/share/classes/sun/security/ssl/TrustManagerFactoryImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -32,6 +32,7 @@ import java.security.cert.*;
import javax.net.ssl.*;
import sun.security.validator.Validator;
+import sun.security.validator.TrustStoreUtil;
abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
@@ -47,7 +48,7 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
protected void engineInit(KeyStore ks) throws KeyStoreException {
if (ks == null) {
try {
- ks = getCacertsKeyStore("trustmanager");
+ trustManager = getInstance(TrustStoreManager.getTrustedCerts());
} catch (SecurityException se) {
// eat security exceptions but report other throwables
if (debug != null && Debug.isOn("trustmanager")) {
@@ -72,14 +73,17 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
"SunX509: skip default keystore: " + e);
}
throw new KeyStoreException(
- "problem accessing trust store" + e);
+ "problem accessing trust store", e);
}
+ } else {
+ trustManager = getInstance(TrustStoreUtil.getTrustedCerts(ks));
}
- trustManager = getInstance(ks);
+
isInitialized = true;
}
- abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
+ abstract X509TrustManager getInstance(
+ Collection<X509Certificate> trustedCerts);
abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException;
@@ -126,126 +130,14 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
});
}
- /**
- * Returns the keystore with the configured CA certificates.
- */
- static KeyStore getCacertsKeyStore(String dbgname) throws Exception
- {
- String storeFileName = null;
- File storeFile = null;
- FileInputStream fis = null;
- String defaultTrustStoreType;
- String defaultTrustStoreProvider;
- final HashMap<String,String> props = new HashMap<>();
- final String sep = File.separator;
- KeyStore ks = null;
-
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws Exception {
- props.put("trustStore", System.getProperty(
- "javax.net.ssl.trustStore"));
- props.put("javaHome", System.getProperty(
- "java.home"));
- props.put("trustStoreType", System.getProperty(
- "javax.net.ssl.trustStoreType",
- KeyStore.getDefaultType()));
- props.put("trustStoreProvider", System.getProperty(
- "javax.net.ssl.trustStoreProvider", ""));
- props.put("trustStorePasswd", System.getProperty(
- "javax.net.ssl.trustStorePassword", ""));
- return null;
- }
- });
-
- /*
- * Try:
- * javax.net.ssl.trustStore (if this variable exists, stop)
- * jssecacerts
- * cacerts
- *
- * If none exists, we use an empty keystore.
- */
-
- try {
- storeFileName = props.get("trustStore");
- if (!"NONE".equals(storeFileName)) {
- if (storeFileName != null) {
- storeFile = new File(storeFileName);
- fis = getFileInputStream(storeFile);
- } else {
- String javaHome = props.get("javaHome");
- storeFile = new File(javaHome + sep + "lib" + sep
- + "security" + sep +
- "jssecacerts");
- if ((fis = getFileInputStream(storeFile)) == null) {
- storeFile = new File(javaHome + sep + "lib" + sep
- + "security" + sep +
- "cacerts");
- fis = getFileInputStream(storeFile);
- }
- }
-
- if (fis != null) {
- storeFileName = storeFile.getPath();
- } else {
- storeFileName = "No File Available, using empty keystore.";
- }
- }
-
- defaultTrustStoreType = props.get("trustStoreType");
- defaultTrustStoreProvider = props.get("trustStoreProvider");
- if (debug != null && Debug.isOn(dbgname)) {
- System.out.println("trustStore is: " + storeFileName);
- System.out.println("trustStore type is : " +
- defaultTrustStoreType);
- System.out.println("trustStore provider is : " +
- defaultTrustStoreProvider);
- }
-
- /*
- * Try to initialize trust store.
- */
- if (defaultTrustStoreType.length() != 0) {
- if (debug != null && Debug.isOn(dbgname)) {
- System.out.println("init truststore");
- }
- if (defaultTrustStoreProvider.length() == 0) {
- ks = KeyStore.getInstance(defaultTrustStoreType);
- } else {
- ks = KeyStore.getInstance(defaultTrustStoreType,
- defaultTrustStoreProvider);
- }
- char[] passwd = null;
- String defaultTrustStorePassword =
- props.get("trustStorePasswd");
- if (defaultTrustStorePassword.length() != 0)
- passwd = defaultTrustStorePassword.toCharArray();
-
- // if trustStore is NONE, fis will be null
- ks.load(fis, passwd);
-
- // Zero out the temporary password storage
- if (passwd != null) {
- for (int i = 0; i < passwd.length; i++) {
- passwd[i] = (char)0;
- }
- }
- }
- } finally {
- if (fis != null) {
- fis.close();
- }
- }
-
- return ks;
- }
-
public static final class SimpleFactory extends TrustManagerFactoryImpl {
@Override
- X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
- return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
+ X509TrustManager getInstance(
+ Collection<X509Certificate> trustedCerts) {
+ return new X509TrustManagerImpl(
+ Validator.TYPE_SIMPLE, trustedCerts);
}
+
@Override
X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException {
@@ -253,13 +145,15 @@ abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
("SunX509 TrustManagerFactory does not use "
+ "ManagerFactoryParameters");
}
- }
+ }
public static final class PKIXFactory extends TrustManagerFactoryImpl {
@Override
- X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
- return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
+ X509TrustManager getInstance(
+ Collection<X509Certificate> trustedCerts) {
+ return new X509TrustManagerImpl(Validator.TYPE_PKIX, trustedCerts);
}
+
@Override
X509TrustManager getInstance(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException {
diff --git a/src/share/classes/sun/security/ssl/TrustStoreManager.java b/src/share/classes/sun/security/ssl/TrustStoreManager.java
new file mode 100644
index 0000000000..3fceccec29
--- /dev/null
+++ b/src/share/classes/sun/security/ssl/TrustStoreManager.java
@@ -0,0 +1,395 @@
+/*
+ * Copyright (c) 2016, 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.ssl;
+
+import java.lang.ref.WeakReference;
+import java.io.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.cert.*;
+import java.security.cert.Certificate;
+
+import sun.security.action.*;
+import sun.security.validator.TrustStoreUtil;
+
+/**
+ * Collection of static utility methods to manage the default trusted KeyStores
+ * effectively.
+ */
+final class TrustStoreManager {
+ private static final Debug debug = Debug.getInstance("ssl");
+
+ // A singleton service to manage the default trusted KeyStores effectively.
+ private static final TrustAnchorManager tam = new TrustAnchorManager();
+
+ // Restrict instantiation of this class.
+ private TrustStoreManager() {
+ // empty
+ }
+
+ /**
+ * Return an unmodifiable set of all trusted X509Certificates contained
+ * in the default trusted KeyStore.
+ */
+ public static Set<X509Certificate> getTrustedCerts() throws Exception {
+ return tam.getTrustedCerts(TrustStoreDescriptor.createInstance());
+ }
+
+ /**
+ * Return an instance of the default trusted KeyStore.
+ */
+ public static KeyStore getTrustedKeyStore() throws Exception {
+ return tam.getKeyStore(TrustStoreDescriptor.createInstance());
+ }
+
+ /**
+ * A descriptor of the default trusted KeyStore.
+ *
+ * The preference of the default trusted KeyStore is:
+ * javax.net.ssl.trustStore
+ * jssecacerts
+ * cacerts
+ */
+ private static final class TrustStoreDescriptor {
+ private static final String fileSep = File.separator;
+ private static final String defaultStorePath =
+ GetPropertyAction.privilegedGetProperty("java.home") +
+ fileSep + "lib" + fileSep + "security";
+ private static final String defaultStore =
+ defaultStorePath + fileSep + "cacerts";
+ private static final String jsseDefaultStore =
+ defaultStorePath + fileSep + "jssecacerts";
+
+ // the trust store name
+ private final String storeName;
+
+ // the trust store type, JKS/PKCS12
+ private final String storeType;
+
+ // the provider of the trust store
+ private final String storeProvider;
+
+ // the password used for the trust store
+ private final String storePassword;
+
+ // the File object of the trust store
+ private final File storeFile;
+
+ // the last modified time of the store
+ private final long lastModified;
+
+ private TrustStoreDescriptor(String storeName, String storeType,
+ String storeProvider, String storePassword,
+ File storeFile, long lastModified) {
+ this.storeName = storeName;
+ this.storeType = storeType;
+ this.storeProvider = storeProvider;
+ this.storePassword = storePassword;
+ this.storeFile = storeFile;
+ this.lastModified = lastModified;
+
+ if (debug != null && Debug.isOn("trustmanager")) {
+ System.out.println(
+ "trustStore is: " + storeName + "\n" +
+ "trustStore type is: " + storeType + "\n" +
+ "trustStore provider is: " + storeProvider + "\n" +
+ "the last modified time is: " + (new Date(lastModified)));
+ }
+ }
+
+ /**
+ * Create an instance of TrustStoreDescriptor for the default
+ * trusted KeyStore.
+ */
+ static TrustStoreDescriptor createInstance() {
+ return AccessController.doPrivileged(new PrivilegedAction<TrustStoreDescriptor>() {
+
+ @Override
+ public TrustStoreDescriptor run() {
+ // Get the system properties for trust store.
+ String storePropName = System.getProperty(
+ "javax.net.ssl.trustStore", jsseDefaultStore);
+ String storePropType = System.getProperty(
+ "javax.net.ssl.trustStoreType",
+ KeyStore.getDefaultType());
+ String storePropProvider = System.getProperty(
+ "javax.net.ssl.trustStoreProvider", "");
+ String storePropPassword = System.getProperty(
+ "javax.net.ssl.trustStorePassword", "");
+
+ String temporaryName = "";
+ File temporaryFile = null;
+ long temporaryTime = 0L;
+ if (!"NONE".equals(storePropName)) {
+ String[] fileNames =
+ new String[] {storePropName, defaultStore};
+ for (String fileName : fileNames) {
+ File f = new File(fileName);
+ if (f.isFile() && f.canRead()) {
+ temporaryName = fileName;;
+ temporaryFile = f;
+ temporaryTime = f.lastModified();
+
+ break;
+ }
+
+ // Not break, the file is inaccessible.
+ if (debug != null &&
+ Debug.isOn("trustmanager")) {
+ System.out.println(
+ "Inaccessible trust store: " +
+ storePropName);
+ }
+ }
+ } else {
+ temporaryName = storePropName;
+ }
+
+ return new TrustStoreDescriptor(
+ temporaryName, storePropType, storePropProvider,
+ storePropPassword, temporaryFile, temporaryTime);
+ }
+ });
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+
+ if (obj instanceof TrustStoreDescriptor) {
+ TrustStoreDescriptor that = (TrustStoreDescriptor)obj;
+ return ((this.lastModified == that.lastModified) &&
+ Objects.equals(this.storeName, that.storeName) &&
+ Objects.equals(this.storeType, that.storeType) &&
+ Objects.equals(this.storeProvider, that.storeProvider));
+ }
+
+ return false;
+ }
+
+
+ // Please be careful if computing security-sensitive attributes'
+ // hash code. For example the storePassword should not be computed.
+ @Override
+ public int hashCode() {
+ int result = 17;
+
+ if (storeName != null && !storeName.isEmpty()) {
+ result = 31 * result + storeName.hashCode();
+ }
+
+ if (storeType != null && !storeType.isEmpty()) {
+ result = 31 * result + storeType.hashCode();
+ }
+
+ if (storeProvider != null && !storeProvider.isEmpty()) {
+ result = 31 * result + storeProvider.hashCode();
+ }
+
+ if (storeFile != null) {
+ result = 31 * result + storeFile.hashCode();
+ }
+
+ if (lastModified != 0L) {
+ result = (int)(31 * result + lastModified);
+ }
+
+ return result;
+ }
+ }
+
+ /**
+ * The trust anchors manager used to expedite the performance.
+ *
+ * This class can be used to provide singleton services to access default
+ * trust KeyStore more effectively.
+ */
+ private static final class TrustAnchorManager {
+ // Last trust store descriptor.
+ private TrustStoreDescriptor descriptor;
+
+ // The key store used for the trust anchors.
+ //
+ // Use weak reference so that the heavy loaded KeyStore object can
+ // be atomically cleared, and reloaded if needed.
+ private WeakReference<KeyStore> ksRef;
+
+ // The trusted X.509 certificates in the key store.
+ //
+ // Use weak reference so that the heavy loaded certificates collection
+ // objects can be atomically cleared, and reloaded if needed.
+ private WeakReference<Set<X509Certificate>> csRef;
+
+ private TrustAnchorManager() {
+ this.descriptor = null;
+ this.ksRef = new WeakReference<>(null);
+ this.csRef = new WeakReference<>(null);
+ }
+
+ /**
+ * Get the default trusted KeyStore with the specified descriptor.
+ *
+ * @return null if the underlying KeyStore is not available.
+ */
+ synchronized KeyStore getKeyStore(
+ TrustStoreDescriptor descriptor) throws Exception {
+
+ TrustStoreDescriptor temporaryDesc = this.descriptor;
+ KeyStore ks = ksRef.get();
+ if ((ks != null) && descriptor.equals(temporaryDesc)) {
+ return ks;
+ }
+
+ // Reload a new key store.
+ if ((debug != null) && Debug.isOn("trustmanager")) {
+ System.out.println("Reload the trust store");
+ }
+
+ ks = loadKeyStore(descriptor);
+ this.descriptor = descriptor;
+ this.ksRef = new WeakReference<>(ks);
+
+ return ks;
+ }
+
+ /**
+ * Get trusted certificates in the default trusted KeyStore with
+ * the specified descriptor.
+ *
+ * @return empty collection if the underlying KeyStore is not available.
+ */
+ synchronized Set<X509Certificate> getTrustedCerts(
+ TrustStoreDescriptor descriptor) throws Exception {
+
+ KeyStore ks = null;
+ TrustStoreDescriptor temporaryDesc = this.descriptor;
+ Set<X509Certificate> certs = csRef.get();
+ if (certs != null) {
+ if (descriptor.equals(temporaryDesc)) {
+ return certs;
+ } else {
+ // Use the new descriptor.
+ this.descriptor = descriptor;
+ }
+ } else {
+ // Try to use the cached store at first.
+ if (descriptor.equals(temporaryDesc)) {
+ ks = ksRef.get();
+ } else {
+ // Use the new descriptor.
+ this.descriptor = descriptor;
+ }
+ }
+
+ // Reload the trust store if needed.
+ if (ks == null) {
+ if ((debug != null) && Debug.isOn("trustmanager")) {
+ System.out.println("Reload the trust store");
+ }
+ ks = loadKeyStore(descriptor);
+ }
+
+ // Reload trust certs from the key store.
+ if ((debug != null) && Debug.isOn("trustmanager")) {
+ System.out.println("Reload trust certs");
+ }
+
+ certs = loadTrustedCerts(ks);
+ if ((debug != null) && Debug.isOn("trustmanager")) {
+ System.out.println("Reloaded " + certs.size() + " trust certs");
+ }
+
+ // Note that as ks is a local variable, it is not
+ // necessary to add it to the ksRef weak reference.
+ this.csRef = new WeakReference<>(certs);
+
+ return certs;
+ }
+
+ /**
+ * Load the the KeyStore as described in the specified descriptor.
+ */
+ private static KeyStore loadKeyStore(
+ TrustStoreDescriptor descriptor) throws Exception {
+ if (!"NONE".equals(descriptor.storeName) &&
+ descriptor.storeFile == null) {
+
+ // No file available, no KeyStore available.
+ if (debug != null && Debug.isOn("trustmanager")) {
+ System.out.println("No available key store");
+ }
+
+ return null;
+ }
+
+ KeyStore ks;
+ if (descriptor.storeProvider.isEmpty()) {
+ ks = KeyStore.getInstance(descriptor.storeType);
+ } else {
+ ks = KeyStore.getInstance(
+ descriptor.storeType, descriptor.storeProvider);
+ }
+
+ char[] password = null;
+ if (!descriptor.storePassword.isEmpty()) {
+ password = descriptor.storePassword.toCharArray();
+ }
+
+ if (!"NONE".equals(descriptor.storeName)) {
+ try (FileInputStream fis = AccessController.doPrivileged(
+ new OpenFileInputStreamAction(descriptor.storeFile))) {
+ ks.load(fis, password);
+ } catch (FileNotFoundException fnfe) {
+ // No file available, no KeyStore available.
+ if (debug != null && Debug.isOn("trustmanager")) {
+ System.out.println(
+ "Not available key store: " + descriptor.storeName);
+ }
+
+ return null;
+ }
+ } else {
+ ks.load(null, password);
+ }
+
+ return ks;
+ }
+
+ /**
+ * Load trusted certificates from the specified KeyStore.
+ */
+ private static Set<X509Certificate> loadTrustedCerts(KeyStore ks) {
+ if (ks == null) {
+ return Collections.<X509Certificate>emptySet();
+ }
+
+ return TrustStoreUtil.getTrustedCerts(ks);
+ }
+ }
+}
diff --git a/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java b/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
index 1137c0739a..19801b16ec 100644
--- a/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
+++ b/src/share/classes/sun/security/ssl/X509TrustManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -68,16 +68,21 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
private static final Debug debug = Debug.getInstance("ssl");
- X509TrustManagerImpl(String validatorType, KeyStore ks)
- throws KeyStoreException {
+ X509TrustManagerImpl(String validatorType,
+ Collection<X509Certificate> trustedCerts) {
+
this.validatorType = validatorType;
this.pkixParams = null;
- if (ks == null) {
+
+ if (trustedCerts == null) {
trustedCerts = Collections.<X509Certificate>emptySet();
- } else {
- trustedCerts = KeyStores.getTrustedCerts(ks);
}
- showTrustedCerts();
+
+ this.trustedCerts = trustedCerts;
+
+ if (debug != null && Debug.isOn("trustmanager")) {
+ showTrustedCerts();
+ }
}
X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
@@ -90,7 +95,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
Validator v = getValidator(Validator.VAR_TLS_SERVER);
trustedCerts = v.getTrustedCertificates();
serverValidator = v;
- showTrustedCerts();
+
+ if (debug != null && Debug.isOn("trustmanager")) {
+ showTrustedCerts();
+ }
}
@Override
@@ -137,7 +145,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
private Validator checkTrustedInit(X509Certificate[] chain,
- String authType, boolean isClient) {
+ String authType, boolean checkClientTrusted) {
if (chain == null || chain.length == 0) {
throw new IllegalArgumentException(
"null or zero-length certificate chain");
@@ -149,7 +157,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
Validator v = null;
- if (isClient) {
+ if (checkClientTrusted) {
v = clientValidator;
if (v == null) {
synchronized (this) {
@@ -179,9 +187,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
- private void checkTrusted(X509Certificate[] chain, String authType,
- Socket socket, boolean isClient) throws CertificateException {
- Validator v = checkTrustedInit(chain, authType, isClient);
+ private void checkTrusted(X509Certificate[] chain,
+ String authType, Socket socket,
+ boolean checkClientTrusted) throws CertificateException {
+ Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
AlgorithmConstraints constraints = null;
if ((socket != null) && socket.isConnected() &&
@@ -197,8 +206,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
String identityAlg = sslSocket.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
- checkIdentity(session, chain[0], identityAlg, isClient,
- getRequestedServerNames(socket));
+ checkIdentity(session, chain, identityAlg, checkClientTrusted);
}
// create the algorithm constraints
@@ -223,7 +231,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
X509Certificate[] trustedChain = null;
- if (isClient) {
+ if (checkClientTrusted) {
trustedChain = validate(v, chain, constraints, null);
} else {
trustedChain = validate(v, chain, constraints, authType);
@@ -234,9 +242,10 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
}
- private void checkTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine, boolean isClient) throws CertificateException {
- Validator v = checkTrustedInit(chain, authType, isClient);
+ private void checkTrusted(X509Certificate[] chain,
+ String authType, SSLEngine engine,
+ boolean checkClientTrusted) throws CertificateException {
+ Validator v = checkTrustedInit(chain, authType, checkClientTrusted);
AlgorithmConstraints constraints = null;
if (engine != null) {
@@ -249,8 +258,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
String identityAlg = engine.getSSLParameters().
getEndpointIdentificationAlgorithm();
if (identityAlg != null && identityAlg.length() != 0) {
- checkIdentity(session, chain[0], identityAlg, isClient,
- getRequestedServerNames(engine));
+ checkIdentity(session, chain, identityAlg, checkClientTrusted);
}
// create the algorithm constraints
@@ -275,7 +283,7 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
X509Certificate[] trustedChain = null;
- if (isClient) {
+ if (checkClientTrusted) {
trustedChain = validate(v, chain, constraints, null);
} else {
trustedChain = validate(v, chain, constraints, authType);
@@ -287,22 +295,20 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
private void showTrustedCerts() {
- if (debug != null && Debug.isOn("trustmanager")) {
- for (X509Certificate cert : trustedCerts) {
- System.out.println("adding as trusted cert:");
- System.out.println(" Subject: "
- + cert.getSubjectX500Principal());
- System.out.println(" Issuer: "
- + cert.getIssuerX500Principal());
- System.out.println(" Algorithm: "
- + cert.getPublicKey().getAlgorithm()
- + "; Serial number: 0x"
- + cert.getSerialNumber().toString(16));
- System.out.println(" Valid from "
- + cert.getNotBefore() + " until "
- + cert.getNotAfter());
- System.out.println();
- }
+ for (X509Certificate cert : trustedCerts) {
+ System.out.println("adding as trusted cert:");
+ System.out.println(" Subject: "
+ + cert.getSubjectX500Principal());
+ System.out.println(" Issuer: "
+ + cert.getIssuerX500Principal());
+ System.out.println(" Algorithm: "
+ + cert.getPublicKey().getAlgorithm()
+ + "; Serial number: 0x"
+ + cert.getSerialNumber().toString(16));
+ System.out.println(" Valid from "
+ + cert.getNotBefore() + " until "
+ + cert.getNotAfter());
+ System.out.println();
}
}
@@ -367,13 +373,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
if (socket != null && socket.isConnected() &&
socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket)socket;
- SSLSession session = sslSocket.getHandshakeSession();
-
- if (session != null && (session instanceof ExtendedSSLSession)) {
- ExtendedSSLSession extSession = (ExtendedSSLSession)session;
- return extSession.getRequestedServerNames();
- }
+ return getRequestedServerNames(
+ ((SSLSocket)socket).getHandshakeSession());
}
return Collections.<SNIServerName>emptyList();
@@ -382,12 +383,16 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
// Also used by X509KeyManagerImpl
static List<SNIServerName> getRequestedServerNames(SSLEngine engine) {
if (engine != null) {
- SSLSession session = engine.getHandshakeSession();
+ return getRequestedServerNames(engine.getHandshakeSession());
+ }
- if (session != null && (session instanceof ExtendedSSLSession)) {
- ExtendedSSLSession extSession = (ExtendedSSLSession)session;
- return extSession.getRequestedServerNames();
- }
+ return Collections.<SNIServerName>emptyList();
+ }
+
+ private static List<SNIServerName> getRequestedServerNames(
+ SSLSession session) {
+ if (session != null && (session instanceof ExtendedSSLSession)) {
+ return ((ExtendedSSLSession)session).getRequestedServerNames();
}
return Collections.<SNIServerName>emptyList();
@@ -408,22 +413,23 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
* the identity checking aginst the server_name extension if present, and
* may failove to peer host checking.
*/
- private static void checkIdentity(SSLSession session,
- X509Certificate cert,
+ static void checkIdentity(SSLSession session,
+ X509Certificate [] trustedChain,
String algorithm,
- boolean isClient,
- List<SNIServerName> sniNames) throws CertificateException {
+ boolean checkClientTrusted) throws CertificateException {
boolean identifiable = false;
String peerHost = session.getPeerHost();
- if (isClient) {
- String hostname = getHostNameInSNI(sniNames);
- if (hostname != null) {
+ if (!checkClientTrusted) {
+ List<SNIServerName> sniNames = getRequestedServerNames(session);
+ String sniHostName = getHostNameInSNI(sniNames);
+ if (sniHostName != null) {
try {
- checkIdentity(hostname, cert, algorithm);
+ checkIdentity(sniHostName,
+ trustedChain[0], algorithm);
identifiable = true;
} catch (CertificateException ce) {
- if (hostname.equalsIgnoreCase(peerHost)) {
+ if (sniHostName.equalsIgnoreCase(peerHost)) {
throw ce;
}
@@ -433,7 +439,8 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager
}
if (!identifiable) {
- checkIdentity(peerHost, cert, algorithm);
+ checkIdentity(peerHost,
+ trustedChain[0], algorithm);
}
}
diff --git a/src/share/classes/sun/security/util/ArrayUtil.java b/src/share/classes/sun/security/util/ArrayUtil.java
new file mode 100644
index 0000000000..ddff7f43d4
--- /dev/null
+++ b/src/share/classes/sun/security/util/ArrayUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018, 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;
+
+/**
+ * This class holds the various utility methods for array range checks.
+ */
+
+public final class ArrayUtil {
+
+ private static void swap(byte[] arr, int i, int j) {
+ byte tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+
+ public static void reverse(byte [] arr) {
+ int i = 0;
+ int j = arr.length - 1;
+
+ while (i < j) {
+ swap(arr, i, j);
+ i++;
+ j--;
+ }
+ }
+}
diff --git a/src/share/classes/sun/security/util/DerIndefLenConverter.java b/src/share/classes/sun/security/util/DerIndefLenConverter.java
index cbd5ecc00e..9eb44862cb 100644
--- a/src/share/classes/sun/security/util/DerIndefLenConverter.java
+++ b/src/share/classes/sun/security/util/DerIndefLenConverter.java
@@ -92,37 +92,41 @@ class DerIndefLenConverter {
private void parseTag() throws IOException {
if (dataPos == dataSize)
return;
- if (isEOC(data[dataPos]) && (data[dataPos + 1] == 0)) {
- int numOfEncapsulatedLenBytes = 0;
- Object elem = null;
- int index;
- for (index = ndefsList.size()-1; index >= 0; index--) {
- // Determine the first element in the vector that does not
- // have a matching EOC
- elem = ndefsList.get(index);
- if (elem instanceof Integer) {
- break;
- } else {
- numOfEncapsulatedLenBytes += ((byte[])elem).length - 3;
+ try {
+ if (isEOC(data[dataPos]) && (data[dataPos + 1] == 0)) {
+ int numOfEncapsulatedLenBytes = 0;
+ Object elem = null;
+ int index;
+ for (index = ndefsList.size()-1; index >= 0; index--) {
+ // Determine the first element in the vector that does not
+ // have a matching EOC
+ elem = ndefsList.get(index);
+ if (elem instanceof Integer) {
+ break;
+ } else {
+ numOfEncapsulatedLenBytes += ((byte[])elem).length - 3;
+ }
}
+ if (index < 0) {
+ throw new IOException("EOC does not have matching " +
+ "indefinite-length tag");
+ }
+ int sectionLen = dataPos - ((Integer)elem).intValue() +
+ numOfEncapsulatedLenBytes;
+ byte[] sectionLenBytes = getLengthBytes(sectionLen);
+ ndefsList.set(index, sectionLenBytes);
+ unresolved--;
+
+ // Add the number of bytes required to represent this section
+ // to the total number of length bytes,
+ // and subtract the indefinite-length tag (1 byte) and
+ // EOC bytes (2 bytes) for this section
+ numOfTotalLenBytes += (sectionLenBytes.length - 3);
}
- if (index < 0) {
- throw new IOException("EOC does not have matching " +
- "indefinite-length tag");
- }
- int sectionLen = dataPos - ((Integer)elem).intValue() +
- numOfEncapsulatedLenBytes;
- byte[] sectionLenBytes = getLengthBytes(sectionLen);
- ndefsList.set(index, sectionLenBytes);
- unresolved--;
-
- // Add the number of bytes required to represent this section
- // to the total number of length bytes,
- // and subtract the indefinite-length tag (1 byte) and
- // EOC bytes (2 bytes) for this section
- numOfTotalLenBytes += (sectionLenBytes.length - 3);
+ dataPos++;
+ } catch (IndexOutOfBoundsException iobe) {
+ throw new IOException(iobe);
}
- dataPos++;
}
/**
diff --git a/src/share/classes/sun/security/util/ECUtil.java b/src/share/classes/sun/security/util/ECUtil.java
index 8bdc575fbb..fac103421a 100644
--- a/src/share/classes/sun/security/util/ECUtil.java
+++ b/src/share/classes/sun/security/util/ECUtil.java
@@ -89,7 +89,7 @@ public class ECUtil {
return Arrays.copyOfRange(b, i, b.length);
}
- private static AlgorithmParameters getECParameters(Provider p) {
+ public static AlgorithmParameters getECParameters(Provider p) {
try {
if (p != null) {
return AlgorithmParameters.getInstance("EC", p);
diff --git a/src/share/classes/sun/security/util/HostnameChecker.java b/src/share/classes/sun/security/util/HostnameChecker.java
index 1b30cf5329..89712ddd99 100644
--- a/src/share/classes/sun/security/util/HostnameChecker.java
+++ b/src/share/classes/sun/security/util/HostnameChecker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -262,18 +262,17 @@ public class HostnameChecker {
* The matching is performed as per RFC 2818 rules for TLS and
* RFC 2830 rules for LDAP.<p>
*
- * The <code>name</code> parameter should represent a DNS name.
- * The <code>template</code> parameter
- * may contain the wildcard character *
+ * The <code>name</code> parameter should represent a DNS name. The
+ * <code>template</code> parameter may contain the wildcard character '*'.
*/
private boolean isMatched(String name, String template) {
// check the validity of the domain name template.
try {
- // Replacing wildcard character '*' with 'x' so as to check
+ // Replacing wildcard character '*' with 'z' so as to check
// the domain name template validity.
//
// Using the checking implemented in SNIHostName
- SNIHostName sni = new SNIHostName(template.replace('*', 'x'));
+ SNIHostName sni = new SNIHostName(template.replace('*', 'z'));
} catch (IllegalArgumentException iae) {
// It would be nice to add debug log if not matching.
return false;
diff --git a/src/share/classes/sun/security/util/SecurityConstants.java b/src/share/classes/sun/security/util/SecurityConstants.java
index 04fafbbd7a..0f6b87941d 100644
--- a/src/share/classes/sun/security/util/SecurityConstants.java
+++ b/src/share/classes/sun/security/util/SecurityConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -176,6 +176,10 @@ public final class SecurityConstants {
public static final NetPermission GET_RESPONSECACHE_PERMISSION =
new NetPermission("getResponseCache");
+ // java.net.ServerSocket, java.net.Socket
+ public static final NetPermission SET_SOCKETIMPL_PERMISSION =
+ new NetPermission("setSocketImpl");
+
// java.lang.SecurityManager, sun.applet.AppletPanel, sun.misc.Launcher
public static final RuntimePermission CREATE_CLASSLOADER_PERMISSION =
new RuntimePermission("createClassLoader");
diff --git a/src/share/classes/sun/security/util/SecurityProperties.java b/src/share/classes/sun/security/util/SecurityProperties.java
new file mode 100644
index 0000000000..7a1ca6a250
--- /dev/null
+++ b/src/share/classes/sun/security/util/SecurityProperties.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018 SAP SE. 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.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Security;
+
+public class SecurityProperties {
+
+ /**
+ * Returns the value of the security property propName, which can be overridden
+ * by a system property of the same name
+ *
+ * @param propName the name of the system or security property
+ * @return the value of the system or security property
+ */
+ public static String privilegedGetOverridable(String propName) {
+ if (System.getSecurityManager() == null) {
+ return getOverridableProperty(propName);
+ } else {
+ return AccessController.doPrivileged((PrivilegedAction<String>) () -> getOverridableProperty(propName));
+ }
+ }
+
+ private static String getOverridableProperty(String propName) {
+ String val = System.getProperty(propName);
+ if (val == null) {
+ return Security.getProperty(propName);
+ } else {
+ return val;
+ }
+ }
+
+ /**
+ * Returns true in case the system or security property "jdk.includeInExceptions"
+ * contains the category refName
+ *
+ * @param refName the category to check
+ * @return true in case the system or security property "jdk.includeInExceptions"
+ * contains refName, false otherwise
+ */
+ public static boolean includedInExceptions(String refName) {
+ String val = privilegedGetOverridable("jdk.includeInExceptions");
+ if (val == null) {
+ return false;
+ }
+
+ String[] tokens = val.split(",");
+ for (String token : tokens) {
+ token = token.trim();
+ if (token.equalsIgnoreCase(refName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java b/src/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java
new file mode 100644
index 0000000000..d921dde4e4
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/ImmutableIntegerModuloP.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, 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.math;
+
+/**
+ * An interface for immutable integers modulo a prime value.
+ */
+
+public interface ImmutableIntegerModuloP extends IntegerModuloP {
+}
+
diff --git a/src/share/classes/sun/security/util/math/IntegerFieldModuloP.java b/src/share/classes/sun/security/util/math/IntegerFieldModuloP.java
new file mode 100644
index 0000000000..57464ee2c2
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/IntegerFieldModuloP.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2018, 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.math;
+
+import java.math.BigInteger;
+
+/**
+ * An interface for the field of integers modulo a prime number. An
+ * implementation of this interface can be used to get properties of the
+ * field and to produce field elements of type ImmutableIntegerModuloP from
+ * other objects and representations of field elements.
+ */
+
+public interface IntegerFieldModuloP {
+
+ /**
+ * Get the size of the field as a BigInteger. This size is equal to the
+ * prime modulus used to construct the field.
+ *
+ * @return the size of the field.
+ */
+ BigInteger getSize();
+
+ /**
+ * Get the additive identity element 0
+ *
+ * @return the additive identity element
+ */
+ ImmutableIntegerModuloP get0();
+
+ /**
+ * Get the multiplicative identity element 1
+ *
+ * @return the multiplicative identity element
+ */
+ ImmutableIntegerModuloP get1();
+
+ /**
+ * Get the field element equivalent to the supplied BigInteger value. The
+ * supplied value may be negative or larger than the modulus that defines
+ * the field.
+ *
+ * @param v a BigInteger value
+ * @return the field element corresponding to v
+ */
+ ImmutableIntegerModuloP getElement(BigInteger v);
+
+ /**
+ * Get a "small" value according to this implementation. This value may
+ * be used in optimized forms of some operations to avoid unnecessary
+ * calculations. For example, multiplication is much faster when it is
+ * known that one of the numbers fits within a single limb.
+ *
+ * The definition of "small", and the range of accepted values, is
+ * implementation-specific.
+ *
+ * @param v the small integer value
+ * @throws IllegalArgumentException when the value is not small
+ */
+ SmallValue getSmallValue(int v);
+
+ /**
+ * Get a field element from a little-endian unsigned integer stored in an
+ * array. The entire array will be used, and the supplied value may be
+ * larger than the modulus that defines the field. The array will not be
+ * modified.
+ *
+ * @param v an array containing a little-endian unsigned integer
+ * @return the field element corresponding to v
+ */
+ default ImmutableIntegerModuloP getElement(byte[] v) {
+ return getElement(v, 0, v.length, (byte) 0);
+ }
+
+ /**
+ * Get a field element from a little-endian unsigned integer stored at the
+ * specified position in an array. The supplied value may be
+ * larger than the modulus that defines the field. This method also takes
+ * a byte which is interpreted as an additional high-order byte of the
+ * number. The array will not be modified.
+ *
+ * @param v an array containing a little-endian unsigned integer
+ * @param offset the starting position of the integer
+ * @param length the number of bytes to read
+ * @param highByte the high-order byte of the number
+ * @return the field element corresponding to the bytes at the specified
+ * position
+ */
+ ImmutableIntegerModuloP getElement(byte[] v, int offset, int length,
+ byte highByte);
+}
+
diff --git a/src/share/classes/sun/security/util/math/IntegerModuloP.java b/src/share/classes/sun/security/util/math/IntegerModuloP.java
new file mode 100644
index 0000000000..262175b837
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/IntegerModuloP.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2018, 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.math;
+
+import java.math.BigInteger;
+
+/**
+ * The base interface for integers modulo a prime value. Objects of this
+ * type may be either mutable or immutable, and subinterfaces can be used
+ * to specify that an object is mutable or immutable. This type should never
+ * be used to declare local/member variables, but it may be used for
+ * formal parameters of a method. None of the methods in this interface
+ * modify the value of arguments or this.
+ *
+ * The behavior of this interface depends on the particular implementation.
+ * For example, some implementations only support a limited number of add
+ * operations before each multiply operation. See the documentation of the
+ * implementation for details.
+ *
+ * @see ImmutableIntegerModuloP
+ * @see MutableIntegerModuloP
+ */
+public interface IntegerModuloP {
+
+ /**
+ * Get the field associated with this element.
+ *
+ * @return the field
+ */
+ IntegerFieldModuloP getField();
+
+ /**
+ * Get the canonical value of this element as a BigInteger. This value
+ * will always be in the range [0, p), where p is the prime that defines
+ * the field. This method performs reduction and other computation to
+ * produce the result.
+ *
+ * @return the value as a BigInteger
+ */
+ BigInteger asBigInteger();
+
+ /**
+ * Return this value as a fixed (immutable) element. This method will
+ * copy the underlying representation if the object is mutable.
+ *
+ * @return a fixed element with the same value
+ */
+ ImmutableIntegerModuloP fixed();
+
+ /**
+ * Return this value as a mutable element. This method will always copy
+ * the underlying representation.
+ *
+ * @return a mutable element with the same value
+ */
+ MutableIntegerModuloP mutable();
+
+ /**
+ * Add this field element with the supplied element and return the result.
+ *
+ * @param b the sumand
+ * @return this + b
+ */
+ ImmutableIntegerModuloP add(IntegerModuloP b);
+
+ /**
+ * Compute the additive inverse of the field element
+ * @return the addditiveInverse (0 - this)
+ */
+ ImmutableIntegerModuloP additiveInverse();
+
+ /**
+ * Multiply this field element with the supplied element and return the
+ * result.
+ *
+ * @param b the multiplicand
+ * @return this * b
+ */
+ ImmutableIntegerModuloP multiply(IntegerModuloP b);
+
+ /**
+ * Perform an addition modulo a power of two and return the little-endian
+ * encoding of the result. The value is (this' + b') % 2^(8 * len),
+ * where this' and b' are the canonical integer values equivalent to
+ * this and b.
+ *
+ * @param b the sumand
+ * @param len the length of the desired array
+ * @return a byte array of length len containing the result
+ */
+ default byte[] addModPowerTwo(IntegerModuloP b, int len) {
+ byte[] result = new byte[len];
+ addModPowerTwo(b, result);
+ return result;
+ }
+
+ /**
+ * Perform an addition modulo a power of two and store the little-endian
+ * encoding of the result in the supplied array. The value is
+ * (this' + b') % 2^(8 * result.length), where this' and b' are the
+ * canonical integer values equivalent to this and b.
+ *
+ * @param b the sumand
+ * @param result an array which stores the result upon return
+ */
+ void addModPowerTwo(IntegerModuloP b, byte[] result);
+
+ /**
+ * Returns the little-endian encoding of this' % 2^(8 * len), where this'
+ * is the canonical integer value equivalent to this.
+ *
+ * @param len the length of the desired array
+ * @return a byte array of length len containing the result
+ */
+ default byte[] asByteArray(int len) {
+ byte[] result = new byte[len];
+ asByteArray(result);
+ return result;
+ }
+
+ /**
+ * Places the little-endian encoding of this' % 2^(8 * result.length)
+ * into the supplied array, where this' is the canonical integer value
+ * equivalent to this.
+ *
+ * @param result an array which stores the result upon return
+ */
+ void asByteArray(byte[] result);
+
+ /**
+ * Compute the multiplicative inverse of this field element.
+ *
+ * @return the multiplicative inverse (1 / this)
+ */
+ default ImmutableIntegerModuloP multiplicativeInverse() {
+ return pow(getField().getSize().subtract(BigInteger.valueOf(2)));
+ }
+
+ /**
+ * Subtract the supplied element from this one and return the result.
+ * @param b the subtrahend
+ *
+ * @return the difference (this - b)
+ */
+ default ImmutableIntegerModuloP subtract(IntegerModuloP b) {
+ return add(b.additiveInverse());
+ }
+
+ /**
+ * Calculate the square of this element and return the result. This method
+ * should be used instead of a.multiply(a) because implementations may
+ * include optimizations that only apply to squaring.
+ *
+ * @return the product (this * this)
+ */
+ default ImmutableIntegerModuloP square() {
+ return multiply(this);
+ }
+
+ /**
+ * Calculate the power this^b and return the result.
+ *
+ * @param b the exponent
+ * @return the value of this^b
+ */
+ default ImmutableIntegerModuloP pow(BigInteger b) {
+ //Default implementation is square and multiply
+ MutableIntegerModuloP y = getField().get1().mutable();
+ MutableIntegerModuloP x = mutable();
+ int bitLength = b.bitLength();
+ for (int bit = 0; bit < bitLength; bit++) {
+ if (b.testBit(bit)) {
+ // odd
+ y.setProduct(x);
+ }
+ x.setSquare();
+ }
+ return y.fixed();
+ }
+
+}
+
diff --git a/src/share/classes/sun/security/util/math/MutableIntegerModuloP.java b/src/share/classes/sun/security/util/math/MutableIntegerModuloP.java
new file mode 100644
index 0000000000..359472a7a1
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/MutableIntegerModuloP.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018, 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.math;
+
+import java.nio.ByteBuffer;
+
+/**
+ * An interface for mutable integers modulo a prime value. This interface
+ * should be used to improve performance and avoid the allocation of a large
+ * number of temporary objects.
+ *
+ * Methods in this interface that modify the value also return the modified
+ * element. This structure enables fluent expressions like:
+ * a.setSum(b).setProduct(c).setDifference(d).setSquare()
+ *
+ */
+
+public interface MutableIntegerModuloP extends IntegerModuloP {
+
+ /**
+ * Set this value to the value of b when set has the value 1.
+ * No change is made to this element when set has the value 0. The
+ * result is undefined when set has a value other than 0 or 1. The set
+ * parameter is an int (rather than boolean) to allow the implementation
+ * to perform the assignment using branch-free integer arithmetic.
+ *
+ * @param b the element to conditionally swap with
+ * @param set an int that determines whether to set
+ */
+ void conditionalSet(IntegerModuloP b, int set);
+
+ /**
+ * Swap the value of this with the value of b when swap has the value 1.
+ * No change is made to either element when swap has the value 0. The
+ * result is undefined when swap has a value other than 0 or 1. The swap
+ * parameter is an int (rather than boolean) to allow the implementation
+ * to perform the swap using branch-free integer arithmetic.
+ *
+ * @param b the element to conditionally swap with
+ * @param swap an int that determines whether to swap
+ */
+ void conditionalSwapWith(MutableIntegerModuloP b, int swap);
+
+ /**
+ * Set the value of this element equal to the value of the supplied
+ * element. The argument is not modified.
+ *
+ * @param v the element whose value should be copied to this
+ * @return this
+ */
+ MutableIntegerModuloP setValue(IntegerModuloP v);
+
+ /**
+ * Set the value equal to the little-endian unsigned integer stored at the
+ * specified position in an array. The range of accepted values is
+ * implementation-specific. This method also takes a byte which is
+ * interpreted as an additional high-order byte of the number.
+ *
+ * @param v an array containing a little-endian unsigned integer
+ * @param offset the starting position of the integer
+ * @param length the number of bytes to read
+ * @param highByte the high-order byte of the number
+ * @return this
+ */
+ MutableIntegerModuloP setValue(byte[] v, int offset, int length,
+ byte highByte);
+
+ /**
+ * Set the value equal to the little-endian unsigned integer stored in a
+ * buffer. The range of accepted values is implementation-specific.
+ * This method also takes a byte which is interpreted as an additional
+ * high-order byte of the number.
+ *
+ * @param buf a buffer containing a little-endian unsigned integer
+ * @param length the number of bytes to read
+ * @param highByte the high-order byte of the number
+ * @return this
+ */
+ MutableIntegerModuloP setValue(ByteBuffer buf, int length, byte highByte);
+
+ /**
+ * Set the value of this element equal to this * this.
+ *
+ * @return this
+ */
+ MutableIntegerModuloP setSquare();
+
+ /**
+ * Set the value of this element equal to this + b. The argument is
+ * not modified.
+ *
+ * @param b the sumand
+ * @return this
+ */
+ MutableIntegerModuloP setSum(IntegerModuloP b);
+
+ /**
+ * Set the value of this element equal to this - b. The argument is
+ * not modified.
+ *
+ * @param b the subtrahend
+ * @return this
+ */
+ MutableIntegerModuloP setDifference(IntegerModuloP b);
+
+ /**
+ * Set the value of this element equal to this * b. The argument is
+ * not modified.
+ *
+ * @param b the multiplicand
+ * @return this
+ */
+ MutableIntegerModuloP setProduct(IntegerModuloP b);
+
+ /**
+ * Set the value of this element equal to this * v. The argument is
+ * not modified.
+ *
+ * @param v the small multiplicand
+ * @return this
+ */
+ MutableIntegerModuloP setProduct(SmallValue v);
+
+ /**
+ * Set the value of this element equal to 0 - this.
+ *
+ * @return this
+ */
+ MutableIntegerModuloP setAdditiveInverse();
+
+ /**
+ * Some implementations required reduction operations to be requested
+ * by the client at certain times. This method reduces the representation.
+ *
+ * @return this
+ */
+ MutableIntegerModuloP setReduced();
+}
+
diff --git a/src/share/classes/sun/security/util/math/SmallValue.java b/src/share/classes/sun/security/util/math/SmallValue.java
new file mode 100644
index 0000000000..4c24594b7c
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/SmallValue.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, 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.math;
+
+/**
+ * A "small" value that can be used with the field arithmetic library. This
+ * interface enables optimizations based on the fact that certain values are
+ * known to be small, where the definition of small is specific to the the
+ * arithmetic implementation.
+ */
+
+public interface SmallValue {
+}
+
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/FieldGen.jsh b/src/share/classes/sun/security/util/math/intpoly/FieldGen.jsh
new file mode 100644
index 0000000000..4824b78ed6
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/FieldGen.jsh
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+
+/*
+ * This file is used to generated optimized finite field implementations.
+ * Required settings are included in the file. To generate, use jshell:
+ * jshell < FieldGen.jsh
+ */
+
+import java.io.*;
+import java.math.BigInteger;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+public class FieldGen {
+
+ static FieldParams Curve25519 = new FieldParams("IntegerPolynomial25519", 26, 10, 1, 255,
+ Arrays.asList(
+ new Term(0, -19)
+ ),
+ Curve25519CrSequence(), simpleSmallCrSequence(10)
+ );
+
+ private static List<CarryReduce> Curve25519CrSequence() {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+
+ // reduce(7,2)
+ result.add(new Reduce(17));
+ result.add(new Reduce(18));
+
+ // carry(8,2)
+ result.add(new Carry(8));
+ result.add(new Carry(9));
+
+ // reduce(0,7)
+ for (int i = 10; i < 17; i++) {
+ result.add(new Reduce(i));
+ }
+
+ // carry(0,9)
+ result.addAll(fullCarry(10));
+
+ return result;
+ }
+
+ static FieldParams Curve448 = new FieldParams("IntegerPolynomial448", 28, 16, 1, 448,
+ Arrays.asList(
+ new Term(224, -1),
+ new Term(0, -1)
+ ),
+ Curve448CrSequence(), simpleSmallCrSequence(16)
+ );
+
+ private static List<CarryReduce> Curve448CrSequence() {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+
+ // reduce(8, 7)
+ for (int i = 24; i < 31; i++) {
+ result.add(new Reduce(i));
+ }
+ // reduce(4, 4)
+ for (int i = 20; i < 24; i++) {
+ result.add(new Reduce(i));
+ }
+
+ //carry(14, 2)
+ result.add(new Carry(14));
+ result.add(new Carry(15));
+
+ // reduce(0, 4)
+ for (int i = 16; i < 20; i++) {
+ result.add(new Reduce(i));
+ }
+
+ // carry(0, 15)
+ result.addAll(fullCarry(16));
+
+ return result;
+ }
+
+ static FieldParams P256 = new FieldParams("IntegerPolynomialP256", 26, 10, 2, 256,
+ Arrays.asList(
+ new Term(224, -1),
+ new Term(192, 1),
+ new Term(96, 1),
+ new Term(0, -1)
+ ),
+ P256CrSequence(), simpleSmallCrSequence(10)
+ );
+
+ private static List<CarryReduce> P256CrSequence() {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullReduce(10));
+ result.addAll(simpleSmallCrSequence(10));
+ return result;
+ }
+
+ static FieldParams P384 = new FieldParams("IntegerPolynomialP384", 28, 14, 2, 384,
+ Arrays.asList(
+ new Term(128, -1),
+ new Term(96, -1),
+ new Term(32, 1),
+ new Term(0, -1)
+ ),
+ P384CrSequence(), simpleSmallCrSequence(14)
+ );
+
+ private static List<CarryReduce> P384CrSequence() {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullReduce(14));
+ result.addAll(simpleSmallCrSequence(14));
+ return result;
+ }
+
+ static FieldParams P521 = new FieldParams("IntegerPolynomialP521", 28, 19, 2, 521,
+ Arrays.asList(new Term(0, -1)), P521CrSequence(), simpleSmallCrSequence(19)
+ );
+
+ private static List<CarryReduce> P521CrSequence() {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullReduce(19));
+ result.addAll(simpleSmallCrSequence(19));
+ return result;
+ }
+
+ static FieldParams O256 = new FieldParams("P256OrderField", 26, 10, 1, 256,
+ new BigInteger("26959946660873538059280334323273029441504803697035324946844617595567"),
+ orderFieldCrSequence(10), orderFieldSmallCrSequence(10)
+ );
+
+ static FieldParams O384 = new FieldParams("P384OrderField", 28, 14, 1, 384,
+ new BigInteger("1388124618062372383947042015309946732620727252194336364173"),
+ orderFieldCrSequence(14), orderFieldSmallCrSequence(14)
+ );
+
+ static FieldParams O521 = new FieldParams("P521OrderField", 28, 19, 1, 521,
+ new BigInteger("657877501894328237357444332315020117536923257219387276263472201219398408051703"),
+ o521crSequence(19), orderFieldSmallCrSequence(19)
+ );
+
+ private static List<CarryReduce> o521crSequence(int numLimbs) {
+
+ // split the full reduce in half, with a carry in between
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullCarry(2 * numLimbs));
+ for (int i = 2 * numLimbs - 1; i >= numLimbs + numLimbs/2; i--) {
+ result.add(new Reduce(i));
+ }
+ // carry
+ for (int i = numLimbs; i < numLimbs + numLimbs / 2 - 1; i++) {
+ result.add(new Carry(i));
+ }
+ // rest of reduce
+ for (int i = numLimbs + numLimbs/2 - 1; i >= numLimbs; i--) {
+ result.add(new Reduce(i));
+ }
+ result.addAll(orderFieldSmallCrSequence(numLimbs));
+
+ return result;
+ }
+
+ private static List<CarryReduce> orderFieldCrSequence(int numLimbs) {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullCarry(2 * numLimbs));
+ result.add(new Reduce(2 * numLimbs - 1));
+ result.addAll(fullReduce(numLimbs));
+ result.addAll(fullCarry(numLimbs + 1));
+ result.add(new Reduce(numLimbs));
+ result.addAll(fullCarry(numLimbs));
+
+ return result;
+ }
+ private static List<CarryReduce> orderFieldSmallCrSequence(int numLimbs) {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ result.addAll(fullCarry(numLimbs + 1));
+ result.add(new Reduce(numLimbs));
+ result.addAll(fullCarry(numLimbs));
+ return result;
+ }
+
+ static final FieldParams[] ALL_FIELDS = {P256, P384, P521, O256, O384, O521};
+
+ public static class Term {
+ private final int power;
+ private final int coefficient;
+
+ public Term(int power, int coefficient) {
+ this.power = power;
+ this.coefficient = coefficient;
+ }
+
+ public int getPower() {
+ return power;
+ }
+
+ public int getCoefficient() {
+ return coefficient;
+ }
+
+ public BigInteger getValue() {
+ return BigInteger.valueOf(2).pow(power).multiply(BigInteger.valueOf(coefficient));
+ }
+
+ }
+
+ static abstract class CarryReduce {
+ private final int index;
+
+ protected CarryReduce(int index) {
+ this.index = index;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public abstract void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining);
+ }
+
+ static class Carry extends CarryReduce {
+ public Carry(int index) {
+ super(index);
+ }
+
+ public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) {
+ carry(out, params, prefix, getIndex());
+ }
+ }
+
+ static class Reduce extends CarryReduce {
+ public Reduce(int index) {
+ super(index);
+ }
+
+ public void write(CodeBuffer out, FieldParams params, String prefix, Iterable<CarryReduce> remaining) {
+ reduce(out, params, prefix, getIndex(), remaining);
+ }
+ }
+
+ static class FieldParams {
+ private final String className;
+ private final int bitsPerLimb;
+ private final int numLimbs;
+ private final int maxAdds;
+ private final int power;
+ private final Iterable<Term> terms;
+ private final List<CarryReduce> crSequence;
+ private final List<CarryReduce> smallCrSequence;
+
+ public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+ Iterable<Term> terms, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) {
+ this.className = className;
+ this.bitsPerLimb = bitsPerLimb;
+ this.numLimbs = numLimbs;
+ this.maxAdds = maxAdds;
+ this.power = power;
+ this.terms = terms;
+ this.crSequence = crSequence;
+ this.smallCrSequence = smallCrSequence;
+ }
+
+ public FieldParams(String className, int bitsPerLimb, int numLimbs, int maxAdds, int power,
+ BigInteger term, List<CarryReduce> crSequence, List<CarryReduce> smallCrSequence) {
+ this.className = className;
+ this.bitsPerLimb = bitsPerLimb;
+ this.numLimbs = numLimbs;
+ this.maxAdds = maxAdds;
+ this.power = power;
+ this.crSequence = crSequence;
+ this.smallCrSequence = smallCrSequence;
+
+ terms = buildTerms(term);
+ }
+
+ private Iterable<Term> buildTerms(BigInteger sub) {
+ // split a large subtrahend into smaller terms that are aligned with limbs
+ List<Term> result = new ArrayList<Term>();
+ BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb);
+ int termIndex = 0;
+ while (!sub.equals(BigInteger.ZERO)) {
+ int coef = sub.mod(mod).intValue();
+ boolean plusOne = false;
+ if (coef > (1 << (bitsPerLimb - 1))) {
+ coef = coef - (1 << bitsPerLimb);
+ plusOne = true;
+ }
+ if (coef != 0) {
+ int pow = termIndex * bitsPerLimb;
+ result.add(new Term(pow, -coef));
+ }
+ sub = sub.shiftRight(bitsPerLimb);
+ if (plusOne) {
+ sub = sub.add(BigInteger.ONE);
+ }
+ ++termIndex;
+ }
+ return result;
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public int getBitsPerLimb() {
+ return bitsPerLimb;
+ }
+
+ public int getNumLimbs() {
+ return numLimbs;
+ }
+
+ public int getMaxAdds() {
+ return maxAdds;
+ }
+
+ public int getPower() {
+ return power;
+ }
+
+ public Iterable<Term> getTerms() {
+ return terms;
+ }
+
+ public List<CarryReduce> getCrSequence() {
+ return crSequence;
+ }
+
+ public List<CarryReduce> getSmallCrSequence() {
+ return smallCrSequence;
+ }
+ }
+
+ static Collection<Carry> fullCarry(int numLimbs) {
+ List<Carry> result = new ArrayList<Carry>();
+ for (int i = 0; i < numLimbs - 1; i++) {
+ result.add(new Carry(i));
+ }
+ return result;
+ }
+
+ static Collection<Reduce> fullReduce(int numLimbs) {
+ List<Reduce> result = new ArrayList<Reduce>();
+ for (int i = numLimbs - 2; i >= 0; i--) {
+ result.add(new Reduce(i + numLimbs));
+ }
+ return result;
+ }
+
+ static List<CarryReduce> simpleCrSequence(int numLimbs) {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ for(int i = 0; i < 4; i++) {
+ result.addAll(fullCarry(2 * numLimbs - 1));
+ result.addAll(fullReduce(numLimbs));
+ }
+
+ return result;
+ }
+
+ static List<CarryReduce> simpleSmallCrSequence(int numLimbs) {
+ List<CarryReduce> result = new ArrayList<CarryReduce>();
+ // carry a few positions at the end
+ for (int i = numLimbs - 2; i < numLimbs; i++) {
+ result.add(new Carry(i));
+ }
+ // this carries out a single value that must be reduced back in
+ result.add(new Reduce(numLimbs));
+ // finish with a full carry
+ result.addAll(fullCarry(numLimbs));
+ return result;
+ }
+
+ private final String packageName;
+ private final String parentName;
+
+ public FieldGen(String packageName, String parentName) {
+ this.packageName = packageName;
+ this.parentName = parentName;
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ FieldGen gen = new FieldGen("sun.security.util.math.intpoly", "IntegerPolynomial");
+ for(FieldParams p : ALL_FIELDS) {
+ gen.generateFile(p);
+ }
+ }
+
+ private void generateFile(FieldParams params) throws IOException {
+ String text = generate(params);
+ String fileName = params.getClassName() + ".java";
+ PrintWriter out = new PrintWriter(new FileWriter(fileName));
+ out.println(text);
+ out.close();
+ }
+
+ static class CodeBuffer {
+
+ private int nextTemporary = 0;
+ private Set<String> temporaries = new HashSet<String>();
+ private StringBuffer buffer = new StringBuffer();
+ private int indent = 0;
+ private Class lastCR;
+ private int lastCrCount = 0;
+ private int crMethodBreakCount = 0;
+ private int crNumLimbs = 0;
+
+ public void incrIndent() {
+ indent++;
+ }
+
+ public void decrIndent() {
+ indent--;
+ }
+
+ public void newTempScope() {
+ nextTemporary = 0;
+ temporaries.clear();
+ }
+
+ public void appendLine(String s) {
+ appendIndent();
+ buffer.append(s + "\n");
+ }
+
+ public void appendLine() {
+ buffer.append("\n");
+ }
+
+ public String toString() {
+ return buffer.toString();
+ }
+
+ public void startCrSequence(int numLimbs) {
+ this.crNumLimbs = numLimbs;
+ lastCrCount = 0;
+ crMethodBreakCount = 0;
+ lastCR = null;
+ }
+ /*
+ * Record a carry/reduce of the specified type. This method is used to
+ * break up large carry/reduce sequences into multiple methods to make
+ * JIT/optimization easier
+ */
+ public void record(Class type) {
+ if (type == lastCR) {
+ lastCrCount++;
+ } else {
+
+ if (lastCrCount >= 8) {
+ insertCrMethodBreak();
+ }
+
+ lastCR = type;
+ lastCrCount = 0;
+ }
+ }
+
+ private void insertCrMethodBreak() {
+
+ appendLine();
+
+ // call the new method
+ appendIndent();
+ append("carryReduce" + crMethodBreakCount + "(r");
+ for(int i = 0; i < crNumLimbs; i++) {
+ append(", c" + i);
+ }
+ // temporaries are not live between operations, no need to send
+ append(");\n");
+
+ decrIndent();
+ appendLine("}");
+
+ // make the method
+ appendIndent();
+ append("void carryReduce" + crMethodBreakCount + "(long[] r");
+ for(int i = 0; i < crNumLimbs; i++) {
+ append (", long c" + i);
+ }
+ append(") {\n");
+ incrIndent();
+ // declare temporaries
+ for(String temp : temporaries) {
+ appendLine("long " + temp + ";");
+ }
+ append("\n");
+
+ crMethodBreakCount++;
+ }
+
+ public String getTemporary(String type, String value) {
+ Iterator<String> iter = temporaries.iterator();
+ if(iter.hasNext()) {
+ String result = iter.next();
+ iter.remove();
+ appendLine(result + " = " + value + ";");
+ return result;
+ } else {
+ String result = "t" + (nextTemporary++);
+ appendLine(type + " " + result + " = " + value + ";");
+ return result;
+ }
+ }
+
+ public void freeTemporary(String temp) {
+ temporaries.add(temp);
+ }
+
+ public void appendIndent() {
+ for(int i = 0; i < indent; i++) {
+ buffer.append(" ");
+ }
+ }
+
+ public void append(String s) {
+ buffer.append(s);
+ }
+ }
+
+ private String generate(FieldParams params) throws IOException {
+ CodeBuffer result = new CodeBuffer();
+ String header = readHeader();
+ result.appendLine(header);
+
+ if (packageName != null) {
+ result.appendLine("package " + packageName + ";");
+ result.appendLine();
+ }
+ result.appendLine("import java.math.BigInteger;");
+
+ result.appendLine("public class " + params.getClassName() + " extends " + this.parentName + " {");
+ result.incrIndent();
+
+ result.appendLine("private static final int BITS_PER_LIMB = " + params.getBitsPerLimb() + ";");
+ result.appendLine("private static final int NUM_LIMBS = " + params.getNumLimbs() + ";");
+ result.appendLine("private static final int MAX_ADDS = " + params.getMaxAdds() + ";");
+ result.appendLine("public static final BigInteger MODULUS = evaluateModulus();");
+ result.appendLine("private static final long CARRY_ADD = 1 << " + (params.getBitsPerLimb() - 1) + ";");
+ if (params.getBitsPerLimb() * params.getNumLimbs() != params.getPower()) {
+ result.appendLine("private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);");
+ }
+ int termIndex = 0;
+
+ result.appendLine("public " + params.getClassName() + "() {");
+ result.appendLine();
+ result.appendLine(" super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);");
+ result.appendLine();
+ result.appendLine("}");
+
+ result.appendLine("private static BigInteger evaluateModulus() {");
+ result.incrIndent();
+ result.appendLine("BigInteger result = BigInteger.valueOf(2).pow(" + params.getPower() + ");");
+ for(Term t : params.getTerms()) {
+ boolean subtract = false;
+ int coefValue = t.getCoefficient();
+ if (coefValue < 0) {
+ coefValue = 0 - coefValue;
+ subtract = true;
+ }
+ String coefExpr = "BigInteger.valueOf(" + coefValue + ")";
+ String powExpr = "BigInteger.valueOf(2).pow(" + t.getPower() + ")";
+ String termExpr = "ERROR";
+ if (t.getPower() == 0) {
+ termExpr = coefExpr;
+ } else if (coefValue == 1) {
+ termExpr = powExpr;
+ } else {
+ termExpr = powExpr + ".multiply(" + coefExpr + ")";
+ }
+ if (subtract) {
+ result.appendLine("result = result.subtract(" + termExpr + ");");
+ } else {
+ result.appendLine("result = result.add(" + termExpr + ");");
+ }
+ }
+ result.appendLine("return result;");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void finalCarryReduceLast(long[] limbs) {");
+ result.incrIndent();
+ int extraBits = params.getBitsPerLimb() * params.getNumLimbs() - params.getPower();
+ int highBits = params.getBitsPerLimb() - extraBits;
+ result.appendLine("long c = limbs[" + (params.getNumLimbs() - 1) + "] >> " + highBits + ";");
+ result.appendLine("limbs[" + (params.getNumLimbs() - 1) + "] -= c << " + highBits + ";");
+ for (Term t : params.getTerms()) {
+ int reduceBits = params.getPower() + extraBits - t.getPower();
+ int negatedCoefficient = -1 * t.getCoefficient();
+ modReduceInBits(result, params, true, "limbs", params.getNumLimbs(), reduceBits, negatedCoefficient, "c");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ // full carry/reduce sequence
+ result.appendIndent();
+ result.append("private void carryReduce(long[] r, ");
+ for(int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append ("long c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(") {\n");
+ result.newTempScope();
+ result.incrIndent();
+ result.appendLine("long c" + (2 * params.getNumLimbs() - 1) + " = 0;");
+ write(result, params.getCrSequence(), params, "c", 2 * params.getNumLimbs());
+ result.appendLine();
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.appendLine("r[" + i + "] = c" + i + ";");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ // small carry/reduce sequence
+ result.appendIndent();
+ result.append("private void carryReduce(long[] r, ");
+ for(int i = 0; i < params.getNumLimbs(); i++) {
+ result.append ("long c" + i);
+ if (i < params.getNumLimbs() - 1) {
+ result.append(", ");
+ }
+ }
+ result.append(") {\n");
+ result.newTempScope();
+ result.incrIndent();
+ result.appendLine("long c" + params.getNumLimbs() + " = 0;");
+ write(result, params.getSmallCrSequence(), params, "c", params.getNumLimbs() + 1);
+ result.appendLine();
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.appendLine("r[" + i + "] = c" + i + ";");
+ }
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void mult(long[] a, long[] b, long[] r) {");
+ result.incrIndent();
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.appendIndent();
+ result.append("long c" + i + " = ");
+ int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+ int endJ = Math.min(params.getNumLimbs(), i + 1);
+ for (int j = startJ; j < endJ; j++) {
+ int bIndex = i - j;
+ result.append("(a[" + j + "] * b[" + bIndex + "])");
+ if (j < endJ - 1) {
+ result.append(" + ");
+ }
+ }
+ result.append(";\n");
+ }
+ result.appendLine();
+ result.appendIndent();
+ result.append("carryReduce(r, ");
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append("c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void reduce(long[] a) {");
+ result.incrIndent();
+ result.appendIndent();
+ result.append("carryReduce(a, ");
+ for (int i = 0; i < params.getNumLimbs(); i++) {
+ result.append("a[" + i + "]");
+ if (i < params.getNumLimbs() - 1) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.appendLine("@Override");
+ result.appendLine("protected void square(long[] a, long[] r) {");
+ result.incrIndent();
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.appendIndent();
+ result.append("long c" + i + " = ");
+ int startJ = Math.max(i + 1 - params.getNumLimbs(), 0);
+ int endJ = Math.min(params.getNumLimbs(), i + 1);
+ int jDiff = endJ - startJ;
+ if (jDiff > 1) {
+ result.append("2 * (");
+ }
+ for (int j = 0; j < jDiff / 2; j++) {
+ int aIndex = j + startJ;
+ int bIndex = i - aIndex;
+ result.append("(a[" + aIndex + "] * a[" + bIndex + "])");
+ if (j < (jDiff / 2) - 1) {
+ result.append(" + ");
+ }
+ }
+ if (jDiff > 1) {
+ result.append(")");
+ }
+ if (jDiff % 2 == 1) {
+ int aIndex = i / 2;
+ if (jDiff > 1) {
+ result.append (" + ");
+ }
+ result.append("(a[" + aIndex + "] * a[" + aIndex + "])");
+ }
+ result.append(";\n");
+ }
+ result.appendLine();
+ result.appendIndent();
+ result.append("carryReduce(r, ");
+ for (int i = 0; i < 2 * params.getNumLimbs() - 1; i++) {
+ result.append("c" + i);
+ if (i < 2 * params.getNumLimbs() - 2) {
+ result.append(", ");
+ }
+ }
+ result.append(");\n");
+ result.decrIndent();
+ result.appendLine("}");
+
+ result.decrIndent();
+ result.appendLine("}"); // end class
+
+ return result.toString();
+ }
+
+ private static void write(CodeBuffer out, List<CarryReduce> sequence, FieldParams params, String prefix, int numLimbs) {
+
+ out.startCrSequence(numLimbs);
+ for (int i = 0; i < sequence.size(); i++) {
+ CarryReduce cr = sequence.get(i);
+ Iterator<CarryReduce> remainingIter = sequence.listIterator(i + 1);
+ List<CarryReduce> remaining = new ArrayList<CarryReduce>();
+ remainingIter.forEachRemaining(remaining::add);
+ cr.write(out, params, prefix, remaining);
+ }
+ }
+
+ private static void reduce(CodeBuffer out, FieldParams params, String prefix, int index, Iterable<CarryReduce> remaining) {
+
+ out.record(Reduce.class);
+
+ out.appendLine("//reduce from position " + index);
+ String reduceFrom = indexedExpr(false, prefix, index);
+ boolean referenced = false;
+ for (CarryReduce cr : remaining) {
+ if(cr.index == index) {
+ referenced = true;
+ }
+ }
+ for (Term t : params.getTerms()) {
+ int reduceBits = params.getPower() - t.getPower();
+ int negatedCoefficient = -1 * t.getCoefficient();
+ modReduceInBits(out, params, false, prefix, index, reduceBits, negatedCoefficient, reduceFrom);
+ }
+ if (referenced) {
+ out.appendLine(reduceFrom + " = 0;");
+ }
+ }
+
+ private static void carry(CodeBuffer out, FieldParams params, String prefix, int index) {
+
+ out.record(Carry.class);
+
+ out.appendLine("//carry from position " + index);
+ String carryFrom = prefix + index;
+ String carryTo = prefix + (index + 1);
+ String carry = "(" + carryFrom + " + CARRY_ADD) >> " + params.getBitsPerLimb();
+ String temp = out.getTemporary("long", carry);
+ out.appendLine(carryFrom + " -= (" + temp + " << " + params.getBitsPerLimb() + ");");
+ out.appendLine(carryTo + " += " + temp + ";");
+ out.freeTemporary(temp);
+ }
+
+ private static String indexedExpr(boolean isArray, String prefix, int index) {
+ String result = prefix + index;
+ if (isArray) {
+ result = prefix + "[" + index + "]";
+ }
+ return result;
+ }
+
+ private static void modReduceInBits(CodeBuffer result, FieldParams params, boolean isArray, String prefix, int index, int reduceBits, int coefficient, String c) {
+
+ String x = coefficient + " * " + c;
+ String accOp = "+=";
+ String temp = null;
+ if (coefficient == 1) {
+ x = c;
+ } else if (coefficient == -1) {
+ x = c;
+ accOp = "-=";
+ } else {
+ temp = result.getTemporary("long", x);
+ x = temp;
+ }
+
+ if (reduceBits % params.getBitsPerLimb() == 0) {
+ int pos = reduceBits / params.getBitsPerLimb();
+ result.appendLine(indexedExpr(isArray, prefix, (index - pos)) + " " + accOp + " " + x + ";");
+ } else {
+ int secondPos = reduceBits / params.getBitsPerLimb();
+ int bitOffset = (secondPos + 1) * params.getBitsPerLimb() - reduceBits;
+ int rightBitOffset = params.getBitsPerLimb() - bitOffset;
+ result.appendLine(indexedExpr(isArray, prefix, (index - (secondPos + 1))) + " " + accOp + " (" + x + " << " + bitOffset + ") & LIMB_MASK;");
+ result.appendLine(indexedExpr(isArray, prefix, (index - secondPos)) + " " + accOp + " " + x + " >> " + rightBitOffset + ";");
+ }
+
+ if (temp != null) {
+ result.freeTemporary(temp);
+ }
+ }
+
+ private String readHeader() throws IOException {
+ BufferedReader reader = Files.newBufferedReader(Paths.get("header.txt"));
+ StringBuffer result = new StringBuffer();
+ reader.lines().forEach(s -> result.append(s + "\n"));
+ return result.toString();
+ }
+}
+
+FieldGen.main(null);
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java
new file mode 100644
index 0000000000..543ceeaebc
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial.java
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2018, 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.math.intpoly;
+
+import sun.security.util.math.*;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.Arrays;
+
+/**
+ * A large number polynomial representation using sparse limbs of signed
+ * long (64-bit) values. Limb values will always fit within a long, so inputs
+ * to multiplication must be less than 32 bits. All IntegerPolynomial
+ * implementations allow at most one addition before multiplication. Additions
+ * after that will result in an ArithmeticException.
+ *
+ * The following element operations are branch-free for all subclasses:
+ *
+ * fixed
+ * mutable
+ * add
+ * additiveInverse
+ * multiply
+ * square
+ * subtract
+ * conditionalSwapWith
+ * setValue (may branch on high-order byte parameter only)
+ * setSum
+ * setDifference
+ * setProduct
+ * setSquare
+ * addModPowerTwo
+ * asByteArray
+ *
+ * All other operations may branch in some subclasses.
+ *
+ */
+
+public abstract class IntegerPolynomial implements IntegerFieldModuloP {
+
+ protected static final BigInteger TWO = BigInteger.valueOf(2);
+
+ protected final int numLimbs;
+ private final BigInteger modulus;
+ protected final int bitsPerLimb;
+ private final long[] posModLimbs;
+ private final int maxAdds;
+
+ /**
+ * Reduce an IntegerPolynomial representation (a) and store the result
+ * in a. Requires that a.length == numLimbs.
+ */
+ protected abstract void reduce(long[] a);
+
+ /**
+ * Multiply an IntegerPolynomial representation (a) with a long (b) and
+ * store the result in an IntegerPolynomial representation in a. Requires
+ * that a.length == numLimbs.
+ */
+ protected void multByInt(long[] a, long b) {
+ for (int i = 0; i < a.length; i++) {
+ a[i] *= b;
+ }
+ reduce(a);
+ }
+
+ /**
+ * Multiply two IntegerPolynomial representations (a and b) and store the
+ * result in an IntegerPolynomial representation (r). Requires that
+ * a.length == b.length == r.length == numLimbs. It is allowed for a and r
+ * to be the same array.
+ */
+ protected abstract void mult(long[] a, long[] b, long[] r);
+
+ /**
+ * Multiply an IntegerPolynomial representation (a) with itself and store
+ * the result in an IntegerPolynomialRepresentation (r). Requires that
+ * a.length == r.length == numLimbs. It is allowed for a and r
+ * to be the same array.
+ */
+ protected abstract void square(long[] a, long[] r);
+
+ IntegerPolynomial(int bitsPerLimb,
+ int numLimbs,
+ int maxAdds,
+ BigInteger modulus) {
+
+
+ this.numLimbs = numLimbs;
+ this.modulus = modulus;
+ this.bitsPerLimb = bitsPerLimb;
+ this.maxAdds = maxAdds;
+
+ posModLimbs = setPosModLimbs();
+ }
+
+ private long[] setPosModLimbs() {
+ long[] result = new long[numLimbs];
+ setLimbsValuePositive(modulus, result);
+ return result;
+ }
+
+ protected int getNumLimbs() {
+ return numLimbs;
+ }
+
+ public int getMaxAdds() {
+ return maxAdds;
+ }
+
+ @Override
+ public BigInteger getSize() {
+ return modulus;
+ }
+
+ @Override
+ public ImmutableElement get0() {
+ return new ImmutableElement(false);
+ }
+
+ @Override
+ public ImmutableElement get1() {
+ return new ImmutableElement(true);
+ }
+
+ @Override
+ public ImmutableElement getElement(BigInteger v) {
+ return new ImmutableElement(v);
+ }
+
+ @Override
+ public SmallValue getSmallValue(int value) {
+ int maxMag = 1 << (bitsPerLimb - 1);
+ if (Math.abs(value) >= maxMag) {
+ throw new IllegalArgumentException(
+ "max magnitude is " + maxMag);
+ }
+ return new Limb(value);
+ }
+
+ /**
+ * This version of encode takes a ByteBuffer that is properly ordered, and
+ * may extract larger values (e.g. long) from the ByteBuffer for better
+ * performance. The implementation below only extracts bytes from the
+ * buffer, but this method may be overridden in field-specific
+ * implementations.
+ */
+ protected void encode(ByteBuffer buf, int length, byte highByte,
+ long[] result) {
+
+ int numHighBits = 32 - Integer.numberOfLeadingZeros(highByte);
+ int numBits = 8 * length + numHighBits;
+ int requiredLimbs = (numBits + bitsPerLimb - 1) / bitsPerLimb;
+ if (requiredLimbs > numLimbs) {
+ long[] temp = new long[requiredLimbs];
+ encodeSmall(buf, length, highByte, temp);
+ // encode does a full carry/reduce
+ System.arraycopy(temp, 0, result, 0, result.length);
+ } else {
+ encodeSmall(buf, length, highByte, result);
+ }
+ }
+
+ protected void encodeSmall(ByteBuffer buf, int length, byte highByte,
+ long[] result) {
+
+ int limbIndex = 0;
+ long curLimbValue = 0;
+ int bitPos = 0;
+ for (int i = 0; i < length; i++) {
+ long curV = buf.get() & 0xFF;
+
+ if (bitPos + 8 >= bitsPerLimb) {
+ int bitsThisLimb = bitsPerLimb - bitPos;
+ curLimbValue += (curV & (0xFF >> (8 - bitsThisLimb))) << bitPos;
+ result[limbIndex++] = curLimbValue;
+ curLimbValue = curV >> bitsThisLimb;
+ bitPos = 8 - bitsThisLimb;
+ }
+ else {
+ curLimbValue += curV << bitPos;
+ bitPos += 8;
+ }
+ }
+
+ // one more for the high byte
+ if (highByte != 0) {
+ long curV = highByte & 0xFF;
+ if (bitPos + 8 >= bitsPerLimb) {
+ int bitsThisLimb = bitsPerLimb - bitPos;
+ curLimbValue += (curV & (0xFF >> (8 - bitsThisLimb))) << bitPos;
+ result[limbIndex++] = curLimbValue;
+ curLimbValue = curV >> bitsThisLimb;
+ }
+ else {
+ curLimbValue += curV << bitPos;
+ }
+ }
+
+ if (limbIndex < result.length) {
+ result[limbIndex++] = curLimbValue;
+ }
+ Arrays.fill(result, limbIndex, result.length, 0);
+
+ postEncodeCarry(result);
+ }
+
+ protected void encode(byte[] v, int offset, int length, byte highByte,
+ long[] result) {
+
+ ByteBuffer buf = ByteBuffer.wrap(v, offset, length);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ encode(buf, length, highByte, result);
+ }
+
+ // Encode does not produce compressed limbs. A simplified carry/reduce
+ // operation can be used to compress the limbs.
+ protected void postEncodeCarry(long[] v) {
+ reduce(v);
+ }
+
+ public ImmutableElement getElement(byte[] v, int offset, int length,
+ byte highByte) {
+
+ long[] result = new long[numLimbs];
+
+ encode(v, offset, length, highByte, result);
+
+ return new ImmutableElement(result, 0);
+ }
+
+ protected BigInteger evaluate(long[] limbs) {
+ BigInteger result = BigInteger.ZERO;
+ for (int i = limbs.length - 1; i >= 0; i--) {
+ result = result.shiftLeft(bitsPerLimb)
+ .add(BigInteger.valueOf(limbs[i]));
+ }
+ return result.mod(modulus);
+ }
+
+ protected long carryValue(long x) {
+ // compressing carry operation
+ // if large positive number, carry one more to make it negative
+ // if large negative number (closer to zero), carry one fewer
+ return (x + (1 << (bitsPerLimb - 1))) >> bitsPerLimb;
+ }
+
+ protected void carry(long[] limbs, int start, int end) {
+
+ for (int i = start; i < end; i++) {
+
+ long carry = carryOut(limbs, i);
+ limbs[i + 1] += carry;
+ }
+ }
+
+ protected void carry(long[] limbs) {
+
+ carry(limbs, 0, limbs.length - 1);
+ }
+
+ /**
+ * Carry out of the specified position and return the carry value.
+ */
+ protected long carryOut(long[] limbs, int index) {
+ long carry = carryValue(limbs[index]);
+ limbs[index] -= (carry << bitsPerLimb);
+ return carry;
+ }
+
+ private void setLimbsValue(BigInteger v, long[] limbs) {
+ // set all limbs positive, and then carry
+ setLimbsValuePositive(v, limbs);
+ carry(limbs);
+ }
+
+ protected void setLimbsValuePositive(BigInteger v, long[] limbs) {
+ BigInteger mod = BigInteger.valueOf(1 << bitsPerLimb);
+ for (int i = 0; i < limbs.length; i++) {
+ limbs[i] = v.mod(mod).longValue();
+ v = v.shiftRight(bitsPerLimb);
+ }
+ }
+
+ /**
+ * Carry out of the last limb and reduce back in. This method will be
+ * called as part of the "finalReduce" operation that puts the
+ * representation into a fully-reduced form. It is representation-
+ * specific, because representations have different amounts of empty
+ * space in the high-order limb. Requires that limbs.length=numLimbs.
+ */
+ protected abstract void finalCarryReduceLast(long[] limbs);
+
+ /**
+ * Convert reduced limbs into a number between 0 and MODULUS-1.
+ * Requires that limbs.length == numLimbs. This method only works if the
+ * modulus has at most three terms.
+ */
+ protected void finalReduce(long[] limbs) {
+
+ // This method works by doing several full carry/reduce operations.
+ // Some representations have extra high bits, so the carry/reduce out
+ // of the high position is implementation-specific. The "unsigned"
+ // carry operation always carries some (negative) value out of a
+ // position occupied by a negative value. So after a number of
+ // passes, all negative values are removed.
+
+ // The first pass may leave a negative value in the high position, but
+ // this only happens if something was carried out of the previous
+ // position. So the previous position must have a "small" value. The
+ // next full carry is guaranteed not to carry out of that position.
+
+ for (int pass = 0; pass < 2; pass++) {
+ // unsigned carry out of last position and reduce in to
+ // first position
+ finalCarryReduceLast(limbs);
+
+ // unsigned carry on all positions
+ long carry = 0;
+ for (int i = 0; i < numLimbs - 1; i++) {
+ limbs[i] += carry;
+ carry = limbs[i] >> bitsPerLimb;
+ limbs[i] -= carry << bitsPerLimb;
+ }
+ limbs[numLimbs - 1] += carry;
+ }
+
+ // Limbs are positive and all less than 2^bitsPerLimb, and the
+ // high-order limb may be even smaller due to the representation-
+ // specific carry/reduce out of the high position.
+ // The value may still be greater than the modulus.
+ // Subtract the max limb values only if all limbs end up non-negative
+ // This only works if there is at most one position where posModLimbs
+ // is less than 2^bitsPerLimb - 1 (not counting the high-order limb,
+ // if it has extra bits that are cleared by finalCarryReduceLast).
+ int smallerNonNegative = 1;
+ long[] smaller = new long[numLimbs];
+ for (int i = numLimbs - 1; i >= 0; i--) {
+ smaller[i] = limbs[i] - posModLimbs[i];
+ // expression on right is 1 if smaller[i] is nonnegative,
+ // 0 otherwise
+ smallerNonNegative *= (int) (smaller[i] >> 63) + 1;
+ }
+ conditionalSwap(smallerNonNegative, limbs, smaller);
+
+ }
+
+ /**
+ * Decode the value in v and store it in dst. Requires that v is final
+ * reduced. I.e. all limbs in [0, 2^bitsPerLimb) and value in [0, modulus).
+ */
+ protected void decode(long[] v, byte[] dst, int offset, int length) {
+
+ int nextLimbIndex = 0;
+ long curLimbValue = v[nextLimbIndex++];
+ int bitPos = 0;
+ for (int i = 0; i < length; i++) {
+
+ int dstIndex = i + offset;
+ if (bitPos + 8 >= bitsPerLimb) {
+ dst[dstIndex] = (byte) curLimbValue;
+ curLimbValue = 0;
+ if (nextLimbIndex < v.length) {
+ curLimbValue = v[nextLimbIndex++];
+ }
+ int bitsAdded = bitsPerLimb - bitPos;
+ int bitsLeft = 8 - bitsAdded;
+
+ dst[dstIndex] += (curLimbValue & (0xFF >> bitsAdded))
+ << bitsAdded;
+ curLimbValue >>= bitsLeft;
+ bitPos = bitsLeft;
+ } else {
+ dst[dstIndex] = (byte) curLimbValue;
+ curLimbValue >>= 8;
+ bitPos += 8;
+ }
+ }
+ }
+
+ /**
+ * Add two IntegerPolynomial representations (a and b) and store the result
+ * in an IntegerPolynomialRepresentation (dst). Requires that
+ * a.length == b.length == dst.length. It is allowed for a and
+ * dst to be the same array.
+ */
+ protected void addLimbs(long[] a, long[] b, long[] dst) {
+ for (int i = 0; i < dst.length; i++) {
+ dst[i] = a[i] + b[i];
+ }
+ }
+
+ /**
+ * Branch-free conditional assignment of b to a. Requires that set is 0 or
+ * 1, and that a.length == b.length. If set==0, then the values of a and b
+ * will be unchanged. If set==1, then the values of b will be assigned to a.
+ * The behavior is undefined if swap has any value other than 0 or 1.
+ */
+ protected static void conditionalAssign(int set, long[] a, long[] b) {
+ int maskValue = 0 - set;
+ for (int i = 0; i < a.length; i++) {
+ long dummyLimbs = maskValue & (a[i] ^ b[i]);
+ a[i] = dummyLimbs ^ a[i];
+ }
+ }
+
+ /**
+ * Branch-free conditional swap of a and b. Requires that swap is 0 or 1,
+ * and that a.length == b.length. If swap==0, then the values of a and b
+ * will be unchanged. If swap==1, then the values of a and b will be
+ * swapped. The behavior is undefined if swap has any value other than
+ * 0 or 1.
+ */
+ protected static void conditionalSwap(int swap, long[] a, long[] b) {
+ int maskValue = 0 - swap;
+ for (int i = 0; i < a.length; i++) {
+ long dummyLimbs = maskValue & (a[i] ^ b[i]);
+ a[i] = dummyLimbs ^ a[i];
+ b[i] = dummyLimbs ^ b[i];
+ }
+ }
+
+ /**
+ * Stores the reduced, little-endian value of limbs in result.
+ */
+ protected void limbsToByteArray(long[] limbs, byte[] result) {
+
+ long[] reducedLimbs = limbs.clone();
+ finalReduce(reducedLimbs);
+
+ decode(reducedLimbs, result, 0, result.length);
+ }
+
+ /**
+ * Add the reduced number corresponding to limbs and other, and store
+ * the low-order bytes of the sum in result. Requires that
+ * limbs.length==other.length. The result array may have any length.
+ */
+ protected void addLimbsModPowerTwo(long[] limbs, long[] other,
+ byte[] result) {
+
+ long[] reducedOther = other.clone();
+ long[] reducedLimbs = limbs.clone();
+ finalReduce(reducedOther);
+ finalReduce(reducedLimbs);
+
+ addLimbs(reducedLimbs, reducedOther, reducedLimbs);
+
+ // may carry out a value which can be ignored
+ long carry = 0;
+ for (int i = 0; i < numLimbs; i++) {
+ reducedLimbs[i] += carry;
+ carry = reducedLimbs[i] >> bitsPerLimb;
+ reducedLimbs[i] -= carry << bitsPerLimb;
+ }
+
+ decode(reducedLimbs, result, 0, result.length);
+ }
+
+ private abstract class Element implements IntegerModuloP {
+
+ protected long[] limbs;
+ protected int numAdds;
+
+ public Element(BigInteger v) {
+ limbs = new long[numLimbs];
+ setValue(v);
+ }
+
+ public Element(boolean v) {
+ this.limbs = new long[numLimbs];
+ this.limbs[0] = v ? 1l : 0l;
+ this.numAdds = 0;
+ }
+
+ private Element(long[] limbs, int numAdds) {
+ this.limbs = limbs;
+ this.numAdds = numAdds;
+ }
+
+ private void setValue(BigInteger v) {
+ setLimbsValue(v, limbs);
+ this.numAdds = 0;
+ }
+
+ @Override
+ public IntegerFieldModuloP getField() {
+ return IntegerPolynomial.this;
+ }
+
+ @Override
+ public BigInteger asBigInteger() {
+ return evaluate(limbs);
+ }
+
+ @Override
+ public MutableElement mutable() {
+ return new MutableElement(limbs.clone(), numAdds);
+ }
+
+ protected boolean isSummand() {
+ return numAdds < maxAdds;
+ }
+
+ @Override
+ public ImmutableElement add(IntegerModuloP genB) {
+
+ Element b = (Element) genB;
+ if (!(isSummand() && b.isSummand())) {
+ throw new ArithmeticException("Not a valid summand");
+ }
+
+ long[] newLimbs = new long[limbs.length];
+ for (int i = 0; i < limbs.length; i++) {
+ newLimbs[i] = limbs[i] + b.limbs[i];
+ }
+
+ int newNumAdds = Math.max(numAdds, b.numAdds) + 1;
+ return new ImmutableElement(newLimbs, newNumAdds);
+ }
+
+ @Override
+ public ImmutableElement additiveInverse() {
+
+ long[] newLimbs = new long[limbs.length];
+ for (int i = 0; i < limbs.length; i++) {
+ newLimbs[i] = -limbs[i];
+ }
+
+ ImmutableElement result = new ImmutableElement(newLimbs, numAdds);
+ return result;
+ }
+
+ protected long[] cloneLow(long[] limbs) {
+ long[] newLimbs = new long[numLimbs];
+ copyLow(limbs, newLimbs);
+ return newLimbs;
+ }
+ protected void copyLow(long[] limbs, long[] out) {
+ System.arraycopy(limbs, 0, out, 0, out.length);
+ }
+
+ @Override
+ public ImmutableElement multiply(IntegerModuloP genB) {
+
+ Element b = (Element) genB;
+
+ long[] newLimbs = new long[limbs.length];
+ mult(limbs, b.limbs, newLimbs);
+ return new ImmutableElement(newLimbs, 0);
+ }
+
+ @Override
+ public ImmutableElement square() {
+ long[] newLimbs = new long[limbs.length];
+ IntegerPolynomial.this.square(limbs, newLimbs);
+ return new ImmutableElement(newLimbs, 0);
+ }
+
+ public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
+
+ Element other = (Element) arg;
+ if (!(isSummand() && other.isSummand())) {
+ throw new ArithmeticException("Not a valid summand");
+ }
+ addLimbsModPowerTwo(limbs, other.limbs, result);
+ }
+
+ public void asByteArray(byte[] result) {
+ if (!isSummand()) {
+ throw new ArithmeticException("Not a valid summand");
+ }
+ limbsToByteArray(limbs, result);
+ }
+ }
+
+ protected class MutableElement extends Element
+ implements MutableIntegerModuloP {
+
+ protected MutableElement(long[] limbs, int numAdds) {
+ super(limbs, numAdds);
+ }
+
+ @Override
+ public ImmutableElement fixed() {
+ return new ImmutableElement(limbs.clone(), numAdds);
+ }
+
+ @Override
+ public void conditionalSet(IntegerModuloP b, int set) {
+
+ Element other = (Element) b;
+
+ conditionalAssign(set, limbs, other.limbs);
+ numAdds = other.numAdds;
+ }
+
+ @Override
+ public void conditionalSwapWith(MutableIntegerModuloP b, int swap) {
+
+ MutableElement other = (MutableElement) b;
+
+ conditionalSwap(swap, limbs, other.limbs);
+ int numAddsTemp = numAdds;
+ numAdds = other.numAdds;
+ other.numAdds = numAddsTemp;
+ }
+
+
+ @Override
+ public MutableElement setValue(IntegerModuloP v) {
+ Element other = (Element) v;
+
+ System.arraycopy(other.limbs, 0, limbs, 0, other.limbs.length);
+ numAdds = other.numAdds;
+ return this;
+ }
+
+ @Override
+ public MutableElement setValue(byte[] arr, int offset,
+ int length, byte highByte) {
+
+ encode(arr, offset, length, highByte, limbs);
+ this.numAdds = 0;
+
+ return this;
+ }
+
+ @Override
+ public MutableElement setValue(ByteBuffer buf, int length,
+ byte highByte) {
+
+ encode(buf, length, highByte, limbs);
+ numAdds = 0;
+
+ return this;
+ }
+
+ @Override
+ public MutableElement setProduct(IntegerModuloP genB) {
+ Element b = (Element) genB;
+ mult(limbs, b.limbs, limbs);
+ numAdds = 0;
+ return this;
+ }
+
+ @Override
+ public MutableElement setProduct(SmallValue v) {
+ int value = ((Limb) v).value;
+ multByInt(limbs, value);
+ numAdds = 0;
+ return this;
+ }
+
+ @Override
+ public MutableElement setSum(IntegerModuloP genB) {
+
+ Element b = (Element) genB;
+ if (!(isSummand() && b.isSummand())) {
+ throw new ArithmeticException("Not a valid summand");
+ }
+
+ for (int i = 0; i < limbs.length; i++) {
+ limbs[i] = limbs[i] + b.limbs[i];
+ }
+
+ numAdds = Math.max(numAdds, b.numAdds) + 1;
+ return this;
+ }
+
+ @Override
+ public MutableElement setDifference(IntegerModuloP genB) {
+
+ Element b = (Element) genB;
+ if (!(isSummand() && b.isSummand())) {
+ throw new ArithmeticException("Not a valid summand");
+ }
+
+ for (int i = 0; i < limbs.length; i++) {
+ limbs[i] = limbs[i] - b.limbs[i];
+ }
+
+ numAdds = Math.max(numAdds, b.numAdds) + 1;
+ return this;
+ }
+
+ @Override
+ public MutableElement setSquare() {
+ IntegerPolynomial.this.square(limbs, limbs);
+ numAdds = 0;
+ return this;
+ }
+
+ @Override
+ public MutableElement setAdditiveInverse() {
+
+ for (int i = 0; i < limbs.length; i++) {
+ limbs[i] = -limbs[i];
+ }
+ return this;
+ }
+
+ @Override
+ public MutableElement setReduced() {
+
+ reduce(limbs);
+ numAdds = 0;
+ return this;
+ }
+ }
+
+ class ImmutableElement extends Element implements ImmutableIntegerModuloP {
+
+ protected ImmutableElement(BigInteger v) {
+ super(v);
+ }
+
+ protected ImmutableElement(boolean v) {
+ super(v);
+ }
+
+ protected ImmutableElement(long[] limbs, int numAdds) {
+ super(limbs, numAdds);
+ }
+
+ @Override
+ public ImmutableElement fixed() {
+ return this;
+ }
+
+ }
+
+ class Limb implements SmallValue {
+ int value;
+
+ Limb(int value) {
+ this.value = value;
+ }
+ }
+
+
+}
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java
new file mode 100644
index 0000000000..794f44fb99
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial1305.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2018, 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.math.intpoly;
+
+import java.lang.invoke.MethodHandles;
+import java.math.BigInteger;
+import java.nio.*;
+
+/**
+ * An IntegerFieldModuloP designed for use with the Poly1305 authenticator.
+ * The representation uses 5 signed long values.
+ */
+
+public class IntegerPolynomial1305 extends IntegerPolynomial {
+
+ protected static final int SUBTRAHEND = 5;
+ protected static final int NUM_LIMBS = 5;
+ private static final int POWER = 130;
+ private static final int BITS_PER_LIMB = 26;
+ private static final BigInteger MODULUS
+ = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
+
+ public IntegerPolynomial1305() {
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
+ }
+
+ protected void mult(long[] a, long[] b, long[] r) {
+
+ // Use grade-school multiplication into primitives to avoid the
+ // temporary array allocation. This is equivalent to the following
+ // code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // for(int j - 0; j < NUM_LIMBS; j++) {
+ // c[i + j] += a[i] * b[j]
+ // }
+ // }
+
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]);
+ long c6 = (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]);
+ long c7 = (a[3] * b[4]) + (a[4] * b[3]);
+ long c8 = (a[4] * b[4]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8);
+ }
+
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3,
+ long c4, long c5, long c6, long c7, long c8) {
+ //reduce(2, 2)
+ r[2] = c2 + (c7 * SUBTRAHEND);
+ c3 += (c8 * SUBTRAHEND);
+
+ // carry(3, 2)
+ long carry3 = carryValue(c3);
+ r[3] = c3 - (carry3 << BITS_PER_LIMB);
+ c4 += carry3;
+
+ long carry4 = carryValue(c4);
+ r[4] = c4 - (carry4 << BITS_PER_LIMB);
+ c5 += carry4;
+
+ // reduce(0, 2)
+ r[0] = c0 + (c5 * SUBTRAHEND);
+ r[1] = c1 + (c6 * SUBTRAHEND);
+
+ // carry(0, 4)
+ carry(r);
+ }
+
+ @Override
+ protected void square(long[] a, long[] r) {
+ // Use grade-school multiplication with a simple squaring optimization.
+ // Multiply into primitives to avoid the temporary array allocation.
+ // This is equivalent to the following code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // c[2 * i] = a[i] * a[i];
+ // for(int j = i + 1; j < NUM_LIMBS; j++) {
+ // c[i + j] += 2 * a[i] * a[j]
+ // }
+ // }
+
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * (a[0] * a[1]);
+ long c2 = 2 * (a[0] * a[2]) + (a[1] * a[1]);
+ long c3 = 2 * (a[0] * a[3] + a[1] * a[2]);
+ long c4 = 2 * (a[0] * a[4] + a[1] * a[3]) + (a[2] * a[2]);
+ long c5 = 2 * (a[1] * a[4] + a[2] * a[3]);
+ long c6 = 2 * (a[2] * a[4]) + (a[3] * a[3]);
+ long c7 = 2 * (a[3] * a[4]);
+ long c8 = (a[4] * a[4]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8);
+ }
+
+ @Override
+ protected void encode(ByteBuffer buf, int length, byte highByte,
+ long[] result) {
+ if (length == 16) {
+ long low = buf.getLong();
+ long high = buf.getLong();
+ encode(high, low, highByte, result);
+ } else {
+ super.encode(buf, length, highByte, result);
+ }
+ }
+
+ protected void encode(long high, long low, byte highByte, long[] result) {
+ result[0] = low & 0x3FFFFFFL;
+ result[1] = (low >>> 26) & 0x3FFFFFFL;
+ result[2] = (low >>> 52) + ((high & 0x3FFFL) << 12);
+ result[3] = (high >>> 14) & 0x3FFFFFFL;
+ result[4] = (high >>> 40) + (highByte << 24L);
+ }
+
+ protected void encode(byte[] v, int offset, int length, byte highByte,
+ long[] result) {
+ if (length == 16) {
+ ByteBuffer asLongLEBuffer = ByteBuffer.wrap(v, offset, length)
+ .order(ByteOrder.LITTLE_ENDIAN);
+ long low = asLongLEBuffer.getLong();
+ long high = asLongLEBuffer.getLong();
+ encode(high, low, highByte, result);
+ } else {
+ super.encode(v, offset, length, highByte, result);
+ }
+ }
+
+ private void modReduceIn(long[] limbs, int index, long x) {
+ // this only works when BITS_PER_LIMB * NUM_LIMBS = POWER exactly
+ long reducedValue = (x * SUBTRAHEND);
+ limbs[index - NUM_LIMBS] += reducedValue;
+ }
+
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long carry = limbs[numLimbs - 1] >> bitsPerLimb;
+ limbs[numLimbs - 1] -= carry << bitsPerLimb;
+ modReduceIn(limbs, numLimbs, carry);
+ }
+
+ protected final void modReduce(long[] limbs, int start, int end) {
+
+ for (int i = start; i < end; i++) {
+ modReduceIn(limbs, i, limbs[i]);
+ limbs[i] = 0;
+ }
+ }
+
+ protected void modReduce(long[] limbs) {
+
+ modReduce(limbs, NUM_LIMBS, NUM_LIMBS - 1);
+ }
+
+ @Override
+ protected long carryValue(long x) {
+ // This representation has plenty of extra space, so we can afford to
+ // do a simplified carry operation that is more time-efficient.
+
+ return x >> BITS_PER_LIMB;
+ }
+
+ @Override
+ protected void postEncodeCarry(long[] v) {
+ // not needed because carry is unsigned
+ }
+
+ @Override
+ protected void reduce(long[] limbs) {
+ long carry3 = carryOut(limbs, 3);
+ long new4 = carry3 + limbs[4];
+
+ long carry4 = carryValue(new4);
+ limbs[4] = new4 - (carry4 << BITS_PER_LIMB);
+
+ modReduceIn(limbs, 5, carry4);
+ carry(limbs);
+ }
+
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java
new file mode 100644
index 0000000000..3118860390
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial25519.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2018, 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.math.intpoly;
+
+import java.math.BigInteger;
+
+/**
+ * An IntegerFieldModuloP designed for use with the Curve25519.
+ * The representation uses 10 signed long values.
+ */
+
+public class IntegerPolynomial25519 extends IntegerPolynomial {
+
+ private static final int POWER = 255;
+ private static final int SUBTRAHEND = 19;
+ private static final int NUM_LIMBS = 10;
+ private static final int BITS_PER_LIMB = 26;
+ public static final BigInteger MODULUS
+ = TWO.pow(POWER).subtract(BigInteger.valueOf(SUBTRAHEND));
+
+ // BITS_PER_LIMB does not divide POWER, so reduction is a bit complicated
+ // The constants below help split up values during reduction
+ private static final int BIT_OFFSET = NUM_LIMBS * BITS_PER_LIMB - POWER;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ private static final int RIGHT_BIT_OFFSET = BITS_PER_LIMB - BIT_OFFSET;
+
+ public IntegerPolynomial25519() {
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
+ }
+
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+
+ long reducedValue = limbs[numLimbs - 1] >> RIGHT_BIT_OFFSET;
+ limbs[numLimbs - 1] -= reducedValue << RIGHT_BIT_OFFSET;
+ limbs[0] += reducedValue * SUBTRAHEND;
+ }
+
+ @Override
+ protected void reduce(long[] a) {
+
+ // carry(8, 2)
+ long carry8 = carryValue(a[8]);
+ a[8] -= (carry8 << BITS_PER_LIMB);
+ a[9] += carry8;
+
+ long carry9 = carryValue(a[9]);
+ a[9] -= (carry9 << BITS_PER_LIMB);
+
+ // reduce(0, 1)
+ long reducedValue10 = (carry9 * SUBTRAHEND);
+ a[0] += ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
+ a[1] += reducedValue10 >> RIGHT_BIT_OFFSET;
+
+ // carry(0, 9)
+ carry(a, 0, 9);
+ }
+
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+
+ // Use grade-school multiplication into primitives to avoid the
+ // temporary array allocation. This is equivalent to the following
+ // code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // for(int j - 0; j < NUM_LIMBS; j++) {
+ // c[i + j] += a[i] * b[j]
+ // }
+ // }
+
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+ long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+ long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+ long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+ long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+ long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+ long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+ long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+ long c18 = a[9] * b[9];
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8,
+ c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+
+ }
+
+ private void carryReduce(long[] r, long c0, long c1, long c2,
+ long c3, long c4, long c5, long c6,
+ long c7, long c8, long c9, long c10,
+ long c11, long c12, long c13, long c14,
+ long c15, long c16, long c17, long c18) {
+ // reduce(7,2)
+ long reducedValue17 = (c17 * SUBTRAHEND);
+ c7 += (reducedValue17 << BIT_OFFSET) & LIMB_MASK;
+ c8 += reducedValue17 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue18 = (c18 * SUBTRAHEND);
+ c8 += (reducedValue18 << BIT_OFFSET) & LIMB_MASK;
+ c9 += reducedValue18 >> RIGHT_BIT_OFFSET;
+
+ // carry(8,2)
+ long carry8 = carryValue(c8);
+ r[8] = c8 - (carry8 << BITS_PER_LIMB);
+ c9 += carry8;
+
+ long carry9 = carryValue(c9);
+ r[9] = c9 - (carry9 << BITS_PER_LIMB);
+ c10 += carry9;
+
+ // reduce(0,7)
+ long reducedValue10 = (c10 * SUBTRAHEND);
+ r[0] = c0 + ((reducedValue10 << BIT_OFFSET) & LIMB_MASK);
+ c1 += reducedValue10 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue11 = (c11 * SUBTRAHEND);
+ r[1] = c1 + ((reducedValue11 << BIT_OFFSET) & LIMB_MASK);
+ c2 += reducedValue11 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue12 = (c12 * SUBTRAHEND);
+ r[2] = c2 + ((reducedValue12 << BIT_OFFSET) & LIMB_MASK);
+ c3 += reducedValue12 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue13 = (c13 * SUBTRAHEND);
+ r[3] = c3 + ((reducedValue13 << BIT_OFFSET) & LIMB_MASK);
+ c4 += reducedValue13 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue14 = (c14 * SUBTRAHEND);
+ r[4] = c4 + ((reducedValue14 << BIT_OFFSET) & LIMB_MASK);
+ c5 += reducedValue14 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue15 = (c15 * SUBTRAHEND);
+ r[5] = c5 + ((reducedValue15 << BIT_OFFSET) & LIMB_MASK);
+ c6 += reducedValue15 >> RIGHT_BIT_OFFSET;
+
+ long reducedValue16 = (c16 * SUBTRAHEND);
+ r[6] = c6 + ((reducedValue16 << BIT_OFFSET) & LIMB_MASK);
+ r[7] = c7 + (reducedValue16 >> RIGHT_BIT_OFFSET);
+
+ // carry(0,9)
+ carry(r, 0, 9);
+ }
+
+ @Override
+ protected void square(long[] a, long[] r) {
+
+ // Use grade-school multiplication with a simple squaring optimization.
+ // Multiply into primitives to avoid the temporary array allocation.
+ // This is equivalent to the following code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // c[2 * i] = a[i] * a[i];
+ // for(int j = i + 1; j < NUM_LIMBS; j++) {
+ // c[i + j] += 2 * a[i] * a[j]
+ // }
+ // }
+
+ long c0 = a[0] * a[0];
+ long c1 = 2 * a[0] * a[1];
+ long c2 = a[1] * a[1] + 2 * a[0] * a[2];
+ long c3 = 2 * (a[0] * a[3] + a[1] * a[2]);
+ long c4 = a[2] * a[2] + 2 * (a[0] * a[4] + a[1] * a[3]);
+ long c5 = 2 * (a[0] * a[5] + a[1] * a[4] + a[2] * a[3]);
+ long c6 = a[3] * a[3] + 2 * (a[0] * a[6] + a[1] * a[5] + a[2] * a[4]);
+ long c7 = 2 * (a[0] * a[7] + a[1] * a[6] + a[2] * a[5] + a[3] * a[4]);
+ long c8 = a[4] * a[4] + 2 * (a[0] * a[8] + a[1] * a[7] + a[2] * a[6] + a[3] * a[5]);
+ long c9 = 2 * (a[0] * a[9] + a[1] * a[8] + a[2] * a[7] + a[3] * a[6] + a[4] * a[5]);
+ long c10 = a[5] * a[5] + 2 * (a[1] * a[9] + a[2] * a[8] + a[3] * a[7] + a[4] * a[6]);
+ long c11 = 2 * (a[2] * a[9] + a[3] * a[8] + a[4] * a[7] + a[5] * a[6]);
+ long c12 = a[6] * a[6] + 2 * (a[3] * a[9] + a[4] * a[8] + a[5] * a[7]);
+ long c13 = 2 * (a[4] * a[9] + a[5] * a[8] + a[6] * a[7]);
+ long c14 = a[7] * a[7] + 2 * (a[5] * a[9] + a[6] * a[8]);
+ long c15 = 2 * (a[6] * a[9] + a[7] * a[8]);
+ long c16 = a[8] * a[8] + 2 * a[7] * a[9];
+ long c17 = 2 * a[8] * a[9];
+ long c18 = a[9] * a[9];
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8,
+ c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+
+
+}
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java
new file mode 100644
index 0000000000..70c4f00952
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomial448.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2018, 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.math.intpoly;
+
+import java.math.BigInteger;
+
+/**
+ * An IntegerFieldModuloP designed for use with the Curve448.
+ * The representation uses 16 signed long values.
+ */
+
+public class IntegerPolynomial448 extends IntegerPolynomial {
+
+ private static final int POWER = 448;
+ private static final int NUM_LIMBS = 16;
+ private static final int BITS_PER_LIMB = 28;
+ public static final BigInteger MODULUS
+ = TWO.pow(POWER).subtract(TWO.pow(POWER / 2))
+ .subtract(BigInteger.valueOf(1));
+
+ public IntegerPolynomial448() {
+ super(BITS_PER_LIMB, NUM_LIMBS, 1, MODULUS);
+ }
+
+ private void modReduceIn(long[] limbs, int index, long x) {
+ limbs[index - NUM_LIMBS] += x;
+ limbs[index - NUM_LIMBS / 2] += x;
+ }
+
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long carry = limbs[numLimbs - 1] >> bitsPerLimb;
+ limbs[numLimbs - 1] -= carry << bitsPerLimb;
+ modReduceIn(limbs, numLimbs, carry);
+ }
+
+ @Override
+ protected void reduce(long[] a) {
+
+ // carry(14, 2)
+ long carry14 = carryValue(a[14]);
+ a[14] -= (carry14 << BITS_PER_LIMB);
+ a[15] += carry14;
+
+ long carry15 = carryValue(a[15]);
+ a[15] -= (carry15 << BITS_PER_LIMB);
+
+ // reduce(0, 1)
+ a[0] += carry15;
+ a[8] += carry15;
+
+ // carry(0, 15)
+ carry(a, 0, 15);
+ }
+
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+
+ // Use grade-school multiplication into primitives to avoid the
+ // temporary array allocation. This is equivalent to the following
+ // code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // for(int j - 0; j < NUM_LIMBS; j++) {
+ // c[i + j] += a[i] * b[j]
+ // }
+ // }
+
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+ long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+ long c16 = (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]);
+ long c17 = (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]);
+ long c18 = (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]);
+ long c19 = (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]);
+ long c20 = (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]);
+ long c21 = (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]);
+ long c22 = (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]);
+ long c23 = (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]);
+ long c24 = (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]);
+ long c25 = (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]);
+ long c26 = (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]);
+ long c27 = (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]);
+ long c28 = (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]);
+ long c29 = (a[14] * b[15]) + (a[15] * b[14]);
+ long c30 = (a[15] * b[15]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25,
+ c26, c27, c28, c29, c30);
+ }
+
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3,
+ long c4, long c5, long c6, long c7, long c8,
+ long c9, long c10, long c11, long c12, long c13,
+ long c14, long c15, long c16, long c17, long c18,
+ long c19, long c20, long c21, long c22, long c23,
+ long c24, long c25, long c26, long c27, long c28,
+ long c29, long c30) {
+
+ // reduce(8, 7)
+ c8 += c24;
+ c16 += c24;
+
+ c9 += c25;
+ c17 += c25;
+
+ c10 += c26;
+ c18 += c26;
+
+ c11 += c27;
+ c19 += c27;
+
+ c12 += c28;
+ c20 += c28;
+
+ c13 += c29;
+ c21 += c29;
+
+ c14 += c30;
+ c22 += c30;
+
+ // reduce(4, 4)
+ r[4] = c4 + c20;
+ r[12] = c12 + c20;
+
+ r[5] = c5 + c21;
+ r[13] = c13 + c21;
+
+ r[6] = c6 + c22;
+ c14 += c22;
+
+ r[7] = c7 + c23;
+ c15 += c23;
+
+ //carry(14, 2)
+ long carry14 = carryValue(c14);
+ r[14] = c14 - (carry14 << BITS_PER_LIMB);
+ c15 += carry14;
+
+ long carry15 = carryValue(c15);
+ r[15] = c15 - (carry15 << BITS_PER_LIMB);
+ c16 += carry15;
+
+ // reduce(0, 4)
+ r[0] = c0 + c16;
+ r[8] = c8 + c16;
+
+ r[1] = c1 + c17;
+ r[9] = c9 + c17;
+
+ r[2] = c2 + c18;
+ r[10] = c10 + c18;
+
+ r[3] = c3 + c19;
+ r[11] = c11 + c19;
+
+ // carry(0, 15)
+ carry(r, 0, 15);
+ }
+
+ @Override
+ protected void square(long[] a, long[] r) {
+
+ // Use grade-school multiplication with a simple squaring optimization.
+ // Multiply into primitives to avoid the temporary array allocation.
+ // This is equivalent to the following code:
+ // long[] c = new long[2 * NUM_LIMBS - 1];
+ // for(int i = 0; i < NUM_LIMBS; i++) {
+ // c[2 * i] = a[i] * a[i];
+ // for(int j = i + 1; j < NUM_LIMBS; j++) {
+ // c[i + j] += 2 * a[i] * a[j]
+ // }
+ // }
+
+ long c0 = a[0] * a[0];
+ long c1 = 2 * a[0] * a[1];
+ long c2 = a[1] * a[1] + 2 * a[0] * a[2];
+ long c3 = 2 * (a[0] * a[3] + a[1] * a[2]);
+ long c4 = a[2] * a[2] + 2 * (a[0] * a[4] + a[1] * a[3]);
+ long c5 = 2 * (a[0] * a[5] + a[1] * a[4] + a[2] * a[3]);
+ long c6 = a[3] * a[3] + 2 * (a[0] * a[6] + a[1] * a[5] + a[2] * a[4]);
+ long c7 = 2 * (a[0] * a[7] + a[1] * a[6] + a[2] * a[5] + a[3] * a[4]);
+ long c8 = a[4] * a[4] + 2 * (a[0] * a[8] + a[1] * a[7] + a[2] * a[6] + a[3] * a[5]);
+ long c9 = 2 * (a[0] * a[9] + a[1] * a[8] + a[2] * a[7] + a[3] * a[6] + a[4] * a[5]);
+ long c10 = a[5] * a[5] + 2 * (a[0] * a[10] + a[1] * a[9] + a[2] * a[8] + a[3] * a[7] + a[4] * a[6]);
+ long c11 = 2 * (a[0] * a[11] + a[1] * a[10] + a[2] * a[9] + a[3] * a[8] + a[4] * a[7] + a[5] * a[6]);
+ long c12 = a[6] * a[6] + 2 * (a[0] * a[12] + a[1] * a[11] + a[2] * a[10] + a[3] * a[9] + a[4] * a[8] + a[5] * a[7]);
+ long c13 = 2 * (a[0] * a[13] + a[1] * a[12] + a[2] * a[11] + a[3] * a[10] + a[4] * a[9] + a[5] * a[8] + a[6] * a[7]);
+ long c14 = a[7] * a[7] + 2 * (a[0] * a[14] + a[1] * a[13] + a[2] * a[12] + a[3] * a[11] + a[4] * a[10] + a[5] * a[9] + a[6] * a[8]);
+ long c15 = 2 * (a[0] * a[15] + a[1] * a[14] + a[2] * a[13] + a[3] * a[12] + a[4] * a[11] + a[5] * a[10] + a[6] * a[9] + a[7] * a[8]);
+ long c16 = a[8] * a[8] + 2 * (a[1] * a[15] + a[2] * a[14] + a[3] * a[13] + a[4] * a[12] + a[5] * a[11] + a[6] * a[10] + a[7] * a[9]);
+ long c17 = 2 * (a[2] * a[15] + a[3] * a[14] + a[4] * a[13] + a[5] * a[12] + a[6] * a[11] + a[7] * a[10] + a[8] * a[9]);
+ long c18 = a[9] * a[9] + 2 * (a[3] * a[15] + a[4] * a[14] + a[5] * a[13] + a[6] * a[12] + a[7] * a[11] + a[8] * a[10]);
+ long c19 = 2 * (a[4] * a[15] + a[5] * a[14] + a[6] * a[13] + a[7] * a[12] + a[8] * a[11] + a[9] * a[10]);
+ long c20 = a[10] * a[10] + 2 * (a[5] * a[15] + a[6] * a[14] + a[7] * a[13] + a[8] * a[12] + a[9] * a[11]);
+ long c21 = 2 * (a[6] * a[15] + a[7] * a[14] + a[8] * a[13] + a[9] * a[12] + a[10] * a[11]);
+ long c22 = a[11] * a[11] + 2 * (a[7] * a[15] + a[8] * a[14] + a[9] * a[13] + a[10] * a[12]);
+ long c23 = 2 * (a[8] * a[15] + a[9] * a[14] + a[10] * a[13] + a[11] * a[12]);
+ long c24 = a[12] * a[12] + 2 * (a[9] * a[15] + a[10] * a[14] + a[11] * a[13]);
+ long c25 = 2 * (a[10] * a[15] + a[11] * a[14] + a[12] * a[13]);
+ long c26 = a[13] * a[13] + 2 * (a[11] * a[15] + a[12] * a[14]);
+ long c27 = 2 * (a[12] * a[15] + a[13] * a[14]);
+ long c28 = a[14] * a[14] + 2 * a[13] * a[15];
+ long c29 = 2 * a[14] * a[15];
+ long c30 = a[15] * a[15];
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25,
+ c26, c27, c28, c29, c30);
+
+ }
+
+
+}
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java
new file mode 100644
index 0000000000..e364db1ae0
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP256.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP256 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 26;
+ private static final int NUM_LIMBS = 10;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 25;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP256() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(256);
+ result = result.subtract(BigInteger.valueOf(2).pow(224));
+ result = result.add(BigInteger.valueOf(2).pow(192));
+ result = result.add(BigInteger.valueOf(2).pow(96));
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[9] >> 22;
+ limbs[9] -= c << 22;
+ limbs[8] += (c << 16) & LIMB_MASK;
+ limbs[9] += c >> 10;
+ limbs[7] -= (c << 10) & LIMB_MASK;
+ limbs[8] -= c >> 16;
+ limbs[3] -= (c << 18) & LIMB_MASK;
+ limbs[4] -= c >> 8;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //reduce from position 18
+ c16 += (c18 << 20) & LIMB_MASK;
+ c17 += c18 >> 6;
+ c15 -= (c18 << 14) & LIMB_MASK;
+ c16 -= c18 >> 12;
+ c11 -= (c18 << 22) & LIMB_MASK;
+ c12 -= c18 >> 4;
+ c8 += (c18 << 4) & LIMB_MASK;
+ c9 += c18 >> 22;
+ //reduce from position 17
+ c15 += (c17 << 20) & LIMB_MASK;
+ c16 += c17 >> 6;
+ c14 -= (c17 << 14) & LIMB_MASK;
+ c15 -= c17 >> 12;
+ c10 -= (c17 << 22) & LIMB_MASK;
+ c11 -= c17 >> 4;
+ c7 += (c17 << 4) & LIMB_MASK;
+ c8 += c17 >> 22;
+ //reduce from position 16
+ c14 += (c16 << 20) & LIMB_MASK;
+ c15 += c16 >> 6;
+ c13 -= (c16 << 14) & LIMB_MASK;
+ c14 -= c16 >> 12;
+ c9 -= (c16 << 22) & LIMB_MASK;
+ c10 -= c16 >> 4;
+ c6 += (c16 << 4) & LIMB_MASK;
+ c7 += c16 >> 22;
+ //reduce from position 15
+ c13 += (c15 << 20) & LIMB_MASK;
+ c14 += c15 >> 6;
+ c12 -= (c15 << 14) & LIMB_MASK;
+ c13 -= c15 >> 12;
+ c8 -= (c15 << 22) & LIMB_MASK;
+ c9 -= c15 >> 4;
+ c5 += (c15 << 4) & LIMB_MASK;
+ c6 += c15 >> 22;
+ //reduce from position 14
+ c12 += (c14 << 20) & LIMB_MASK;
+ c13 += c14 >> 6;
+ c11 -= (c14 << 14) & LIMB_MASK;
+ c12 -= c14 >> 12;
+ c7 -= (c14 << 22) & LIMB_MASK;
+ c8 -= c14 >> 4;
+ c4 += (c14 << 4) & LIMB_MASK;
+ c5 += c14 >> 22;
+ //reduce from position 13
+ c11 += (c13 << 20) & LIMB_MASK;
+ c12 += c13 >> 6;
+ c10 -= (c13 << 14) & LIMB_MASK;
+ c11 -= c13 >> 12;
+ c6 -= (c13 << 22) & LIMB_MASK;
+ c7 -= c13 >> 4;
+ c3 += (c13 << 4) & LIMB_MASK;
+ c4 += c13 >> 22;
+ //reduce from position 12
+ c10 += (c12 << 20) & LIMB_MASK;
+ c11 += c12 >> 6;
+ c9 -= (c12 << 14) & LIMB_MASK;
+ c10 -= c12 >> 12;
+ c5 -= (c12 << 22) & LIMB_MASK;
+ c6 -= c12 >> 4;
+ c2 += (c12 << 4) & LIMB_MASK;
+ c3 += c12 >> 22;
+ //reduce from position 11
+ c9 += (c11 << 20) & LIMB_MASK;
+ c10 += c11 >> 6;
+ c8 -= (c11 << 14) & LIMB_MASK;
+ c9 -= c11 >> 12;
+ c4 -= (c11 << 22) & LIMB_MASK;
+ c5 -= c11 >> 4;
+ c1 += (c11 << 4) & LIMB_MASK;
+ c2 += c11 >> 22;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ c10 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+
+ //carry from position 8
+ long t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+ long c10 = 0;
+ //carry from position 8
+ long t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //reduce from position 10
+ c8 += (c10 << 20) & LIMB_MASK;
+ c9 += c10 >> 6;
+ c7 -= (c10 << 14) & LIMB_MASK;
+ c8 -= c10 >> 12;
+ c3 -= (c10 << 22) & LIMB_MASK;
+ c4 -= c10 >> 4;
+ c0 += (c10 << 4) & LIMB_MASK;
+ c1 += c10 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+ long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+ long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+ long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+ long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+ long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+ long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+ long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+ long c18 = (a[9] * b[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[8] * a[9]));
+ long c18 = (a[9] * a[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java
new file mode 100644
index 0000000000..91c3bab57d
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP384.java
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP384 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 14;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP384() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(384);
+ result = result.subtract(BigInteger.valueOf(2).pow(128));
+ result = result.subtract(BigInteger.valueOf(2).pow(96));
+ result = result.add(BigInteger.valueOf(2).pow(32));
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[13] >> 20;
+ limbs[13] -= c << 20;
+ limbs[4] += (c << 16) & LIMB_MASK;
+ limbs[5] += c >> 12;
+ limbs[3] += (c << 12) & LIMB_MASK;
+ limbs[4] += c >> 16;
+ limbs[1] -= (c << 4) & LIMB_MASK;
+ limbs[2] -= c >> 24;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+ long c27 = 0;
+ //reduce from position 26
+ c16 += (c26 << 24) & LIMB_MASK;
+ c17 += c26 >> 4;
+ c15 += (c26 << 20) & LIMB_MASK;
+ c16 += c26 >> 8;
+ c13 -= (c26 << 12) & LIMB_MASK;
+ c14 -= c26 >> 16;
+ c12 += (c26 << 8) & LIMB_MASK;
+ c13 += c26 >> 20;
+ //reduce from position 25
+ c15 += (c25 << 24) & LIMB_MASK;
+ c16 += c25 >> 4;
+ c14 += (c25 << 20) & LIMB_MASK;
+ c15 += c25 >> 8;
+ c12 -= (c25 << 12) & LIMB_MASK;
+ c13 -= c25 >> 16;
+ c11 += (c25 << 8) & LIMB_MASK;
+ c12 += c25 >> 20;
+ //reduce from position 24
+ c14 += (c24 << 24) & LIMB_MASK;
+ c15 += c24 >> 4;
+ c13 += (c24 << 20) & LIMB_MASK;
+ c14 += c24 >> 8;
+ c11 -= (c24 << 12) & LIMB_MASK;
+ c12 -= c24 >> 16;
+ c10 += (c24 << 8) & LIMB_MASK;
+ c11 += c24 >> 20;
+ //reduce from position 23
+ c13 += (c23 << 24) & LIMB_MASK;
+ c14 += c23 >> 4;
+ c12 += (c23 << 20) & LIMB_MASK;
+ c13 += c23 >> 8;
+ c10 -= (c23 << 12) & LIMB_MASK;
+ c11 -= c23 >> 16;
+ c9 += (c23 << 8) & LIMB_MASK;
+ c10 += c23 >> 20;
+ //reduce from position 22
+ c12 += (c22 << 24) & LIMB_MASK;
+ c13 += c22 >> 4;
+ c11 += (c22 << 20) & LIMB_MASK;
+ c12 += c22 >> 8;
+ c9 -= (c22 << 12) & LIMB_MASK;
+ c10 -= c22 >> 16;
+ c8 += (c22 << 8) & LIMB_MASK;
+ c9 += c22 >> 20;
+ //reduce from position 21
+ c11 += (c21 << 24) & LIMB_MASK;
+ c12 += c21 >> 4;
+ c10 += (c21 << 20) & LIMB_MASK;
+ c11 += c21 >> 8;
+ c8 -= (c21 << 12) & LIMB_MASK;
+ c9 -= c21 >> 16;
+ c7 += (c21 << 8) & LIMB_MASK;
+ c8 += c21 >> 20;
+ //reduce from position 20
+ c10 += (c20 << 24) & LIMB_MASK;
+ c11 += c20 >> 4;
+ c9 += (c20 << 20) & LIMB_MASK;
+ c10 += c20 >> 8;
+ c7 -= (c20 << 12) & LIMB_MASK;
+ c8 -= c20 >> 16;
+ c6 += (c20 << 8) & LIMB_MASK;
+ c7 += c20 >> 20;
+ //reduce from position 19
+ c9 += (c19 << 24) & LIMB_MASK;
+ c10 += c19 >> 4;
+ c8 += (c19 << 20) & LIMB_MASK;
+ c9 += c19 >> 8;
+ c6 -= (c19 << 12) & LIMB_MASK;
+ c7 -= c19 >> 16;
+ c5 += (c19 << 8) & LIMB_MASK;
+ c6 += c19 >> 20;
+ //reduce from position 18
+ c8 += (c18 << 24) & LIMB_MASK;
+ c9 += c18 >> 4;
+ c7 += (c18 << 20) & LIMB_MASK;
+ c8 += c18 >> 8;
+ c5 -= (c18 << 12) & LIMB_MASK;
+ c6 -= c18 >> 16;
+ c4 += (c18 << 8) & LIMB_MASK;
+ c5 += c18 >> 20;
+ //reduce from position 17
+ c7 += (c17 << 24) & LIMB_MASK;
+ c8 += c17 >> 4;
+ c6 += (c17 << 20) & LIMB_MASK;
+ c7 += c17 >> 8;
+ c4 -= (c17 << 12) & LIMB_MASK;
+ c5 -= c17 >> 16;
+ c3 += (c17 << 8) & LIMB_MASK;
+ c4 += c17 >> 20;
+ //reduce from position 16
+ c6 += (c16 << 24) & LIMB_MASK;
+ c7 += c16 >> 4;
+ c5 += (c16 << 20) & LIMB_MASK;
+ c6 += c16 >> 8;
+ c3 -= (c16 << 12) & LIMB_MASK;
+ c4 -= c16 >> 16;
+ c2 += (c16 << 8) & LIMB_MASK;
+ c3 += c16 >> 20;
+ //reduce from position 15
+ c5 += (c15 << 24) & LIMB_MASK;
+ c6 += c15 >> 4;
+ c4 += (c15 << 20) & LIMB_MASK;
+ c5 += c15 >> 8;
+ c2 -= (c15 << 12) & LIMB_MASK;
+ c3 -= c15 >> 16;
+ c1 += (c15 << 8) & LIMB_MASK;
+ c2 += c15 >> 20;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ c14 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+
+ //carry from position 12
+ long t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+ long c14 = 0;
+ //carry from position 12
+ long t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //reduce from position 14
+ c4 += (c14 << 24) & LIMB_MASK;
+ c5 += c14 >> 4;
+ c3 += (c14 << 20) & LIMB_MASK;
+ c4 += c14 >> 8;
+ c1 -= (c14 << 12) & LIMB_MASK;
+ c2 -= c14 >> 16;
+ c0 += (c14 << 8) & LIMB_MASK;
+ c1 += c14 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+ long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+ long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+ long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+ long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+ long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+ long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+ long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+ long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+ long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+ long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+ long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+ long c26 = (a[13] * b[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[12] * a[13]));
+ long c26 = (a[13] * a[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java
new file mode 100644
index 0000000000..7899b62e02
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/IntegerPolynomialP521.java
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class IntegerPolynomialP521 extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 19;
+ private static final int MAX_ADDS = 2;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public IntegerPolynomialP521() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(521);
+ result = result.subtract(BigInteger.valueOf(1));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[18] >> 17;
+ limbs[18] -= c << 17;
+ limbs[0] += c;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+ long c37 = 0;
+ //reduce from position 36
+ c17 += (c36 << 11) & LIMB_MASK;
+ c18 += c36 >> 17;
+ //reduce from position 35
+ c16 += (c35 << 11) & LIMB_MASK;
+ c17 += c35 >> 17;
+ //reduce from position 34
+ c15 += (c34 << 11) & LIMB_MASK;
+ c16 += c34 >> 17;
+ //reduce from position 33
+ c14 += (c33 << 11) & LIMB_MASK;
+ c15 += c33 >> 17;
+ //reduce from position 32
+ c13 += (c32 << 11) & LIMB_MASK;
+ c14 += c32 >> 17;
+ //reduce from position 31
+ c12 += (c31 << 11) & LIMB_MASK;
+ c13 += c31 >> 17;
+ //reduce from position 30
+ c11 += (c30 << 11) & LIMB_MASK;
+ c12 += c30 >> 17;
+ //reduce from position 29
+ c10 += (c29 << 11) & LIMB_MASK;
+ c11 += c29 >> 17;
+ //reduce from position 28
+ c9 += (c28 << 11) & LIMB_MASK;
+ c10 += c28 >> 17;
+ //reduce from position 27
+ c8 += (c27 << 11) & LIMB_MASK;
+ c9 += c27 >> 17;
+ //reduce from position 26
+ c7 += (c26 << 11) & LIMB_MASK;
+ c8 += c26 >> 17;
+ //reduce from position 25
+ c6 += (c25 << 11) & LIMB_MASK;
+ c7 += c25 >> 17;
+ //reduce from position 24
+ c5 += (c24 << 11) & LIMB_MASK;
+ c6 += c24 >> 17;
+ //reduce from position 23
+ c4 += (c23 << 11) & LIMB_MASK;
+ c5 += c23 >> 17;
+ //reduce from position 22
+ c3 += (c22 << 11) & LIMB_MASK;
+ c4 += c22 >> 17;
+ //reduce from position 21
+ c2 += (c21 << 11) & LIMB_MASK;
+ c3 += c21 >> 17;
+ //reduce from position 20
+ c1 += (c20 << 11) & LIMB_MASK;
+ c2 += c20 >> 17;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ c19 = 0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+
+ //carry from position 17
+ long t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 17
+ long t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //reduce from position 19
+ c0 += (c19 << 11) & LIMB_MASK;
+ c1 += c19 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+ long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+ long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+ long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+ long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+ long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+ long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+ long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+ long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+ long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+ long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+ long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+ long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+ long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+ long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+ long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+ long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+ long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+ long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+ long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+ long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+ long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+ long c36 = (a[18] * b[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+ long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+ long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+ long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+ long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+ long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+ long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+ long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+ long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+ long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+ long c35 = 2 * ((a[17] * a[18]));
+ long c36 = (a[18] * a[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/P256OrderField.java b/src/share/classes/sun/security/util/math/intpoly/P256OrderField.java
new file mode 100644
index 0000000000..5831d12e06
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/P256OrderField.java
@@ -0,0 +1,673 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P256OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 26;
+ private static final int NUM_LIMBS = 10;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 25;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P256OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(256);
+ result = result.add(BigInteger.valueOf(6497617));
+ result = result.subtract(BigInteger.valueOf(2).pow(26).multiply(BigInteger.valueOf(26038081)));
+ result = result.add(BigInteger.valueOf(2).pow(52).multiply(BigInteger.valueOf(32001852)));
+ result = result.subtract(BigInteger.valueOf(2).pow(78).multiply(BigInteger.valueOf(21586850)));
+ result = result.subtract(BigInteger.valueOf(2).pow(104).multiply(BigInteger.valueOf(4397317)));
+ result = result.add(BigInteger.valueOf(2).pow(182).multiply(BigInteger.valueOf(1024)));
+ result = result.subtract(BigInteger.valueOf(2).pow(208).multiply(BigInteger.valueOf(65536)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[9] >> 22;
+ limbs[9] -= c << 22;
+ long t0 = -6497617 * c;
+ limbs[0] += t0;
+ t0 = 26038081 * c;
+ limbs[1] += t0;
+ t0 = -32001852 * c;
+ limbs[2] += t0;
+ t0 = 21586850 * c;
+ limbs[3] += t0;
+ t0 = 4397317 * c;
+ limbs[4] += t0;
+ t0 = -1024 * c;
+ limbs[7] += t0;
+ t0 = 65536 * c;
+ limbs[8] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 26;
+ c10 -= (t0 << 26);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 26;
+ c11 -= (t0 << 26);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 26;
+ c12 -= (t0 << 26);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 26;
+ c13 -= (t0 << 26);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 26;
+ c14 -= (t0 << 26);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 26;
+ c15 -= (t0 << 26);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 26;
+ c16 -= (t0 << 26);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 26;
+ c17 -= (t0 << 26);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 26;
+ c18 -= (t0 << 26);
+ c19 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -6497617 * c19;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 26038081 * c19;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = -32001852 * c19;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 21586850 * c19;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = 4397317 * c19;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ t0 = -1024 * c19;
+ c16 += (t0 << 4) & LIMB_MASK;
+ c17 += t0 >> 22;
+ t0 = 65536 * c19;
+ c17 += (t0 << 4) & LIMB_MASK;
+ c18 += t0 >> 22;
+ //reduce from position 18
+ t0 = -6497617 * c18;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 26038081 * c18;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = -32001852 * c18;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 21586850 * c18;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 4397317 * c18;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = -1024 * c18;
+ c15 += (t0 << 4) & LIMB_MASK;
+ c16 += t0 >> 22;
+ t0 = 65536 * c18;
+ c16 += (t0 << 4) & LIMB_MASK;
+ c17 += t0 >> 22;
+ //reduce from position 17
+ t0 = -6497617 * c17;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 26038081 * c17;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = -32001852 * c17;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 21586850 * c17;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 4397317 * c17;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = -1024 * c17;
+ c14 += (t0 << 4) & LIMB_MASK;
+ c15 += t0 >> 22;
+ t0 = 65536 * c17;
+ c15 += (t0 << 4) & LIMB_MASK;
+ c16 += t0 >> 22;
+ //reduce from position 16
+ t0 = -6497617 * c16;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 26038081 * c16;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = -32001852 * c16;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 21586850 * c16;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 4397317 * c16;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = -1024 * c16;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ t0 = 65536 * c16;
+ c14 += (t0 << 4) & LIMB_MASK;
+ c15 += t0 >> 22;
+ //reduce from position 15
+ t0 = -6497617 * c15;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 26038081 * c15;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = -32001852 * c15;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 21586850 * c15;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 4397317 * c15;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = -1024 * c15;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ t0 = 65536 * c15;
+ c13 += (t0 << 4) & LIMB_MASK;
+ c14 += t0 >> 22;
+ //reduce from position 14
+ t0 = -6497617 * c14;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 26038081 * c14;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = -32001852 * c14;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 21586850 * c14;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 4397317 * c14;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = -1024 * c14;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ t0 = 65536 * c14;
+ c12 += (t0 << 4) & LIMB_MASK;
+ c13 += t0 >> 22;
+ //reduce from position 13
+ t0 = -6497617 * c13;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 26038081 * c13;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -32001852 * c13;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 21586850 * c13;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = 4397317 * c13;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = -1024 * c13;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ t0 = 65536 * c13;
+ c11 += (t0 << 4) & LIMB_MASK;
+ c12 += t0 >> 22;
+ //reduce from position 12
+ t0 = -6497617 * c12;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 26038081 * c12;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = -32001852 * c12;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 21586850 * c12;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = 4397317 * c12;
+ c6 += (t0 << 4) & LIMB_MASK;
+ c7 += t0 >> 22;
+ t0 = -1024 * c12;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ t0 = 65536 * c12;
+ c10 += (t0 << 4) & LIMB_MASK;
+ c11 += t0 >> 22;
+ //reduce from position 11
+ t0 = -6497617 * c11;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = 26038081 * c11;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = -32001852 * c11;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 21586850 * c11;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = 4397317 * c11;
+ c5 += (t0 << 4) & LIMB_MASK;
+ c6 += t0 >> 22;
+ t0 = -1024 * c11;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ t0 = 65536 * c11;
+ c9 += (t0 << 4) & LIMB_MASK;
+ c10 += t0 >> 22;
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ c10 = 0;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9) {
+ long c10 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 26;
+ c9 -= (t0 << 26);
+ c10 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10) {
+ long t0;
+
+ //reduce from position 10
+ t0 = -6497617 * c10;
+ c0 += (t0 << 4) & LIMB_MASK;
+ c1 += t0 >> 22;
+ t0 = 26038081 * c10;
+ c1 += (t0 << 4) & LIMB_MASK;
+ c2 += t0 >> 22;
+ t0 = -32001852 * c10;
+ c2 += (t0 << 4) & LIMB_MASK;
+ c3 += t0 >> 22;
+ t0 = 21586850 * c10;
+ c3 += (t0 << 4) & LIMB_MASK;
+ c4 += t0 >> 22;
+ t0 = 4397317 * c10;
+ c4 += (t0 << 4) & LIMB_MASK;
+ c5 += t0 >> 22;
+ t0 = -1024 * c10;
+ c7 += (t0 << 4) & LIMB_MASK;
+ c8 += t0 >> 22;
+ t0 = 65536 * c10;
+ c8 += (t0 << 4) & LIMB_MASK;
+ c9 += t0 >> 22;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 26;
+ c0 -= (t0 << 26);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 26;
+ c1 -= (t0 << 26);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 26;
+ c2 -= (t0 << 26);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 26;
+ c3 -= (t0 << 26);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 26;
+ c4 -= (t0 << 26);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 26;
+ c5 -= (t0 << 26);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 26;
+ c6 -= (t0 << 26);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 26;
+ c7 -= (t0 << 26);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 26;
+ c8 -= (t0 << 26);
+ c9 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]);
+ long c11 = (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]);
+ long c12 = (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]);
+ long c13 = (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]);
+ long c14 = (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]);
+ long c15 = (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]);
+ long c16 = (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]);
+ long c17 = (a[8] * b[9]) + (a[9] * b[8]);
+ long c18 = (a[9] * b[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[8] * a[9]));
+ long c18 = (a[9] * a[9]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/P384OrderField.java b/src/share/classes/sun/security/util/math/intpoly/P384OrderField.java
new file mode 100644
index 0000000000..249faabd50
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/P384OrderField.java
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P384OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 14;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P384OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(384);
+ result = result.subtract(BigInteger.valueOf(54187661));
+ result = result.subtract(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(20867411)));
+ result = result.add(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(10975981)));
+ result = result.add(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(14361739)));
+ result = result.subtract(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(35694566)));
+ result = result.subtract(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(132168845)));
+ result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(3710130)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[13] >> 20;
+ limbs[13] -= c << 20;
+ long t0 = 54187661 * c;
+ limbs[0] += t0;
+ t0 = 20867411 * c;
+ limbs[1] += t0;
+ t0 = -10975981 * c;
+ limbs[2] += t0;
+ t0 = -14361739 * c;
+ limbs[3] += t0;
+ t0 = 35694566 * c;
+ limbs[4] += t0;
+ t0 = 132168845 * c;
+ limbs[5] += t0;
+ t0 = 3710130 * c;
+ limbs[6] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26) {
+ long c27 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //reduce from position 27
+ t0 = 54187661 * c27;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 20867411 * c27;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = -10975981 * c27;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = -14361739 * c27;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 35694566 * c27;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ t0 = 132168845 * c27;
+ c18 += (t0 << 8) & LIMB_MASK;
+ c19 += t0 >> 20;
+ t0 = 3710130 * c27;
+ c19 += (t0 << 8) & LIMB_MASK;
+ c20 += t0 >> 20;
+ //reduce from position 26
+ t0 = 54187661 * c26;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 20867411 * c26;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = -10975981 * c26;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = -14361739 * c26;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 35694566 * c26;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 132168845 * c26;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ t0 = 3710130 * c26;
+ c18 += (t0 << 8) & LIMB_MASK;
+ c19 += t0 >> 20;
+ //reduce from position 25
+ t0 = 54187661 * c25;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 20867411 * c25;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = -10975981 * c25;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = -14361739 * c25;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 35694566 * c25;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 132168845 * c25;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ t0 = 3710130 * c25;
+ c17 += (t0 << 8) & LIMB_MASK;
+ c18 += t0 >> 20;
+ //reduce from position 24
+ t0 = 54187661 * c24;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 20867411 * c24;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = -10975981 * c24;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = -14361739 * c24;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 35694566 * c24;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 132168845 * c24;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ t0 = 3710130 * c24;
+ c16 += (t0 << 8) & LIMB_MASK;
+ c17 += t0 >> 20;
+ //reduce from position 23
+ t0 = 54187661 * c23;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 20867411 * c23;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = -10975981 * c23;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = -14361739 * c23;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 35694566 * c23;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 132168845 * c23;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ t0 = 3710130 * c23;
+ c15 += (t0 << 8) & LIMB_MASK;
+ c16 += t0 >> 20;
+ //reduce from position 22
+ t0 = 54187661 * c22;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 20867411 * c22;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = -10975981 * c22;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = -14361739 * c22;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 35694566 * c22;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 132168845 * c22;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ t0 = 3710130 * c22;
+ c14 += (t0 << 8) & LIMB_MASK;
+ c15 += t0 >> 20;
+ //reduce from position 21
+ t0 = 54187661 * c21;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 20867411 * c21;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = -10975981 * c21;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = -14361739 * c21;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 35694566 * c21;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 132168845 * c21;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ t0 = 3710130 * c21;
+ c13 += (t0 << 8) & LIMB_MASK;
+ c14 += t0 >> 20;
+ //reduce from position 20
+ t0 = 54187661 * c20;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 20867411 * c20;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = -10975981 * c20;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = -14361739 * c20;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 35694566 * c20;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 132168845 * c20;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ t0 = 3710130 * c20;
+ c12 += (t0 << 8) & LIMB_MASK;
+ c13 += t0 >> 20;
+ //reduce from position 19
+ t0 = 54187661 * c19;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 20867411 * c19;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = -10975981 * c19;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = -14361739 * c19;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 35694566 * c19;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 132168845 * c19;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ t0 = 3710130 * c19;
+ c11 += (t0 << 8) & LIMB_MASK;
+ c12 += t0 >> 20;
+ //reduce from position 18
+ t0 = 54187661 * c18;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 20867411 * c18;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = -10975981 * c18;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = -14361739 * c18;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 35694566 * c18;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 132168845 * c18;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ t0 = 3710130 * c18;
+ c10 += (t0 << 8) & LIMB_MASK;
+ c11 += t0 >> 20;
+ //reduce from position 17
+ t0 = 54187661 * c17;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 20867411 * c17;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = -10975981 * c17;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = -14361739 * c17;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 35694566 * c17;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 132168845 * c17;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ t0 = 3710130 * c17;
+ c9 += (t0 << 8) & LIMB_MASK;
+ c10 += t0 >> 20;
+ //reduce from position 16
+ t0 = 54187661 * c16;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = 20867411 * c16;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = -10975981 * c16;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = -14361739 * c16;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 35694566 * c16;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 132168845 * c16;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ t0 = 3710130 * c16;
+ c8 += (t0 << 8) & LIMB_MASK;
+ c9 += t0 >> 20;
+ //reduce from position 15
+ t0 = 54187661 * c15;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = 20867411 * c15;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -10975981 * c15;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = -14361739 * c15;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 35694566 * c15;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 132168845 * c15;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ t0 = 3710130 * c15;
+ c7 += (t0 << 8) & LIMB_MASK;
+ c8 += t0 >> 20;
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ c14 = 0;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27) {
+ long t0;
+
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13) {
+ long c14 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14) {
+ long t0;
+
+ //reduce from position 14
+ t0 = 54187661 * c14;
+ c0 += (t0 << 8) & LIMB_MASK;
+ c1 += t0 >> 20;
+ t0 = 20867411 * c14;
+ c1 += (t0 << 8) & LIMB_MASK;
+ c2 += t0 >> 20;
+ t0 = -10975981 * c14;
+ c2 += (t0 << 8) & LIMB_MASK;
+ c3 += t0 >> 20;
+ t0 = -14361739 * c14;
+ c3 += (t0 << 8) & LIMB_MASK;
+ c4 += t0 >> 20;
+ t0 = 35694566 * c14;
+ c4 += (t0 << 8) & LIMB_MASK;
+ c5 += t0 >> 20;
+ t0 = 132168845 * c14;
+ c5 += (t0 << 8) & LIMB_MASK;
+ c6 += t0 >> 20;
+ t0 = 3710130 * c14;
+ c6 += (t0 << 8) & LIMB_MASK;
+ c7 += t0 >> 20;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]);
+ long c15 = (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]);
+ long c16 = (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]);
+ long c17 = (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]);
+ long c18 = (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]);
+ long c19 = (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]);
+ long c20 = (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]);
+ long c21 = (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]);
+ long c22 = (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]);
+ long c23 = (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]);
+ long c24 = (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]);
+ long c25 = (a[12] * b[13]) + (a[13] * b[12]);
+ long c26 = (a[13] * b[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[12] * a[13]));
+ long c26 = (a[13] * a[13]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/P521OrderField.java b/src/share/classes/sun/security/util/math/intpoly/P521OrderField.java
new file mode 100644
index 0000000000..439b7e0d59
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/P521OrderField.java
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
+
+package sun.security.util.math.intpoly;
+
+import java.math.BigInteger;
+public class P521OrderField extends IntegerPolynomial {
+ private static final int BITS_PER_LIMB = 28;
+ private static final int NUM_LIMBS = 19;
+ private static final int MAX_ADDS = 1;
+ public static final BigInteger MODULUS = evaluateModulus();
+ private static final long CARRY_ADD = 1 << 27;
+ private static final int LIMB_MASK = -1 >>> (64 - BITS_PER_LIMB);
+ public P521OrderField() {
+
+ super(BITS_PER_LIMB, NUM_LIMBS, MAX_ADDS, MODULUS);
+
+ }
+ private static BigInteger evaluateModulus() {
+ BigInteger result = BigInteger.valueOf(2).pow(521);
+ result = result.add(BigInteger.valueOf(20472841));
+ result = result.add(BigInteger.valueOf(2).pow(28).multiply(BigInteger.valueOf(117141993)));
+ result = result.subtract(BigInteger.valueOf(2).pow(56).multiply(BigInteger.valueOf(62411077)));
+ result = result.subtract(BigInteger.valueOf(2).pow(84).multiply(BigInteger.valueOf(56915814)));
+ result = result.add(BigInteger.valueOf(2).pow(112).multiply(BigInteger.valueOf(97532854)));
+ result = result.add(BigInteger.valueOf(2).pow(140).multiply(BigInteger.valueOf(76509338)));
+ result = result.subtract(BigInteger.valueOf(2).pow(168).multiply(BigInteger.valueOf(75510783)));
+ result = result.subtract(BigInteger.valueOf(2).pow(196).multiply(BigInteger.valueOf(67962521)));
+ result = result.add(BigInteger.valueOf(2).pow(224).multiply(BigInteger.valueOf(25593732)));
+ result = result.subtract(BigInteger.valueOf(2).pow(252).multiply(BigInteger.valueOf(91)));
+ return result;
+ }
+ @Override
+ protected void finalCarryReduceLast(long[] limbs) {
+ long c = limbs[18] >> 17;
+ limbs[18] -= c << 17;
+ long t0 = -20472841 * c;
+ limbs[0] += t0;
+ t0 = -117141993 * c;
+ limbs[1] += t0;
+ t0 = 62411077 * c;
+ limbs[2] += t0;
+ t0 = 56915814 * c;
+ limbs[3] += t0;
+ t0 = -97532854 * c;
+ limbs[4] += t0;
+ t0 = -76509338 * c;
+ limbs[5] += t0;
+ t0 = 75510783 * c;
+ limbs[6] += t0;
+ t0 = 67962521 * c;
+ limbs[7] += t0;
+ t0 = -25593732 * c;
+ limbs[8] += t0;
+ t0 = 91 * c;
+ limbs[9] += t0;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36) {
+ long c37 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+ //carry from position 27
+ t0 = (c27 + CARRY_ADD) >> 28;
+ c27 -= (t0 << 28);
+ c28 += t0;
+ //carry from position 28
+ t0 = (c28 + CARRY_ADD) >> 28;
+ c28 -= (t0 << 28);
+ c29 += t0;
+ //carry from position 29
+ t0 = (c29 + CARRY_ADD) >> 28;
+ c29 -= (t0 << 28);
+ c30 += t0;
+ //carry from position 30
+ t0 = (c30 + CARRY_ADD) >> 28;
+ c30 -= (t0 << 28);
+ c31 += t0;
+ //carry from position 31
+ t0 = (c31 + CARRY_ADD) >> 28;
+ c31 -= (t0 << 28);
+ c32 += t0;
+ //carry from position 32
+ t0 = (c32 + CARRY_ADD) >> 28;
+ c32 -= (t0 << 28);
+ c33 += t0;
+ //carry from position 33
+ t0 = (c33 + CARRY_ADD) >> 28;
+ c33 -= (t0 << 28);
+ c34 += t0;
+ //carry from position 34
+ t0 = (c34 + CARRY_ADD) >> 28;
+ c34 -= (t0 << 28);
+ c35 += t0;
+ //carry from position 35
+ t0 = (c35 + CARRY_ADD) >> 28;
+ c35 -= (t0 << 28);
+ c36 += t0;
+ //carry from position 36
+ t0 = (c36 + CARRY_ADD) >> 28;
+ c36 -= (t0 << 28);
+ c37 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //reduce from position 37
+ t0 = -20472841 * c37;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -117141993 * c37;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 62411077 * c37;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 56915814 * c37;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -97532854 * c37;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = -76509338 * c37;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 75510783 * c37;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = 67962521 * c37;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ t0 = -25593732 * c37;
+ c26 += (t0 << 11) & LIMB_MASK;
+ c27 += t0 >> 17;
+ t0 = 91 * c37;
+ c27 += (t0 << 11) & LIMB_MASK;
+ c28 += t0 >> 17;
+ //reduce from position 36
+ t0 = -20472841 * c36;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -117141993 * c36;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 62411077 * c36;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 56915814 * c36;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -97532854 * c36;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -76509338 * c36;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 75510783 * c36;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 67962521 * c36;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = -25593732 * c36;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ t0 = 91 * c36;
+ c26 += (t0 << 11) & LIMB_MASK;
+ c27 += t0 >> 17;
+ //reduce from position 35
+ t0 = -20472841 * c35;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -117141993 * c35;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 62411077 * c35;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 56915814 * c35;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -97532854 * c35;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -76509338 * c35;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 75510783 * c35;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 67962521 * c35;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = -25593732 * c35;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ t0 = 91 * c35;
+ c25 += (t0 << 11) & LIMB_MASK;
+ c26 += t0 >> 17;
+ //reduce from position 34
+ t0 = -20472841 * c34;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -117141993 * c34;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 62411077 * c34;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 56915814 * c34;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -97532854 * c34;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -76509338 * c34;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 75510783 * c34;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 67962521 * c34;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = -25593732 * c34;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ t0 = 91 * c34;
+ c24 += (t0 << 11) & LIMB_MASK;
+ c25 += t0 >> 17;
+ //reduce from position 33
+ t0 = -20472841 * c33;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -117141993 * c33;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 62411077 * c33;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 56915814 * c33;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -97532854 * c33;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -76509338 * c33;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 75510783 * c33;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 67962521 * c33;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = -25593732 * c33;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ t0 = 91 * c33;
+ c23 += (t0 << 11) & LIMB_MASK;
+ c24 += t0 >> 17;
+ //reduce from position 32
+ t0 = -20472841 * c32;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -117141993 * c32;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 62411077 * c32;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 56915814 * c32;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -97532854 * c32;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -76509338 * c32;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 75510783 * c32;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 67962521 * c32;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = -25593732 * c32;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ t0 = 91 * c32;
+ c22 += (t0 << 11) & LIMB_MASK;
+ c23 += t0 >> 17;
+ //reduce from position 31
+ t0 = -20472841 * c31;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -117141993 * c31;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 62411077 * c31;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 56915814 * c31;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -97532854 * c31;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -76509338 * c31;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 75510783 * c31;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 67962521 * c31;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = -25593732 * c31;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ t0 = 91 * c31;
+ c21 += (t0 << 11) & LIMB_MASK;
+ c22 += t0 >> 17;
+ //reduce from position 30
+ t0 = -20472841 * c30;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -117141993 * c30;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 62411077 * c30;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 56915814 * c30;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -97532854 * c30;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -76509338 * c30;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 75510783 * c30;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 67962521 * c30;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = -25593732 * c30;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ t0 = 91 * c30;
+ c20 += (t0 << 11) & LIMB_MASK;
+ c21 += t0 >> 17;
+ //reduce from position 29
+ t0 = -20472841 * c29;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -117141993 * c29;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 62411077 * c29;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 56915814 * c29;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -97532854 * c29;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -76509338 * c29;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 75510783 * c29;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 67962521 * c29;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = -25593732 * c29;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+ t0 = 91 * c29;
+ c19 += (t0 << 11) & LIMB_MASK;
+ c20 += t0 >> 17;
+ //reduce from position 28
+ t0 = -20472841 * c28;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -117141993 * c28;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 62411077 * c28;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 56915814 * c28;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -97532854 * c28;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -76509338 * c28;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 75510783 * c28;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 67962521 * c28;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = -25593732 * c28;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ t0 = 91 * c28;
+ c18 += (t0 << 11) & LIMB_MASK;
+ c19 += t0 >> 17;
+
+ carryReduce1(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce1(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //carry from position 19
+ t0 = (c19 + CARRY_ADD) >> 28;
+ c19 -= (t0 << 28);
+ c20 += t0;
+ //carry from position 20
+ t0 = (c20 + CARRY_ADD) >> 28;
+ c20 -= (t0 << 28);
+ c21 += t0;
+ //carry from position 21
+ t0 = (c21 + CARRY_ADD) >> 28;
+ c21 -= (t0 << 28);
+ c22 += t0;
+ //carry from position 22
+ t0 = (c22 + CARRY_ADD) >> 28;
+ c22 -= (t0 << 28);
+ c23 += t0;
+ //carry from position 23
+ t0 = (c23 + CARRY_ADD) >> 28;
+ c23 -= (t0 << 28);
+ c24 += t0;
+ //carry from position 24
+ t0 = (c24 + CARRY_ADD) >> 28;
+ c24 -= (t0 << 28);
+ c25 += t0;
+ //carry from position 25
+ t0 = (c25 + CARRY_ADD) >> 28;
+ c25 -= (t0 << 28);
+ c26 += t0;
+ //carry from position 26
+ t0 = (c26 + CARRY_ADD) >> 28;
+ c26 -= (t0 << 28);
+ c27 += t0;
+ //reduce from position 27
+ t0 = -20472841 * c27;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -117141993 * c27;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 62411077 * c27;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 56915814 * c27;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -97532854 * c27;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -76509338 * c27;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 75510783 * c27;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 67962521 * c27;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = -25593732 * c27;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ t0 = 91 * c27;
+ c17 += (t0 << 11) & LIMB_MASK;
+ c18 += t0 >> 17;
+ //reduce from position 26
+ t0 = -20472841 * c26;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -117141993 * c26;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 62411077 * c26;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 56915814 * c26;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -97532854 * c26;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -76509338 * c26;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 75510783 * c26;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 67962521 * c26;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = -25593732 * c26;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ t0 = 91 * c26;
+ c16 += (t0 << 11) & LIMB_MASK;
+ c17 += t0 >> 17;
+ //reduce from position 25
+ t0 = -20472841 * c25;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -117141993 * c25;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 62411077 * c25;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 56915814 * c25;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -97532854 * c25;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -76509338 * c25;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 75510783 * c25;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 67962521 * c25;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = -25593732 * c25;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ t0 = 91 * c25;
+ c15 += (t0 << 11) & LIMB_MASK;
+ c16 += t0 >> 17;
+ //reduce from position 24
+ t0 = -20472841 * c24;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -117141993 * c24;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 62411077 * c24;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 56915814 * c24;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -97532854 * c24;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -76509338 * c24;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 75510783 * c24;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 67962521 * c24;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = -25593732 * c24;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ t0 = 91 * c24;
+ c14 += (t0 << 11) & LIMB_MASK;
+ c15 += t0 >> 17;
+ //reduce from position 23
+ t0 = -20472841 * c23;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -117141993 * c23;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 62411077 * c23;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 56915814 * c23;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -97532854 * c23;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -76509338 * c23;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 75510783 * c23;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 67962521 * c23;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = -25593732 * c23;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ t0 = 91 * c23;
+ c13 += (t0 << 11) & LIMB_MASK;
+ c14 += t0 >> 17;
+ //reduce from position 22
+ t0 = -20472841 * c22;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -117141993 * c22;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = 62411077 * c22;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 56915814 * c22;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -97532854 * c22;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -76509338 * c22;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 75510783 * c22;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 67962521 * c22;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = -25593732 * c22;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ t0 = 91 * c22;
+ c12 += (t0 << 11) & LIMB_MASK;
+ c13 += t0 >> 17;
+ //reduce from position 21
+ t0 = -20472841 * c21;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = -117141993 * c21;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = 62411077 * c21;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = 56915814 * c21;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -97532854 * c21;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = -76509338 * c21;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 75510783 * c21;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 67962521 * c21;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = -25593732 * c21;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ t0 = 91 * c21;
+ c11 += (t0 << 11) & LIMB_MASK;
+ c12 += t0 >> 17;
+ //reduce from position 20
+ t0 = -20472841 * c20;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = -117141993 * c20;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 62411077 * c20;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = 56915814 * c20;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -97532854 * c20;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = -76509338 * c20;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 75510783 * c20;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = 67962521 * c20;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = -25593732 * c20;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ t0 = 91 * c20;
+ c10 += (t0 << 11) & LIMB_MASK;
+ c11 += t0 >> 17;
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ c19 = 0;
+
+ carryReduce2(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce2(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+
+ carryReduce3(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36, c37);
+ }
+ void carryReduce3(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19, long c20, long c21, long c22, long c23, long c24, long c25, long c26, long c27, long c28, long c29, long c30, long c31, long c32, long c33, long c34, long c35, long c36, long c37) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ private void carryReduce(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18) {
+ long c19 = 0;
+ //carry from position 0
+ long t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+ //carry from position 18
+ t0 = (c18 + CARRY_ADD) >> 28;
+ c18 -= (t0 << 28);
+ c19 += t0;
+
+ carryReduce0(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19);
+ }
+ void carryReduce0(long[] r, long c0, long c1, long c2, long c3, long c4, long c5, long c6, long c7, long c8, long c9, long c10, long c11, long c12, long c13, long c14, long c15, long c16, long c17, long c18, long c19) {
+ long t0;
+
+ //reduce from position 19
+ t0 = -20472841 * c19;
+ c0 += (t0 << 11) & LIMB_MASK;
+ c1 += t0 >> 17;
+ t0 = -117141993 * c19;
+ c1 += (t0 << 11) & LIMB_MASK;
+ c2 += t0 >> 17;
+ t0 = 62411077 * c19;
+ c2 += (t0 << 11) & LIMB_MASK;
+ c3 += t0 >> 17;
+ t0 = 56915814 * c19;
+ c3 += (t0 << 11) & LIMB_MASK;
+ c4 += t0 >> 17;
+ t0 = -97532854 * c19;
+ c4 += (t0 << 11) & LIMB_MASK;
+ c5 += t0 >> 17;
+ t0 = -76509338 * c19;
+ c5 += (t0 << 11) & LIMB_MASK;
+ c6 += t0 >> 17;
+ t0 = 75510783 * c19;
+ c6 += (t0 << 11) & LIMB_MASK;
+ c7 += t0 >> 17;
+ t0 = 67962521 * c19;
+ c7 += (t0 << 11) & LIMB_MASK;
+ c8 += t0 >> 17;
+ t0 = -25593732 * c19;
+ c8 += (t0 << 11) & LIMB_MASK;
+ c9 += t0 >> 17;
+ t0 = 91 * c19;
+ c9 += (t0 << 11) & LIMB_MASK;
+ c10 += t0 >> 17;
+ //carry from position 0
+ t0 = (c0 + CARRY_ADD) >> 28;
+ c0 -= (t0 << 28);
+ c1 += t0;
+ //carry from position 1
+ t0 = (c1 + CARRY_ADD) >> 28;
+ c1 -= (t0 << 28);
+ c2 += t0;
+ //carry from position 2
+ t0 = (c2 + CARRY_ADD) >> 28;
+ c2 -= (t0 << 28);
+ c3 += t0;
+ //carry from position 3
+ t0 = (c3 + CARRY_ADD) >> 28;
+ c3 -= (t0 << 28);
+ c4 += t0;
+ //carry from position 4
+ t0 = (c4 + CARRY_ADD) >> 28;
+ c4 -= (t0 << 28);
+ c5 += t0;
+ //carry from position 5
+ t0 = (c5 + CARRY_ADD) >> 28;
+ c5 -= (t0 << 28);
+ c6 += t0;
+ //carry from position 6
+ t0 = (c6 + CARRY_ADD) >> 28;
+ c6 -= (t0 << 28);
+ c7 += t0;
+ //carry from position 7
+ t0 = (c7 + CARRY_ADD) >> 28;
+ c7 -= (t0 << 28);
+ c8 += t0;
+ //carry from position 8
+ t0 = (c8 + CARRY_ADD) >> 28;
+ c8 -= (t0 << 28);
+ c9 += t0;
+ //carry from position 9
+ t0 = (c9 + CARRY_ADD) >> 28;
+ c9 -= (t0 << 28);
+ c10 += t0;
+ //carry from position 10
+ t0 = (c10 + CARRY_ADD) >> 28;
+ c10 -= (t0 << 28);
+ c11 += t0;
+ //carry from position 11
+ t0 = (c11 + CARRY_ADD) >> 28;
+ c11 -= (t0 << 28);
+ c12 += t0;
+ //carry from position 12
+ t0 = (c12 + CARRY_ADD) >> 28;
+ c12 -= (t0 << 28);
+ c13 += t0;
+ //carry from position 13
+ t0 = (c13 + CARRY_ADD) >> 28;
+ c13 -= (t0 << 28);
+ c14 += t0;
+ //carry from position 14
+ t0 = (c14 + CARRY_ADD) >> 28;
+ c14 -= (t0 << 28);
+ c15 += t0;
+ //carry from position 15
+ t0 = (c15 + CARRY_ADD) >> 28;
+ c15 -= (t0 << 28);
+ c16 += t0;
+ //carry from position 16
+ t0 = (c16 + CARRY_ADD) >> 28;
+ c16 -= (t0 << 28);
+ c17 += t0;
+ //carry from position 17
+ t0 = (c17 + CARRY_ADD) >> 28;
+ c17 -= (t0 << 28);
+ c18 += t0;
+
+ r[0] = c0;
+ r[1] = c1;
+ r[2] = c2;
+ r[3] = c3;
+ r[4] = c4;
+ r[5] = c5;
+ r[6] = c6;
+ r[7] = c7;
+ r[8] = c8;
+ r[9] = c9;
+ r[10] = c10;
+ r[11] = c11;
+ r[12] = c12;
+ r[13] = c13;
+ r[14] = c14;
+ r[15] = c15;
+ r[16] = c16;
+ r[17] = c17;
+ r[18] = c18;
+ }
+ @Override
+ protected void mult(long[] a, long[] b, long[] r) {
+ long c0 = (a[0] * b[0]);
+ long c1 = (a[0] * b[1]) + (a[1] * b[0]);
+ long c2 = (a[0] * b[2]) + (a[1] * b[1]) + (a[2] * b[0]);
+ long c3 = (a[0] * b[3]) + (a[1] * b[2]) + (a[2] * b[1]) + (a[3] * b[0]);
+ long c4 = (a[0] * b[4]) + (a[1] * b[3]) + (a[2] * b[2]) + (a[3] * b[1]) + (a[4] * b[0]);
+ long c5 = (a[0] * b[5]) + (a[1] * b[4]) + (a[2] * b[3]) + (a[3] * b[2]) + (a[4] * b[1]) + (a[5] * b[0]);
+ long c6 = (a[0] * b[6]) + (a[1] * b[5]) + (a[2] * b[4]) + (a[3] * b[3]) + (a[4] * b[2]) + (a[5] * b[1]) + (a[6] * b[0]);
+ long c7 = (a[0] * b[7]) + (a[1] * b[6]) + (a[2] * b[5]) + (a[3] * b[4]) + (a[4] * b[3]) + (a[5] * b[2]) + (a[6] * b[1]) + (a[7] * b[0]);
+ long c8 = (a[0] * b[8]) + (a[1] * b[7]) + (a[2] * b[6]) + (a[3] * b[5]) + (a[4] * b[4]) + (a[5] * b[3]) + (a[6] * b[2]) + (a[7] * b[1]) + (a[8] * b[0]);
+ long c9 = (a[0] * b[9]) + (a[1] * b[8]) + (a[2] * b[7]) + (a[3] * b[6]) + (a[4] * b[5]) + (a[5] * b[4]) + (a[6] * b[3]) + (a[7] * b[2]) + (a[8] * b[1]) + (a[9] * b[0]);
+ long c10 = (a[0] * b[10]) + (a[1] * b[9]) + (a[2] * b[8]) + (a[3] * b[7]) + (a[4] * b[6]) + (a[5] * b[5]) + (a[6] * b[4]) + (a[7] * b[3]) + (a[8] * b[2]) + (a[9] * b[1]) + (a[10] * b[0]);
+ long c11 = (a[0] * b[11]) + (a[1] * b[10]) + (a[2] * b[9]) + (a[3] * b[8]) + (a[4] * b[7]) + (a[5] * b[6]) + (a[6] * b[5]) + (a[7] * b[4]) + (a[8] * b[3]) + (a[9] * b[2]) + (a[10] * b[1]) + (a[11] * b[0]);
+ long c12 = (a[0] * b[12]) + (a[1] * b[11]) + (a[2] * b[10]) + (a[3] * b[9]) + (a[4] * b[8]) + (a[5] * b[7]) + (a[6] * b[6]) + (a[7] * b[5]) + (a[8] * b[4]) + (a[9] * b[3]) + (a[10] * b[2]) + (a[11] * b[1]) + (a[12] * b[0]);
+ long c13 = (a[0] * b[13]) + (a[1] * b[12]) + (a[2] * b[11]) + (a[3] * b[10]) + (a[4] * b[9]) + (a[5] * b[8]) + (a[6] * b[7]) + (a[7] * b[6]) + (a[8] * b[5]) + (a[9] * b[4]) + (a[10] * b[3]) + (a[11] * b[2]) + (a[12] * b[1]) + (a[13] * b[0]);
+ long c14 = (a[0] * b[14]) + (a[1] * b[13]) + (a[2] * b[12]) + (a[3] * b[11]) + (a[4] * b[10]) + (a[5] * b[9]) + (a[6] * b[8]) + (a[7] * b[7]) + (a[8] * b[6]) + (a[9] * b[5]) + (a[10] * b[4]) + (a[11] * b[3]) + (a[12] * b[2]) + (a[13] * b[1]) + (a[14] * b[0]);
+ long c15 = (a[0] * b[15]) + (a[1] * b[14]) + (a[2] * b[13]) + (a[3] * b[12]) + (a[4] * b[11]) + (a[5] * b[10]) + (a[6] * b[9]) + (a[7] * b[8]) + (a[8] * b[7]) + (a[9] * b[6]) + (a[10] * b[5]) + (a[11] * b[4]) + (a[12] * b[3]) + (a[13] * b[2]) + (a[14] * b[1]) + (a[15] * b[0]);
+ long c16 = (a[0] * b[16]) + (a[1] * b[15]) + (a[2] * b[14]) + (a[3] * b[13]) + (a[4] * b[12]) + (a[5] * b[11]) + (a[6] * b[10]) + (a[7] * b[9]) + (a[8] * b[8]) + (a[9] * b[7]) + (a[10] * b[6]) + (a[11] * b[5]) + (a[12] * b[4]) + (a[13] * b[3]) + (a[14] * b[2]) + (a[15] * b[1]) + (a[16] * b[0]);
+ long c17 = (a[0] * b[17]) + (a[1] * b[16]) + (a[2] * b[15]) + (a[3] * b[14]) + (a[4] * b[13]) + (a[5] * b[12]) + (a[6] * b[11]) + (a[7] * b[10]) + (a[8] * b[9]) + (a[9] * b[8]) + (a[10] * b[7]) + (a[11] * b[6]) + (a[12] * b[5]) + (a[13] * b[4]) + (a[14] * b[3]) + (a[15] * b[2]) + (a[16] * b[1]) + (a[17] * b[0]);
+ long c18 = (a[0] * b[18]) + (a[1] * b[17]) + (a[2] * b[16]) + (a[3] * b[15]) + (a[4] * b[14]) + (a[5] * b[13]) + (a[6] * b[12]) + (a[7] * b[11]) + (a[8] * b[10]) + (a[9] * b[9]) + (a[10] * b[8]) + (a[11] * b[7]) + (a[12] * b[6]) + (a[13] * b[5]) + (a[14] * b[4]) + (a[15] * b[3]) + (a[16] * b[2]) + (a[17] * b[1]) + (a[18] * b[0]);
+ long c19 = (a[1] * b[18]) + (a[2] * b[17]) + (a[3] * b[16]) + (a[4] * b[15]) + (a[5] * b[14]) + (a[6] * b[13]) + (a[7] * b[12]) + (a[8] * b[11]) + (a[9] * b[10]) + (a[10] * b[9]) + (a[11] * b[8]) + (a[12] * b[7]) + (a[13] * b[6]) + (a[14] * b[5]) + (a[15] * b[4]) + (a[16] * b[3]) + (a[17] * b[2]) + (a[18] * b[1]);
+ long c20 = (a[2] * b[18]) + (a[3] * b[17]) + (a[4] * b[16]) + (a[5] * b[15]) + (a[6] * b[14]) + (a[7] * b[13]) + (a[8] * b[12]) + (a[9] * b[11]) + (a[10] * b[10]) + (a[11] * b[9]) + (a[12] * b[8]) + (a[13] * b[7]) + (a[14] * b[6]) + (a[15] * b[5]) + (a[16] * b[4]) + (a[17] * b[3]) + (a[18] * b[2]);
+ long c21 = (a[3] * b[18]) + (a[4] * b[17]) + (a[5] * b[16]) + (a[6] * b[15]) + (a[7] * b[14]) + (a[8] * b[13]) + (a[9] * b[12]) + (a[10] * b[11]) + (a[11] * b[10]) + (a[12] * b[9]) + (a[13] * b[8]) + (a[14] * b[7]) + (a[15] * b[6]) + (a[16] * b[5]) + (a[17] * b[4]) + (a[18] * b[3]);
+ long c22 = (a[4] * b[18]) + (a[5] * b[17]) + (a[6] * b[16]) + (a[7] * b[15]) + (a[8] * b[14]) + (a[9] * b[13]) + (a[10] * b[12]) + (a[11] * b[11]) + (a[12] * b[10]) + (a[13] * b[9]) + (a[14] * b[8]) + (a[15] * b[7]) + (a[16] * b[6]) + (a[17] * b[5]) + (a[18] * b[4]);
+ long c23 = (a[5] * b[18]) + (a[6] * b[17]) + (a[7] * b[16]) + (a[8] * b[15]) + (a[9] * b[14]) + (a[10] * b[13]) + (a[11] * b[12]) + (a[12] * b[11]) + (a[13] * b[10]) + (a[14] * b[9]) + (a[15] * b[8]) + (a[16] * b[7]) + (a[17] * b[6]) + (a[18] * b[5]);
+ long c24 = (a[6] * b[18]) + (a[7] * b[17]) + (a[8] * b[16]) + (a[9] * b[15]) + (a[10] * b[14]) + (a[11] * b[13]) + (a[12] * b[12]) + (a[13] * b[11]) + (a[14] * b[10]) + (a[15] * b[9]) + (a[16] * b[8]) + (a[17] * b[7]) + (a[18] * b[6]);
+ long c25 = (a[7] * b[18]) + (a[8] * b[17]) + (a[9] * b[16]) + (a[10] * b[15]) + (a[11] * b[14]) + (a[12] * b[13]) + (a[13] * b[12]) + (a[14] * b[11]) + (a[15] * b[10]) + (a[16] * b[9]) + (a[17] * b[8]) + (a[18] * b[7]);
+ long c26 = (a[8] * b[18]) + (a[9] * b[17]) + (a[10] * b[16]) + (a[11] * b[15]) + (a[12] * b[14]) + (a[13] * b[13]) + (a[14] * b[12]) + (a[15] * b[11]) + (a[16] * b[10]) + (a[17] * b[9]) + (a[18] * b[8]);
+ long c27 = (a[9] * b[18]) + (a[10] * b[17]) + (a[11] * b[16]) + (a[12] * b[15]) + (a[13] * b[14]) + (a[14] * b[13]) + (a[15] * b[12]) + (a[16] * b[11]) + (a[17] * b[10]) + (a[18] * b[9]);
+ long c28 = (a[10] * b[18]) + (a[11] * b[17]) + (a[12] * b[16]) + (a[13] * b[15]) + (a[14] * b[14]) + (a[15] * b[13]) + (a[16] * b[12]) + (a[17] * b[11]) + (a[18] * b[10]);
+ long c29 = (a[11] * b[18]) + (a[12] * b[17]) + (a[13] * b[16]) + (a[14] * b[15]) + (a[15] * b[14]) + (a[16] * b[13]) + (a[17] * b[12]) + (a[18] * b[11]);
+ long c30 = (a[12] * b[18]) + (a[13] * b[17]) + (a[14] * b[16]) + (a[15] * b[15]) + (a[16] * b[14]) + (a[17] * b[13]) + (a[18] * b[12]);
+ long c31 = (a[13] * b[18]) + (a[14] * b[17]) + (a[15] * b[16]) + (a[16] * b[15]) + (a[17] * b[14]) + (a[18] * b[13]);
+ long c32 = (a[14] * b[18]) + (a[15] * b[17]) + (a[16] * b[16]) + (a[17] * b[15]) + (a[18] * b[14]);
+ long c33 = (a[15] * b[18]) + (a[16] * b[17]) + (a[17] * b[16]) + (a[18] * b[15]);
+ long c34 = (a[16] * b[18]) + (a[17] * b[17]) + (a[18] * b[16]);
+ long c35 = (a[17] * b[18]) + (a[18] * b[17]);
+ long c36 = (a[18] * b[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+ @Override
+ protected void reduce(long[] a) {
+ carryReduce(a, a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], a[16], a[17], a[18]);
+ }
+ @Override
+ protected void square(long[] a, long[] r) {
+ long c0 = (a[0] * a[0]);
+ long c1 = 2 * ((a[0] * a[1]));
+ long c2 = 2 * ((a[0] * a[2])) + (a[1] * a[1]);
+ long c3 = 2 * ((a[0] * a[3]) + (a[1] * a[2]));
+ long c4 = 2 * ((a[0] * a[4]) + (a[1] * a[3])) + (a[2] * a[2]);
+ long c5 = 2 * ((a[0] * a[5]) + (a[1] * a[4]) + (a[2] * a[3]));
+ long c6 = 2 * ((a[0] * a[6]) + (a[1] * a[5]) + (a[2] * a[4])) + (a[3] * a[3]);
+ long c7 = 2 * ((a[0] * a[7]) + (a[1] * a[6]) + (a[2] * a[5]) + (a[3] * a[4]));
+ long c8 = 2 * ((a[0] * a[8]) + (a[1] * a[7]) + (a[2] * a[6]) + (a[3] * a[5])) + (a[4] * a[4]);
+ long c9 = 2 * ((a[0] * a[9]) + (a[1] * a[8]) + (a[2] * a[7]) + (a[3] * a[6]) + (a[4] * a[5]));
+ long c10 = 2 * ((a[0] * a[10]) + (a[1] * a[9]) + (a[2] * a[8]) + (a[3] * a[7]) + (a[4] * a[6])) + (a[5] * a[5]);
+ long c11 = 2 * ((a[0] * a[11]) + (a[1] * a[10]) + (a[2] * a[9]) + (a[3] * a[8]) + (a[4] * a[7]) + (a[5] * a[6]));
+ long c12 = 2 * ((a[0] * a[12]) + (a[1] * a[11]) + (a[2] * a[10]) + (a[3] * a[9]) + (a[4] * a[8]) + (a[5] * a[7])) + (a[6] * a[6]);
+ long c13 = 2 * ((a[0] * a[13]) + (a[1] * a[12]) + (a[2] * a[11]) + (a[3] * a[10]) + (a[4] * a[9]) + (a[5] * a[8]) + (a[6] * a[7]));
+ long c14 = 2 * ((a[0] * a[14]) + (a[1] * a[13]) + (a[2] * a[12]) + (a[3] * a[11]) + (a[4] * a[10]) + (a[5] * a[9]) + (a[6] * a[8])) + (a[7] * a[7]);
+ long c15 = 2 * ((a[0] * a[15]) + (a[1] * a[14]) + (a[2] * a[13]) + (a[3] * a[12]) + (a[4] * a[11]) + (a[5] * a[10]) + (a[6] * a[9]) + (a[7] * a[8]));
+ long c16 = 2 * ((a[0] * a[16]) + (a[1] * a[15]) + (a[2] * a[14]) + (a[3] * a[13]) + (a[4] * a[12]) + (a[5] * a[11]) + (a[6] * a[10]) + (a[7] * a[9])) + (a[8] * a[8]);
+ long c17 = 2 * ((a[0] * a[17]) + (a[1] * a[16]) + (a[2] * a[15]) + (a[3] * a[14]) + (a[4] * a[13]) + (a[5] * a[12]) + (a[6] * a[11]) + (a[7] * a[10]) + (a[8] * a[9]));
+ long c18 = 2 * ((a[0] * a[18]) + (a[1] * a[17]) + (a[2] * a[16]) + (a[3] * a[15]) + (a[4] * a[14]) + (a[5] * a[13]) + (a[6] * a[12]) + (a[7] * a[11]) + (a[8] * a[10])) + (a[9] * a[9]);
+ long c19 = 2 * ((a[1] * a[18]) + (a[2] * a[17]) + (a[3] * a[16]) + (a[4] * a[15]) + (a[5] * a[14]) + (a[6] * a[13]) + (a[7] * a[12]) + (a[8] * a[11]) + (a[9] * a[10]));
+ long c20 = 2 * ((a[2] * a[18]) + (a[3] * a[17]) + (a[4] * a[16]) + (a[5] * a[15]) + (a[6] * a[14]) + (a[7] * a[13]) + (a[8] * a[12]) + (a[9] * a[11])) + (a[10] * a[10]);
+ long c21 = 2 * ((a[3] * a[18]) + (a[4] * a[17]) + (a[5] * a[16]) + (a[6] * a[15]) + (a[7] * a[14]) + (a[8] * a[13]) + (a[9] * a[12]) + (a[10] * a[11]));
+ long c22 = 2 * ((a[4] * a[18]) + (a[5] * a[17]) + (a[6] * a[16]) + (a[7] * a[15]) + (a[8] * a[14]) + (a[9] * a[13]) + (a[10] * a[12])) + (a[11] * a[11]);
+ long c23 = 2 * ((a[5] * a[18]) + (a[6] * a[17]) + (a[7] * a[16]) + (a[8] * a[15]) + (a[9] * a[14]) + (a[10] * a[13]) + (a[11] * a[12]));
+ long c24 = 2 * ((a[6] * a[18]) + (a[7] * a[17]) + (a[8] * a[16]) + (a[9] * a[15]) + (a[10] * a[14]) + (a[11] * a[13])) + (a[12] * a[12]);
+ long c25 = 2 * ((a[7] * a[18]) + (a[8] * a[17]) + (a[9] * a[16]) + (a[10] * a[15]) + (a[11] * a[14]) + (a[12] * a[13]));
+ long c26 = 2 * ((a[8] * a[18]) + (a[9] * a[17]) + (a[10] * a[16]) + (a[11] * a[15]) + (a[12] * a[14])) + (a[13] * a[13]);
+ long c27 = 2 * ((a[9] * a[18]) + (a[10] * a[17]) + (a[11] * a[16]) + (a[12] * a[15]) + (a[13] * a[14]));
+ long c28 = 2 * ((a[10] * a[18]) + (a[11] * a[17]) + (a[12] * a[16]) + (a[13] * a[15])) + (a[14] * a[14]);
+ long c29 = 2 * ((a[11] * a[18]) + (a[12] * a[17]) + (a[13] * a[16]) + (a[14] * a[15]));
+ long c30 = 2 * ((a[12] * a[18]) + (a[13] * a[17]) + (a[14] * a[16])) + (a[15] * a[15]);
+ long c31 = 2 * ((a[13] * a[18]) + (a[14] * a[17]) + (a[15] * a[16]));
+ long c32 = 2 * ((a[14] * a[18]) + (a[15] * a[17])) + (a[16] * a[16]);
+ long c33 = 2 * ((a[15] * a[18]) + (a[16] * a[17]));
+ long c34 = 2 * ((a[16] * a[18])) + (a[17] * a[17]);
+ long c35 = 2 * ((a[17] * a[18]));
+ long c36 = (a[18] * a[18]);
+
+ carryReduce(r, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35, c36);
+ }
+}
+
diff --git a/src/share/classes/sun/security/util/math/intpoly/header.txt b/src/share/classes/sun/security/util/math/intpoly/header.txt
new file mode 100644
index 0000000000..f76bb8a50b
--- /dev/null
+++ b/src/share/classes/sun/security/util/math/intpoly/header.txt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is generated by FieldGen.jsh. Do not modify it directly.
+ */
diff --git a/src/share/classes/sun/security/validator/KeyStores.java b/src/share/classes/sun/security/validator/TrustStoreUtil.java
index 8a33cd315a..9d610ce62e 100644
--- a/src/share/classes/sun/security/validator/KeyStores.java
+++ b/src/share/classes/sun/security/validator/TrustStoreUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, 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,76 +25,33 @@
package sun.security.validator;
-import java.io.*;
-import java.util.*;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.Enumeration;
-import java.security.*;
-import java.security.cert.*;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.X509Certificate;
import java.security.cert.Certificate;
-import sun.security.action.*;
-
/**
- * Collection of static utility methods related to KeyStores.
+ * Collection of static utility methods related to trust anchor KeyStores.
*
* @author Andreas Sterbenz
*/
-public class KeyStores {
+public final class TrustStoreUtil {
- private KeyStores() {
+ private TrustStoreUtil() {
// empty
}
- // in the future, all accesses to the system cacerts keystore should
- // go through this class. but not right now.
-/*
- private final static String javaHome =
- (String)AccessController.doPrivileged(new GetPropertyAction("java.home"));
-
- private final static char SEP = File.separatorChar;
-
- private static KeyStore caCerts;
-
- private static KeyStore getKeyStore(String type, String name,
- char[] password) throws IOException {
- if (type == null) {
- type = "JKS";
- }
- try {
- KeyStore ks = KeyStore.getInstance(type);
- FileInputStream in = (FileInputStream)AccessController.doPrivileged
- (new OpenFileInputStreamAction(name));
- ks.load(in, password);
- return ks;
- } catch (GeneralSecurityException e) {
- // XXX
- throw new IOException();
- } catch (PrivilegedActionException e) {
- throw (IOException)e.getCause();
- }
- }
-
- /**
- * Return a KeyStore with the contents of the lib/security/cacerts file.
- * The file is only opened once per JVM invocation and the contents
- * cached subsequently.
- *
- public synchronized static KeyStore getCaCerts() throws IOException {
- if (caCerts != null) {
- return caCerts;
- }
- String name = javaHome + SEP + "lib" + SEP + "security" + SEP + "cacerts";
- caCerts = getKeyStore(null, name, null);
- return caCerts;
- }
-*/
-
/**
- * Return a Set with all trusted X509Certificates contained in
- * this KeyStore.
+ * Return an unmodifiable Set with all trusted X509Certificates contained
+ * in the specified KeyStore.
*/
public static Set<X509Certificate> getTrustedCerts(KeyStore ks) {
- Set<X509Certificate> set = new HashSet<X509Certificate>();
+ Set<X509Certificate> set = new HashSet<>();
try {
for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
String alias = e.nextElement();
@@ -113,8 +70,10 @@ public class KeyStores {
}
} catch (KeyStoreException e) {
// ignore
+ //
+ // This should be rare, but better to log this in the future.
}
- return set;
- }
+ return Collections.unmodifiableSet(set);
+ }
}
diff --git a/src/share/classes/sun/security/validator/Validator.java b/src/share/classes/sun/security/validator/Validator.java
index c96454d1ab..44d06ceb2a 100644
--- a/src/share/classes/sun/security/validator/Validator.java
+++ b/src/share/classes/sun/security/validator/Validator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -166,7 +166,7 @@ public abstract class Validator {
*/
public static Validator getInstance(String type, String variant,
KeyStore ks) {
- return getInstance(type, variant, KeyStores.getTrustedCerts(ks));
+ return getInstance(type, variant, TrustStoreUtil.getTrustedCerts(ks));
}
/**
diff --git a/src/share/classes/sun/swing/SwingUtilities2.java b/src/share/classes/sun/swing/SwingUtilities2.java
index baa8b8f0e4..adefb301cc 100644
--- a/src/share/classes/sun/swing/SwingUtilities2.java
+++ b/src/share/classes/sun/swing/SwingUtilities2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -549,11 +549,15 @@ public class SwingUtilities2 {
String trimmedText = trimTrailingSpaces(text);
if (!trimmedText.isEmpty()) {
float screenWidth = (float) g2d.getFont().getStringBounds
- (trimmedText, DEFAULT_FRC).getWidth();
+ (trimmedText, getFontRenderContext(c)).getWidth();
TextLayout layout = createTextLayout(c, text, g2d.getFont(),
g2d.getFontRenderContext());
- layout = layout.getJustifiedLayout(screenWidth);
+ // If text fits the screenWidth, then do not need to justify
+ if (SwingUtilities2.stringWidth(c, g2d.getFontMetrics(),
+ trimmedText) > screenWidth) {
+ layout = layout.getJustifiedLayout(screenWidth);
+ }
/* Use alternate print color if specified */
Color col = g2d.getColor();
if (col instanceof PrintColorUIResource) {
@@ -678,8 +682,12 @@ public class SwingUtilities2 {
g2d.getFontRenderContext());
if (isPrinting) {
float screenWidth = (float)g2d.getFont().
- getStringBounds(text, DEFAULT_FRC).getWidth();
- layout = layout.getJustifiedLayout(screenWidth);
+ getStringBounds(text, getFontRenderContext(c)).getWidth();
+ // If text fits the screenWidth, then do not need to justify
+ if (SwingUtilities2.stringWidth(c, g2d.getFontMetrics(),
+ text) > screenWidth) {
+ layout = layout.getJustifiedLayout(screenWidth);
+ }
}
TextHitInfo leading =
TextHitInfo.leading(underlinedIndex);
@@ -863,7 +871,11 @@ public class SwingUtilities2 {
if (!trimmedText.isEmpty()) {
float screenWidth = (float)g2d.getFont().
getStringBounds(trimmedText, frc).getWidth();
- layout = layout.getJustifiedLayout(screenWidth);
+ // If text fits the screenWidth, then do not need to justify
+ if (SwingUtilities2.stringWidth(c, g2d.getFontMetrics(),
+ trimmedText) > screenWidth) {
+ layout = layout.getJustifiedLayout(screenWidth);
+ }
/* Use alternate print color if specified */
Color col = g2d.getColor();
diff --git a/src/share/classes/sun/text/resources/ar/FormatData_ar.java b/src/share/classes/sun/text/resources/ar/FormatData_ar.java
index acb5cb9c40..38ca522070 100644
--- a/src/share/classes/sun/text/resources/ar/FormatData_ar.java
+++ b/src/share/classes/sun/text/resources/ar/FormatData_ar.java
@@ -212,6 +212,7 @@ public class FormatData_ar extends ParallelListResourceBundle {
"\u062a\u064a\u0634\u0648",
"\u0634\u0648\u0648\u0627",
"\u0647\u064a\u0633\u064a",
+ "\u0631\u064a\u0648\u0627",
}
},
{ "japanese.short.Eras",
@@ -221,6 +222,7 @@ public class FormatData_ar extends ParallelListResourceBundle {
"\u062a\u064a\u0634\u0648",
"\u0634\u0648\u0648\u0627",
"\u0647\u064a\u0633\u064a",
+ "\u0631\u064a\u0648\u0627",
}
},
{ "buddhist.Eras",
diff --git a/src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java b/src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java
index 9f261e6e1e..c335acfe71 100644
--- a/src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java
+++ b/src/share/classes/sun/text/resources/ar/JavaTimeSupplementary_ar.java
@@ -229,6 +229,7 @@ public class JavaTimeSupplementary_ar extends OpenListResourceBundle {
"\u062a\u064a\u0634\u0648",
"\u0634\u0648\u0648\u0627",
"\u0647\u064a\u0633\u064a",
+ "\u0631\u064a\u0648\u0627",
}
},
{ "java.time.japanese.short.Eras",
@@ -238,6 +239,7 @@ public class JavaTimeSupplementary_ar extends OpenListResourceBundle {
"\u062a\u064a\u0634\u0648",
"\u0634\u0648\u0648\u0627",
"\u0647\u064a\u0633\u064a",
+ "\u0631\u064a\u0648\u0627",
}
},
{ "java.time.long.Eras",
diff --git a/src/share/classes/sun/text/resources/es/FormatData_es_PE.java b/src/share/classes/sun/text/resources/es/FormatData_es_PE.java
index afa72f032e..310d4980e3 100644
--- a/src/share/classes/sun/text/resources/es/FormatData_es_PE.java
+++ b/src/share/classes/sun/text/resources/es/FormatData_es_PE.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -63,6 +63,21 @@ public class FormatData_es_PE extends ParallelListResourceBundle {
"hh:mm a", // short time pattern
}
},
+ { "NumberElements",
+ new String[] {
+ ".", // decimal separator
+ ",", // group (thousands) separator
+ ";", // list separator
+ "%", // percent sign
+ "0", // native 0 digit
+ "#", // pattern digit
+ "-", // minus sign
+ "E", // exponential
+ "\u2030", // per mille
+ "\u221e", // infinity
+ "\ufffd" // NaN
+ }
+ },
{ "DatePatterns",
new String[] {
"EEEE d' de 'MMMM' de 'yyyy", // full date pattern
diff --git a/src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java b/src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java
index e59acabd33..e2bf2aee6f 100644
--- a/src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java
+++ b/src/share/classes/sun/text/resources/hi/JavaTimeSupplementary_hi_IN.java
@@ -145,6 +145,7 @@ public class JavaTimeSupplementary_hi_IN extends OpenListResourceBundle {
"\u0924\u093e\u0908\u0936\u094b",
"\u0936\u094b\u0935\u093e",
"\u0939\u0947\u0908\u0938\u0947\u0908",
+ "\u0930\u0947\u0907\u0935\u093e",
}
},
{ "java.time.japanese.short.Eras",
@@ -154,6 +155,7 @@ public class JavaTimeSupplementary_hi_IN extends OpenListResourceBundle {
"\u0924\u093e\u0908\u0936\u094b",
"\u0936\u094b\u0935\u093e",
"\u0939\u0947\u0908\u0938\u0947\u0908",
+ "\u0930\u0947\u0907\u0935\u093e",
}
},
{ "java.time.short.Eras",
diff --git a/src/share/classes/sun/text/resources/ko/FormatData_ko.java b/src/share/classes/sun/text/resources/ko/FormatData_ko.java
index 4483ad2e94..9eb1b4260f 100644
--- a/src/share/classes/sun/text/resources/ko/FormatData_ko.java
+++ b/src/share/classes/sun/text/resources/ko/FormatData_ko.java
@@ -192,6 +192,7 @@ public class FormatData_ko extends ParallelListResourceBundle {
"\ub2e4\uc774\uc1fc",
"\uc1fc\uc640",
"\ud5e4\uc774\uc138\uc774",
+ "\ub808\uc774\uc640",
}
},
{ "AmPmMarkers",
diff --git a/src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java b/src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java
index 7435b6d721..87a08683a3 100644
--- a/src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java
+++ b/src/share/classes/sun/text/resources/ko/JavaTimeSupplementary_ko.java
@@ -158,6 +158,7 @@ public class JavaTimeSupplementary_ko extends OpenListResourceBundle {
"\ub2e4\uc774\uc1fc",
"\uc1fc\uc640",
"\ud5e4\uc774\uc138\uc774",
+ "\ub808\uc774\uc640",
}
},
{ "java.time.japanese.short.Eras",
@@ -167,6 +168,7 @@ public class JavaTimeSupplementary_ko extends OpenListResourceBundle {
"\ub2e4\uc774\uc1fc",
"\uc1fc\uc640",
"\ud5e4\uc774\uc138\uc774",
+ "\ub808\uc774\uc640",
}
},
{ "java.time.long.Eras",
diff --git a/src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java b/src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java
index 54b74f0f0c..4c017787b0 100644
--- a/src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java
+++ b/src/share/classes/sun/text/resources/ru/JavaTimeSupplementary_ru.java
@@ -219,6 +219,7 @@ public class JavaTimeSupplementary_ru extends OpenListResourceBundle {
"\u042d\u043f\u043e\u0445\u0430 \u0422\u0430\u0439\u0441\u044c\u043e",
"\u0421\u044c\u043e\u0432\u0430",
"\u042d\u043f\u043e\u0445\u0430 \u0425\u044d\u0439\u0441\u044d\u0439",
+ "\u0420\u044d\u0439\u0432\u0430",
}
},
{ "java.time.japanese.short.Eras",
@@ -228,6 +229,7 @@ public class JavaTimeSupplementary_ru extends OpenListResourceBundle {
"\u042d\u043f\u043e\u0445\u0430 \u0422\u0430\u0439\u0441\u044c\u043e",
"\u0421\u044c\u043e\u0432\u0430",
"\u042d\u043f\u043e\u0445\u0430 \u0425\u044d\u0439\u0441\u044d\u0439",
+ "\u0420\u044d\u0439\u0432\u0430",
}
},
{ "java.time.long.Eras",
diff --git a/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java b/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java
index c25a26bab0..1b6fe9247a 100644
--- a/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java
+++ b/src/share/classes/sun/text/resources/sr/JavaTimeSupplementary_sr.java
@@ -179,6 +179,7 @@ public class JavaTimeSupplementary_sr extends OpenListResourceBundle {
"\u0422\u0430\u0438\u0448\u043e",
"\u0428\u043e\u0432\u0430",
"\u0425\u0430\u0438\u0441\u0435\u0438",
+ "\u0420\u0435\u0438\u0432\u0430",
}
},
{ "java.time.japanese.short.Eras",
@@ -188,6 +189,7 @@ public class JavaTimeSupplementary_sr extends OpenListResourceBundle {
"\u0422\u0430\u0438\u0448\u043e",
"\u0428\u043e\u0432\u0430",
"\u0425\u0430\u0438\u0441\u0435\u0438",
+ "\u0420\u0435\u0438\u0432\u0430",
}
},
{ "java.time.long.Eras",
diff --git a/src/share/classes/sun/text/resources/th/FormatData_th.java b/src/share/classes/sun/text/resources/th/FormatData_th.java
index 15c679a0d9..5ef88b58c2 100644
--- a/src/share/classes/sun/text/resources/th/FormatData_th.java
+++ b/src/share/classes/sun/text/resources/th/FormatData_th.java
@@ -245,6 +245,7 @@ public class FormatData_th extends ParallelListResourceBundle {
"\u0e17\u0e30\u0e2d\u0e34\u0e42\u0e0a",
"\u0e42\u0e0a\u0e27\u0e30",
"\u0e40\u0e2e\u0e40\u0e0b",
+ "\u0e40\u0e23\u0e27\u0e30",
}
},
{ "japanese.short.Eras",
@@ -254,6 +255,7 @@ public class FormatData_th extends ParallelListResourceBundle {
"\u0e17",
"\u0e0a",
"\u0e2e",
+ "R",
}
},
{ "buddhist.TimePatterns",
diff --git a/src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java b/src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java
index b0f4bbcae7..71b3b5ffaf 100644
--- a/src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java
+++ b/src/share/classes/sun/text/resources/th/JavaTimeSupplementary_th.java
@@ -199,6 +199,7 @@ public class JavaTimeSupplementary_th extends OpenListResourceBundle {
"\u0e17\u0e30\u0e2d\u0e34\u0e42\u0e0a",
"\u0e42\u0e0a\u0e27\u0e30",
"\u0e40\u0e2e\u0e40\u0e0b",
+ "\u0e40\u0e23\u0e27\u0e30",
}
},
{ "java.time.japanese.short.Eras",
@@ -208,6 +209,7 @@ public class JavaTimeSupplementary_th extends OpenListResourceBundle {
"\u0e17\u0e30\u0e2d\u0e34\u0e42\u0e0a",
"\u0e42\u0e0a\u0e27\u0e30",
"\u0e40\u0e2e\u0e40\u0e0b",
+ "\u0e40\u0e23\u0e27\u0e30",
}
},
{ "java.time.long.Eras",
diff --git a/src/share/classes/sun/text/resources/zh/FormatData_zh.java b/src/share/classes/sun/text/resources/zh/FormatData_zh.java
index 1f8f7cb31f..ef43c449ef 100644
--- a/src/share/classes/sun/text/resources/zh/FormatData_zh.java
+++ b/src/share/classes/sun/text/resources/zh/FormatData_zh.java
@@ -282,6 +282,7 @@ public class FormatData_zh extends ParallelListResourceBundle {
"\u5927\u6b63",
"\u662d\u548c",
"\u5e73\u6210",
+ "\u4ee4\u548c",
}
},
{ "TimePatterns",
diff --git a/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java b/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java
index e5f44fd71c..00cb127a32 100644
--- a/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java
+++ b/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh.java
@@ -186,6 +186,7 @@ public class JavaTimeSupplementary_zh extends OpenListResourceBundle {
"\u5927\u6b63",
"\u662d\u548c",
"\u5e73\u6210",
+ "\u4ee4\u548c",
}
},
{ "java.time.japanese.short.Eras",
@@ -195,6 +196,7 @@ public class JavaTimeSupplementary_zh extends OpenListResourceBundle {
"\u5927\u6b63",
"\u662d\u548c",
"\u5e73\u6210",
+ "\u4ee4\u548c",
}
},
{ "java.time.roc.DatePatterns",
diff --git a/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java b/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java
index 7359b8eeaf..6e61ca71d9 100644
--- a/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java
+++ b/src/share/classes/sun/text/resources/zh/JavaTimeSupplementary_zh_TW.java
@@ -175,6 +175,7 @@ public class JavaTimeSupplementary_zh_TW extends OpenListResourceBundle {
"\u5927\u6b63",
"\u662d\u548c",
"\u5e73\u6210",
+ "\u4ee4\u548c",
}
},
{ "java.time.japanese.short.Eras",
@@ -184,6 +185,7 @@ public class JavaTimeSupplementary_zh_TW extends OpenListResourceBundle {
"\u5927\u6b63",
"\u662d\u548c",
"\u5e73\u6210",
+ "\u4ee4\u548c",
}
},
{ "java.time.roc.DatePatterns",
diff --git a/src/share/classes/sun/util/calendar/ZoneInfoFile.java b/src/share/classes/sun/util/calendar/ZoneInfoFile.java
index 61efb543d5..a54abaeee9 100644
--- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java
+++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -609,8 +609,6 @@ public final class ZoneInfoFile {
dstSavings = (startRule.offsetAfter - startRule.offsetBefore) * 1000;
// Note: known mismatching -> Asia/Amman
- // Asia/Gaza
- // Asia/Hebron
// ZoneInfo : startDayOfWeek=5 <= Thursday
// startTime=86400000 <= 24 hours
// This: startDayOfWeek=6
@@ -619,18 +617,14 @@ public final class ZoneInfoFile {
// its endDayOfWeek and endTime
// Below is the workarounds, it probably slows down everyone a little
if (params[2] == 6 && params[3] == 0 &&
- (zoneId.equals("Asia/Amman") ||
- zoneId.equals("Asia/Gaza") ||
- zoneId.equals("Asia/Hebron"))) {
+ (zoneId.equals("Asia/Amman"))) {
params[2] = 5;
params[3] = 86400000;
}
// Additional check for startDayOfWeek=6 and starTime=86400000
- // is needed for Asia/Amman; Asia/Gasa and Asia/Hebron
+ // is needed for Asia/Amman;
if (params[2] == 7 && params[3] == 0 &&
- (zoneId.equals("Asia/Amman") ||
- zoneId.equals("Asia/Gaza") ||
- zoneId.equals("Asia/Hebron"))) {
+ (zoneId.equals("Asia/Amman"))) {
params[2] = 6; // Friday
params[3] = 86400000; // 24h
}
diff --git a/src/share/classes/sun/util/locale/LocaleEquivalentMaps.java b/src/share/classes/sun/util/locale/LocaleEquivalentMaps.java
deleted file mode 100644
index 64638d0391..0000000000
--- a/src/share/classes/sun/util/locale/LocaleEquivalentMaps.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.util.locale;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Locale equivalent map for BCP47 Locale matching
- */
-final class LocaleEquivalentMaps {
-
- static final Map<String, String> singleEquivMap;
- static final Map<String, String[]> multiEquivsMap;
- static final Map<String, String> regionVariantEquivMap;
-
- static {
- singleEquivMap = new HashMap<>();
- multiEquivsMap = new HashMap<>();
- regionVariantEquivMap = new HashMap<>();
-
- // This is an auto-generated file and should not be manually edited.
- // LSR Revision: 2013-09-23
- singleEquivMap.put("acn", "xia");
- singleEquivMap.put("adx", "pcr");
- singleEquivMap.put("ami", "i-ami");
- singleEquivMap.put("art-lojban", "jbo");
- singleEquivMap.put("ase", "sgn-us");
- singleEquivMap.put("ayx", "nun");
- singleEquivMap.put("bfi", "sgn-gb");
- singleEquivMap.put("bjd", "drl");
- singleEquivMap.put("bnn", "i-bnn");
- singleEquivMap.put("bzs", "sgn-br");
- singleEquivMap.put("cir", "meg");
- singleEquivMap.put("cjr", "mom");
- singleEquivMap.put("cka", "cmr");
- singleEquivMap.put("cmk", "xch");
- singleEquivMap.put("cmn-hans", "zh-cmn-hans");
- singleEquivMap.put("cmn-hant", "zh-cmn-hant");
- singleEquivMap.put("cmr", "cka");
- singleEquivMap.put("csn", "sgn-co");
- singleEquivMap.put("dev", "gav");
- singleEquivMap.put("drh", "khk");
- singleEquivMap.put("drl", "bjd");
- singleEquivMap.put("dse", "sgn-nl");
- singleEquivMap.put("dsl", "sgn-dk");
- singleEquivMap.put("fsl", "sgn-fr");
- singleEquivMap.put("gal", "ilw");
- singleEquivMap.put("gan", "zh-gan");
- singleEquivMap.put("gav", "dev");
- singleEquivMap.put("gsg", "sgn-de");
- singleEquivMap.put("gss", "sgn-gr");
- singleEquivMap.put("he", "iw");
- singleEquivMap.put("hle", "sca");
- singleEquivMap.put("hrr", "jal");
- singleEquivMap.put("hsn", "zh-xiang");
- singleEquivMap.put("i-ami", "ami");
- singleEquivMap.put("i-bnn", "bnn");
- singleEquivMap.put("i-klingon", "tlh");
- singleEquivMap.put("i-lux", "lb");
- singleEquivMap.put("i-navajo", "nv");
- singleEquivMap.put("i-pwn", "pwn");
- singleEquivMap.put("i-tao", "tao");
- singleEquivMap.put("i-tay", "tay");
- singleEquivMap.put("i-tsu", "tsu");
- singleEquivMap.put("ibi", "opa");
- singleEquivMap.put("id", "in");
- singleEquivMap.put("ilw", "gal");
- singleEquivMap.put("in", "id");
- singleEquivMap.put("ise", "sgn-it");
- singleEquivMap.put("isg", "sgn-ie");
- singleEquivMap.put("iw", "he");
- singleEquivMap.put("jal", "hrr");
- singleEquivMap.put("jbo", "art-lojban");
- singleEquivMap.put("ji", "yi");
- singleEquivMap.put("jsl", "sgn-jp");
- singleEquivMap.put("jv", "jw");
- singleEquivMap.put("jw", "jv");
- singleEquivMap.put("kgh", "kml");
- singleEquivMap.put("khk", "drh");
- singleEquivMap.put("kml", "kgh");
- singleEquivMap.put("lb", "i-lux");
- singleEquivMap.put("lcq", "ppr");
- singleEquivMap.put("lrr", "yma");
- singleEquivMap.put("meg", "cir");
- singleEquivMap.put("mfs", "sgn-mx");
- singleEquivMap.put("mo", "ro");
- singleEquivMap.put("mom", "cjr");
- singleEquivMap.put("nan", "zh-min-nan");
- singleEquivMap.put("nb", "no-bok");
- singleEquivMap.put("ncs", "sgn-ni");
- singleEquivMap.put("nn", "no-nyn");
- singleEquivMap.put("no-bok", "nb");
- singleEquivMap.put("no-nyn", "nn");
- singleEquivMap.put("nsl", "sgn-no");
- singleEquivMap.put("nun", "ayx");
- singleEquivMap.put("nv", "i-navajo");
- singleEquivMap.put("opa", "ibi");
- singleEquivMap.put("pcr", "adx");
- singleEquivMap.put("ppr", "lcq");
- singleEquivMap.put("psr", "sgn-pt");
- singleEquivMap.put("pwn", "i-pwn");
- singleEquivMap.put("ras", "tie");
- singleEquivMap.put("ro", "mo");
- singleEquivMap.put("sca", "hle");
- singleEquivMap.put("sfb", "sgn-be-fr");
- singleEquivMap.put("sfs", "sgn-za");
- singleEquivMap.put("sgg", "sgn-ch-de");
- singleEquivMap.put("sgn-be-fr", "sfb");
- singleEquivMap.put("sgn-be-nl", "vgt");
- singleEquivMap.put("sgn-br", "bzs");
- singleEquivMap.put("sgn-ch-de", "sgg");
- singleEquivMap.put("sgn-co", "csn");
- singleEquivMap.put("sgn-de", "gsg");
- singleEquivMap.put("sgn-dk", "dsl");
- singleEquivMap.put("sgn-es", "ssp");
- singleEquivMap.put("sgn-fr", "fsl");
- singleEquivMap.put("sgn-gb", "bfi");
- singleEquivMap.put("sgn-gr", "gss");
- singleEquivMap.put("sgn-ie", "isg");
- singleEquivMap.put("sgn-it", "ise");
- singleEquivMap.put("sgn-jp", "jsl");
- singleEquivMap.put("sgn-mx", "mfs");
- singleEquivMap.put("sgn-ni", "ncs");
- singleEquivMap.put("sgn-nl", "dse");
- singleEquivMap.put("sgn-no", "nsl");
- singleEquivMap.put("sgn-pt", "psr");
- singleEquivMap.put("sgn-se", "swl");
- singleEquivMap.put("sgn-us", "ase");
- singleEquivMap.put("sgn-za", "sfs");
- singleEquivMap.put("ssp", "sgn-es");
- singleEquivMap.put("swl", "sgn-se");
- singleEquivMap.put("tao", "i-tao");
- singleEquivMap.put("tay", "i-tay");
- singleEquivMap.put("tie", "ras");
- singleEquivMap.put("tkk", "twm");
- singleEquivMap.put("tlh", "i-klingon");
- singleEquivMap.put("tlw", "weo");
- singleEquivMap.put("tsu", "i-tsu");
- singleEquivMap.put("twm", "tkk");
- singleEquivMap.put("vgt", "sgn-be-nl");
- singleEquivMap.put("weo", "tlw");
- singleEquivMap.put("wuu", "zh-wuu");
- singleEquivMap.put("xch", "cmk");
- singleEquivMap.put("xia", "acn");
- singleEquivMap.put("yi", "ji");
- singleEquivMap.put("yma", "lrr");
- singleEquivMap.put("yos", "zom");
- singleEquivMap.put("yue", "zh-yue");
- singleEquivMap.put("zh-cmn-hans", "cmn-hans");
- singleEquivMap.put("zh-cmn-hant", "cmn-hant");
- singleEquivMap.put("zh-gan", "gan");
- singleEquivMap.put("zh-min-nan", "nan");
- singleEquivMap.put("zh-wuu", "wuu");
- singleEquivMap.put("zh-xiang", "hsn");
- singleEquivMap.put("zh-yue", "yue");
- singleEquivMap.put("zom", "yos");
-
- multiEquivsMap.put("ccq", new String[] {"rki", "ybd"});
- multiEquivsMap.put("cmn", new String[] {"zh-guoyu", "zh-cmn"});
- multiEquivsMap.put("drw", new String[] {"prs", "tnf"});
- multiEquivsMap.put("hak", new String[] {"i-hak", "zh-hakka"});
- multiEquivsMap.put("i-hak", new String[] {"hak", "zh-hakka"});
- multiEquivsMap.put("mry", new String[] {"mst", "myt"});
- multiEquivsMap.put("mst", new String[] {"mry", "myt"});
- multiEquivsMap.put("myt", new String[] {"mry", "mst"});
- multiEquivsMap.put("prs", new String[] {"drw", "tnf"});
- multiEquivsMap.put("rki", new String[] {"ccq", "ybd"});
- multiEquivsMap.put("tnf", new String[] {"prs", "drw"});
- multiEquivsMap.put("ybd", new String[] {"rki", "ccq"});
- multiEquivsMap.put("zh-cmn", new String[] {"cmn", "zh-guoyu"});
- multiEquivsMap.put("zh-guoyu", new String[] {"cmn", "zh-cmn"});
- multiEquivsMap.put("zh-hakka", new String[] {"hak", "i-hak"});
-
- regionVariantEquivMap.put("-alalc97", "-heploc");
- regionVariantEquivMap.put("-bu", "-mm");
- regionVariantEquivMap.put("-cd", "-zr");
- regionVariantEquivMap.put("-dd", "-de");
- regionVariantEquivMap.put("-de", "-dd");
- regionVariantEquivMap.put("-fr", "-fx");
- regionVariantEquivMap.put("-fx", "-fr");
- regionVariantEquivMap.put("-heploc", "-alalc97");
- regionVariantEquivMap.put("-mm", "-bu");
- regionVariantEquivMap.put("-tl", "-tp");
- regionVariantEquivMap.put("-tp", "-tl");
- regionVariantEquivMap.put("-yd", "-ye");
- regionVariantEquivMap.put("-ye", "-yd");
- regionVariantEquivMap.put("-zr", "-cd");
- }
-
-}
diff --git a/src/share/classes/sun/util/resources/CurrencyNames.properties b/src/share/classes/sun/util/resources/CurrencyNames.properties
index c62d518e4b..238186bf21 100644
--- a/src/share/classes/sun/util/resources/CurrencyNames.properties
+++ b/src/share/classes/sun/util/resources/CurrencyNames.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2018, 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
@@ -178,6 +178,7 @@ MMK=MMK
MNT=MNT
MOP=MOP
MRO=MRO
+MRU=MRU
MTL=MTL
MUR=MUR
MVR=MVR
@@ -226,6 +227,7 @@ SRD=SRD
SRG=SRG
SSP=SSP
STD=STD
+STN=STN
SVC=SVC
SYP=SYP
SZL=SZL
@@ -250,6 +252,7 @@ UYU=UYU
UZS=UZS
VEB=VEB
VEF=VEF
+VES=VES
VND=VND
VUV=VUV
WST=WST
@@ -294,7 +297,7 @@ ats=Austrian Schilling
aud=Australian Dollar
awg=Aruban Florin
azm=Azerbaijani Manat (1993-2006)
-azn=Azerbaijani Manat
+azn=Azerbaijan Manat
bam=Bosnia-Herzegovina Convertible Mark
bbd=Barbadian Dollar
bdt=Bangladeshi Taka
@@ -380,7 +383,7 @@ krw=South Korean Won
kwd=Kuwaiti Dinar
kyd=Cayman Islands Dollar
kzt=Kazakhstani Tenge
-lak=Laotian Kip
+lak=Lao Kip
lbp=Lebanese Pound
lkr=Sri Lankan Rupee
lrd=Liberian Dollar
@@ -398,6 +401,7 @@ mmk=Myanma Kyat
mnt=Mongolian Tugrik
mop=Macanese Pataca
mro=Mauritanian Ouguiya
+mru=Mauritanian Ouguiya
mtl=Maltese Lira
mur=Mauritian Rupee
mvr=Maldivian Rufiyaa
@@ -446,6 +450,7 @@ srd=Surinamese Dollar
srg=Surinamese Guilder
ssp=South Sudanese Pound
std=S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra
+stn=S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra
svc=Salvadoran Col\u00f3n
syp=Syrian Pound
szl=Swazi Lilangeni
@@ -470,6 +475,7 @@ uyu=Uruguayan Peso
uzs=Uzbekistan Som
veb=Venezuelan Bol\u00edvar (1871-2008)
vef=Venezuelan Bol\u00edvar
+ves=Venezuelan Bol\u00edvar Soberano
vnd=Vietnamese Dong
vuv=Vanuatu Vatu
wst=Samoan Tala
diff --git a/src/share/classes/sun/util/resources/TimeZoneNames.java b/src/share/classes/sun/util/resources/TimeZoneNames.java
index 261d43a340..2c4b56da7e 100644
--- a/src/share/classes/sun/util/resources/TimeZoneNames.java
+++ b/src/share/classes/sun/util/resources/TimeZoneNames.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -370,7 +370,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
@@ -683,6 +683,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
{"Asia/Pontianak", WIT},
{"Asia/Pyongyang", KST},
{"Asia/Qatar", ARAST},
+ {"Asia/Qostanay", new String[] {"Kostanay Standard Time", "QOST",
+ "Kostanay Summer Time", "QOSST",
+ "Kostanay Time", "QOST"}},
{"Asia/Qyzylorda", new String[] {"Qyzylorda Time", "QYZT",
"Qyzylorda Summer Time", "QYZST",
"Qyzylorda Time", "QYZT"}},
diff --git a/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java b/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
index 67cc5b04f4..e258618c9d 100644
--- a/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
+++ b/src/share/classes/sun/util/resources/de/TimeZoneNames_de.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/es/CurrencyNames_es_VE.properties b/src/share/classes/sun/util/resources/es/CurrencyNames_es_VE.properties
index 41c45105be..e7fc92cbba 100644
--- a/src/share/classes/sun/util/resources/es/CurrencyNames_es_VE.properties
+++ b/src/share/classes/sun/util/resources/es/CurrencyNames_es_VE.properties
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2018, 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
@@ -37,4 +37,4 @@
VEB=Bs
VEF=Bs.F.
-
+VES=Bs.S.
diff --git a/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java b/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
index 4d564b0ffc..ea8887e139 100644
--- a/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
+++ b/src/share/classes/sun/util/resources/es/TimeZoneNames_es.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java b/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
index c649f9af45..58891022d3 100644
--- a/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
+++ b/src/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java b/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
index b9724ee463..53ab4a6d73 100644
--- a/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
+++ b/src/share/classes/sun/util/resources/it/TimeZoneNames_it.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java b/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
index 6fe96fa9a7..8bec0d7db0 100644
--- a/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
+++ b/src/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java b/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
index 4621b479ce..7c72073b73 100644
--- a/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
+++ b/src/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java b/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
index 6baac2d415..c65dfa5da7 100644
--- a/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
+++ b/src/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_pt_BR extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java b/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
index 0a071924df..6ce81e8011 100644
--- a/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
+++ b/src/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
index 1d1b2dc7be..3e81b6b42c 100644
--- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
+++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
index 280c186cc2..0233a53f4f 100644
--- a/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
+++ b/src/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2019, 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
@@ -371,7 +371,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
{"Africa/Nouakchott", GMT},
{"Africa/Ouagadougou", GMT},
{"Africa/Porto-Novo", WAT},
- {"Africa/Sao_Tome", WAT},
+ {"Africa/Sao_Tome", GMT},
{"Africa/Timbuktu", GMT},
{"Africa/Tripoli", EET},
{"Africa/Tunis", CET},
diff --git a/src/share/lib/security/cacerts b/src/share/lib/security/cacerts
index 318a166205..1db6c41b89 100644
--- a/src/share/lib/security/cacerts
+++ b/src/share/lib/security/cacerts
Binary files differ
diff --git a/src/share/lib/security/java.policy b/src/share/lib/security/java.policy
index 120694d699..59d99a964c 100644
--- a/src/share/lib/security/java.policy
+++ b/src/share/lib/security/java.policy
@@ -45,5 +45,7 @@ grant {
permission java.util.PropertyPermission "java.vm.version", "read";
permission java.util.PropertyPermission "java.vm.vendor", "read";
permission java.util.PropertyPermission "java.vm.name", "read";
+
+ permission java.util.PropertyPermission "sun.security.pkcs11.disableKeyExtraction", "read";
};
diff --git a/src/share/lib/security/java.security-aix b/src/share/lib/security/java.security-aix
index e2c0ff9b3e..69cc59fa65 100644
--- a/src/share/lib/security/java.security-aix
+++ b/src/share/lib/security/java.security-aix
@@ -1005,3 +1005,32 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS
+
+#
+# Policies for the proxy_impersonator Kerberos ccache configuration entry
+#
+# The proxy_impersonator ccache configuration entry indicates that the ccache
+# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
+# server. The ccache file should also contain the TGT of this server and
+# an evidence ticket from the default principal of the ccache to this server.
+#
+# This security property determines how Java uses this configuration entry.
+# There are 3 possible values:
+#
+# no-impersonate - Ignore this configuration entry, and always act as
+# the owner of the TGT (if it exists).
+#
+# try-impersonate - Try impersonation when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# fallback to no-impersonate.
+#
+# always-impersonate - Always impersonate when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# no initial credential is read from the ccache.
+#
+# The default value is "always-impersonate".
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file
diff --git a/src/share/lib/security/java.security-linux b/src/share/lib/security/java.security-linux
index 2f33b1acbc..ae28ce7b7b 100644
--- a/src/share/lib/security/java.security-linux
+++ b/src/share/lib/security/java.security-linux
@@ -1011,3 +1011,32 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS
+
+#
+# Policies for the proxy_impersonator Kerberos ccache configuration entry
+#
+# The proxy_impersonator ccache configuration entry indicates that the ccache
+# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
+# server. The ccache file should also contain the TGT of this server and
+# an evidence ticket from the default principal of the ccache to this server.
+#
+# This security property determines how Java uses this configuration entry.
+# There are 3 possible values:
+#
+# no-impersonate - Ignore this configuration entry, and always act as
+# the owner of the TGT (if it exists).
+#
+# try-impersonate - Try impersonation when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# fallback to no-impersonate.
+#
+# always-impersonate - Always impersonate when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# no initial credential is read from the ccache.
+#
+# The default value is "always-impersonate".
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file
diff --git a/src/share/lib/security/java.security-macosx b/src/share/lib/security/java.security-macosx
index 277c3356d3..8af804b714 100644
--- a/src/share/lib/security/java.security-macosx
+++ b/src/share/lib/security/java.security-macosx
@@ -1009,3 +1009,32 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS
+
+#
+# Policies for the proxy_impersonator Kerberos ccache configuration entry
+#
+# The proxy_impersonator ccache configuration entry indicates that the ccache
+# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
+# server. The ccache file should also contain the TGT of this server and
+# an evidence ticket from the default principal of the ccache to this server.
+#
+# This security property determines how Java uses this configuration entry.
+# There are 3 possible values:
+#
+# no-impersonate - Ignore this configuration entry, and always act as
+# the owner of the TGT (if it exists).
+#
+# try-impersonate - Try impersonation when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# fallback to no-impersonate.
+#
+# always-impersonate - Always impersonate when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# no initial credential is read from the ccache.
+#
+# The default value is "always-impersonate".
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file
diff --git a/src/share/lib/security/java.security-solaris b/src/share/lib/security/java.security-solaris
index 27ce9669e7..204871b144 100644
--- a/src/share/lib/security/java.security-solaris
+++ b/src/share/lib/security/java.security-solaris
@@ -1008,3 +1008,32 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS
+
+#
+# Policies for the proxy_impersonator Kerberos ccache configuration entry
+#
+# The proxy_impersonator ccache configuration entry indicates that the ccache
+# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
+# server. The ccache file should also contain the TGT of this server and
+# an evidence ticket from the default principal of the ccache to this server.
+#
+# This security property determines how Java uses this configuration entry.
+# There are 3 possible values:
+#
+# no-impersonate - Ignore this configuration entry, and always act as
+# the owner of the TGT (if it exists).
+#
+# try-impersonate - Try impersonation when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# fallback to no-impersonate.
+#
+# always-impersonate - Always impersonate when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# no initial credential is read from the ccache.
+#
+# The default value is "always-impersonate".
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file
diff --git a/src/share/lib/security/java.security-windows b/src/share/lib/security/java.security-windows
index 58aad3a1d8..e49d1880aa 100644
--- a/src/share/lib/security/java.security-windows
+++ b/src/share/lib/security/java.security-windows
@@ -1009,3 +1009,32 @@ jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;\
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS
+
+#
+# Policies for the proxy_impersonator Kerberos ccache configuration entry
+#
+# The proxy_impersonator ccache configuration entry indicates that the ccache
+# is a synthetic delegated credential for use with S4U2Proxy by an intermediate
+# server. The ccache file should also contain the TGT of this server and
+# an evidence ticket from the default principal of the ccache to this server.
+#
+# This security property determines how Java uses this configuration entry.
+# There are 3 possible values:
+#
+# no-impersonate - Ignore this configuration entry, and always act as
+# the owner of the TGT (if it exists).
+#
+# try-impersonate - Try impersonation when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# fallback to no-impersonate.
+#
+# always-impersonate - Always impersonate when this configuration entry exists.
+# If no matching TGT or evidence ticket is found,
+# no initial credential is read from the ccache.
+#
+# The default value is "always-impersonate".
+#
+# If a system property of the same name is also specified, it supersedes the
+# security property value defined here.
+#
+#jdk.security.krb5.default.initiate.credential=always-impersonate \ No newline at end of file
diff --git a/src/share/native/common/jni_util.c b/src/share/native/common/jni_util.c
index 87cd00e5e1..a4147703c4 100644
--- a/src/share/native/common/jni_util.c
+++ b/src/share/native/common/jni_util.c
@@ -27,8 +27,7 @@
#include <string.h>
#include "jvm.h"
-#include "jni.h"
-#include "jni_util.h"
+#include "io_util.h"
/* Due to a bug in the win32 C runtime library strings
* such as "z:" need to be appended with a "." so we
@@ -683,10 +682,14 @@ initializeEncoding(JNIEnv *env)
{
jstring propname = 0;
jstring enc = 0;
+ jclass strClazz = NULL;
if ((*env)->EnsureLocalCapacity(env, 3) < 0)
return;
+ strClazz = JNU_ClassString(env);
+ CHECK_NULL(strClazz);
+
propname = (*env)->NewStringUTF(env, "sun.jnu.encoding");
if (propname) {
jboolean exc;
@@ -740,10 +743,12 @@ initializeEncoding(JNIEnv *env)
(*env)->DeleteLocalRef(env, enc);
/* Initialize method-id cache */
- String_getBytes_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+ String_getBytes_ID = (*env)->GetMethodID(env, strClazz,
"getBytes", "(Ljava/lang/String;)[B");
- String_init_ID = (*env)->GetMethodID(env, JNU_ClassString(env),
+ CHECK_NULL(String_getBytes_ID);
+ String_init_ID = (*env)->GetMethodID(env, strClazz,
"<init>", "([BLjava/lang/String;)V");
+ CHECK_NULL(String_init_ID);
}
static jboolean isJNUEncodingSupported = JNI_FALSE;
@@ -777,8 +782,10 @@ JNU_NewStringPlatform(JNIEnv *env, const char *str)
jbyteArray hab = 0;
int len;
- if (fastEncoding == NO_ENCODING_YET)
+ if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
+ JNU_CHECK_EXCEPTION_RETURN(env, NULL);
+ }
if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
return newString8859_1(env, str);
@@ -793,9 +800,11 @@ JNU_NewStringPlatform(JNIEnv *env, const char *str)
len = (int)strlen(str);
hab = (*env)->NewByteArray(env, len);
if (hab != 0) {
+ jclass strClazz = JNU_ClassString(env);
+ CHECK_NULL_RETURN(strClazz, 0);
(*env)->SetByteArrayRegion(env, hab, 0, len, (jbyte *)str);
if (jnuEncodingSupported(env)) {
- result = (*env)->NewObject(env, JNU_ClassString(env),
+ result = (*env)->NewObject(env, strClazz,
String_init_ID, hab, jnuEncoding);
} else {
/*If the encoding specified in sun.jnu.encoding is not endorsed
@@ -804,9 +813,11 @@ JNU_NewStringPlatform(JNIEnv *env, const char *str)
StringCoding class will pickup the iso-8859-1 as the fallback
converter for us.
*/
- jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
+ jmethodID mid = (*env)->GetMethodID(env, strClazz,
"<init>", "([B)V");
- result = (*env)->NewObject(env, JNU_ClassString(env), mid, hab);
+ if (mid != NULL) {
+ result = (*env)->NewObject(env, strClazz, mid, hab);
+ }
}
(*env)->DeleteLocalRef(env, hab);
return result;
@@ -832,8 +843,10 @@ JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
if (isCopy)
*isCopy = JNI_TRUE;
- if (fastEncoding == NO_ENCODING_YET)
+ if (fastEncoding == NO_ENCODING_YET) {
initializeEncoding(env);
+ JNU_CHECK_EXCEPTION_RETURN(env, 0);
+ }
if ((fastEncoding == FAST_8859_1) || (fastEncoding == NO_ENCODING_YET))
return getString8859_1Chars(env, jstr);
@@ -848,9 +861,14 @@ JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy)
if (jnuEncodingSupported(env)) {
hab = (*env)->CallObjectMethod(env, jstr, String_getBytes_ID, jnuEncoding);
} else {
- jmethodID mid = (*env)->GetMethodID(env, JNU_ClassString(env),
- "getBytes", "()[B");
- hab = (*env)->CallObjectMethod(env, jstr, mid);
+ jmethodID mid;
+ jclass strClazz = JNU_ClassString(env);
+ CHECK_NULL_RETURN(strClazz, 0);
+ mid = (*env)->GetMethodID(env, strClazz,
+ "getBytes", "()[B");
+ if (mid != NULL) {
+ hab = (*env)->CallObjectMethod(env, jstr, mid);
+ }
}
if (!(*env)->ExceptionCheck(env)) {
@@ -899,6 +917,7 @@ JNU_ClassString(JNIEnv *env)
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return 0;
c = (*env)->FindClass(env, "java/lang/String");
+ CHECK_NULL_RETURN(c, NULL);
cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
@@ -914,6 +933,7 @@ JNU_ClassClass(JNIEnv *env)
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return 0;
c = (*env)->FindClass(env, "java/lang/Class");
+ CHECK_NULL_RETURN(c, NULL);
cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
@@ -929,6 +949,7 @@ JNU_ClassObject(JNIEnv *env)
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return 0;
c = (*env)->FindClass(env, "java/lang/Object");
+ CHECK_NULL_RETURN(c, NULL);
cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
@@ -944,6 +965,7 @@ JNU_ClassThrowable(JNIEnv *env)
if ((*env)->EnsureLocalCapacity(env, 1) < 0)
return 0;
c = (*env)->FindClass(env, "java/lang/Throwable");
+ CHECK_NULL_RETURN(c, NULL);
cls = (*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
}
@@ -993,8 +1015,11 @@ JNU_Equals(JNIEnv *env, jobject object1, jobject object2)
{
static jmethodID mid = NULL;
if (mid == NULL) {
- mid = (*env)->GetMethodID(env, JNU_ClassObject(env), "equals",
+ jclass objClazz = JNU_ClassObject(env);
+ CHECK_NULL_RETURN(objClazz, JNI_FALSE);
+ mid = (*env)->GetMethodID(env, objClazz, "equals",
"(Ljava/lang/Object;)Z");
+ CHECK_NULL_RETURN(mid, JNI_FALSE);
}
return (*env)->CallBooleanMethod(env, object1, mid, object2);
}
@@ -1096,7 +1121,9 @@ JNU_PrintClass(JNIEnv *env, char* hdr, jobject object)
} else {
jclass cls = (*env)->GetObjectClass(env, object);
jstring clsName = JNU_ToString(env, cls);
- JNU_PrintString(env, hdr, clsName);
+ if (clsName == NULL) {
+ JNU_PrintString(env, hdr, clsName);
+ }
(*env)->DeleteLocalRef(env, cls);
(*env)->DeleteLocalRef(env, clsName);
}
diff --git a/src/share/native/sun/awt/giflib/dgif_lib.c b/src/share/native/sun/awt/giflib/dgif_lib.c
index 1c1b217654..0a59e2bcb4 100644
--- a/src/share/native/sun/awt/giflib/dgif_lib.c
+++ b/src/share/native/sun/awt/giflib/dgif_lib.c
@@ -36,13 +36,16 @@ two modules will be linked. Preserve this property!
#include <limits.h>
#include <stdint.h>
#include <fcntl.h>
+/** Begin JDK modifications to support building on Windows **/
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+/** End JDK modifications to support building on Windows **/
#include <stdio.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
-#else
-#include <unistd.h>
#endif /* _WIN32 */
#include "gif_lib.h"
@@ -52,10 +55,14 @@ two modules will be linked. Preserve this property!
#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
/* avoid extra function call in case we use fread (TVT) */
-#define READ(_gif,_buf,_len) \
- (((GifFilePrivateType*)_gif->Private)->Read ? \
- ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
- fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
+/** JDK modification "inline" is dropped to support c89 **/
+static /**inline**/ int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
+ //fprintf(stderr, "### Read: %d\n", len);
+ return
+ (((GifFilePrivateType*)gif->Private)->Read ?
+ ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) :
+ fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
+}
static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
static int DGifSetupDecompress(GifFileType *GifFile);
@@ -142,7 +149,7 @@ DGifOpenFileHandle(int FileHandle, int *Error)
/* Let's see if this is a GIF file: */
/* coverity[check_return] */
- if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
+ if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
if (Error != NULL)
*Error = D_GIF_ERR_READ_FAILED;
(void)fclose(f);
@@ -219,7 +226,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
/* Lets see if this is a GIF file: */
/* coverity[check_return] */
- if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
+ if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
if (Error != NULL)
*Error = D_GIF_ERR_READ_FAILED;
free((char *)Private);
@@ -276,7 +283,7 @@ DGifGetScreenDesc(GifFileType *GifFile)
DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
return GIF_ERROR;
- if (READ(GifFile, Buf, 3) != 3) {
+ if (InternalRead(GifFile, Buf, 3) != 3) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
GifFreeMapObject(GifFile->SColorMap);
GifFile->SColorMap = NULL;
@@ -300,7 +307,7 @@ DGifGetScreenDesc(GifFileType *GifFile)
GifFile->SColorMap->SortFlag = SortFlag;
for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
/* coverity[check_return] */
- if (READ(GifFile, Buf, 3) != 3) {
+ if (InternalRead(GifFile, Buf, 3) != 3) {
GifFreeMapObject(GifFile->SColorMap);
GifFile->SColorMap = NULL;
GifFile->Error = D_GIF_ERR_READ_FAILED;
@@ -314,9 +321,25 @@ DGifGetScreenDesc(GifFileType *GifFile)
GifFile->SColorMap = NULL;
}
+ /*
+ * No check here for whether the background color is in range for the
+ * screen color map. Possibly there should be.
+ */
+
return GIF_OK;
}
+const char *
+DGifGetGifVersion(GifFileType *GifFile)
+{
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (Private->gif89)
+ return GIF89_STAMP;
+ else
+ return GIF87_STAMP;
+}
+
/******************************************************************************
This routine should be called before any attempt to read an image.
******************************************************************************/
@@ -333,11 +356,12 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
}
/* coverity[check_return] */
- if (READ(GifFile, &Buf, 1) != 1) {
+ if (InternalRead(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
+ //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
switch (Buf) {
case DESCRIPTOR_INTRODUCER:
*Type = IMAGE_DESC_RECORD_TYPE;
@@ -357,17 +381,12 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
return GIF_OK;
}
-/******************************************************************************
- This routine should be called before any attempt to read an image.
- Note it is assumed the Image desc. header has been read.
-******************************************************************************/
int
-DGifGetImageDesc(GifFileType *GifFile)
+DGifGetImageHeader(GifFileType *GifFile)
{
unsigned int BitsPerPixel;
GifByteType Buf[3];
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
- SavedImage *sp;
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
@@ -380,7 +399,7 @@ DGifGetImageDesc(GifFileType *GifFile)
DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
return GIF_ERROR;
- if (READ(GifFile, Buf, 1) != 1) {
+ if (InternalRead(GifFile, Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
GifFreeMapObject(GifFile->Image.ColorMap);
GifFile->Image.ColorMap = NULL;
@@ -407,7 +426,7 @@ DGifGetImageDesc(GifFileType *GifFile)
/* Get the image local color map: */
for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
/* coverity[check_return] */
- if (READ(GifFile, Buf, 3) != 3) {
+ if (InternalRead(GifFile, Buf, 3) != 3) {
GifFreeMapObject(GifFile->Image.ColorMap);
GifFile->Error = D_GIF_ERR_READ_FAILED;
GifFile->Image.ColorMap = NULL;
@@ -419,6 +438,33 @@ DGifGetImageDesc(GifFileType *GifFile)
}
}
+ Private->PixelCount = (long)GifFile->Image.Width *
+ (long)GifFile->Image.Height;
+
+ /* Reset decompress algorithm parameters. */
+ return DGifSetupDecompress(GifFile);
+}
+
+/******************************************************************************
+ This routine should be called before any attempt to read an image.
+ Note it is assumed the Image desc. header has been read.
+******************************************************************************/
+int
+DGifGetImageDesc(GifFileType *GifFile)
+{
+ GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
+ SavedImage *sp;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ GifFile->Error = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
+ return GIF_ERROR;
+ }
+
if (GifFile->SavedImages) {
SavedImage* new_saved_images =
(SavedImage *)reallocarray(GifFile->SavedImages,
@@ -453,11 +499,7 @@ DGifGetImageDesc(GifFileType *GifFile)
GifFile->ImageCount++;
- Private->PixelCount = (long)GifFile->Image.Width *
- (long)GifFile->Image.Height;
-
- /* Reset decompress algorithm parameters. */
- return DGifSetupDecompress(GifFile);
+ return GIF_OK;
}
/******************************************************************************
@@ -550,6 +592,7 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
+ //fprintf(stderr, "### -> DGifGetExtension:\n");
if (!IS_READABLE(Private)) {
/* This file was NOT open for reading: */
GifFile->Error = D_GIF_ERR_NOT_READABLE;
@@ -557,11 +600,12 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
}
/* coverity[check_return] */
- if (READ(GifFile, &Buf, 1) != 1) {
+ if (InternalRead(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
*ExtCode = Buf;
+ //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
return DGifGetExtensionNext(GifFile, Extension);
}
@@ -577,20 +621,24 @@ DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
GifByteType Buf;
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
- if (READ(GifFile, &Buf, 1) != 1) {
+ //fprintf(stderr, "### -> DGifGetExtensionNext\n");
+ if (InternalRead(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
+ //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
+
if (Buf > 0) {
*Extension = Private->Buf; /* Use private unused buffer. */
(*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
/* coverity[tainted_data,check_return] */
- if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
+ if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
} else
*Extension = NULL;
+ //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
return GIF_OK;
}
@@ -707,7 +755,7 @@ DGifGetWord(GifFileType *GifFile, GifWord *Word)
unsigned char c[2];
/* coverity[check_return] */
- if (READ(GifFile, c, 2) != 2) {
+ if (InternalRead(GifFile, c, 2) != 2) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
@@ -752,7 +800,7 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
/* coverity[tainted_data_argument] */
/* coverity[check_return] */
- if (READ(GifFile, &Buf, 1) != 1) {
+ if (InternalRead(GifFile, &Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
@@ -762,7 +810,7 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
*CodeBlock = Private->Buf; /* Use private unused buffer. */
(*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
/* coverity[tainted_data] */
- if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
+ if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
@@ -787,7 +835,7 @@ DGifSetupDecompress(GifFileType *GifFile)
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
/* coverity[check_return] */
- if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
+ if (InternalRead(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
return GIF_ERROR; /* Failed to read Code size. */
}
BitsPerPixel = CodeSize;
@@ -921,7 +969,7 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
while (StackPtr != 0 && i < LineLen)
Line[i++] = Stack[--StackPtr];
}
- if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
+ if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < LZ_MAX_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
Prefix[Private->RunningCode - 2] = LastCode;
if (CrntCode == Private->RunningCode - 2) {
@@ -1069,7 +1117,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
if (Buf[0] == 0) {
/* Needs to read the next buffer - this one is empty: */
/* coverity[check_return] */
- if (READ(GifFile, Buf, 1) != 1) {
+ if (InternalRead(GifFile, Buf, 1) != 1) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
@@ -1081,7 +1129,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
return GIF_ERROR;
}
- if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
+ if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
GifFile->Error = D_GIF_ERR_READ_FAILED;
return GIF_ERROR;
}
@@ -1124,7 +1172,7 @@ DGifSlurp(GifFileType *GifFile)
sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
/* Allocate memory for the image */
- if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 &&
+ if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
return GIF_ERROR;
}
@@ -1184,9 +1232,11 @@ DGifSlurp(GifFileType *GifFile)
== GIF_ERROR)
return (GIF_ERROR);
}
- while (ExtData != NULL) {
+ for (;;) {
if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
return (GIF_ERROR);
+ if (ExtData == NULL)
+ break;
/* Continue the extension block */
if (ExtData != NULL)
if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
diff --git a/src/share/native/sun/awt/giflib/gif_hash.h b/src/share/native/sun/awt/giflib/gif_hash.h
index 5896875a64..a2fc081af9 100644
--- a/src/share/native/sun/awt/giflib/gif_hash.h
+++ b/src/share/native/sun/awt/giflib/gif_hash.h
@@ -31,6 +31,11 @@ gif_hash.h - magfic constants and declarations for GIF LZW
#ifndef _GIF_HASH_H_
#define _GIF_HASH_H_
+/** Begin JDK modifications to support building on Windows **/
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+/** End JDK modifications to support building on Windows **/
#include <stdint.h>
#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */
diff --git a/src/share/native/sun/awt/giflib/gif_lib.h b/src/share/native/sun/awt/giflib/gif_lib.h
index e8d7090bd1..828c1520b4 100644
--- a/src/share/native/sun/awt/giflib/gif_lib.h
+++ b/src/share/native/sun/awt/giflib/gif_lib.h
@@ -37,19 +37,21 @@ extern "C" {
#define GIFLIB_MAJOR 5
#define GIFLIB_MINOR 1
-#define GIFLIB_RELEASE 4
+#define GIFLIB_RELEASE 8
#define GIF_ERROR 0
#define GIF_OK 1
#include <stddef.h>
-
+/** Begin JDK modifications to support building using old compilers**/
+//#include <stdbool.h>
#ifdef bool
#undef bool
#endif
typedef int bool;
#define false 0
#define true 1
+/** End JDK modifications to support building using old compilers**/
#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
@@ -88,7 +90,7 @@ typedef struct ExtensionBlock {
#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */
#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control (GIF89) */
#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */
-#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */
+#define APPLICATION_EXT_FUNC_CODE 0xff /* application block (GIF89) */
} ExtensionBlock;
typedef struct SavedImage {
@@ -230,10 +232,10 @@ GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new
/* These are legacy. You probably do not want to call them directly */
int DGifGetScreenDesc(GifFileType *GifFile);
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
+int DGifGetImageHeader(GifFileType *GifFile);
int DGifGetImageDesc(GifFileType *GifFile);
int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel);
-int DGifGetComment(GifFileType *GifFile, char *GifComment);
int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
GifByteType **GifExtension);
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension);
@@ -241,6 +243,7 @@ int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
GifByteType **GifCodeBlock);
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
+const char *DGifGetGifVersion(GifFileType *GifFile);
/******************************************************************************
@@ -274,9 +277,6 @@ extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
GifPixelType ColorTransIn2[]);
extern int GifBitSize(int n);
-extern void * reallocarray(void *optr, size_t nmemb, size_t size);
-
-
/******************************************************************************
Support for the in-core structures allocation (slurp mode).
******************************************************************************/
diff --git a/src/share/native/sun/awt/giflib/gif_lib_private.h b/src/share/native/sun/awt/giflib/gif_lib_private.h
index 67c4746588..21a5f2074e 100644
--- a/src/share/native/sun/awt/giflib/gif_lib_private.h
+++ b/src/share/native/sun/awt/giflib/gif_lib_private.h
@@ -34,6 +34,10 @@ gif_lib_private.h - internal giflib routines and structures
#include "gif_lib.h"
#include "gif_hash.h"
+#ifndef SIZE_MAX
+ #define SIZE_MAX UINTPTR_MAX
+#endif
+
#define EXTENSION_INTRODUCER 0x21
#define DESCRIPTOR_INTRODUCER 0x2c
#define TERMINATOR_INTRODUCER 0x3b
@@ -78,6 +82,11 @@ typedef struct GifFilePrivateType {
bool gif89;
} GifFilePrivateType;
+#ifndef HAVE_REALLOCARRAY
+extern void *openbsd_reallocarray(void *optr, size_t nmemb, size_t size);
+#define reallocarray openbsd_reallocarray
+#endif
+
#endif /* _GIF_LIB_PRIVATE_H */
/* end */
diff --git a/src/share/native/sun/awt/giflib/gifalloc.c b/src/share/native/sun/awt/giflib/gifalloc.c
index cc784d19bd..632458bf2b 100644
--- a/src/share/native/sun/awt/giflib/gifalloc.c
+++ b/src/share/native/sun/awt/giflib/gifalloc.c
@@ -33,6 +33,7 @@
#include <string.h>
#include "gif_lib.h"
+#include "gif_lib_private.h"
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
@@ -348,15 +349,17 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
{
if (GifFile->SavedImages == NULL)
GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
- else
- GifFile->SavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
+ else {
+ SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
(GifFile->ImageCount + 1), sizeof(SavedImage));
-
+ if( newSavedImages == NULL)
+ return ((SavedImage *)NULL);
+ GifFile->SavedImages = newSavedImages;
+ }
if (GifFile->SavedImages == NULL)
return ((SavedImage *)NULL);
else {
SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
- memset((char *)sp, '\0', sizeof(SavedImage));
if (CopyFrom != NULL) {
memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
@@ -368,7 +371,7 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
*/
/* first, the local color map */
- if (sp->ImageDesc.ColorMap != NULL) {
+ if (CopyFrom->ImageDesc.ColorMap != NULL) {
sp->ImageDesc.ColorMap = GifMakeMapObject(
CopyFrom->ImageDesc.ColorMap->ColorCount,
CopyFrom->ImageDesc.ColorMap->Colors);
@@ -392,7 +395,7 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
CopyFrom->ImageDesc.Width);
/* finally, the extension blocks */
- if (sp->ExtensionBlocks != NULL) {
+ if (CopyFrom->ExtensionBlocks != NULL) {
sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
CopyFrom->ExtensionBlockCount,
sizeof(ExtensionBlock));
@@ -404,6 +407,9 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
}
}
+ else {
+ memset((char *)sp, '\0', sizeof(SavedImage));
+ }
return (sp);
}
diff --git a/src/share/native/sun/awt/giflib/openbsd-reallocarray.c b/src/share/native/sun/awt/giflib/openbsd-reallocarray.c
index 1087671c27..fdc0754026 100644
--- a/src/share/native/sun/awt/giflib/openbsd-reallocarray.c
+++ b/src/share/native/sun/awt/giflib/openbsd-reallocarray.c
@@ -44,6 +44,10 @@
#include <stdint.h>
#include <stdlib.h>
+#ifndef SIZE_MAX
+ #define SIZE_MAX UINTPTR_MAX
+#endif
+
/*
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
@@ -51,7 +55,7 @@
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
void *
-reallocarray(void *optr, size_t nmemb, size_t size)
+openbsd_reallocarray(void *optr, size_t nmemb, size_t size)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size) {
diff --git a/src/share/native/sun/awt/libpng/CHANGES b/src/share/native/sun/awt/libpng/CHANGES
index 0ed6a11872..f0b0a9342c 100644
--- a/src/share/native/sun/awt/libpng/CHANGES
+++ b/src/share/native/sun/awt/libpng/CHANGES
@@ -6063,9 +6063,47 @@ Version 1.6.35 [July 15, 2018]
Added missing parentheses to a macro definition
(suggested by "irwir" in GitHub issue #216)
-Send comments/corrections/commendations to png-mng-implement at lists.sf.net
-(subscription required; visit
+Version 1.6.36 [December 1, 2018]
+ Optimized png_do_expand_palette for ARM processors.
+ Improved performance by around 10-22% on a recent ARM Chromebook.
+ (Contributed by Richard Townsend, ARM Holdings)
+ Fixed manipulation of machine-specific optimization options.
+ (Contributed by Vicki Pfau)
+ Used memcpy instead of manual pointer arithmetic on Intel SSE2.
+ (Contributed by Samuel Williams)
+ Fixed build errors with MSVC on ARM64.
+ (Contributed by Zhijie Liang)
+ Fixed detection of libm in CMakeLists.
+ (Contributed by Cameron Cawley)
+ Fixed incorrect creation of pkg-config file in CMakeLists.
+ (Contributed by Kyle Bentley)
+ Fixed the CMake build on Windows MSYS by avoiding symlinks.
+ Fixed a build warning on OpenBSD.
+ (Contributed by Theo Buehler)
+ Fixed various typos in comments.
+ (Contributed by "luz.paz")
+ Raised the minimum required CMake version from 3.0.2 to 3.1.
+ Removed yet more of the vestigial support for pre-ANSI C compilers.
+ Removed ancient makefiles for ancient systems that have been broken
+ across all previous libpng-1.6.x versions.
+ Removed the Y2K compliance statement and the export control
+ information.
+ Applied various code style and documentation fixes.
+
+Version 1.6.37 [April 14, 2019]
+ Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free.
+ Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette.
+ Fixed a memory leak in pngtest.c.
+ Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in
+ contrib/pngminus; refactor.
+ Changed the license of contrib/pngminus to MIT; refresh makefile and docs.
+ (Contributed by Willem van Schaik)
+ Fixed a typo in the libpng license v2.
+ (Contributed by Miguel Ojeda)
+ Added makefiles for AddressSanitizer-enabled builds.
+ Cleaned up various makefiles.
+
+Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
+Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
-to subscribe).
-
-Glenn R-P
+to subscribe.
diff --git a/src/share/native/sun/awt/libpng/LICENSE b/src/share/native/sun/awt/libpng/LICENSE
index 6ee9c8f554..e0c5b531cf 100644
--- a/src/share/native/sun/awt/libpng/LICENSE
+++ b/src/share/native/sun/awt/libpng/LICENSE
@@ -1,53 +1,82 @@
+COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+=========================================
-This copy of the libpng notices is provided for your convenience. In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
+PNG Reference Library License version 2
+---------------------------------------
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * Copyright (c) 2018-2019 Cosmin Truta.
+ * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * Copyright (c) 1996-1997 Andreas Dilger.
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-If you modify libpng you may insert additional notices immediately following
-this sentence.
+The software is supplied "as is", without warranty of any kind,
+express or implied, including, without limitation, the warranties
+of merchantability, fitness for a particular purpose, title, and
+non-infringement. In no event shall the Copyright owners, or
+anyone distributing the software, be liable for any damages or
+other liability, whether in contract, tort or otherwise, arising
+from, out of, or in connection with the software, or the use or
+other dealings in the software, even if advised of the possibility
+of such damage.
-This code is released under the libpng license.
+Permission is hereby granted to use, copy, modify, and distribute
+this software, or portions hereof, for any purpose, without fee,
+subject to the following restrictions:
-libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+ 1. The origin of this software must not be misrepresented; you
+ must not claim that you wrote the original software. If you
+ use this software in a product, an acknowledgment in the product
+ documentation would be appreciated, but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
+
+
+PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+-----------------------------------------------------------------------
+
+libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
derived from libpng-1.0.6, and are distributed according to the same
disclaimer and license as libpng-1.0.6 with the following individuals
added to the list of Contributing Authors:
- Simon-Pierre Cadieux
- Eric S. Raymond
- Mans Rullgard
- Cosmin Truta
- Gilles Vollant
- James Yu
- Mandar Sahastrabuddhe
- Google Inc.
- Vadim Barkov
+ Simon-Pierre Cadieux
+ Eric S. Raymond
+ Mans Rullgard
+ Cosmin Truta
+ Gilles Vollant
+ James Yu
+ Mandar Sahastrabuddhe
+ Google Inc.
+ Vadim Barkov
and with the following additions to the disclaimer:
- There is no warranty against interference with your enjoyment of the
- library or against infringement. There is no warranty that our
- efforts or the library will fulfill any of your particular purposes
- or needs. This library is provided with all faults, and the entire
- risk of satisfactory quality, performance, accuracy, and effort is with
- the user.
+ There is no warranty against interference with your enjoyment of
+ the library or against infringement. There is no warranty that our
+ efforts or the library will fulfill any of your particular purposes
+ or needs. This library is provided with all faults, and the entire
+ risk of satisfactory quality, performance, accuracy, and effort is
+ with the user.
Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners and
+files that are distributed with libpng have other copyright owners, and
are released under other open source licenses.
libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
+license as libpng-0.96, with the following individuals added to the
+list of Contributing Authors:
- Tom Lane
- Glenn Randers-Pehrson
- Willem van Schaik
+ Tom Lane
+ Glenn Randers-Pehrson
+ Willem van Schaik
libpng versions 0.89, June 1996, through 0.96, May 1997, are
Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -55,14 +84,14 @@ and are distributed according to the same disclaimer and license as
libpng-0.88, with the following individuals added to the list of
Contributing Authors:
- John Bowler
- Kevin Bracey
- Sam Bushell
- Magnus Holmgren
- Greg Roelofs
- Tom Tanner
+ John Bowler
+ Kevin Bracey
+ Sam Bushell
+ Magnus Holmgren
+ Greg Roelofs
+ Tom Tanner
-Some files in the "scripts" directory have other copyright owners
+Some files in the "scripts" directory have other copyright owners,
but are released under this license.
libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -71,63 +100,35 @@ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
For the purposes of this copyright and license, "Contributing Authors"
is defined as the following set of individuals:
- Andreas Dilger
- Dave Martindale
- Guy Eric Schalnat
- Paul Schmidt
- Tim Wegner
-
-The PNG Reference Library is supplied "AS IS". The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose. The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
+ Andreas Dilger
+ Dave Martindale
+ Guy Eric Schalnat
+ Paul Schmidt
+ Tim Wegner
+
+The PNG Reference Library is supplied "AS IS". The Contributing
+Authors and Group 42, Inc. disclaim all warranties, expressed or
+implied, including, without limitation, the warranties of
+merchantability and of fitness for any purpose. The Contributing
+Authors and Group 42, Inc. assume no liability for direct, indirect,
+incidental, special, exemplary, or consequential damages, which may
+result from the use of the PNG Reference Library, even if advised of
+the possibility of such damage.
Permission is hereby granted to use, copy, modify, and distribute this
source code, or portions hereof, for any purpose, without fee, subject
to the following restrictions:
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
- be misrepresented as being the original source.
-
- 3. This Copyright notice may not be removed or altered from any
- source or altered source distribution.
-
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products. If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
-
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
-
-TRADEMARK:
-
-The name "libpng" has not been registered by the Copyright owner
-as a trademark in any jurisdiction. However, because libpng has
-been distributed and maintained world-wide, continually since 1995,
-the Copyright owner claims "common-law trademark protection" in any
-jurisdiction where common-law trademark is recognized.
-
-OSI CERTIFICATION:
-
-Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
-a certification mark of the Open Source Initiative. OSI has not addressed
-the additional disclaimers inserted at version 1.0.7.
+ 1. The origin of this source code must not be misrepresented.
-EXPORT CONTROL:
+ 2. Altered versions must be plainly marked as such and must not
+ be misrepresented as being the original source.
-The Copyright owner believes that the Export Control Classification
-Number (ECCN) for libpng is EAR99, which means not subject to export
-controls or International Traffic in Arms Regulations (ITAR) because
-it is open source, publicly available software, that does not contain
-any encryption software. See the EAR, paragraphs 734.3(b)(3) and
-734.7(b).
+ 3. This Copyright notice may not be removed or altered from any
+ source or altered source distribution.
-Glenn Randers-Pehrson
-glennrp at users.sourceforge.net
-July 15, 2018
+The Contributing Authors and Group 42, Inc. specifically permit,
+without fee, and encourage the use of this source code as a component
+to supporting the PNG file format in commercial products. If you use
+this source code in a product, acknowledgment is not required but would
+be appreciated.
diff --git a/src/share/native/sun/awt/libpng/README b/src/share/native/sun/awt/libpng/README
index f098b27f39..cfc1f0e3dc 100644
--- a/src/share/native/sun/awt/libpng/README
+++ b/src/share/native/sun/awt/libpng/README
@@ -1,15 +1,16 @@
-README for libpng version 1.6.35 - July 15, 2018 (shared library 16.0)
-See the note about version numbers near the top of png.h
+README for libpng version 1.6.37 - April 14, 2019
+=================================================
+See the note about version numbers near the top of png.h.
See INSTALL for instructions on how to install libpng.
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
-libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
-or lpng*.7z or lpng*.zip if you want DOS-style line endings.
+libpng-*.tar.xz or if you want UNIX-style line endings in the text
+files, or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
-fact that it's the first release fool you. The libpng library has been in
-extensive use and testing since mid-1995. By late 1997 it had
+fact that it's the first release fool you. The libpng library has been
+in extensive use and testing since mid-1995. By late 1997 it had
finally gotten to the stage where there hadn't been significant
changes to the API in some time, and people have a bad feeling about
libraries with versions < 1.0. Version 1.0.0 was released in
@@ -60,59 +61,37 @@ the library action on the detection of chunk CRC errors. It is possible
to set different actions based on whether the CRC error occurred in a
critical or an ancillary chunk.
-The changes made to the library, and bugs fixed are based on discussions
-on the PNG-implement mailing list and not on material submitted
-privately to Guy, Andreas, or Glenn. They will forward any good
-suggestions to the list.
-
-For a detailed description on using libpng, read libpng-manual.txt. For
-examples of libpng in a program, see example.c and pngtest.c. For usage
-information and restrictions (what little they are) on libpng, see
-png.h. For a description on using zlib (the compression library used by
-libpng) and zlib's restrictions, see zlib.h
+For a detailed description on using libpng, read libpng-manual.txt.
+For examples of libpng in a program, see example.c and pngtest.c. For
+usage information and restrictions (what little they are) on libpng,
+see png.h. For a description on using zlib (the compression library
+used by libpng) and zlib's restrictions, see zlib.h
I have included a general makefile, as well as several machine and
-compiler specific ones, but you may have to modify one for your own needs.
+compiler specific ones, but you may have to modify one for your own
+needs.
You should use zlib 1.0.4 or later to run this, but it MAY work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib
versions which can cause the output of invalid compression streams for
-some images. You will definitely need zlib 1.0.4 or later if you are
-taking advantage of the MS-DOS "far" structure allocation for the small
-and medium memory models. You should also note that zlib is a
-compression library that is useful for more things than just PNG files.
-You can use zlib as a drop-in replacement for fread() and fwrite() if
-you are so inclined.
+some images.
+
+You should also note that zlib is a compression library that is useful
+for more things than just PNG files. You can use zlib as a drop-in
+replacement for fread() and fwrite(), if you are so inclined.
-zlib should be available at the same place that libpng is, or at zlib.net.
+zlib should be available at the same place that libpng is, or at
+https://zlib.net.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/pngdocs.html .
This code is currently being archived at libpng.sourceforge.io in the
-[DOWNLOAD] area, and at http://libpng.download/src . If you
-can't find it in any of those places, e-mail me, and I'll help you find it.
-
-I am not a lawyer, but I believe that the Export Control Classification
-Number (ECCN) for libpng is EAR99, which means not subject to export
-controls or International Traffic in Arms Regulations (ITAR) because it
-is open source, publicly available software, that does not contain any
-encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
-
-If you have any code changes, requests, problems, etc., please e-mail
-them to me. Also, I'd appreciate any make files or project files,
-and any modifications you needed to make to get libpng to compile,
-along with a #define variable to tell what compiler/system you are on.
-If you needed to add transformations to libpng, or wish libpng would
-provide the image in a different way, drop me a note (and code, if
-possible), so I can consider supporting the transformation.
-Finally, if you get any warning messages when compiling libpng
-(note: not zlib), and they are easy to fix, I'd appreciate the
-fix. Please mention "libpng" somewhere in the subject line. Thanks.
-
-This release was created and will be supported by myself (of course
-based in a large way on Guy's and Andreas' earlier work), and the PNG
+[DOWNLOAD] area, and at http://libpng.download/src .
+
+This release, based in a large way on Glenn's, Guy's and Andreas'
+earlier work, was created and will be supported by myself and the PNG
development group.
Send comments/corrections/commendations to png-mng-implement at
@@ -120,34 +99,21 @@ lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe).
-You can't reach Guy, the original libpng author, at the addresses
-given in previous versions of this document. He and Andreas will
-read mail addressed to the png-implement list, however.
-
-Please do not send general questions about PNG. Send them to
-png-mng-misc at lists.sf.net (subscription required; visit
+Send general questions about the PNG specification to png-mng-misc
+at lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
-subscribe). If you have a question about something
-in the PNG specification that is related to using libpng, send it
-to me. Send me any questions that start with "I was using libpng,
-and ...". If in doubt, send questions to me. I'll bounce them
-to others, if necessary.
-
-Please do not send suggestions on how to change PNG. We have
-been discussing PNG for twenty years now, and it is official and
-finished. If you have suggestions for libpng, however, I'll
-gladly listen. Even if your suggestion is not used immediately,
-it may be used later.
+subscribe).
Files in this distribution:
ANNOUNCE => Announcement of this version, with recent changes
+ AUTHORS => List of contributing authors
CHANGES => Description of changes between libpng versions
KNOWNBUG => List of known bugs and deficiencies
LICENSE => License to use and redistribute libpng
README => This file
TODO => Things not implemented in the current library
- Y2KINFO => Statement of Y2K compliance
+ TRADEMARK => Trademark information
example.c => Example code for using libpng functions
libpng.3 => manual page for libpng (includes libpng-manual.txt)
libpng-manual.txt => Description of libpng and its functions
@@ -208,15 +174,10 @@ Files in this distribution:
scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts)
-Good luck, and happy coding.
-
--Glenn Randers-Pehrson (current maintainer, since 1998)
- Internet: glennrp at users.sourceforge.net
-
--Andreas Eric Dilger (former maintainer, 1996-1997)
- Internet: adilger at enel.ucalgary.ca
- Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
+Good luck, and happy coding!
--Guy Eric Schalnat (original author and former maintainer, 1995-1996)
- (formerly of Group 42, Inc)
- Internet: gschal at infinet.com
+ * Cosmin Truta (current maintainer, since 2018)
+ * Glenn Randers-Pehrson (former maintainer, 1998-2018)
+ * Andreas Eric Dilger (former maintainer, 1996-1997)
+ * Guy Eric Schalnat (original author and former maintainer, 1995-1996)
+ (formerly of Group 42, Inc.)
diff --git a/src/share/native/sun/awt/libpng/png.c b/src/share/native/sun/awt/libpng/png.c
index 1a44c9c8cf..3740c3cd21 100644
--- a/src/share/native/sun/awt/libpng/png.c
+++ b/src/share/native/sun/awt/libpng/png.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -42,7 +42,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_35 Your_png_h_is_not_version_1_6_35;
+typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
@@ -764,7 +764,7 @@ png_save_int_32(png_bytep buf, png_int_32 i)
int PNGAPI
png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{
- static PNG_CONST char short_months[12][4] =
+ static const char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
@@ -842,20 +842,14 @@ png_get_copyright(png_const_structrp png_ptr)
#ifdef PNG_STRING_COPYRIGHT
return PNG_STRING_COPYRIGHT
#else
-# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.35 - July 15, 2018" PNG_STRING_NEWLINE \
+ "libpng version 1.6.37" PNG_STRING_NEWLINE \
+ "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
-# else
- return "libpng version 1.6.35 - July 15, 2018\
- Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\
- Copyright (c) 1996-1997 Andreas Dilger\
- Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
-# endif
#endif
}
@@ -1149,7 +1143,7 @@ png_colorspace_set_gamma(png_const_structrp png_ptr,
png_colorspacerp colorspace, png_fixed_point gAMA)
{
/* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is asymetrical it is
+ * occur. Since the fixed point representation is asymmetrical it is
* possible for 1/gamma to overflow the limit of 21474 and this means the
* gamma value must be at least 5/100000 and hence at most 20000.0. For
* safety the limits here are a little narrower. The values are 0.00016 to
@@ -3162,11 +3156,11 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
/* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are
- * done and just need to terminate the string. At
- * this point exp_b10==(-1) is effectively a flag - it got
- * to '-1' because of the decrement after outputting
- * the decimal point above (the exponent required is
- * *not* -1!)
+ * done and just need to terminate the string. At this
+ * point, exp_b10==(-1) is effectively a flag: it got
+ * to '-1' because of the decrement, after outputting
+ * the decimal point above. (The exponent required is
+ * *not* -1.)
*/
if (exp_b10 >= (-1) && exp_b10 <= 2)
{
@@ -4004,18 +3998,18 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value,
*/
static void
png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
/* Various values derived from 'shift': */
- PNG_CONST unsigned int num = 1U << (8U - shift);
+ unsigned int num = 1U << (8U - shift);
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* CSE the division and work round wacky GCC warnings (see the comments
* in png_gamma_8bit_correct for where these come from.)
*/
- PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
+ double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1);
#endif
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
- PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
+ unsigned int max = (1U << (16U - shift)) - 1U;
+ unsigned int max_by_2 = 1U << (15U - shift);
unsigned int i;
png_uint_16pp table = *ptable =
@@ -4081,10 +4075,10 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/
static void
png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
- PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
+ unsigned int shift, png_fixed_point gamma_val)
{
- PNG_CONST unsigned int num = 1U << (8U - shift);
- PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
+ unsigned int num = 1U << (8U - shift);
+ unsigned int max = (1U << (16U - shift))-1U;
unsigned int i;
png_uint_32 last;
@@ -4149,7 +4143,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/
static void
png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
- PNG_CONST png_fixed_point gamma_val)
+ png_fixed_point gamma_val)
{
unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
@@ -4622,8 +4616,7 @@ png_image_free(png_imagep image)
if (image != NULL && image->opaque != NULL &&
image->opaque->error_buf == NULL)
{
- /* Ignore errors here: */
- (void)png_safe_execute(image, png_image_free_function, image);
+ png_image_free_function(image);
image->opaque = NULL;
}
}
diff --git a/src/share/native/sun/awt/libpng/png.h b/src/share/native/sun/awt/libpng/png.h
index d3beb21c04..e5e87d3b81 100644
--- a/src/share/native/sun/awt/libpng/png.h
+++ b/src/share/native/sun/awt/libpng/png.h
@@ -29,68 +29,105 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.37 - April 14, 2019
*
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
- * This code is released under the libpng license (See LICENSE, below)
+ * This code is released under the libpng license. (See LICENSE, below.)
*
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.6.35, July 15, 2018:
- * Glenn Randers-Pehrson.
+ * libpng versions 0.97, January 1998, through 1.6.35, July 2018:
+ * Glenn Randers-Pehrson
+ * libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
+ * Cosmin Truta
* See also "Contributing Authors", below.
*/
/*
- * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
+ * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
+ * =========================================
+ *
+ * PNG Reference Library License version 2
+ * ---------------------------------------
+ *
+ * * Copyright (c) 1995-2019 The PNG Reference Library Authors.
+ * * Copyright (c) 2018-2019 Cosmin Truta.
+ * * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
+ * * Copyright (c) 1996-1997 Andreas Dilger.
+ * * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
+ *
+ * The software is supplied "as is", without warranty of any kind,
+ * express or implied, including, without limitation, the warranties
+ * of merchantability, fitness for a particular purpose, title, and
+ * non-infringement. In no event shall the Copyright owners, or
+ * anyone distributing the software, be liable for any damages or
+ * other liability, whether in contract, tort or otherwise, arising
+ * from, out of, or in connection with the software, or the use or
+ * other dealings in the software, even if advised of the possibility
+ * of such damage.
+ *
+ * Permission is hereby granted to use, copy, modify, and distribute
+ * this software, or portions hereof, for any purpose, without fee,
+ * subject to the following restrictions:
*
- * If you modify libpng you may insert additional notices immediately following
- * this sentence.
+ * 1. The origin of this software must not be misrepresented; you
+ * must not claim that you wrote the original software. If you
+ * use this software in a product, an acknowledgment in the product
+ * documentation would be appreciated, but is not required.
*
- * This code is released under the libpng license.
+ * 2. Altered source versions must be plainly marked as such, and must
+ * not be misrepresented as being the original software.
*
- * libpng versions 1.0.7, July 1, 2000 through 1.6.35, July 15, 2018 are
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
+ *
+ *
+ * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
+ * -----------------------------------------------------------------------
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors:
*
- * Simon-Pierre Cadieux
- * Eric S. Raymond
- * Mans Rullgard
- * Cosmin Truta
- * Gilles Vollant
- * James Yu
- * Mandar Sahastrabuddhe
- * Google Inc.
- * Vadim Barkov
+ * Simon-Pierre Cadieux
+ * Eric S. Raymond
+ * Mans Rullgard
+ * Cosmin Truta
+ * Gilles Vollant
+ * James Yu
+ * Mandar Sahastrabuddhe
+ * Google Inc.
+ * Vadim Barkov
*
* and with the following additions to the disclaimer:
*
- * There is no warranty against interference with your enjoyment of the
- * library or against infringement. There is no warranty that our
- * efforts or the library will fulfill any of your particular purposes
- * or needs. This library is provided with all faults, and the entire
- * risk of satisfactory quality, performance, accuracy, and effort is with
- * the user.
+ * There is no warranty against interference with your enjoyment of
+ * the library or against infringement. There is no warranty that our
+ * efforts or the library will fulfill any of your particular purposes
+ * or needs. This library is provided with all faults, and the entire
+ * risk of satisfactory quality, performance, accuracy, and effort is
+ * with the user.
*
* Some files in the "contrib" directory and some configure-generated
- * files that are distributed with libpng have other copyright owners and
+ * files that are distributed with libpng have other copyright owners, and
* are released under other open source licenses.
*
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and
- * license as libpng-0.96, with the following individuals added to the list
- * of Contributing Authors:
+ * license as libpng-0.96, with the following individuals added to the
+ * list of Contributing Authors:
*
- * Tom Lane
- * Glenn Randers-Pehrson
- * Willem van Schaik
+ * Tom Lane
+ * Glenn Randers-Pehrson
+ * Willem van Schaik
*
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
* Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
@@ -98,14 +135,14 @@
* libpng-0.88, with the following individuals added to the list of
* Contributing Authors:
*
- * John Bowler
- * Kevin Bracey
- * Sam Bushell
- * Magnus Holmgren
- * Greg Roelofs
- * Tom Tanner
+ * John Bowler
+ * Kevin Bracey
+ * Sam Bushell
+ * Magnus Holmgren
+ * Greg Roelofs
+ * Tom Tanner
*
- * Some files in the "scripts" directory have other copyright owners
+ * Some files in the "scripts" directory have other copyright owners,
* but are released under this license.
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
@@ -114,62 +151,49 @@
* For the purposes of this copyright and license, "Contributing Authors"
* is defined as the following set of individuals:
*
- * Andreas Dilger
- * Dave Martindale
- * Guy Eric Schalnat
- * Paul Schmidt
- * Tim Wegner
- *
- * The PNG Reference Library is supplied "AS IS". The Contributing Authors
- * and Group 42, Inc. disclaim all warranties, expressed or implied,
- * including, without limitation, the warranties of merchantability and of
- * fitness for any purpose. The Contributing Authors and Group 42, Inc.
- * assume no liability for direct, indirect, incidental, special, exemplary,
- * or consequential damages, which may result from the use of the PNG
- * Reference Library, even if advised of the possibility of such damage.
+ * Andreas Dilger
+ * Dave Martindale
+ * Guy Eric Schalnat
+ * Paul Schmidt
+ * Tim Wegner
+ *
+ * The PNG Reference Library is supplied "AS IS". The Contributing
+ * Authors and Group 42, Inc. disclaim all warranties, expressed or
+ * implied, including, without limitation, the warranties of
+ * merchantability and of fitness for any purpose. The Contributing
+ * Authors and Group 42, Inc. assume no liability for direct, indirect,
+ * incidental, special, exemplary, or consequential damages, which may
+ * result from the use of the PNG Reference Library, even if advised of
+ * the possibility of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject
* to the following restrictions:
*
- * 1. The origin of this source code must not be misrepresented.
+ * 1. The origin of this source code must not be misrepresented.
*
- * 2. Altered versions must be plainly marked as such and must not
- * be misrepresented as being the original source.
+ * 2. Altered versions must be plainly marked as such and must not
+ * be misrepresented as being the original source.
*
- * 3. This Copyright notice may not be removed or altered from any
- * source or altered source distribution.
+ * 3. This Copyright notice may not be removed or altered from any
+ * source or altered source distribution.
*
- * The Contributing Authors and Group 42, Inc. specifically permit, without
- * fee, and encourage the use of this source code as a component to
- * supporting the PNG file format in commercial products. If you use this
- * source code in a product, acknowledgment is not required but would be
- * appreciated.
+ * The Contributing Authors and Group 42, Inc. specifically permit,
+ * without fee, and encourage the use of this source code as a component
+ * to supporting the PNG file format in commercial products. If you use
+ * this source code in a product, acknowledgment is not required but would
+ * be appreciated.
*
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*
- * TRADEMARK:
+ * TRADEMARK
+ * =========
*
- * The name "libpng" has not been registered by the Copyright owner
+ * The name "libpng" has not been registered by the Copyright owners
* as a trademark in any jurisdiction. However, because libpng has
* been distributed and maintained world-wide, continually since 1995,
- * the Copyright owner claims "common-law trademark protection" in any
+ * the Copyright owners claim "common-law trademark protection" in any
* jurisdiction where common-law trademark is recognized.
- *
- * OSI CERTIFICATION:
- *
- * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- *
- * EXPORT CONTROL:
- *
- * The Copyright owner believes that the Export Control Classification
- * Number (ECCN) for libpng is EAR99, which means not subject to export
- * controls or International Traffic in Arms Regulations (ITAR) because
- * it is open source, publicly available software, that does not contain
- * any encryption software. See the EAR, paragraphs 734.3(b)(3) and
- * 734.7(b).
*/
/*
@@ -235,23 +259,25 @@
* 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
* 1.0.7 1 10007 (still compatible)
* ...
- * 1.0.19 10 10019 10.so.0.19[.0]
+ * 1.0.69 10 10069 10.so.0.69[.0]
+ * ...
+ * 1.2.59 13 10259 12.so.0.59[.0]
* ...
- * 1.2.59 13 10257 12.so.0.59[.0]
+ * 1.4.20 14 10420 14.so.0.20[.0]
* ...
- * 1.5.30 15 10527 15.so.15.30[.0]
+ * 1.5.30 15 10530 15.so.15.30[.0]
* ...
- * 1.6.35 16 10635 16.so.16.35[.0]
- *
- * Henceforth the source version will match the shared-library major
- * and minor numbers; the shared-library major version number will be
- * used for changes in backward compatibility, as it is intended. The
- * PNG_LIBPNG_VER macro, which is not used within libpng but is available
- * for applications, is an unsigned integer of the form xyyzz corresponding
- * to the source version x.y.z (leading zeros in y and z). Beta versions
- * were given the previous public release number plus a letter, until
- * version 1.0.6j; from then on they were given the upcoming public
- * release number plus "betaNN" or "rcNN".
+ * 1.6.37 16 10637 16.so.16.37[.0]
+ *
+ * Henceforth the source version will match the shared-library major and
+ * minor numbers; the shared-library major version number will be used for
+ * changes in backward compatibility, as it is intended.
+ * The PNG_LIBPNG_VER macro, which is not used within libpng but is
+ * available for applications, is an unsigned integer of the form XYYZZ
+ * corresponding to the source version X.Y.Z (leading zeros in Y and Z).
+ * Beta versions were given the previous public release number plus a
+ * letter, until version 1.0.6j; from then on they were given the upcoming
+ * public release number plus "betaNN" or "rcNN".
*
* Binary incompatibility exists only when applications make direct access
* to the info_ptr or png_ptr members through png.h, and the compiled
@@ -261,65 +287,8 @@
* in binary compatibility (e.g., when a new feature is added).
*
* See libpng.txt or libpng.3 for more information. The PNG specification
- * is available as a W3C Recommendation and as an ISO Specification,
- * <https://www.w3.org/TR/2003/REC-PNG-20031110/
- */
-
-/*
- * Y2K compliance in libpng:
- * =========================
- *
- * July 15, 2018
- *
- * Since the PNG Development group is an ad-hoc body, we can't make
- * an official declaration.
- *
- * This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.6.35 are Y2K compliant. It is my belief that
- * earlier versions were also Y2K compliant.
- *
- * Libpng only has two year fields. One is a 2-byte unsigned integer
- * that will hold years up to 65535. The other, which is deprecated,
- * holds the date in text format, and will hold years up to 9999.
- *
- * The integer is
- * "png_uint_16 year" in png_time_struct.
- *
- * The string is
- * "char time_buffer[29]" in png_struct. This is no longer used
- * in libpng-1.6.x and will be removed from libpng-1.7.0.
- *
- * There are seven time-related functions:
- * png.c: png_convert_to_rfc_1123_buffer() in png.c
- * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
- * png_convert_to_rfc_1152() in error prior to libpng-0.98)
- * png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
- * png_convert_from_time_t() in pngwrite.c
- * png_get_tIME() in pngget.c
- * png_handle_tIME() in pngrutil.c, called in pngread.c
- * png_set_tIME() in pngset.c
- * png_write_tIME() in pngwutil.c, called in pngwrite.c
- *
- * All handle dates properly in a Y2K environment. The
- * png_convert_from_time_t() function calls gmtime() to convert from system
- * clock time, which returns (year - 1900), which we properly convert to
- * the full 4-digit year. There is a possibility that libpng applications
- * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
- * function, or that they are incorrectly passing only a 2-digit year
- * instead of "year - 1900" into the png_convert_from_struct_tm() function,
- * but this is not under our control. The libpng documentation has always
- * stated that it works with 4-digit years, and the APIs have been
- * documented as such.
- *
- * The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
- * integer to hold the year, and can hold years as large as 65535.
- *
- * zlib, upon which libpng depends, is also Y2K compliant. It contains
- * no date-related code.
- *
- * Glenn Randers-Pehrson
- * libpng maintainer
- * PNG Development Group
+ * is available as a W3C Recommendation and as an ISO/IEC Standard; see
+ * <https://www.w3.org/TR/2003/REC-PNG-20031110/>
*/
#ifndef PNG_H
@@ -337,8 +306,8 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.35"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.35 - July 15, 2018\n"
+#define PNG_LIBPNG_VER_STRING "1.6.37"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -346,13 +315,12 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
-#define PNG_LIBPNG_VER_RELEASE 35
+#define PNG_LIBPNG_VER_RELEASE 37
-/* This should match the numeric part of the final component of
- * PNG_LIBPNG_VER_STRING, omitting any leading zero:
+/* This should be zero for a public release, or non-zero for a
+ * development version. [Deprecated]
*/
-
-#define PNG_LIBPNG_VER_BUILD 02
+#define PNG_LIBPNG_VER_BUILD 0
/* Release Status */
#define PNG_LIBPNG_BUILD_ALPHA 1
@@ -369,15 +337,16 @@
#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
PNG_LIBPNG_BUILD_PRIVATE */
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
-/* Careful here. At one time, Guy wanted to use 082, but that would be octal.
- * We must not include leading zeros.
- * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only
- * version 1.0.0 was mis-numbered 100 instead of 10000). From
- * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
+/* Careful here. At one time, Guy wanted to use 082, but that
+ * would be octal. We must not include leading zeros.
+ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here
+ * (only version 1.0.0 was mis-numbered 100 instead of 10000).
+ * From version 1.0.1 it is:
+ * XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
-#define PNG_LIBPNG_VER 10635 /* 1.6.35 */
+#define PNG_LIBPNG_VER 10637 /* 1.6.37 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -487,7 +456,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_35;
+typedef char* png_libpng_version_1_6_37;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -2041,12 +2010,12 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_bytep exif));
+ png_inforp info_ptr, png_bytep exif));
PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
- png_inforp info_ptr, const png_uint_32 num_exif, const png_bytep exif));
+ png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
#endif
#ifdef PNG_gAMA_SUPPORTED
@@ -2792,7 +2761,7 @@ typedef struct
*
* When the simplified API needs to convert between sRGB and linear colorspaces,
* the actual sRGB transfer curve defined in the sRGB specification (see the
- * article at https://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+ * article at <https://en.wikipedia.org/wiki/SRGB>) is used, not the gamma=1/2.2
* approximation used elsewhere in libpng.
*
* When an alpha channel is present it is expected to denote pixel coverage
@@ -2995,7 +2964,7 @@ typedef struct
* 'flags' field of png_image.
*/
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
- /* This indicates the the RGB values of the in-memory bitmap do not
+ /* This indicates that the RGB values of the in-memory bitmap do not
* correspond to the red, green and blue end-points defined by sRGB.
*/
diff --git a/src/share/native/sun/awt/libpng/pngconf.h b/src/share/native/sun/awt/libpng/pngconf.h
index b010164b13..e6c993b857 100644
--- a/src/share/native/sun/awt/libpng/pngconf.h
+++ b/src/share/native/sun/awt/libpng/pngconf.h
@@ -22,18 +22,19 @@
* questions.
*/
-/* pngconf.h - machine configurable file for libpng
+/* pngconf.h - machine-configurable file for libpng
*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * libpng version 1.6.35, July 15, 2018
+ * libpng version 1.6.37
*
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -85,14 +86,13 @@
#endif /* PNG_BUILDING_SYMBOL_TABLE */
-/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
- * PNG_NO_CONST; this is no longer supported except for data declarations which
- * apparently still cause problems in 2011 on some compilers.
+/* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
+ * using PNG_NO_CONST. This is no longer supported.
*/
#define PNG_CONST const /* backward compatibility only */
-/* This controls optimization of the reading of 16-bit and 32-bit values
- * from PNG files. It can be set on a per-app-file basis - it
+/* This controls optimization of the reading of 16-bit and 32-bit
+ * values from PNG files. It can be set on a per-app-file basis: it
* just changes whether a macro is used when the function is called.
* The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on.
diff --git a/src/share/native/sun/awt/libpng/pngdebug.h b/src/share/native/sun/awt/libpng/pngdebug.h
index f65bb8a3e0..8eb5400ea9 100644
--- a/src/share/native/sun/awt/libpng/pngdebug.h
+++ b/src/share/native/sun/awt/libpng/pngdebug.h
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.8 [December 19, 2013]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/src/share/native/sun/awt/libpng/pngerror.c b/src/share/native/sun/awt/libpng/pngerror.c
index 672fb35b0c..623735f06f 100644
--- a/src/share/native/sun/awt/libpng/pngerror.c
+++ b/src/share/native/sun/awt/libpng/pngerror.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.31 [July 27, 2017]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -453,7 +453,7 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
-static PNG_CONST char png_digit[16] = {
+static const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
@@ -913,7 +913,7 @@ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* An error is always logged here, overwriting anything (typically a warning)
@@ -948,7 +948,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{
- const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* A warning is only logged if there is no prior warning or error. */
diff --git a/src/share/native/sun/awt/libpng/pngget.c b/src/share/native/sun/awt/libpng/pngget.c
index 79a036ceb5..4e5f6c962a 100644
--- a/src/share/native/sun/awt/libpng/pngget.c
+++ b/src/share/native/sun/awt/libpng/pngget.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/src/share/native/sun/awt/libpng/pnginfo.h b/src/share/native/sun/awt/libpng/pnginfo.h
index 4317f2a16b..d241eaebff 100644
--- a/src/share/native/sun/awt/libpng/pnginfo.h
+++ b/src/share/native/sun/awt/libpng/pnginfo.h
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/src/share/native/sun/awt/libpng/pnglibconf.h b/src/share/native/sun/awt/libpng/pnglibconf.h
index ab1341507d..7cf81e122b 100644
--- a/src/share/native/sun/awt/libpng/pnglibconf.h
+++ b/src/share/native/sun/awt/libpng/pnglibconf.h
@@ -29,18 +29,16 @@
* THIS FILE WAS MODIFIED BY ORACLE, INC.
*/
-/* libpng STANDARD API DEFINITION */
-
/* pnglibconf.h - library build configuration */
/* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*/
+/* libpng version 1.6.37 */
-/* libpng version 1.6.35, July 15, 2018 */
-
-/* Copyright (c) 1998-2018 Glenn Randers-Pehrson */
+/* Copyright (c) 2018-2019 Cosmin Truta */
+/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
@@ -80,6 +78,8 @@
#define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
+/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
+/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED
@@ -118,6 +118,7 @@
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
+/*#undef PNG_READ_eXIf_SUPPORTED*/
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED
/*#undef PNG_READ_iCCP_SUPPORTED*/
@@ -187,6 +188,7 @@
/*#undef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED*/
/*#undef PNG_WRITE_bKGD_SUPPORTED*/
/*#undef PNG_WRITE_cHRM_SUPPORTED*/
+/*#undef PNG_WRITE_eXIf_SUPPORTED*/
/*#undef PNG_WRITE_gAMA_SUPPORTED*/
/*#undef PNG_WRITE_hIST_SUPPORTED*/
/*#undef PNG_WRITE_iCCP_SUPPORTED*/
@@ -204,6 +206,7 @@
/*#undef PNG_WRITE_zTXt_SUPPORTED*/
#define PNG_bKGD_SUPPORTED
#define PNG_cHRM_SUPPORTED
+/*#undef PNG_eXIf_SUPPORTED*/
#define PNG_gAMA_SUPPORTED
#define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED
@@ -241,7 +244,7 @@
#define PNG_USER_HEIGHT_MAX 8000
#define PNG_USER_WIDTH_MAX 8000
#define PNG_ZBUF_SIZE 8192
-#define PNG_ZLIB_VERNUM 0
+#define PNG_ZLIB_VERNUM 0 /* unknown */
#define PNG_Z_DEFAULT_COMPRESSION (-1)
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
#define PNG_Z_DEFAULT_STRATEGY 1
diff --git a/src/share/native/sun/awt/libpng/pngmem.c b/src/share/native/sun/awt/libpng/pngmem.c
index 51c826a31e..d5ad0735f3 100644
--- a/src/share/native/sun/awt/libpng/pngmem.c
+++ b/src/share/native/sun/awt/libpng/pngmem.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.26 [October 20, 2016]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/src/share/native/sun/awt/libpng/pngpread.c b/src/share/native/sun/awt/libpng/pngpread.c
index 7506ff9b42..a98b201325 100644
--- a/src/share/native/sun/awt/libpng/pngpread.c
+++ b/src/share/native/sun/awt/libpng/pngpread.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -1000,20 +1000,20 @@ png_read_push_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
- static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
diff --git a/src/share/native/sun/awt/libpng/pngpriv.h b/src/share/native/sun/awt/libpng/pngpriv.h
index b1f9994dae..5f70426030 100644
--- a/src/share/native/sun/awt/libpng/pngpriv.h
+++ b/src/share/native/sun/awt/libpng/pngpriv.h
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -202,7 +202,10 @@
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
-# define PNG_ARM_NEON_IMPLEMENTATION 2
+# if !defined(__aarch64__)
+ /* The assembler code currently does not work on ARM64 */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __aarch64__ */
# endif /* __ARM_NEON__ */
# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
@@ -298,6 +301,7 @@
#endif
+
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
* so PNG_BUILD_DLL must be set.
@@ -1564,10 +1568,10 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
#endif
PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
- const png_uint_32 chunk_name),PNG_EMPTY);
+ png_uint_32 chunk_name),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
- const png_uint_32 chunk_length),PNG_EMPTY);
+ png_uint_32 chunk_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
@@ -2144,6 +2148,29 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
png_const_charp key, png_bytep new_key), PNG_EMPTY);
+#if PNG_ARM_NEON_IMPLEMENTATION == 1
+PNG_INTERNAL_FUNCTION(void,
+ png_riffle_palette_neon,
+ (png_structrp),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_rgba8_neon,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,
+ png_do_expand_palette_rgb8_neon,
+ (png_structrp,
+ png_row_infop,
+ png_const_bytep,
+ const png_bytepp,
+ const png_bytepp),
+ PNG_EMPTY);
+#endif
+
/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
diff --git a/src/share/native/sun/awt/libpng/pngread.c b/src/share/native/sun/awt/libpng/pngread.c
index 6955be06c9..b558c5716f 100644
--- a/src/share/native/sun/awt/libpng/pngread.c
+++ b/src/share/native/sun/awt/libpng/pngread.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -1022,6 +1022,12 @@ png_read_destroy(png_structrp png_ptr)
png_ptr->chunk_list = NULL;
#endif
+#if defined(PNG_READ_EXPAND_SUPPORTED) && \
+ defined(PNG_ARM_NEON_IMPLEMENTATION)
+ png_free(png_ptr, png_ptr->riffled_palette);
+ png_ptr->riffled_palette = NULL;
+#endif
+
/* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
* callbacks are still set at this point. They are required to complete the
* destruction of the png_struct itself.
@@ -1649,7 +1655,7 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
* errors (which are unfortunately quite common.)
*/
{
- static PNG_CONST png_byte chunks_to_process[] = {
+ static const png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */
@@ -1786,9 +1792,9 @@ png_create_colormap_entry(png_image_read_control *display,
png_uint_32 alpha, int encoding)
{
png_imagep image = display->image;
- const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
- const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
(red != green || green != blue);
if (ip > 255)
@@ -1897,13 +1903,13 @@ png_create_colormap_entry(png_image_read_control *display,
/* Store the value. */
{
# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
- const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+ int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else
# define bgr 0
# endif
@@ -2113,11 +2119,11 @@ png_image_read_colormap(png_voidp argument)
{
png_image_read_control *display =
png_voidcast(png_image_read_control*, argument);
- const png_imagep image = display->image;
+ png_imagep image = display->image;
- const png_structrp png_ptr = image->opaque->png_ptr;
- const png_uint_32 output_format = image->format;
- const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_uint_32 output_format = image->format;
+ int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB;
unsigned int cmap_entries;
@@ -2830,7 +2836,7 @@ png_image_read_colormap(png_voidp argument)
unsigned int num_trans = png_ptr->num_trans;
png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
png_const_colorp colormap = png_ptr->palette;
- const int do_background = trans != NULL &&
+ int do_background = trans != NULL &&
(output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
unsigned int i;
@@ -3974,7 +3980,7 @@ png_image_read_direct(png_voidp argument)
*/
if (linear != 0)
{
- PNG_CONST png_uint_16 le = 0x0001;
+ png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr);
@@ -4136,7 +4142,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
* original PNG format because it may not occur in the output PNG format
* and libpng deals with the issues of reading the original.
*/
- const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+ unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
/* The following checks just the 'row_stride' calculation to ensure it
* fits in a signed 32-bit value. Because channels/components can be
@@ -4147,7 +4153,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
- const png_uint_32 png_row_stride = image->width * channels;
+ png_uint_32 png_row_stride = image->width * channels;
if (row_stride == 0)
row_stride = (png_int_32)/*SAFE*/png_row_stride;
diff --git a/src/share/native/sun/awt/libpng/pngrio.c b/src/share/native/sun/awt/libpng/pngrio.c
index 90d3abdb2a..961d010df4 100644
--- a/src/share/native/sun/awt/libpng/pngrio.c
+++ b/src/share/native/sun/awt/libpng/pngrio.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
diff --git a/src/share/native/sun/awt/libpng/pngrtran.c b/src/share/native/sun/awt/libpng/pngrtran.c
index e12d32d7c6..efe7135553 100644
--- a/src/share/native/sun/awt/libpng/pngrtran.c
+++ b/src/share/native/sun/awt/libpng/pngrtran.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -46,6 +46,17 @@
#include "pngpriv.h"
+#ifdef PNG_ARM_NEON_IMPLEMENTATION
+# if PNG_ARM_NEON_IMPLEMENTATION == 1
+# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
+# if defined(_MSC_VER) && defined(_M_ARM64)
+# include <arm64_neon.h>
+# else
+# include <arm_neon.h>
+# endif
+# endif
+#endif
+
#ifdef PNG_READ_SUPPORTED
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
@@ -1199,20 +1210,20 @@ png_init_palette_transformations(png_structrp png_ptr)
png_ptr->palette[png_ptr->background.index].blue;
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
- {
- if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
- {
- /* Invert the alpha channel (in tRNS) unless the pixels are
- * going to be expanded, in which case leave it for later
- */
- int i, istop = png_ptr->num_trans;
-
- for (i=0; i<istop; i++)
- png_ptr->trans_alpha[i] = (png_byte)(255 -
- png_ptr->trans_alpha[i]);
- }
- }
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ {
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
+ {
+ /* Invert the alpha channel (in tRNS) unless the pixels are
+ * going to be expanded, in which case leave it for later
+ */
+ int i, istop = png_ptr->num_trans;
+
+ for (i = 0; i < istop; i++)
+ png_ptr->trans_alpha[i] =
+ (png_byte)(255 - png_ptr->trans_alpha[i]);
+ }
+ }
#endif /* READ_INVERT_ALPHA */
}
} /* background expand and (therefore) no alpha association. */
@@ -3014,7 +3025,6 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
*/
static int
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
-
{
int rgb_error = 0;
@@ -3023,12 +3033,11 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
- PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
- PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
- PNG_CONST png_uint_32 bc = 32768 - rc - gc;
- PNG_CONST png_uint_32 row_width = row_info->width;
- PNG_CONST int have_alpha =
- (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
+ png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
+ png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
+ png_uint_32 bc = 32768 - rc - gc;
+ png_uint_32 row_width = row_info->width;
+ int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
if (row_info->bit_depth == 8)
{
@@ -4171,12 +4180,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
if (row_info->bit_depth == 8)
{
- PNG_CONST png_bytep table = png_ptr->gamma_from_1;
+ png_bytep table = png_ptr->gamma_from_1;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
/* The alpha channel is the last component: */
row += step - 1;
@@ -4190,13 +4198,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
else if (row_info->bit_depth == 16)
{
- PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1;
- PNG_CONST int gamma_shift = png_ptr->gamma_shift;
+ png_uint_16pp table = png_ptr->gamma_16_from_1;
+ int gamma_shift = png_ptr->gamma_shift;
if (table != NULL)
{
- PNG_CONST int step =
- (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
+ int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
/* The alpha channel is the last component: */
row += step - 2;
@@ -4227,8 +4234,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
* upon whether you supply trans and num_trans.
*/
static void
-png_do_expand_palette(png_row_infop row_info, png_bytep row,
- png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
+png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
+ png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
+ int num_trans)
{
int shift, value;
png_bytep sp, dp;
@@ -4332,14 +4340,27 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
sp = row + (size_t)row_width - 1;
dp = row + ((size_t)row_width << 2) - 1;
- for (i = 0; i < row_width; i++)
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if (png_ptr->riffled_palette != NULL)
+ {
+ /* The RGBA optimization works with png_ptr->bit_depth == 8
+ * but sometimes row_info->bit_depth has been changed to 8.
+ * In these cases, the palette hasn't been riffled.
+ */
+ i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
+ &sp, &dp);
+ }
+#else
+ PNG_UNUSED(png_ptr)
+#endif
+
+ for (; i < row_width; i++)
{
if ((int)(*sp) >= num_trans)
*dp-- = 0xff;
-
else
*dp-- = trans_alpha[*sp];
-
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
*dp-- = palette[*sp].red;
@@ -4356,8 +4377,15 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
{
sp = row + (size_t)row_width - 1;
dp = row + (size_t)(row_width * 3) - 1;
+ i = 0;
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
+ &sp, &dp);
+#else
+ PNG_UNUSED(png_ptr)
+#endif
- for (i = 0; i < row_width; i++)
+ for (; i < row_width; i++)
{
*dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green;
@@ -4771,7 +4799,19 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{
- png_do_expand_palette(row_info, png_ptr->row_buf + 1,
+#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
+ if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
+ {
+ if (png_ptr->riffled_palette == NULL)
+ {
+ /* Initialize the accelerated palette expansion. */
+ png_ptr->riffled_palette =
+ (png_bytep)png_malloc(png_ptr, 256 * 4);
+ png_riffle_palette_neon(png_ptr);
+ }
+ }
+#endif
+ png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
}
diff --git a/src/share/native/sun/awt/libpng/pngrutil.c b/src/share/native/sun/awt/libpng/pngrutil.c
index bf316efc53..5c6244116a 100644
--- a/src/share/native/sun/awt/libpng/pngrutil.c
+++ b/src/share/native/sun/awt/libpng/pngrutil.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -1489,8 +1489,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
/* We have the ICC profile header; do the basic header checks.
*/
- const png_uint_32 profile_length =
- png_get_uint_32(profile_header);
+ png_uint_32 profile_length = png_get_uint_32(profile_header);
if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
keyword, profile_length) != 0)
@@ -1507,8 +1506,8 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
* profile. The header check has already validated
* that none of this stuff will overflow.
*/
- const png_uint_32 tag_count = png_get_uint_32(
- profile_header+128);
+ png_uint_32 tag_count =
+ png_get_uint_32(profile_header + 128);
png_bytep profile = png_read_buffer(png_ptr,
profile_length, 2/*silent*/);
@@ -3160,7 +3159,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
*/
void /* PRIVATE */
-png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
+png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
int i;
png_uint_32 cn=chunk_name;
@@ -3179,7 +3178,7 @@ png_check_chunk_name(png_const_structrp png_ptr, const png_uint_32 chunk_name)
}
void /* PRIVATE */
-png_check_chunk_length(png_const_structrp png_ptr, const png_uint_32 length)
+png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
{
png_alloc_size_t limit = PNG_UINT_31_MAX;
@@ -3391,7 +3390,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
/* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
* then pass:
*/
- static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
+ static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
{
/* Little-endian byte masks for PACKSWAP */
{ S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
@@ -3402,7 +3401,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
/* display_mask has only three entries for the odd passes, so index by
* pass>>1.
*/
- static PNG_CONST png_uint_32 display_mask[2][3][3] =
+ static const png_uint_32 display_mask[2][3][3] =
{
/* Little-endian byte masks for PACKSWAP */
{ B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
@@ -3715,7 +3714,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Offset to next interlace block */
- static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_read_interlace");
if (row != NULL && row_info != NULL)
@@ -4357,16 +4356,16 @@ png_read_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
@@ -4422,16 +4421,16 @@ png_read_start_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
+ static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
+ static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
+ static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
+ static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
unsigned int max_pixel_depth;
size_t row_bytes;
diff --git a/src/share/native/sun/awt/libpng/pngset.c b/src/share/native/sun/awt/libpng/pngset.c
index 6802034f57..1b075795b6 100644
--- a/src/share/native/sun/awt/libpng/pngset.c
+++ b/src/share/native/sun/awt/libpng/pngset.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -165,7 +165,7 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_bytep eXIf_buf)
+ png_bytep eXIf_buf)
{
png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
PNG_UNUSED(info_ptr)
@@ -174,7 +174,7 @@ png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
- const png_uint_32 num_exif, const png_bytep eXIf_buf)
+ png_uint_32 num_exif, png_bytep eXIf_buf)
{
int i;
@@ -1427,7 +1427,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
/* Ignore all unknown chunks and all chunks recognized by
* libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
*/
- static PNG_CONST png_byte chunks_to_ignore[] = {
+ static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
101, 88, 73, 102, '\0', /* eXIf */
diff --git a/src/share/native/sun/awt/libpng/pngstruct.h b/src/share/native/sun/awt/libpng/pngstruct.h
index 62f1269003..1f53e0534a 100644
--- a/src/share/native/sun/awt/libpng/pngstruct.h
+++ b/src/share/native/sun/awt/libpng/pngstruct.h
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -420,6 +420,12 @@ struct png_struct_def
/* deleted in 1.5.5: rgb_to_gray_blue_coeff; */
#endif
+/* New member added in libpng-1.6.36 */
+#if defined(PNG_READ_EXPAND_SUPPORTED) && \
+ defined(PNG_ARM_NEON_IMPLEMENTATION)
+ png_bytep riffled_palette; /* buffer for accelerated palette expansion */
+#endif
+
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */
diff --git a/src/share/native/sun/awt/libpng/pngtrans.c b/src/share/native/sun/awt/libpng/pngtrans.c
index 2da23c8dbf..89a62191b6 100644
--- a/src/share/native/sun/awt/libpng/pngtrans.c
+++ b/src/share/native/sun/awt/libpng/pngtrans.c
@@ -29,10 +29,10 @@
* However, the following notice accompanied the original version of this
* file and, per its terms, should not be removed:
*
- * Last changed in libpng 1.6.35 [July 15, 2018]
+ * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
- * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
+ * Copyright (c) 1996-1997 Andreas Dilger
+ * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
@@ -373,7 +373,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-static PNG_CONST png_byte onebppswaptable[256] = {
+static const png_byte onebppswaptable[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
@@ -408,7 +408,7 @@ static PNG_CONST png_byte onebppswaptable[256] = {
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
-static PNG_CONST png_byte twobppswaptable[256] = {
+static const png_byte twobppswaptable[256] = {
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
@@ -443,7 +443,7 @@ static PNG_CONST png_byte twobppswaptable[256] = {
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
};
-static PNG_CONST png_byte fourbppswaptable[256] = {
+static const png_byte fourbppswaptable[256] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
diff --git a/src/share/native/sun/font/DrawGlyphList.c b/src/share/native/sun/font/DrawGlyphList.c
index 4626c47152..743f0b0a2f 100644
--- a/src/share/native/sun/font/DrawGlyphList.c
+++ b/src/share/native/sun/font/DrawGlyphList.c
@@ -533,6 +533,12 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist, jint fromGly
*/
if (subPixPos && len > 0) {
ginfo = (GlyphInfo*)imagePtrs[fromGlyph];
+ if (ginfo == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, glyphImages,
+ imagePtrs, JNI_ABORT);
+ free(gbv);
+ return (GlyphBlitVector*)NULL;
+ }
/* rowBytes==width tests if its a B&W or LCD glyph */
if (ginfo->width == ginfo->rowBytes) {
subPixPos = JNI_FALSE;
@@ -555,6 +561,12 @@ GlyphBlitVector* setupLCDBlitVector(JNIEnv *env, jobject glyphlist, jint fromGly
jfloat px, py;
ginfo = (GlyphInfo*)imagePtrs[g + fromGlyph];
+ if (ginfo == NULL) {
+ (*env)->ReleasePrimitiveArrayCritical(env, glyphImages,
+ imagePtrs, JNI_ABORT);
+ free(gbv);
+ return (GlyphBlitVector*)NULL;
+ }
gbv->glyphs[g].glyphInfo = ginfo;
gbv->glyphs[g].pixels = ginfo->image;
gbv->glyphs[g].width = ginfo->width;
diff --git a/src/share/native/sun/font/freetypeScaler.c b/src/share/native/sun/font/freetypeScaler.c
index a0dceee5c5..4a45aaadde 100644
--- a/src/share/native/sun/font/freetypeScaler.c
+++ b/src/share/native/sun/font/freetypeScaler.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, 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,6 +48,7 @@
#include FT_SIZES_H
#include FT_OUTLINE_H
#include FT_SYNTHESIS_H
+#include FT_MODULE_H
#include FT_LCD_FILTER_H
#ifndef DISABLE_FONTCONFIG
@@ -376,7 +377,31 @@ static unsigned long ReadTTFontFileFunc(FT_Stream stream,
jobject bBuffer;
int bread = 0;
- if (numBytes == 0) return 0;
+ /* A call with numBytes == 0 is a seek. It should return 0 if the
+ * seek position is within the file and non-zero otherwise.
+ * For all other cases, ie numBytes !=0, return the number of bytes
+ * actually read. This applies to truncated reads and also failed reads.
+ */
+
+ if (numBytes == 0) {
+ if (offset >= scalerInfo->fileSize) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ if (offset + numBytes < offset) {
+ return 0; // ft should not do this, but just in case.
+ }
+
+ if (offset >= scalerInfo->fileSize) {
+ return 0;
+ }
+
+ if (offset + numBytes > scalerInfo->fileSize) {
+ numBytes = scalerInfo->fileSize - offset;
+ }
/* Large reads will bypass the cache and data copying */
if (numBytes > FILEDATACACHESIZE) {
@@ -386,7 +411,11 @@ static unsigned long ReadTTFontFileFunc(FT_Stream stream,
scalerInfo->font2D,
sunFontIDs.ttReadBlockMID,
bBuffer, offset, numBytes);
- return bread;
+ if (bread < 0) {
+ return 0;
+ } else {
+ return bread;
+ }
} else {
/* We probably hit bug bug 4845371. For reasons that
* are currently unclear, the call stacks after the initial
@@ -401,9 +430,18 @@ static unsigned long ReadTTFontFileFunc(FT_Stream stream,
(*env)->CallObjectMethod(env, scalerInfo->font2D,
sunFontIDs.ttReadBytesMID,
offset, numBytes);
- (*env)->GetByteArrayRegion(env, byteArray,
- 0, numBytes, (jbyte*)destBuffer);
- return numBytes;
+ /* If there's an OutofMemoryError then byteArray will be null */
+ if (byteArray == NULL) {
+ return 0;
+ } else {
+ jsize len = (*env)->GetArrayLength(env, byteArray);
+ if (len < numBytes) {
+ numBytes = len; // don't get more bytes than there are ..
+ }
+ (*env)->GetByteArrayRegion(env, byteArray,
+ 0, numBytes, (jbyte*)destBuffer);
+ return numBytes;
+ }
}
} /* Do we have a cache hit? */
else if (scalerInfo->fontDataOffset <= offset &&
@@ -425,11 +463,62 @@ static unsigned long ReadTTFontFileFunc(FT_Stream stream,
sunFontIDs.ttReadBlockMID,
bBuffer, offset,
scalerInfo->fontDataLength);
+ if (bread <= 0) {
+ return 0;
+ } else if (bread < numBytes) {
+ numBytes = bread;
+ }
memcpy(destBuffer, scalerInfo->fontData, numBytes);
return numBytes;
}
}
+typedef FT_Error (*FT_Prop_Set_Func)(FT_Library library,
+ const FT_String* module_name,
+ const FT_String* property_name,
+ const void* value );
+
+/**
+ * Prefer the older v35 freetype byte code interpreter.
+ */
+static void setInterpreterVersion(FT_Library library) {
+
+ char* props = getenv("FREETYPE_PROPERTIES");
+ int version = 35;
+ const char* module = "truetype";
+ const char* property = "interpreter-version";
+
+ /* If some one is setting this, don't override it */
+ if (props != NULL && strstr(property, props)) {
+ return;
+ }
+ /*
+ * FT_Property_Set was introduced in 2.4.11.
+ * Some older supported Linux OSes may not include it so look
+ * this up dynamically.
+ * And if its not available it doesn't matter, since the reason
+ * we need it dates from 2.7.
+ * On Windows & Mac the library is always bundled so it is safe
+ * to use directly in those cases.
+ */
+#if defined(_WIN32) || defined(__APPLE__)
+ FT_Property_Set(library, module, property, (void*)(&version));
+#else
+ void *lib = dlopen("libfreetype.so", RTLD_LOCAL|RTLD_LAZY);
+ if (lib == NULL) {
+ lib = dlopen("libfreetype.so.6", RTLD_LOCAL|RTLD_LAZY);
+ if (lib == NULL) {
+ return;
+ }
+ }
+ FT_Prop_Set_Func func = (FT_Prop_Set_Func)dlsym(lib, "FT_Property_Set");
+ if (func != NULL) {
+ func(library, module, property, (void*)(&version));
+ }
+ dlclose(lib);
+#endif
+}
+
/*
* Class: sun_font_FreetypeFontScaler
* Method: initNativeScaler
@@ -469,6 +558,7 @@ Java_sun_font_FreetypeFontScaler_initNativeScaler(
free(scalerInfo);
return 0;
}
+ setInterpreterVersion(scalerInfo->library);
#define TYPE1_FROM_JAVA 2
@@ -856,10 +946,18 @@ static int setupFTContext(JNIEnv *env, jobject font2D, FTScalerInfo *scalerInfo,
return 0;
}
-/* ftsynth.c uses (0x10000, 0x06000, 0x0, 0x10000) matrix to get oblique
- outline. Therefore x coordinate will change by 0x06000*y.
- Note that y coordinate does not change. */
-#define OBLIQUE_MODIFIER(y) (context->doItalize ? ((y)*6/16) : 0)
+/* ftsynth.c uses (0x10000, 0x0366A, 0x0, 0x10000) matrix to get oblique
+ outline. Therefore x coordinate will change by 0x0366A*y.
+ Note that y coordinate does not change. These values are based on
+ libfreetype version 2.9.1. */
+#define OBLIQUE_MODIFIER(y) (context->doItalize ? ((y)*0x366A/0x10000) : 0)
+
+/* FT_GlyphSlot_Embolden (ftsynth.c) uses FT_MulFix(units_per_EM, y_scale) / 24
+ * strength value when glyph format is FT_GLYPH_FORMAT_OUTLINE. This value has
+ * been taken from libfreetype version 2.6 and remain valid at least up to
+ * 2.9.1. */
+#define BOLD_MODIFIER(units_per_EM, y_scale) \
+ (context->doBold ? FT_MulFix(units_per_EM, y_scale) / 24 : 0)
/*
* Class: sun_font_FreetypeFontScaler
@@ -938,7 +1036,9 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative(
/* max advance */
mx = (jfloat) FT26Dot6ToFloat(
scalerInfo->face->size->metrics.max_advance +
- OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height));
+ OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height) +
+ BOLD_MODIFIER(scalerInfo->face->units_per_EM,
+ scalerInfo->face->size->metrics.y_scale));
my = 0;
// apply transformation matrix
@@ -987,16 +1087,17 @@ Java_sun_font_FreetypeFontScaler_getGlyphAdvanceNative(
to avoid unnecesary work with bitmaps. */
GlyphInfo *info;
- jfloat advance;
+ jfloat advance = 0.0f;
jlong image;
image = Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
env, scaler, font2D, pScalerContext, pScaler, glyphCode);
info = (GlyphInfo*) jlong_to_ptr(image);
- advance = info->advanceX;
-
- free(info);
+ if (info != NULL) {
+ advance = info->advanceX;
+ free(info);
+ }
return advance;
}
@@ -1134,6 +1235,13 @@ static void CopyFTSubpixelVToSubpixel(const void* srcImage, int srcRowBytes,
}
+/* JDK does not use glyph images for fonts with a
+ * pixel size > 100 (see THRESHOLD in OutlineTextRenderer.java)
+ * so if the glyph bitmap image dimension is > 1024 pixels,
+ * something is up.
+ */
+#define MAX_GLYPH_DIM 1024
+
/*
* Class: sun_font_FreetypeFontScaler
* Method: getGlyphImageNative
@@ -1228,11 +1336,28 @@ Java_sun_font_FreetypeFontScaler_getGlyphImageNative(
/* generate bitmap if it is not done yet
e.g. if algorithmic styling is performed and style was added to outline */
if (ftglyph->format == FT_GLYPH_FORMAT_OUTLINE) {
- FT_Render_Glyph(ftglyph, context->renderFlags);
+ FT_BBox bbox;
+ int w, h;
+ FT_Outline_Get_CBox(&(ftglyph->outline), &bbox);
+ w = (int)((bbox.xMax>>6)-(bbox.xMin>>6));
+ h = (int)((bbox.yMax>>6)-(bbox.yMin>>6));
+ if (w > MAX_GLYPH_DIM || h > MAX_GLYPH_DIM) {
+ glyphInfo = getNullGlyphImage();
+ return ptr_to_jlong(glyphInfo);
+ }
+ error = FT_Render_Glyph(ftglyph, context->renderFlags);
+ if (error != 0) {
+ return ptr_to_jlong(getNullGlyphImage());
+ }
}
width = (UInt16) ftglyph->bitmap.width;
height = (UInt16) ftglyph->bitmap.rows;
+ if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) {
+ glyphInfo = getNullGlyphImage();
+ return ptr_to_jlong(glyphInfo);
+ }
+
imageSize = width*height;
glyphInfo = (GlyphInfo*) malloc(sizeof(GlyphInfo) + imageSize);
diff --git a/src/share/native/sun/font/hb-jdk-font.cpp b/src/share/native/sun/font/hb-jdk-font.cpp
index 03ecdb2e24..15f8cf714c 100644
--- a/src/share/native/sun/font/hb-jdk-font.cpp
+++ b/src/share/native/sun/font/hb-jdk-font.cpp
@@ -27,9 +27,6 @@
#include "sun_font_Font2D.h"
#include "hb.h"
#include "hb-jdk.h"
-#ifdef MACOSX
-#include "hb-coretext.h"
-#endif
#include <stdlib.h>
#if defined(__GNUC__) && __GNUC__ >= 4
@@ -331,12 +328,6 @@ reference_table(hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data) {
* Signature: (ZJ)J
*/
JNIEXPORT jlong JNICALL Java_sun_font_Font2D_createHarfbuzzFace(JNIEnv *env, jobject font2D, jboolean aat, jlong platformFontPtr) {
-#ifdef MACOSX
- if (aat && platformFontPtr) {
- hb_face_t *face = hb_coretext_face_create((CGFontRef)platformFontPtr);
- return ptr_to_jlong(face);
- }
-#endif
Font2DPtr *fi = (Font2DPtr*)malloc(sizeof(Font2DPtr));
if (!fi) {
return 0;
@@ -375,29 +366,12 @@ static hb_font_t* _hb_jdk_font_create(hb_face_t* face,
return font;
}
-#ifdef MACOSX
-static hb_font_t* _hb_jdk_ct_font_create(hb_face_t* face, JDKFontInfo *jdkFontInfo) {
-
- hb_font_t *font = NULL;
- font = hb_font_create(face);
- hb_font_set_scale(font,
- HBFloatToFixed(jdkFontInfo->ptSize),
- HBFloatToFixed(jdkFontInfo->ptSize));
- return font;
-}
-#endif
-
hb_font_t* hb_jdk_font_create(hb_face_t* hbface,
JDKFontInfo *jdkFontInfo,
hb_destroy_func_t destroy) {
hb_font_t* font = NULL;
-#ifdef MACOSX
- if (jdkFontInfo->aat && jdkFontInfo->nativeFont) {
- font = _hb_jdk_ct_font_create(hbface, jdkFontInfo);
- }
-#endif
if (font == NULL) {
font = _hb_jdk_font_create(hbface, jdkFontInfo, destroy);
}
diff --git a/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp b/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp
index f296e89d3d..d27afeae18 100644
--- a/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp
+++ b/src/share/native/sun/font/layout/AlternateSubstSubtables.cpp
@@ -42,6 +42,10 @@ U_NAMESPACE_BEGIN
le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSubstitutionSubtable> &base,
GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
// NOTE: For now, we'll just pick the first alternative...
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
@@ -50,7 +54,13 @@ le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSu
le_uint16 altSetCount = SWAPW(alternateSetCount);
if (coverageIndex < altSetCount) {
- Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]);
+ const LEReferenceToArrayOf<Offset>
+ arrayRef(base, success, alternateSetTableOffsetArray, altSetCount);
+ if (!LE_SUCCESS(success)) return 0;
+
+ Offset alternateSetTableOffset = SWAPW(arrayRef.getObject(coverageIndex, success));
+ if (!LE_SUCCESS(success)) return 0;
+
const LEReferenceTo<AlternateSetTable> alternateSetTable(base, success,
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset));
if (!LE_SUCCESS(success)) return 0;
diff --git a/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp b/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp
index 0f230f12e7..44c2015a90 100644
--- a/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp
+++ b/src/share/native/sun/font/layout/CursiveAttachmentSubtables.cpp
@@ -41,6 +41,10 @@ U_NAMESPACE_BEGIN
le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyphID = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
le_uint16 eeCount = SWAPW(entryExitCount);
diff --git a/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp b/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp
index 5520940957..48cdbf49f6 100644
--- a/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp
+++ b/src/share/native/sun/font/layout/LigatureSubstSubtables.cpp
@@ -42,6 +42,10 @@ U_NAMESPACE_BEGIN
le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
diff --git a/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp b/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp
index 086da91629..713de9a603 100644
--- a/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp
+++ b/src/share/native/sun/font/layout/MarkToBasePosnSubtables.cpp
@@ -53,6 +53,10 @@ LEGlyphID MarkToBasePositioningSubtable::findBaseGlyph(GlyphIterator *glyphItera
le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
@@ -80,6 +84,9 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
// FIXME: We probably don't want to find a base glyph before a previous ligature...
GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/));
LEGlyphID baseGlyph = findBaseGlyph(&baseIterator);
+ if (baseGlyph == 0xFFFF) {
+ return 0;
+ }
le_int32 baseCoverage = getBaseCoverage(base, (LEGlyphID) baseGlyph, success);
LEReferenceTo<BaseArray> baseArray(base, success, (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset)));
if(LE_FAILURE(success)) return 0;
diff --git a/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp b/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp
index 2515b8afb5..106d1a9a49 100644
--- a/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp
+++ b/src/share/native/sun/font/layout/MarkToLigaturePosnSubtables.cpp
@@ -52,6 +52,10 @@ LEGlyphID MarkToLigaturePositioningSubtable::findLigatureGlyph(GlyphIterator *gl
le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
@@ -81,6 +85,9 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
// FIXME: we probably don't want to find a ligature before a previous base glyph...
GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
+ if (ligatureGlyph == 0xFFFF) {
+ return 0;
+ }
le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success);
LEReferenceTo<LigatureArray> ligatureArray(base, success, SWAPW(baseArrayOffset));
if (LE_FAILURE(success)) { return 0; }
diff --git a/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp b/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp
index 4ed835453a..4648eb7ef7 100644
--- a/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp
+++ b/src/share/native/sun/font/layout/MarkToMarkPosnSubtables.cpp
@@ -53,6 +53,10 @@ LEGlyphID MarkToMarkPositioningSubtable::findMark2Glyph(GlyphIterator *glyphIter
le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID markGlyph = glyphIterator->getCurrGlyphID();
le_int32 markCoverage = getGlyphCoverage(base, (LEGlyphID) markGlyph, success);
@@ -81,6 +85,9 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
GlyphIterator mark2Iterator(*glyphIterator);
LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator);
+ if (mark2Glyph == 0xFFFF) {
+ return 0;
+ }
le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success);
LEReferenceTo<Mark2Array> mark2Array(base, success, (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset)));
if(LE_FAILURE(success)) return 0;
diff --git a/src/share/native/sun/font/layout/MorphTables.cpp b/src/share/native/sun/font/layout/MorphTables.cpp
index 152b94774b..cfbb825927 100644
--- a/src/share/native/sun/font/layout/MorphTables.cpp
+++ b/src/share/native/sun/font/layout/MorphTables.cpp
@@ -46,8 +46,10 @@ U_NAMESPACE_BEGIN
void MorphTableHeader::process(const LETableReference &base, LEGlyphStorage &glyphStorage, LEErrorCode &success) const
{
- le_uint32 chainCount = SWAPL(this->nChains);
- LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header
+ if (LE_FAILURE(success)) return;
+
+ le_uint32 chainCount = SWAPL(this->nChains);
+ LEReferenceTo<ChainHeader> chainHeader(base, success, chains); // moving header
LEReferenceToArrayOf<ChainHeader> chainHeaderArray(base, success, chains, chainCount);
le_uint32 chain;
diff --git a/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp b/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp
index b4c9122c5e..a02894954f 100644
--- a/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp
+++ b/src/share/native/sun/font/layout/OpenTypeLayoutEngine.cpp
@@ -543,7 +543,7 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
yAdjust += yKerning;
#endif
- for (le_int32 base = i; base >= 0; base = adjustments->getBaseOffset(base)) {
+ for (le_int32 base = i; base >= 0 && base < glyphCount; base = adjustments->getBaseOffset(base)) {
xPlacement += adjustments->getXPlacement(base);
yPlacement += adjustments->getYPlacement(base);
}
diff --git a/src/share/native/sun/font/layout/PairPositioningSubtables.cpp b/src/share/native/sun/font/layout/PairPositioningSubtables.cpp
index 41922b7faf..5cb30d37af 100644
--- a/src/share/native/sun/font/layout/PairPositioningSubtables.cpp
+++ b/src/share/native/sun/font/layout/PairPositioningSubtables.cpp
@@ -43,6 +43,10 @@ U_NAMESPACE_BEGIN
le_uint32 PairPositioningSubtable::process(const LEReferenceTo<PairPositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
switch(SWAPW(subtableFormat))
{
case 0:
@@ -74,6 +78,10 @@ le_uint32 PairPositioningSubtable::process(const LEReferenceTo<PairPositioningSu
le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
GlyphIterator tempIterator(*glyphIterator);
@@ -123,6 +131,10 @@ le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositi
le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
diff --git a/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp b/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp
index a8b8d0c64c..18523574c1 100644
--- a/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp
+++ b/src/share/native/sun/font/layout/SegmentArrayProcessor.cpp
@@ -59,6 +59,8 @@ SegmentArrayProcessor::~SegmentArrayProcessor()
void SegmentArrayProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
const LookupSegment *segments = segmentArrayLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
diff --git a/src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp b/src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp
index 89222a0cdf..ca73c053eb 100644
--- a/src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp
+++ b/src/share/native/sun/font/layout/SegmentArrayProcessor2.cpp
@@ -59,6 +59,8 @@ SegmentArrayProcessor2::~SegmentArrayProcessor2()
void SegmentArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
const LookupSegment *segments = segmentArrayLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
diff --git a/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp b/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp
index 42866a5473..bbbe145603 100644
--- a/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp
+++ b/src/share/native/sun/font/layout/SegmentSingleProcessor.cpp
@@ -59,6 +59,8 @@ SegmentSingleProcessor::~SegmentSingleProcessor()
void SegmentSingleProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
const LookupSegment *segments = segmentSingleLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
diff --git a/src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp b/src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp
index 5572783518..d6b182289e 100644
--- a/src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp
+++ b/src/share/native/sun/font/layout/SegmentSingleProcessor2.cpp
@@ -60,6 +60,8 @@ SegmentSingleProcessor2::~SegmentSingleProcessor2()
void SegmentSingleProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
const LookupSegment *segments = segmentSingleLookupTable->segments;
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
diff --git a/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp b/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp
index 1aa71b002b..749daa082b 100644
--- a/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp
+++ b/src/share/native/sun/font/layout/SimpleArrayProcessor.cpp
@@ -59,6 +59,8 @@ SimpleArrayProcessor::~SimpleArrayProcessor()
void SimpleArrayProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
le_int32 glyphCount = glyphStorage.getGlyphCount();
le_int32 glyph;
diff --git a/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp b/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp
index fd912b4481..4d32e3a4c8 100644
--- a/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp
+++ b/src/share/native/sun/font/layout/SinglePositioningSubtables.cpp
@@ -42,6 +42,10 @@ U_NAMESPACE_BEGIN
le_uint32 SinglePositioningSubtable::process(const LEReferenceTo<SinglePositioningSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
switch(SWAPW(subtableFormat))
{
case 0:
@@ -68,6 +72,10 @@ le_uint32 SinglePositioningSubtable::process(const LEReferenceTo<SinglePositioni
le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
@@ -85,6 +93,10 @@ le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePo
le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePositioningFormat2Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int16 coverageIndex = (le_int16) getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
diff --git a/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp b/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp
index ccbc0523d3..81f7a28a1e 100644
--- a/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp
+++ b/src/share/native/sun/font/layout/SingleSubstitutionSubtables.cpp
@@ -41,6 +41,10 @@ U_NAMESPACE_BEGIN
le_uint32 SingleSubstitutionSubtable::process(const LEReferenceTo<SingleSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
switch(SWAPW(subtableFormat))
{
case 0:
@@ -67,6 +71,10 @@ le_uint32 SingleSubstitutionSubtable::process(const LEReferenceTo<SingleSubstitu
le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleSubstitutionFormat1Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
@@ -88,6 +96,10 @@ le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleS
le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleSubstitutionFormat2Subtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{
+ if (LE_FAILURE(success)) {
+ return 0;
+ }
+
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (LE_FAILURE(success)) {
diff --git a/src/share/native/sun/font/layout/SingleTableProcessor.cpp b/src/share/native/sun/font/layout/SingleTableProcessor.cpp
index e7c7c868be..b613c5a667 100644
--- a/src/share/native/sun/font/layout/SingleTableProcessor.cpp
+++ b/src/share/native/sun/font/layout/SingleTableProcessor.cpp
@@ -59,6 +59,8 @@ SingleTableProcessor::~SingleTableProcessor()
void SingleTableProcessor::process(LEGlyphStorage &glyphStorage, LEErrorCode &success)
{
+ if (LE_FAILURE(success)) return;
+
const LookupSingle *entries = singleTableLookupTable->entries;
le_int32 glyph;
le_int32 glyphCount = glyphStorage.getGlyphCount();
diff --git a/src/share/native/sun/java2d/cmm/lcms/cmsxform.c b/src/share/native/sun/java2d/cmm/lcms/cmsxform.c
index 77d54804a4..007f770b67 100644
--- a/src/share/native/sun/java2d/cmm/lcms/cmsxform.c
+++ b/src/share/native/sun/java2d/cmm/lcms/cmsxform.c
@@ -836,7 +836,7 @@ _cmsTRANSFORM* AllocEmptyTransform(cmsContext ContextID, cmsPipeline* lut,
// Save the day? (Ignore the warning)
if (Plugin->OldXform) {
- p->OldXform = (_cmsTransformFn) p->xform;
+ p->OldXform = (_cmsTransformFn)(void*) p->xform;
p->xform = _cmsTransform2toTransformAdaptor;
}
diff --git a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h
index 0249dae346..96651246d3 100644
--- a/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h
+++ b/src/share/native/sun/java2d/loops/GraphicsPrimitiveMgr.h
@@ -489,6 +489,8 @@ extern struct _CompositeTypes {
#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, \
((ptrdiff_t)(y))*(yinc) + \
((ptrdiff_t)(x))*(xinc))
+#define PtrPixelsRow(p, y, scanStride) PtrAddBytes(p, \
+ ((intptr_t) (y)) * (scanStride))
/*
* The function to call with an array of NativePrimitive structures
diff --git a/src/share/native/sun/java2d/loops/LoopMacros.h b/src/share/native/sun/java2d/loops/LoopMacros.h
index 370d024966..e4c634c699 100644
--- a/src/share/native/sun/java2d/loops/LoopMacros.h
+++ b/src/share/native/sun/java2d/loops/LoopMacros.h
@@ -137,7 +137,7 @@
do { \
juint w = WIDTH; \
jint tmpsxloc = SXLOC; \
- SRCPTR = PtrAddBytes(SRCBASE, ((SYLOC >> SHIFT) * srcScan)); \
+ SRCPTR = PtrPixelsRow(SRCBASE, (SYLOC >> SHIFT), srcScan); \
Init ## DSTTYPE ## StoreVarsX(DSTPREFIX, DSTINFO); \
do { \
jint XVAR = (tmpsxloc >> SHIFT); \
@@ -2015,7 +2015,7 @@ void NAME_TRANSFORMHELPER_NN(SRC)(SurfaceDataRasInfo *pSrcInfo, \
\
Init ## SRC ## LoadVars(SrcRead, pSrcInfo); \
while (pRGB < pEnd) { \
- SRC ## DataType *pRow = PtrAddBytes(pBase, WholeOfLong(ylong) * scan); \
+ SRC ## DataType *pRow = PtrPixelsRow(pBase, WholeOfLong(ylong), scan); \
Copy ## SRC ## ToIntArgbPre(pRGB, 0, \
SrcRead, pRow, WholeOfLong(xlong)); \
pRGB++; \
@@ -2063,7 +2063,7 @@ void NAME_TRANSFORMHELPER_BL(SRC)(SurfaceDataRasInfo *pSrcInfo, \
ydelta &= scan; \
\
xwhole += cx; \
- pRow = PtrAddBytes(pSrcInfo->rasBase, (ywhole + cy) * scan); \
+ pRow = PtrPixelsRow(pSrcInfo->rasBase, (ywhole + cy), scan); \
Copy ## SRC ## ToIntArgbPre(pRGB, 0, SrcRead, pRow, xwhole); \
Copy ## SRC ## ToIntArgbPre(pRGB, 1, SrcRead, pRow, xwhole+xdelta); \
pRow = PtrAddBytes(pRow, ydelta); \
@@ -2121,7 +2121,7 @@ void NAME_TRANSFORMHELPER_BC(SRC)(SurfaceDataRasInfo *pSrcInfo, \
ydelta1 += (isneg & -scan); \
\
xwhole += cx; \
- pRow = PtrAddBytes(pSrcInfo->rasBase, (ywhole + cy) * scan); \
+ pRow = PtrPixelsRow(pSrcInfo->rasBase, (ywhole + cy), scan); \
pRow = PtrAddBytes(pRow, ydelta0); \
Copy ## SRC ## ToIntArgbPre(pRGB, 0, SrcRead, pRow, xwhole+xdelta0); \
Copy ## SRC ## ToIntArgbPre(pRGB, 1, SrcRead, pRow, xwhole ); \
diff --git a/src/share/native/sun/java2d/opengl/OGLBlitLoops.c b/src/share/native/sun/java2d/opengl/OGLBlitLoops.c
index c96791f76c..4976e3cdaa 100644
--- a/src/share/native/sun/java2d/opengl/OGLBlitLoops.c
+++ b/src/share/native/sun/java2d/opengl/OGLBlitLoops.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, 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
@@ -180,6 +180,7 @@ OGLBlitSwToSurface(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2)
{
GLfloat scalex, scaley;
+ GLvoid *pSrc;
scalex = ((GLfloat)(dx2-dx1)) / (sx2-sx1);
scaley = ((GLfloat)(dy2-dy1)) / (sy2-sy1);
@@ -208,21 +209,22 @@ OGLBlitSwToSurface(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
j2d_glPixelZoom(scalex, -scaley);
+ pSrc = PtrCoord(srcInfo->rasBase, sx1, srcInfo->pixelStride,
+ sy1, srcInfo->scanStride);
+
// in case pixel stride is not a multiple of scanline stride the copy
// has to be done line by line (see 6207877)
if (srcInfo->scanStride % srcInfo->pixelStride != 0) {
jint width = sx2-sx1;
jint height = sy2-sy1;
- GLvoid *pSrc = srcInfo->rasBase;
-
while (height > 0) {
j2d_glDrawPixels(width, 1, pf->format, pf->type, pSrc);
- j2d_glBitmap(0, 0, 0, 0, (GLfloat)0, (GLfloat)-1, NULL);
+ j2d_glBitmap(0, 0, 0, 0, (GLfloat)0, (GLfloat)-scaley, NULL);
pSrc = PtrAddBytes(pSrc, srcInfo->scanStride);
height--;
}
} else {
- j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, srcInfo->rasBase);
+ j2d_glDrawPixels(sx2-sx1, sy2-sy1, pf->format, pf->type, pSrc);
}
j2d_glPixelZoom(1.0, 1.0);
@@ -317,12 +319,11 @@ OGLBlitToSurfaceViaTexture(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
ty2 = ((GLdouble)sh) / th;
if (swsurface) {
+ GLvoid *pSrc = PtrCoord(srcInfo->rasBase,
+ sx, srcInfo->pixelStride,
+ sy, srcInfo->scanStride);
if (slowPath) {
jint tmph = sh;
- GLvoid *pSrc = PtrCoord(srcInfo->rasBase,
- sx, srcInfo->pixelStride,
- sy, srcInfo->scanStride);
-
while (tmph > 0) {
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
0, sh - tmph, sw, 1,
@@ -332,16 +333,10 @@ OGLBlitToSurfaceViaTexture(OGLContext *oglc, SurfaceDataRasInfo *srcInfo,
tmph--;
}
} else {
- j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx);
- j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy);
-
j2d_glTexSubImage2D(GL_TEXTURE_2D, 0,
0, 0, sw, sh,
pf->format, pf->type,
- srcInfo->rasBase);
-
- j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
- j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+ pSrc);
}
// the texture image is "right side up", so we align the
@@ -638,8 +633,9 @@ OGLBlitLoops_Blit(JNIEnv *env,
J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f",
dx1, dy1, dx2, dy2);
- j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, sx1);
- j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, sy1);
+ // Note: we will calculate x/y positions in the raster manually
+ j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+ j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH,
srcInfo.scanStride / srcInfo.pixelStride);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, pf.alignment);
@@ -696,8 +692,6 @@ OGLBlitLoops_Blit(JNIEnv *env,
}
}
- j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
- j2d_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
j2d_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
j2d_glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
@@ -717,8 +711,8 @@ void flip(void *pDst, juint w, juint h, jint scanStride, jboolean convert) {
juint step = 0;
// vertical flip and convert argbpre to argb if necessary
for (; i < h / 2; ++i) {
- juint *r1 = PtrAddBytes(pDst, (i * scanStride));
- juint *r2 = PtrAddBytes(pDst, (h - i - 1) * scanStride);
+ juint *r1 = PtrPixelsRow(pDst, i, scanStride);
+ juint *r2 = PtrPixelsRow(pDst, h - i - 1, scanStride);
if (tempRow) {
// fast path
memcpy(tempRow, r1, clippedStride);
@@ -740,7 +734,7 @@ void flip(void *pDst, juint w, juint h, jint scanStride, jboolean convert) {
}
// convert the middle line if necessary
if (convert && h % 2) {
- juint *r1 = PtrAddBytes(pDst, (i * scanStride));
+ juint *r1 = PtrPixelsRow(pDst, i, scanStride);
for (step = 0; step < w; ++step) {
LoadIntArgbPreTo1IntArgb(r1, 0, step, r1[step]);
}
@@ -813,7 +807,7 @@ OGLBlitLoops_SurfaceToSwBlit(JNIEnv *env, OGLContext *oglc,
height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
pDst = PtrAddBytes(pDst, dstx * dstInfo.pixelStride);
- pDst = PtrAddBytes(pDst, dsty * dstInfo.scanStride);
+ pDst = PtrPixelsRow(pDst, dsty, dstInfo.scanStride);
j2d_glPixelStorei(GL_PACK_ROW_LENGTH,
dstInfo.scanStride / dstInfo.pixelStride);
diff --git a/src/share/native/sun/security/ec/ECC_JNI.cpp b/src/share/native/sun/security/ec/ECC_JNI.cpp
index b7fb6750e5..0e49b3ed32 100644
--- a/src/share/native/sun/security/ec/ECC_JNI.cpp
+++ b/src/share/native/sun/security/ec/ECC_JNI.cpp
@@ -84,6 +84,50 @@ jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
/*
* Class: sun_security_ec_ECKeyPairGenerator
+ * Method: isCurveSupported
+ * Signature: ([B)Z
+ */
+JNIEXPORT jboolean
+JNICALL Java_sun_security_ec_ECKeyPairGenerator_isCurveSupported
+ (JNIEnv *env, jclass clazz, jbyteArray encodedParams)
+{
+ SECKEYECParams params_item;
+ ECParams *ecparams = NULL;
+ jboolean result = JNI_FALSE;
+
+ // The curve is supported if we can get parameters for it
+ params_item.len = env->GetArrayLength(encodedParams);
+ params_item.data =
+ (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
+ if (params_item.data == NULL) {
+ goto cleanup;
+ }
+
+ // Fill a new ECParams using the supplied OID
+ if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+ /* bad curve OID */
+ goto cleanup;
+ }
+
+ // If we make it to here, then the curve is supported
+ result = JNI_TRUE;
+
+cleanup:
+ {
+ if (params_item.data) {
+ env->ReleaseByteArrayElements(encodedParams,
+ (jbyte *) params_item.data, JNI_ABORT);
+ }
+ if (ecparams) {
+ FreeECParams(ecparams, true);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Class: sun_security_ec_ECKeyPairGenerator
* Method: generateECKeyPair
* Signature: (I[B[B)[[B
*/
diff --git a/src/share/native/sun/security/ec/impl/ec.c b/src/share/native/sun/security/ec/impl/ec.c
index 4e94d27793..264e1a86e1 100644
--- a/src/share/native/sun/security/ec/impl/ec.c
+++ b/src/share/native/sun/security/ec/impl/ec.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
@@ -659,6 +659,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
SECItem kGpoint = { siBuffer, NULL, 0};
int flen = 0; /* length in bytes of the field size */
unsigned olen; /* length in bytes of the base point order */
+ unsigned int orderBitSize;
#if EC_DEBUG
char mpstr[256];
@@ -761,10 +762,11 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */
/* In the definition of EC signing, digests are truncated
- * to the length of n in bits.
+ * to the order length
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
- if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
- mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
+ orderBitSize = mpl_significant_bits(&n);
+ if (digest->len*8 > orderBitSize) {
+ mpl_rsh(&s,&s,digest->len*8 - orderBitSize);
}
#if EC_DEBUG
@@ -897,6 +899,7 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
int slen; /* length in bytes of a half signature (r or s) */
int flen; /* length in bytes of the field size */
unsigned olen; /* length in bytes of the base point order */
+ unsigned int orderBitSize;
#if EC_DEBUG
char mpstr[256];
@@ -976,11 +979,12 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */
/* In the definition of EC signing, digests are truncated
- * to the length of n in bits.
+ * to the order length, in bits.
* (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
/* u1 = HASH(M') */
- if (digest->len*8 > (unsigned int)ecParams->fieldID.size) {
- mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
+ orderBitSize = mpl_significant_bits(&n);
+ if (digest->len*8 > orderBitSize) {
+ mpl_rsh(&u1,&u1,digest->len*8- orderBitSize);
}
#if EC_DEBUG
diff --git a/src/share/native/sun/security/krb5/nativeccache.c b/src/share/native/sun/security/krb5/nativeccache.c
index beb5bf0262..1b50a2e176 100644
--- a/src/share/native/sun/security/krb5/nativeccache.c
+++ b/src/share/native/sun/security/krb5/nativeccache.c
@@ -291,6 +291,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
int netypes;
jint *etypes = NULL;
+ int proxy_flag = 0;
/* Initialize the Kerberos 5 context */
err = krb5_init_context (&kcontext);
@@ -303,6 +304,48 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
err = krb5_cc_set_flags (kcontext, ccache, flags); /* turn off OPENCLOSE */
}
+ // First round read. The proxy_impersonator config flag is not supported.
+ // This ccache will not be used if this flag exists.
+ if (!err) {
+ err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
+ }
+
+ if (!err) {
+ while ((err = krb5_cc_next_cred (kcontext, ccache, &cursor, &creds)) == 0) {
+ char *serverName = NULL;
+
+ if (!err) {
+ err = krb5_unparse_name (kcontext, creds.server, &serverName);
+ printiferr (err, "while unparsing server name");
+ }
+
+ if (!err) {
+ if (!strcmp(serverName, "krb5_ccache_conf_data/proxy_impersonator@X-CACHECONF:")) {
+ proxy_flag = 1;
+ }
+ }
+
+ if (serverName != NULL) { krb5_free_unparsed_name (kcontext, serverName); }
+
+ krb5_free_cred_contents (kcontext, &creds);
+
+ if (proxy_flag) break;
+ }
+
+ if (err == KRB5_CC_END) { err = 0; }
+ printiferr (err, "while retrieving a ticket");
+ }
+
+ if (!err) {
+ err = krb5_cc_end_seq_get (kcontext, ccache, &cursor);
+ printiferr (err, "while finishing ticket retrieval");
+ }
+
+ if (proxy_flag) {
+ goto outer_cleanup;
+ }
+ // End of first round read
+
if (!err) {
err = krb5_cc_start_seq_get (kcontext, ccache, &cursor);
}
@@ -430,6 +473,7 @@ cleanup:
printiferr (err, "while finishing ticket retrieval");
}
+outer_cleanup:
if (!err) {
flags = KRB5_TC_OPENCLOSE; /* restore OPENCLOSE mode */
err = krb5_cc_set_flags (kcontext, ccache, flags);
diff --git a/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c b/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
index 9824da2dfd..fa725ae176 100644
--- a/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
+++ b/src/share/native/sun/security/pkcs11/wrapper/p11_keymgmt.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 2002 Graz University of Technology. All rights reserved.
@@ -54,6 +54,446 @@
#include "sun_security_pkcs11_wrapper_PKCS11.h"
+#ifdef P11_ENABLE_GETNATIVEKEYINFO
+
+#define CK_ATTRIBUTES_TEMPLATE_LENGTH (CK_ULONG)61U
+
+static CK_ATTRIBUTE ckpAttributesTemplate[CK_ATTRIBUTES_TEMPLATE_LENGTH] = {
+ {CKA_CLASS, 0, 0},
+ {CKA_TOKEN, 0, 0},
+ {CKA_PRIVATE, 0, 0},
+ {CKA_LABEL, 0, 0},
+ {CKA_APPLICATION, 0, 0},
+ {CKA_VALUE, 0, 0},
+ {CKA_OBJECT_ID, 0, 0},
+ {CKA_CERTIFICATE_TYPE, 0, 0},
+ {CKA_ISSUER, 0, 0},
+ {CKA_SERIAL_NUMBER, 0, 0},
+ {CKA_AC_ISSUER, 0, 0},
+ {CKA_OWNER, 0, 0},
+ {CKA_ATTR_TYPES, 0, 0},
+ {CKA_TRUSTED, 0, 0},
+ {CKA_KEY_TYPE, 0, 0},
+ {CKA_SUBJECT, 0, 0},
+ {CKA_ID, 0, 0},
+ {CKA_SENSITIVE, 0, 0},
+ {CKA_ENCRYPT, 0, 0},
+ {CKA_DECRYPT, 0, 0},
+ {CKA_WRAP, 0, 0},
+ {CKA_UNWRAP, 0, 0},
+ {CKA_SIGN, 0, 0},
+ {CKA_SIGN_RECOVER, 0, 0},
+ {CKA_VERIFY, 0, 0},
+ {CKA_VERIFY_RECOVER, 0, 0},
+ {CKA_DERIVE, 0, 0},
+ {CKA_START_DATE, 0, 0},
+ {CKA_END_DATE, 0, 0},
+ {CKA_MODULUS, 0, 0},
+ {CKA_MODULUS_BITS, 0, 0},
+ {CKA_PUBLIC_EXPONENT, 0, 0},
+ {CKA_PRIVATE_EXPONENT, 0, 0},
+ {CKA_PRIME_1, 0, 0},
+ {CKA_PRIME_2, 0, 0},
+ {CKA_EXPONENT_1, 0, 0},
+ {CKA_EXPONENT_2, 0, 0},
+ {CKA_COEFFICIENT, 0, 0},
+ {CKA_PRIME, 0, 0},
+ {CKA_SUBPRIME, 0, 0},
+ {CKA_BASE, 0, 0},
+ {CKA_PRIME_BITS, 0, 0},
+ {CKA_SUB_PRIME_BITS, 0, 0},
+ {CKA_VALUE_BITS, 0, 0},
+ {CKA_VALUE_LEN, 0, 0},
+ {CKA_EXTRACTABLE, 0, 0},
+ {CKA_LOCAL, 0, 0},
+ {CKA_NEVER_EXTRACTABLE, 0, 0},
+ {CKA_ALWAYS_SENSITIVE, 0, 0},
+ {CKA_KEY_GEN_MECHANISM, 0, 0},
+ {CKA_MODIFIABLE, 0, 0},
+ {CKA_ECDSA_PARAMS, 0, 0},
+ {CKA_EC_PARAMS, 0, 0},
+ {CKA_EC_POINT, 0, 0},
+ {CKA_SECONDARY_AUTH, 0, 0},
+ {CKA_AUTH_PIN_FLAGS, 0, 0},
+ {CKA_HW_FEATURE_TYPE, 0, 0},
+ {CKA_RESET_ON_INIT, 0, 0},
+ {CKA_HAS_RESET, 0, 0},
+ {CKA_VENDOR_DEFINED, 0, 0},
+ {CKA_NETSCAPE_DB, 0, 0},
+};
+
+/*
+ * Class: sun_security_pkcs11_wrapper_PKCS11
+ * Method: getNativeKeyInfo
+ * Signature: (JJJLsun/security/pkcs11/wrapper/CK_MECHANISM;)[B
+ * Parametermapping: *PKCS11*
+ * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
+ * @param jlong jKeyHandle CK_OBJECT_HANDLE hObject
+ * @param jlong jWrappingKeyHandle CK_OBJECT_HANDLE hObject
+ * @param jobject jWrappingMech CK_MECHANISM_PTR pMechanism
+ * @return jbyteArray jNativeKeyInfo -
+ */
+JNIEXPORT jbyteArray JNICALL
+Java_sun_security_pkcs11_wrapper_PKCS11_getNativeKeyInfo
+ (JNIEnv *env, jobject obj, jlong jSessionHandle, jlong jKeyHandle,
+ jlong jWrappingKeyHandle, jobject jWrappingMech)
+{
+ jbyteArray returnValue = NULL;
+ CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
+ CK_OBJECT_HANDLE ckObjectHandle = jLongToCKULong(jKeyHandle);
+ CK_ATTRIBUTE_PTR ckpAttributes = NULL;
+ CK_RV rv;
+ jbyteArray nativeKeyInfoArray = NULL;
+ jbyteArray nativeKeyInfoWrappedKeyArray = NULL;
+ jbyte* nativeKeyInfoArrayRaw = NULL;
+ jbyte* nativeKeyInfoWrappedKeyArrayRaw = NULL;
+ unsigned int sensitiveAttributePosition = (unsigned int)-1;
+ unsigned int i = 0U;
+ unsigned long totalDataSize = 0UL, attributesCount = 0UL;
+ unsigned long totalCkAttributesSize = 0UL, totalNativeKeyInfoArraySize = 0UL;
+ jbyte* wrappedKeySizePtr = NULL;
+ jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
+ jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
+ jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
+ CK_MECHANISM ckMechanism;
+ char iv[16] = {0x0};
+ CK_ULONG ckWrappedKeyLength = 0U;
+ jbyte* wrappedKeySizeWrappedKeyArrayPtr = NULL;
+ CK_BYTE_PTR wrappedKeyBufferPtr = NULL;
+ CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
+ CK_OBJECT_CLASS class;
+ CK_KEY_TYPE keyType;
+ CK_BBOOL sensitive;
+ CK_BBOOL netscapeAttributeValueNeeded = CK_FALSE;
+ CK_ATTRIBUTE ckNetscapeAttributesTemplate[4];
+ ckNetscapeAttributesTemplate[0].type = CKA_CLASS;
+ ckNetscapeAttributesTemplate[1].type = CKA_KEY_TYPE;
+ ckNetscapeAttributesTemplate[2].type = CKA_SENSITIVE;
+ ckNetscapeAttributesTemplate[3].type = CKA_NETSCAPE_DB;
+ ckNetscapeAttributesTemplate[0].pValue = &class;
+ ckNetscapeAttributesTemplate[1].pValue = &keyType;
+ ckNetscapeAttributesTemplate[2].pValue = &sensitive;
+ ckNetscapeAttributesTemplate[3].pValue = 0;
+ ckNetscapeAttributesTemplate[0].ulValueLen = sizeof(class);
+ ckNetscapeAttributesTemplate[1].ulValueLen = sizeof(keyType);
+ ckNetscapeAttributesTemplate[2].ulValueLen = sizeof(sensitive);
+ ckNetscapeAttributesTemplate[3].ulValueLen = 0;
+
+ if (ckpFunctions == NULL) { goto cleanup; }
+
+ // If key is private and of DSA or EC type, NSS may require CKA_NETSCAPE_DB
+ // attribute to unwrap it.
+ rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+ ckNetscapeAttributesTemplate,
+ sizeof(ckNetscapeAttributesTemplate)/sizeof(CK_ATTRIBUTE));
+
+ if (rv == CKR_OK && class == CKO_PRIVATE_KEY &&
+ (keyType == CKK_EC || keyType == CKK_DSA) &&
+ sensitive == CK_TRUE &&
+ ckNetscapeAttributesTemplate[3].ulValueLen == CK_UNAVAILABLE_INFORMATION) {
+ // We cannot set the attribute through C_SetAttributeValue here
+ // because it might be read-only. However, we can add it to
+ // the extracted buffer.
+ netscapeAttributeValueNeeded = CK_TRUE;
+ TRACE0("DEBUG: override CKA_NETSCAPE_DB attr value to TRUE\n");
+ }
+
+ ckpAttributes = (CK_ATTRIBUTE_PTR)malloc(
+ CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+ if (ckpAttributes == NULL) {
+ throwOutOfMemoryError(env, 0);
+ goto cleanup;
+ }
+ memcpy(ckpAttributes, ckpAttributesTemplate,
+ CK_ATTRIBUTES_TEMPLATE_LENGTH * sizeof(CK_ATTRIBUTE));
+
+ // Get sizes for value buffers
+ // NOTE: may return an error code but length values are filled anyways
+ (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+ ckpAttributes, CK_ATTRIBUTES_TEMPLATE_LENGTH);
+
+ for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
+ if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
+ totalDataSize += (ckpAttributes+i)->ulValueLen;
+ if ((ckpAttributes+i)->type == CKA_SENSITIVE) {
+ sensitiveAttributePosition = attributesCount;
+ TRACE0("DEBUG: GetNativeKeyInfo key is sensitive");
+ }
+ attributesCount++;
+ }
+ }
+
+ if (netscapeAttributeValueNeeded) {
+ attributesCount++;
+ }
+
+ // Allocate a single buffer to hold valid attributes and attribute's values
+ // Buffer structure: [ attributes-size, [ ... attributes ... ],
+ // values-size, [ ... values ... ], wrapped-key-size,
+ // [ ... wrapped-key ... ] ]
+ // * sizes are expressed in bytes and data type is unsigned long
+ totalCkAttributesSize = attributesCount * sizeof(CK_ATTRIBUTE);
+ TRACE1("DEBUG: GetNativeKeyInfo attributesCount = %lu\n", attributesCount);
+ TRACE1("DEBUG: GetNativeKeyInfo sizeof CK_ATTRIBUTE = %zu\n", sizeof(CK_ATTRIBUTE));
+ TRACE1("DEBUG: GetNativeKeyInfo totalCkAttributesSize = %lu\n", totalCkAttributesSize);
+ TRACE1("DEBUG: GetNativeKeyInfo totalDataSize = %lu\n", totalDataSize);
+
+ totalNativeKeyInfoArraySize =
+ totalCkAttributesSize + sizeof(unsigned long) * 3 + totalDataSize;
+
+ TRACE1("DEBUG: GetNativeKeyInfo totalNativeKeyInfoArraySize = %lu\n", totalNativeKeyInfoArraySize);
+
+ nativeKeyInfoArray = (*env)->NewByteArray(env, totalNativeKeyInfoArraySize);
+ if (nativeKeyInfoArray == NULL) {
+ goto cleanup;
+ }
+
+ nativeKeyInfoArrayRaw = (*env)->GetByteArrayElements(env, nativeKeyInfoArray,
+ NULL);
+ if (nativeKeyInfoArrayRaw == NULL) {
+ goto cleanup;
+ }
+
+ wrappedKeySizePtr = nativeKeyInfoArrayRaw +
+ sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize;
+ memcpy(nativeKeyInfoArrayRaw, &totalCkAttributesSize, sizeof(unsigned long));
+
+ memcpy(nativeKeyInfoArrayRaw + sizeof(unsigned long) + totalCkAttributesSize,
+ &totalDataSize, sizeof(unsigned long));
+
+ memset(wrappedKeySizePtr, 0, sizeof(unsigned long));
+
+ nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
+ sizeof(unsigned long);
+ nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
+ nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
+ totalCkAttributesSize + sizeof(unsigned long) * 2;
+
+ for (i = 0; i < CK_ATTRIBUTES_TEMPLATE_LENGTH; i++) {
+ if ((ckpAttributes+i)->ulValueLen != CK_UNAVAILABLE_INFORMATION) {
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type =
+ (ckpAttributes+i)->type;
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen =
+ (ckpAttributes+i)->ulValueLen;
+ if ((ckpAttributes+i)->ulValueLen != 0) {
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
+ nativeKeyInfoArrayRawDataPtr;
+ } else {
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue = 0;
+ }
+ nativeKeyInfoArrayRawDataPtr +=
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
+ nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
+ }
+ }
+
+ TRACE0("DEBUG: GetNativeKeyInfo finished prepping nativeKeyInfoArray\n");
+
+ // Get attribute's values
+ rv = (*ckpFunctions->C_GetAttributeValue)(ckSessionHandle, ckObjectHandle,
+ (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+ attributesCount);
+ if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+ goto cleanup;
+ }
+
+ TRACE0("DEBUG: GetNativeKeyInfo 1st C_GetAttributeValue call passed\n");
+
+ if (netscapeAttributeValueNeeded) {
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).type = CKA_NETSCAPE_DB;
+ // Value is not needed, public key is not used
+ }
+
+ if ((sensitiveAttributePosition != (unsigned int)-1) &&
+ *(CK_BBOOL*)(((CK_ATTRIBUTE_PTR)(((CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes)
+ +sensitiveAttributePosition))->pValue) == CK_TRUE) {
+ // Key is sensitive. Need to extract it wrapped.
+ if (jWrappingKeyHandle != 0) {
+
+ jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
+ rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
+ jLongToCKULong(jWrappingKeyHandle), ckObjectHandle,
+ NULL_PTR, &ckWrappedKeyLength);
+ if (ckWrappedKeyLength != 0) {
+ // Allocate space for getting the wrapped key
+ nativeKeyInfoWrappedKeyArray = (*env)->NewByteArray(env,
+ totalNativeKeyInfoArraySize + ckWrappedKeyLength);
+ if (nativeKeyInfoWrappedKeyArray == NULL) {
+ goto cleanup;
+ }
+ nativeKeyInfoWrappedKeyArrayRaw =
+ (*env)->GetByteArrayElements(env,
+ nativeKeyInfoWrappedKeyArray, NULL);
+ if (nativeKeyInfoWrappedKeyArrayRaw == NULL) {
+ goto cleanup;
+ }
+ memcpy(nativeKeyInfoWrappedKeyArrayRaw, nativeKeyInfoArrayRaw,
+ totalNativeKeyInfoArraySize);
+ wrappedKeySizeWrappedKeyArrayPtr =
+ nativeKeyInfoWrappedKeyArrayRaw +
+ sizeof(unsigned long)*2 + totalCkAttributesSize +
+ totalDataSize;
+ memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
+ TRACE1("DEBUG: GetNativeKeyInfo 1st C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+
+ wrappedKeyBufferPtr =
+ (CK_BYTE_PTR) (wrappedKeySizeWrappedKeyArrayPtr +
+ sizeof(unsigned long));
+ rv = (*ckpFunctions->C_WrapKey)(ckSessionHandle, &ckMechanism,
+ jLongToCKULong(jWrappingKeyHandle),ckObjectHandle,
+ wrappedKeyBufferPtr, &ckWrappedKeyLength);
+ if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+ goto cleanup;
+ }
+ memcpy(wrappedKeySizeWrappedKeyArrayPtr, &ckWrappedKeyLength, sizeof(unsigned long));
+ TRACE1("DEBUG: GetNativeKeyInfo 2nd C_WrapKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+ } else {
+ goto cleanup;
+ }
+ } else {
+ ckAssertReturnValueOK(env, CKR_KEY_HANDLE_INVALID);
+ goto cleanup;
+ }
+ returnValue = nativeKeyInfoWrappedKeyArray;
+ } else {
+ returnValue = nativeKeyInfoArray;
+ }
+
+cleanup:
+ if (ckpAttributes != NULL) {
+ free(ckpAttributes);
+ }
+
+ if (nativeKeyInfoArrayRaw != NULL) {
+ (*env)->ReleaseByteArrayElements(env, nativeKeyInfoArray,
+ nativeKeyInfoArrayRaw, 0);
+ }
+
+ if (nativeKeyInfoWrappedKeyArrayRaw != NULL) {
+ (*env)->ReleaseByteArrayElements(env, nativeKeyInfoWrappedKeyArray,
+ nativeKeyInfoWrappedKeyArrayRaw, 0);
+ }
+
+ if (nativeKeyInfoArray != NULL && returnValue != nativeKeyInfoArray) {
+ (*env)->DeleteLocalRef(env, nativeKeyInfoArray);
+ }
+
+ if (nativeKeyInfoWrappedKeyArray != NULL
+ && returnValue != nativeKeyInfoWrappedKeyArray) {
+ (*env)->DeleteLocalRef(env, nativeKeyInfoWrappedKeyArray);
+ }
+
+ return returnValue;
+}
+#endif
+
+#ifdef P11_ENABLE_CREATENATIVEKEY
+/*
+ * Class: sun_security_pkcs11_wrapper_PKCS11
+ * Method: createNativeKey
+ * Signature: (J[BJLsun/security/pkcs11/wrapper/CK_MECHANISM;)J
+ * Parametermapping: *PKCS11*
+ * @param jlong jSessionHandle CK_SESSION_HANDLE hSession
+ * @param jbyteArray jNativeKeyInfo -
+ * @param jlong jWrappingKeyHandle CK_OBJECT_HANDLE hObject
+ * @param jobject jWrappingMech CK_MECHANISM_PTR pMechanism
+ * @return jlong jKeyHandle CK_OBJECT_HANDLE hObject
+ */
+JNIEXPORT jlong JNICALL
+Java_sun_security_pkcs11_wrapper_PKCS11_createNativeKey
+ (JNIEnv *env, jobject obj, jlong jSessionHandle, jbyteArray jNativeKeyInfo,
+ jlong jWrappingKeyHandle, jobject jWrappingMech)
+{
+ CK_OBJECT_HANDLE ckObjectHandle;
+ CK_RV rv;
+ CK_SESSION_HANDLE ckSessionHandle = jLongToCKULong(jSessionHandle);
+ jbyte* nativeKeyInfoArrayRaw = NULL;
+ jlong jObjectHandle = 0L;
+ unsigned long totalCkAttributesSize = 0UL;
+ unsigned long nativeKeyInfoCkAttributesCount = 0UL;
+ jbyte* nativeKeyInfoArrayRawCkAttributes = NULL;
+ jbyte* nativeKeyInfoArrayRawCkAttributesPtr = NULL;
+ jbyte* nativeKeyInfoArrayRawDataPtr = NULL;
+ unsigned long totalDataSize = 0UL;
+ jbyte* wrappedKeySizePtr = NULL;
+ unsigned int i = 0U;
+ CK_MECHANISM ckMechanism;
+ char iv[16] = {0x0};
+ CK_ULONG ckWrappedKeyLength = 0UL;
+ CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj);
+
+ if (ckpFunctions == NULL) { goto cleanup; }
+
+ nativeKeyInfoArrayRaw =
+ (*env)->GetByteArrayElements(env, jNativeKeyInfo, NULL);
+ if (nativeKeyInfoArrayRaw == NULL) {
+ goto cleanup;
+ }
+
+ memcpy(&totalCkAttributesSize, nativeKeyInfoArrayRaw, sizeof(unsigned long));
+ TRACE1("DEBUG: createNativeKey totalCkAttributesSize = %lu\n", totalCkAttributesSize);
+ nativeKeyInfoCkAttributesCount = totalCkAttributesSize/sizeof(CK_ATTRIBUTE);
+ TRACE1("DEBUG: createNativeKey nativeKeyInfoCkAttributesCount = %lu\n", nativeKeyInfoCkAttributesCount);
+
+ nativeKeyInfoArrayRawCkAttributes = nativeKeyInfoArrayRaw +
+ sizeof(unsigned long);
+ nativeKeyInfoArrayRawCkAttributesPtr = nativeKeyInfoArrayRawCkAttributes;
+ nativeKeyInfoArrayRawDataPtr = nativeKeyInfoArrayRaw +
+ totalCkAttributesSize + sizeof(unsigned long) * 2;
+ memcpy(&totalDataSize, (nativeKeyInfoArrayRaw + totalCkAttributesSize + sizeof(unsigned long)),
+ sizeof(unsigned long));
+ TRACE1("DEBUG: createNativeKey totalDataSize = %lu\n", totalDataSize);
+
+ wrappedKeySizePtr = nativeKeyInfoArrayRaw +
+ sizeof(unsigned long)*2 + totalCkAttributesSize + totalDataSize;
+
+ memcpy(&ckWrappedKeyLength, wrappedKeySizePtr, sizeof(unsigned long));
+ TRACE1("DEBUG: createNativeKey wrappedKeyLength = %lu\n", ckWrappedKeyLength);
+
+ for (i = 0; i < nativeKeyInfoCkAttributesCount; i++) {
+ if ((*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen
+ > 0) {
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).pValue =
+ nativeKeyInfoArrayRawDataPtr;
+ }
+ nativeKeyInfoArrayRawDataPtr +=
+ (*(CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributesPtr).ulValueLen;
+ nativeKeyInfoArrayRawCkAttributesPtr += sizeof(CK_ATTRIBUTE);
+ }
+
+ if (ckWrappedKeyLength == 0) {
+ // Not a wrapped key
+ rv = (*ckpFunctions->C_CreateObject)(ckSessionHandle,
+ (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+ jLongToCKULong(nativeKeyInfoCkAttributesCount), &ckObjectHandle);
+ } else {
+ // Wrapped key
+ jMechanismToCKMechanism(env, jWrappingMech, &ckMechanism);
+ rv = (*ckpFunctions->C_UnwrapKey)(ckSessionHandle, &ckMechanism,
+ jLongToCKULong(jWrappingKeyHandle),
+ (CK_BYTE_PTR)(wrappedKeySizePtr + sizeof(unsigned long)),
+ ckWrappedKeyLength,
+ (CK_ATTRIBUTE_PTR)nativeKeyInfoArrayRawCkAttributes,
+ jLongToCKULong(nativeKeyInfoCkAttributesCount),
+ &ckObjectHandle);
+ }
+ if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) {
+ goto cleanup;
+ }
+
+ jObjectHandle = ckULongToJLong(ckObjectHandle);
+
+cleanup:
+
+ if (nativeKeyInfoArrayRaw != NULL) {
+ (*env)->ReleaseByteArrayElements(env, jNativeKeyInfo,
+ nativeKeyInfoArrayRaw, JNI_ABORT);
+ }
+
+ return jObjectHandle;
+}
+#endif
+
#ifdef P11_ENABLE_C_GENERATEKEY
/*
* Class: sun_security_pkcs11_wrapper_PKCS11
diff --git a/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h b/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
index 0f62b3e7b5..00174e1a97 100644
--- a/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
+++ b/src/share/native/sun/security/pkcs11/wrapper/pkcs11t.h
@@ -548,6 +548,7 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE;
#define CKA_ALLOWED_MECHANISMS (CKF_ARRAY_ATTRIBUTE|0x00000600)
#define CKA_VENDOR_DEFINED 0x80000000
+#define CKA_NETSCAPE_DB 0xD5A0DB00
/* CK_ATTRIBUTE is a structure that includes the type, length
diff --git a/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h b/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
index b8042c0586..e60ae99473 100644
--- a/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
+++ b/src/share/native/sun/security/pkcs11/wrapper/pkcs11wrapper.h
@@ -148,6 +148,8 @@
#undef P11_ENABLE_C_GETFUNCTIONSTATUS
#undef P11_ENABLE_C_CANCELFUNCTION
#undef P11_ENABLE_C_WAITFORSLOTEVENT
+#define P11_ENABLE_GETNATIVEKEYINFO
+#define P11_ENABLE_CREATENATIVEKEY
/* include the platform dependent part of the header */
#include "p11_md.h"
diff --git a/src/share/native/sun/security/smartcardio/pcsc.c b/src/share/native/sun/security/smartcardio/pcsc.c
index b837234761..5f8e53ec7f 100644
--- a/src/share/native/sun/security/smartcardio/pcsc.c
+++ b/src/share/native/sun/security/smartcardio/pcsc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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
@@ -179,7 +179,7 @@ JNIEXPORT jobjectArray JNICALL Java_sun_security_smartcardio_PCSC_SCardListReade
{
SCARDCONTEXT context = (SCARDCONTEXT)jContext;
LONG rv;
- LPTSTR mszReaders = NULL;
+ LPSTR mszReaders = NULL;
DWORD size = 0;
jobjectArray result;
@@ -216,7 +216,7 @@ JNIEXPORT jlong JNICALL Java_sun_security_smartcardio_PCSC_SCardConnect
{
SCARDCONTEXT context = (SCARDCONTEXT)jContext;
LONG rv;
- LPCTSTR readerName;
+ LPCSTR readerName;
SCARDHANDLE card = 0;
DWORD proto = 0;
diff --git a/src/solaris/classes/sun/awt/X11/InfoWindow.java b/src/solaris/classes/sun/awt/X11/InfoWindow.java
index 20c6174c2e..fef9704d02 100644
--- a/src/solaris/classes/sun/awt/X11/InfoWindow.java
+++ b/src/solaris/classes/sun/awt/X11/InfoWindow.java
@@ -414,12 +414,24 @@ public abstract class InfoWindow extends Window {
private void loadGtkImages() {
if (!gtkImagesLoaded) {
- errorImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
- "gtk.icon.gtk-dialog-error.6.rtl");
- warnImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
- "gtk.icon.gtk-dialog-warning.6.rtl");
- infoImage = (Image)Toolkit.getDefaultToolkit().getDesktopProperty(
- "gtk.icon.gtk-dialog-info.6.rtl");
+ //check whether the gtk version is >= 3.10 as the Icon names were
+ //changed from this release
+ UNIXToolkit tk = (UNIXToolkit) Toolkit.getDefaultToolkit();
+ if (tk.checkGtkVersion(3, 10, 0)) {
+ errorImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.dialog-error.6.rtl");
+ warnImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.dialog-warning.6.rtl");
+ infoImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.dialog-information.6.rtl");
+ } else {
+ errorImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.gtk-dialog-error.6.rtl");
+ warnImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.gtk-dialog-warning.6.rtl");
+ infoImage = (Image) tk.getDesktopProperty(
+ "gtk.icon.gtk-dialog-info.6.rtl");
+ }
gtkImagesLoaded = true;
}
}
@@ -492,4 +504,3 @@ public abstract class InfoWindow extends Window {
}
}
}
-
diff --git a/src/solaris/classes/sun/awt/X11/XKeysym.java b/src/solaris/classes/sun/awt/X11/XKeysym.java
index b0b0d0728e..7fe9bd773c 100644
--- a/src/solaris/classes/sun/awt/X11/XKeysym.java
+++ b/src/solaris/classes/sun/awt/X11/XKeysym.java
@@ -1,5 +1,3 @@
-// This is a generated file: do not edit! Edit keysym2ucs.h if necessary.
-
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -25,6 +23,19 @@
* questions.
*/
+/*
+ * This file was originally generated by a tool that embedded much of
+ * an X11 keysym header file, keysym2ucs.h, turned into a Java program,
+ * and which also consumed an UnicodeData.txt database file.
+ * keysym2ucs.h and a genhash.awk script were checked in alongside this
+ * source file. Maintaining the Java program to match updated versions
+ * of keysym2ucs.h is too burdensome, since it is rarely, needed and any
+ * updates will be minimal, so they have been removed and
+ * this file can now be hand maintained. If it ever becomes necessary
+ * to re-generate it, then the deleted files can be recovered from
+ * the history.
+ */
+
package sun.awt.X11;
import java.util.Hashtable;
import sun.misc.Unsafe;
@@ -33,15 +44,6 @@ import sun.util.logging.PlatformLogger;
public class XKeysym {
- public static void main( String args[] ) {
- System.out.println( "Cyrillc zhe:"+convertKeysym(0x06d6, 0));
- System.out.println( "Arabic sheen:"+convertKeysym(0x05d4, 0));
- System.out.println( "Latin a breve:"+convertKeysym(0x01e3, 0));
- System.out.println( "Latin f:"+convertKeysym(0x066, 0));
- System.out.println( "Backspace:"+Integer.toHexString(convertKeysym(0xff08, 0)));
- System.out.println( "Ctrl+f:"+Integer.toHexString(convertKeysym(0x066, XConstants.ControlMask)));
- }
-
private XKeysym() {}
static class Keysym2JavaKeycode {
@@ -71,7 +73,7 @@ public class XKeysym {
static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize());
static Keysym2JavaKeycode kanaLock = new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK,
java.awt.event.KeyEvent.KEY_LOCATION_STANDARD);
- private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XKeysym");
+ private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.key.XKeysym");
public static char convertKeysym( long ks, int state ) {
/* First check for Latin-1 characters (1:1 mapping) */
diff --git a/src/solaris/classes/sun/awt/X11/XMSelection.java b/src/solaris/classes/sun/awt/X11/XMSelection.java
index a74dad630e..5115c25611 100644
--- a/src/solaris/classes/sun/awt/X11/XMSelection.java
+++ b/src/solaris/classes/sun/awt/X11/XMSelection.java
@@ -97,7 +97,15 @@ public class XMSelection {
XToolkit.awtLock();
try {
long root = XlibWrapper.RootWindow(display,screen);
- XlibWrapper.XSelectInput(display, root, XConstants.StructureNotifyMask);
+ XWindowAttributes wattr = new XWindowAttributes();
+ try {
+ XlibWrapper.XGetWindowAttributes(display, root, wattr.pData);
+ XlibWrapper.XSelectInput(display, root,
+ XConstants.StructureNotifyMask |
+ wattr.get_your_event_mask());
+ } finally {
+ wattr.dispose();
+ }
XToolkit.addEventDispatcher(root,
new XEventDispatcher() {
public void dispatchEvent(XEvent ev) {
diff --git a/src/solaris/classes/sun/awt/X11/XWindow.java b/src/solaris/classes/sun/awt/X11/XWindow.java
index bf40108888..fc0cbd9710 100644
--- a/src/solaris/classes/sun/awt/X11/XWindow.java
+++ b/src/solaris/classes/sun/awt/X11/XWindow.java
@@ -453,14 +453,7 @@ class XWindow extends XBaseWindow implements X11ComponentPeer {
if (!doEraseBackground()) {
return;
}
- // 6304250: XAWT: Items in choice show a blue border on OpenGL + Solaris10 when background color is set
- // Note: When OGL is enabled, surfaceData.pixelFor() will not
- // return a pixel value appropriate for passing to
- // XSetWindowBackground(). Therefore, we will use the ColorModel
- // for this component in order to calculate a pixel value from
- // the given RGB value.
- ColorModel cm = getColorModel();
- int pixel = PixelConverter.instance.rgbToPixel(c.getRGB(), cm);
+ int pixel = surfaceData.pixelFor(c.getRGB());
XlibWrapper.XSetWindowBackground(XToolkit.getDisplay(), getContentWindow(), pixel);
XlibWrapper.XClearWindow(XToolkit.getDisplay(), getContentWindow());
}
diff --git a/src/solaris/classes/sun/awt/X11/genhash.awk b/src/solaris/classes/sun/awt/X11/genhash.awk
deleted file mode 100644
index 43637c3409..0000000000
--- a/src/solaris/classes/sun/awt/X11/genhash.awk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (c) 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.
-#
-# With this script one can generate a new version XKeysym.java file out
-# of keysym2ucs.h prototype and UnicodeData.txt database.
-# Latter file should be fetched from a unicode.org site, most
-# probably http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
-#
-BEGIN { FS=";";
- while((getline < "UnicodeData.txt")){
- unic[$1]=$2;
- }
- FS=" ";
- print("// This is a generated file: do not edit! Edit keysym2ucs.h if necessary.\n");
- }
-
-/^0x/{
- if( $1 != "0x0000" ) {
- ndx = toupper($1);
- sub(/0X/, "", ndx);
- printf(" keysym2UCSHash.put( (long)%s, (char)%s); // %s -->%s\n",
- $4, $1, $3, (unic[ndx]=="" ? "" : " " unic[ndx]));
- }
- }
-/tojava/ { sub(/tojava /, ""); sub(/tojava$/, ""); print}
diff --git a/src/solaris/classes/sun/awt/X11/keysym2ucs.h b/src/solaris/classes/sun/awt/X11/keysym2ucs.h
deleted file mode 100644
index 09de3bee09..0000000000
--- a/src/solaris/classes/sun/awt/X11/keysym2ucs.h
+++ /dev/null
@@ -1,2758 +0,0 @@
-/*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * yan:
- * This table looks like C header because
- * (1) I use actual headers to make it;
- * (2) syntax is nicely highlighted in my editor.
- * Processed will be all lines started with 0x; 0x0000-started lines will
- * be skipped though.
- * Also java code will be copied to a resulting file.
- *
- * 0x0000 unicode means here either there's no equivalent to a keysym
- * or we just skip it from the table for now because i.e. we'll never use
- * the conversion in our workflow.
- *
- */
-
-tojava /*
-tojava * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
-tojava * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-tojava *
-tojava * This code is free software; you can redistribute it and/or modify it
-tojava * under the terms of the GNU General Public License version 2 only, as
-tojava * published by the Free Software Foundation. Oracle designates this
-tojava * particular file as subject to the "Classpath" exception as provided
-tojava * by Oracle in the LICENSE file that accompanied this code.
-tojava *
-tojava * This code is distributed in the hope that it will be useful, but WITHOUT
-tojava * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-tojava * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-tojava * version 2 for more details (a copy is included in the LICENSE file that
-tojava * accompanied this code).
-tojava *
-tojava * You should have received a copy of the GNU General Public License version
-tojava * 2 along with this work; if not, write to the Free Software Foundation,
-tojava * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-tojava *
-tojava * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-tojava * or visit www.oracle.com if you need additional information or have any
-tojava * questions.
-tojava */
-tojava
-tojava package sun.awt.X11;
-tojava import java.util.Hashtable;
-tojava import sun.misc.Unsafe;
-tojava
-tojava import sun.util.logging.PlatformLogger;
-tojava
-tojava public class XKeysym {
-tojava
-tojava public static void main( String args[] ) {
-tojava System.out.println( "Cyrillc zhe:"+convertKeysym(0x06d6, 0));
-tojava System.out.println( "Arabic sheen:"+convertKeysym(0x05d4, 0));
-tojava System.out.println( "Latin a breve:"+convertKeysym(0x01e3, 0));
-tojava System.out.println( "Latin f:"+convertKeysym(0x066, 0));
-tojava System.out.println( "Backspace:"+Integer.toHexString(convertKeysym(0xff08, 0)));
-tojava System.out.println( "Ctrl+f:"+Integer.toHexString(convertKeysym(0x066, XConstants.ControlMask)));
-tojava }
-tojava
-tojava private XKeysym() {}
-tojava
-tojava static class Keysym2JavaKeycode {
-tojava int jkeycode;
-tojava int keyLocation;
-tojava int getJavaKeycode() {
-tojava return jkeycode;
-tojava }
-tojava int getKeyLocation() {
-tojava return keyLocation;
-tojava }
-tojava Keysym2JavaKeycode(int jk, int loc) {
-tojava jkeycode = jk;
-tojava keyLocation = loc;
-tojava }
-tojava };
-tojava private static Unsafe unsafe = XlibWrapper.unsafe;
-tojava static Hashtable<Long, Keysym2JavaKeycode> keysym2JavaKeycodeHash = new Hashtable<Long, Keysym2JavaKeycode>();
-tojava static Hashtable<Long, Character> keysym2UCSHash = new Hashtable<Long, Character>();
-tojava static Hashtable<Long, Long> uppercaseHash = new Hashtable<Long, Long>();
-tojava // TODO: or not to do: add reverse lookup javakeycode2keysym,
-tojava // for robot only it seems to me. After that, we can remove lookup table
-tojava // from XWindow.c altogether.
-tojava // Another use for reverse lookup: query keyboard state, for some keys.
-tojava static Hashtable<Integer, Long> javaKeycode2KeysymHash = new Hashtable<Integer, Long>();
-tojava static long keysym_lowercase = unsafe.allocateMemory(Native.getLongSize());
-tojava static long keysym_uppercase = unsafe.allocateMemory(Native.getLongSize());
-tojava static Keysym2JavaKeycode kanaLock = new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK,
-tojava java.awt.event.KeyEvent.KEY_LOCATION_STANDARD);
-tojava private static PlatformLogger keyEventLog = PlatformLogger.getLogger("sun.awt.X11.kye.XKeysym");
-tojava public static char convertKeysym( long ks, int state ) {
-tojava
-tojava /* First check for Latin-1 characters (1:1 mapping) */
-tojava if ((ks >= 0x0020 && ks <= 0x007e) ||
-tojava (ks >= 0x00a0 && ks <= 0x00ff)) {
-tojava if( (state & XConstants.ControlMask) != 0 ) {
-tojava if ((ks >= 'A' && ks <= ']') || (ks == '_') ||
-tojava (ks >= 'a' && ks <='z')) {
-tojava ks &= 0x1F;
-tojava }
-tojava }
-tojava return (char)ks;
-tojava }
-tojava
-tojava /* XXX: Also check for directly encoded 24-bit UCS characters:
-tojava */
-tojava if ((ks & 0xff000000) == 0x01000000)
-tojava return (char)(ks & 0x00ffffff);
-tojava
-tojava Character ch = keysym2UCSHash.get(ks);
-tojava return ch == null ? (char)0 : ch.charValue();
-tojava }
-tojava static long xkeycode2keysym_noxkb(XKeyEvent ev, int ndx) {
-tojava XToolkit.awtLock();
-tojava try {
-tojava return XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx);
-tojava } finally {
-tojava XToolkit.awtUnlock();
-tojava }
-tojava }
-tojava static long xkeycode2keysym_xkb(XKeyEvent ev, int ndx) {
-tojava XToolkit.awtLock();
-tojava try {
-tojava int mods = ev.get_state();
-tojava if ((ndx == 0) && ((mods & XConstants.ShiftMask) != 0)) {
-tojava // I don't know all possible meanings of 'ndx' in case of XKB
-tojava // and don't want to speculate. But this particular case
-tojava // clearly means that caller needs a so called primary keysym.
-tojava mods ^= XConstants.ShiftMask;
-tojava }
-tojava long kbdDesc = XToolkit.getXKBKbdDesc();
-tojava if( kbdDesc != 0 ) {
-tojava XlibWrapper.XkbTranslateKeyCode(kbdDesc, ev.get_keycode(),
-tojava mods, XlibWrapper.iarg1, XlibWrapper.larg3);
-tojava }else{
-tojava // xkb resources already gone
-tojava keyEventLog.fine("Thread race: Toolkit shutdown before the end of a key event processing.");
-tojava return 0;
-tojava }
-tojava //XXX unconsumed modifiers?
-tojava return Native.getLong(XlibWrapper.larg3);
-tojava } finally {
-tojava XToolkit.awtUnlock();
-tojava }
-tojava }
-tojava static long xkeycode2keysym(XKeyEvent ev, int ndx) {
-tojava XToolkit.awtLock();
-tojava try {
-tojava if (XToolkit.canUseXKBCalls()) {
-tojava return xkeycode2keysym_xkb(ev, ndx);
-tojava }else{
-tojava return xkeycode2keysym_noxkb(ev, ndx);
-tojava }
-tojava } finally {
-tojava XToolkit.awtUnlock();
-tojava }
-tojava }
-tojava static long xkeycode2primary_keysym(XKeyEvent ev) {
-tojava return xkeycode2keysym(ev, 0);
-tojava }
-tojava public static boolean isKPEvent( XKeyEvent ev )
-tojava {
-tojava // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event.
-tojava // Otherwise, it is [1].
-tojava int ndx = XToolkit.isXsunKPBehavior() &&
-tojava ! XToolkit.isXKBenabled() ? 2 : 1;
-tojava // Even if XKB is enabled, we have another problem: some symbol tables (e.g. cz) force
-tojava // a regular comma instead of KP_comma for a decimal separator. Result is,
-tojava // bugs like 6454041. So, we will try for keypadness a keysym with ndx==0 as well.
-tojava XToolkit.awtLock();
-tojava try {
-tojava return (XlibWrapper.IsKeypadKey(
-tojava XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), ndx ) ) ||
-tojava XlibWrapper.IsKeypadKey(
-tojava XlibWrapper.XKeycodeToKeysym(ev.get_display(), ev.get_keycode(), 0 ) ));
-tojava } finally {
-tojava XToolkit.awtUnlock();
-tojava }
-tojava }
-tojava /**
-tojava Return uppercase keysym correspondent to a given keysym.
-tojava If input keysym does not belong to any lower/uppercase pair, return -1.
-tojava */
-tojava public static long getUppercaseAlphabetic( long keysym ) {
-tojava long lc = -1;
-tojava long uc = -1;
-tojava Long stored = uppercaseHash.get(keysym);
-tojava if (stored != null ) {
-tojava return stored.longValue();
-tojava }
-tojava XToolkit.awtLock();
-tojava try {
-tojava XlibWrapper.XConvertCase(keysym, keysym_lowercase, keysym_uppercase);
-tojava lc = Native.getLong(keysym_lowercase);
-tojava uc = Native.getLong(keysym_uppercase);
-tojava if (lc == uc) {
-tojava //not applicable
-tojava uc = -1;
-tojava }
-tojava uppercaseHash.put(keysym, uc);
-tojava } finally {
-tojava XToolkit.awtUnlock();
-tojava }
-tojava return uc;
-tojava }
-tojava /**
-tojava Get a keypad keysym derived from a keycode.
-tojava I do not check if this is a keypad event, I just presume it.
-tojava */
-tojava private static long getKeypadKeysym( XKeyEvent ev ) {
-tojava int ndx = 0;
-tojava long keysym = XConstants.NoSymbol;
-tojava if( XToolkit.isXsunKPBehavior() &&
-tojava ! XToolkit.isXKBenabled() ) {
-tojava if( (ev.get_state() & XConstants.ShiftMask) != 0 ) { // shift modifier is on
-tojava ndx = 3;
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava } else {
-tojava ndx = 2;
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava }
-tojava } else {
-tojava if( (ev.get_state() & XConstants.ShiftMask) != 0 || // shift modifier is on
-tojava ((ev.get_state() & XConstants.LockMask) != 0 && // lock modifier is on
-tojava (XToolkit.modLockIsShiftLock != 0)) ) { // it is interpreted as ShiftLock
-tojava ndx = 0;
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava } else {
-tojava ndx = 1;
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava }
-tojava }
-tojava return keysym;
-tojava }
-tojava
-tojava /**
-tojava Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X keysym.
-tojava Some keysyms maps to more than one keycode, these would require extra processing.
-tojava */
-tojava static Keysym2JavaKeycode getJavaKeycode( long keysym ) {
-tojava if(keysym == XKeySymConstants.XK_Mode_switch){
-tojava /* XK_Mode_switch on solaris maps either to VK_ALT_GRAPH (default) or VK_KANA_LOCK */
-tojava if( XToolkit.isKanaKeyboard() ) {
-tojava return kanaLock;
-tojava }
-tojava }else if(keysym == XKeySymConstants.XK_L1){
-tojava /* if it is Sun keyboard, trick hash to return VK_STOP else VK_F11 (default) */
-tojava if( XToolkit.isSunKeyboard() ) {
-tojava keysym = XKeySymConstants.SunXK_Stop;
-tojava }
-tojava }else if(keysym == XKeySymConstants.XK_L2) {
-tojava /* if it is Sun keyboard, trick hash to return VK_AGAIN else VK_F12 (default) */
-tojava if( XToolkit.isSunKeyboard() ) {
-tojava keysym = XKeySymConstants.SunXK_Again;
-tojava }
-tojava }
-tojava
-tojava return keysym2JavaKeycodeHash.get( keysym );
-tojava }
-tojava /**
-tojava Return java.awt.KeyEvent constant meaning (Java) keycode, derived from X Window KeyEvent.
-tojava Algorithm is, extract via XKeycodeToKeysym a proper keysym according to Xlib spec rules and
-tojava err exceptions, then search a java keycode in a table.
-tojava */
-tojava static Keysym2JavaKeycode getJavaKeycode( XKeyEvent ev ) {
-tojava // get from keysym2JavaKeycodeHash.
-tojava long keysym = XConstants.NoSymbol;
-tojava int ndx = 0;
-tojava if( (ev.get_state() & XToolkit.numLockMask) != 0 &&
-tojava isKPEvent(ev)) {
-tojava keysym = getKeypadKeysym( ev );
-tojava } else {
-tojava // we only need primary-layer keysym to derive a java keycode.
-tojava ndx = 0;
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava }
-tojava
-tojava Keysym2JavaKeycode jkc = getJavaKeycode( keysym );
-tojava return jkc;
-tojava }
-tojava static int getJavaKeycodeOnly( XKeyEvent ev ) {
-tojava Keysym2JavaKeycode jkc = getJavaKeycode( ev );
-tojava return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
-tojava }
-tojava /**
-tojava * Return an integer java keycode apprx as it was before extending keycodes range.
-tojava * This call would ignore for instance XKB and process whatever is on the bottom
-tojava * of keysym stack. Result will not depend on actual locale, will differ between
-tojava * dual/multiple keyboard setup systems (e.g. English+Russian vs French+Russian)
-tojava * but will be someway compatible with old releases.
-tojava */
-tojava static int getLegacyJavaKeycodeOnly( XKeyEvent ev ) {
-tojava long keysym = XConstants.NoSymbol;
-tojava int ndx = 0;
-tojava if( (ev.get_state() & XToolkit.numLockMask) != 0 &&
-tojava isKPEvent(ev)) {
-tojava keysym = getKeypadKeysym( ev );
-tojava } else {
-tojava // we only need primary-layer keysym to derive a java keycode.
-tojava ndx = 0;
-tojava keysym = xkeycode2keysym_noxkb(ev, ndx);
-tojava }
-tojava Keysym2JavaKeycode jkc = getJavaKeycode( keysym );
-tojava return jkc == null ? java.awt.event.KeyEvent.VK_UNDEFINED : jkc.getJavaKeycode();
-tojava }
-tojava static long javaKeycode2Keysym( int jkey ) {
-tojava Long ks = javaKeycode2KeysymHash.get( jkey );
-tojava return (ks == null ? 0 : ks.longValue());
-tojava }
-tojava /**
-tojava Return keysym derived from a keycode and modifiers.
-tojava Usually an input method does this. However non-system input methods (e.g. Java IMs) do not.
-tojava For rules, see "Xlib - C Language X Interface",
-tojava MIT X Consortium Standard
-tojava X Version 11, Release 6
-tojava Ch. 12.7
-tojava XXX TODO: or maybe not to do: process Mode Lock and therefore
-tojava not only 0-th and 1-st but 2-nd and 3-rd keysyms for a keystroke.
-tojava */
-tojava static long getKeysym( XKeyEvent ev ) {
-tojava long keysym = XConstants.NoSymbol;
-tojava long uppercaseKeysym = XConstants.NoSymbol;
-tojava int ndx = 0;
-tojava boolean getUppercase = false;
-tojava if ((ev.get_state() & XToolkit.numLockMask) != 0 &&
-tojava isKPEvent(ev)) {
-tojava keysym = getKeypadKeysym( ev );
-tojava } else {
-tojava // XXX: at this point, anything in keysym[23] is ignored.
-tojava //
-tojava // Shift & Lock are off ===> ndx = 0;
-tojava // Shift off & Lock on & Lock is CapsLock ===> ndx = 0;
-tojava // if keysym[ndx] is lowecase alphabetic, then corresp. uppercase used.
-tojava // Shift on & Lock on & Lock is CapsLock ===> ndx == 1;
-tojava // if keysym[ndx] is lowecase alphabetic, then corresp. uppercase used.
-tojava // Shift on || (Lock on & Lock is ShiftLock) ===> ndx = 1.
-tojava if ((ev.get_state() & XConstants.ShiftMask) == 0) { // shift is off
-tojava if ((ev.get_state() & XConstants.LockMask) == 0 ) { // lock is off
-tojava ndx = 0;
-tojava getUppercase = false;
-tojava } else if ((ev.get_state() & XConstants.LockMask) != 0 && // lock is on
-tojava (XToolkit.modLockIsShiftLock == 0)) { // lock is capslock
-tojava ndx = 0;
-tojava getUppercase = true;
-tojava } else if ((ev.get_state() & XConstants.LockMask) != 0 && // lock is on
-tojava (XToolkit.modLockIsShiftLock != 0)) { // lock is shift lock
-tojava ndx = 1;
-tojava getUppercase = false;
-tojava }
-tojava } else { // shift on
-tojava if ((ev.get_state() & XConstants.LockMask) != 0 && // lock is on
-tojava (XToolkit.modLockIsShiftLock == 0)) { // lock is capslock
-tojava ndx = 1;
-tojava getUppercase = true;
-tojava } else {
-tojava ndx = 1;
-tojava getUppercase = false;
-tojava }
-tojava }
-tojava keysym = xkeycode2keysym(ev, ndx);
-tojava if (getUppercase && (uppercaseKeysym = getUppercaseAlphabetic( keysym )) != -1) {
-tojava keysym = uppercaseKeysym;
-tojava }
-tojava }
-tojava return keysym;
-tojava }
-tojava
-tojava static {
-
-/***********************************************************
-Copyright 1987, 1994, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/*
- * TTY Functions, cleverly chosen to map to ascii, for convenience of
- * programming, but could have been arbitrary (at the cost of lookup
- * tables in client code.
- */
-
-0x0008 #define XK_BackSpace 0xFF08 /* back space, back char */
-0x0009 #define XK_Tab 0xFF09
-0x000a #define XK_Linefeed 0xFF0A /* Linefeed, LF */
-0x000b #define XK_Clear 0xFF0B
-/*XXX map to 0a instead of 0d - why? for some good reason I hope */
-0x000a #define XK_Return 0xFF0D /* Return, enter */
-0x0000 #define XK_Pause 0xFF13 /* Pause, hold */
-0x0000 #define XK_Scroll_Lock 0xFF14
-0x0000 #define XK_Sys_Req 0xFF15
-0x001B #define XK_Escape 0xFF1B
-0x007F #define XK_Delete 0xFFFF /* Delete, rubout */
-
-
-
-/* International & multi-key character composition */
-
-0x0000 #define XK_Multi_key 0xFF20 /* Multi-key character compose */
-0x0000 #define XK_Codeinput 0xFF37
-0x0000 #define XK_SingleCandidate 0xFF3C
-0x0000 #define XK_MultipleCandidate 0xFF3D
-0x0000 #define XK_PreviousCandidate 0xFF3E
-
-/* Japanese keyboard support */
-
-0x0000 #define XK_Kanji 0xFF21 /* Kanji, Kanji convert */
-0x0000 #define XK_Muhenkan 0xFF22 /* Cancel Conversion */
-0x0000 #define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */
-0x0000 #define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */
-0x0000 #define XK_Romaji 0xFF24 /* to Romaji */
-0x0000 #define XK_Hiragana 0xFF25 /* to Hiragana */
-0x0000 #define XK_Katakana 0xFF26 /* to Katakana */
-0x0000 #define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */
-0x0000 #define XK_Zenkaku 0xFF28 /* to Zenkaku */
-0x0000 #define XK_Hankaku 0xFF29 /* to Hankaku */
-0x0000 #define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */
-0x0000 #define XK_Touroku 0xFF2B /* Add to Dictionary */
-0x0000 #define XK_Massyo 0xFF2C /* Delete from Dictionary */
-0x0000 #define XK_Kana_Lock 0xFF2D /* Kana Lock */
-0x0000 #define XK_Kana_Shift 0xFF2E /* Kana Shift */
-0x0000 #define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */
-0x0000 #define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */
-0x0000 #define XK_Kanji_Bangou 0xFF37 /* Codeinput */
-0x0000 #define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */
-0x0000 #define XK_Mae_Koho 0xFF3E /* Previous Candidate */
-
-/* Cursor control & motion */
-
-0x0000 #define XK_Home 0xFF50
-0x0000 #define XK_Left 0xFF51 /* Move left, left arrow */
-0x0000 #define XK_Up 0xFF52 /* Move up, up arrow */
-0x0000 #define XK_Right 0xFF53 /* Move right, right arrow */
-0x0000 #define XK_Down 0xFF54 /* Move down, down arrow */
-0x0000 #define XK_Prior 0xFF55 /* Prior, previous */
-0x0000 #define XK_Page_Up 0xFF55
-0x0000 #define XK_Next 0xFF56 /* Next */
-0x0000 #define XK_Page_Down 0xFF56
-0x0000 #define XK_End 0xFF57 /* EOL */
-0x0000 #define XK_Begin 0xFF58 /* BOL */
-
-
-/* Misc Functions */
-
-0x0000 #define XK_Select 0xFF60 /* Select, mark */
-0x0000 #define XK_Print 0xFF61
-0x0000 #define XK_Execute 0xFF62 /* Execute, run, do */
-0x0000 #define XK_Insert 0xFF63 /* Insert, insert here */
-0x0000 #define XK_Undo 0xFF65 /* Undo, oops */
-0x0000 #define XK_Redo 0xFF66 /* redo, again */
-0x0000 #define XK_Menu 0xFF67
-0x0000 #define XK_Find 0xFF68 /* Find, search */
-0x0000 #define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */
-0x0000 #define XK_Help 0xFF6A /* Help */
-0x0000 #define XK_Break 0xFF6B
-0x0000 #define XK_Mode_switch 0xFF7E /* Character set switch */
-0x0000 #define XK_script_switch 0xFF7E /* Alias for mode_switch */
-0x0000 #define XK_Num_Lock 0xFF7F
-
-/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */
-
-0x0020 #define XK_KP_Space 0xFF80 /* space */
-0x0009 #define XK_KP_Tab 0xFF89
-0x000A #define XK_KP_Enter 0xFF8D /* enter: note that it is again 0A */
-0x0000 #define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */
-0x0000 #define XK_KP_F2 0xFF92
-0x0000 #define XK_KP_F3 0xFF93
-0x0000 #define XK_KP_F4 0xFF94
-0x0000 #define XK_KP_Home 0xFF95
-0x0000 #define XK_KP_Left 0xFF96
-0x0000 #define XK_KP_Up 0xFF97
-0x0000 #define XK_KP_Right 0xFF98
-0x0000 #define XK_KP_Down 0xFF99
-0x0000 #define XK_KP_Prior 0xFF9A
-0x0000 #define XK_KP_Page_Up 0xFF9A
-0x0000 #define XK_KP_Next 0xFF9B
-0x0000 #define XK_KP_Page_Down 0xFF9B
-0x0000 #define XK_KP_End 0xFF9C
-0x0000 #define XK_KP_Begin 0xFF9D
-0x0000 #define XK_KP_Insert 0xFF9E
-0x007F #define XK_KP_Delete 0xFF9F
-0x003d #define XK_KP_Equal 0xFFBD /* equals */
-0x002a #define XK_KP_Multiply 0xFFAA
-0x002b #define XK_KP_Add 0xFFAB
-0x002c #define XK_KP_Separator 0xFFAC /* separator, often comma */
-0x002d #define XK_KP_Subtract 0xFFAD
-0x002e #define XK_KP_Decimal 0xFFAE
-0x002f #define XK_KP_Divide 0xFFAF
-
-0x0030 #define XK_KP_0 0xFFB0
-0x0031 #define XK_KP_1 0xFFB1
-0x0032 #define XK_KP_2 0xFFB2
-0x0033 #define XK_KP_3 0xFFB3
-0x0034 #define XK_KP_4 0xFFB4
-0x0035 #define XK_KP_5 0xFFB5
-0x0036 #define XK_KP_6 0xFFB6
-0x0037 #define XK_KP_7 0xFFB7
-0x0038 #define XK_KP_8 0xFFB8
-0x0039 #define XK_KP_9 0xFFB9
-
-
-
-/*
- * Auxilliary Functions; note the duplicate definitions for left and right
- * function keys; Sun keyboards and a few other manufactures have such
- * function key groups on the left and/or right sides of the keyboard.
- * We've not found a keyboard with more than 35 function keys total.
- */
-
-0x0000 #define XK_F1 0xFFBE
-0x0000 #define XK_F2 0xFFBF
-0x0000 #define XK_F3 0xFFC0
-0x0000 #define XK_F4 0xFFC1
-0x0000 #define XK_F5 0xFFC2
-0x0000 #define XK_F6 0xFFC3
-0x0000 #define XK_F7 0xFFC4
-0x0000 #define XK_F8 0xFFC5
-0x0000 #define XK_F9 0xFFC6
-0x0000 #define XK_F10 0xFFC7
-0x0000 #define XK_F11 0xFFC8
-0x0000 #define XK_L1 0xFFC8
-0x0000 #define XK_F12 0xFFC9
-0x0000 #define XK_L2 0xFFC9
-0x0000 #define XK_F13 0xFFCA
-0x0000 #define XK_L3 0xFFCA
-0x0000 #define XK_F14 0xFFCB
-0x0000 #define XK_L4 0xFFCB
-0x0000 #define XK_F15 0xFFCC
-0x0000 #define XK_L5 0xFFCC
-0x0000 #define XK_F16 0xFFCD
-0x0000 #define XK_L6 0xFFCD
-0x0000 #define XK_F17 0xFFCE
-0x0000 #define XK_L7 0xFFCE
-0x0000 #define XK_F18 0xFFCF
-0x0000 #define XK_L8 0xFFCF
-0x0000 #define XK_F19 0xFFD0
-0x0000 #define XK_L9 0xFFD0
-0x0000 #define XK_F20 0xFFD1
-0x0000 #define XK_L10 0xFFD1
-0x0000 #define XK_F21 0xFFD2
-0x0000 #define XK_R1 0xFFD2
-0x0000 #define XK_F22 0xFFD3
-0x0000 #define XK_R2 0xFFD3
-0x0000 #define XK_F23 0xFFD4
-0x0000 #define XK_R3 0xFFD4
-0x0000 #define XK_F24 0xFFD5
-0x0000 #define XK_R4 0xFFD5
-0x0000 #define XK_F25 0xFFD6
-0x0000 #define XK_R5 0xFFD6
-0x0000 #define XK_F26 0xFFD7
-0x0000 #define XK_R6 0xFFD7
-0x0000 #define XK_F27 0xFFD8
-0x0000 #define XK_R7 0xFFD8
-0x0000 #define XK_F28 0xFFD9
-0x0000 #define XK_R8 0xFFD9
-0x0000 #define XK_F29 0xFFDA
-0x0000 #define XK_R9 0xFFDA
-0x0000 #define XK_F30 0xFFDB
-0x0000 #define XK_R10 0xFFDB
-0x0000 #define XK_F31 0xFFDC
-0x0000 #define XK_R11 0xFFDC
-0x0000 #define XK_F32 0xFFDD
-0x0000 #define XK_R12 0xFFDD
-0x0000 #define XK_F33 0xFFDE
-0x0000 #define XK_R13 0xFFDE
-0x0000 #define XK_F34 0xFFDF
-0x0000 #define XK_R14 0xFFDF
-0x0000 #define XK_F35 0xFFE0
-0x0000 #define XK_R15 0xFFE0
-
-/* Modifiers */
-
-0x0000 #define XK_Shift_L 0xFFE1 /* Left shift */
-0x0000 #define XK_Shift_R 0xFFE2 /* Right shift */
-0x0000 #define XK_Control_L 0xFFE3 /* Left control */
-0x0000 #define XK_Control_R 0xFFE4 /* Right control */
-0x0000 #define XK_Caps_Lock 0xFFE5 /* Caps lock */
-0x0000 #define XK_Shift_Lock 0xFFE6 /* Shift lock */
-
-0x0000 #define XK_Meta_L 0xFFE7 /* Left meta */
-0x0000 #define XK_Meta_R 0xFFE8 /* Right meta */
-0x0000 #define XK_Alt_L 0xFFE9 /* Left alt */
-0x0000 #define XK_Alt_R 0xFFEA /* Right alt */
-0x0000 #define XK_Super_L 0xFFEB /* Left super */
-0x0000 #define XK_Super_R 0xFFEC /* Right super */
-0x0000 #define XK_Hyper_L 0xFFED /* Left hyper */
-0x0000 #define XK_Hyper_R 0xFFEE /* Right hyper */
-#endif /* XK_MISCELLANY */
-
-/*
- * ISO 9995 Function and Modifier Keys
- * Byte 3 = 0xFE
- */
-
-#ifdef XK_XKB_KEYS
-0x0000 #define XK_ISO_Lock 0xFE01
-0x0000 #define XK_ISO_Level2_Latch 0xFE02
-0x0000 #define XK_ISO_Level3_Shift 0xFE03
-0x0000 #define XK_ISO_Level3_Latch 0xFE04
-0x0000 #define XK_ISO_Level3_Lock 0xFE05
-0x0000 #define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */
-0x0000 #define XK_ISO_Group_Latch 0xFE06
-0x0000 #define XK_ISO_Group_Lock 0xFE07
-0x0000 #define XK_ISO_Next_Group 0xFE08
-0x0000 #define XK_ISO_Next_Group_Lock 0xFE09
-0x0000 #define XK_ISO_Prev_Group 0xFE0A
-0x0000 #define XK_ISO_Prev_Group_Lock 0xFE0B
-0x0000 #define XK_ISO_First_Group 0xFE0C
-0x0000 #define XK_ISO_First_Group_Lock 0xFE0D
-0x0000 #define XK_ISO_Last_Group 0xFE0E
-0x0000 #define XK_ISO_Last_Group_Lock 0xFE0F
-
-0x0009 #define XK_ISO_Left_Tab 0xFE20
-0x0000 #define XK_ISO_Move_Line_Up 0xFE21
-0x0000 #define XK_ISO_Move_Line_Down 0xFE22
-0x0000 #define XK_ISO_Partial_Line_Up 0xFE23
-0x0000 #define XK_ISO_Partial_Line_Down 0xFE24
-0x0000 #define XK_ISO_Partial_Space_Left 0xFE25
-0x0000 #define XK_ISO_Partial_Space_Right 0xFE26
-0x0000 #define XK_ISO_Set_Margin_Left 0xFE27
-0x0000 #define XK_ISO_Set_Margin_Right 0xFE28
-0x0000 #define XK_ISO_Release_Margin_Left 0xFE29
-0x0000 #define XK_ISO_Release_Margin_Right 0xFE2A
-0x0000 #define XK_ISO_Release_Both_Margins 0xFE2B
-0x0000 #define XK_ISO_Fast_Cursor_Left 0xFE2C
-0x0000 #define XK_ISO_Fast_Cursor_Right 0xFE2D
-0x0000 #define XK_ISO_Fast_Cursor_Up 0xFE2E
-0x0000 #define XK_ISO_Fast_Cursor_Down 0xFE2F
-0x0000 #define XK_ISO_Continuous_Underline 0xFE30
-0x0000 #define XK_ISO_Discontinuous_Underline 0xFE31
-0x0000 #define XK_ISO_Emphasize 0xFE32
-0x0000 #define XK_ISO_Center_Object 0xFE33
-0x0000 #define XK_ISO_Enter 0xFE34
-
-0x02CB #define XK_dead_grave 0xFE50
-0x02CA #define XK_dead_acute 0xFE51
-0x02C6 #define XK_dead_circumflex 0xFE52
-0x02DC #define XK_dead_tilde 0xFE53
-0x02C9 #define XK_dead_macron 0xFE54
-0x02D8 #define XK_dead_breve 0xFE55
-0x02D9 #define XK_dead_abovedot 0xFE56
-0x00A8 #define XK_dead_diaeresis 0xFE57
-0x02DA #define XK_dead_abovering 0xFE58
-0x02DD #define XK_dead_doubleacute 0xFE59
-0x02C7 #define XK_dead_caron 0xFE5A
-0x00B8 #define XK_dead_cedilla 0xFE5B
-0x02DB #define XK_dead_ogonek 0xFE5C
-0x0269 #define XK_dead_iota 0xFE5D
-0x3099 #define XK_dead_voiced_sound 0xFE5E
-0x309A #define XK_dead_semivoiced_sound 0xFE5F
-0x0323 #define XK_dead_belowdot 0xFE60
-0x0321 #define XK_dead_hook 0xFE61
-0x031B #define XK_dead_horn 0xFE62
-
-0x0000 #define XK_First_Virtual_Screen 0xFED0
-0x0000 #define XK_Prev_Virtual_Screen 0xFED1
-0x0000 #define XK_Next_Virtual_Screen 0xFED2
-0x0000 #define XK_Last_Virtual_Screen 0xFED4
-0x0000 #define XK_Terminate_Server 0xFED5
-
-0x0000 #define XK_AccessX_Enable 0xFE70
-0x0000 #define XK_AccessX_Feedback_Enable 0xFE71
-0x0000 #define XK_RepeatKeys_Enable 0xFE72
-0x0000 #define XK_SlowKeys_Enable 0xFE73
-0x0000 #define XK_BounceKeys_Enable 0xFE74
-0x0000 #define XK_StickyKeys_Enable 0xFE75
-0x0000 #define XK_MouseKeys_Enable 0xFE76
-0x0000 #define XK_MouseKeys_Accel_Enable 0xFE77
-0x0000 #define XK_Overlay1_Enable 0xFE78
-0x0000 #define XK_Overlay2_Enable 0xFE79
-0x0000 #define XK_AudibleBell_Enable 0xFE7A
-
-0x0000 #define XK_Pointer_Left 0xFEE0
-0x0000 #define XK_Pointer_Right 0xFEE1
-0x0000 #define XK_Pointer_Up 0xFEE2
-0x0000 #define XK_Pointer_Down 0xFEE3
-0x0000 #define XK_Pointer_UpLeft 0xFEE4
-0x0000 #define XK_Pointer_UpRight 0xFEE5
-0x0000 #define XK_Pointer_DownLeft 0xFEE6
-0x0000 #define XK_Pointer_DownRight 0xFEE7
-0x0000 #define XK_Pointer_Button_Dflt 0xFEE8
-0x0000 #define XK_Pointer_Button1 0xFEE9
-0x0000 #define XK_Pointer_Button2 0xFEEA
-0x0000 #define XK_Pointer_Button3 0xFEEB
-0x0000 #define XK_Pointer_Button4 0xFEEC
-0x0000 #define XK_Pointer_Button5 0xFEED
-0x0000 #define XK_Pointer_DblClick_Dflt 0xFEEE
-0x0000 #define XK_Pointer_DblClick1 0xFEEF
-0x0000 #define XK_Pointer_DblClick2 0xFEF0
-0x0000 #define XK_Pointer_DblClick3 0xFEF1
-0x0000 #define XK_Pointer_DblClick4 0xFEF2
-0x0000 #define XK_Pointer_DblClick5 0xFEF3
-0x0000 #define XK_Pointer_Drag_Dflt 0xFEF4
-0x0000 #define XK_Pointer_Drag1 0xFEF5
-0x0000 #define XK_Pointer_Drag2 0xFEF6
-0x0000 #define XK_Pointer_Drag3 0xFEF7
-0x0000 #define XK_Pointer_Drag4 0xFEF8
-0x0000 #define XK_Pointer_Drag5 0xFEFD
-
-0x0000 #define XK_Pointer_EnableKeys 0xFEF9
-0x0000 #define XK_Pointer_Accelerate 0xFEFA
-0x0000 #define XK_Pointer_DfltBtnNext 0xFEFB
-0x0000 #define XK_Pointer_DfltBtnPrev 0xFEFC
-
-#endif
-
-/*
- * 3270 Terminal Keys
- * Byte 3 = 0xFD
- */
-
-#ifdef XK_3270
-0x0000 #define XK_3270_Duplicate 0xFD01
-0x0000 #define XK_3270_FieldMark 0xFD02
-0x0000 #define XK_3270_Right2 0xFD03
-0x0000 #define XK_3270_Left2 0xFD04
-0x0000 #define XK_3270_BackTab 0xFD05
-0x0000 #define XK_3270_EraseEOF 0xFD06
-0x0000 #define XK_3270_EraseInput 0xFD07
-0x0000 #define XK_3270_Reset 0xFD08
-0x0000 #define XK_3270_Quit 0xFD09
-0x0000 #define XK_3270_PA1 0xFD0A
-0x0000 #define XK_3270_PA2 0xFD0B
-0x0000 #define XK_3270_PA3 0xFD0C
-0x0000 #define XK_3270_Test 0xFD0D
-0x0000 #define XK_3270_Attn 0xFD0E
-0x0000 #define XK_3270_CursorBlink 0xFD0F
-0x0000 #define XK_3270_AltCursor 0xFD10
-0x0000 #define XK_3270_KeyClick 0xFD11
-0x0000 #define XK_3270_Jump 0xFD12
-0x0000 #define XK_3270_Ident 0xFD13
-0x0000 #define XK_3270_Rule 0xFD14
-0x0000 #define XK_3270_Copy 0xFD15
-0x0000 #define XK_3270_Play 0xFD16
-0x0000 #define XK_3270_Setup 0xFD17
-0x0000 #define XK_3270_Record 0xFD18
-0x0000 #define XK_3270_ChangeScreen 0xFD19
-0x0000 #define XK_3270_DeleteWord 0xFD1A
-0x0000 #define XK_3270_ExSelect 0xFD1B
-0x0000 #define XK_3270_CursorSelect 0xFD1C
-0x0000 #define XK_3270_PrintScreen 0xFD1D
-0x0000 #define XK_3270_Enter 0xFD1E
-#endif
-
-/*
- * Latin 1
- * Byte 3 = 0
- */
-// yan: skip Latin1 as it is mapped to Unicode 1:1
-#ifdef XK_LATIN1
-0x0000 #define XK_space 0x020
-0x0000 #define XK_exclam 0x021
-0x0000 #define XK_quotedbl 0x022
-0x0000 #define XK_numbersign 0x023
-0x0000 #define XK_dollar 0x024
-0x0000 #define XK_percent 0x025
-0x0000 #define XK_ampersand 0x026
-0x0000 #define XK_apostrophe 0x027
-0x0000 #define XK_quoteright 0x027 /* deprecated */
-0x0000 #define XK_parenleft 0x028
-0x0000 #define XK_parenright 0x029
-0x0000 #define XK_asterisk 0x02a
-0x0000 #define XK_plus 0x02b
-0x0000 #define XK_comma 0x02c
-0x0000 #define XK_minus 0x02d
-0x0000 #define XK_period 0x02e
-0x0000 #define XK_slash 0x02f
-0x0000 #define XK_0 0x030
-0x0000 #define XK_1 0x031
-0x0000 #define XK_2 0x032
-0x0000 #define XK_3 0x033
-0x0000 #define XK_4 0x034
-0x0000 #define XK_5 0x035
-0x0000 #define XK_6 0x036
-0x0000 #define XK_7 0x037
-0x0000 #define XK_8 0x038
-0x0000 #define XK_9 0x039
-0x0000 #define XK_colon 0x03a
-0x0000 #define XK_semicolon 0x03b
-0x0000 #define XK_less 0x03c
-0x0000 #define XK_equal 0x03d
-0x0000 #define XK_greater 0x03e
-0x0000 #define XK_question 0x03f
-0x0000 #define XK_at 0x040
-0x0000 #define XK_A 0x041
-0x0000 #define XK_B 0x042
-0x0000 #define XK_C 0x043
-0x0000 #define XK_D 0x044
-0x0000 #define XK_E 0x045
-0x0000 #define XK_F 0x046
-0x0000 #define XK_G 0x047
-0x0000 #define XK_H 0x048
-0x0000 #define XK_I 0x049
-0x0000 #define XK_J 0x04a
-0x0000 #define XK_K 0x04b
-0x0000 #define XK_L 0x04c
-0x0000 #define XK_M 0x04d
-0x0000 #define XK_N 0x04e
-0x0000 #define XK_O 0x04f
-0x0000 #define XK_P 0x050
-0x0000 #define XK_Q 0x051
-0x0000 #define XK_R 0x052
-0x0000 #define XK_S 0x053
-0x0000 #define XK_T 0x054
-0x0000 #define XK_U 0x055
-0x0000 #define XK_V 0x056
-0x0000 #define XK_W 0x057
-0x0000 #define XK_X 0x058
-0x0000 #define XK_Y 0x059
-0x0000 #define XK_Z 0x05a
-0x0000 #define XK_bracketleft 0x05b
-0x0000 #define XK_backslash 0x05c
-0x0000 #define XK_bracketright 0x05d
-0x0000 #define XK_asciicircum 0x05e
-0x0000 #define XK_underscore 0x05f
-0x0000 #define XK_grave 0x060
-0x0000 #define XK_quoteleft 0x060 /* deprecated */
-0x0000 #define XK_a 0x061
-0x0000 #define XK_b 0x062
-0x0000 #define XK_c 0x063
-0x0000 #define XK_d 0x064
-0x0000 #define XK_e 0x065
-0x0000 #define XK_f 0x066
-0x0000 #define XK_g 0x067
-0x0000 #define XK_h 0x068
-0x0000 #define XK_i 0x069
-0x0000 #define XK_j 0x06a
-0x0000 #define XK_k 0x06b
-0x0000 #define XK_l 0x06c
-0x0000 #define XK_m 0x06d
-0x0000 #define XK_n 0x06e
-0x0000 #define XK_o 0x06f
-0x0000 #define XK_p 0x070
-0x0000 #define XK_q 0x071
-0x0000 #define XK_r 0x072
-0x0000 #define XK_s 0x073
-0x0000 #define XK_t 0x074
-0x0000 #define XK_u 0x075
-0x0000 #define XK_v 0x076
-0x0000 #define XK_w 0x077
-0x0000 #define XK_x 0x078
-0x0000 #define XK_y 0x079
-0x0000 #define XK_z 0x07a
-0x0000 #define XK_braceleft 0x07b
-0x0000 #define XK_bar 0x07c
-0x0000 #define XK_braceright 0x07d
-0x0000 #define XK_asciitilde 0x07e
-
-0x0000 #define XK_nobreakspace 0x0a0
-0x0000 #define XK_exclamdown 0x0a1
-0x0000 #define XK_cent 0x0a2
-0x0000 #define XK_sterling 0x0a3
-0x0000 #define XK_currency 0x0a4
-0x0000 #define XK_yen 0x0a5
-0x0000 #define XK_brokenbar 0x0a6
-0x0000 #define XK_section 0x0a7
-0x0000 #define XK_diaeresis 0x0a8
-0x0000 #define XK_copyright 0x0a9
-0x0000 #define XK_ordfeminine 0x0aa
-0x0000 #define XK_guillemotleft 0x0ab /* left angle quotation mark */
-0x0000 #define XK_notsign 0x0ac
-0x0000 #define XK_hyphen 0x0ad
-0x0000 #define XK_registered 0x0ae
-0x0000 #define XK_macron 0x0af
-0x0000 #define XK_degree 0x0b0
-0x0000 #define XK_plusminus 0x0b1
-0x0000 #define XK_twosuperior 0x0b2
-0x0000 #define XK_threesuperior 0x0b3
-0x0000 #define XK_acute 0x0b4
-0x0000 #define XK_mu 0x0b5
-0x0000 #define XK_paragraph 0x0b6
-0x0000 #define XK_periodcentered 0x0b7
-0x0000 #define XK_cedilla 0x0b8
-0x0000 #define XK_onesuperior 0x0b9
-0x0000 #define XK_masculine 0x0ba
-0x0000 #define XK_guillemotright 0x0bb /* right angle quotation mark */
-0x0000 #define XK_onequarter 0x0bc
-0x0000 #define XK_onehalf 0x0bd
-0x0000 #define XK_threequarters 0x0be
-0x0000 #define XK_questiondown 0x0bf
-0x0000 #define XK_Agrave 0x0c0
-0x0000 #define XK_Aacute 0x0c1
-0x0000 #define XK_Acircumflex 0x0c2
-0x0000 #define XK_Atilde 0x0c3
-0x0000 #define XK_Adiaeresis 0x0c4
-0x0000 #define XK_Aring 0x0c5
-0x0000 #define XK_AE 0x0c6
-0x0000 #define XK_Ccedilla 0x0c7
-0x0000 #define XK_Egrave 0x0c8
-0x0000 #define XK_Eacute 0x0c9
-0x0000 #define XK_Ecircumflex 0x0ca
-0x0000 #define XK_Ediaeresis 0x0cb
-0x0000 #define XK_Igrave 0x0cc
-0x0000 #define XK_Iacute 0x0cd
-0x0000 #define XK_Icircumflex 0x0ce
-0x0000 #define XK_Idiaeresis 0x0cf
-0x0000 #define XK_ETH 0x0d0
-0x0000 #define XK_Eth 0x0d0 /* deprecated */
-0x0000 #define XK_Ntilde 0x0d1
-0x0000 #define XK_Ograve 0x0d2
-0x0000 #define XK_Oacute 0x0d3
-0x0000 #define XK_Ocircumflex 0x0d4
-0x0000 #define XK_Otilde 0x0d5
-0x0000 #define XK_Odiaeresis 0x0d6
-0x0000 #define XK_multiply 0x0d7
-0x0000 #define XK_Ooblique 0x0d8
-0x0000 #define XK_Ugrave 0x0d9
-0x0000 #define XK_Uacute 0x0da
-0x0000 #define XK_Ucircumflex 0x0db
-0x0000 #define XK_Udiaeresis 0x0dc
-0x0000 #define XK_Yacute 0x0dd
-0x0000 #define XK_THORN 0x0de
-0x0000 #define XK_Thorn 0x0de /* deprecated */
-0x0000 #define XK_ssharp 0x0df
-0x0000 #define XK_agrave 0x0e0
-0x0000 #define XK_aacute 0x0e1
-0x0000 #define XK_acircumflex 0x0e2
-0x0000 #define XK_atilde 0x0e3
-0x0000 #define XK_adiaeresis 0x0e4
-0x0000 #define XK_aring 0x0e5
-0x0000 #define XK_ae 0x0e6
-0x0000 #define XK_ccedilla 0x0e7
-0x0000 #define XK_egrave 0x0e8
-0x0000 #define XK_eacute 0x0e9
-0x0000 #define XK_ecircumflex 0x0ea
-0x0000 #define XK_ediaeresis 0x0eb
-0x0000 #define XK_igrave 0x0ec
-0x0000 #define XK_iacute 0x0ed
-0x0000 #define XK_icircumflex 0x0ee
-0x0000 #define XK_idiaeresis 0x0ef
-0x0000 #define XK_eth 0x0f0
-0x0000 #define XK_ntilde 0x0f1
-0x0000 #define XK_ograve 0x0f2
-0x0000 #define XK_oacute 0x0f3
-0x0000 #define XK_ocircumflex 0x0f4
-0x0000 #define XK_otilde 0x0f5
-0x0000 #define XK_odiaeresis 0x0f6
-0x0000 #define XK_division 0x0f7
-0x0000 #define XK_oslash 0x0f8
-0x0000 #define XK_ugrave 0x0f9
-0x0000 #define XK_uacute 0x0fa
-0x0000 #define XK_ucircumflex 0x0fb
-0x0000 #define XK_udiaeresis 0x0fc
-0x0000 #define XK_yacute 0x0fd
-0x0000 #define XK_thorn 0x0fe
-0x0000 #define XK_ydiaeresis 0x0ff
-#endif /* XK_LATIN1 */
-
-/*
- * Latin 2
- * Byte 3 = 1
- */
-
-#ifdef XK_LATIN2
-0x0104 #define XK_Aogonek 0x1a1
-0x02d8 #define XK_breve 0x1a2
-0x0141 #define XK_Lstroke 0x1a3
-0x013d #define XK_Lcaron 0x1a5
-0x015a #define XK_Sacute 0x1a6
-0x0160 #define XK_Scaron 0x1a9
-0x015e #define XK_Scedilla 0x1aa
-0x0164 #define XK_Tcaron 0x1ab
-0x0179 #define XK_Zacute 0x1ac
-0x017d #define XK_Zcaron 0x1ae
-0x017b #define XK_Zabovedot 0x1af
-0x0105 #define XK_aogonek 0x1b1
-0x02db #define XK_ogonek 0x1b2
-0x0142 #define XK_lstroke 0x1b3
-0x013e #define XK_lcaron 0x1b5
-0x015b #define XK_sacute 0x1b6
-0x02c7 #define XK_caron 0x1b7
-0x0161 #define XK_scaron 0x1b9
-0x015f #define XK_scedilla 0x1ba
-0x0165 #define XK_tcaron 0x1bb
-0x017a #define XK_zacute 0x1bc
-0x02dd #define XK_doubleacute 0x1bd
-0x017e #define XK_zcaron 0x1be
-0x017c #define XK_zabovedot 0x1bf
-0x0154 #define XK_Racute 0x1c0
-0x0102 #define XK_Abreve 0x1c3
-0x0139 #define XK_Lacute 0x1c5
-0x0106 #define XK_Cacute 0x1c6
-0x010c #define XK_Ccaron 0x1c8
-0x0118 #define XK_Eogonek 0x1ca
-0x011a #define XK_Ecaron 0x1cc
-0x010e #define XK_Dcaron 0x1cf
-0x0110 #define XK_Dstroke 0x1d0
-0x0143 #define XK_Nacute 0x1d1
-0x0147 #define XK_Ncaron 0x1d2
-0x0150 #define XK_Odoubleacute 0x1d5
-0x0158 #define XK_Rcaron 0x1d8
-0x016e #define XK_Uring 0x1d9
-0x0170 #define XK_Udoubleacute 0x1db
-0x0162 #define XK_Tcedilla 0x1de
-0x0155 #define XK_racute 0x1e0
-0x0103 #define XK_abreve 0x1e3
-0x013a #define XK_lacute 0x1e5
-0x0107 #define XK_cacute 0x1e6
-0x010d #define XK_ccaron 0x1e8
-0x0119 #define XK_eogonek 0x1ea
-0x011b #define XK_ecaron 0x1ec
-0x010f #define XK_dcaron 0x1ef
-0x0111 #define XK_dstroke 0x1f0
-0x0144 #define XK_nacute 0x1f1
-0x0148 #define XK_ncaron 0x1f2
-0x0151 #define XK_odoubleacute 0x1f5
-0x0171 #define XK_udoubleacute 0x1fb
-0x0159 #define XK_rcaron 0x1f8
-0x016f #define XK_uring 0x1f9
-0x0163 #define XK_tcedilla 0x1fe
-0x02d9 #define XK_abovedot 0x1ff
-#endif /* XK_LATIN2 */
-
-/*
- * Latin 3
- * Byte 3 = 2
- */
-
-#ifdef XK_LATIN3
-0x0126 #define XK_Hstroke 0x2a1
-0x0124 #define XK_Hcircumflex 0x2a6
-0x0130 #define XK_Iabovedot 0x2a9
-0x011e #define XK_Gbreve 0x2ab
-0x0134 #define XK_Jcircumflex 0x2ac
-0x0127 #define XK_hstroke 0x2b1
-0x0125 #define XK_hcircumflex 0x2b6
-0x0131 #define XK_idotless 0x2b9
-0x011f #define XK_gbreve 0x2bb
-0x0135 #define XK_jcircumflex 0x2bc
-0x010a #define XK_Cabovedot 0x2c5
-0x0108 #define XK_Ccircumflex 0x2c6
-0x0120 #define XK_Gabovedot 0x2d5
-0x011c #define XK_Gcircumflex 0x2d8
-0x016c #define XK_Ubreve 0x2dd
-0x015c #define XK_Scircumflex 0x2de
-0x010b #define XK_cabovedot 0x2e5
-0x0109 #define XK_ccircumflex 0x2e6
-0x0121 #define XK_gabovedot 0x2f5
-0x011d #define XK_gcircumflex 0x2f8
-0x016d #define XK_ubreve 0x2fd
-0x015d #define XK_scircumflex 0x2fe
-#endif /* XK_LATIN3 */
-
-
-/*
- * Latin 4
- * Byte 3 = 3
- */
-
-#ifdef XK_LATIN4
-0x0138 #define XK_kra 0x3a2
-0x0000 #define XK_kappa 0x3a2 /* deprecated */
-0x0156 #define XK_Rcedilla 0x3a3
-0x0128 #define XK_Itilde 0x3a5
-0x013b #define XK_Lcedilla 0x3a6
-0x0112 #define XK_Emacron 0x3aa
-0x0122 #define XK_Gcedilla 0x3ab
-0x0166 #define XK_Tslash 0x3ac
-0x0157 #define XK_rcedilla 0x3b3
-0x0129 #define XK_itilde 0x3b5
-0x013c #define XK_lcedilla 0x3b6
-0x0113 #define XK_emacron 0x3ba
-0x0123 #define XK_gcedilla 0x3bb
-0x0167 #define XK_tslash 0x3bc
-0x014a #define XK_ENG 0x3bd
-0x014b #define XK_eng 0x3bf
-0x0100 #define XK_Amacron 0x3c0
-0x012e #define XK_Iogonek 0x3c7
-0x0116 #define XK_Eabovedot 0x3cc
-0x012a #define XK_Imacron 0x3cf
-0x0145 #define XK_Ncedilla 0x3d1
-0x014c #define XK_Omacron 0x3d2
-0x0136 #define XK_Kcedilla 0x3d3
-0x0172 #define XK_Uogonek 0x3d9
-0x0168 #define XK_Utilde 0x3dd
-0x016a #define XK_Umacron 0x3de
-0x0101 #define XK_amacron 0x3e0
-0x012f #define XK_iogonek 0x3e7
-0x0117 #define XK_eabovedot 0x3ec
-0x012b #define XK_imacron 0x3ef
-0x0146 #define XK_ncedilla 0x3f1
-0x014d #define XK_omacron 0x3f2
-0x0137 #define XK_kcedilla 0x3f3
-0x0173 #define XK_uogonek 0x3f9
-0x0169 #define XK_utilde 0x3fd
-0x016b #define XK_umacron 0x3fe
-#endif /* XK_LATIN4 */
-
-/*
- * Latin-8
- * Byte 3 = 18
- */
-#ifdef XK_LATIN8
-0x1e02 #define XK_Babovedot 0x12a1
-0x1e03 #define XK_babovedot 0x12a2
-0x1e0a #define XK_Dabovedot 0x12a6
-0x1e80 #define XK_Wgrave 0x12a8
-0x1e82 #define XK_Wacute 0x12aa
-0x1e0b #define XK_dabovedot 0x12ab
-0x1ef2 #define XK_Ygrave 0x12ac
-0x1e1e #define XK_Fabovedot 0x12b0
-0x1e1f #define XK_fabovedot 0x12b1
-0x1e40 #define XK_Mabovedot 0x12b4
-0x1e41 #define XK_mabovedot 0x12b5
-0x1e56 #define XK_Pabovedot 0x12b7
-0x1e81 #define XK_wgrave 0x12b8
-0x1e57 #define XK_pabovedot 0x12b9
-0x1e83 #define XK_wacute 0x12ba
-0x1e60 #define XK_Sabovedot 0x12bb
-0x1ef3 #define XK_ygrave 0x12bc
-0x1e84 #define XK_Wdiaeresis 0x12bd
-0x1e85 #define XK_wdiaeresis 0x12be
-0x1e61 #define XK_sabovedot 0x12bf
-0x017 4#define XK_Wcircumflex 0x12d0
-0x1e6a #define XK_Tabovedot 0x12d7
-0x0176 #define XK_Ycircumflex 0x12de
-0x0175 #define XK_wcircumflex 0x12f0
-0x1e6b #define XK_tabovedot 0x12f7
-0x0177 #define XK_ycircumflex 0x12fe
-#endif /* XK_LATIN8 */
-
-/*
- * Latin-9 (a.k.a. Latin-0)
- * Byte 3 = 19
- */
-
-#ifdef XK_LATIN9
-0x0152 #define XK_OE 0x13bc
-0x0153 #define XK_oe 0x13bd
-0x0178 #define XK_Ydiaeresis 0x13be
-#endif /* XK_LATIN9 */
-
-/*
- * Katakana
- * Byte 3 = 4
- */
-
-#ifdef XK_KATAKANA
-0x203e #define XK_overline 0x47e
-0x3002 #define XK_kana_fullstop 0x4a1
-0x300c #define XK_kana_openingbracket 0x4a2
-0x300d #define XK_kana_closingbracket 0x4a3
-0x3001 #define XK_kana_comma 0x4a4
-0x30fb #define XK_kana_conjunctive 0x4a5
-0x0000 #define XK_kana_middledot 0x4a5 /* deprecated */
-0x30f2 #define XK_kana_WO 0x4a6
-0x30a1 #define XK_kana_a 0x4a7
-0x30a3 #define XK_kana_i 0x4a8
-0x30a5 #define XK_kana_u 0x4a9
-0x30a7 #define XK_kana_e 0x4aa
-0x30a9 #define XK_kana_o 0x4ab
-0x30e3 #define XK_kana_ya 0x4ac
-0x30e5 #define XK_kana_yu 0x4ad
-0x30e7 #define XK_kana_yo 0x4ae
-0x30c3 #define XK_kana_tsu 0x4af
-0x0000 #define XK_kana_tu 0x4af /* deprecated */
-0x30fc #define XK_prolongedsound 0x4b0
-0x30a2 #define XK_kana_A 0x4b1
-0x30a4 #define XK_kana_I 0x4b2
-0x30a6 #define XK_kana_U 0x4b3
-0x30a8 #define XK_kana_E 0x4b4
-0x30aa #define XK_kana_O 0x4b5
-0x30ab #define XK_kana_KA 0x4b6
-0x30ad #define XK_kana_KI 0x4b7
-0x30af #define XK_kana_KU 0x4b8
-0x30b1 #define XK_kana_KE 0x4b9
-0x30b3 #define XK_kana_KO 0x4ba
-0x30b5 #define XK_kana_SA 0x4bb
-0x30b7 #define XK_kana_SHI 0x4bc
-0x30b9 #define XK_kana_SU 0x4bd
-0x30bb #define XK_kana_SE 0x4be
-0x30bd #define XK_kana_SO 0x4bf
-0x30bf #define XK_kana_TA 0x4c0
-0x30c1 #define XK_kana_CHI 0x4c1
-0x0000 #define XK_kana_TI 0x4c1 /* deprecated */
-0x30c4 #define XK_kana_TSU 0x4c2
-0x0000 #define XK_kana_TU 0x4c2 /* deprecated */
-0x30c6 #define XK_kana_TE 0x4c3
-0x30c8 #define XK_kana_TO 0x4c4
-0x30ca #define XK_kana_NA 0x4c5
-0x30cb #define XK_kana_NI 0x4c6
-0x30cc #define XK_kana_NU 0x4c7
-0x30cd #define XK_kana_NE 0x4c8
-0x30ce #define XK_kana_NO 0x4c9
-0x30cf #define XK_kana_HA 0x4ca
-0x30d2 #define XK_kana_HI 0x4cb
-0x30d5 #define XK_kana_FU 0x4cc
-0x0000 #define XK_kana_HU 0x4cc /* deprecated */
-0x30d8 #define XK_kana_HE 0x4cd
-0x30db #define XK_kana_HO 0x4ce
-0x30de #define XK_kana_MA 0x4cf
-0x30df #define XK_kana_MI 0x4d0
-0x30e0 #define XK_kana_MU 0x4d1
-0x30e1 #define XK_kana_ME 0x4d2
-0x30e2 #define XK_kana_MO 0x4d3
-0x30e4 #define XK_kana_YA 0x4d4
-0x30e6 #define XK_kana_YU 0x4d5
-0x30e8 #define XK_kana_YO 0x4d6
-0x30e9 #define XK_kana_RA 0x4d7
-0x30ea #define XK_kana_RI 0x4d8
-0x30eb #define XK_kana_RU 0x4d9
-0x30ec #define XK_kana_RE 0x4da
-0x30ed #define XK_kana_RO 0x4db
-0x30ef #define XK_kana_WA 0x4dc
-0x30f3 #define XK_kana_N 0x4dd
-0x309b #define XK_voicedsound 0x4de
-0x309c #define XK_semivoicedsound 0x4df
-0x0000 #define XK_kana_switch 0xFF7E /* Alias for mode_switch */
-#endif /* XK_KATAKANA */
-
-/*
- * Arabic
- * Byte 3 = 5
- */
-
-#ifdef XK_ARABIC
-0x0670 #define XK_Farsi_0 0x590
-0x06f1 #define XK_Farsi_1 0x591
-0x06f2 #define XK_Farsi_2 0x592
-0x06f3 #define XK_Farsi_3 0x593
-0x06f4 #define XK_Farsi_4 0x594
-0x06f5 #define XK_Farsi_5 0x595
-0x06f6 #define XK_Farsi_6 0x596
-0x06f7 #define XK_Farsi_7 0x597
-0x06f8 #define XK_Farsi_8 0x598
-0x06f9 #define XK_Farsi_9 0x599
-0x066a #define XK_Arabic_percent 0x5a5
-0x0670 #define XK_Arabic_superscript_alef 0x5a6
-0x0679 #define XK_Arabic_tteh 0x5a7
-0x067e #define XK_Arabic_peh 0x5a8
-0x0686 #define XK_Arabic_tcheh 0x5a9
-0x0688 #define XK_Arabic_ddal 0x5aa
-0x0691 #define XK_Arabic_rreh 0x5ab
-0x060c #define XK_Arabic_comma 0x5ac
-0x06d4 #define XK_Arabic_fullstop 0x5ae
-0x0660 #define XK_Arabic_0 0x5b0
-0x0661 #define XK_Arabic_1 0x5b1
-0x0662 #define XK_Arabic_2 0x5b2
-0x0663 #define XK_Arabic_3 0x5b3
-0x0664 #define XK_Arabic_4 0x5b4
-0x0665 #define XK_Arabic_5 0x5b5
-0x0666 #define XK_Arabic_6 0x5b6
-0x0667 #define XK_Arabic_7 0x5b7
-0x0668 #define XK_Arabic_8 0x5b8
-0x0669 #define XK_Arabic_9 0x5b9
-0x061b #define XK_Arabic_semicolon 0x5bb
-0x061f #define XK_Arabic_question_mark 0x5bf
-0x0621 #define XK_Arabic_hamza 0x5c1
-0x0622 #define XK_Arabic_maddaonalef 0x5c2
-0x0623 #define XK_Arabic_hamzaonalef 0x5c3
-0x0624 #define XK_Arabic_hamzaonwaw 0x5c4
-0x0625 #define XK_Arabic_hamzaunderalef 0x5c5
-0x0626 #define XK_Arabic_hamzaonyeh 0x5c6
-0x0627 #define XK_Arabic_alef 0x5c7
-0x0628 #define XK_Arabic_beh 0x5c8
-0x0629 #define XK_Arabic_tehmarbuta 0x5c9
-0x062a #define XK_Arabic_teh 0x5ca
-0x062b #define XK_Arabic_theh 0x5cb
-0x062c #define XK_Arabic_jeem 0x5cc
-0x062d #define XK_Arabic_hah 0x5cd
-0x062e #define XK_Arabic_khah 0x5ce
-0x062f #define XK_Arabic_dal 0x5cf
-0x0630 #define XK_Arabic_thal 0x5d0
-0x0631 #define XK_Arabic_ra 0x5d1
-0x0632 #define XK_Arabic_zain 0x5d2
-0x0633 #define XK_Arabic_seen 0x5d3
-0x0634 #define XK_Arabic_sheen 0x5d4
-0x0635 #define XK_Arabic_sad 0x5d5
-0x0636 #define XK_Arabic_dad 0x5d6
-0x0637 #define XK_Arabic_tah 0x5d7
-0x0638 #define XK_Arabic_zah 0x5d8
-0x0639 #define XK_Arabic_ain 0x5d9
-0x063a #define XK_Arabic_ghain 0x5da
-0x0640 #define XK_Arabic_tatweel 0x5e0
-0x0641 #define XK_Arabic_feh 0x5e1
-0x0642 #define XK_Arabic_qaf 0x5e2
-0x0643 #define XK_Arabic_kaf 0x5e3
-0x0644 #define XK_Arabic_lam 0x5e4
-0x0645 #define XK_Arabic_meem 0x5e5
-0x0646 #define XK_Arabic_noon 0x5e6
-0x0647 #define XK_Arabic_ha 0x5e7
-0x0000 #define XK_Arabic_heh 0x5e7 /* deprecated */
-0x0648 #define XK_Arabic_waw 0x5e8
-0x0649 #define XK_Arabic_alefmaksura 0x5e9
-0x064a #define XK_Arabic_yeh 0x5ea
-0x064b #define XK_Arabic_fathatan 0x5eb
-0x064c #define XK_Arabic_dammatan 0x5ec
-0x064d #define XK_Arabic_kasratan 0x5ed
-0x064e #define XK_Arabic_fatha 0x5ee
-0x064f #define XK_Arabic_damma 0x5ef
-0x0650 #define XK_Arabic_kasra 0x5f0
-0x0651 #define XK_Arabic_shadda 0x5f1
-0x0652 #define XK_Arabic_sukun 0x5f2
-0x0653 #define XK_Arabic_madda_above 0x5f3
-0x0654 #define XK_Arabic_hamza_above 0x5f4
-0x0655 #define XK_Arabic_hamza_below 0x5f5
-0x0698 #define XK_Arabic_jeh 0x5f6
-0x06a4 #define XK_Arabic_veh 0x5f7
-0x06a9 #define XK_Arabic_keheh 0x5f8
-0x06af #define XK_Arabic_gaf 0x5f9
-0x06ba #define XK_Arabic_noon_ghunna 0x5fa
-0x06be #define XK_Arabic_heh_doachashmee 0x5fb
-0x06cc #define XK_Farsi_yeh 0x5fc
-0x06d2 #define XK_Arabic_yeh_baree 0x5fd
-0x06c1 #define XK_Arabic_heh_goal 0x5fe
-0x0000 #define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */
-#endif /* XK_ARABIC */
-
-/*
- * Cyrillic
- * Byte 3 = 6
- */
-#ifdef XK_CYRILLIC
-0x0492 #define XK_Cyrillic_GHE_bar 0x680
-0x0493 #define XK_Cyrillic_ghe_bar 0x690
-0x0496 #define XK_Cyrillic_ZHE_descender 0x681
-0x0497 #define XK_Cyrillic_zhe_descender 0x691
-0x049a #define XK_Cyrillic_KA_descender 0x682
-0x049b #define XK_Cyrillic_ka_descender 0x692
-0x049c #define XK_Cyrillic_KA_vertstroke 0x683
-0x049d #define XK_Cyrillic_ka_vertstroke 0x693
-0x04a2 #define XK_Cyrillic_EN_descender 0x684
-0x04a3 #define XK_Cyrillic_en_descender 0x694
-0x04ae #define XK_Cyrillic_U_straight 0x685
-0x04af #define XK_Cyrillic_u_straight 0x695
-0x04b0 #define XK_Cyrillic_U_straight_bar 0x686
-0x04b1 #define XK_Cyrillic_u_straight_bar 0x696
-0x04b2 #define XK_Cyrillic_HA_descender 0x687
-0x04b3 #define XK_Cyrillic_ha_descender 0x697
-0x04b6 #define XK_Cyrillic_CHE_descender 0x688
-0x04b7 #define XK_Cyrillic_che_descender 0x698
-0x04b8 #define XK_Cyrillic_CHE_vertstroke 0x689
-0x04b9 #define XK_Cyrillic_che_vertstroke 0x699
-0x04ba #define XK_Cyrillic_SHHA 0x68a
-0x04bb #define XK_Cyrillic_shha 0x69a
-
-0x04d8 #define XK_Cyrillic_SCHWA 0x68c
-0x04d9 #define XK_Cyrillic_schwa 0x69c
-0x04e2 #define XK_Cyrillic_I_macron 0x68d
-0x04e3 #define XK_Cyrillic_i_macron 0x69d
-0x04e8 #define XK_Cyrillic_O_bar 0x68e
-0x04e9 #define XK_Cyrillic_o_bar 0x69e
-0x04ee #define XK_Cyrillic_U_macron 0x68f
-0x04ef #define XK_Cyrillic_u_macron 0x69f
-
-0x0452 #define XK_Serbian_dje 0x6a1
-0x0453 #define XK_Macedonia_gje 0x6a2
-0x0451 #define XK_Cyrillic_io 0x6a3
-0x0454 #define XK_Ukrainian_ie 0x6a4
-0x0000 #define XK_Ukranian_je 0x6a4 /* deprecated */
-0x0455 #define XK_Macedonia_dse 0x6a5
-0x0456 #define XK_Ukrainian_i 0x6a6
-0x0000 #define XK_Ukranian_i 0x6a6 /* deprecated */
-0x0457 #define XK_Ukrainian_yi 0x6a7
-0x0000 #define XK_Ukranian_yi 0x6a7 /* deprecated */
-0x0458 #define XK_Cyrillic_je 0x6a8
-0x0000 #define XK_Serbian_je 0x6a8 /* deprecated */
-0x0459 #define XK_Cyrillic_lje 0x6a9
-0x0000 #define XK_Serbian_lje 0x6a9 /* deprecated */
-0x045a #define XK_Cyrillic_nje 0x6aa
-0x0000 #define XK_Serbian_nje 0x6aa /* deprecated */
-0x045b #define XK_Serbian_tshe 0x6ab
-0x045c #define XK_Macedonia_kje 0x6ac
-0x0491 #define XK_Ukrainian_ghe_with_upturn 0x6ad
-0x045e #define XK_Byelorussian_shortu 0x6ae
-0x045f #define XK_Cyrillic_dzhe 0x6af
-0x0000 #define XK_Serbian_dze 0x6af /* deprecated */
-0x2116 #define XK_numerosign 0x6b0
-0x0402 #define XK_Serbian_DJE 0x6b1
-0x0403 #define XK_Macedonia_GJE 0x6b2
-0x0401 #define XK_Cyrillic_IO 0x6b3
-0x0404 #define XK_Ukrainian_IE 0x6b4
-0x0000 #define XK_Ukranian_JE 0x6b4 /* deprecated */
-0x0405 #define XK_Macedonia_DSE 0x6b5
-0x0406 #define XK_Ukrainian_I 0x6b6
-0x0000 #define XK_Ukranian_I 0x6b6 /* deprecated */
-0x0407 #define XK_Ukrainian_YI 0x6b7
-0x0000 #define XK_Ukranian_YI 0x6b7 /* deprecated */
-0x0408 #define XK_Cyrillic_JE 0x6b8
-0x0000 #define XK_Serbian_JE 0x6b8 /* deprecated */
-0x0409 #define XK_Cyrillic_LJE 0x6b9
-0x0000 #define XK_Serbian_LJE 0x6b9 /* deprecated */
-0x040a #define XK_Cyrillic_NJE 0x6ba
-0x0000 #define XK_Serbian_NJE 0x6ba /* deprecated */
-0x040b #define XK_Serbian_TSHE 0x6bb
-0x040c #define XK_Macedonia_KJE 0x6bc
-0x0490 #define XK_Ukrainian_GHE_WITH_UPTURN 0x6bd
-0x040e #define XK_Byelorussian_SHORTU 0x6be
-0x040f #define XK_Cyrillic_DZHE 0x6bf
-0x0000 #define XK_Serbian_DZE 0x6bf /* deprecated */
-0x044e #define XK_Cyrillic_yu 0x6c0
-0x0430 #define XK_Cyrillic_a 0x6c1
-0x0431 #define XK_Cyrillic_be 0x6c2
-0x0446 #define XK_Cyrillic_tse 0x6c3
-0x0434 #define XK_Cyrillic_de 0x6c4
-0x0435 #define XK_Cyrillic_ie 0x6c5
-0x0444 #define XK_Cyrillic_ef 0x6c6
-0x0433 #define XK_Cyrillic_ghe 0x6c7
-0x0445 #define XK_Cyrillic_ha 0x6c8
-0x0438 #define XK_Cyrillic_i 0x6c9
-0x0439 #define XK_Cyrillic_shorti 0x6ca
-0x043a #define XK_Cyrillic_ka 0x6cb
-0x043b #define XK_Cyrillic_el 0x6cc
-0x043c #define XK_Cyrillic_em 0x6cd
-0x043d #define XK_Cyrillic_en 0x6ce
-0x043e #define XK_Cyrillic_o 0x6cf
-0x043f #define XK_Cyrillic_pe 0x6d0
-0x044f #define XK_Cyrillic_ya 0x6d1
-0x0440 #define XK_Cyrillic_er 0x6d2
-0x0441 #define XK_Cyrillic_es 0x6d3
-0x0442 #define XK_Cyrillic_te 0x6d4
-0x0443 #define XK_Cyrillic_u 0x6d5
-0x0436 #define XK_Cyrillic_zhe 0x6d6
-0x0432 #define XK_Cyrillic_ve 0x6d7
-0x044c #define XK_Cyrillic_softsign 0x6d8
-0x044b #define XK_Cyrillic_yeru 0x6d9
-0x0437 #define XK_Cyrillic_ze 0x6da
-0x0448 #define XK_Cyrillic_sha 0x6db
-0x044d #define XK_Cyrillic_e 0x6dc
-0x0449 #define XK_Cyrillic_shcha 0x6dd
-0x0447 #define XK_Cyrillic_che 0x6de
-0x044a #define XK_Cyrillic_hardsign 0x6df
-0x042e #define XK_Cyrillic_YU 0x6e0
-0x0410 #define XK_Cyrillic_A 0x6e1
-0x0411 #define XK_Cyrillic_BE 0x6e2
-0x0426 #define XK_Cyrillic_TSE 0x6e3
-0x0414 #define XK_Cyrillic_DE 0x6e4
-0x0415 #define XK_Cyrillic_IE 0x6e5
-0x0424 #define XK_Cyrillic_EF 0x6e6
-0x0413 #define XK_Cyrillic_GHE 0x6e7
-0x0425 #define XK_Cyrillic_HA 0x6e8
-0x0418 #define XK_Cyrillic_I 0x6e9
-0x0419 #define XK_Cyrillic_SHORTI 0x6ea
-0x041a #define XK_Cyrillic_KA 0x6eb
-0x041b #define XK_Cyrillic_EL 0x6ec
-0x041c #define XK_Cyrillic_EM 0x6ed
-0x041d #define XK_Cyrillic_EN 0x6ee
-0x041e #define XK_Cyrillic_O 0x6ef
-0x041f #define XK_Cyrillic_PE 0x6f0
-0x042f #define XK_Cyrillic_YA 0x6f1
-0x0420 #define XK_Cyrillic_ER 0x6f2
-0x0421 #define XK_Cyrillic_ES 0x6f3
-0x0422 #define XK_Cyrillic_TE 0x6f4
-0x0423 #define XK_Cyrillic_U 0x6f5
-0x0416 #define XK_Cyrillic_ZHE 0x6f6
-0x0412 #define XK_Cyrillic_VE 0x6f7
-0x042c #define XK_Cyrillic_SOFTSIGN 0x6f8
-0x042b #define XK_Cyrillic_YERU 0x6f9
-0x0417 #define XK_Cyrillic_ZE 0x6fa
-0x0428 #define XK_Cyrillic_SHA 0x6fb
-0x042d #define XK_Cyrillic_E 0x6fc
-0x0429 #define XK_Cyrillic_SHCHA 0x6fd
-0x0427 #define XK_Cyrillic_CHE 0x6fe
-0x042a #define XK_Cyrillic_HARDSIGN 0x6ff
-#endif /* XK_CYRILLIC */
-
-/*
- * Greek
- * Byte 3 = 7
- */
-
-#ifdef XK_GREEK
-0x0386 #define XK_Greek_ALPHAaccent 0x7a1
-0x0388 #define XK_Greek_EPSILONaccent 0x7a2
-0x0389 #define XK_Greek_ETAaccent 0x7a3
-0x038a #define XK_Greek_IOTAaccent 0x7a4
-0x03aa #define XK_Greek_IOTAdieresis 0x7a5
-0x0000 #define XK_Greek_IOTAdiaeresis XK_Greek_IOTAdieresis /* old typo */
-0x038c #define XK_Greek_OMICRONaccent 0x7a7
-0x038e #define XK_Greek_UPSILONaccent 0x7a8
-0x03ab #define XK_Greek_UPSILONdieresis 0x7a9
-0x038f #define XK_Greek_OMEGAaccent 0x7ab
-0x0385 #define XK_Greek_accentdieresis 0x7ae
-0x2015 #define XK_Greek_horizbar 0x7af
-0x03ac #define XK_Greek_alphaaccent 0x7b1
-0x03ad #define XK_Greek_epsilonaccent 0x7b2
-0x03ae #define XK_Greek_etaaccent 0x7b3
-0x03af #define XK_Greek_iotaaccent 0x7b4
-0x03ca #define XK_Greek_iotadieresis 0x7b5
-0x0390 #define XK_Greek_iotaaccentdieresis 0x7b6
-0x03cc #define XK_Greek_omicronaccent 0x7b7
-0x03cd #define XK_Greek_upsilonaccent 0x7b8
-0x03cb #define XK_Greek_upsilondieresis 0x7b9
-0x03b0 #define XK_Greek_upsilonaccentdieresis 0x7ba
-0x03ce #define XK_Greek_omegaaccent 0x7bb
-0x0391 #define XK_Greek_ALPHA 0x7c1
-0x0392 #define XK_Greek_BETA 0x7c2
-0x0393 #define XK_Greek_GAMMA 0x7c3
-0x0394 #define XK_Greek_DELTA 0x7c4
-0x0395 #define XK_Greek_EPSILON 0x7c5
-0x0396 #define XK_Greek_ZETA 0x7c6
-0x0397 #define XK_Greek_ETA 0x7c7
-0x0398 #define XK_Greek_THETA 0x7c8
-0x0399 #define XK_Greek_IOTA 0x7c9
-0x039a #define XK_Greek_KAPPA 0x7ca
-0x0000 #define XK_Greek_LAMDA 0x7cb
-0x039b #define XK_Greek_LAMBDA 0x7cb
-0x039c #define XK_Greek_MU 0x7cc
-0x039d #define XK_Greek_NU 0x7cd
-0x039e #define XK_Greek_XI 0x7ce
-0x039f #define XK_Greek_OMICRON 0x7cf
-0x03a0 #define XK_Greek_PI 0x7d0
-0x03a1 #define XK_Greek_RHO 0x7d1
-0x03a3 #define XK_Greek_SIGMA 0x7d2
-0x03a4 #define XK_Greek_TAU 0x7d4
-0x03a5 #define XK_Greek_UPSILON 0x7d5
-0x03a6 #define XK_Greek_PHI 0x7d6
-0x03a7 #define XK_Greek_CHI 0x7d7
-0x03a8 #define XK_Greek_PSI 0x7d8
-0x03a9 #define XK_Greek_OMEGA 0x7d9
-0x03b1 #define XK_Greek_alpha 0x7e1
-0x03b2 #define XK_Greek_beta 0x7e2
-0x03b3 #define XK_Greek_gamma 0x7e3
-0x03b4 #define XK_Greek_delta 0x7e4
-0x03b5 #define XK_Greek_epsilon 0x7e5
-0x03b6 #define XK_Greek_zeta 0x7e6
-0x03b7 #define XK_Greek_eta 0x7e7
-0x03b8 #define XK_Greek_theta 0x7e8
-0x03b9 #define XK_Greek_iota 0x7e9
-0x03ba #define XK_Greek_kappa 0x7ea
-0x0000 #define XK_Greek_lamda 0x7eb
-0x03bb #define XK_Greek_lambda 0x7eb
-0x03bc #define XK_Greek_mu 0x7ec
-0x03bd #define XK_Greek_nu 0x7ed
-0x03be #define XK_Greek_xi 0x7ee
-0x03bf #define XK_Greek_omicron 0x7ef
-0x03c0 #define XK_Greek_pi 0x7f0
-0x03c1 #define XK_Greek_rho 0x7f1
-0x03c3 #define XK_Greek_sigma 0x7f2
-0x03c2 #define XK_Greek_finalsmallsigma 0x7f3
-0x03c4 #define XK_Greek_tau 0x7f4
-0x03c5 #define XK_Greek_upsilon 0x7f5
-0x03c6 #define XK_Greek_phi 0x7f6
-0x03c7 #define XK_Greek_chi 0x7f7
-0x03c8 #define XK_Greek_psi 0x7f8
-0x03c9 #define XK_Greek_omega 0x7f9
-0x0000 #define XK_Greek_switch 0xFF7E /* Alias for mode_switch */
-#endif /* XK_GREEK */
-
-/*
- * Technical
- * Byte 3 = 8
- */
-
-#ifdef XK_TECHNICAL
-0x23b7 #define XK_leftradical 0x8a1
-0x250c #define XK_topleftradical 0x8a2
-0x2500 #define XK_horizconnector 0x8a3
-0x2320 #define XK_topintegral 0x8a4
-0x2321 #define XK_botintegral 0x8a5
-0x2502 #define XK_vertconnector 0x8a6
-0x23a1 #define XK_topleftsqbracket 0x8a7
-0x23a3 #define XK_botleftsqbracket 0x8a8
-0x23a4 #define XK_toprightsqbracket 0x8a9
-0x23a6 #define XK_botrightsqbracket 0x8aa
-0x239b #define XK_topleftparens 0x8ab
-0x239d #define XK_botleftparens 0x8ac
-0x239e #define XK_toprightparens 0x8ad
-0x23a0 #define XK_botrightparens 0x8ae
-0x23a8 #define XK_leftmiddlecurlybrace 0x8af
-0x23ac #define XK_rightmiddlecurlybrace 0x8b0
-0x0000 #define XK_topleftsummation 0x8b1
-0x0000 #define XK_botleftsummation 0x8b2
-0x0000 #define XK_topvertsummationconnector 0x8b3
-0x0000 #define XK_botvertsummationconnector 0x8b4
-0x0000 #define XK_toprightsummation 0x8b5
-0x0000 #define XK_botrightsummation 0x8b6
-0x0000 #define XK_rightmiddlesummation 0x8b7
-0x2264 #define XK_lessthanequal 0x8bc
-0x2260 #define XK_notequal 0x8bd
-0x2265 #define XK_greaterthanequal 0x8be
-0x222b #define XK_integral 0x8bf
-0x2234 #define XK_therefore 0x8c0
-0x221d #define XK_variation 0x8c1
-0x221e #define XK_infinity 0x8c2
-0x2207 #define XK_nabla 0x8c5
-0x223c #define XK_approximate 0x8c8
-0x2243 #define XK_similarequal 0x8c9
-0x2104 #define XK_ifonlyif 0x8cd
-0x21d2 #define XK_implies 0x8ce
-0x2261 #define XK_identical 0x8cf
-0x221a #define XK_radical 0x8d6
-0x2282 #define XK_includedin 0x8da
-0x2283 #define XK_includes 0x8db
-0x2229 #define XK_intersection 0x8dc
-0x222a #define XK_union 0x8dd
-0x2227 #define XK_logicaland 0x8de
-0x2228 #define XK_logicalor 0x8df
-0x2202 #define XK_partialderivative 0x8ef
-0x0192 #define XK_function 0x8f6
-0x2190 #define XK_leftarrow 0x8fb
-0x2191 #define XK_uparrow 0x8fc
-0x2192 #define XK_rightarrow 0x8fd
-0x2193 #define XK_downarrow 0x8fe
-#endif /* XK_TECHNICAL */
-
-/*
- * Special
- * Byte 3 = 9
- */
-
-#ifdef XK_SPECIAL
-0x0000 #define XK_blank 0x9df
-0x25c6 #define XK_soliddiamond 0x9e0
-0x2592 #define XK_checkerboard 0x9e1
-0x2409 #define XK_ht 0x9e2
-0x240c #define XK_ff 0x9e3
-0x240d #define XK_cr 0x9e4
-0x240a #define XK_lf 0x9e5
-0x2424 #define XK_nl 0x9e8
-0x240b #define XK_vt 0x9e9
-0x2518 #define XK_lowrightcorner 0x9ea
-0x2510 #define XK_uprightcorner 0x9eb
-0x250c #define XK_upleftcorner 0x9ec
-0x2514 #define XK_lowleftcorner 0x9ed
-0x253c #define XK_crossinglines 0x9ee
-0x23ba #define XK_horizlinescan1 0x9ef
-0x23bb #define XK_horizlinescan3 0x9f0
-0x2500 #define XK_horizlinescan5 0x9f1
-0x23bc #define XK_horizlinescan7 0x9f2
-0x23bd #define XK_horizlinescan9 0x9f3
-0x251c #define XK_leftt 0x9f4
-0x2524 #define XK_rightt 0x9f5
-0x2534 #define XK_bott 0x9f6
-0x242c #define XK_topt 0x9f7
-0x2502 #define XK_vertbar 0x9f8
-#endif /* XK_SPECIAL */
-
-/*
- * Publishing
- * Byte 3 = a
- */
-
-#ifdef XK_PUBLISHING
-0x2003 #define XK_emspace 0xaa1
-0x2002 #define XK_enspace 0xaa2
-0x2004 #define XK_em3space 0xaa3
-0x2005 #define XK_em4space 0xaa4
-0x2007 #define XK_digitspace 0xaa5
-0x2008 #define XK_punctspace 0xaa6
-0x2009 #define XK_thinspace 0xaa7
-0x200a #define XK_hairspace 0xaa8
-0x2014 #define XK_emdash 0xaa9
-0x2013 #define XK_endash 0xaaa
-0x2423 #define XK_signifblank 0xaac
-0x2026 #define XK_ellipsis 0xaae
-0x2025 #define XK_doubbaselinedot 0xaaf
-0x2153 #define XK_onethird 0xab0
-0x2154 #define XK_twothirds 0xab1
-0x2155 #define XK_onefifth 0xab2
-0x2156 #define XK_twofifths 0xab3
-0x2157 #define XK_threefifths 0xab4
-0x2158 #define XK_fourfifths 0xab5
-0x2159 #define XK_onesixth 0xab6
-0x215a #define XK_fivesixths 0xab7
-0x2105 #define XK_careof 0xab8
-0x2012 #define XK_figdash 0xabb
-0x27e8 #define XK_leftanglebracket 0xabc
-0x002e #define XK_decimalpoint 0xabd
-0x27e9 #define XK_rightanglebracket 0xabe
-0x0000 #define XK_marker 0xabf
-0x215b #define XK_oneeighth 0xac3
-0x215c #define XK_threeeighths 0xac4
-0x215d #define XK_fiveeighths 0xac5
-0x215e #define XK_seveneighths 0xac6
-0x2122 #define XK_trademark 0xac9
-0x2613 #define XK_signaturemark 0xaca
-0x0000 #define XK_trademarkincircle 0xacb
-0x25c1 #define XK_leftopentriangle 0xacc
-0x25b7 #define XK_rightopentriangle 0xacd
-0x25cb #define XK_emopencircle 0xace
-0x25af #define XK_emopenrectangle 0xacf
-0x2018 #define XK_leftsinglequotemark 0xad0
-0x2019 #define XK_rightsinglequotemark 0xad1
-0x201c #define XK_leftdoublequotemark 0xad2
-0x201d #define XK_rightdoublequotemark 0xad3
-0x211e #define XK_prescription 0xad4
-0x2032 #define XK_minutes 0xad6
-0x2033 #define XK_seconds 0xad7
-0x271d #define XK_latincross 0xad9
-0x0000 #define XK_hexagram 0xada
-0x25ac #define XK_filledrectbullet 0xadb
-0x25c0 #define XK_filledlefttribullet 0xadc
-0x25b6 #define XK_filledrighttribullet 0xadd
-0x25cf #define XK_emfilledcircle 0xade
-0x25ae #define XK_emfilledrect 0xadf
-0x25e6 #define XK_enopencircbullet 0xae0
-0x25ab #define XK_enopensquarebullet 0xae1
-0x25ad #define XK_openrectbullet 0xae2
-0x25b3 #define XK_opentribulletup 0xae3
-0x25bd #define XK_opentribulletdown 0xae4
-0x2606 #define XK_openstar 0xae5
-0x2022 #define XK_enfilledcircbullet 0xae6
-0x25aa #define XK_enfilledsqbullet 0xae7
-0x25b2 #define XK_filledtribulletup 0xae8
-0x25bc #define XK_filledtribulletdown 0xae9
-0x261c #define XK_leftpointer 0xaea
-0x261e #define XK_rightpointer 0xaeb
-0x2663 #define XK_club 0xaec
-0x2666 #define XK_diamond 0xaed
-0x2665 #define XK_heart 0xaee
-0x2720 #define XK_maltesecross 0xaf0
-0x2020 #define XK_dagger 0xaf1
-0x2021 #define XK_doubledagger 0xaf2
-0x2713 #define XK_checkmark 0xaf3
-0x2717 #define XK_ballotcross 0xaf4
-0x266f #define XK_musicalsharp 0xaf5
-0x266d #define XK_musicalflat 0xaf6
-0x2642 #define XK_malesymbol 0xaf7
-0x2640 #define XK_femalesymbol 0xaf8
-0x260e #define XK_telephone 0xaf9
-0x2315 #define XK_telephonerecorder 0xafa
-0x2117 #define XK_phonographcopyright 0xafb
-0x2038 #define XK_caret 0xafc
-0x201a #define XK_singlelowquotemark 0xafd
-0x201e #define XK_doublelowquotemark 0xafe
-0x0000 #define XK_cursor 0xaff
-#endif /* XK_PUBLISHING */
-
-/*
- * APL
- * Byte 3 = b
- */
-
-#ifdef XK_APL
-0x003c #define XK_leftcaret 0xba3
-0x003e #define XK_rightcaret 0xba6
-0x2228 #define XK_downcaret 0xba8
-0x2227 #define XK_upcaret 0xba9
-0x00af #define XK_overbar 0xbc0
-0x22a5 #define XK_downtack 0xbc2
-0x2229 #define XK_upshoe 0xbc3
-0x230a #define XK_downstile 0xbc4
-0x005f #define XK_underbar 0xbc6
-0x2218 #define XK_jot 0xbca
-0x2395 #define XK_quad 0xbcc
-0x22a4 #define XK_uptack 0xbce
-0x25cb #define XK_circle 0xbcf
-0x2308 #define XK_upstile 0xbd3
-0x222a #define XK_downshoe 0xbd6
-0x2283 #define XK_rightshoe 0xbd8
-0x2282 #define XK_leftshoe 0xbda
-0x22a2 #define XK_lefttack 0xbdc
-0x22a3 #define XK_righttack 0xbfc
-#endif /* XK_APL */
-
-/*
- * Hebrew
- * Byte 3 = c
- */
-
-#ifdef XK_HEBREW
-0x2017 #define XK_hebrew_doublelowline 0xcdf
-0x05d0 #define XK_hebrew_aleph 0xce0
-0x05d1 #define XK_hebrew_bet 0xce1
-0x0000 #define XK_hebrew_beth 0xce1 /* deprecated */
-0x05d2 #define XK_hebrew_gimel 0xce2
-0x0000 #define XK_hebrew_gimmel 0xce2 /* deprecated */
-0x05d3 #define XK_hebrew_dalet 0xce3
-0x0000 #define XK_hebrew_daleth 0xce3 /* deprecated */
-0x05d4 #define XK_hebrew_he 0xce4
-0x05d5 #define XK_hebrew_waw 0xce5
-0x05d6 #define XK_hebrew_zain 0xce6
-0x0000 #define XK_hebrew_zayin 0xce6 /* deprecated */
-0x05d7 #define XK_hebrew_chet 0xce7
-0x0000 #define XK_hebrew_het 0xce7 /* deprecated */
-0x05d8 #define XK_hebrew_tet 0xce8
-0x0000 #define XK_hebrew_teth 0xce8 /* deprecated */
-0x05d9 #define XK_hebrew_yod 0xce9
-0x05da #define XK_hebrew_finalkaph 0xcea
-0x05db #define XK_hebrew_kaph 0xceb
-0x05dc #define XK_hebrew_lamed 0xcec
-0x05dd #define XK_hebrew_finalmem 0xced
-0x05de #define XK_hebrew_mem 0xcee
-0x05df #define XK_hebrew_finalnun 0xcef
-0x05e0 #define XK_hebrew_nun 0xcf0
-0x05e1 #define XK_hebrew_samech 0xcf1
-0x0000 #define XK_hebrew_samekh 0xcf1 /* deprecated */
-0x05e2 #define XK_hebrew_ayin 0xcf2
-0x05e3 #define XK_hebrew_finalpe 0xcf3
-0x05e4 #define XK_hebrew_pe 0xcf4
-0x05e5 #define XK_hebrew_finalzade 0xcf5
-0x0000 #define XK_hebrew_finalzadi 0xcf5 /* deprecated */
-0x05e6 #define XK_hebrew_zade 0xcf6
-0x0000 #define XK_hebrew_zadi 0xcf6 /* deprecated */
-0x05e7 #define XK_hebrew_qoph 0xcf7
-0x0000 #define XK_hebrew_kuf 0xcf7 /* deprecated */
-0x05e8 #define XK_hebrew_resh 0xcf8
-0x05e9 #define XK_hebrew_shin 0xcf9
-0x05ea #define XK_hebrew_taw 0xcfa
-0x0000 #define XK_hebrew_taf 0xcfa /* deprecated */
-0x0000 #define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */
-#endif /* XK_HEBREW */
-
-/*
- * Thai
- * Byte 3 = d
- */
-
-#ifdef XK_THAI
-0x0e01 #define XK_Thai_kokai 0xda1
-0x0e02 #define XK_Thai_khokhai 0xda2
-0x0e03 #define XK_Thai_khokhuat 0xda3
-0x0e04 #define XK_Thai_khokhwai 0xda4
-0x0e05 #define XK_Thai_khokhon 0xda5
-0x0e06 #define XK_Thai_khorakhang 0xda6
-0x0e07 #define XK_Thai_ngongu 0xda7
-0x0e08 #define XK_Thai_chochan 0xda8
-0x0e09 #define XK_Thai_choching 0xda9
-0x0e0a #define XK_Thai_chochang 0xdaa
-0x0e0b #define XK_Thai_soso 0xdab
-0x0e0c #define XK_Thai_chochoe 0xdac
-0x0e0d #define XK_Thai_yoying 0xdad
-0x0e0e #define XK_Thai_dochada 0xdae
-0x0e0f #define XK_Thai_topatak 0xdaf
-0x0e10 #define XK_Thai_thothan 0xdb0
-0x0e11 #define XK_Thai_thonangmontho 0xdb1
-0x0e12 #define XK_Thai_thophuthao 0xdb2
-0x0e13 #define XK_Thai_nonen 0xdb3
-0x0e14 #define XK_Thai_dodek 0xdb4
-0x0e15 #define XK_Thai_totao 0xdb5
-0x0e16 #define XK_Thai_thothung 0xdb6
-0x0e17 #define XK_Thai_thothahan 0xdb7
-0x0e18 #define XK_Thai_thothong 0xdb8
-0x0e19 #define XK_Thai_nonu 0xdb9
-0x0e1a #define XK_Thai_bobaimai 0xdba
-0x0e1b #define XK_Thai_popla 0xdbb
-0x0e1c #define XK_Thai_phophung 0xdbc
-0x0e1d #define XK_Thai_fofa 0xdbd
-0x0e1e #define XK_Thai_phophan 0xdbe
-0x0e1f #define XK_Thai_fofan 0xdbf
-0x0e20 #define XK_Thai_phosamphao 0xdc0
-0x0e21 #define XK_Thai_moma 0xdc1
-0x0e22 #define XK_Thai_yoyak 0xdc2
-0x0e23 #define XK_Thai_rorua 0xdc3
-0x0e24 #define XK_Thai_ru 0xdc4
-0x0e25 #define XK_Thai_loling 0xdc5
-0x0e26 #define XK_Thai_lu 0xdc6
-0x0e27 #define XK_Thai_wowaen 0xdc7
-0x0e28 #define XK_Thai_sosala 0xdc8
-0x0e29 #define XK_Thai_sorusi 0xdc9
-0x0e2a #define XK_Thai_sosua 0xdca
-0x0e2b #define XK_Thai_hohip 0xdcb
-0x0e2c #define XK_Thai_lochula 0xdcc
-0x0e2d #define XK_Thai_oang 0xdcd
-0x0e2e #define XK_Thai_honokhuk 0xdce
-0x0e2f #define XK_Thai_paiyannoi 0xdcf
-0x0e30 #define XK_Thai_saraa 0xdd0
-0x0e31 #define XK_Thai_maihanakat 0xdd1
-0x0e32 #define XK_Thai_saraaa 0xdd2
-0x0e33 #define XK_Thai_saraam 0xdd3
-0x0e34 #define XK_Thai_sarai 0xdd4
-0x0e35 #define XK_Thai_saraii 0xdd5
-0x0e36 #define XK_Thai_saraue 0xdd6
-0x0e37 #define XK_Thai_sarauee 0xdd7
-0x0e38 #define XK_Thai_sarau 0xdd8
-0x0e39 #define XK_Thai_sarauu 0xdd9
-0x0e3a #define XK_Thai_phinthu 0xdda
-0x0000 #define XK_Thai_maihanakat_maitho 0xdde
-0x0e3f #define XK_Thai_baht 0xddf
-0x0e40 #define XK_Thai_sarae 0xde0
-0x0e41 #define XK_Thai_saraae 0xde1
-0x0e42 #define XK_Thai_sarao 0xde2
-0x0e43 #define XK_Thai_saraaimaimuan 0xde3
-0x0e44 #define XK_Thai_saraaimaimalai 0xde4
-0x0e45 #define XK_Thai_lakkhangyao 0xde5
-0x0e46 #define XK_Thai_maiyamok 0xde6
-0x0e47 #define XK_Thai_maitaikhu 0xde7
-0x0e48 #define XK_Thai_maiek 0xde8
-0x0e49 #define XK_Thai_maitho 0xde9
-0x0e4a #define XK_Thai_maitri 0xdea
-0x0e4b #define XK_Thai_maichattawa 0xdeb
-0x0e4c #define XK_Thai_thanthakhat 0xdec
-0x0e4d #define XK_Thai_nikhahit 0xded
-0x0e50 #define XK_Thai_leksun 0xdf0
-0x0e51 #define XK_Thai_leknung 0xdf1
-0x0e52 #define XK_Thai_leksong 0xdf2
-0x0e53 #define XK_Thai_leksam 0xdf3
-0x0e54 #define XK_Thai_leksi 0xdf4
-0x0e55 #define XK_Thai_lekha 0xdf5
-0x0e56 #define XK_Thai_lekhok 0xdf6
-0x0e57 #define XK_Thai_lekchet 0xdf7
-0x0e58 #define XK_Thai_lekpaet 0xdf8
-0x0e59 #define XK_Thai_lekkao 0xdf9
-#endif /* XK_THAI */
-
-/*
- * Korean
- * Byte 3 = e
- */
-
-#ifdef XK_KOREAN
-
-0x0000 #define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */
-0x0000 #define XK_Hangul_Start 0xff32 /* Hangul start */
-0x0000 #define XK_Hangul_End 0xff33 /* Hangul end, English start */
-0x0000 #define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */
-0x0000 #define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */
-0x0000 #define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */
-0x0000 #define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */
-0x0000 #define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */
-0x0000 #define XK_Hangul_Banja 0xff39 /* Banja mode */
-0x0000 #define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */
-0x0000 #define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */
-0x0000 #define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */
-0x0000 #define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */
-0x0000 #define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */
-0x0000 #define XK_Hangul_Special 0xff3f /* Special symbols */
-0x0000 #define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */
-
-/* Hangul Consonant Characters */
-0x3131 #define XK_Hangul_Kiyeog 0xea1
-0x3132 #define XK_Hangul_SsangKiyeog 0xea2
-0x3133 #define XK_Hangul_KiyeogSios 0xea3
-0x3134 #define XK_Hangul_Nieun 0xea4
-0x3135 #define XK_Hangul_NieunJieuj 0xea5
-0x3136 #define XK_Hangul_NieunHieuh 0xea6
-0x3137 #define XK_Hangul_Dikeud 0xea7
-0x3138 #define XK_Hangul_SsangDikeud 0xea8
-0x3139 #define XK_Hangul_Rieul 0xea9
-0x313a #define XK_Hangul_RieulKiyeog 0xeaa
-0x313b #define XK_Hangul_RieulMieum 0xeab
-0x313c #define XK_Hangul_RieulPieub 0xeac
-0x313d #define XK_Hangul_RieulSios 0xead
-0x313e #define XK_Hangul_RieulTieut 0xeae
-0x313f #define XK_Hangul_RieulPhieuf 0xeaf
-0x3140 #define XK_Hangul_RieulHieuh 0xeb0
-0x3141 #define XK_Hangul_Mieum 0xeb1
-0x3142 #define XK_Hangul_Pieub 0xeb2
-0x3143 #define XK_Hangul_SsangPieub 0xeb3
-0x3144 #define XK_Hangul_PieubSios 0xeb4
-0x3145 #define XK_Hangul_Sios 0xeb5
-0x3146 #define XK_Hangul_SsangSios 0xeb6
-0x3147 #define XK_Hangul_Ieung 0xeb7
-0x3148 #define XK_Hangul_Jieuj 0xeb8
-0x3149 #define XK_Hangul_SsangJieuj 0xeb9
-0x314a #define XK_Hangul_Cieuc 0xeba
-0x314b #define XK_Hangul_Khieuq 0xebb
-0x314c #define XK_Hangul_Tieut 0xebc
-0x314d #define XK_Hangul_Phieuf 0xebd
-0x314e #define XK_Hangul_Hieuh 0xebe
-
- /* Hangul Vowel Characters */
-0x314f #define XK_Hangul_A 0xebf
-0x3150 #define XK_Hangul_AE 0xec0
-0x3151 #define XK_Hangul_YA 0xec1
-0x3152 #define XK_Hangul_YAE 0xec2
-0x3153 #define XK_Hangul_EO 0xec3
-0x3154 #define XK_Hangul_E 0xec4
-0x3155 #define XK_Hangul_YEO 0xec5
-0x3156 #define XK_Hangul_YE 0xec6
-0x3157 #define XK_Hangul_O 0xec7
-0x3158 #define XK_Hangul_WA 0xec8
-0x3159 #define XK_Hangul_WAE 0xec9
-0x315a #define XK_Hangul_OE 0xeca
-0x315b #define XK_Hangul_YO 0xecb
-0x315c #define XK_Hangul_U 0xecc
-0x315d #define XK_Hangul_WEO 0xecd
-0x315e #define XK_Hangul_WE 0xece
-0x315f #define XK_Hangul_WI 0xecf
-0x3160 #define XK_Hangul_YU 0xed0
-0x3161 #define XK_Hangul_EU 0xed1
-0x3162 #define XK_Hangul_YI 0xed2
-0x3163 #define XK_Hangul_I 0xed3
-
-/* Hangul syllable-final (JongSeong) Characters */
-0x11a8 #define XK_Hangul_J_Kiyeog 0xed4
-0x11a9 #define XK_Hangul_J_SsangKiyeog 0xed5
-0x11aa #define XK_Hangul_J_KiyeogSios 0xed6
-0x11ab #define XK_Hangul_J_Nieun 0xed7
-0x11ac #define XK_Hangul_J_NieunJieuj 0xed8
-0x11ad #define XK_Hangul_J_NieunHieuh 0xed9
-0x11ae #define XK_Hangul_J_Dikeud 0xeda
-0x11af #define XK_Hangul_J_Rieul 0xedb
-0x11b0 #define XK_Hangul_J_RieulKiyeog 0xedc
-0x11b1 #define XK_Hangul_J_RieulMieum 0xedd
-0x11b2 #define XK_Hangul_J_RieulPieub 0xede
-0x11b3 #define XK_Hangul_J_RieulSios 0xedf
-0x11b4 #define XK_Hangul_J_RieulTieut 0xee0
-0x11b5 #define XK_Hangul_J_RieulPhieuf 0xee1
-0x11b6 #define XK_Hangul_J_RieulHieuh 0xee2
-0x11b7 #define XK_Hangul_J_Mieum 0xee3
-0x11b8 #define XK_Hangul_J_Pieub 0xee4
-0x11b9 #define XK_Hangul_J_PieubSios 0xee5
-0x11ba #define XK_Hangul_J_Sios 0xee6
-0x11bb #define XK_Hangul_J_SsangSios 0xee7
-0x11bc #define XK_Hangul_J_Ieung 0xee8
-0x11bd #define XK_Hangul_J_Jieuj 0xee9
-0x11be #define XK_Hangul_J_Cieuc 0xeea
-0x11bf #define XK_Hangul_J_Khieuq 0xeeb
-0x11c0 #define XK_Hangul_J_Tieut 0xeec
-0x11c1 #define XK_Hangul_J_Phieuf 0xeed
-0x11c2 #define XK_Hangul_J_Hieuh 0xeee
-
-/* Ancient Hangul Consonant Characters */
-0x316d #define XK_Hangul_RieulYeorinHieuh 0xeef
-0x3171 #define XK_Hangul_SunkyeongeumMieum 0xef0
-0x3178 #define XK_Hangul_SunkyeongeumPieub 0xef1
-0x317f #define XK_Hangul_PanSios 0xef2
-0x3181 #define XK_Hangul_KkogjiDalrinIeung 0xef3
-0x3184 #define XK_Hangul_SunkyeongeumPhieuf 0xef4
-0x3186 #define XK_Hangul_YeorinHieuh 0xef5
-
-/* Ancient Hangul Vowel Characters */
-0x318d #define XK_Hangul_AraeA 0xef6
-0x318e #define XK_Hangul_AraeAE 0xef7
-
-/* Ancient Hangul syllable-final (JongSeong) Characters */
-0x11eb #define XK_Hangul_J_PanSios 0xef8
-0x11f0 #define XK_Hangul_J_KkogjiDalrinIeung 0xef9
-0x11f9 #define XK_Hangul_J_YeorinHieuh 0xefa
-
-/* Korean currency symbol */
-0x20a9 #define XK_Korean_Won 0xeff
-
-#endif /* XK_KOREAN */
-
-/*
- * Armenian
- * Byte 3 = 0x14
- */
-// yan: skip Armenian for the time being
-#ifdef XK_ARMENIAN
-0x0000 #define XK_Armenian_eternity 0x14a1
-0x0000 #define XK_Armenian_ligature_ew 0x14a2
-0x0000 #define XK_Armenian_full_stop 0x14a3
-0x0000 #define XK_Armenian_verjaket 0x14a3
-0x0000 #define XK_Armenian_parenright 0x14a4
-0x0000 #define XK_Armenian_parenleft 0x14a5
-0x0000 #define XK_Armenian_guillemotright 0x14a6
-0x0000 #define XK_Armenian_guillemotleft 0x14a7
-0x0000 #define XK_Armenian_em_dash 0x14a8
-0x0000 #define XK_Armenian_dot 0x14a9
-0x0000 #define XK_Armenian_mijaket 0x14a9
-0x0000 #define XK_Armenian_separation_mark 0x14aa
-0x0000 #define XK_Armenian_but 0x14aa
-0x0000 #define XK_Armenian_comma 0x14ab
-0x0000 #define XK_Armenian_en_dash 0x14ac
-0x0000 #define XK_Armenian_hyphen 0x14ad
-0x0000 #define XK_Armenian_yentamna 0x14ad
-0x0000 #define XK_Armenian_ellipsis 0x14ae
-0x0000 #define XK_Armenian_exclam 0x14af
-0x0000 #define XK_Armenian_amanak 0x14af
-0x0000 #define XK_Armenian_accent 0x14b0
-0x0000 #define XK_Armenian_shesht 0x14b0
-0x0000 #define XK_Armenian_question 0x14b1
-0x0000 #define XK_Armenian_paruyk 0x14b1
-0x0000 #define XK_Armenian_AYB 0x14b2
-0x0000 #define XK_Armenian_ayb 0x14b3
-0x0000 #define XK_Armenian_BEN 0x14b4
-0x0000 #define XK_Armenian_ben 0x14b5
-0x0000 #define XK_Armenian_GIM 0x14b6
-0x0000 #define XK_Armenian_gim 0x14b7
-0x0000 #define XK_Armenian_DA 0x14b8
-0x0000 #define XK_Armenian_da 0x14b9
-0x0000 #define XK_Armenian_YECH 0x14ba
-0x0000 #define XK_Armenian_yech 0x14bb
-0x0000 #define XK_Armenian_ZA 0x14bc
-0x0000 #define XK_Armenian_za 0x14bd
-0x0000 #define XK_Armenian_E 0x14be
-0x0000 #define XK_Armenian_e 0x14bf
-0x0000 #define XK_Armenian_AT 0x14c0
-0x0000 #define XK_Armenian_at 0x14c1
-0x0000 #define XK_Armenian_TO 0x14c2
-0x0000 #define XK_Armenian_to 0x14c3
-0x0000 #define XK_Armenian_ZHE 0x14c4
-0x0000 #define XK_Armenian_zhe 0x14c5
-0x0000 #define XK_Armenian_INI 0x14c6
-0x0000 #define XK_Armenian_ini 0x14c7
-0x0000 #define XK_Armenian_LYUN 0x14c8
-0x0000 #define XK_Armenian_lyun 0x14c9
-0x0000 #define XK_Armenian_KHE 0x14ca
-0x0000 #define XK_Armenian_khe 0x14cb
-0x0000 #define XK_Armenian_TSA 0x14cc
-0x0000 #define XK_Armenian_tsa 0x14cd
-0x0000 #define XK_Armenian_KEN 0x14ce
-0x0000 #define XK_Armenian_ken 0x14cf
-0x0000 #define XK_Armenian_HO 0x14d0
-0x0000 #define XK_Armenian_ho 0x14d1
-0x0000 #define XK_Armenian_DZA 0x14d2
-0x0000 #define XK_Armenian_dza 0x14d3
-0x0000 #define XK_Armenian_GHAT 0x14d4
-0x0000 #define XK_Armenian_ghat 0x14d5
-0x0000 #define XK_Armenian_TCHE 0x14d6
-0x0000 #define XK_Armenian_tche 0x14d7
-0x0000 #define XK_Armenian_MEN 0x14d8
-0x0000 #define XK_Armenian_men 0x14d9
-0x0000 #define XK_Armenian_HI 0x14da
-0x0000 #define XK_Armenian_hi 0x14db
-0x0000 #define XK_Armenian_NU 0x14dc
-0x0000 #define XK_Armenian_nu 0x14dd
-0x0000 #define XK_Armenian_SHA 0x14de
-0x0000 #define XK_Armenian_sha 0x14df
-0x0000 #define XK_Armenian_VO 0x14e0
-0x0000 #define XK_Armenian_vo 0x14e1
-0x0000 #define XK_Armenian_CHA 0x14e2
-0x0000 #define XK_Armenian_cha 0x14e3
-0x0000 #define XK_Armenian_PE 0x14e4
-0x0000 #define XK_Armenian_pe 0x14e5
-0x0000 #define XK_Armenian_JE 0x14e6
-0x0000 #define XK_Armenian_je 0x14e7
-0x0000 #define XK_Armenian_RA 0x14e8
-0x0000 #define XK_Armenian_ra 0x14e9
-0x0000 #define XK_Armenian_SE 0x14ea
-0x0000 #define XK_Armenian_se 0x14eb
-0x0000 #define XK_Armenian_VEV 0x14ec
-0x0000 #define XK_Armenian_vev 0x14ed
-0x0000 #define XK_Armenian_TYUN 0x14ee
-0x0000 #define XK_Armenian_tyun 0x14ef
-0x0000 #define XK_Armenian_RE 0x14f0
-0x0000 #define XK_Armenian_re 0x14f1
-0x0000 #define XK_Armenian_TSO 0x14f2
-0x0000 #define XK_Armenian_tso 0x14f3
-0x0000 #define XK_Armenian_VYUN 0x14f4
-0x0000 #define XK_Armenian_vyun 0x14f5
-0x0000 #define XK_Armenian_PYUR 0x14f6
-0x0000 #define XK_Armenian_pyur 0x14f7
-0x0000 #define XK_Armenian_KE 0x14f8
-0x0000 #define XK_Armenian_ke 0x14f9
-0x0000 #define XK_Armenian_O 0x14fa
-0x0000 #define XK_Armenian_o 0x14fb
-0x0000 #define XK_Armenian_FE 0x14fc
-0x0000 #define XK_Armenian_fe 0x14fd
-0x0000 #define XK_Armenian_apostrophe 0x14fe
-0x0000 #define XK_Armenian_section_sign 0x14ff
-#endif /* XK_ARMENIAN */
-
-/*
- * Georgian
- * Byte 3 = 0x15
- */
-//yan: skip Georgian for now;
-#ifdef XK_GEORGIAN
-0x0000 #define XK_Georgian_an 0x15d0
-0x0000 #define XK_Georgian_ban 0x15d1
-0x0000 #define XK_Georgian_gan 0x15d2
-0x0000 #define XK_Georgian_don 0x15d3
-0x0000 #define XK_Georgian_en 0x15d4
-0x0000 #define XK_Georgian_vin 0x15d5
-0x0000 #define XK_Georgian_zen 0x15d6
-0x0000 #define XK_Georgian_tan 0x15d7
-0x0000 #define XK_Georgian_in 0x15d8
-0x0000 #define XK_Georgian_kan 0x15d9
-0x0000 #define XK_Georgian_las 0x15da
-0x0000 #define XK_Georgian_man 0x15db
-0x0000 #define XK_Georgian_nar 0x15dc
-0x0000 #define XK_Georgian_on 0x15dd
-0x0000 #define XK_Georgian_par 0x15de
-0x0000 #define XK_Georgian_zhar 0x15df
-0x0000 #define XK_Georgian_rae 0x15e0
-0x0000 #define XK_Georgian_san 0x15e1
-0x0000 #define XK_Georgian_tar 0x15e2
-0x0000 #define XK_Georgian_un 0x15e3
-0x0000 #define XK_Georgian_phar 0x15e4
-0x0000 #define XK_Georgian_khar 0x15e5
-0x0000 #define XK_Georgian_ghan 0x15e6
-0x0000 #define XK_Georgian_qar 0x15e7
-0x0000 #define XK_Georgian_shin 0x15e8
-0x0000 #define XK_Georgian_chin 0x15e9
-0x0000 #define XK_Georgian_can 0x15ea
-0x0000 #define XK_Georgian_jil 0x15eb
-0x0000 #define XK_Georgian_cil 0x15ec
-0x0000 #define XK_Georgian_char 0x15ed
-0x0000 #define XK_Georgian_xan 0x15ee
-0x0000 #define XK_Georgian_jhan 0x15ef
-0x0000 #define XK_Georgian_hae 0x15f0
-0x0000 #define XK_Georgian_he 0x15f1
-0x0000 #define XK_Georgian_hie 0x15f2
-0x0000 #define XK_Georgian_we 0x15f3
-0x0000 #define XK_Georgian_har 0x15f4
-0x0000 #define XK_Georgian_hoe 0x15f5
-0x0000 #define XK_Georgian_fi 0x15f6
-#endif /* XK_GEORGIAN */
-
-/*
- * Azeri (and other Turkic or Caucasian languages of ex-USSR)
- * Byte 3 = 0x16
- */
-
-#ifdef XK_CAUCASUS
-/* latin */
-0x0000 #define XK_Ccedillaabovedot 0x16a2
-0x1e8a #define XK_Xabovedot 0x16a3
-0x0000 #define XK_Qabovedot 0x16a5
-0x012c #define XK_Ibreve 0x16a6
-0x0000 #define XK_IE 0x16a7
-0x0000 #define XK_UO 0x16a8
-0x01b5 #define XK_Zstroke 0x16a9
-0x01e6 #define XK_Gcaron 0x16aa
-0x019f #define XK_Obarred 0x16af
-0x0000 #define XK_ccedillaabovedot 0x16b2
-0x1e8b #define XK_xabovedot 0x16b3
-0x0000 #define XK_Ocaron 0x16b4
-0x0000 #define XK_qabovedot 0x16b5
-0x012d #define XK_ibreve 0x16b6
-0x0000 #define XK_ie 0x16b7
-0x0000 #define XK_uo 0x16b8
-0x01b6 #define XK_zstroke 0x16b9
-0x01e7 #define XK_gcaron 0x16ba
-0x01d2 #define XK_ocaron 0x16bd
-0x0275 #define XK_obarred 0x16bf
-0x018f #define XK_SCHWA 0x16c6
-0x0259 #define XK_schwa 0x16f6
-/* those are not really Caucasus, but I put them here for now */
-/* For Inupiak */
-// yan: is there unicode for Inupiak or Guarani at all?
-0x0000 #define XK_Lbelowdot 0x16d1
-0x0000 #define XK_Lstrokebelowdot 0x16d2
-0x0000 #define XK_lbelowdot 0x16e1
-0x0000 #define XK_lstrokebelowdot 0x16e2
-/* For Guarani */
-0x0000 #define XK_Gtilde 0x16d3
-0x0000 #define XK_gtilde 0x16e3
-#endif /* XK_CAUCASUS */
-
-/*
- * Vietnamese
- * Byte 3 = 0x1e
- */
-
-#ifdef XK_VIETNAMESE
-0x1ea0 #define XK_Abelowdot 0x1ea0
-0x1ea1 #define XK_abelowdot 0x1ea1
-0x1ea2 #define XK_Ahook 0x1ea2
-0x1ea3 #define XK_ahook 0x1ea3
-0x1ea4 #define XK_Acircumflexacute 0x1ea4
-0x1ea5 #define XK_acircumflexacute 0x1ea5
-0x1ea6 #define XK_Acircumflexgrave 0x1ea6
-0x1ea7 #define XK_acircumflexgrave 0x1ea7
-0x1ea8 #define XK_Acircumflexhook 0x1ea8
-0x1ea9 #define XK_acircumflexhook 0x1ea9
-0x1eaa #define XK_Acircumflextilde 0x1eaa
-0x1eab #define XK_acircumflextilde 0x1eab
-0x1eac #define XK_Acircumflexbelowdot 0x1eac
-0x1ead #define XK_acircumflexbelowdot 0x1ead
-0x1eae #define XK_Abreveacute 0x1eae
-0x1eaf #define XK_abreveacute 0x1eaf
-0x1eb0 #define XK_Abrevegrave 0x1eb0
-0x1eb1 #define XK_abrevegrave 0x1eb1
-0x1eb2 #define XK_Abrevehook 0x1eb2
-0x1eb3 #define XK_abrevehook 0x1eb3
-0x1eb4 #define XK_Abrevetilde 0x1eb4
-0x1eb5 #define XK_abrevetilde 0x1eb5
-0x1eb6 #define XK_Abrevebelowdot 0x1eb6
-0x1eb7 #define XK_abrevebelowdot 0x1eb7
-0x1eb8 #define XK_Ebelowdot 0x1eb8
-0x1eb9 #define XK_ebelowdot 0x1eb9
-0x1eba #define XK_Ehook 0x1eba
-0x1ebb #define XK_ehook 0x1ebb
-0x1ebc #define XK_Etilde 0x1ebc
-0x1ebd #define XK_etilde 0x1ebd
-0x1ebe #define XK_Ecircumflexacute 0x1ebe
-0x1ebf #define XK_ecircumflexacute 0x1ebf
-0x1ec0 #define XK_Ecircumflexgrave 0x1ec0
-0x1ec1 #define XK_ecircumflexgrave 0x1ec1
-0x1ec2 #define XK_Ecircumflexhook 0x1ec2
-0x1ec3 #define XK_ecircumflexhook 0x1ec3
-0x1ec4 #define XK_Ecircumflextilde 0x1ec4
-0x1ec5 #define XK_ecircumflextilde 0x1ec5
-0x1ec6 #define XK_Ecircumflexbelowdot 0x1ec6
-0x1ec7 #define XK_ecircumflexbelowdot 0x1ec7
-0x1ec8 #define XK_Ihook 0x1ec8
-0x1ec9 #define XK_ihook 0x1ec9
-0x1eca #define XK_Ibelowdot 0x1eca
-0x1ecb #define XK_ibelowdot 0x1ecb
-0x1ecc #define XK_Obelowdot 0x1ecc
-0x1ecd #define XK_obelowdot 0x1ecd
-0x1ece #define XK_Ohook 0x1ece
-0x1ecf #define XK_ohook 0x1ecf
-0x1ed0 #define XK_Ocircumflexacute 0x1ed0
-0x1ed1 #define XK_ocircumflexacute 0x1ed1
-0x1ed2 #define XK_Ocircumflexgrave 0x1ed2
-0x1ed3 #define XK_ocircumflexgrave 0x1ed3
-0x1ed4 #define XK_Ocircumflexhook 0x1ed4
-0x1ed5 #define XK_ocircumflexhook 0x1ed5
-0x1ed6 #define XK_Ocircumflextilde 0x1ed6
-0x1ed7 #define XK_ocircumflextilde 0x1ed7
-0x1ed8 #define XK_Ocircumflexbelowdot 0x1ed8
-0x1ed9 #define XK_ocircumflexbelowdot 0x1ed9
-0x1eda #define XK_Ohornacute 0x1eda
-0x1edb #define XK_ohornacute 0x1edb
-0x1edc #define XK_Ohorngrave 0x1edc
-0x1edd #define XK_ohorngrave 0x1edd
-0x1ede #define XK_Ohornhook 0x1ede
-0x1edf #define XK_ohornhook 0x1edf
-0x1ee0 #define XK_Ohorntilde 0x1ee0
-0x1ee1 #define XK_ohorntilde 0x1ee1
-0x1ee2 #define XK_Ohornbelowdot 0x1ee2
-0x1ee3 #define XK_ohornbelowdot 0x1ee3
-0x1ee4 #define XK_Ubelowdot 0x1ee4
-0x1ee5 #define XK_ubelowdot 0x1ee5
-0x1ee6 #define XK_Uhook 0x1ee6
-0x1ee7 #define XK_uhook 0x1ee7
-0x1ee8 #define XK_Uhornacute 0x1ee8
-0x1ee9 #define XK_uhornacute 0x1ee9
-0x1eea #define XK_Uhorngrave 0x1eea
-0x1eeb #define XK_uhorngrave 0x1eeb
-0x1eec #define XK_Uhornhook 0x1eec
-0x1eed #define XK_uhornhook 0x1eed
-0x1eee #define XK_Uhorntilde 0x1eee
-0x1eef #define XK_uhorntilde 0x1eef
-0x1ef0 #define XK_Uhornbelowdot 0x1ef0
-0x1ef1 #define XK_uhornbelowdot 0x1ef1
-0x1ef4 #define XK_Ybelowdot 0x1ef4
-0x1ef5 #define XK_ybelowdot 0x1ef5
-0x1ef6 #define XK_Yhook 0x1ef6
-0x1ef7 #define XK_yhook 0x1ef7
-0x1ef8 #define XK_Ytilde 0x1ef8
-0x1ef9 #define XK_ytilde 0x1ef9
-0x01a0 #define XK_Ohorn 0x1efa /* U+01a0 */
-0x01a1 #define XK_ohorn 0x1efb /* U+01a1 */
-0x01af #define XK_Uhorn 0x1efc /* U+01af */
-0x01b0 #define XK_uhorn 0x1efd /* U+01b0 */
-
-0x0000 #define XK_combining_tilde 0x1e9f /* U+0303 */
-0x0000 #define XK_combining_grave 0x1ef2 /* U+0300 */
-0x0000 #define XK_combining_acute 0x1ef3 /* U+0301 */
-0x0000 #define XK_combining_hook 0x1efe /* U+0309 */
-0x0000 #define XK_combining_belowdot 0x1eff /* U+0323 */
-#endif /* XK_VIETNAMESE */
-
-#ifdef XK_CURRENCY
-0x20a0 #define XK_EcuSign 0x20a0
-0x20a1 #define XK_ColonSign 0x20a1
-0x20a2 #define XK_CruzeiroSign 0x20a2
-0x20a3 #define XK_FFrancSign 0x20a3
-0x20a4 #define XK_LiraSign 0x20a4
-0x20a5 #define XK_MillSign 0x20a5
-0x20a6 #define XK_NairaSign 0x20a6
-0x20a7 #define XK_PesetaSign 0x20a7
-0x20a8 #define XK_RupeeSign 0x20a8
-0x20a9 #define XK_WonSign 0x20a9
-0x20aa #define XK_NewSheqelSign 0x20aa
-0x20ab #define XK_DongSign 0x20ab
-0x20ac #define XK_EuroSign 0x20ac
-#endif
-
-//yan: keysyms from vendor headers go here. I don't know many though.
-
-0x0008 #define osfXK_BackSpace 0x1004FF08
-0x001b #define osfXK_Escape 0x1004FF1B
-//XXX ? Esc on Solaris?, to check
-0x0000 #define osfXK_Cancel 0x1004FF69
-0x007f #define osfXK_Delete 0x1004FFFF
-
-tojava
-tojava //XXX fill keysym2JavaKeycodeHash.
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_a), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_A, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_b), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_B, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_c), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_C, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_d), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_D, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_e), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_E, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_f), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_g), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_G, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_h), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_H, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_i), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_I, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_j), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_J, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_k), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_K, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_l), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_L, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_m), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_M, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_n), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_N, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_o), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_O, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_p), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_P, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_q), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_Q, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_r), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_R, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_s), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_S, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_t), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_T, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_u), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_U, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_v), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_V, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_w), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_W, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_x), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_X, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_y), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_Y, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_z), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_Z, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* TTY Function keys */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_BackSpace), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BACK_SPACE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Tab), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_TAB, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_ISO_Left_Tab), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_TAB, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Clear), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CLEAR, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Return), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ENTER, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Linefeed), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ENTER, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Pause), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAUSE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F21), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAUSE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R1), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAUSE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Scroll_Lock), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SCROLL_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F23), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SCROLL_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R3), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SCROLL_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Escape), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ESCAPE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Other vendor-specific versions of TTY Function keys */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_BackSpace), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BACK_SPACE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Clear), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CLEAR, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Escape), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ESCAPE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Modifier keys */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Shift_L), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SHIFT, java.awt.event.KeyEvent.KEY_LOCATION_LEFT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Shift_R), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SHIFT, java.awt.event.KeyEvent.KEY_LOCATION_RIGHT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Control_L), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CONTROL, java.awt.event.KeyEvent.KEY_LOCATION_LEFT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Control_R), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CONTROL, java.awt.event.KeyEvent.KEY_LOCATION_RIGHT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Alt_L), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALT, java.awt.event.KeyEvent.KEY_LOCATION_LEFT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Alt_R), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALT, java.awt.event.KeyEvent.KEY_LOCATION_RIGHT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Meta_L), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_META, java.awt.event.KeyEvent.KEY_LOCATION_LEFT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Meta_R), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_META, java.awt.event.KeyEvent.KEY_LOCATION_RIGHT));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Caps_Lock), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CAPS_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Shift_Lock), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CAPS_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Misc Functions */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Print), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PRINTSCREEN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F22), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PRINTSCREEN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R2), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PRINTSCREEN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Cancel), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CANCEL, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Help), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HELP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Num_Lock), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUM_LOCK, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava
-tojava /* Other vendor-specific versions of Misc Functions */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Cancel), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CANCEL, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Help), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HELP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Rectangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Home), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HOME, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R7), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HOME, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Page_Up), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Prior), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R9), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Page_Down), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Next), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R15), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_End), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_END, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R13), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_END, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Insert), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_INSERT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Delete), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DELETE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Keypad equivalents of Rectangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Home), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HOME, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Page_Up), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Prior), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Page_Down), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Next), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_End), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_END, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Insert), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_INSERT, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Delete), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DELETE, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava
-tojava /* Other vendor-specific Rectangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_PageUp), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Prior), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_PageDown), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Next), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PAGE_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_EndLine), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_END, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Insert), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_INSERT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Delete), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DELETE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Triangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Left), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_LEFT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Up), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Right), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_RIGHT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Down), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Keypad equivalents of Triangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Left), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KP_LEFT, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Up), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KP_UP, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Right), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KP_RIGHT, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Down), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KP_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava
-tojava /* Other vendor-specific Triangular Navigation Block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Left), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_LEFT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Up), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Right), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_RIGHT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Down), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DOWN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Remaining Cursor control & motion */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Begin), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BEGIN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Begin), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BEGIN, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_0), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_0, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_1), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_1, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_2), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_2, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_3), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_3, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_4), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_4, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_5), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_5, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_6), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_6, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_7), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_7, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_8), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_8, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_9), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_9, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_space), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SPACE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_exclam), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_EXCLAMATION_MARK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_quotedbl), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_QUOTEDBL, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_numbersign), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMBER_SIGN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dollar), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DOLLAR, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_ampersand), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_AMPERSAND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_apostrophe), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_QUOTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_parenleft), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_LEFT_PARENTHESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_parenright), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_RIGHT_PARENTHESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_asterisk), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ASTERISK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_plus), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PLUS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_comma), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COMMA, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_minus), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_MINUS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_period), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PERIOD, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_slash), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SLASH, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_colon), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COLON, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_semicolon), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SEMICOLON, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_less), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_LESS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_equal), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_EQUALS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_greater), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_GREATER, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_at), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_AT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_bracketleft), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_OPEN_BRACKET, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_backslash), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BACK_SLASH, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_bracketright), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CLOSE_BRACKET, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_asciicircum), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_underscore), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDERSCORE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Super_L), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_WINDOWS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Super_R), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_WINDOWS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Menu), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CONTEXT_MENU, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_grave), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BACK_QUOTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_braceleft), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BRACELEFT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_braceright), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_BRACERIGHT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_exclamdown), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_INVERTED_EXCLAMATION_MARK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Remaining Numeric Keypad Keys */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_0), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD0, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_1), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD1, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_2), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD2, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_3), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD3, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_4), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD4, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_5), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD5, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_6), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD6, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_7), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD7, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_8), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD8, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_9), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NUMPAD9, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Space), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SPACE, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Tab), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_TAB, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Enter), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ENTER, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Equal), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_EQUALS, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R4), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_EQUALS, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Multiply), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_MULTIPLY, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F26), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_MULTIPLY, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R6), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_MULTIPLY, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Add), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ADD, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Separator), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SEPARATOR, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Subtract), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SUBTRACT, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F24), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_SUBTRACT, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Decimal), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DECIMAL, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_KP_Divide), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DIVIDE, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F25), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DIVIDE, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_R5), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DIVIDE, java.awt.event.KeyEvent.KEY_LOCATION_NUMPAD));
-tojava
-tojava /* Function Keys */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F1), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F1, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F2), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F2, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F3), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F3, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F4), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F4, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F5), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F5, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F6), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F6, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F7), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F7, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F8), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F8, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F9), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F9, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F10), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F10, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F11), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F11, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_F12), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F12, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Sun vendor-specific version of F11 and F12 */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_F36), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F11, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_F37), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_F12, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* X11 keysym names for input method related keys don't always
-tojava * match keytop engravings or Java virtual key names, so here we
-tojava * only map constants that we've found on real keyboards.
-tojava */
-tojava /* Type 5c Japanese keyboard: kakutei */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Execute), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ACCEPT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava /* Type 5c Japanese keyboard: henkan */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Kanji), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CONVERT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava /* Type 5c Japanese keyboard: nihongo */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Henkan_Mode), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_INPUT_METHOD_ON_OFF, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Eisu_Shift ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALPHANUMERIC , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Eisu_toggle ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALPHANUMERIC , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Zenkaku ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_FULL_WIDTH , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Hankaku ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HALF_WIDTH , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Hiragana ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_HIRAGANA , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Katakana ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KATAKANA , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Romaji ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_JAPANESE_ROMAN , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Kana_Shift ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Kana_Lock ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_KANA_LOCK , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Muhenkan ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_NONCONVERT , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Zen_Koho ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALL_CANDIDATES , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Kanji_Bangou ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CODE_INPUT , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Mae_Koho ), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PREVIOUS_CANDIDATE , java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava
-tojava /* VK_KANA_LOCK is handled separately because it generates the
-tojava * same keysym as ALT_GRAPH in spite of its different behavior.
-tojava */
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Multi_key), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COMPOSE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Mode_switch), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALT_GRAPH, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_ISO_Level3_Shift), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_ALT_GRAPH, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Editing block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Redo), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_AGAIN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava // XXX XK_L2 == F12; TODO: add code to use only one of them depending on the keyboard type. For now, restore
-tojava // good PC behavior and bad but old Sparc behavior.
-tojava // keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L2), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_AGAIN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Undo), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDO, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L4), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDO, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L6), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COPY, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L8), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PASTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L10), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CUT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_Find), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_FIND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L9), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_FIND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L3), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PROPS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava // XXX XK_L1 == F11; TODO: add code to use only one of them depending on the keyboard type. For now, restore
-tojava // good PC behavior and bad but old Sparc behavior.
-tojava // keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_L1), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_STOP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Sun vendor-specific versions for editing block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Again), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_AGAIN, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Undo), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDO, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Copy), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COPY, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Paste), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PASTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Cut), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CUT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Find), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_FIND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Props), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PROPS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_Stop), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_STOP, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Apollo (HP) vendor-specific versions for editing block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.apXK_Copy), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COPY, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.apXK_Cut), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CUT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.apXK_Paste), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PASTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Other vendor-specific versions for editing block */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Copy), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_COPY, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Cut), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_CUT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Paste), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_PASTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.osfXK_Undo), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDO, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Dead key mappings (for European keyboards) */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_grave), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_GRAVE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_acute), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ACUTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_circumflex), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_tilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_macron), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_MACRON, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_breve), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_BREVE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_abovedot), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ABOVEDOT, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_diaeresis), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DIAERESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_abovering), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ABOVERING, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_doubleacute), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DOUBLEACUTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_caron), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CARON, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_cedilla), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CEDILLA, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_ogonek), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_OGONEK, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_iota), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_IOTA, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_voiced_sound), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_VOICED_SOUND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.XK_dead_semivoiced_sound), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_SEMIVOICED_SOUND, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Sun vendor-specific dead key mappings (for European keyboards) */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Grave), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_GRAVE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Circum), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Tilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Acute), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ACUTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Diaeresis), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DIAERESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.SunXK_FA_Cedilla), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CEDILLA, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* DEC vendor-specific dead key mappings (for European keyboards) */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_ring_accent), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ABOVERING, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_circumflex_accent), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_cedilla_accent), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CEDILLA, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_acute_accent), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ACUTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_grave_accent), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_GRAVE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_tilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.DXK_diaeresis), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DIAERESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava /* Other vendor-specific dead key mappings (for European keyboards) */
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_acute), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_ACUTE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_grave), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_GRAVE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciicircum), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_CIRCUMFLEX, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_diaeresis), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_DIAERESIS, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XKeySymConstants.hpXK_mute_asciitilde), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_DEAD_TILDE, java.awt.event.KeyEvent.KEY_LOCATION_STANDARD));
-tojava
-tojava keysym2JavaKeycodeHash.put( Long.valueOf(XConstants.NoSymbol), new Keysym2JavaKeycode(java.awt.event.KeyEvent.VK_UNDEFINED, java.awt.event.KeyEvent.KEY_LOCATION_UNKNOWN));
-tojava
-tojava /* Reverse search of keysym by keycode. */
-tojava
-tojava /* Add keyboard locking codes. */
-tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_CAPS_LOCK, XKeySymConstants.XK_Caps_Lock);
-tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_NUM_LOCK, XKeySymConstants.XK_Num_Lock);
-tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_SCROLL_LOCK, XKeySymConstants.XK_Scroll_Lock);
-tojava javaKeycode2KeysymHash.put( java.awt.event.KeyEvent.VK_KANA_LOCK, XKeySymConstants.XK_Kana_Lock);
-tojava };
-tojava
-tojava }
diff --git a/src/solaris/classes/sun/font/XRGlyphCache.java b/src/solaris/classes/sun/font/XRGlyphCache.java
index 74ac140a78..ec31af6a29 100644
--- a/src/solaris/classes/sun/font/XRGlyphCache.java
+++ b/src/solaris/classes/sun/font/XRGlyphCache.java
@@ -114,6 +114,9 @@ public class XRGlyphCache implements GlyphDisposedListener {
for (int i = 0; i < glyphList.getNumGlyphs(); i++) {
XRGlyphCacheEntry glyph;
+ if (imgPtrs[i] == 0L) {
+ continue;
+ }
// Find uncached glyphs and queue them for upload
if ((glyph = getEntryForPointer(imgPtrs[i])) == null) {
glyph = new XRGlyphCacheEntry(imgPtrs[i], glyphList);
diff --git a/src/solaris/classes/sun/font/XRTextRenderer.java b/src/solaris/classes/sun/font/XRTextRenderer.java
index 93cce2ef2b..613b6c556e 100644
--- a/src/solaris/classes/sun/font/XRTextRenderer.java
+++ b/src/solaris/classes/sun/font/XRTextRenderer.java
@@ -93,6 +93,9 @@ public class XRTextRenderer extends GlyphListPipe {
for (int i = 0; i < gl.getNumGlyphs(); i++) {
gl.setGlyphIndex(i);
XRGlyphCacheEntry cacheEntry = cachedGlyphs[i];
+ if (cacheEntry == null) {
+ continue;
+ }
eltList.getGlyphs().addInt(cacheEntry.getGlyphID());
int glyphSet = cacheEntry.getGlyphSet();
diff --git a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
index 428f05cf6e..6d196b8c7c 100644
--- a/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
+++ b/src/solaris/classes/sun/nio/ch/UnixAsynchronousSocketChannelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -269,6 +269,7 @@ class UnixAsynchronousSocketChannelImpl
// invoke handler and set result
CompletionHandler<Void,Object> handler = connectHandler;
+ connectHandler = null;
Object att = connectAttachment;
PendingFuture<Void,Object> future = connectFuture;
if (handler == null) {
@@ -398,6 +399,7 @@ class UnixAsynchronousSocketChannelImpl
this.readBuffer = null;
this.readBuffers = null;
this.readAttachment = null;
+ this.readHandler = null;
// allow another read to be initiated
enableReading();
@@ -593,6 +595,7 @@ class UnixAsynchronousSocketChannelImpl
this.writeBuffer = null;
this.writeBuffers = null;
this.writeAttachment = null;
+ this.writeHandler = null;
// allow another write to be initiated
enableWriting();
diff --git a/src/solaris/classes/sun/nio/fs/BsdFileStore.java b/src/solaris/classes/sun/nio/fs/BsdFileStore.java
index b73218ead5..dee2980502 100644
--- a/src/solaris/classes/sun/nio/fs/BsdFileStore.java
+++ b/src/solaris/classes/sun/nio/fs/BsdFileStore.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -62,22 +62,14 @@ class BsdFileStore
}
// step 2: find mount point
- UnixPath parent = path.getParent();
- while (parent != null) {
- UnixFileAttributes attrs = null;
- try {
- attrs = UnixFileAttributes.get(parent, true);
- } catch (UnixException x) {
- x.rethrowAsIOException(parent);
- }
- if (attrs.dev() != dev())
- break;
- path = parent;
- parent = parent.getParent();
+ byte[] dir = null;
+ try {
+ dir = BsdNativeDispatcher.getmntonname(path);
+ } catch (UnixException x) {
+ x.rethrowAsIOException(path);
}
// step 3: lookup mounted file systems
- byte[] dir = path.asByteArray();
for (UnixMountEntry entry: fs.getMountEntries()) {
if (Arrays.equals(dir, entry.dir()))
return entry;
diff --git a/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java b/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java
index 7acbc4fa75..b5174e7a98 100644
--- a/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java
+++ b/src/solaris/classes/sun/nio/fs/BsdNativeDispatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -51,6 +51,20 @@ class BsdNativeDispatcher extends UnixNativeDispatcher {
*/
static native void endfsstat(long iter) throws UnixException;
+ /**
+ * int statfs(const char *path, struct statfs *buf);
+ * returns buf->f_mntonname (directory on which mounted)
+ */
+ static byte[] getmntonname(UnixPath path) throws UnixException {
+ NativeBuffer pathBuffer = copyToNativeBuffer(path);
+ try {
+ return getmntonname0(pathBuffer.address());
+ } finally {
+ pathBuffer.release();
+ }
+ }
+ static native byte[] getmntonname0(long pathAddress) throws UnixException;
+
// initialize field IDs
private static native void initIDs();
diff --git a/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
index 7a676d1863..7a8c918af2 100644
--- a/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
+++ b/src/solaris/classes/sun/nio/fs/UnixNativeDispatcher.java
@@ -36,7 +36,7 @@ class UnixNativeDispatcher {
protected UnixNativeDispatcher() { }
// returns a NativeBuffer containing the given path
- private static NativeBuffer copyToNativeBuffer(UnixPath path) {
+ static NativeBuffer copyToNativeBuffer(UnixPath path) {
byte[] cstr = path.getByteArrayForSysCalls();
int size = cstr.length + 1;
NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size);
diff --git a/src/solaris/classes/sun/print/CUPSPrinter.java b/src/solaris/classes/sun/print/CUPSPrinter.java
index ef33dde420..479071c655 100644
--- a/src/solaris/classes/sun/print/CUPSPrinter.java
+++ b/src/solaris/classes/sun/print/CUPSPrinter.java
@@ -318,8 +318,8 @@ public class CUPSPrinter {
* reported, exec lpstat -d which has all the Apple
* special behaviour for this built in.
*/
- if (UnixPrintServiceLookup.isMac()) {
- printerInfo[0] = UnixPrintServiceLookup.
+ if (PrintServiceLookupProvider.isMac()) {
+ printerInfo[0] = PrintServiceLookupProvider.
getDefaultPrinterNameSysV();
printerInfo[1] = null;
return (String[])printerInfo.clone();
diff --git a/src/solaris/classes/sun/print/IPPPrintService.java b/src/solaris/classes/sun/print/IPPPrintService.java
index ee8cf62171..c8ed952b3a 100644
--- a/src/solaris/classes/sun/print/IPPPrintService.java
+++ b/src/solaris/classes/sun/print/IPPPrintService.java
@@ -1042,7 +1042,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
setting like collation. Therefore, we temporarily exclude
Linux.
*/
- if (!UnixPrintServiceLookup.isLinux()) {
+ if (!PrintServiceLookupProvider.isLinux()) {
catList.add(SheetCollate.class);
}
}
@@ -1586,7 +1586,7 @@ public class IPPPrintService implements PrintService, SunPrinterJobService {
* Mac is using printer-info IPP attribute for its human-readable printer
* name and is also the identifier used in NSPrintInfo:setPrinter.
*/
- if (UnixPrintServiceLookup.isMac()) {
+ if (PrintServiceLookupProvider.isMac()) {
PrintServiceAttributeSet psaSet = this.getAttributes();
if (psaSet != null) {
PrinterInfo pName = (PrinterInfo)psaSet.get(PrinterInfo.class);
diff --git a/src/solaris/classes/sun/print/UnixPrintServiceLookup.java b/src/solaris/classes/sun/print/PrintServiceLookupProvider.java
index 373494e510..e1432b9ff9 100644
--- a/src/solaris/classes/sun/print/UnixPrintServiceLookup.java
+++ b/src/solaris/classes/sun/print/PrintServiceLookupProvider.java
@@ -58,7 +58,7 @@ import java.nio.file.Files;
* Remind: This class uses solaris commands. We also need a linux
* version
*/
-public class UnixPrintServiceLookup extends PrintServiceLookup
+public class PrintServiceLookupProvider extends PrintServiceLookup
implements BackgroundServiceLookup, Runnable {
/* Remind: the current implementation is static, as its assumed
@@ -70,7 +70,7 @@ public class UnixPrintServiceLookup extends PrintServiceLookup
private PrintService defaultPrintService;
private PrintService[] printServices; /* includes the default printer */
private Vector lookupListeners = null;
- private static String debugPrefix = "UnixPrintServiceLookup>> ";
+ private static String debugPrefix = "PrintServiceLookupProvider>> ";
private static boolean pollServices = true;
private static final int DEFAULT_MINREFRESH = 120; // 2 minutes
private static int minRefreshTime = DEFAULT_MINREFRESH;
@@ -208,7 +208,7 @@ public class UnixPrintServiceLookup extends PrintServiceLookup
}
- public UnixPrintServiceLookup() {
+ public PrintServiceLookupProvider() {
// start the printer listener thread
if (pollServices) {
PrinterChangeListener thr = new PrinterChangeListener();
diff --git a/src/solaris/classes/sun/print/UnixPrintJob.java b/src/solaris/classes/sun/print/UnixPrintJob.java
index c18bb757d0..314f7e9d8f 100644
--- a/src/solaris/classes/sun/print/UnixPrintJob.java
+++ b/src/solaris/classes/sun/print/UnixPrintJob.java
@@ -122,7 +122,7 @@ public class UnixPrintJob implements CancelablePrintJob {
UnixPrintJob(PrintService service) {
this.service = service;
mDestination = service.getName();
- if (UnixPrintServiceLookup.isMac()) {
+ if (PrintServiceLookupProvider.isMac()) {
mDestination = ((IPPPrintService)service).getDest();
}
mDestType = UnixPrintJob.DESTPRINTER;
@@ -873,7 +873,7 @@ public class UnixPrintJob implements CancelablePrintJob {
pFlags |= NOSHEET;
ncomps+=1;
}
- if (UnixPrintServiceLookup.osname.equals("SunOS")) {
+ if (PrintServiceLookupProvider.osname.equals("SunOS")) {
ncomps+=1; // lp uses 1 more arg than lpr (make a copy)
execCmd = new String[ncomps];
execCmd[n++] = "/usr/bin/lp";
diff --git a/src/solaris/classes/sun/print/UnixPrintService.java b/src/solaris/classes/sun/print/UnixPrintService.java
index bb9a6dfce5..9d22b666ae 100644
--- a/src/solaris/classes/sun/print/UnixPrintService.java
+++ b/src/solaris/classes/sun/print/UnixPrintService.java
@@ -220,7 +220,7 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {
String command = "/usr/bin/lpstat -a " + printer;
- String results[]= UnixPrintServiceLookup.execCmd(command);
+ String results[]= PrintServiceLookupProvider.execCmd(command);
if (results != null && results.length > 0) {
if (results[0].startsWith(printer + " accepting requests")) {
@@ -244,20 +244,20 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
}
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {
- if (UnixPrintServiceLookup.cmdIndex ==
- UnixPrintServiceLookup.UNINITIALIZED) {
+ if (PrintServiceLookupProvider.cmdIndex ==
+ PrintServiceLookupProvider.UNINITIALIZED) {
- UnixPrintServiceLookup.cmdIndex =
- UnixPrintServiceLookup.getBSDCommandIndex();
+ PrintServiceLookupProvider.cmdIndex =
+ PrintServiceLookupProvider.getBSDCommandIndex();
}
String command = "/usr/sbin/lpc status " + printer
- + lpcStatusCom[UnixPrintServiceLookup.cmdIndex];
- String results[]= UnixPrintServiceLookup.execCmd(command);
+ + lpcStatusCom[PrintServiceLookupProvider.cmdIndex];
+ String results[]= PrintServiceLookupProvider.execCmd(command);
if (results != null && results.length > 0) {
- if (UnixPrintServiceLookup.cmdIndex ==
- UnixPrintServiceLookup.BSD_LPD_NG) {
+ if (PrintServiceLookupProvider.cmdIndex ==
+ PrintServiceLookupProvider.BSD_LPD_NG) {
if (results[0].startsWith("enabled enabled")) {
return PrinterIsAcceptingJobs.ACCEPTING_JOBS ;
}
@@ -276,7 +276,7 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
// Filter the list of possible AIX Printers and remove header lines
// and extra lines which have been added for remote printers.
- // 'protected' because this method is also used from UnixPrintServiceLookup.
+ // 'protected' because this method is also used from PrintServiceLookupProvider.
protected static String[] filterPrinterNamesAIX(String[] posPrinters) {
ArrayList printers = new ArrayList();
String [] splitPart;
@@ -301,7 +301,7 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsAIX() {
// On AIX there should not be a blank after '-a'.
String command = "/usr/bin/lpstat -a" + printer;
- String results[]= UnixPrintServiceLookup.execCmd(command);
+ String results[]= PrintServiceLookupProvider.execCmd(command);
// Remove headers and bogus entries added by remote printers.
results = filterPrinterNamesAIX(results);
@@ -320,11 +320,11 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
}
private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
- if (UnixPrintServiceLookup.isSysV()) {
+ if (PrintServiceLookupProvider.isSysV()) {
return getPrinterIsAcceptingJobsSysV();
- } else if (UnixPrintServiceLookup.isBSD()) {
+ } else if (PrintServiceLookupProvider.isBSD()) {
return getPrinterIsAcceptingJobsBSD();
- } else if (UnixPrintServiceLookup.isAIX()) {
+ } else if (PrintServiceLookupProvider.isAIX()) {
return getPrinterIsAcceptingJobsAIX();
} else {
return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
@@ -351,29 +351,29 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
private QueuedJobCount getQueuedJobCountSysV() {
String command = "/usr/bin/lpstat -R " + printer;
- String results[]= UnixPrintServiceLookup.execCmd(command);
+ String results[]= PrintServiceLookupProvider.execCmd(command);
int qlen = (results == null) ? 0 : results.length;
return new QueuedJobCount(qlen);
}
private QueuedJobCount getQueuedJobCountBSD() {
- if (UnixPrintServiceLookup.cmdIndex ==
- UnixPrintServiceLookup.UNINITIALIZED) {
+ if (PrintServiceLookupProvider.cmdIndex ==
+ PrintServiceLookupProvider.UNINITIALIZED) {
- UnixPrintServiceLookup.cmdIndex =
- UnixPrintServiceLookup.getBSDCommandIndex();
+ PrintServiceLookupProvider.cmdIndex =
+ PrintServiceLookupProvider.getBSDCommandIndex();
}
int qlen = 0;
String command = "/usr/sbin/lpc status " + printer
- + lpcQueueCom[UnixPrintServiceLookup.cmdIndex];
- String results[] = UnixPrintServiceLookup.execCmd(command);
+ + lpcQueueCom[PrintServiceLookupProvider.cmdIndex];
+ String results[] = PrintServiceLookupProvider.execCmd(command);
if (results != null && results.length > 0) {
String queued;
- if (UnixPrintServiceLookup.cmdIndex ==
- UnixPrintServiceLookup.BSD_LPD_NG) {
+ if (PrintServiceLookupProvider.cmdIndex ==
+ PrintServiceLookupProvider.BSD_LPD_NG) {
queued = results[0];
} else {
queued = results[3].trim();
@@ -396,7 +396,7 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
private QueuedJobCount getQueuedJobCountAIX() {
// On AIX there should not be a blank after '-a'.
String command = "/usr/bin/lpstat -a" + printer;
- String results[]= UnixPrintServiceLookup.execCmd(command);
+ String results[]= PrintServiceLookupProvider.execCmd(command);
// Remove headers and bogus entries added by remote printers.
results = filterPrinterNamesAIX(results);
@@ -413,11 +413,11 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
}
private QueuedJobCount getQueuedJobCount() {
- if (UnixPrintServiceLookup.isSysV()) {
+ if (PrintServiceLookupProvider.isSysV()) {
return getQueuedJobCountSysV();
- } else if (UnixPrintServiceLookup.isBSD()) {
+ } else if (PrintServiceLookupProvider.isBSD()) {
return getQueuedJobCountBSD();
- } else if (UnixPrintServiceLookup.isAIX()) {
+ } else if (PrintServiceLookupProvider.isAIX()) {
return getQueuedJobCountAIX();
} else {
return new QueuedJobCount(0);
@@ -468,9 +468,9 @@ public class UnixPrintService implements PrintService, AttributeUpdater,
}
private PrintServiceAttributeSet getDynamicAttributes() {
- if (UnixPrintServiceLookup.isSysV()) {
+ if (PrintServiceLookupProvider.isSysV()) {
return getSysVServiceAttributes();
- } else if (UnixPrintServiceLookup.isAIX()) {
+ } else if (PrintServiceLookupProvider.isAIX()) {
return getAIXServiceAttributes();
} else {
return getBSDServiceAttributes();
diff --git a/src/solaris/classes/sun/print/services/javax.print.PrintServiceLookup b/src/solaris/classes/sun/print/services/javax.print.PrintServiceLookup
deleted file mode 100644
index 74beed6173..0000000000
--- a/src/solaris/classes/sun/print/services/javax.print.PrintServiceLookup
+++ /dev/null
@@ -1,2 +0,0 @@
-# Provider for Java Print Service
-sun.print.UnixPrintServiceLookup
diff --git a/src/solaris/native/java/io/canonicalize_md.c b/src/solaris/native/java/io/canonicalize_md.c
index e985c39b31..cb8ce69c88 100644
--- a/src/solaris/native/java/io/canonicalize_md.c
+++ b/src/solaris/native/java/io/canonicalize_md.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2019, 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
@@ -211,11 +211,10 @@ canonicalize(char *original, char *resolved, int len)
char *p, *end, *r = NULL;
char path[PATH_MAX + 1];
- strncpy(path, original, sizeof(path));
- if (path[PATH_MAX] != '\0') {
- errno = ENAMETOOLONG;
- return -1;
- }
+ // strlen(original) <= PATH_MAX, see above
+ strncpy(path, original, PATH_MAX);
+ // append null for == case
+ path[PATH_MAX] = '\0';
end = path + strlen(path);
for (p = end; p > path;) {
diff --git a/src/solaris/native/java/lang/java_props_macosx.c b/src/solaris/native/java/lang/java_props_macosx.c
index b11a4d0014..ce656170ce 100644
--- a/src/solaris/native/java/lang/java_props_macosx.c
+++ b/src/solaris/native/java/lang/java_props_macosx.c
@@ -47,6 +47,8 @@ char *getPosixLocale(int cat) {
#define LOCALEIDLENGTH 128
char *getMacOSXLocale(int cat) {
const char* retVal = NULL;
+ char languageString[LOCALEIDLENGTH];
+ char localeString[LOCALEIDLENGTH];
switch (cat) {
case LC_MESSAGES:
@@ -66,7 +68,6 @@ char *getMacOSXLocale(int cat) {
CFRelease(languages);
return NULL;
}
- char languageString[LOCALEIDLENGTH];
if (CFStringGetCString(primaryLanguage, languageString,
LOCALEIDLENGTH, CFStringGetSystemEncoding()) == false) {
CFRelease(languages);
@@ -81,7 +82,6 @@ char *getMacOSXLocale(int cat) {
// from Portuguese in Portugal), but this is missing when using the
// "Portuguese (Brazil)" language.
// If language is "pt" and the current locale is pt_BR, return pt_BR.
- char localeString[LOCALEIDLENGTH];
if (strcmp(retVal, "pt") == 0 &&
CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding()) &&
@@ -92,7 +92,6 @@ char *getMacOSXLocale(int cat) {
break;
default:
{
- char localeString[LOCALEIDLENGTH];
if (!CFStringGetCString(CFLocaleGetIdentifier(CFLocaleCopyCurrent()),
localeString, LOCALEIDLENGTH, CFStringGetSystemEncoding())) {
return NULL;
diff --git a/src/solaris/native/java/net/PlainDatagramSocketImpl.c b/src/solaris/native/java/net/PlainDatagramSocketImpl.c
index a53c28931f..cd15654e1e 100644
--- a/src/solaris/native/java/net/PlainDatagramSocketImpl.c
+++ b/src/solaris/native/java/net/PlainDatagramSocketImpl.c
@@ -1566,6 +1566,7 @@ jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) {
CHECK_NULL_RETURN(ni_class, NULL);
}
ni = Java_java_net_NetworkInterface_getByInetAddress0(env, ni_class, addr);
+ JNU_CHECK_EXCEPTION_RETURN(env, NULL);
if (ni) {
return ni;
}
diff --git a/src/solaris/native/sun/awt/awt_InputMethod.c b/src/solaris/native/sun/awt/awt_InputMethod.c
index 9f7aa8ad9d..30b197719e 100644
--- a/src/solaris/native/sun/awt/awt_InputMethod.c
+++ b/src/solaris/native/sun/awt/awt_InputMethod.c
@@ -1319,9 +1319,14 @@ static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data)
/* mark that XIM server was destroyed */
X11im = NULL;
JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+
+ AWT_LOCK();
/* free the old pX11IMData and set it to null. this also avoids crashing
* the jvm if the XIM server reappears */
- X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance);
+ while (x11InputMethodGRefListHead != NULL) {
+ getX11InputMethodData(env, x11InputMethodGRefListHead->inputMethodGRef);
+ }
+ AWT_UNLOCK();
}
/*
diff --git a/src/solaris/native/sun/awt/gtk3_interface.c b/src/solaris/native/sun/awt/gtk3_interface.c
index add75febce..cc259036a5 100644
--- a/src/solaris/native/sun/awt/gtk3_interface.c
+++ b/src/solaris/native/sun/awt/gtk3_interface.c
@@ -477,8 +477,7 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");
fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");
fp_gtk_image_new = dl_symbol("gtk_image_new");
- fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");
- fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");
+ fp_gtk_paned_new = dl_symbol("gtk_paned_new");
fp_gtk_scale_new = dl_symbol("gtk_scale_new");
fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");
fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");
@@ -1081,7 +1080,7 @@ static GtkWidget *gtk3_get_widget(WidgetType widget_type)
case SPLIT_PANE:
if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE]))
{
- gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();
+ gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_paned_new)(GTK_ORIENTATION_HORIZONTAL);
}
result = gtk3_widgets[_GTK_HPANED_TYPE];
break;
@@ -1314,7 +1313,7 @@ static GtkWidget *gtk3_get_widget(WidgetType widget_type)
case VSPLIT_PANE_DIVIDER:
if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE]))
{
- gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();
+ gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_paned_new)(GTK_ORIENTATION_VERTICAL);
}
result = gtk3_widgets[_GTK_VPANED_TYPE];
break;
@@ -1434,6 +1433,10 @@ static GtkStyleContext* get_style(WidgetType widget_type, const gchar *detail)
} else if (strcmp(detail, "option") == 0) {
path = createWidgetPath (NULL);
append_element(path, "radio");
+ } else if (strcmp(detail, "paned") == 0) {
+ path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
+ append_element(path, "paned");
+ append_element(path, "separator");
} else {
path = createWidgetPath (fp_gtk_style_context_get_path (widget_context));
append_element(path, detail);
@@ -1708,7 +1711,11 @@ static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type,
GtkStateFlags flags = get_gtk_flags(state_type);
if (expander_style == GTK_EXPANDER_EXPANDED) {
- flags |= GTK_STATE_FLAG_ACTIVE;
+ if (gtk3_version_3_14) {
+ flags |= GTK_STATE_FLAG_CHECKED;
+ } else {
+ flags |= GTK_STATE_FLAG_ACTIVE;
+ }
}
fp_gtk_style_context_set_state(context, flags);
@@ -1773,13 +1780,18 @@ static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
(widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) {
return;
}
- gtk3_widget = gtk3_get_widget(widget_type);
- GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
- fp_gtk_style_context_save (context);
-
- if (detail != 0) {
- transform_detail_string(detail, context);
+ GtkStyleContext* context = NULL;
+ if (widget_type == TOOL_TIP) {
+ context = get_style(widget_type, detail);
+ fp_gtk_style_context_add_class(context, "background");
+ } else {
+ gtk3_widget = gtk3_get_widget(widget_type);
+ context = fp_gtk_widget_get_style_context (gtk3_widget);
+ fp_gtk_style_context_save (context);
+ if (detail != 0) {
+ transform_detail_string(detail, context);
+ }
}
GtkStateFlags flags = get_gtk_flags(state_type);
@@ -1795,8 +1807,11 @@ static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
}
fp_gtk_render_background (context, cr, x, y, width, height);
-
- fp_gtk_style_context_restore (context);
+ if (widget_type == TOOL_TIP) {
+ disposeOrRestoreContext(context);
+ } else {
+ fp_gtk_style_context_restore (context);
+ }
}
static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type,
@@ -1820,22 +1835,30 @@ static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type,
{
gtk3_widget = gtk3_get_widget(widget_type);
- GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
-
- fp_gtk_style_context_save (context);
+ GtkStyleContext* context = get_style(widget_type, detail);
GtkStateFlags flags = get_gtk_flags(state_type);
fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT);
- if (detail != 0) {
+ if (detail != 0 && !(strcmp(detail, "paned") == 0)) {
transform_detail_string(detail, context);
fp_gtk_style_context_add_class (context, "handlebox_bin");
}
- fp_gtk_render_handle(context, cr, x, y, width, height);
- fp_gtk_render_background(context, cr, x, y, width, height);
+ if (!(strcmp(detail, "paned") == 0)) {
+ fp_gtk_render_handle(context, cr, x, y, width, height);
+ fp_gtk_render_background(context, cr, x, y, width, height);
+ } else {
+ if (orientation == GTK_ORIENTATION_VERTICAL) {
+ fp_gtk_render_handle(context, cr, x+width/2, y, 2, height);
+ fp_gtk_render_background(context, cr, x+width/2, y, 2, height);
+ } else {
+ fp_gtk_render_handle(context, cr, x, y+height/2, width, 2);
+ fp_gtk_render_background(context, cr, x, y+height/2, width, 2);
+ }
+ }
- fp_gtk_style_context_restore (context);
+ disposeOrRestoreContext(context);
}
static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type,
@@ -2356,12 +2379,19 @@ static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type,
init_containers();
- gtk3_widget = gtk3_get_widget(widget_type);
-
- GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget);
+ if (gtk3_version_3_20) {
+ if ((widget_type == TEXT_FIELD || widget_type == PASSWORD_FIELD || widget_type == SPINNER_TEXT_FIELD ||
+ widget_type == FORMATTED_TEXT_FIELD) && state_type == GTK_STATE_SELECTED && color_type == TEXT_BACKGROUND) {
+ widget_type = TEXT_AREA;
+ }
+ }
+ GtkStyleContext* context = NULL;
if (widget_type == TOOL_TIP) {
- fp_gtk_style_context_add_class(context, "tooltip");
+ context = get_style(widget_type, "tooltip");
+ } else {
+ gtk3_widget = gtk3_get_widget(widget_type);
+ context = fp_gtk_widget_get_style_context(gtk3_widget);
}
if (widget_type == CHECK_BOX_MENU_ITEM
|| widget_type == RADIO_BUTTON_MENU_ITEM) {
@@ -2379,7 +2409,9 @@ static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type,
result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 |
recode_color(color.green) << 8 | recode_color(color.blue);
-
+ if (widget_type == TOOL_TIP) {
+ disposeOrRestoreContext(context);
+ }
return result;
}
diff --git a/src/solaris/native/sun/awt/gtk3_interface.h b/src/solaris/native/sun/awt/gtk3_interface.h
index 3d6e053602..783ac8734a 100644
--- a/src/solaris/native/sun/awt/gtk3_interface.h
+++ b/src/solaris/native/sun/awt/gtk3_interface.h
@@ -163,6 +163,7 @@ typedef void GtkRange;
typedef void GtkProgressBar;
typedef void GtkProgress;
typedef void GtkWidgetPath;
+typedef void GtkPaned;
/* Some real structures */
typedef struct
@@ -502,8 +503,7 @@ static GtkWidget* (*fp_gtk_combo_box_entry_new)();
static GtkWidget* (*fp_gtk_entry_new)();
static GtkWidget* (*fp_gtk_fixed_new)();
static GtkWidget* (*fp_gtk_handle_box_new)();
-static GtkWidget* (*fp_gtk_hpaned_new)();
-static GtkWidget* (*fp_gtk_vpaned_new)();
+static GtkWidget* (*fp_gtk_paned_new)(GtkOrientation orientation);
static GtkWidget* (*fp_gtk_scale_new)(GtkOrientation orientation,
GtkAdjustment* adjustment);
static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);
diff --git a/src/solaris/native/sun/awt/multiVis.c b/src/solaris/native/sun/awt/multiVis.c
index 92a9401e52..22f539896b 100644
--- a/src/solaris/native/sun/awt/multiVis.c
+++ b/src/solaris/native/sun/awt/multiVis.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -394,77 +394,50 @@ int32_t format ;
XRectangle bbox; /* bounding box of grabbed area */
list_ptr regions;/* list of regions to read from */
{
- image_region_type *reg;
- int32_t dst_x, dst_y; /* where in pixmap to write (UL) */
- int32_t diff;
-
- XImage *reg_image,*ximage ;
- int32_t srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
- int32_t rem ;
- int32_t bytes_per_line;
- int32_t bitmap_unit;
-
- bitmap_unit = sizeof (long);
- if (format == ZPixmap)
- bytes_per_line = width*depth/8;
- else
- bytes_per_line = width/8;
-
-
- /* Find out how many more bytes are required for padding so that
- ** bytes per scan line will be multiples of bitmap_unit bits */
- if (format == ZPixmap) {
- rem = (bytes_per_line*8)%bitmap_unit;
- if (rem)
- bytes_per_line += (rem/8 + 1);
- }
+ XImage *ximage ;
+ image_region_type* reg;
+ int32_t rect;
ximage = XCreateImage(disp,fakeVis,(uint32_t) depth,format,0,NULL,
(uint32_t)width,(uint32_t)height,8,0);
- bytes_per_line = ximage->bytes_per_line;
-
- if (format == ZPixmap)
- ximage->data = malloc(height*bytes_per_line);
- else
- ximage->data = malloc(height*bytes_per_line*depth);
-
+ ximage->data = calloc(ximage->bytes_per_line*height*((format==ZPixmap)? 1 : depth), sizeof(char));
ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
for (reg = (image_region_type *) first_in_list( regions); reg;
reg = (image_region_type *) next_in_list( regions))
{
- int32_t rect;
- struct my_XRegion *vis_reg;
- vis_reg = (struct my_XRegion *)(reg->visible_region);
- for (rect = 0;
- rect < vis_reg->numRects;
- rect++)
+ struct my_XRegion *vis_reg = (struct my_XRegion *)(reg->visible_region);
+ for (rect = 0; rect < vis_reg->numRects; rect++)
{
- /** ------------------------------------------------------------------------
- Intersect bbox with visible part of region giving src rect & output
- location. Width is the min right side minus the max left side.
- Similar for height. Offset src rect so x,y are relative to
- origin of win, not the root-relative visible rect of win.
- ------------------------------------------------------------------------ **/
- srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x)
- - MAX( vis_reg->rects[rect].x1, bbox.x);
-
- srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y)
- - MAX( vis_reg->rects[rect].y1, bbox.y);
-
- diff = bbox.x - vis_reg->rects[rect].x1;
- srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
- dst_x = MAX( 0, -diff) ;
- diff = bbox.y - vis_reg->rects[rect].y1;
- srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
- dst_y = MAX( 0, -diff) ;
- reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
- (uint32_t) srcRect_width, (uint32_t) srcRect_height,AllPlanes,format) ;
- TransferImage(disp,reg_image,srcRect_width,
- srcRect_height,reg,ximage,dst_x,dst_y) ;
- XDestroyImage(reg_image);
- }
+ /** ------------------------------------------------------------------------
+ Intersect bbox with visible part of region giving src rect & output
+ location. Width is the min right side minus the max left side.
+ Similar for height. Offset src rect so x,y are relative to
+ origin of win, not the root-relative visible rect of win.
+ ------------------------------------------------------------------------ **/
+ int32_t srcRect_width = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x)
+ - MAX( vis_reg->rects[rect].x1, bbox.x);
+
+ int32_t srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y)
+ - MAX( vis_reg->rects[rect].y1, bbox.y);
+
+ int32_t diff = bbox.x - vis_reg->rects[rect].x1;
+ int32_t srcRect_x = MAX( 0, diff) + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
+ int32_t dst_x = MAX( 0, -diff) ;
+
+ diff = bbox.y - vis_reg->rects[rect].y1;
+ int32_t srcRect_y = MAX( 0, diff) + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
+ int32_t dst_y = MAX( 0, -diff) ;
+ XImage* reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
+ (uint32_t) srcRect_width, (uint32_t) srcRect_height,AllPlanes,format) ;
+
+ if (reg_image) {
+ TransferImage(disp,reg_image,srcRect_width,
+ srcRect_height,reg,ximage,dst_x,dst_y) ;
+ XDestroyImage(reg_image);
+ }
+ }
}
return ximage ;
}
diff --git a/src/solaris/native/sun/java2d/x11/X11FontScaler_md.c b/src/solaris/native/sun/java2d/x11/X11FontScaler_md.c
index 745a65f53a..2ab6f287b6 100644
--- a/src/solaris/native/sun/java2d/x11/X11FontScaler_md.c
+++ b/src/solaris/native/sun/java2d/x11/X11FontScaler_md.c
@@ -273,6 +273,7 @@ JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) {
unsigned int imageSize;
JNIEnv *env;
+
FONT_AWT_LOCK();
/* XTextExtents16(xFont, xChar, 1, &direction, &ascent, &descent, &xcs); */
XQueryTextExtents16(awt_display,xFont->fid, xChar, 1,
@@ -280,8 +281,11 @@ JNIEXPORT jlong JNICALL AWTFontGenerateImage(AWTFont pFont, AWTChar2b* xChar) {
width = xcs.rbearing - xcs.lbearing;
height = xcs.ascent+xcs.descent;
imageSize = width*height;
-
glyphInfo = (GlyphInfo*)malloc(sizeof(GlyphInfo)+imageSize);
+ if (glyphInfo == NULL) {
+ AWT_UNLOCK();
+ return (jlong)(uintptr_t)NULL;
+ }
glyphInfo->cellInfo = NULL;
glyphInfo->width = width;
glyphInfo->height = height;
diff --git a/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c b/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c
index 9453f75d3d..056d08eecc 100644
--- a/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c
+++ b/src/solaris/native/sun/nio/fs/BsdNativeDispatcher.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -203,3 +203,24 @@ Java_sun_nio_fs_BsdNativeDispatcher_endfsstat(JNIEnv* env, jclass this, jlong va
free(iter);
}
}
+
+JNIEXPORT jbyteArray JNICALL
+Java_sun_nio_fs_BsdNativeDispatcher_getmntonname0(JNIEnv *env, jclass this,
+ jlong pathAddress)
+{
+ struct statfs buf;
+ const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+ if (statfs(path, &buf) != 0) {
+ throwUnixException(env, errno);
+ }
+
+ jsize len = strlen(buf.f_mntonname);
+ jbyteArray mntonname = (*env)->NewByteArray(env, len);
+ if (mntonname != NULL) {
+ (*env)->SetByteArrayRegion(env, mntonname, 0, len,
+ (jbyte*)buf.f_mntonname);
+ }
+
+ return mntonname;
+}
diff --git a/src/solaris/native/sun/security/smartcardio/MUSCLE/COPYING b/src/solaris/native/sun/security/smartcardio/MUSCLE/COPYING
index b1743ed007..b3471ee09e 100644
--- a/src/solaris/native/sun/security/smartcardio/MUSCLE/COPYING
+++ b/src/solaris/native/sun/security/smartcardio/MUSCLE/COPYING
@@ -1,4 +1,5 @@
-Copyright (c) 1999-2003 David Corcoran <corcoran@linuxnet.com>
+Copyright (c) 1999-2003 David Corcoran <corcoran@musclecard.com>
+Copyright (c) 2001-2011 Ludovic Rousseau <ludovic.rousseau@free.fr>
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -13,9 +14,6 @@ are met:
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
-Changes to this license can be made only by the copyright author with
-explicit written consent.
-
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@@ -26,3 +24,72 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Some files are under GNU GPL v3 or any later version
+- doc/example/pcsc_demo.c
+- the files in src/spy/
+- the files in UnitaryTests/
+
+ Copyright (C) 2003-2014 Ludovic Rousseau
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+Files src/auth.c and src/auth.h are:
+ * Copyright (C) 2013 Red Hat
+ *
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * Author: Nikos Mavrogiannopoulos <nmav@redhat.com>
+
+
+Files src/simclist.c and src/simclist.h are:
+ * Copyright (c) 2007,2008,2009,2010,2011 Mij <mij@bitchx.it>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
diff --git a/src/solaris/native/sun/security/smartcardio/MUSCLE/pcsclite.h b/src/solaris/native/sun/security/smartcardio/MUSCLE/pcsclite.h
index 251d83de93..ee131c9040 100644
--- a/src/solaris/native/sun/security/smartcardio/MUSCLE/pcsclite.h
+++ b/src/solaris/native/sun/security/smartcardio/MUSCLE/pcsclite.h
@@ -1,374 +1,306 @@
/*
- * This keeps a list of defines for pcsc-lite.
- *
- * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
*
* Copyright (C) 1999-2004
- * David Corcoran <corcoran@linuxnet.com>
+ * David Corcoran <corcoran@musclecard.com>
+ * Copyright (C) 2002-2011
* Ludovic Rousseau <ludovic.rousseau@free.fr>
+ * Copyright (C) 2005
+ * Martin Paljak <martin@paljak.pri.ee>
*
- * $Id: pcsclite.h.in,v 1.47 2004/08/24 21:46:57 rousseau Exp $
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief This keeps a list of defines for pcsc-lite.
+ *
+ * Error codes from http://msdn.microsoft.com/en-us/library/aa924526.aspx
*/
#ifndef __pcsclite_h__
#define __pcsclite_h__
-#ifndef __sun_jdk
#include <wintypes.h>
-#else
-#include <sys/types.h>
-#include <inttypes.h>
-#ifdef BYTE
-#error BYTE is already defined
-#else
- typedef unsigned char BYTE;
-#endif /* End BYTE */
-
- typedef unsigned char UCHAR;
- typedef unsigned char *PUCHAR;
- typedef unsigned short USHORT;
- typedef unsigned long ULONG;
- typedef void *LPVOID;
- typedef short BOOL;
- typedef unsigned long *PULONG;
- typedef const void *LPCVOID;
- typedef unsigned long DWORD;
- typedef unsigned long *PDWORD;
- typedef unsigned short WORD;
- typedef long LONG;
- typedef long RESPONSECODE;
- typedef const char *LPCTSTR;
- typedef const BYTE *LPCBYTE;
- typedef BYTE *LPBYTE;
- typedef DWORD *LPDWORD;
- typedef char *LPTSTR;
-
-#endif
#ifdef __cplusplus
extern "C"
{
#endif
-#ifdef WIN32
-#include <winscard.h>
-#else
-typedef long SCARDCONTEXT;
+typedef LONG SCARDCONTEXT; /**< \p hContext returned by SCardEstablishContext() */
typedef SCARDCONTEXT *PSCARDCONTEXT;
typedef SCARDCONTEXT *LPSCARDCONTEXT;
-typedef long SCARDHANDLE;
+typedef LONG SCARDHANDLE; /**< \p hCard returned by SCardConnect() */
typedef SCARDHANDLE *PSCARDHANDLE;
typedef SCARDHANDLE *LPSCARDHANDLE;
-#define MAX_ATR_SIZE 33 /* Maximum ATR size */
+#define MAX_ATR_SIZE 33 /**< Maximum ATR size */
-#ifndef __APPLE__
+/* Set structure elements aligment on bytes
+ * http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html */
+#ifdef __APPLE__
+#pragma pack(1)
+#endif
typedef struct
{
- const char *szReader;
- void *pvUserData;
- unsigned long dwCurrentState;
- unsigned long dwEventState;
- unsigned long cbAtr;
- unsigned char rgbAtr[MAX_ATR_SIZE];
+ const char *szReader;
+ void *pvUserData;
+ DWORD dwCurrentState;
+ DWORD dwEventState;
+ DWORD cbAtr;
+ unsigned char rgbAtr[MAX_ATR_SIZE];
}
-SCARD_READERSTATE_A;
+SCARD_READERSTATE, *LPSCARD_READERSTATE;
-typedef struct _SCARD_IO_REQUEST
-{
- unsigned long dwProtocol; /* Protocol identifier */
- unsigned long cbPciLength; /* Protocol Control Inf Length */
-}
-SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
-
-#else // __APPLE__
-
-#pragma pack(1)
+/** Protocol Control Information (PCI) */
typedef struct
{
- const char *szReader;
- void *pvUserData;
- uint32_t dwCurrentState;
- uint32_t dwEventState;
- uint32_t cbAtr;
- unsigned char rgbAtr[MAX_ATR_SIZE];
-}
-SCARD_READERSTATE_A;
-
-typedef struct _SCARD_IO_REQUEST
-{
- uint32_t dwProtocol; /* Protocol identifier */
- uint32_t cbPciLength; /* Protocol Control Inf Length */
+ unsigned long dwProtocol; /**< Protocol identifier */
+ unsigned long cbPciLength; /**< Protocol Control Inf Length */
}
SCARD_IO_REQUEST, *PSCARD_IO_REQUEST, *LPSCARD_IO_REQUEST;
-#pragma pack()
-
-#endif // __APPLE__
-
-typedef SCARD_READERSTATE_A SCARD_READERSTATE, *PSCARD_READERSTATE_A,
- *LPSCARD_READERSTATE_A;
typedef const SCARD_IO_REQUEST *LPCSCARD_IO_REQUEST;
-extern SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci,
- g_rgSCardRawPci;
-
-#define SCARD_PCI_T0 (&g_rgSCardT0Pci)
-#define SCARD_PCI_T1 (&g_rgSCardT1Pci)
-#define SCARD_PCI_RAW (&g_rgSCardRawPci)
-
-#define SCARD_S_SUCCESS 0x00000000
-#define SCARD_E_CANCELLED 0x80100002
-#define SCARD_E_CANT_DISPOSE 0x8010000E
-#define SCARD_E_INSUFFICIENT_BUFFER 0x80100008
-#define SCARD_E_INVALID_ATR 0x80100015
-#define SCARD_E_INVALID_HANDLE 0x80100003
-#define SCARD_E_INVALID_PARAMETER 0x80100004
-#define SCARD_E_INVALID_TARGET 0x80100005
-#define SCARD_E_INVALID_VALUE 0x80100011
-#define SCARD_E_NO_MEMORY 0x80100006
-#define SCARD_F_COMM_ERROR 0x80100013
-#define SCARD_F_INTERNAL_ERROR 0x80100001
-#define SCARD_F_UNKNOWN_ERROR 0x80100014
-#define SCARD_F_WAITED_TOO_LONG 0x80100007
-#define SCARD_E_UNKNOWN_READER 0x80100009
-#define SCARD_E_TIMEOUT 0x8010000A
-#define SCARD_E_SHARING_VIOLATION 0x8010000B
-#define SCARD_E_NO_SMARTCARD 0x8010000C
-#define SCARD_E_UNKNOWN_CARD 0x8010000D
-#define SCARD_E_PROTO_MISMATCH 0x8010000F
-#define SCARD_E_NOT_READY 0x80100010
-#define SCARD_E_SYSTEM_CANCELLED 0x80100012
-#define SCARD_E_NOT_TRANSACTED 0x80100016
-#define SCARD_E_READER_UNAVAILABLE 0x80100017
-
-#define SCARD_W_UNSUPPORTED_CARD 0x80100065
-#define SCARD_W_UNRESPONSIVE_CARD 0x80100066
-#define SCARD_W_UNPOWERED_CARD 0x80100067
-#define SCARD_W_RESET_CARD 0x80100068
-#define SCARD_W_REMOVED_CARD 0x80100069
-
-#define SCARD_E_PCI_TOO_SMALL 0x80100019
-#define SCARD_E_READER_UNSUPPORTED 0x8010001A
-#define SCARD_E_DUPLICATE_READER 0x8010001B
-#define SCARD_E_CARD_UNSUPPORTED 0x8010001C
-#define SCARD_E_NO_SERVICE 0x8010001D
-#define SCARD_E_SERVICE_STOPPED 0x8010001E
-
-#define SCARD_SCOPE_USER 0x0000 /* Scope in user space */
-#define SCARD_SCOPE_TERMINAL 0x0001 /* Scope in terminal */
-#define SCARD_SCOPE_SYSTEM 0x0002 /* Scope in system */
-
-#define SCARD_PROTOCOL_UNSET 0x0000 /* protocol not set */
-#define SCARD_PROTOCOL_T0 0x0001 /* T=0 active protocol. */
-#define SCARD_PROTOCOL_T1 0x0002 /* T=1 active protocol. */
-#define SCARD_PROTOCOL_RAW 0x0004 /* Raw active protocol. */
-#define SCARD_PROTOCOL_T15 0x0008 /* T=15 protocol. */
-
-#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /* IFD determines prot. */
-
-#define SCARD_SHARE_EXCLUSIVE 0x0001 /* Exclusive mode only */
-#define SCARD_SHARE_SHARED 0x0002 /* Shared mode only */
-#define SCARD_SHARE_DIRECT 0x0003 /* Raw mode only */
-
-#define SCARD_LEAVE_CARD 0x0000 /* Do nothing on close */
-#define SCARD_RESET_CARD 0x0001 /* Reset on close */
-#define SCARD_UNPOWER_CARD 0x0002 /* Power down on close */
-#define SCARD_EJECT_CARD 0x0003 /* Eject on close */
-
-#define SCARD_UNKNOWN 0x0001 /* Unknown state */
-#define SCARD_ABSENT 0x0002 /* Card is absent */
-#define SCARD_PRESENT 0x0004 /* Card is present */
-#define SCARD_SWALLOWED 0x0008 /* Card not powered */
-#define SCARD_POWERED 0x0010 /* Card is powered */
-#define SCARD_NEGOTIABLE 0x0020 /* Ready for PTS */
-#define SCARD_SPECIFIC 0x0040 /* PTS has been set */
-
-#define SCARD_STATE_UNAWARE 0x0000 /* App wants status */
-#define SCARD_STATE_IGNORE 0x0001 /* Ignore this reader */
-#define SCARD_STATE_CHANGED 0x0002 /* State has changed */
-#define SCARD_STATE_UNKNOWN 0x0004 /* Reader unknown */
-#define SCARD_STATE_UNAVAILABLE 0x0008 /* Status unavailable */
-#define SCARD_STATE_EMPTY 0x0010 /* Card removed */
-#define SCARD_STATE_PRESENT 0x0020 /* Card inserted */
-#define SCARD_STATE_ATRMATCH 0x0040 /* ATR matches card */
-#define SCARD_STATE_EXCLUSIVE 0x0080 /* Exclusive Mode */
-#define SCARD_STATE_INUSE 0x0100 /* Shared Mode */
-#define SCARD_STATE_MUTE 0x0200 /* Unresponsive card */
-#define SCARD_STATE_UNPOWERED 0x0400 /* Unpowered card */
-
-/*
- * Tags for requesting card and reader attributes
- */
-
-#define SCARD_ATTR_VALUE(Class, Tag) ((((ULONG)(Class)) << 16) | ((ULONG)(Tag)))
-
-#define SCARD_CLASS_VENDOR_INFO 1 /* Vendor information definitions */
-#define SCARD_CLASS_COMMUNICATIONS 2 /* Communication definitions */
-#define SCARD_CLASS_PROTOCOL 3 /* Protocol definitions */
-#define SCARD_CLASS_POWER_MGMT 4 /* Power Management definitions */
-#define SCARD_CLASS_SECURITY 5 /* Security Assurance definitions */
-#define SCARD_CLASS_MECHANICAL 6 /* Mechanical characteristic definitions */
-#define SCARD_CLASS_VENDOR_DEFINED 7 /* Vendor specific definitions */
-#define SCARD_CLASS_IFD_PROTOCOL 8 /* Interface Device Protocol options */
-#define SCARD_CLASS_ICC_STATE 9 /* ICC State specific definitions */
-#define SCARD_CLASS_SYSTEM 0x7fff /* System-specific definitions */
-
-#define SCARD_ATTR_VENDOR_NAME SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0100)
-#define SCARD_ATTR_VENDOR_IFD_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0101)
-#define SCARD_ATTR_VENDOR_IFD_VERSION SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0102)
-#define SCARD_ATTR_VENDOR_IFD_SERIAL_NO SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_INFO, 0x0103)
-#define SCARD_ATTR_CHANNEL_ID SCARD_ATTR_VALUE(SCARD_CLASS_COMMUNICATIONS, 0x0110)
-#define SCARD_ATTR_ASYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0120)
-#define SCARD_ATTR_DEFAULT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0121)
-#define SCARD_ATTR_MAX_CLK SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0122)
-#define SCARD_ATTR_DEFAULT_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0123)
-#define SCARD_ATTR_MAX_DATA_RATE SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0124)
-#define SCARD_ATTR_MAX_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0125)
-#define SCARD_ATTR_SYNC_PROTOCOL_TYPES SCARD_ATTR_VALUE(SCARD_CLASS_PROTOCOL, 0x0126)
-#define SCARD_ATTR_POWER_MGMT_SUPPORT SCARD_ATTR_VALUE(SCARD_CLASS_POWER_MGMT, 0x0131)
-#define SCARD_ATTR_USER_TO_CARD_AUTH_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0140)
-#define SCARD_ATTR_USER_AUTH_INPUT_DEVICE SCARD_ATTR_VALUE(SCARD_CLASS_SECURITY, 0x0142)
-#define SCARD_ATTR_CHARACTERISTICS SCARD_ATTR_VALUE(SCARD_CLASS_MECHANICAL, 0x0150)
-
-#define SCARD_ATTR_CURRENT_PROTOCOL_TYPE SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0201)
-#define SCARD_ATTR_CURRENT_CLK SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0202)
-#define SCARD_ATTR_CURRENT_F SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0203)
-#define SCARD_ATTR_CURRENT_D SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0204)
-#define SCARD_ATTR_CURRENT_N SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0205)
-#define SCARD_ATTR_CURRENT_W SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0206)
-#define SCARD_ATTR_CURRENT_IFSC SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0207)
-#define SCARD_ATTR_CURRENT_IFSD SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0208)
-#define SCARD_ATTR_CURRENT_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x0209)
-#define SCARD_ATTR_CURRENT_CWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020a)
-#define SCARD_ATTR_CURRENT_EBC_ENCODING SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020b)
-#define SCARD_ATTR_EXTENDED_BWT SCARD_ATTR_VALUE(SCARD_CLASS_IFD_PROTOCOL, 0x020c)
-
-#define SCARD_ATTR_ICC_PRESENCE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0300)
-#define SCARD_ATTR_ICC_INTERFACE_STATUS SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0301)
-#define SCARD_ATTR_CURRENT_IO_STATE SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0302)
-#define SCARD_ATTR_ATR_STRING SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0303)
-#define SCARD_ATTR_ICC_TYPE_PER_ATR SCARD_ATTR_VALUE(SCARD_CLASS_ICC_STATE, 0x0304)
-
-#define SCARD_ATTR_ESC_RESET SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA000)
-#define SCARD_ATTR_ESC_CANCEL SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA003)
-#define SCARD_ATTR_ESC_AUTHREQUEST SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA005)
-#define SCARD_ATTR_MAXINPUT SCARD_ATTR_VALUE(SCARD_CLASS_VENDOR_DEFINED, 0xA007)
-
-#define SCARD_ATTR_DEVICE_UNIT SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0001)
-#define SCARD_ATTR_DEVICE_IN_USE SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0002)
-#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0003)
-#define SCARD_ATTR_DEVICE_SYSTEM_NAME_A SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0004)
-#define SCARD_ATTR_DEVICE_FRIENDLY_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0005)
-#define SCARD_ATTR_DEVICE_SYSTEM_NAME_W SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0006)
-#define SCARD_ATTR_SUPRESS_T1_IFS_REQUEST SCARD_ATTR_VALUE(SCARD_CLASS_SYSTEM, 0x0007)
-
-#ifdef UNICODE
-#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_W
-#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_W
-#else
-#define SCARD_ATTR_DEVICE_FRIENDLY_NAME SCARD_ATTR_DEVICE_FRIENDLY_NAME_A
-#define SCARD_ATTR_DEVICE_SYSTEM_NAME SCARD_ATTR_DEVICE_SYSTEM_NAME_A
-#endif
+extern const SCARD_IO_REQUEST g_rgSCardT0Pci, g_rgSCardT1Pci, g_rgSCardRawPci;
+/* restore default structure elements alignment */
+#ifdef __APPLE__
+#pragma pack()
#endif
-/* PC/SC Lite specific extensions */
-#define SCARD_W_INSERTED_CARD 0x8010006A
-#define SCARD_E_UNSUPPORTED_FEATURE 0x8010001F
-
-#define SCARD_SCOPE_GLOBAL 0x0003 /* Scope is global */
-
-#define SCARD_RESET 0x0001 /* Card was reset */
-#define SCARD_INSERTED 0x0002 /* Card was inserted */
-#define SCARD_REMOVED 0x0004 /* Card was removed */
-
-#define BLOCK_STATUS_RESUME 0x00FF /* Normal resume */
-#define BLOCK_STATUS_BLOCKING 0x00FA /* Function is blocking */
+#define SCARD_PCI_T0 (&g_rgSCardT0Pci) /**< protocol control information (PCI) for T=0 */
+#define SCARD_PCI_T1 (&g_rgSCardT1Pci) /**< protocol control information (PCI) for T=1 */
+#define SCARD_PCI_RAW (&g_rgSCardRawPci) /**< protocol control information (PCI) for RAW protocol */
-#define PCSCLITE_CONFIG_DIR "/etc"
+/**
+ * @defgroup ErrorCodes ErrorCodes
+ * @brief Error code documentation
+ *
+ * The error codes descriptions are from
+ * http://msdn.microsoft.com/en-us/library/aa924526.aspx
+ */
+/** @ingroup ErrorCodes */
+#define SCARD_S_SUCCESS ((LONG)0x00000000) /**< No error was encountered. */
+/** @ingroup ErrorCodes */
+#define SCARD_F_INTERNAL_ERROR ((LONG)0x80100001) /**< An internal consistency check failed. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_CANCELLED ((LONG)0x80100002) /**< The action was cancelled by an SCardCancel request. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_HANDLE ((LONG)0x80100003) /**< The supplied handle was invalid. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_PARAMETER ((LONG)0x80100004) /**< One or more of the supplied parameters could not be properly interpreted. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_TARGET ((LONG)0x80100005) /**< Registry startup information is missing or invalid. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_MEMORY ((LONG)0x80100006) /**< Not enough memory available to complete this command. */
+/** @ingroup ErrorCodes */
+#define SCARD_F_WAITED_TOO_LONG ((LONG)0x80100007) /**< An internal consistency timer has expired. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INSUFFICIENT_BUFFER ((LONG)0x80100008) /**< The data buffer to receive returned data is too small for the returned data. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_UNKNOWN_READER ((LONG)0x80100009) /**< The specified reader name is not recognized. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_TIMEOUT ((LONG)0x8010000A) /**< The user-specified timeout value has expired. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_SHARING_VIOLATION ((LONG)0x8010000B) /**< The smart card cannot be accessed because of other connections outstanding. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_SMARTCARD ((LONG)0x8010000C) /**< The operation requires a Smart Card, but no Smart Card is currently in the device. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_UNKNOWN_CARD ((LONG)0x8010000D) /**< The specified smart card name is not recognized. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_CANT_DISPOSE ((LONG)0x8010000E) /**< The system could not dispose of the media in the requested manner. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_PROTO_MISMATCH ((LONG)0x8010000F) /**< The requested protocols are incompatible with the protocol currently in use with the smart card. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NOT_READY ((LONG)0x80100010) /**< The reader or smart card is not ready to accept commands. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_VALUE ((LONG)0x80100011) /**< One or more of the supplied parameters values could not be properly interpreted. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_SYSTEM_CANCELLED ((LONG)0x80100012) /**< The action was cancelled by the system, presumably to log off or shut down. */
+/** @ingroup ErrorCodes */
+#define SCARD_F_COMM_ERROR ((LONG)0x80100013) /**< An internal communications error has been detected. */
+/** @ingroup ErrorCodes */
+#define SCARD_F_UNKNOWN_ERROR ((LONG)0x80100014) /**< An internal error has been detected, but the source is unknown. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_ATR ((LONG)0x80100015) /**< An ATR obtained from the registry is not a valid ATR string. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NOT_TRANSACTED ((LONG)0x80100016) /**< An attempt was made to end a non-existent transaction. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_READER_UNAVAILABLE ((LONG)0x80100017) /**< The specified reader is not currently available for use. */
+/** @ingroup ErrorCodes */
+#define SCARD_P_SHUTDOWN ((LONG)0x80100018) /**< The operation has been aborted to allow the server application to exit. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_PCI_TOO_SMALL ((LONG)0x80100019) /**< The PCI Receive buffer was too small. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_READER_UNSUPPORTED ((LONG)0x8010001A) /**< The reader driver does not meet minimal requirements for support. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_DUPLICATE_READER ((LONG)0x8010001B) /**< The reader driver did not produce a unique reader name. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_CARD_UNSUPPORTED ((LONG)0x8010001C) /**< The smart card does not meet minimal requirements for support. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_SERVICE ((LONG)0x8010001D) /**< The Smart card resource manager is not running. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_SERVICE_STOPPED ((LONG)0x8010001E) /**< The Smart card resource manager has shut down. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_UNEXPECTED ((LONG)0x8010001F) /**< An unexpected card error has occurred. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x8010001F) /**< This smart card does not support the requested feature. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_ICC_INSTALLATION ((LONG)0x80100020) /**< No primary provider can be found for the smart card. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_ICC_CREATEORDER ((LONG)0x80100021) /**< The requested order of object creation is not supported. */
+/** @ingroup ErrorCodes */
+/* #define SCARD_E_UNSUPPORTED_FEATURE ((LONG)0x80100022) / **< This smart card does not support the requested feature. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_DIR_NOT_FOUND ((LONG)0x80100023) /**< The identified directory does not exist in the smart card. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_FILE_NOT_FOUND ((LONG)0x80100024) /**< The identified file does not exist in the smart card. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_DIR ((LONG)0x80100025) /**< The supplied path does not represent a smart card directory. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_FILE ((LONG)0x80100026) /**< The supplied path does not represent a smart card file. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_ACCESS ((LONG)0x80100027) /**< Access is denied to this file. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_WRITE_TOO_MANY ((LONG)0x80100028) /**< The smart card does not have enough memory to store the information. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_BAD_SEEK ((LONG)0x80100029) /**< There was an error trying to set the smart card file object pointer. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_INVALID_CHV ((LONG)0x8010002A) /**< The supplied PIN is incorrect. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_UNKNOWN_RES_MNG ((LONG)0x8010002B) /**< An unrecognized error code was returned from a layered component. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_SUCH_CERTIFICATE ((LONG)0x8010002C) /**< The requested certificate does not exist. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_CERTIFICATE_UNAVAILABLE ((LONG)0x8010002D) /**< The requested certificate could not be obtained. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_READERS_AVAILABLE ((LONG)0x8010002E) /**< Cannot find a smart card reader. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_COMM_DATA_LOST ((LONG)0x8010002F) /**< A communications error with the smart card has been detected. Retry the operation. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_NO_KEY_CONTAINER ((LONG)0x80100030) /**< The requested key container does not exist on the smart card. */
+/** @ingroup ErrorCodes */
+#define SCARD_E_SERVER_TOO_BUSY ((LONG)0x80100031) /**< The Smart Card Resource Manager is too busy to complete this operation. */
+
+/** @ingroup ErrorCodes */
+#define SCARD_W_UNSUPPORTED_CARD ((LONG)0x80100065) /**< The reader cannot communicate with the card, due to ATR string configuration conflicts. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_UNRESPONSIVE_CARD ((LONG)0x80100066) /**< The smart card is not responding to a reset. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_UNPOWERED_CARD ((LONG)0x80100067) /**< Power has been removed from the smart card, so that further communication is not possible. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_RESET_CARD ((LONG)0x80100068) /**< The smart card has been reset, so any shared state information is invalid. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_REMOVED_CARD ((LONG)0x80100069) /**< The smart card has been removed, so further communication is not possible. */
+
+/** @ingroup ErrorCodes */
+#define SCARD_W_SECURITY_VIOLATION ((LONG)0x8010006A) /**< Access was denied because of a security violation. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_WRONG_CHV ((LONG)0x8010006B) /**< The card cannot be accessed because the wrong PIN was presented. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_CHV_BLOCKED ((LONG)0x8010006C) /**< The card cannot be accessed because the maximum number of PIN entry attempts has been reached. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_EOF ((LONG)0x8010006D) /**< The end of the smart card file has been reached. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_CANCELLED_BY_USER ((LONG)0x8010006E) /**< The user pressed "Cancel" on a Smart Card Selection Dialog. */
+/** @ingroup ErrorCodes */
+#define SCARD_W_CARD_NOT_AUTHENTICATED ((LONG)0x8010006F) /**< No PIN was presented to the smart card. */
+
+#define SCARD_AUTOALLOCATE (DWORD)(-1) /**< see SCardFreeMemory() */
+#define SCARD_SCOPE_USER 0x0000 /**< Scope in user space */
+#define SCARD_SCOPE_TERMINAL 0x0001 /**< Scope in terminal */
+#define SCARD_SCOPE_SYSTEM 0x0002 /**< Scope in system */
+#define SCARD_SCOPE_GLOBAL 0x0003 /**< Scope is global */
+
+#define SCARD_PROTOCOL_UNDEFINED 0x0000 /**< protocol not set */
+#define SCARD_PROTOCOL_UNSET SCARD_PROTOCOL_UNDEFINED /* backward compat */
+#define SCARD_PROTOCOL_T0 0x0001 /**< T=0 active protocol. */
+#define SCARD_PROTOCOL_T1 0x0002 /**< T=1 active protocol. */
+#define SCARD_PROTOCOL_RAW 0x0004 /**< Raw active protocol. */
+#define SCARD_PROTOCOL_T15 0x0008 /**< T=15 protocol. */
+
+#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1) /**< IFD determines prot. */
+
+#define SCARD_SHARE_EXCLUSIVE 0x0001 /**< Exclusive mode only */
+#define SCARD_SHARE_SHARED 0x0002 /**< Shared mode only */
+#define SCARD_SHARE_DIRECT 0x0003 /**< Raw mode only */
+
+#define SCARD_LEAVE_CARD 0x0000 /**< Do nothing on close */
+#define SCARD_RESET_CARD 0x0001 /**< Reset on close */
+#define SCARD_UNPOWER_CARD 0x0002 /**< Power down on close */
+#define SCARD_EJECT_CARD 0x0003 /**< Eject on close */
+
+#define SCARD_UNKNOWN 0x0001 /**< Unknown state */
+#define SCARD_ABSENT 0x0002 /**< Card is absent */
+#define SCARD_PRESENT 0x0004 /**< Card is present */
+#define SCARD_SWALLOWED 0x0008 /**< Card not powered */
+#define SCARD_POWERED 0x0010 /**< Card is powered */
+#define SCARD_NEGOTIABLE 0x0020 /**< Ready for PTS */
+#define SCARD_SPECIFIC 0x0040 /**< PTS has been set */
+
+#define SCARD_STATE_UNAWARE 0x0000 /**< App wants status */
+#define SCARD_STATE_IGNORE 0x0001 /**< Ignore this reader */
+#define SCARD_STATE_CHANGED 0x0002 /**< State has changed */
+#define SCARD_STATE_UNKNOWN 0x0004 /**< Reader unknown */
+#define SCARD_STATE_UNAVAILABLE 0x0008 /**< Status unavailable */
+#define SCARD_STATE_EMPTY 0x0010 /**< Card removed */
+#define SCARD_STATE_PRESENT 0x0020 /**< Card inserted */
+#define SCARD_STATE_ATRMATCH 0x0040 /**< ATR matches card */
+#define SCARD_STATE_EXCLUSIVE 0x0080 /**< Exclusive Mode */
+#define SCARD_STATE_INUSE 0x0100 /**< Shared Mode */
+#define SCARD_STATE_MUTE 0x0200 /**< Unresponsive card */
+#define SCARD_STATE_UNPOWERED 0x0400 /**< Unpowered card */
-#ifndef USE_IPCDIR
-#define PCSCLITE_IPC_DIR "/var/run"
-#else
-#define PCSCLITE_IPC_DIR USE_IPCDIR
+#ifndef INFINITE
+#define INFINITE 0xFFFFFFFF /**< Infinite timeout */
#endif
-#define PCSCLITE_READER_CONFIG PCSCLITE_CONFIG_DIR "/reader.conf"
-#define PCSCLITE_PUBSHM_FILE PCSCLITE_IPC_DIR "/pcscd.pub"
-#define PCSCLITE_CSOCK_NAME PCSCLITE_IPC_DIR "/pcscd.comm"
+#define PCSCLITE_VERSION_NUMBER "1.8.24" /**< Current version */
+/** Maximum readers context (a slot is count as a reader) */
+#define PCSCLITE_MAX_READERS_CONTEXTS 16
-#define PCSCLITE_SVC_IDENTITY 0x01030000 /* Service ID */
-
-#ifndef INFINITE
-#define INFINITE 0xFFFFFFFF /* Infinite timeout */
-#endif
-#define PCSCLITE_INFINITE_TIMEOUT 4320000 /* 50 day infinite t/o */
-
-#define PCSCLITE_VERSION_NUMBER "1.2.9-beta7" /* Current version */
-#define PCSCLITE_CLIENT_ATTEMPTS 120 /* Attempts to reach sv */
-#define PCSCLITE_MCLIENT_ATTEMPTS 20 /* Attempts to reach sv */
-#define PCSCLITE_STATUS_POLL_RATE 400000 /* Status polling rate */
-#define PCSCLITE_MSG_KEY_LEN 16 /* App ID key length */
-#define PCSCLITE_RW_ATTEMPTS 100 /* Attempts to rd/wrt */
-
-/* Maximum applications */
-#define PCSCLITE_MAX_APPLICATIONS 16
-/* Maximum contexts by application */
-#define PCSCLITE_MAX_APPLICATION_CONTEXTS 16
-/* Maximum of applications contexts that pcscd can accept */
-#define PCSCLITE_MAX_APPLICATIONS_CONTEXTS \
- PCSCLITE_MAX_APPLICATIONS * PCSCLITE_MAX_APPLICATION_CONTEXTS
-/* Maximum channels on a reader context */
-#define PCSCLITE_MAX_READER_CONTEXT_CHANNELS 16
-/* Maximum channels on an application context */
-#define PCSCLITE_MAX_APPLICATION_CONTEXT_CHANNELS 16
-/* Maximum readers context (a slot is count as a reader) */
-#define PCSCLITE_MAX_READERS_CONTEXTS 16
-
-/* PCSCLITE_MAX_READERS is deprecated
- * use PCSCLITE_MAX_READERS_CONTEXTS instead */
-/* extern int PCSCLITE_MAX_READERS __attribute__ ((deprecated)); */
-
-#define PCSCLITE_MAX_THREADS 16 /* Stat change threads */
-#define PCSCLITE_STATUS_WAIT 200000 /* Status Change Sleep */
-#define PCSCLITE_TRANSACTION_TIMEOUT 40 /* Transaction timeout */
-#define MAX_READERNAME 52
-#define MAX_LIBNAME 100
-#define MAX_DEVICENAME 255
+#define MAX_READERNAME 128
#ifndef SCARD_ATR_LENGTH
-#define SCARD_ATR_LENGTH MAX_ATR_SIZE /* Maximum ATR size */
+#define SCARD_ATR_LENGTH MAX_ATR_SIZE /**< Maximum ATR size */
#endif
/*
- * Enhanced messaging has been added to accommodate newer devices which have
- * more advanced capabilities, such as dedicated secure co-processors which
- * can stream and encrypt data over USB. In order to used enhanced messaging
- * you must define PCSCLITE_ENHANCED_MESSAGING in the framework(library),
- * the daemon, and your application
- */
-#undef PCSCLITE_ENHANCED_MESSAGING
-#ifndef PCSCLITE_ENHANCED_MESSAGING
-#define PCSCLITE_MAX_MESSAGE_SIZE 2048 /* Transport msg len */
-#define MAX_BUFFER_SIZE 264 /* Maximum Tx/Rx Buffer */
-#define PCSCLITE_SERVER_ATTEMPTS 5 /* Attempts to reach cl */
-#else
-/*
* The message and buffer sizes must be multiples of 16.
* The max message size must be at least large enough
- * to accommodate the transmit_struct
+ * to accomodate the transmit_struct
*/
-#define PCSCLITE_MAX_MESSAGE_SIZE (1<<17) /* enhanced (128K) msg len */
-#define MAX_BUFFER_SIZE (1<<15) /* enhanced (32K) Tx/Rx Buffer */
-#define PCSCLITE_SERVER_ATTEMPTS 200 /* To allow larger data reads/writes */
-#endif
+#define MAX_BUFFER_SIZE 264 /**< Maximum Tx/Rx Buffer for short APDU */
+#define MAX_BUFFER_SIZE_EXTENDED (4 + 3 + (1<<16) + 3 + 2) /**< enhanced (64K + APDU + Lc + Le + SW) Tx/Rx Buffer */
/*
* Gets a stringified error response
*/
-char *pcsc_stringify_error(long);
+const char *pcsc_stringify_error(const LONG);
#ifdef __cplusplus
}
diff --git a/src/solaris/native/sun/security/smartcardio/MUSCLE/winscard.h b/src/solaris/native/sun/security/smartcardio/MUSCLE/winscard.h
index 37d40bb85b..7da9d713e6 100644
--- a/src/solaris/native/sun/security/smartcardio/MUSCLE/winscard.h
+++ b/src/solaris/native/sun/security/smartcardio/MUSCLE/winscard.h
@@ -1,13 +1,38 @@
/*
- * This handles smartcard reader communications.
- *
- * MUSCLE SmartCard Development ( http://www.linuxnet.com )
+ * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
*
* Copyright (C) 1999-2003
- * David Corcoran <corcoran@linuxnet.com>
+ * David Corcoran <corcoran@musclecard.com>
+ * Copyright (C) 2002-2009
* Ludovic Rousseau <ludovic.rousseau@free.fr>
*
- * $Id: winscard.h,v 1.13 2004/08/06 12:12:19 rousseau Exp $
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief This handles smart card reader communications.
*/
#ifndef __winscard_h__
@@ -20,71 +45,79 @@ extern "C"
{
#endif
- LONG SCardEstablishContext(DWORD dwScope,
- LPCVOID pvReserved1, LPCVOID pvReserved2, LPSCARDCONTEXT phContext);
+#ifndef PCSC_API
+#define PCSC_API
+#endif
- LONG SCardReleaseContext(SCARDCONTEXT hContext);
+ PCSC_API LONG SCardEstablishContext(DWORD dwScope,
+ /*@null@*/ LPCVOID pvReserved1, /*@null@*/ LPCVOID pvReserved2,
+ /*@out@*/ LPSCARDCONTEXT phContext);
- LONG SCardSetTimeout(SCARDCONTEXT hContext, DWORD dwTimeout);
+ PCSC_API LONG SCardReleaseContext(SCARDCONTEXT hContext);
- LONG SCardConnect(SCARDCONTEXT hContext,
- LPCTSTR szReader,
- DWORD dwShareMode,
- DWORD dwPreferredProtocols,
- LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);
+ PCSC_API LONG SCardIsValidContext(SCARDCONTEXT hContext);
- LONG SCardReconnect(SCARDHANDLE hCard,
- DWORD dwShareMode,
- DWORD dwPreferredProtocols,
- DWORD dwInitialization, LPDWORD pdwActiveProtocol);
+ PCSC_API LONG SCardConnect(SCARDCONTEXT hContext,
+ LPCSTR szReader,
+ DWORD dwShareMode,
+ DWORD dwPreferredProtocols,
+ /*@out@*/ LPSCARDHANDLE phCard, /*@out@*/ LPDWORD pdwActiveProtocol);
- LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
+ PCSC_API LONG SCardReconnect(SCARDHANDLE hCard,
+ DWORD dwShareMode,
+ DWORD dwPreferredProtocols,
+ DWORD dwInitialization, /*@out@*/ LPDWORD pdwActiveProtocol);
- LONG SCardBeginTransaction(SCARDHANDLE hCard);
+ PCSC_API LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition);
- LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition);
+ PCSC_API LONG SCardBeginTransaction(SCARDHANDLE hCard);
- LONG SCardCancelTransaction(SCARDHANDLE hCard);
+ PCSC_API LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition);
- LONG SCardStatus(SCARDHANDLE hCard,
- LPTSTR mszReaderNames, LPDWORD pcchReaderLen,
- LPDWORD pdwState,
- LPDWORD pdwProtocol,
- LPBYTE pbAtr, LPDWORD pcbAtrLen);
+ PCSC_API LONG SCardStatus(SCARDHANDLE hCard,
+ /*@null@*/ /*@out@*/ LPSTR mszReaderName,
+ /*@null@*/ /*@out@*/ LPDWORD pcchReaderLen,
+ /*@null@*/ /*@out@*/ LPDWORD pdwState,
+ /*@null@*/ /*@out@*/ LPDWORD pdwProtocol,
+ /*@null@*/ /*@out@*/ LPBYTE pbAtr,
+ /*@null@*/ /*@out@*/ LPDWORD pcbAtrLen);
- LONG SCardGetStatusChange(SCARDCONTEXT hContext,
- DWORD dwTimeout,
- LPSCARD_READERSTATE_A rgReaderStates, DWORD cReaders);
+ PCSC_API LONG SCardGetStatusChange(SCARDCONTEXT hContext,
+ DWORD dwTimeout,
+ SCARD_READERSTATE *rgReaderStates, DWORD cReaders);
- LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
- LPCVOID pbSendBuffer, DWORD cbSendLength,
- LPVOID pbRecvBuffer, DWORD cbRecvLength, LPDWORD lpBytesReturned);
+ PCSC_API LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode,
+ LPCVOID pbSendBuffer, DWORD cbSendLength,
+ /*@out@*/ LPVOID pbRecvBuffer, DWORD cbRecvLength,
+ LPDWORD lpBytesReturned);
- LONG SCardTransmit(SCARDHANDLE hCard,
- LPCSCARD_IO_REQUEST pioSendPci,
- LPCBYTE pbSendBuffer, DWORD cbSendLength,
- LPSCARD_IO_REQUEST pioRecvPci,
- LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
+ PCSC_API LONG SCardTransmit(SCARDHANDLE hCard,
+ const SCARD_IO_REQUEST *pioSendPci,
+ LPCBYTE pbSendBuffer, DWORD cbSendLength,
+ /*@out@*/ SCARD_IO_REQUEST *pioRecvPci,
+ /*@out@*/ LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
- LONG SCardListReaderGroups(SCARDCONTEXT hContext,
- LPTSTR mszGroups, LPDWORD pcchGroups);
+ PCSC_API LONG SCardListReaderGroups(SCARDCONTEXT hContext,
+ /*@out@*/ LPSTR mszGroups, LPDWORD pcchGroups);
- LONG SCardListReaders(SCARDCONTEXT hContext,
- LPCTSTR mszGroups,
- LPTSTR mszReaders, LPDWORD pcchReaders);
+ PCSC_API LONG SCardListReaders(SCARDCONTEXT hContext,
+ /*@null@*/ /*@out@*/ LPCSTR mszGroups,
+ /*@null@*/ /*@out@*/ LPSTR mszReaders,
+ /*@out@*/ LPDWORD pcchReaders);
- LONG SCardCancel(SCARDCONTEXT hContext);
+ PCSC_API LONG SCardFreeMemory(SCARDCONTEXT hContext, LPCVOID pvMem);
- LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPBYTE pbAttr,
- LPDWORD pcbAttrLen);
+ PCSC_API LONG SCardCancel(SCARDCONTEXT hContext);
- LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId, LPCBYTE pbAttr,
- DWORD cbAttrLen);
+ PCSC_API LONG SCardGetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
+ /*@out@*/ LPBYTE pbAttr, LPDWORD pcbAttrLen);
- void SCardUnload(void);
+ PCSC_API LONG SCardSetAttrib(SCARDHANDLE hCard, DWORD dwAttrId,
+ LPCBYTE pbAttr, DWORD cbAttrLen);
#ifdef __cplusplus
}
#endif
#endif
+
diff --git a/src/solaris/native/sun/security/smartcardio/MUSCLE/wintypes.h b/src/solaris/native/sun/security/smartcardio/MUSCLE/wintypes.h
new file mode 100644
index 0000000000..3770de2090
--- /dev/null
+++ b/src/solaris/native/sun/security/smartcardio/MUSCLE/wintypes.h
@@ -0,0 +1,115 @@
+/*
+ * MUSCLE SmartCard Development ( https://pcsclite.apdu.fr/ )
+ *
+ * Copyright (C) 1999
+ * David Corcoran <corcoran@musclecard.com>
+ * Copyright (C) 2002-2011
+ * Ludovic Rousseau <ludovic.rousseau@free.fr>
+ *
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file
+ * @brief This keeps a list of Windows(R) types.
+ */
+
+#ifndef __wintypes_h__
+#define __wintypes_h__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef __APPLE__
+
+#include <stdint.h>
+
+#ifndef BYTE
+ typedef uint8_t BYTE;
+#endif
+ typedef uint8_t UCHAR;
+ typedef UCHAR *PUCHAR;
+ typedef uint16_t USHORT;
+
+#ifndef __COREFOUNDATION_CFPLUGINCOM__
+ typedef uint32_t ULONG;
+ typedef void *LPVOID;
+ typedef int16_t BOOL;
+#endif
+
+ typedef ULONG *PULONG;
+ typedef const void *LPCVOID;
+ typedef uint32_t DWORD;
+ typedef DWORD *PDWORD;
+ typedef uint16_t WORD;
+ typedef int32_t LONG;
+ typedef const char *LPCSTR;
+ typedef const BYTE *LPCBYTE;
+ typedef BYTE *LPBYTE;
+ typedef DWORD *LPDWORD;
+ typedef char *LPSTR;
+
+#else
+
+#ifndef BYTE
+ typedef unsigned char BYTE;
+#endif
+ typedef unsigned char UCHAR;
+ typedef UCHAR *PUCHAR;
+ typedef unsigned short USHORT;
+
+#ifndef __COREFOUNDATION_CFPLUGINCOM__
+ typedef unsigned long ULONG;
+ typedef void *LPVOID;
+#endif
+
+ typedef const void *LPCVOID;
+ typedef unsigned long DWORD;
+ typedef DWORD *PDWORD;
+ typedef long LONG;
+ typedef const char *LPCSTR;
+ typedef const BYTE *LPCBYTE;
+ typedef BYTE *LPBYTE;
+ typedef DWORD *LPDWORD;
+ typedef char *LPSTR;
+
+ /* these types were deprecated but still used by old drivers and
+ * applications. So just declare and use them. */
+ typedef LPSTR LPTSTR;
+ typedef LPCSTR LPCTSTR;
+
+ /* types unused by pcsc-lite */
+ typedef short BOOL;
+ typedef unsigned short WORD;
+ typedef ULONG *PULONG;
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/solaris/native/sun/security/smartcardio/pcsc_md.h b/src/solaris/native/sun/security/smartcardio/pcsc_md.h
index 4a8137595a..db93c9cd93 100644
--- a/src/solaris/native/sun/security/smartcardio/pcsc_md.h
+++ b/src/solaris/native/sun/security/smartcardio/pcsc_md.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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,48 +23,49 @@
* questions.
*/
-typedef LONG (*FPTR_SCardEstablishContext)(ULONG dwScope,
- const void *pvReserved1,
- const void *pvReserved2,
- LONG *phContext);
-
-typedef LONG (*FPTR_SCardConnect)(LONG hContext,
- const char *szReader,
- ULONG dwShareMode,
- ULONG dwPreferredProtocols,
- LONG *phCard, ULONG *pdwActiveProtocol);
-
-typedef LONG (*FPTR_SCardDisconnect)(LONG hCard, ULONG dwDisposition);
-
-typedef LONG (*FPTR_SCardStatus)(LONG hCard,
- char *mszReaderNames,
- ULONG *pcchReaderLen,
- ULONG *pdwState,
- ULONG *pdwProtocol,
- unsigned char *pbAtr, ULONG *pcbAtrLen);
-
-typedef LONG (*FPTR_SCardGetStatusChange)(LONG hContext,
- ULONG dwTimeout,
- LPSCARD_READERSTATE_A rgReaderStates, ULONG cReaders);
-
-typedef LONG (*FPTR_SCardTransmit)(LONG hCard,
- LPCSCARD_IO_REQUEST pioSendPci,
- const unsigned char *pbSendBuffer,
- ULONG cbSendLength,
- LPSCARD_IO_REQUEST pioRecvPci,
- unsigned char *pbRecvBuffer, ULONG *pcbRecvLength);
-
-typedef LONG (*FPTR_SCardListReaders)(LONG hContext,
- const char *mszGroups,
- char *mszReaders, ULONG *pcchReaders);
-
-typedef LONG (*FPTR_SCardBeginTransaction)(LONG hCard);
-
-typedef LONG (*FPTR_SCardEndTransaction)(LONG hCard, ULONG dwDisposition);
-
-typedef LONG (*FPTR_SCardControl)(LONG hCard, ULONG dwControlCode,
- const void* pbSendBuffer, ULONG cbSendLength, const void* pbRecvBuffer,
- ULONG pcbRecvLength, ULONG *lpBytesReturned);
+typedef LONG (*FPTR_SCardEstablishContext)(DWORD dwScope,
+ LPCVOID pvReserved1,
+ LPCVOID pvReserved2,
+ LPSCARDCONTEXT phContext);
+
+typedef LONG (*FPTR_SCardConnect)(SCARDCONTEXT hContext,
+ LPCSTR szReader,
+ DWORD dwShareMode,
+ DWORD dwPreferredProtocols,
+ LPSCARDHANDLE phCard, LPDWORD pdwActiveProtocol);
+
+typedef LONG (*FPTR_SCardDisconnect)(SCARDHANDLE hCard, DWORD dwDisposition);
+
+typedef LONG (*FPTR_SCardStatus)(SCARDHANDLE hCard,
+ LPSTR mszReaderNames,
+ LPDWORD pcchReaderLen,
+ LPDWORD pdwState,
+ LPDWORD pdwProtocol,
+ LPBYTE pbAtr, LPDWORD pcbAtrLen);
+
+typedef LONG (*FPTR_SCardGetStatusChange)(SCARDCONTEXT hContext,
+ DWORD dwTimeout,
+ SCARD_READERSTATE *rgReaderStates, DWORD cReaders);
+
+typedef LONG (*FPTR_SCardTransmit)(SCARDHANDLE hCard,
+ const SCARD_IO_REQUEST *pioSendPci,
+ LPCBYTE pbSendBuffer,
+ DWORD cbSendLength,
+ SCARD_IO_REQUEST *pioRecvPci,
+ LPBYTE pbRecvBuffer, LPDWORD pcbRecvLength);
+
+typedef LONG (*FPTR_SCardListReaders)(SCARDCONTEXT hContext,
+ LPCSTR mszGroups,
+ LPSTR mszReaders, LPDWORD pcchReaders);
+
+typedef LONG (*FPTR_SCardBeginTransaction)(SCARDHANDLE hCard);
+
+typedef LONG (*FPTR_SCardEndTransaction)(SCARDHANDLE hCard,
+ DWORD dwDisposition);
+
+typedef LONG (*FPTR_SCardControl)(SCARDHANDLE hCard, DWORD dwControlCode,
+ LPCVOID pbSendBuffer, DWORD cbSendLength, LPVOID pbRecvBuffer,
+ DWORD pcbRecvLength, LPDWORD lpBytesReturned);
#define CALL_SCardEstablishContext(dwScope, pvReserved1, pvReserved2, phContext) \
((scardEstablishContext)(dwScope, pvReserved1, pvReserved2, phContext))
diff --git a/src/windows/classes/java/lang/ProcessImpl.java b/src/windows/classes/java/lang/ProcessImpl.java
index 21b43866a7..37c3237547 100644
--- a/src/windows/classes/java/lang/ProcessImpl.java
+++ b/src/windows/classes/java/lang/ProcessImpl.java
@@ -38,9 +38,11 @@ import java.lang.ProcessBuilder.Redirect;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
+import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import sun.security.action.GetPropertyAction;
/* This class is for the exclusive use of ProcessBuilder.start() to
* create new processes.
@@ -172,12 +174,15 @@ final class ProcessImpl extends Process {
private static final int VERIFICATION_CMD_BAT = 0;
private static final int VERIFICATION_WIN32 = 1;
- private static final int VERIFICATION_LEGACY = 2;
+ private static final int VERIFICATION_WIN32_SAFE = 2; // inside quotes not allowed
+ private static final int VERIFICATION_LEGACY = 3;
+ // See Command shell overview for documentation of special characters.
+ // https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-xp/bb490954(v=technet.10)
private static final char ESCAPE_VERIFICATION[][] = {
// We guarantee the only command file execution for implicit [cmd.exe] run.
// http://technet.microsoft.com/en-us/library/bb490954.aspx
{' ', '\t', '<', '>', '&', '|', '^'},
-
+ {' ', '\t', '<', '>'},
{' ', '\t', '<', '>'},
{' ', '\t'}
};
@@ -194,8 +199,25 @@ final class ProcessImpl extends Process {
cmdbuf.append(' ');
String s = cmd[i];
if (needsEscaping(verificationType, s)) {
- cmdbuf.append('"').append(s);
+ cmdbuf.append('"');
+ if (verificationType == VERIFICATION_WIN32_SAFE) {
+ // Insert the argument, adding '\' to quote any interior quotes
+ int length = s.length();
+ for (int j = 0; j < length; j++) {
+ char c = s.charAt(j);
+ if (c == DOUBLEQUOTE) {
+ int count = countLeadingBackslash(verificationType, s, j);
+ while (count-- > 0) {
+ cmdbuf.append(BACKSLASH); // double the number of backslashes
+ }
+ cmdbuf.append(BACKSLASH); // backslash to quote the quote
+ }
+ cmdbuf.append(c);
+ }
+ } else {
+ cmdbuf.append(s);
+ }
// The code protects the [java.exe] and console command line
// parser, that interprets the [\"] combination as an escape
// sequence for the ["] char.
@@ -208,8 +230,9 @@ final class ProcessImpl extends Process {
// command line parser. The case of the [""] tail escape
// sequence could not be realized due to the argument validation
// procedure.
- if ((verificationType != VERIFICATION_CMD_BAT) && s.endsWith("\\")) {
- cmdbuf.append('\\');
+ int count = countLeadingBackslash(verificationType, s, s.length());
+ while (count-- > 0) {
+ cmdbuf.append(BACKSLASH); // double the number of backslashes
}
cmdbuf.append('"');
} else {
@@ -219,26 +242,16 @@ final class ProcessImpl extends Process {
return cmdbuf.toString();
}
- private static boolean isQuoted(boolean noQuotesInside, String arg,
- String errorMessage) {
- int lastPos = arg.length() - 1;
- if (lastPos >=1 && arg.charAt(0) == '"' && arg.charAt(lastPos) == '"') {
- // The argument has already been quoted.
- if (noQuotesInside) {
- if (arg.indexOf('"', 1) != lastPos) {
- // There is ["] inside.
- throw new IllegalArgumentException(errorMessage);
- }
- }
- return true;
- }
- if (noQuotesInside) {
- if (arg.indexOf('"') >= 0) {
- // There is ["] inside.
- throw new IllegalArgumentException(errorMessage);
- }
- }
- return false;
+ /**
+ * Return the argument without quotes (1st and last) if present, else the arg.
+ * @param str a string
+ * @return the string without 1st and last quotes
+ */
+ private static String unQuote(String str) {
+ int len = str.length();
+ return (len >= 2 && str.charAt(0) == DOUBLEQUOTE && str.charAt(len - 1) == DOUBLEQUOTE)
+ ? str.substring(1, len - 1)
+ : str;
}
private static boolean needsEscaping(int verificationType, String arg) {
@@ -249,9 +262,26 @@ final class ProcessImpl extends Process {
// For [.exe] or [.com] file the unpaired/internal ["]
// in the argument is not a problem.
- boolean argIsQuoted = isQuoted(
- (verificationType == VERIFICATION_CMD_BAT),
- arg, "Argument has embedded quote, use the explicit CMD.EXE call.");
+ String unquotedArg = unQuote(arg);
+ boolean argIsQuoted = !arg.equals(unquotedArg);
+ boolean embeddedQuote = unquotedArg.indexOf(DOUBLEQUOTE) >= 0;
+
+ switch (verificationType) {
+ case VERIFICATION_CMD_BAT:
+ if (embeddedQuote) {
+ throw new IllegalArgumentException("Argument has embedded quote, " +
+ "use the explicit CMD.EXE call.");
+ }
+ break; // break determine whether to quote
+ case VERIFICATION_WIN32_SAFE:
+ if (argIsQuoted && embeddedQuote) {
+ throw new IllegalArgumentException("Malformed argument has embedded quote: "
+ + unquotedArg);
+ }
+ break;
+ default:
+ break;
+ }
if (!argIsQuoted) {
char testEscape[] = ESCAPE_VERIFICATION[verificationType];
@@ -267,13 +297,13 @@ final class ProcessImpl extends Process {
private static String getExecutablePath(String path)
throws IOException
{
- boolean pathIsQuoted = isQuoted(true, path,
- "Executable name has embedded quote, split the arguments");
-
+ String name = unQuote(path);
+ if (name.indexOf(DOUBLEQUOTE) >= 0) {
+ throw new IllegalArgumentException("Executable name has embedded quote, " +
+ "split the arguments: " + name);
+ }
// Win32 CreateProcess requires path to be normalized
- File fileToRun = new File(pathIsQuoted
- ? path.substring(1, path.length() - 1)
- : path);
+ File fileToRun = new File(name);
// From the [CreateProcess] function documentation:
//
@@ -288,13 +318,26 @@ final class ProcessImpl extends Process {
// sequence:..."
//
// In practice ANY non-existent path is extended by [.exe] extension
- // in the [CreateProcess] funcion with the only exception:
+ // in the [CreateProcess] function with the only exception:
// the path ends by (.)
return fileToRun.getPath();
}
+ /**
+ * An executable is any program that is an EXE or does not have an extension
+ * and the Windows createProcess will be looking for .exe.
+ * The comparison is case insensitive based on the name.
+ * @param executablePath the executable file
+ * @return true if the path ends in .exe or does not have an extension.
+ */
+ private boolean isExe(String executablePath) {
+ File file = new File(executablePath);
+ String upName = file.getName().toUpperCase(Locale.ROOT);
+ return (upName.endsWith(".EXE") || upName.indexOf('.') < 0);
+ }
+ // Old version that can be bypassed
private boolean isShellFile(String executablePath) {
String upPath = executablePath.toUpperCase();
return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT"));
@@ -305,6 +348,21 @@ final class ProcessImpl extends Process {
return argbuf.append('"').append(arg).append('"').toString();
}
+ // Count backslashes before start index of string.
+ // .bat files don't include backslashes as part of the quote
+ private static int countLeadingBackslash(int verificationType,
+ CharSequence input, int start) {
+ if (verificationType == VERIFICATION_CMD_BAT)
+ return 0;
+ int j;
+ for (j = start - 1; j >= 0 && input.charAt(j) == BACKSLASH; j--) {
+ // just scanning backwards
+ }
+ return (start - 1) - j; // number of BACKSLASHES
+ }
+
+ private static final char DOUBLEQUOTE = '\"';
+ private static final char BACKSLASH = '\\';
private long handle = 0;
private OutputStream stdin_stream;
@@ -319,15 +377,14 @@ final class ProcessImpl extends Process {
throws IOException
{
String cmdstr;
- SecurityManager security = System.getSecurityManager();
- boolean allowAmbiguousCommands = false;
- if (security == null) {
- allowAmbiguousCommands = true;
- String value = System.getProperty("jdk.lang.Process.allowAmbiguousCommands");
- if (value != null)
- allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
- }
- if (allowAmbiguousCommands) {
+ final SecurityManager security = System.getSecurityManager();
+ String propertyValue = GetPropertyAction.
+ privilegedGetProperty("jdk.lang.Process.allowAmbiguousCommands");
+ final String value = propertyValue != null ? propertyValue
+ : (security == null ? "true" : "false");
+ final boolean allowAmbiguousCommands = !"false".equalsIgnoreCase(value);
+
+ if (allowAmbiguousCommands && security == null) {
// Legacy mode.
// Normalize path if possible.
@@ -374,11 +431,12 @@ final class ProcessImpl extends Process {
// Quotation protects from interpretation of the [path] argument as
// start of longer path with spaces. Quotation has no influence to
// [.exe] extension heuristic.
+ boolean isShell = allowAmbiguousCommands ? isShellFile(executablePath)
+ : !isExe(executablePath);
cmdstr = createCommandLine(
- // We need the extended verification procedure for CMD files.
- isShellFile(executablePath)
- ? VERIFICATION_CMD_BAT
- : VERIFICATION_WIN32,
+ // We need the extended verification procedures
+ isShell ? VERIFICATION_CMD_BAT
+ : (allowAmbiguousCommands ? VERIFICATION_WIN32 : VERIFICATION_WIN32_SAFE),
quoteString(executablePath),
cmd);
}
diff --git a/src/windows/classes/sun/awt/windows/WPrinterJob.java b/src/windows/classes/sun/awt/windows/WPrinterJob.java
index 3b7c5f3c98..e32bd50999 100644
--- a/src/windows/classes/sun/awt/windows/WPrinterJob.java
+++ b/src/windows/classes/sun/awt/windows/WPrinterJob.java
@@ -93,7 +93,7 @@ import sun.print.SunAlternateMedia;
import sun.print.SunPageSelection;
import sun.print.Win32MediaTray;
import sun.print.Win32PrintService;
-import sun.print.Win32PrintServiceLookup;
+import sun.print.PrintServiceLookupProvider;
import sun.print.ServiceDialog;
import sun.print.DialogOwner;
@@ -454,7 +454,7 @@ public final class WPrinterJob extends RasterPrinterJob
// native printer is different !
// we update the current PrintService
try {
- setPrintService(Win32PrintServiceLookup.
+ setPrintService(PrintServiceLookupProvider.
getWin32PrintLUS().
getPrintServiceByName(printerName));
} catch (PrinterException e) {
@@ -628,7 +628,7 @@ public final class WPrinterJob extends RasterPrinterJob
String printerName = getNativePrintService();
if (printerName != null) {
- myService = Win32PrintServiceLookup.getWin32PrintLUS().
+ myService = PrintServiceLookupProvider.getWin32PrintLUS().
getPrintServiceByName(printerName);
// no need to call setNativePrintService as this name is
// currently set in native
diff --git a/src/windows/classes/sun/net/www/protocol/file/Handler.java b/src/windows/classes/sun/net/www/protocol/file/Handler.java
index 8a5531268d..7a331a0c5e 100644
--- a/src/windows/classes/sun/net/www/protocol/file/Handler.java
+++ b/src/windows/classes/sun/net/www/protocol/file/Handler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, 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
@@ -95,7 +95,7 @@ public class Handler extends URLStreamHandler {
path = "\\\\" + host + path;
File f = new File(path);
if (f.exists()) {
- return createFileURLConnection(url, f);
+ return new UNCFileURLConnection(url, f, path);
}
/*
diff --git a/src/windows/classes/sun/net/www/protocol/file/UNCFileURLConnection.java b/src/windows/classes/sun/net/www/protocol/file/UNCFileURLConnection.java
new file mode 100644
index 0000000000..c36b84aa4d
--- /dev/null
+++ b/src/windows/classes/sun/net/www/protocol/file/UNCFileURLConnection.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.www.protocol.file;
+
+import java.io.File;
+import java.io.FilePermission;
+import java.net.URL;
+import java.security.Permission;
+
+final class UNCFileURLConnection extends FileURLConnection {
+
+ private final String effectivePath;
+ private volatile Permission permission;
+
+ UNCFileURLConnection(URL u, File file, String effectivePath) {
+ super(u, file);
+ this.effectivePath = effectivePath;
+ }
+
+ @Override
+ public Permission getPermission() {
+ Permission perm = permission;
+ if (perm == null) {
+ permission = perm = new FilePermission(effectivePath, "read");
+ }
+ return perm;
+ }
+}
+
diff --git a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
index 1b2c874e72..535adc0591 100644
--- a/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
+++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2019, 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
@@ -194,7 +194,17 @@ public class NTLMAuthentication extends AuthenticationInfo {
}
}
- static native boolean isTrustedSite(String url);
+ private static final boolean isTrustedSiteAvailable = isTrustedSiteAvailable();
+
+ private static native boolean isTrustedSiteAvailable();
+
+ private static boolean isTrustedSite(String url) {
+ if (isTrustedSiteAvailable)
+ return isTrustedSite0(url);
+ return false;
+ }
+
+ private static native boolean isTrustedSite0(String url);
/**
* Not supported. Must use the setHeaders() method
diff --git a/src/windows/classes/sun/print/Win32PrintServiceLookup.java b/src/windows/classes/sun/print/PrintServiceLookupProvider.java
index 06d4b0840d..9e7a329913 100644
--- a/src/windows/classes/sun/print/Win32PrintServiceLookup.java
+++ b/src/windows/classes/sun/print/PrintServiceLookupProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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,14 +25,10 @@
package sun.print;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.util.ArrayList;
import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import javax.print.DocFlavor;
import javax.print.MultiDocPrintService;
import javax.print.PrintService;
@@ -47,14 +43,38 @@ import javax.print.attribute.PrintServiceAttribute;
import javax.print.attribute.PrintServiceAttributeSet;
import javax.print.attribute.standard.PrinterName;
-public class Win32PrintServiceLookup extends PrintServiceLookup {
+public class PrintServiceLookupProvider extends PrintServiceLookup {
private String defaultPrinter;
private PrintService defaultPrintService;
private String[] printers; /* excludes the default printer */
private PrintService[] printServices; /* includes the default printer */
+ private static final int DEFAULT_REFRESH_TIME = 240; // 4 minutes
+ private static final int MINIMUM_REFRESH_TIME = 120; // 2 minutes
+ private static final boolean pollServices;
+ private static final int refreshTime;
+
static {
+ /* The system property "sun.java2d.print.polling"
+ * can be used to force the printing code to poll or not poll
+ * for PrintServices.
+ */
+ String pollStr = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));
+ pollServices = !("false".equalsIgnoreCase(pollStr));
+
+ /* The system property "sun.java2d.print.minRefreshTime"
+ * can be used to specify minimum refresh time (in seconds)
+ * for polling PrintServices. The default is 240.
+ */
+ String refreshTimeStr = java.security.AccessController.doPrivileged(
+ new sun.security.action.GetPropertyAction(
+ "sun.java2d.print.minRefreshTime"));
+ refreshTime = (refreshTimeStr != null)
+ ? getRefreshTime(refreshTimeStr)
+ : DEFAULT_REFRESH_TIME;
+
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
@@ -64,16 +84,27 @@ public class Win32PrintServiceLookup extends PrintServiceLookup {
});
}
+ private static int getRefreshTime(final String refreshTimeStr) {
+ try {
+ int minRefreshTime = Integer.parseInt(refreshTimeStr);
+ return (minRefreshTime < MINIMUM_REFRESH_TIME)
+ ? MINIMUM_REFRESH_TIME
+ : minRefreshTime;
+ } catch (NumberFormatException e) {
+ return DEFAULT_REFRESH_TIME;
+ }
+ }
+
/* The singleton win32 print lookup service.
* Code that is aware of this field and wants to use it must first
* see if its null, and if so instantiate it by calling a method such as
* javax.print.PrintServiceLookup.defaultPrintService() so that the
* same instance is stored there.
*/
- private static Win32PrintServiceLookup win32PrintLUS;
+ private static PrintServiceLookupProvider win32PrintLUS;
/* Think carefully before calling this. Preferably don't call it. */
- public static Win32PrintServiceLookup getWin32PrintLUS() {
+ public static PrintServiceLookupProvider getWin32PrintLUS() {
if (win32PrintLUS == null) {
/* This call is internally synchronized.
* When it returns an instance of this class will have
@@ -84,7 +115,7 @@ public class Win32PrintServiceLookup extends PrintServiceLookup {
return win32PrintLUS;
}
- public Win32PrintServiceLookup() {
+ public PrintServiceLookupProvider() {
if (win32PrintLUS == null) {
win32PrintLUS = this;
@@ -96,10 +127,17 @@ public class Win32PrintServiceLookup extends PrintServiceLookup {
if (osName != null && osName.startsWith("Windows 98")) {
return;
}
- // start the printer listener thread
- PrinterChangeListener thr = new PrinterChangeListener();
+ // start the local printer listener thread
+ Thread thr = new PrinterChangeListener();
thr.setDaemon(true);
thr.start();
+
+ if (pollServices) {
+ // start the remote printer listener thread
+ Thread remThr = new RemotePrinterChangeListener();
+ remThr.setDaemon(true);
+ remThr.start();
+ }
} /* else condition ought to never happen! */
}
@@ -340,9 +378,71 @@ public class Win32PrintServiceLookup extends PrintServiceLookup {
}
}
+ /* Windows provides *PrinterChangeNotification* functions that provides
+ information about printer status changes of the local printers but not
+ network printers.
+ Alternatively, Windows provides a way through which one can get the
+ network printer status changes by using WMI, RegistryKeyChange combination,
+ which is a slightly complex mechanism.
+ The Windows WMI offers an async and sync method to read through registry
+ via the WQL query. The async method is considered dangerous as it leaves
+ open a channel until we close it. But the async method has the advantage of
+ being notified of a change in registry by calling callback without polling for it.
+ The sync method uses the polling mechanism to notify.
+ RegistryValueChange cannot be used in combination with WMI to get registry
+ value change notification because of an error that may be generated because the
+ scope of the query would be too big to handle(at times).
+ Hence an alternative mechanism is chosen via the EnumPrinters by polling for the
+ count of printer status changes(add\remove) and based on it update the printers
+ list.
+ */
+ class RemotePrinterChangeListener extends Thread implements Comparator<String>{
+ RemotePrinterChangeListener() {
+ }
+
+ @Override
+ public int compare(String o1, String o2) {
+ return ((o1 == null)
+ ? ((o2 == null) ? 0 : 1)
+ : ((o2 == null) ? -1 : o1.compareTo(o2)));
+ }
+
+ @Override
+ public void run() {
+ // Init the list of remote printers
+ String[] prevRemotePrinters = getRemotePrintersNames();
+ if (prevRemotePrinters != null) {
+ Arrays.sort(prevRemotePrinters, this);
+ }
+
+ while (true) {
+ try {
+ Thread.sleep(refreshTime * 1000);
+ } catch (InterruptedException e) {
+ break;
+ }
+
+ String[] currentRemotePrinters = getRemotePrintersNames();
+ if (currentRemotePrinters != null) {
+ Arrays.sort(currentRemotePrinters, this);
+ }
+ if (!Arrays.equals(prevRemotePrinters, currentRemotePrinters)) {
+ // The list of remote printers got updated,
+ // so update the cached list printers which
+ // includes both local and network printers
+ refreshServices();
+
+ // store the current data for next comparison
+ prevRemotePrinters = currentRemotePrinters;
+ }
+ }
+ }
+ }
+
private native String getDefaultPrinterName();
private native String[] getAllPrinterNames();
private native long notifyFirstPrinterChange(String printer);
private native void notifyClosePrinterChange(long chgObj);
private native int notifyPrinterChange(long chgObj);
+ private native String[] getRemotePrintersNames();
}
diff --git a/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup b/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup
deleted file mode 100644
index b3844117e0..0000000000
--- a/src/windows/classes/sun/print/services/javax.print.PrintServiceLookup
+++ /dev/null
@@ -1,2 +0,0 @@
-# Provider for Java Print Service
-sun.print.Win32PrintServiceLookup
diff --git a/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory b/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory
deleted file mode 100644
index 6ab63408bc..0000000000
--- a/src/windows/classes/sun/print/services/javax.print.StreamPrintServiceFactory
+++ /dev/null
@@ -1,2 +0,0 @@
-# Providers for Java 2D/JPS Stream print services.
-sun.print.PSStreamPrinterFactory
diff --git a/src/windows/classes/sun/security/krb5/internal/tools/Klist.java b/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
index ca5a473cba..37f59adae8 100644
--- a/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
+++ b/src/windows/classes/sun/security/krb5/internal/tools/Klist.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,8 @@
package sun.security.krb5.internal.tools;
import java.net.InetAddress;
+import java.util.List;
+
import sun.security.krb5.*;
import sun.security.krb5.internal.*;
import sun.security.krb5.internal.ccache.*;
@@ -241,6 +243,8 @@ public class Klist {
String endtime;
String renewTill;
String servicePrincipal;
+ PrincipalName servicePrincipal2;
+ String clientPrincipal;
if (creds[i].getStartTime() != null) {
starttime = format(creds[i].getStartTime());
} else {
@@ -252,6 +256,18 @@ public class Klist {
System.out.println("[" + (i + 1) + "] " +
" Service Principal: " +
servicePrincipal);
+ servicePrincipal2 =
+ creds[i].getServicePrincipal2();
+ if (servicePrincipal2 != null) {
+ System.out.println(" Second Service: "
+ + servicePrincipal2);
+ }
+ clientPrincipal =
+ creds[i].getClientPrincipal().toString();
+ if (!clientPrincipal.equals(defaultPrincipal)) {
+ System.out.println(" Client Principal: " +
+ clientPrincipal);
+ }
System.out.println(" Valid starting: " + starttime);
System.out.println(" Expires: " + endtime);
if (creds[i].getRenewTill() != null) {
@@ -262,8 +278,15 @@ public class Klist {
if (options[0] == 'e') {
String eskey = EType.toString(creds[i].getEType());
String etkt = EType.toString(creds[i].getTktEType());
- System.out.println(" EType (skey, tkt): "
- + eskey + ", " + etkt);
+ if (creds[i].getTktEType2() == 0) {
+ System.out.println(" EType (skey, tkt): "
+ + eskey + ", " + etkt);
+ } else {
+ String etkt2 = EType.toString(creds[i].getTktEType2());
+ System.out.println(" EType (skey, tkts): "
+ + eskey + ", " + etkt
+ + ", " + etkt2);
+ }
}
if (options[1] == 'f') {
System.out.println(" Flags: " +
@@ -302,6 +325,15 @@ public class Klist {
} else {
System.out.println("\nNo entries found.");
}
+
+ List<CredentialsCache.ConfigEntry> configEntries
+ = cache.getConfigEntries();
+ if (configEntries != null && !configEntries.isEmpty()) {
+ System.out.println("\nConfig entries:");
+ for (CredentialsCache.ConfigEntry e : configEntries) {
+ System.out.println(" " + e);
+ }
+ }
}
void displayMessage(String target) {
diff --git a/src/windows/native/sun/java2d/d3d/D3DContext.cpp b/src/windows/native/sun/java2d/d3d/D3DContext.cpp
index 8722d549ba..9d62f4ce37 100644
--- a/src/windows/native/sun/java2d/d3d/D3DContext.cpp
+++ b/src/windows/native/sun/java2d/d3d/D3DContext.cpp
@@ -1156,7 +1156,9 @@ D3DContext::UploadTileToTexture(D3DResource *pTextureRes, void *pixels,
{
#ifndef PtrAddBytes
#define PtrAddBytes(p, b) ((void *) (((intptr_t) (p)) + (b)))
-#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, (y)*(yinc) + (x)*(xinc))
+#define PtrCoord(p, x, xinc, y, yinc) PtrAddBytes(p, \
+ ((ptrdiff_t)(y))*(yinc) + \
+ ((ptrdiff_t)(x))*(xinc))
#endif // PtrAddBytes
HRESULT res = S_OK;
diff --git a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c
index db771d8cc2..65f2cabda4 100644
--- a/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c
+++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthentication.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
@@ -26,11 +26,34 @@
#include <jni.h>
#include <windows.h>
#include "jni_util.h"
+#include "jdk_util.h"
#include <urlmon.h>
-JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite(JNIEnv *env, jclass clazz, jstring url )
+typedef HRESULT (WINAPI *CoInternetCreateSecurityManagerType)
+ (IServiceProvider*,IInternetSecurityManager**,DWORD);
+
+static CoInternetCreateSecurityManagerType fn_CoInternetCreateSecurityManager;
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSiteAvailable
+ (JNIEnv *env, jclass clazz)
{
+ HMODULE libUrlmon = JDK_LoadSystemLibrary("urlmon.dll");
+ if (libUrlmon != NULL) {
+ fn_CoInternetCreateSecurityManager = (CoInternetCreateSecurityManagerType)
+ GetProcAddress(libUrlmon, "CoInternetCreateSecurityManager");
+ if (fn_CoInternetCreateSecurityManager != NULL) {
+ return JNI_TRUE;
+ }
+ }
+ return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_net_www_protocol_http_ntlm_NTLMAuthentication_isTrustedSite0
+ (JNIEnv *env, jclass clazz, jstring url)
+{
HRESULT hr;
DWORD dwZone;
DWORD pPolicy = 0;
@@ -38,8 +61,11 @@ JNIEXPORT jboolean JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthenticatio
jboolean ret;
LPCWSTR bstrURL;
+ if (fn_CoInternetCreateSecurityManager == NULL)
+ return JNI_FALSE;
+
// Create IInternetSecurityManager
- hr = CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
+ hr = fn_CoInternetCreateSecurityManager(NULL, &spSecurityManager, (DWORD)0);
if (FAILED(hr)) {
return JNI_FALSE;
}
diff --git a/src/windows/native/sun/nio/ch/FileDispatcherImpl.c b/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
index 850d8adec9..753725f0da 100644
--- a/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
+++ b/src/windows/native/sun/nio/ch/FileDispatcherImpl.c
@@ -210,6 +210,7 @@ Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, jobject fdo
if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+ return IOS_THROWN;
}
return convertReturnVal(env, (jint)written, JNI_FALSE);
@@ -258,6 +259,7 @@ Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, jobject fd
if ((h == INVALID_HANDLE_VALUE) || (result == 0)) {
JNU_ThrowIOExceptionWithLastError(env, "Write failed");
+ return IOS_THROWN;
}
return convertLongReturnVal(env, totalWritten, JNI_FALSE);
diff --git a/src/windows/native/sun/security/mscapi/security.cpp b/src/windows/native/sun/security/mscapi/security.cpp
index 7012a35ccd..12c408e8ee 100644
--- a/src/windows/native/sun/security/mscapi/security.cpp
+++ b/src/windows/native/sun/security/mscapi/security.cpp
@@ -202,14 +202,17 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
}
/*
- * If length is negative then use the supplied seed to re-seed the
- * generator and return null.
+ * If length is negative and a seed is supplied, use it to re-seed the
+ * generator. Return null whether a seed is supplied or not.
* If length is non-zero then generate a new seed according to the
* requested length and return the new seed.
* If length is zero then overwrite the supplied seed with a new
* seed of the same length and return the seed.
*/
if (length < 0) {
+ if (seed == NULL) {
+ __leave;
+ }
length = env->GetArrayLength(seed);
if ((reseedBytes = env->GetByteArrayElements(seed, 0)) == NULL) {
__leave;
diff --git a/src/windows/native/sun/windows/WPrinterJob.cpp b/src/windows/native/sun/windows/WPrinterJob.cpp
index 70aaa74236..90b2f3606f 100644
--- a/src/windows/native/sun/windows/WPrinterJob.cpp
+++ b/src/windows/native/sun/windows/WPrinterJob.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2019, 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
@@ -68,7 +68,7 @@ static BOOL IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
extern "C" {
JNIEXPORT jstring JNICALL
-Java_sun_print_Win32PrintServiceLookup_getDefaultPrinterName(JNIEnv *env,
+Java_sun_print_PrintServiceLookupProvider_getDefaultPrinterName(JNIEnv *env,
jobject peer)
{
TRY;
@@ -118,10 +118,7 @@ Java_sun_print_Win32PrintServiceLookup_getDefaultPrinterName(JNIEnv *env,
}
-JNIEXPORT jobjectArray JNICALL
-Java_sun_print_Win32PrintServiceLookup_getAllPrinterNames(JNIEnv *env,
- jobject peer)
-{
+static jobjectArray getPrinterNames(JNIEnv *env, DWORD flags) {
TRY;
DWORD cbNeeded = 0;
@@ -136,10 +133,10 @@ Java_sun_print_Win32PrintServiceLookup_getAllPrinterNames(JNIEnv *env,
jobjectArray nameArray;
try {
- ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
+ ::EnumPrinters(flags,
NULL, 4, NULL, 0, &cbNeeded, &cReturned);
pPrinterEnum = new BYTE[cbNeeded];
- ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
+ ::EnumPrinters(flags,
NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded,
&cReturned);
@@ -174,9 +171,23 @@ Java_sun_print_Win32PrintServiceLookup_getAllPrinterNames(JNIEnv *env,
CATCH_BAD_ALLOC_RET(NULL);
}
+JNIEXPORT jobjectArray JNICALL
+Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
+ jobject peer)
+{
+ return getPrinterNames(env, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS);
+}
+
+JNIEXPORT jobjectArray JNICALL
+Java_sun_print_PrintServiceLookupProvider_getRemotePrintersNames(JNIEnv *env,
+ jobject peer)
+{
+ return getPrinterNames(env, PRINTER_ENUM_CONNECTIONS);
+}
+
JNIEXPORT jlong JNICALL
-Java_sun_print_Win32PrintServiceLookup_notifyFirstPrinterChange(JNIEnv *env,
+Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv *env,
jobject peer,
jstring printer) {
HANDLE hPrinter;
@@ -210,7 +221,7 @@ Java_sun_print_Win32PrintServiceLookup_notifyFirstPrinterChange(JNIEnv *env,
JNIEXPORT void JNICALL
-Java_sun_print_Win32PrintServiceLookup_notifyClosePrinterChange(JNIEnv *env,
+Java_sun_print_PrintServiceLookupProvider_notifyClosePrinterChange(JNIEnv *env,
jobject peer,
jlong chgObject) {
FindClosePrinterChangeNotification((HANDLE)chgObject);
@@ -218,7 +229,7 @@ Java_sun_print_Win32PrintServiceLookup_notifyClosePrinterChange(JNIEnv *env,
JNIEXPORT jint JNICALL
-Java_sun_print_Win32PrintServiceLookup_notifyPrinterChange(JNIEnv *env,
+Java_sun_print_PrintServiceLookupProvider_notifyPrinterChange(JNIEnv *env,
jobject peer,
jlong chgObject) {
DWORD dwChange;
diff --git a/test/Makefile b/test/Makefile
index 64b828bb58..612300a27e 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -272,7 +272,7 @@ JTREG_BASIC_OPTIONS += -a
JTREG_ASSERT_OPTION = -ea -esa
JTREG_BASIC_OPTIONS += $(JTREG_ASSERT_OPTION)
# Report details on all failed or error tests, times too
-JTREG_BASIC_OPTIONS += -v:fail,error,time
+JTREG_BASIC_OPTIONS += -v:fail,error,summary
# Retain all files for failing tests
JTREG_BASIC_OPTIONS += -retain:fail,error
# Ignore tests are not run and completely silent about it
diff --git a/test/ProblemList.txt b/test/ProblemList.txt
index 0abaccff0b..bb7f70061b 100644
--- a/test/ProblemList.txt
+++ b/test/ProblemList.txt
@@ -112,6 +112,9 @@
# jdk_awt
+# 8221305
+java/awt/FontMetrics/MaxAdvanceIsMax.java solaris-all,macosx-all
+
############################################################################
# jdk_beans
@@ -305,6 +308,8 @@ com/sun/crypto/provider/CICO/PBEFunc/CICOPBEFuncTest.java solaris-sparcv9
# 8206912
sun/security/krb5/auto/ReplayCacheTestProc.java solaris-sparcv9
+security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
+
############################################################################
# jdk_sound
diff --git a/test/TEST.groups b/test/TEST.groups
index 8afd9dd26c..920885746a 100644
--- a/test/TEST.groups
+++ b/test/TEST.groups
@@ -20,6 +20,34 @@
# questions.
#
+###############################################################################
+#
+# Tiered testing definitions
+#
+
+jdk_tier1 = \
+ :jdk_lang \
+ :jdk_util \
+ :jdk_math \
+ :jdk_jdi
+
+jdk_tier2 = \
+ :jdk_io \
+ :jdk_nio \
+ :jdk_net \
+ :jdk_rmi \
+ :jdk_time \
+ :jdk_security \
+ :jdk_text \
+ :core_tools \
+ :jdk_other \
+ :jdk_svc
+
+###############################################################################
+#
+# Other test definitions; generally smaller granularity than tiers
+#
+
# java.lang package and VM runtime support
jdk_lang = \
java/lang \
@@ -145,6 +173,9 @@ jdk_security = \
:jdk_security3 \
:jdk_security4
+jdk_security_infra = \
+ security/infra/java/security/cert/CertPathValidator/certification
+
jdk_text = \
java/text \
sun/text
@@ -376,12 +407,16 @@ needs_jre = \
java/net/URLConnection/HandleContentTypeWithAttrs.java \
java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh \
java/security/Security/ClassLoaderDeadlock/Deadlock.sh \
+ java/text/AttributedCharacterIterator/Attribute/ReadResolve.java \
+ java/text/AttributedString/TestAttributedStringCtor.java \
+ java/text/AttributedString/getRunStartLimitTest.java \
java/util/jar/Manifest/CreateManifest.java \
java/util/logging/Listeners.java \
java/util/logging/ListenersWithSM.java \
java/util/logging/TestMainAppContext.java \
java/util/logging/TestLoggingWithMainAppContext.java \
java/util/ResourceBundle/Control/Bug6530694.java \
+ java/util/TimeZone/DefaultTimeZoneTest.java \
java/text/Bidi/BidiConformance.java \
java/text/Bidi/BidiEmbeddingTest.java \
java/text/Bidi/Bug7042148.java \
@@ -587,6 +622,7 @@ needs_compact2 = \
java/util/Collections/UnmodifiableMapEntrySet.java \
java/util/Comparator/BasicTest.java \
java/util/Comparator/TypeTest.java \
+ java/util/Date/TimestampTest.java \
java/util/Iterator/IteratorDefaults.java \
java/util/Iterator/PrimitiveIteratorDefaults.java \
java/util/List/ListDefaults.java \
diff --git a/test/java/awt/BasicStroke/DashOffset.java b/test/java/awt/BasicStroke/DashOffset.java
new file mode 100644
index 0000000000..a7183e249d
--- /dev/null
+++ b/test/java/awt/BasicStroke/DashOffset.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2001, 2019, 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.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+import javax.imageio.ImageIO;
+
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/*
+ * @test
+ * @bug 4469881 8217263
+ * @summary Verifies that dashed rectangles drawn to the screen line
+ * up with their undashed counterparts
+ * @author flar
+ * @run main/othervm -Dsun.java2d.uiScale=1 DashOffset
+ */
+public class DashOffset {
+
+ private static final BasicStroke dash =
+ new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER, 10.0f,
+ new float[] {2.0f, 2.0f}, 0.0f);
+
+ private static final Color COLOR1 = Color.BLUE;
+ private static final Color COLOR2 = Color.GREEN;
+
+ private static final Color BACKGROUND = Color.WHITE;
+
+ private static final int WIDTH = 20;
+ private static final int HEIGHT = 20;
+
+ private static final int OFFSET = 2;
+
+ private static final int MAX_DASH_LENGTH = 3;
+
+ public static void main(String[] argv) throws Exception {
+ final boolean saveImage = argv.length > 0 && "-save".equals(argv[0]);
+
+ final BufferedImage img = new BufferedImage(WIDTH, HEIGHT,
+ TYPE_INT_RGB);
+ try {
+ draw(img);
+ validate(img);
+ } finally {
+ if (saveImage) {
+ save(img, "bufferedImage.png");
+ }
+ }
+
+ if (GraphicsEnvironment.isHeadless()) {
+ return;
+ }
+
+ BufferedImage snapshot = null;
+ try {
+ final GraphicsConfiguration gc =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice()
+ .getDefaultConfiguration();
+
+ VolatileImage vi = gc.createCompatibleVolatileImage(WIDTH, HEIGHT);
+ int attempt = 0;
+ do {
+ vi.validate(gc);
+ draw(vi);
+ snapshot = vi.getSnapshot();
+ } while (vi.contentsLost() && ++attempt <= 10);
+ if (attempt > 10) {
+ throw new RuntimeException("Too many attempts: " + attempt);
+ }
+ validate(snapshot);
+ } finally {
+ if (saveImage) {
+ save(snapshot, "volatileImage.png");
+ }
+ }
+ }
+
+ private static void draw(final Image img) {
+ Graphics g = img.getGraphics();
+ g.setColor(BACKGROUND);
+ g.fillRect(0, 0, WIDTH, HEIGHT);
+ g.setColor(COLOR1);
+ g.drawRect(OFFSET, OFFSET, WIDTH - OFFSET * 2, HEIGHT - OFFSET * 2);
+ g.setColor(COLOR2);
+ g.clipRect(OFFSET, OFFSET, WIDTH - OFFSET * 2 + 1, HEIGHT - OFFSET * 2 + 1);
+ ((Graphics2D) g).setStroke(dash);
+ g.drawRect(OFFSET, OFFSET, WIDTH - OFFSET * 2, HEIGHT - OFFSET * 2);
+ g.dispose();
+ }
+
+ private static void validate(final BufferedImage img) {
+ checkHorizontalLine(img, OFFSET);
+ checkHorizontalLine(img, HEIGHT - OFFSET);
+ checkVerticalLine(img, OFFSET);
+ checkVerticalLine(img, WIDTH - OFFSET);
+ checkCorners(img);
+ }
+
+ private static void checkHorizontalLine(final BufferedImage img,
+ final int y) {
+ int prev = img.getRGB(OFFSET, y);
+ int curr;
+ int count = 1;
+ checkColor(OFFSET, y, prev, COLOR1, COLOR2);
+ for (int x = OFFSET + 1; x <= WIDTH - OFFSET; x++) {
+ curr = img.getRGB(x, y);
+ if (curr != prev) {
+ checkColor(x, y, curr, COLOR1, COLOR2);
+ checkCount(x, y, count);
+ prev = curr;
+ count = 1;
+ } else {
+ count++;
+ }
+ if (x < WIDTH - OFFSET) {
+ checkColor(x, y - 1, img.getRGB(x, y - 1), BACKGROUND);
+ checkColor(x, y + 1, img.getRGB(x, y + 1), BACKGROUND);
+ }
+ }
+ checkCount(WIDTH - OFFSET, y, count);
+ }
+
+ private static void checkVerticalLine(final BufferedImage img,
+ final int x) {
+ int prev = img.getRGB(x, OFFSET);
+ checkColor(x, OFFSET, prev, COLOR1, COLOR2);
+ int count = 1;
+ for (int y = OFFSET + 1; y <= HEIGHT - OFFSET; y++) {
+ int curr = img.getRGB(x, y);
+ if (curr != prev) {
+ checkColor(x, y, curr, COLOR1, COLOR2);
+ checkCount(x, y, count);
+ prev = curr;
+ count = 1;
+ } else {
+ count++;
+ }
+ if (y < HEIGHT - OFFSET) {
+ checkColor(x - 1, y, img.getRGB(x - 1, y), BACKGROUND);
+ checkColor(x + 1, y, img.getRGB(x + 1, y), BACKGROUND);
+ }
+ }
+ checkCount(x, HEIGHT - OFFSET, count);
+ }
+
+ private static void checkCorners(final BufferedImage img) {
+ int[][] corners = {
+ {OFFSET - 1, OFFSET - 1},
+ {OFFSET, OFFSET - 1},
+ {OFFSET - 1, OFFSET + 1},
+
+ {OFFSET - 1, HEIGHT - OFFSET},
+ {OFFSET - 1, HEIGHT - OFFSET + 1},
+ {OFFSET, HEIGHT - OFFSET + 1},
+
+ {WIDTH - OFFSET, OFFSET - 1},
+ {WIDTH - OFFSET + 1, OFFSET - 1},
+ {WIDTH - OFFSET + 1, OFFSET},
+
+ {WIDTH - OFFSET + 1, HEIGHT - OFFSET},
+ {WIDTH - OFFSET + 1, HEIGHT - OFFSET + 1},
+ {WIDTH - OFFSET, HEIGHT - OFFSET + 1},
+ };
+
+ for (int[] corner : corners) {
+ int color = img.getRGB(corner[0], corner[1]);
+ checkColor(corner[0], corner[1], color, BACKGROUND);
+ }
+ }
+
+ private static void checkColor(final int x, final int y,
+ final int color,
+ final Color... validColors) {
+ checkColor(x, y, color, Arrays.stream(validColors)
+ .mapToInt(Color::getRGB)
+ .toArray());
+ }
+
+ private static void checkColor(final int x, final int y,
+ final int color,
+ final int... validColors) {
+ for (int valid : validColors) {
+ if (color == valid) {
+ return;
+ }
+ }
+ throw new RuntimeException("Unexpected color at " + x + ", " + y
+ + ": " + Integer.toHexString(color) + "; expected: "
+ + Arrays.stream(validColors)
+ .mapToObj(Integer::toHexString)
+ .collect(Collectors.joining(", ")));
+ }
+
+ private static void checkCount(final int x, final int y, final int count) {
+ if (count > MAX_DASH_LENGTH) {
+ throw new RuntimeException("Dash is longer than " + MAX_DASH_LENGTH
+ + " at " + x + ", " + y);
+ }
+ }
+
+ private static void save(final BufferedImage img,
+ final String fileName) throws IOException {
+ ImageIO.write(img, "png", new File(fileName));
+ }
+
+}
diff --git a/test/java/awt/BasicStroke/DashScaleMinWidth.java b/test/java/awt/BasicStroke/DashScaleMinWidth.java
new file mode 100644
index 0000000000..ef7dded92e
--- /dev/null
+++ b/test/java/awt/BasicStroke/DashScaleMinWidth.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2003, 2017, 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.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.geom.Line2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+
+/**
+ * @test
+ * @bug 4917097 8019816
+ * @summary 1.4.1 REGRESSION: BasicStroke Dashes don't show when scale * line width = 1.0
+ * @run main/othervm -Dsun.java2d.uiScale=1 DashScaleMinWidth
+ */
+public final class DashScaleMinWidth {
+
+ public static void main(final String[] args) {
+ BufferedImage img = new BufferedImage(200, 40, TYPE_INT_ARGB);
+ draw(img);
+ validate(img);
+
+ if (GraphicsEnvironment.isHeadless()) {
+ return;
+ }
+
+ GraphicsConfiguration gc =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ VolatileImage vi = gc.createCompatibleVolatileImage(200, 40);
+ BufferedImage snapshot;
+ int attempt = 0;
+ while (true) {
+ if (++attempt > 10) {
+ throw new RuntimeException("Too many attempts: " + attempt);
+ }
+ vi.validate(gc);
+ draw(vi);
+ snapshot = vi.getSnapshot();
+ if (!vi.contentsLost()) {
+ break;
+ }
+ }
+ validate(snapshot);
+ }
+
+ private static void draw(final Image img) {
+ float[] dashes = {200.0f, 200.0f};
+ BasicStroke bs = new BasicStroke(20.0f,
+ BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER,
+ 1.0f,
+ dashes,
+ 0.0f);
+ Graphics2D g = (Graphics2D) img.getGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, 200, 40);
+ Line2D line = new Line2D.Double(400, 400, 3600, 400);
+ g.setColor(Color.BLACK);
+ g.scale(0.05, 0.05);
+ g.setStroke(bs);
+ g.draw(line);
+ g.dispose();
+ }
+
+ private static void validate(final BufferedImage img) {
+ int white = Color.white.getRGB();
+ int point = img.getRGB(35, 20); // point in the gap
+ if (point != white) {
+ throw new RuntimeException("Line should be dashed");
+ }
+ }
+}
diff --git a/test/java/awt/BasicStroke/DashZeroWidth.java b/test/java/awt/BasicStroke/DashZeroWidth.java
new file mode 100644
index 0000000000..fb0f51ce4a
--- /dev/null
+++ b/test/java/awt/BasicStroke/DashZeroWidth.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003, 2017, 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.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.geom.Line2D;
+import java.awt.image.BufferedImage;
+import java.awt.image.VolatileImage;
+
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+
+/**
+ * @test
+ * @bug 4779211 8019816
+ * @summary REGRESSION: 1.4 Dashed lines disappear if BasicStroke width=0.0
+ * @run main/othervm -Dsun.java2d.uiScale=1 DashZeroWidth
+ */
+public final class DashZeroWidth {
+
+ public static void main(final String[] args) {
+ BufferedImage img = new BufferedImage(200, 40, TYPE_INT_ARGB);
+ draw(img);
+ validate(img);
+
+ if (GraphicsEnvironment.isHeadless()) {
+ return;
+ }
+
+ GraphicsConfiguration gc =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+
+ VolatileImage vi = gc.createCompatibleVolatileImage(200, 40);
+ BufferedImage snapshot;
+ int attempt = 0;
+ while (true) {
+ if (++attempt > 10) {
+ throw new RuntimeException("Too many attempts: " + attempt);
+ }
+ vi.validate(gc);
+ draw(vi);
+ snapshot = vi.getSnapshot();
+ if (!vi.contentsLost()) {
+ break;
+ }
+ }
+ validate(snapshot);
+ }
+
+ private static void draw(final Image img) {
+ float[] dashes = {10.0f, 10.0f};
+ BasicStroke bs = new BasicStroke(0.0f, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_BEVEL, 10.0f, dashes,
+ 0.0f);
+ Graphics2D g = (Graphics2D) img.getGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, 200, 40);
+ Line2D line = new Line2D.Double(20, 20, 180, 20);
+ g.setColor(Color.BLACK);
+ g.setStroke(bs);
+ g.draw(line);
+ g.dispose();
+ }
+
+ private static void validate(final BufferedImage img) {
+ int black = Color.black.getRGB();
+ int white = Color.white.getRGB();
+ int pointB = img.getRGB(25, 20); // point on the dash
+ int pointW = img.getRGB(35, 20); // point in the gap
+ if (pointB != black || pointW != white) {
+ throw new RuntimeException("Line should be visible and dashed");
+ }
+ }
+}
diff --git a/test/java/awt/ComponentOrientation/BasicTest.java b/test/java/awt/ComponentOrientation/BasicTest.java
new file mode 100644
index 0000000000..50c0f61eaf
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/BasicTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4108453 4778440 6304780 6396378
+ * @summary Basic tests for java.awt.ComponentOrientation
+ * @build TestBundle TestBundle_es TestBundle_iw
+ * @build TestBundle1 TestBundle1_ar
+ *
+ * @run main BasicTest
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.ComponentOrientation;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class BasicTest {
+ public static void main(String args[]) {
+ System.out.println("BasicTest {");
+ TestInvariants();
+ TestLocale();
+ TestBundle();
+
+ System.out.println("} Pass");
+ }
+
+ // TestInvariants
+ //
+ // Various no-brainer tests to make sure the constants behave properly
+ // and so on.
+ //
+ static void TestInvariants() {
+ System.out.println(" TestInvariants {");
+
+ Assert(ComponentOrientation.LEFT_TO_RIGHT.isLeftToRight(),
+ "LEFT_TO_RIGHT.isLeftToRight()");
+
+ Assert(ComponentOrientation.UNKNOWN.isLeftToRight(),
+ "UNKNOWN.isLeftToRight()");
+
+ Assert(!ComponentOrientation.RIGHT_TO_LEFT.isLeftToRight(),
+ "!RIGHT_TO_LEFT.isLeftToRight()");
+
+ Assert(ComponentOrientation.LEFT_TO_RIGHT.isHorizontal(),
+ "LEFT_TO_RIGHT.isHorizontal()");
+
+ Assert(ComponentOrientation.UNKNOWN.isHorizontal(),
+ "UNKNOWN.isHorizontal()");
+
+ Assert(ComponentOrientation.RIGHT_TO_LEFT.isHorizontal(),
+ "RIGHT_TO_LEFT.isHorizontal()");
+
+ System.out.println(" } Pass");
+ }
+
+ // TestLocale
+ //
+ // Make sure that getOrientation(Locale) works, and that the appropriate
+ // system locales are RIGHT_TO_LEFT
+ //
+ static void TestLocale() {
+ System.out.println(" TestLocale {");
+
+ ComponentOrientation orient = ComponentOrientation.getOrientation(Locale.US);
+ Assert(orient == ComponentOrientation.LEFT_TO_RIGHT, "US == LEFT_TO_RIGHT");
+
+ orient = ComponentOrientation.getOrientation(new Locale("iw", ""));
+ Assert(orient == ComponentOrientation.RIGHT_TO_LEFT, "iw == RIGHT_TO_LEFT");
+
+ orient = ComponentOrientation.getOrientation(new Locale("ar", ""));
+ Assert(orient == ComponentOrientation.RIGHT_TO_LEFT, "ar == RIGHT_TO_LEFT");
+
+ System.out.println(" } Pass");
+ }
+
+ // TestBundle
+ //
+ // Make sure that getOrientation(ResourceBundle) works right, especially
+ // the fallback mechasm
+ //
+ static void TestBundle() {
+ System.out.println(" TestBundle {");
+
+ // This will fall back to the default locale's bundle or root bundle
+ ResourceBundle rb = ResourceBundle.getBundle("TestBundle",
+ new Locale("et", ""));
+ if (rb.getLocale().getLanguage().equals(new Locale("iw").getLanguage())) {
+ assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "et == RIGHT_TO_LEFT" );
+ } else if (rb.getLocale().getLanguage() == "es") {
+ assertEquals(rb, ComponentOrientation.LEFT_TO_RIGHT, "et == LEFT_TO_RIGHT" );
+ } else {
+ assertEquals(rb, ComponentOrientation.UNKNOWN, "et == UNKNOWN" );
+ }
+
+ // We have actual bundles for "es" and "iw", so it should just fetch
+ // the orientation object out of them
+ rb = ResourceBundle.getBundle("TestBundle",new Locale("es", ""));
+ assertEquals(rb, ComponentOrientation.LEFT_TO_RIGHT, "es == LEFT_TO_RIGHT" );
+
+ rb = ResourceBundle.getBundle("TestBundle", new Locale("iw", "IL"));
+ assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "iw == RIGHT_TO_LEFT" );
+
+ // This bundle has no orientation setting at all, so we should get
+ // the system's default orientation for Arabic
+ rb = ResourceBundle.getBundle("TestBundle1", new Locale("ar", ""));
+ assertEquals(rb, ComponentOrientation.RIGHT_TO_LEFT, "ar == RIGHT_TO_LEFT" );
+
+ System.out.println(" } Pass");
+ }
+
+ static void assertEquals(ResourceBundle rb, ComponentOrientation o, String str) {
+ Assert(ComponentOrientation.getOrientation(rb) == o, str);
+ }
+
+ static void Assert(boolean condition, String str) {
+ if (!condition) {
+ System.err.println(" ASSERT FAILED: " + str);
+ throw new RuntimeException("Assert Failed: " + str);
+ }
+ }
+}
diff --git a/test/java/awt/ComponentOrientation/BorderTest.java b/test/java/awt/ComponentOrientation/BorderTest.java
new file mode 100644
index 0000000000..5cc2138bc4
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/BorderTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4108453
+ * @summary Test ComponentOrientation (Bidi) support in BorderLayout
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.Applet;
+
+public class BorderTest extends Applet {
+ Panel panel1;
+ Panel panel2;
+
+ public BorderTest() {
+ setLayout(new GridLayout(0,2));
+
+ // Create a panel with a BorderLayout and a bunch of buttons in it
+ panel1 = new Panel();
+ panel1.setLayout(new BorderLayout());
+ panel1.add("North", new Button("North"));
+ panel1.add("South", new Button("South"));
+ panel1.add("East", new Button("East"));
+ panel1.add("West", new Button("West"));
+ panel1.add("Center", new Button("Center"));
+ add(panel1);
+
+ // Create a panel with a BorderLayout and a bunch of buttons in it
+ panel2 = new Panel();
+ panel2.setLayout(new BorderLayout());
+ panel2.add(BorderLayout.BEFORE_FIRST_LINE, new Button("FirstLine"));
+ panel2.add(BorderLayout.AFTER_LAST_LINE, new Button("LastLine"));
+ panel2.add(BorderLayout.BEFORE_LINE_BEGINS, new Button("FirstItem"));
+ panel2.add(BorderLayout.AFTER_LINE_ENDS, new Button("LastItem"));
+ panel2.add("Center", new Button("Center"));
+ add(panel2);
+
+ // Create a popup menu for switching between orientations
+ {
+ Choice c = new Choice();
+ c.addItem("LEFT_TO_RIGHT");
+ c.addItem("RIGHT_TO_LEFT");
+ c.addItem("UNKNOWN");
+ c.addItemListener( new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ String item = (String)(e.getItem());
+
+ ComponentOrientation o = ComponentOrientation.UNKNOWN;
+ if (item.equals("LEFT_TO_RIGHT")) {
+ o = ComponentOrientation.LEFT_TO_RIGHT;
+ } else if (item.equals("RIGHT_TO_LEFT")) {
+ o = ComponentOrientation.RIGHT_TO_LEFT;
+ }
+ panel1.setComponentOrientation(o);
+ panel2.setComponentOrientation(o);
+ panel1.layout();
+ panel2.layout();
+ panel1.repaint();
+ panel2.repaint();
+ }
+ } );
+ add(c);
+ }
+ }
+
+ public static void main(String args[]) {
+ Frame f = new Frame("BorderTest");
+
+ f.addWindowListener( new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ e.getWindow().hide();
+ e.getWindow().dispose();
+ System.exit(0);
+ };
+ } );
+
+ BorderTest BorderTest = new BorderTest();
+ BorderTest.init();
+ BorderTest.start();
+
+ f.add("Center", BorderTest);
+ f.setSize(450, 300);
+ f.show();
+ }
+}
diff --git a/test/java/awt/ComponentOrientation/FlowTest.java b/test/java/awt/ComponentOrientation/FlowTest.java
new file mode 100644
index 0000000000..046953ce9c
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/FlowTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4108453
+ * @summary Test ComponentOrientation (Bidi) support in FlowLayout
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+import java.applet.Applet;
+
+public class FlowTest extends Applet {
+ Panel panel;
+
+ public FlowTest() {
+ setLayout(new BorderLayout());
+
+ // Create a panel with a FlowLayout and a bunch of buttons in it
+ panel = new Panel();
+ panel.setLayout(new FlowLayout(FlowLayout.LEFT));
+ panel.add(new Button("one"));
+ panel.add(new Button("two"));
+ panel.add(new Button("three"));
+ panel.add(new Button("four"));
+ panel.add(new Button("five"));
+ panel.add(new Button("six"));
+ panel.add(new Button("seven"));
+ panel.add(new Button("eight"));
+ panel.add(new Button("nine"));
+ panel.add(new Button("ten"));
+ panel.add(new Button("eleven"));
+
+ add("Center", panel);
+
+ Panel controls = new Panel();
+ controls.setLayout(new GridLayout(0, 2));
+
+ // Menu for setting the alignment of the main FlowLayout panel
+ {
+ Choice c = new Choice();
+ c.addItem("LEFT");
+ c.addItem("CENTER");
+ c.addItem("RIGHT");
+ c.addItem("LEADING");
+ c.addItem("TRAILING");
+ c.addItemListener( new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ String item = (String)(e.getItem());
+ FlowLayout layout = (FlowLayout) panel.getLayout();
+
+ if (item.equals("LEFT")) {
+ layout.setAlignment(FlowLayout.LEFT);
+ } else if (item.equals("CENTER")) {
+ layout.setAlignment(FlowLayout.CENTER);
+ } else if (item.equals("RIGHT")) {
+ layout.setAlignment(FlowLayout.RIGHT);
+ } else if (item.equals("LEADING")) {
+ layout.setAlignment(FlowLayout.LEADING);
+ } else if (item.equals("TRAILING")) {
+ layout.setAlignment(FlowLayout.TRAILING);
+ }
+ panel.layout();
+ panel.repaint();
+ }
+ } );
+ controls.add(new Label("FlowLayout Alignment:"));
+ controls.add(c);
+ }
+
+ // Create a popup menu for switching the Panel between orientations
+ {
+ Choice c = new Choice();
+ c.addItem("LEFT_TO_RIGHT");
+ c.addItem("RIGHT_TO_LEFT");
+ c.addItem("UNKNOWN");
+ c.addItemListener( new ItemListener() {
+ public void itemStateChanged(ItemEvent e) {
+ String item = (String)(e.getItem());
+
+ if (item.equals("LEFT_TO_RIGHT")) {
+ panel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
+ } else if (item.equals("RIGHT_TO_LEFT")) {
+ panel.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
+ } else {
+ panel.setComponentOrientation(ComponentOrientation.UNKNOWN);
+ }
+ panel.layout();
+ panel.repaint();
+ }
+ } );
+
+ controls.add(new Label("ComponentOrientation:"));
+ controls.add(c);
+ }
+
+ add("South", controls);
+
+ }
+
+ public static void main(String args[]) {
+ Frame f = new Frame("FlowTest");
+
+ f.addWindowListener( new WindowAdapter() {
+ public void windowClosing(WindowEvent e) {
+ e.getWindow().hide();
+ e.getWindow().dispose();
+ System.exit(0);
+ };
+ } );
+
+ FlowTest flowTest = new FlowTest();
+ flowTest.init();
+ flowTest.start();
+
+ f.add("Center", flowTest);
+ f.setSize(300, 300);
+ f.show();
+ }
+}
diff --git a/test/java/awt/ComponentOrientation/TestBundle.java b/test/java/awt/ComponentOrientation/TestBundle.java
new file mode 100644
index 0000000000..3669d1651c
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/TestBundle.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/**
+ * TestBundle.java -- used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle extends ListResourceBundle {
+
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "Orientation", ComponentOrientation.UNKNOWN },
+ };
+ }
+};
diff --git a/test/java/awt/ComponentOrientation/TestBundle1.java b/test/java/awt/ComponentOrientation/TestBundle1.java
new file mode 100644
index 0000000000..ae3e012bf6
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/TestBundle1.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/**
+ * TestBundle1.java -- used by BasicTest
+ *
+ * @bug 4108453
+ * @summary Basic tests for java.awt.ComponentOrientation
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle1 extends ListResourceBundle {
+
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { },
+ };
+ }
+};
diff --git a/test/java/awt/ComponentOrientation/TestBundle1_ar.java b/test/java/awt/ComponentOrientation/TestBundle1_ar.java
new file mode 100644
index 0000000000..66c971b8c7
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/TestBundle1_ar.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/**
+ * TestBundle1_ar.java -- used by BasicTest
+ *
+ * @bug 4108453
+ * @summary Basic tests for java.awt.ComponentOrientation
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle1_ar extends ListResourceBundle {
+
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { },
+ };
+ }
+};
diff --git a/test/java/awt/ComponentOrientation/TestBundle_es.java b/test/java/awt/ComponentOrientation/TestBundle_es.java
new file mode 100644
index 0000000000..a5e9c7dfa7
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/TestBundle_es.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/**
+ * TestBundle_es.java -- used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle_es extends ListResourceBundle {
+
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "Orientation", ComponentOrientation.LEFT_TO_RIGHT },
+ };
+ }
+};
diff --git a/test/java/awt/ComponentOrientation/TestBundle_iw.java b/test/java/awt/ComponentOrientation/TestBundle_iw.java
new file mode 100644
index 0000000000..87ff453245
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/TestBundle_iw.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/**
+ *
+ *
+ * used by BasicTest
+ *
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.ListResourceBundle;
+import java.awt.ComponentOrientation;
+
+public class TestBundle_iw extends ListResourceBundle {
+
+ protected Object[][] getContents() {
+ return new Object[][] {
+ { "Orientation", ComponentOrientation.RIGHT_TO_LEFT },
+ };
+ }
+};
diff --git a/test/java/awt/ComponentOrientation/WindowTest.java b/test/java/awt/ComponentOrientation/WindowTest.java
new file mode 100644
index 0000000000..85242e1544
--- /dev/null
+++ b/test/java/awt/ComponentOrientation/WindowTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4108453 4778440 6304785
+ * @summary Test Window.applyResourceBundle orientation support
+ *
+ * @build TestBundle TestBundle_es TestBundle_iw
+ * @build TestBundle1 TestBundle1_ar
+ * @run main WindowTest
+ */
+
+import java.awt.*;
+import java.applet.*;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+public class WindowTest extends Applet {
+ static Exception failure=null;
+ static Thread mainThread=null;
+
+ public static void main(String args[]) throws Exception {
+ mainThread = Thread.currentThread();
+ WindowTest app = new WindowTest();
+ app.start();
+ try {
+ Thread.sleep(300000);
+ } catch (InterruptedException e) {
+ if (failure != null) {
+ throw failure;
+ }
+ }
+ }
+
+ public void start() {
+ try {
+ doTest();
+ } catch (Exception e) {
+ failure = e;
+ }
+ mainThread.interrupt();
+ }
+
+ public void doTest() {
+ System.out.println("WindowTest {");
+
+ ResourceBundle rb;
+ Frame myFrame;
+
+ // Create a window containing a hierarchy of components.
+ System.out.println(" Creating component hierarchy...");
+ myFrame = new Frame();
+ myFrame.setLayout(new FlowLayout());
+ Panel panel1 = new Panel();
+ panel1.setLayout(new BorderLayout());
+ panel1.add("North", new Button("North"));
+ panel1.add("South", new Button("South"));
+ panel1.add("East", new Button("East"));
+ panel1.add("West", new Button("West"));
+ panel1.add("Center", new Button("Center"));
+ myFrame.add(panel1);
+
+ Panel panel2 = new Panel();
+ panel2.setLayout(new BorderLayout());
+ panel2.add(BorderLayout.BEFORE_FIRST_LINE, new Button("FirstLine"));
+ panel2.add(BorderLayout.AFTER_LAST_LINE, new Button("LastLine"));
+ panel2.add(BorderLayout.BEFORE_LINE_BEGINS, new Button("FirstItem"));
+ panel2.add(BorderLayout.AFTER_LINE_ENDS, new Button("LastItem"));
+ panel2.add("Center", new Button("Center"));
+ myFrame.add(panel2);
+
+ // After construction, all of the components' orientations should be
+ // set to ComponentOrientation.UNKNOWN.
+ System.out.println(" Verifying orientation is UNKNOWN...");
+ verifyOrientation(myFrame, ComponentOrientation.UNKNOWN);
+
+ // This will load TestBundle1 using the default locale and apply
+ // it to the component hierarchy. Since the bundle has no Orientation
+ // specified, this should fall back to the bundle-locale's orientation
+ System.out.println(" Applying TestBundle1 by name and verifying...");
+ myFrame.applyResourceBundle("TestBundle1");
+ verifyOrientation(myFrame,
+ ComponentOrientation.getOrientation(
+ ResourceBundle.getBundle("TestBundle1", Locale.getDefault())));
+
+ System.out.println(" Applying TestBundle_iw and verifying...");
+ rb = ResourceBundle.getBundle("TestBundle", new Locale("iw", ""));
+ myFrame.applyResourceBundle(rb);
+ verifyOrientation(myFrame, ComponentOrientation.RIGHT_TO_LEFT);
+
+ System.out.println(" Applying TestBundle_es and verifying...");
+ rb = ResourceBundle.getBundle("TestBundle", new Locale("es", ""));
+ myFrame.applyResourceBundle(rb);
+ verifyOrientation(myFrame, ComponentOrientation.LEFT_TO_RIGHT);
+
+
+ myFrame.setVisible(false);
+ myFrame.dispose();
+ System.out.println("}");
+ }
+
+ static void verifyOrientation(Component c, ComponentOrientation orient) {
+
+ ComponentOrientation o = c.getComponentOrientation();
+
+ if (o != orient) {
+ throw new RuntimeException("ERROR: expected " + oString(orient) +
+ ", got " + oString(o) +
+ " on component " + c);
+ }
+
+ if (c instanceof Container) {
+ Container cont = (Container) c;
+ int ncomponents = cont.getComponentCount();
+
+ for (int i = 0 ; i < ncomponents ; ++i) {
+ Component comp = cont.getComponent(i);
+ verifyOrientation(comp, orient);
+ }
+ }
+ }
+
+ static String oString(ComponentOrientation o) {
+ if (o == ComponentOrientation.LEFT_TO_RIGHT) {
+ return "LEFT_TO_RIGHT";
+ }
+ else if (o == ComponentOrientation.RIGHT_TO_LEFT) {
+ return "RIGHT_TO_LEFT";
+ }
+ else {
+ return "UNKNOWN";
+ }
+ }
+}
diff --git a/test/java/awt/FontClass/FontSize1Test.java b/test/java/awt/FontClass/FontSize1Test.java
new file mode 100644
index 0000000000..f0676b7221
--- /dev/null
+++ b/test/java/awt/FontClass/FontSize1Test.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, 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 8216965
+ * @summary verify no crash when rendering size 1 fonts
+ */
+
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.BufferedImage;
+
+public class FontSize1Test {
+
+ static final String text = "abcdefghijklmnopqrstuvwxyz";
+
+ public static void main(String[] args) {
+
+ BufferedImage bi =
+ new BufferedImage(100, 20, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = bi.createGraphics();
+ Font af[] =
+ GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
+
+ for (Font f : af) {
+ System.out.println("Looking at font " + f);
+ g2d.setFont(f);
+ g2d.getFontMetrics().getWidths();
+ g2d.drawString(text, 50, 10);
+ }
+ g2d.dispose();
+ }
+
+}
diff --git a/test/java/awt/FontMetrics/MaxAdvanceIsMax.java b/test/java/awt/FontMetrics/MaxAdvanceIsMax.java
new file mode 100644
index 0000000000..9c131704d8
--- /dev/null
+++ b/test/java/awt/FontMetrics/MaxAdvanceIsMax.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2019, Red Hat, Inc.
+ * 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 8218854
+ * @requires jdk.version.major >= 8
+ * @run main/othervm MaxAdvanceIsMax
+ */
+
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class MaxAdvanceIsMax {
+
+ private static boolean debug = true;
+
+ private static final class AntialiasHint {
+ private Object aaHint;
+ private String asString = "";
+
+ AntialiasHint(Object aaHint) {
+ if (aaHint.equals(
+ RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+ asString += "FT_LOAD_TARGET_MONO";
+ } else if (aaHint.equals(
+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) {
+ asString += "FT_LOAD_TARGET_NORMAL";
+ } else if (aaHint.equals(
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB)) {
+ asString += "FT_LOAD_TARGET_LCD";
+ } else if (aaHint.equals(
+ RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)) {
+ asString += "FT_LOAD_TARGET_LCD_V";
+ }
+ this.aaHint = aaHint;
+ }
+
+ public Object getHint() {
+ return aaHint;
+ }
+
+ public String toString() {
+ return asString;
+ }
+ }
+
+ private static final AntialiasHint[] antialiasHints = {
+ new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF),
+ new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_ON),
+ new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB),
+ new AntialiasHint(RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_VRGB)
+ };
+
+ private static final class StyleAndSize {
+ int style;
+ float size;
+ public StyleAndSize(int style, float size) {
+ this.style = style;
+ this.size = size;
+ }
+ };
+
+ private static final StyleAndSize[] stylesAndSizes = new StyleAndSize[] {
+ new StyleAndSize(Font.BOLD | Font.ITALIC, 10)
+ };
+
+ public static void main(String[] args) throws Exception {
+ GraphicsEnvironment e =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ Font[] fonts = e.getAllFonts();
+ BufferedImage bi = new BufferedImage(500, 500,
+ BufferedImage.TYPE_INT_RGB);
+ for (AntialiasHint antialiasHint : antialiasHints) {
+ for (Font f : fonts) {
+ for (StyleAndSize styleAndSize : stylesAndSizes) {
+ f = f.deriveFont(styleAndSize.style, styleAndSize.size);
+ Graphics2D g2d = bi.createGraphics();
+ g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
+ antialiasHint.getHint());
+ FontMetrics fm = g2d.getFontMetrics(f);
+ int[] width;
+ int maxWidth = -1;
+ int maxAdvance = fm.getMaxAdvance();
+ if (debug) {
+ System.out.println("Testing " + f + " in " +
+ antialiasHint);
+ System.out.println("getMaxAdvance: " + maxAdvance);
+ }
+ if (maxAdvance != -1) {
+ String failureMessage = null;
+ width = fm.getWidths();
+ for (int j = 0; j < width.length; j++) {
+ if (width[j] > maxWidth) {
+ maxWidth = width[j];
+ }
+ if (width[j] > maxAdvance) {
+ failureMessage = "FAILED: getMaxAdvance is " +
+ "not max for font: " +
+ f.toString() +
+ " getMaxAdvance(): " +
+ maxAdvance +
+ " getWidths()[" + j + "]: " +
+ width[j];
+ throw new Exception(failureMessage);
+ }
+ }
+ }
+ if (debug) {
+ System.out.println("Max char width: " + maxWidth);
+ System.out.println("PASSED");
+ System.out.println(".........................");
+ }
+ }
+ }
+ }
+ System.out.println("TEST PASS - OK");
+ }
+}
diff --git a/test/java/awt/Headless/ThemeReaderCrashTest.java b/test/java/awt/Headless/ThemeReaderCrashTest.java
new file mode 100644
index 0000000000..e6fbd5cbc8
--- /dev/null
+++ b/test/java/awt/Headless/ThemeReaderCrashTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, 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 8159956
+ * @summary Test to check JVM crash is not observed in headless mode while
+ * trying to create a JScrollPane
+ * @run main/othervm -Djava.awt.headless=true ThemeReaderCrashTest
+ */
+
+import javax.swing.JScrollPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.ScrollPaneConstants;
+
+public class ThemeReaderCrashTest {
+
+ public static void main(String[] args) throws Exception {
+
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ ThemeReaderCrashTest obj = new ThemeReaderCrashTest();
+ }
+ });
+ }
+
+ ThemeReaderCrashTest() {
+ JPanel panel = new JPanel();
+ JScrollPane pane =
+ new JScrollPane(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
+ ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+ panel.setSize(300, 200);
+
+ panel.add(pane);
+ }
+}
+
diff --git a/test/java/awt/font/TextLayout/FontGlyphCompare.java b/test/java/awt/font/TextLayout/FontGlyphCompare.java
new file mode 100644
index 0000000000..4935b34d4e
--- /dev/null
+++ b/test/java/awt/font/TextLayout/FontGlyphCompare.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, 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 8214002
+ * @requires (os.family == "windows")
+ * @summary verify MS Mincho's Plain & Italic style
+ */
+
+import java.awt.Font;
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.image.BufferedImage;
+
+public class FontGlyphCompare {
+
+ static BufferedImage getFontImage(Font font, String text) {
+ int x = 1;
+ int y = 15;
+ int w = 10;
+ int h = 18;
+ BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = (Graphics2D)bi.getGraphics();
+ g.setColor(Color.black);
+ g.fillRect(0, 0, w, h);
+ g.setColor(Color.white);
+ g.setFont(font);
+ g.drawString(text, x, y);
+ return bi;
+ }
+
+ public static void main(String[] args) throws Exception {
+ String osName = System.getProperty("os.name");
+ System.out.println("OS is " + osName);
+ osName = osName.toLowerCase();
+ if (!osName.startsWith("windows")) {
+ return;
+ }
+ Font msMincho = new Font("MS Mincho", Font.PLAIN, 16);
+ String family = msMincho.getFamily(java.util.Locale.ENGLISH);
+ if (!family.equalsIgnoreCase("MS Mincho")) {
+ System.out.println("Japanese fonts not installed");
+ return;
+ }
+ String s = "|";
+ BufferedImage bi1 = getFontImage(new Font("MS Mincho", Font.PLAIN, 16), s);
+ int h1 = bi1.getHeight();
+ int w1 = bi1.getWidth();
+ BufferedImage bi2 = getFontImage(new Font("MS Mincho", Font.ITALIC, 16), s);
+ int h2 = bi2.getHeight();
+ int w2 = bi2.getWidth();
+ if ((h1 == h2) && (w1 == w2)) {
+ int cnt = 0;
+ for(int yy = 0; yy < h1; yy++) {
+ for(int xx = 0; xx < w1; xx++) {
+ if (bi1.getRGB(xx, yy) != bi2.getRGB(xx, yy)) {
+ cnt++;
+ }
+ }
+ }
+ if (cnt == 0) {
+ throw new Exception("Test failed");
+ }
+ }
+ }
+}
diff --git a/test/java/awt/im/InputContext/ReconnectTest.java b/test/java/awt/im/InputContext/ReconnectTest.java
new file mode 100644
index 0000000000..33f8656074
--- /dev/null
+++ b/test/java/awt/im/InputContext/ReconnectTest.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2018, 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
+ * @key headful
+ * @bug 8213183
+ * @summary verifies InputMethod reconnection
+ * @run main/manual ReconnectTest
+ */
+import java.awt.*;
+import java.awt.event.*;
+
+public class ReconnectTest {
+
+ private static void init() throws Exception {
+ String[] instructions
+ = {
+ "This test supports Linux and Japanese/Korean/Chinese",
+ "input method(IM). Under other environment, press Pass.",
+ "Test steps:",
+ "1.Turn on IM and input some Asian characters to TestWindow.",
+ "2.kill IM frontend by OS, and restart it.",
+ " e.g. for ibus, $ ibus-daemon -r --xim &",
+ "3.Change focus to this Instructions window and back to TestWindow.",
+ "4.Confirm IM can be activated."
+ };
+
+ Sysout.createDialog();
+ Sysout.printInstructions(instructions);
+ }
+
+ static Frame mainFrame;
+
+ public static void initTestWindow() {
+ mainFrame = new Frame();
+ mainFrame.setTitle("TestWindow");
+ mainFrame.setLayout(new BorderLayout());
+ Panel p0 = new Panel();
+ p0.setLayout(new FlowLayout());
+ mainFrame.add(p0, BorderLayout.CENTER);
+ TextArea text = new TextArea();
+ p0.add(text);
+
+ mainFrame.pack();
+ mainFrame.setLocation(700, 10);
+ mainFrame.setVisible(true);
+ }
+
+ public static void dispose() {
+ Sysout.dispose();
+ mainFrame.dispose();
+ }
+
+ /**
+ * ***************************************************
+ * Standard Test Machinery Section DO NOT modify anything in this section --
+ * it's a standard chunk of code which has all of the synchronisation
+ * necessary for the test harness. By keeping it the same in all tests, it
+ * is easier to read and understand someone else's test, as well as insuring
+ * that all tests behave correctly with the test harness. There is a section
+ * following this for test-defined classes
+ * ****************************************************
+ */
+ private static boolean theTestPassed = false;
+ private static boolean testGeneratedInterrupt = false;
+ private static String failureMessage = "";
+ private static Thread mainThread = null;
+ final private static int sleepTime = 300000;
+
+ public static void main(String args[]) throws Exception {
+ mainThread = Thread.currentThread();
+ try {
+ init();
+ initTestWindow();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ try {
+ mainThread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ dispose();
+ if (testGeneratedInterrupt && !theTestPassed) {
+ throw new Exception(failureMessage);
+ }
+ }
+ if (!testGeneratedInterrupt) {
+ dispose();
+ throw new RuntimeException("Timed out after " + sleepTime / 1000
+ + " seconds");
+ }
+ }
+
+ public static synchronized void pass() {
+ theTestPassed = true;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ public static synchronized void fail(String whyFailed) {
+ theTestPassed = false;
+ testGeneratedInterrupt = true;
+ failureMessage = whyFailed;
+ mainThread.interrupt();
+ }
+}
+
+// *********** End Standard Test Machinery Section **********
+/**
+ * **************************************************
+ * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk
+ * of code whose purpose is to make user interaction uniform, and thereby make
+ * it simpler to read and understand someone else's test.
+ * **************************************************
+ */
+/**
+ * This is part of the standard test machinery. It creates a dialog (with the
+ * instructions), and is the interface for sending text messages to the user. To
+ * print the instructions, send an array of strings to Sysout.createDialog
+ * WithInstructions method. Put one line of instructions per array entry. To
+ * display a message for the tester to see, simply call Sysout.println with the
+ * string to be displayed. This mimics System.out.println but works within the
+ * test harness as well as standalone.
+ */
+class Sysout {
+
+ private static TestDialog dialog;
+ private static Frame frame;
+
+ public static void createDialog() {
+ frame = new Frame();
+ dialog = new TestDialog(frame, "Instructions");
+ String[] defInstr = {"Instructions will appear here. ", ""};
+ dialog.printInstructions(defInstr);
+ dialog.setVisible(true);
+ println("Any messages for the tester will display here.");
+ }
+
+ public static void printInstructions(String[] instructions) {
+ dialog.printInstructions(instructions);
+ }
+
+ public static void println(String messageIn) {
+ dialog.displayMessage(messageIn);
+ }
+
+ public static void dispose() {
+ dialog.dispose();
+ frame.dispose();
+ }
+}
+
+/**
+ * This is part of the standard test machinery. It provides a place for the test
+ * instructions to be displayed, and a place for interactive messages to the
+ * user to be displayed. To have the test instructions displayed, see Sysout. To
+ * have a message to the user be displayed, see Sysout. Do not call anything in
+ * this dialog directly.
+ */
+class TestDialog extends Dialog implements ActionListener {
+
+ TextArea instructionsText;
+ TextArea messageText;
+ int maxStringLength = 80;
+ Panel buttonP;
+ Button failB;
+ Button passB;
+
+ // DO NOT call this directly, go through Sysout
+ public TestDialog(Frame frame, String name) {
+ super(frame, name);
+ int scrollBoth = TextArea.SCROLLBARS_BOTH;
+ instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
+ add("North", instructionsText);
+
+ messageText = new TextArea("", 5, maxStringLength, scrollBoth);
+ add("Center", messageText);
+
+ buttonP = new Panel();
+ failB = new Button("Fail");
+ failB.setActionCommand("fail");
+ failB.addActionListener(this);
+ passB = new Button("Pass");
+ buttonP.add(passB);
+ buttonP.add(failB);
+ passB.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ ReconnectTest.pass();
+ }
+ });
+
+ add("South", buttonP);
+ pack();
+ setVisible(true);
+ }
+
+ // DO NOT call this directly, go through Sysout
+ public void printInstructions(String[] instructions) {
+ instructionsText.setText("");
+ String printStr, remainingStr;
+ for (int i = 0; i < instructions.length; i++) {
+ remainingStr = instructions[i];
+ while (remainingStr.length() > 0) {
+ if (remainingStr.length() >= maxStringLength) {
+ int posOfSpace = remainingStr.
+ lastIndexOf(' ', maxStringLength - 1);
+
+ if (posOfSpace <= 0) {
+ posOfSpace = maxStringLength - 1;
+ }
+
+ printStr = remainingStr.substring(0, posOfSpace + 1);
+ remainingStr = remainingStr.substring(posOfSpace + 1);
+ } else {
+ printStr = remainingStr;
+ remainingStr = "";
+ }
+ instructionsText.append(printStr + "\n");
+ }
+ }
+ }
+
+ public void displayMessage(String messageIn) {
+ messageText.append(messageIn + "\n");
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand() == "fail") {
+ ReconnectTest.fail("User Clicked Fail");
+ }
+ }
+}
diff --git a/test/java/awt/image/DrawImage/IncorrectManagedImageSourceOffset.java b/test/java/awt/image/DrawImage/IncorrectManagedImageSourceOffset.java
new file mode 100644
index 0000000000..5c5180e00b
--- /dev/null
+++ b/test/java/awt/image/DrawImage/IncorrectManagedImageSourceOffset.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2014, 2019, 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.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import sun.awt.image.SunWritableRaster;
+
+import static java.awt.Transparency.BITMASK;
+import static java.awt.Transparency.OPAQUE;
+import static java.awt.Transparency.TRANSLUCENT;
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
+import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+import static java.awt.image.BufferedImage.TYPE_CUSTOM;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
+import static java.awt.image.BufferedImage.TYPE_INT_BGR;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8029253 6207877
+ * @summary Tests asymmetric source offsets when managed image is drawn to VI.
+ * Results of the blit to compatibleImage are used for comparison.
+ * @author Sergey Bylokhov
+ * @modules java.desktop/sun.awt.image
+ * @run main/othervm -Dsun.java2d.accthreshold=0 IncorrectManagedImageSourceOffset
+ * @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=1 IncorrectManagedImageSourceOffset
+ * @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=2 IncorrectManagedImageSourceOffset
+ */
+public final class IncorrectManagedImageSourceOffset {
+
+ // See the same test for unmanaged images: IncorrectUnmanagedImageSourceOffset
+
+ private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
+ TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
+ TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
+ TYPE_4BYTE_ABGR_PRE,
+ /*TYPE_USHORT_565_RGB,
+ TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
+ TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
+ TYPE_BYTE_INDEXED, TYPE_CUSTOM};
+ private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
+
+ public static void main(final String[] args) throws IOException {
+ for (final int viType : TRANSPARENCIES) {
+ for (final int biType : TYPES) {
+ BufferedImage bi = makeManagedBI(biType);
+ fill(bi);
+ test(bi, viType);
+ }
+ }
+ }
+
+ private static void test(BufferedImage bi, int type)
+ throws IOException {
+ GraphicsEnvironment ge = GraphicsEnvironment
+ .getLocalGraphicsEnvironment();
+ GraphicsConfiguration gc = ge.getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ VolatileImage vi = gc.createCompatibleVolatileImage(511, 255, type);
+ BufferedImage gold = gc.createCompatibleImage(511, 255, type);
+ // draw to compatible Image
+ Graphics2D big = gold.createGraphics();
+ // force scaled blit
+ big.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
+ big.dispose();
+ // draw to volatile image
+ BufferedImage snapshot;
+ while (true) {
+ vi.validate(gc);
+ if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ Graphics2D vig = vi.createGraphics();
+ // force scaled blit
+ vig.drawImage(bi, 7, 11, 127, 111, 7, 11, 127 * 2, 111, null);
+ vig.dispose();
+ snapshot = vi.getSnapshot();
+ if (vi.contentsLost()) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ break;
+ }
+ // validate images
+ for (int x = 7; x < 127; ++x) {
+ for (int y = 11; y < 111; ++y) {
+ if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
+ ImageIO.write(gold, "png", new File("gold.png"));
+ ImageIO.write(snapshot, "png", new File("bi.png"));
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ }
+ }
+
+ private static BufferedImage makeManagedBI(final int type) {
+ final BufferedImage bi;
+ if (type == TYPE_CUSTOM) {
+ bi = makeCustomManagedBI();
+ } else {
+ bi = new BufferedImage(511, 255, type);
+ }
+ bi.setAccelerationPriority(1.0f);
+ return bi;
+ }
+
+ /**
+ * Returns the custom buffered image, which mostly identical to
+ * BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
+ * This means that the raster will have gaps, between the rows.
+ */
+ private static BufferedImage makeCustomManagedBI() {
+ int w = 511, h = 255;
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = {8, 8, 8};
+ int[] bOffs = {2, 1, 0};
+ ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+ w * 3 + 2, 3, bOffs, null);
+ BufferedImage bi = new BufferedImage(colorModel, raster, true, null);
+ SunWritableRaster.makeTrackable(raster.getDataBuffer());
+ SunWritableRaster.markDirty(bi);
+ return bi;
+ }
+
+ private static void fill(final Image image) {
+ final Graphics2D graphics = (Graphics2D) image.getGraphics();
+ graphics.setComposite(AlphaComposite.Src);
+ for (int i = 0; i < image.getHeight(null); ++i) {
+ graphics.setColor(new Color(i, 0, 0));
+ graphics.fillRect(0, i, image.getWidth(null), 1);
+ }
+ graphics.dispose();
+ }
+}
diff --git a/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java b/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java
index 98cbcd44fa..d0c49c9468 100644
--- a/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java
+++ b/test/java/awt/image/DrawImage/IncorrectUnmanagedImageSourceOffset.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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,29 +27,52 @@ import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DataBufferShort;
+import java.awt.image.Raster;
import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
-import static java.awt.Transparency.*;
-import static java.awt.image.BufferedImage.*;
+import static java.awt.Transparency.BITMASK;
+import static java.awt.Transparency.OPAQUE;
+import static java.awt.Transparency.TRANSLUCENT;
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
+import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+import static java.awt.image.BufferedImage.TYPE_CUSTOM;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
+import static java.awt.image.BufferedImage.TYPE_INT_BGR;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
/**
* @test
- * @bug 8029253
+ * @key headful
+ * @bug 8029253 6207877
* @summary Tests asymmetric source offsets when unmanaged image is drawn to VI.
* Results of the blit to compatibleImage are used for comparison.
* @author Sergey Bylokhov
+ * @run main/othervm IncorrectUnmanagedImageSourceOffset
+ * @run main/othervm -Dsun.java2d.uiScale=1 IncorrectUnmanagedImageSourceOffset
+ * @run main/othervm -Dsun.java2d.uiScale=2 IncorrectUnmanagedImageSourceOffset
*/
public final class IncorrectUnmanagedImageSourceOffset {
+ // See the same test for managed images: IncorrectManagedImageSourceOffset
+
private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
@@ -57,7 +80,7 @@ public final class IncorrectUnmanagedImageSourceOffset {
/*TYPE_USHORT_565_RGB,
TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
- TYPE_BYTE_INDEXED};
+ TYPE_BYTE_INDEXED, TYPE_CUSTOM};
private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
public static void main(final String[] args) throws IOException {
@@ -121,7 +144,12 @@ public final class IncorrectUnmanagedImageSourceOffset {
}
private static BufferedImage makeUnmanagedBI(final int type) {
- final BufferedImage bi = new BufferedImage(511, 255, type);
+ final BufferedImage bi;
+ if (type == TYPE_CUSTOM) {
+ bi = makeCustomUnmanagedBI();
+ } else {
+ bi = new BufferedImage(511, 255, type);
+ }
final DataBuffer db = bi.getRaster().getDataBuffer();
if (db instanceof DataBufferInt) {
((DataBufferInt) db).getData();
@@ -129,15 +157,30 @@ public final class IncorrectUnmanagedImageSourceOffset {
((DataBufferShort) db).getData();
} else if (db instanceof DataBufferByte) {
((DataBufferByte) db).getData();
- } else {
- try {
- bi.setAccelerationPriority(0.0f);
- } catch (final Throwable ignored) {
- }
}
+ bi.setAccelerationPriority(0.0f);
return bi;
}
+ /**
+ * Returns the custom buffered image, which mostly identical to
+ * BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
+ * This means that the raster will have gaps, between the rows.
+ */
+ private static BufferedImage makeCustomUnmanagedBI() {
+ int w = 511, h = 255;
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = {8, 8, 8};
+ int[] bOffs = {2, 1, 0};
+ ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+ w * 3 + 2, 3, bOffs, null);
+ return new BufferedImage(colorModel, raster, true, null);
+ }
+
private static void fill(final Image image) {
final Graphics2D graphics = (Graphics2D) image.getGraphics();
graphics.setComposite(AlphaComposite.Src);
diff --git a/test/java/awt/image/DrawImage/SimpleManagedImage.java b/test/java/awt/image/DrawImage/SimpleManagedImage.java
new file mode 100644
index 0000000000..e0fefa7430
--- /dev/null
+++ b/test/java/awt/image/DrawImage/SimpleManagedImage.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014, 2019, 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.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.Raster;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import sun.awt.image.SunWritableRaster;
+
+import static java.awt.Transparency.BITMASK;
+import static java.awt.Transparency.OPAQUE;
+import static java.awt.Transparency.TRANSLUCENT;
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
+import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+import static java.awt.image.BufferedImage.TYPE_CUSTOM;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
+import static java.awt.image.BufferedImage.TYPE_INT_BGR;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8029253 6207877
+ * @summary Tests the case when managed image is drawn to VI.
+ * Results of the blit to compatibleImage are used for comparison.
+ * @author Sergey Bylokhov
+ * @modules java.desktop/sun.awt.image
+ * @run main/othervm -Dsun.java2d.accthreshold=0 SimpleManagedImage
+ * @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=1 SimpleManagedImage
+ * @run main/othervm -Dsun.java2d.accthreshold=0 -Dsun.java2d.uiScale=2 SimpleManagedImage
+ */
+public final class SimpleManagedImage {
+
+ // See the same test for unmanaged images: SimpleUnmanagedImage
+
+ private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
+ TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
+ TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
+ TYPE_4BYTE_ABGR_PRE,
+ /*TYPE_USHORT_565_RGB,
+ TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
+ TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
+ TYPE_BYTE_INDEXED, TYPE_CUSTOM};
+ private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
+
+ public static void main(final String[] args) throws IOException {
+ for (final int viType : TRANSPARENCIES) {
+ for (final int biType : TYPES) {
+ BufferedImage bi = makeManagedBI(biType);
+ fill(bi);
+ test(bi, viType);
+ }
+ }
+ }
+
+ private static void test(BufferedImage bi, int type)
+ throws IOException {
+ GraphicsEnvironment ge = GraphicsEnvironment
+ .getLocalGraphicsEnvironment();
+ GraphicsConfiguration gc = ge.getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ VolatileImage vi = gc.createCompatibleVolatileImage(1000, 1000, type);
+ BufferedImage gold = gc.createCompatibleImage(1000, 1000, type);
+ // draw to compatible Image
+ init(gold);
+ Graphics2D big = gold.createGraphics();
+ big.drawImage(bi, 7, 11, null);
+ big.dispose();
+ // draw to volatile image
+ BufferedImage snapshot;
+ while (true) {
+ vi.validate(gc);
+ if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ init(vi);
+ Graphics2D vig = vi.createGraphics();
+ vig.drawImage(bi, 7, 11, null);
+ vig.dispose();
+ snapshot = vi.getSnapshot();
+ if (vi.contentsLost()) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ break;
+ }
+ // validate images
+ for (int x = 0; x < 1000; ++x) {
+ for (int y = 0; y < 1000; ++y) {
+ if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
+ ImageIO.write(gold, "png", new File("gold.png"));
+ ImageIO.write(snapshot, "png", new File("bi.png"));
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ }
+ }
+
+ private static BufferedImage makeManagedBI(final int type) {
+ final BufferedImage bi;
+ if (type == TYPE_CUSTOM) {
+ bi = makeCustomManagedBI();
+ } else {
+ bi = new BufferedImage(511, 255, type);
+ }
+ bi.setAccelerationPriority(1.0f);
+ return bi;
+ }
+
+ /**
+ * Returns the custom buffered image, which mostly identical to
+ * BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
+ * This means that the raster will have gaps, between the rows.
+ */
+ private static BufferedImage makeCustomManagedBI() {
+ int w = 511, h = 255;
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = {8, 8, 8};
+ int[] bOffs = {2, 1, 0};
+ ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+ w * 3 + 2, 3, bOffs, null);
+ BufferedImage bi = new BufferedImage(colorModel, raster, true, null);
+ SunWritableRaster.makeTrackable(raster.getDataBuffer());
+ SunWritableRaster.markDirty(bi);
+ return bi;
+ }
+
+ private static void init(final Image image) {
+ final Graphics2D graphics = (Graphics2D) image.getGraphics();
+ graphics.setComposite(AlphaComposite.Src);
+ graphics.setColor(new Color(0, 0, 0, 0));
+ graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
+ graphics.dispose();
+ }
+
+ private static void fill(final Image image) {
+ final Graphics2D graphics = (Graphics2D) image.getGraphics();
+ graphics.setComposite(AlphaComposite.Src);
+ for (int i = 0; i < image.getHeight(null); ++i) {
+ graphics.setColor(new Color(i, 0, 0));
+ graphics.fillRect(0, i, image.getWidth(null), 1);
+ }
+ graphics.dispose();
+ }
+}
diff --git a/test/java/awt/image/DrawImage/SimpleUnmanagedImage.java b/test/java/awt/image/DrawImage/SimpleUnmanagedImage.java
new file mode 100644
index 0000000000..0192124946
--- /dev/null
+++ b/test/java/awt/image/DrawImage/SimpleUnmanagedImage.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2014, 2019, 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.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorModel;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+import java.awt.image.DataBufferByte;
+import java.awt.image.DataBufferInt;
+import java.awt.image.DataBufferShort;
+import java.awt.image.Raster;
+import java.awt.image.VolatileImage;
+import java.awt.image.WritableRaster;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import static java.awt.Transparency.BITMASK;
+import static java.awt.Transparency.OPAQUE;
+import static java.awt.Transparency.TRANSLUCENT;
+import static java.awt.image.BufferedImage.TYPE_3BYTE_BGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR;
+import static java.awt.image.BufferedImage.TYPE_4BYTE_ABGR_PRE;
+import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
+import static java.awt.image.BufferedImage.TYPE_BYTE_INDEXED;
+import static java.awt.image.BufferedImage.TYPE_CUSTOM;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB_PRE;
+import static java.awt.image.BufferedImage.TYPE_INT_BGR;
+import static java.awt.image.BufferedImage.TYPE_INT_RGB;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8029253 6207877
+ * @summary Tests the case when unmanaged image is drawn to VI.
+ * Results of the blit to compatibleImage are used for comparison.
+ * @author Sergey Bylokhov
+ * @run main/othervm SimpleUnmanagedImage
+ * @run main/othervm -Dsun.java2d.uiScale=1 SimpleUnmanagedImage
+ * @run main/othervm -Dsun.java2d.uiScale=2 SimpleUnmanagedImage
+ */
+public final class SimpleUnmanagedImage {
+
+ // See the same test for managed images: SimpleManagedImage
+
+ private static final int[] TYPES = {TYPE_INT_RGB, TYPE_INT_ARGB,
+ TYPE_INT_ARGB_PRE, TYPE_INT_BGR,
+ TYPE_3BYTE_BGR, TYPE_4BYTE_ABGR,
+ TYPE_4BYTE_ABGR_PRE,
+ /*TYPE_USHORT_565_RGB,
+ TYPE_USHORT_555_RGB, TYPE_BYTE_GRAY,
+ TYPE_USHORT_GRAY,*/ TYPE_BYTE_BINARY,
+ TYPE_BYTE_INDEXED, TYPE_CUSTOM};
+ private static final int[] TRANSPARENCIES = {OPAQUE, BITMASK, TRANSLUCENT};
+
+ public static void main(final String[] args) throws IOException {
+ for (final int viType : TRANSPARENCIES) {
+ for (final int biType : TYPES) {
+ BufferedImage bi = makeUnmanagedBI(biType);
+ fill(bi);
+ test(bi, viType);
+ }
+ }
+ }
+
+ private static void test(BufferedImage bi, int type)
+ throws IOException {
+ GraphicsEnvironment ge = GraphicsEnvironment
+ .getLocalGraphicsEnvironment();
+ GraphicsConfiguration gc = ge.getDefaultScreenDevice()
+ .getDefaultConfiguration();
+ VolatileImage vi = gc.createCompatibleVolatileImage(1000, 1000, type);
+ BufferedImage gold = gc.createCompatibleImage(1000, 1000, type);
+ // draw to compatible Image
+ init(gold);
+ Graphics2D big = gold.createGraphics();
+ big.drawImage(bi, 7, 11, null);
+ big.dispose();
+ // draw to volatile image
+ BufferedImage snapshot;
+ while (true) {
+ vi.validate(gc);
+ if (vi.validate(gc) != VolatileImage.IMAGE_OK) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ init(vi);
+ Graphics2D vig = vi.createGraphics();
+ vig.drawImage(bi, 7, 11, null);
+ vig.dispose();
+ snapshot = vi.getSnapshot();
+ if (vi.contentsLost()) {
+ try {
+ Thread.sleep(100);
+ } catch (final InterruptedException ignored) {
+ }
+ continue;
+ }
+ break;
+ }
+ // validate images
+ for (int x = 0; x < 1000; ++x) {
+ for (int y = 0; y < 1000; ++y) {
+ if (gold.getRGB(x, y) != snapshot.getRGB(x, y)) {
+ ImageIO.write(gold, "png", new File("gold.png"));
+ ImageIO.write(snapshot, "png", new File("bi.png"));
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ }
+ }
+
+ private static BufferedImage makeUnmanagedBI(final int type) {
+ final BufferedImage bi;
+ if (type == TYPE_CUSTOM) {
+ bi = makeCustomUnmanagedBI();
+ } else {
+ bi = new BufferedImage(511, 255, type);
+ }
+ final DataBuffer db = bi.getRaster().getDataBuffer();
+ if (db instanceof DataBufferInt) {
+ ((DataBufferInt) db).getData();
+ } else if (db instanceof DataBufferShort) {
+ ((DataBufferShort) db).getData();
+ } else if (db instanceof DataBufferByte) {
+ ((DataBufferByte) db).getData();
+ }
+ bi.setAccelerationPriority(0.0f);
+ return bi;
+ }
+
+ /**
+ * Returns the custom buffered image, which mostly identical to
+ * BufferedImage.(w,h,TYPE_3BYTE_BGR), but uses the bigger scanlineStride.
+ * This means that the raster will have gaps, between the rows.
+ */
+ private static BufferedImage makeCustomUnmanagedBI() {
+ int w = 511, h = 255;
+ ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+ int[] nBits = {8, 8, 8};
+ int[] bOffs = {2, 1, 0};
+ ColorModel colorModel = new ComponentColorModel(cs, nBits, false, false,
+ Transparency.OPAQUE,
+ DataBuffer.TYPE_BYTE);
+ WritableRaster raster =
+ Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, w, h,
+ w * 3 + 2, 3, bOffs, null);
+ return new BufferedImage(colorModel, raster, true, null);
+ }
+
+ private static void init(final Image image) {
+ final Graphics2D graphics = (Graphics2D) image.getGraphics();
+ graphics.setComposite(AlphaComposite.Src);
+ graphics.setColor(new Color(0, 0, 0, 0));
+ graphics.fillRect(0, 0, image.getWidth(null), image.getHeight(null));
+ graphics.dispose();
+ }
+
+ private static void fill(final Image image) {
+ final Graphics2D graphics = (Graphics2D) image.getGraphics();
+ graphics.setComposite(AlphaComposite.Src);
+ for (int i = 0; i < image.getHeight(null); ++i) {
+ graphics.setColor(new Color(i, 0, 0));
+ graphics.fillRect(0, i, image.getWidth(null), 1);
+ }
+ graphics.dispose();
+ }
+}
diff --git a/test/java/io/FilePermission/Invalid.java b/test/java/io/FilePermission/Invalid.java
new file mode 100644
index 0000000000..261f25e80a
--- /dev/null
+++ b/test/java/io/FilePermission/Invalid.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, 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 8167646
+ * @summary Better invalid FilePermission
+ * @library /lib/testlibrary
+ */
+
+import jdk.testlibrary.Asserts;
+
+import java.io.FilePermission;
+
+public class Invalid {
+
+ public static void main(String args[]) throws Exception {
+
+ // Normal
+ FilePermission fp = new FilePermission("a", "read");
+
+ // Invalid
+ FilePermission fp1 = new FilePermission("a\000", "read");
+ FilePermission fp2 = new FilePermission("a\000", "read");
+ FilePermission fp3 = new FilePermission("b\000", "read");
+
+ // Invalid equals to itself
+ Asserts.assertEQ(fp1, fp1);
+
+ // and not equals to anything else, including other invalid ones
+ Asserts.assertNE(fp, fp1);
+ Asserts.assertNE(fp1, fp);
+ Asserts.assertNE(fp1, fp2);
+ Asserts.assertNE(fp1, fp3);
+
+ // Invalid implies itself
+ Asserts.assertTrue(fp1.implies(fp1));
+
+ // and not implies or implied by anything else, including other
+ // invalid ones
+ Asserts.assertFalse(fp.implies(fp1));
+ Asserts.assertFalse(fp1.implies(fp));
+ Asserts.assertFalse(fp1.implies(fp2));
+ Asserts.assertFalse(fp1.implies(fp3));
+ }
+}
diff --git a/test/java/io/LineNumberReader/MarkSplitCRLF.java b/test/java/io/LineNumberReader/MarkSplitCRLF.java
new file mode 100644
index 0000000000..d735e78f68
--- /dev/null
+++ b/test/java/io/LineNumberReader/MarkSplitCRLF.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019, 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 8218280
+ * @summary Make sure marking a line feed within a CRLF sequence works correctly
+ * @run testng MarkSplitCRLF
+ */
+
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class MarkSplitCRLF {
+ @Test
+ public static void testSpecifiedBufferSize() throws IOException {
+ final String string = "foo\r\nbar";
+ try (Reader reader =
+ new LineNumberReader(new StringReader(string), 5)) {
+ reader.read(); // 'f'
+ reader.read(); // 'o'
+ reader.read(); // 'o'
+ reader.read(); // '\r' -> '\n'
+ reader.mark(1); // mark position of '\n'
+ reader.read(); // 'b'
+ reader.reset(); // reset to '\n' position
+ assertEquals(reader.read(), 'b');
+ assertEquals(reader.read(), 'a');
+ assertEquals(reader.read(), 'r');
+ }
+ }
+
+ @Test
+ public static void testCRNotFollowedByLF() throws IOException {
+ final String string = "foo\rbar";
+ try (Reader reader =
+ new LineNumberReader(new StringReader(string), 5)) {
+ reader.read(); // 'f'
+ reader.read(); // 'o'
+ reader.read(); // 'o'
+ reader.read(); // '\r'
+ reader.mark(1); // mark position of next character
+ reader.read(); // 'b'
+ reader.reset(); // reset to position after '\r'
+ assertEquals(reader.read(), 'b');
+ assertEquals(reader.read(), 'a');
+ assertEquals(reader.read(), 'r');
+ }
+ }
+
+ @Test
+ public static void testDefaultBufferSize() throws IOException {
+ StringBuilder sb = new StringBuilder(8195);
+ for (int i = 0; i < 8190; i++) {
+ char c = (char)i;
+ sb.append(c);
+ }
+ sb.append('\r');
+ sb.append('\n');
+ sb.append('X');
+ sb.append('Y');
+ sb.append('Z');
+ final String string = sb.toString();
+ try (Reader reader = new LineNumberReader(new StringReader(string))) {
+ for (int i = 0; i < 8191; i++) reader.read();
+ reader.mark(1);
+ reader.read();
+ reader.reset();
+ assertEquals(reader.read(), 'X');
+ assertEquals(reader.read(), 'Y');
+ assertEquals(reader.read(), 'Z');
+ }
+ }
+}
diff --git a/test/java/lang/ClassLoader/forNameLeak/ClassForName.java b/test/java/lang/ClassLoader/forNameLeak/ClassForName.java
new file mode 100644
index 0000000000..584728800f
--- /dev/null
+++ b/test/java/lang/ClassLoader/forNameLeak/ClassForName.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, 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.net.URLClassLoader;
+
+/*
+ * This class is loaded by the custom URLClassLoader, and then calls
+ * Class.forName();
+ */
+public class ClassForName implements Runnable {
+ static {
+ if (!(ClassForName.class.getClassLoader() instanceof URLClassLoader)) {
+ throw new RuntimeException("Supposed to be loaded by URLClassLoader");
+ }
+ }
+
+ public void run() {
+ try {
+ Class.forName(java.util.List.class.getName(), false,
+ ClassLoader.getSystemClassLoader());
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java b/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
new file mode 100644
index 0000000000..d243103bd4
--- /dev/null
+++ b/test/java/lang/ClassLoader/forNameLeak/ClassForNameLeak.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2016, 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 8151486
+ * @summary Call Class.forName() on the system classloader from a class loaded
+ * from a custom classloader.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Utils jdk.testlibrary.JarUtils
+ * @build ClassForName ClassForNameLeak
+ * @run main/othervm/policy=test.policy -Djava.security.manager ClassForNameLeak
+ */
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import jdk.testlibrary.Utils;
+import jdk.testlibrary.JarUtils;
+
+/*
+ * Create .jar, load ClassForName from .jar using a URLClassLoader
+ */
+public class ClassForNameLeak {
+ private static final long TIMEOUT = (long)(5000.0 * Utils.TIMEOUT_FACTOR);
+ private static final String TESTCLASSES = System.getProperty("test.classes", ".");
+ private static final String CLASSFILENAME = "ClassForName.class";
+ private static final int THREADS = 10;
+ private static final ReferenceQueue<ClassLoader> rq = new ReferenceQueue<>();
+
+ // Use a new classloader to load the ClassForName class, then run its
+ // Runnable.
+ public static PhantomReference<ClassLoader> loadAndRun(Path jarFilePath)
+ throws Exception {
+ ClassLoader classLoader = new URLClassLoader(
+ new URL[]{jarFilePath.toUri().toURL()}) {
+ @Override public String toString() { return "LeakedClassLoader"; }
+ };
+
+ Class<?> loadClass = Class.forName("ClassForName", true, classLoader);
+ ((Runnable) loadClass.newInstance()).run();
+
+ PhantomReference<ClassLoader> ref = new PhantomReference<>(classLoader, rq);
+ System.out.println("returning phantom ref: " + ref + " to " + classLoader);
+ return ref;
+ }
+
+ public static void main(final String[] args) throws Exception {
+ Path classFile = FileSystems.getDefault().getPath(TESTCLASSES,
+ CLASSFILENAME);
+
+ // Create a temporary .jar file containing ClassForName.class
+ Path testClassesDir = Paths.get(TESTCLASSES);
+ Path jarFilePath = Files.createTempFile("cfn", ".jar");
+ JarUtils.createJarFile(jarFilePath, testClassesDir, classFile);
+ jarFilePath.toFile().deleteOnExit();
+
+ // Remove the ClassForName.class file that jtreg built, to make sure
+ // we're loading from the tmp .jar
+ Files.delete(classFile);
+
+ // Make simultaneous calls to the test method, to stress things a bit
+ ExecutorService es = Executors.newFixedThreadPool(THREADS);
+
+ List<Callable<PhantomReference<ClassLoader>>> callables =
+ Stream.generate(() -> {
+ Callable<PhantomReference<ClassLoader>> cprcl = () -> {
+ return loadAndRun(jarFilePath);
+ };
+ return cprcl;
+ }).limit(THREADS).collect(Collectors.toList());
+
+ List<Future<PhantomReference<ClassLoader>>> refs = es.invokeAll(callables);
+
+ // Give the GC a chance to enqueue the PhantomReferences
+ for (int i = 0; i < 10; i++) {
+ System.gc();
+ }
+ // Make sure all PhantomReferences to the leaked classloader are enqueued
+ for (int j = 0; j < THREADS; j++) {
+ Reference rmRef = rq.remove(TIMEOUT);
+ if (rmRef == null) {
+ throw new RuntimeException("ClassLoader was never enqueued!");
+ } else {
+ System.out.println("Enqueued " + rmRef);
+ }
+ }
+ System.out.println("All Classloaders successfully enqued");
+ }
+}
diff --git a/test/java/lang/ClassLoader/forNameLeak/test.policy b/test/java/lang/ClassLoader/forNameLeak/test.policy
new file mode 100644
index 0000000000..46145b9fa4
--- /dev/null
+++ b/test/java/lang/ClassLoader/forNameLeak/test.policy
@@ -0,0 +1,6 @@
+grant {
+ permission java.io.FilePermission "<<ALL FILES>>", "read, write, delete";
+ permission java.lang.RuntimePermission "createClassLoader";
+ permission java.lang.RuntimePermission "getClassLoader";
+ permission java.util.PropertyPermission "*", "read"; /* for Utils */
+};
diff --git a/test/java/lang/invoke/MethodHandlesProxiesTest.java b/test/java/lang/invoke/MethodHandlesProxiesTest.java
new file mode 100644
index 0000000000..3236705a6b
--- /dev/null
+++ b/test/java/lang/invoke/MethodHandlesProxiesTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018, 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 8206955
+ * @run testng/othervm -ea -esa test.java.lang.invoke.MethodHandlesProxiesTest
+ */
+
+package test.java.lang.invoke;
+
+import org.testng.annotations.Test;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleProxies;
+import java.lang.invoke.MethodHandles;
+
+import static org.testng.Assert.assertEquals;
+
+public class MethodHandlesProxiesTest {
+
+ public interface A {
+ default String a() {
+ return "A";
+ }
+ }
+
+ public interface B {
+ default String b() {
+ return "B";
+ }
+ }
+
+ public interface C extends A, B {
+ String f();
+
+ default String c() {
+ return "C";
+ }
+
+ default String concat() {
+ return a() + b() + c();
+ }
+ }
+
+ public interface Override extends C {
+ String f();
+
+ default String a() {
+ return "OA";
+ }
+
+ default String b() {
+ return "OB";
+ }
+
+ default String c() {
+ return "OC";
+ }
+ }
+
+ @Test
+ public static void testDefaultMethods() throws Throwable {
+ MethodHandle target = MethodHandles.constant(String.class, "F");
+ C proxy = MethodHandleProxies.asInterfaceInstance(C.class, target);
+
+ assertEquals(proxy.f(), "F");
+ assertEquals(proxy.a(), "A");
+ assertEquals(proxy.b(), "B");
+ assertEquals(proxy.c(), "C");
+ assertEquals(proxy.concat(), "ABC");
+ }
+
+ @Test
+ public static void testOverriddenDefaultMethods() throws Throwable {
+ MethodHandle target = MethodHandles.constant(String.class, "F");
+ Override proxy = MethodHandleProxies.asInterfaceInstance(Override.class, target);
+
+ assertEquals(proxy.a(), "OA");
+ assertEquals(proxy.b(), "OB");
+ assertEquals(proxy.c(), "OC");
+ }
+}
diff --git a/test/java/net/NetworkInterface/IPv4Only.java b/test/java/net/NetworkInterface/IPv4Only.java
index 4d0bc3d404..76bf0b867e 100644
--- a/test/java/net/NetworkInterface/IPv4Only.java
+++ b/test/java/net/NetworkInterface/IPv4Only.java
@@ -22,8 +22,8 @@
*/
/* @test
- * @bug 6964714
- * @run main/othervm IPv4Only
+ * @bug 6964714 8226928
+ * @run main/othervm -Djava.net.preferIPv4Stack=true IPv4Only
* @summary Test the networkinterface listing with java.net.preferIPv4Stack=true.
*/
@@ -34,8 +34,6 @@ import java.util.*;
public class IPv4Only {
public static void main(String[] args) throws Exception {
- System.setProperty("java.net.preferIPv4Stack","true");
-
Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
while (nifs.hasMoreElements()) {
NetworkInterface nif = nifs.nextElement();
diff --git a/test/java/net/Socket/asyncClose/AsyncClose.java b/test/java/net/Socket/asyncClose/AsyncClose.java
index db9dddf791..4de5d4851d 100644
--- a/test/java/net/Socket/asyncClose/AsyncClose.java
+++ b/test/java/net/Socket/asyncClose/AsyncClose.java
@@ -21,15 +21,17 @@
* questions.
*/
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import static java.util.concurrent.CompletableFuture.*;
+
/*
* @test
* @bug 4344135
* @summary Check that {Socket,ServerSocket,DatagramSocket}.close will
* cause any thread blocked on the socket to throw a SocketException.
- * @run main/timeout=60 AsyncClose
*/
-import java.net.*;
-import java.io.*;
public class AsyncClose {
@@ -37,34 +39,35 @@ public class AsyncClose {
AsyncCloseTest tests[] = {
new Socket_getInputStream_read(),
- new Socket_getInputStream_read(5000),
+ new Socket_getInputStream_read(20000),
new Socket_getOutputStream_write(),
new DatagramSocket_receive(),
- new DatagramSocket_receive(5000),
+ new DatagramSocket_receive(20000),
new ServerSocket_accept(),
- new ServerSocket_accept(5000),
+ new ServerSocket_accept(20000),
};
int failures = 0;
- for (int i=0; i<tests.length; i++) {
- AsyncCloseTest tst = tests[i];
+ List<CompletableFuture<AsyncCloseTest>> cfs = new ArrayList<>();
+ for (AsyncCloseTest test : tests)
+ cfs.add( supplyAsync(() -> test.go()));
- System.out.println("******************************");
- System.out.println("Test: " + tst.description());
+ for (CompletableFuture<AsyncCloseTest> cf : cfs) {
+ AsyncCloseTest test = cf.get();
- if (tst.go()) {
+ System.out.println("******************************");
+ System.out.println("Test: " + test.description());
+ if (test.hasPassed()) {
System.out.println("Passed.");
} else {
- System.out.println("Failed: " + tst.failureReason());
+ System.out.println("Failed: " + test.failureReason());
failures++;
}
System.out.println("");
-
}
- if (failures > 0) {
+ if (failures > 0)
throw new Exception(failures + " sub-tests failed - see log.");
- }
}
}
diff --git a/test/java/net/Socket/asyncClose/AsyncCloseTest.java b/test/java/net/Socket/asyncClose/AsyncCloseTest.java
index ef6fc43dd9..e7fd6fc597 100644
--- a/test/java/net/Socket/asyncClose/AsyncCloseTest.java
+++ b/test/java/net/Socket/asyncClose/AsyncCloseTest.java
@@ -29,11 +29,22 @@ public abstract class AsyncCloseTest {
public abstract String description();
- public abstract boolean go() throws Exception;
+ public abstract AsyncCloseTest go();
+ public synchronized boolean hasPassed() {
+ return passed;
+ }
+
+ protected synchronized AsyncCloseTest passed() {
+ if (reason == null)
+ passed = true;
+ return this;
+ }
- protected synchronized void failed(String reason) {
- this.reason = reason;
+ protected synchronized AsyncCloseTest failed(String r) {
+ passed = false;
+ reason = r;
+ return this;
}
public synchronized String failureReason() {
@@ -48,7 +59,7 @@ public abstract class AsyncCloseTest {
return closed;
}
+ private boolean passed;
private String reason;
private boolean closed;
-
}
diff --git a/test/java/net/Socket/asyncClose/DatagramSocket_receive.java b/test/java/net/Socket/asyncClose/DatagramSocket_receive.java
index b35ebdff8e..48a842e30d 100644
--- a/test/java/net/Socket/asyncClose/DatagramSocket_receive.java
+++ b/test/java/net/Socket/asyncClose/DatagramSocket_receive.java
@@ -26,20 +26,25 @@
* throws a SocketException if the socket is asynchronously closed.
*/
import java.net.*;
+import java.util.concurrent.CountDownLatch;
public class DatagramSocket_receive extends AsyncCloseTest implements Runnable {
- DatagramSocket s;
- int timeout = 0;
+ private final DatagramSocket s;
+ private final int timeout;
+ private final CountDownLatch latch;
- public DatagramSocket_receive() {
+ public DatagramSocket_receive() throws SocketException {
+ this(0);
}
- public DatagramSocket_receive(int timeout) {
+ public DatagramSocket_receive(int timeout) throws SocketException {
this.timeout = timeout;
+ latch = new CountDownLatch(1);
+ s = new DatagramSocket();
}
public String description() {
- String s = "DatagramSocket.receive";
+ String s = "DatagramSocket.receive(DatagramPacket)";
if (timeout > 0) {
s += " (timeout specified)";
}
@@ -47,46 +52,45 @@ public class DatagramSocket_receive extends AsyncCloseTest implements Runnable {
}
public void run() {
- DatagramPacket p;
try {
-
byte b[] = new byte[1024];
- p = new DatagramPacket(b, b.length);
-
+ DatagramPacket p = new DatagramPacket(b, b.length);
if (timeout > 0) {
s.setSoTimeout(timeout);
}
- } catch (Exception e) {
- failed(e.getMessage());
- return;
- }
-
- try {
+ latch.countDown();
s.receive(p);
+ failed("DatagramSocket.receive(DatagramPacket) returned unexpectly!!");
} catch (SocketException se) {
- closed();
+ if (latch.getCount() != 1) {
+ closed();
+ }
} catch (Exception e) {
failed(e.getMessage());
+ } finally {
+ if (latch.getCount() == 1) {
+ latch.countDown();
+ }
}
}
- public boolean go() throws Exception {
- s = new DatagramSocket();
-
- Thread thr = new Thread(this);
- thr.start();
-
- Thread.currentThread().sleep(1000);
-
- s.close();
-
- Thread.currentThread().sleep(1000);
+ public AsyncCloseTest go() {
+ try {
+ Thread thr = new Thread(this);
+ thr.start();
+ latch.await();
+ Thread.sleep(5000); //sleep, so receive(DatagramPacket) can block
+ s.close();
+ thr.join();
- if (isClosed()) {
- return true;
- } else {
- failed("DatagramSocket.receive wasn't preempted");
- return false;
+ if (isClosed()) {
+ return passed();
+ } else {
+ return failed("DatagramSocket.receive(DatagramPacket) wasn't preempted");
+ }
+ } catch (Exception x) {
+ failed(x.getMessage());
+ throw new RuntimeException(x);
}
}
}
diff --git a/test/java/net/Socket/asyncClose/Race.java b/test/java/net/Socket/asyncClose/Race.java
index 5a9585682f..3a7b7affee 100644
--- a/test/java/net/Socket/asyncClose/Race.java
+++ b/test/java/net/Socket/asyncClose/Race.java
@@ -30,6 +30,7 @@
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
+import java.net.ConnectException;
import java.net.SocketException;
import java.util.concurrent.Phaser;
@@ -43,33 +44,37 @@ public class Race {
final int port = ss.getLocalPort();
final Phaser phaser = new Phaser(THREADS + 1);
for (int i=0; i<100; i++) {
- final Socket s = new Socket("localhost", port);
- s.setSoLinger(false, 0);
- try (Socket sa = ss.accept()) {
- sa.setSoLinger(false, 0);
- final InputStream is = s.getInputStream();
- Thread[] threads = new Thread[THREADS];
- for (int j=0; j<THREADS; j++) {
- threads[j] = new Thread() {
- public void run() {
- try {
- phaser.arriveAndAwaitAdvance();
- while (is.read() != -1)
- Thread.sleep(50);
- } catch (Exception x) {
- if (!(x instanceof SocketException
- && x.getMessage().equalsIgnoreCase("socket closed")))
- x.printStackTrace();
- // ok, expect Socket closed
- }
- }};
+ try {
+ final Socket s = new Socket("localhost", port);
+ s.setSoLinger(false, 0);
+ try (Socket sa = ss.accept()) {
+ sa.setSoLinger(false, 0);
+ final InputStream is = s.getInputStream();
+ Thread[] threads = new Thread[THREADS];
+ for (int j=0; j<THREADS; j++) {
+ threads[j] = new Thread() {
+ public void run() {
+ try {
+ phaser.arriveAndAwaitAdvance();
+ while (is.read() != -1)
+ Thread.sleep(50);
+ } catch (Exception x) {
+ if (!(x instanceof SocketException
+ && x.getMessage().equalsIgnoreCase("socket closed")))
+ x.printStackTrace();
+ // ok, expect Socket closed
+ }
+ }};
+ }
+ for (int j=0; j<100; j++)
+ threads[j].start();
+ phaser.arriveAndAwaitAdvance();
+ s.close();
+ for (int j=0; j<100; j++)
+ threads[j].join();
}
- for (int j=0; j<100; j++)
- threads[j].start();
- phaser.arriveAndAwaitAdvance();
- s.close();
- for (int j=0; j<100; j++)
- threads[j].join();
+ } catch (ConnectException e) {
+ System.err.println("Exception " + e + " Port: " + port);
}
}
}
diff --git a/test/java/net/Socket/asyncClose/ServerSocket_accept.java b/test/java/net/Socket/asyncClose/ServerSocket_accept.java
index 07fbcc95ae..0461ba58f8 100644
--- a/test/java/net/Socket/asyncClose/ServerSocket_accept.java
+++ b/test/java/net/Socket/asyncClose/ServerSocket_accept.java
@@ -25,17 +25,23 @@
* Tests that a thread blocked in ServerSocket.accept
* throws a SocketException if the socket is asynchronously closed.
*/
+import java.io.IOException;
import java.net.*;
+import java.util.concurrent.CountDownLatch;
public class ServerSocket_accept extends AsyncCloseTest implements Runnable {
- ServerSocket ss;
- int timeout = 0;
+ private final ServerSocket ss;
+ private final int timeout;
+ private final CountDownLatch latch;
- public ServerSocket_accept() {
+ public ServerSocket_accept() throws IOException {
+ this(0);
}
- public ServerSocket_accept(int timeout) {
+ public ServerSocket_accept(int timeout) throws IOException {
this.timeout = timeout;
+ latch = new CountDownLatch(1);
+ ss = new ServerSocket(0);
}
public String description() {
@@ -48,7 +54,9 @@ public class ServerSocket_accept extends AsyncCloseTest implements Runnable {
public void run() {
try {
+ latch.countDown();
Socket s = ss.accept();
+ failed("ServerSocket.accept() returned unexpectly!!");
} catch (SocketException se) {
closed();
} catch (Exception e) {
@@ -56,23 +64,23 @@ public class ServerSocket_accept extends AsyncCloseTest implements Runnable {
}
}
- public boolean go() throws Exception {
- ss = new ServerSocket(0);
-
- Thread thr = new Thread(this);
- thr.start();
-
- Thread.currentThread().sleep(1000);
-
- ss.close();
-
- Thread.currentThread().sleep(1000);
+ public AsyncCloseTest go(){
+ try {
+ Thread thr = new Thread(this);
+ thr.start();
+ latch.await();
+ Thread.sleep(5000); //sleep, so ServerSocket.accept() can block
+ ss.close();
+ thr.join();
- if (isClosed()) {
- return true;
- } else {
- failed("ServerSocket.accept() wasn't preempted");
- return false;
+ if (isClosed()) {
+ return passed();
+ } else {
+ return failed("ServerSocket.accept() wasn't preempted");
+ }
+ } catch (Exception x) {
+ failed(x.getMessage());
+ throw new RuntimeException(x);
}
}
}
diff --git a/test/java/net/Socket/asyncClose/Socket_getInputStream_read.java b/test/java/net/Socket/asyncClose/Socket_getInputStream_read.java
index a4d76020cd..25f8589858 100644
--- a/test/java/net/Socket/asyncClose/Socket_getInputStream_read.java
+++ b/test/java/net/Socket/asyncClose/Socket_getInputStream_read.java
@@ -27,16 +27,21 @@
*/
import java.net.*;
import java.io.*;
+import java.util.concurrent.CountDownLatch;
public class Socket_getInputStream_read extends AsyncCloseTest implements Runnable {
- Socket s;
- int timeout = 0;
+ private final Socket s;
+ private final int timeout;
+ private final CountDownLatch latch;
public Socket_getInputStream_read() {
+ this(0);
}
public Socket_getInputStream_read(int timeout) {
this.timeout = timeout;
+ latch = new CountDownLatch(1);
+ s = new Socket();
}
public String description() {
@@ -48,53 +53,48 @@ public class Socket_getInputStream_read extends AsyncCloseTest implements Runnab
}
public void run() {
- InputStream in;
-
try {
- in = s.getInputStream();
+ InputStream in = s.getInputStream();
if (timeout > 0) {
s.setSoTimeout(timeout);
}
- } catch (Exception e) {
- failed(e.getMessage());
- return;
- }
-
- try {
+ latch.countDown();
int n = in.read();
- failed("getInptuStream().read() returned unexpectly!!");
+ failed("Socket.getInputStream().read() returned unexpectly!!");
} catch (SocketException se) {
- closed();
+ if (latch.getCount() != 1) {
+ closed();
+ }
} catch (Exception e) {
failed(e.getMessage());
+ } finally {
+ if (latch.getCount() == 1) {
+ latch.countDown();
+ }
}
}
- public boolean go() throws Exception {
-
- ServerSocket ss = new ServerSocket(0);
-
- InetAddress lh = InetAddress.getLocalHost();
- s = new Socket();
- s.connect( new InetSocketAddress(lh, ss.getLocalPort()) );
-
- Socket s2 = ss.accept();
-
- Thread thr = new Thread(this);
- thr.start();
-
- Thread.currentThread().sleep(1000);
-
- s.close();
-
- Thread.currentThread().sleep(1000);
-
- if (isClosed()) {
- return true;
- } else {
- failed("getInputStream().read() wasn't preempted");
- return false;
+ public AsyncCloseTest go() {
+ try {
+ ServerSocket ss = new ServerSocket(0);
+ InetAddress lh = InetAddress.getLocalHost();
+ s.connect( new InetSocketAddress(lh, ss.getLocalPort()) );
+ Socket s2 = ss.accept();
+ Thread thr = new Thread(this);
+ thr.start();
+ latch.await();
+ Thread.sleep(5000); //sleep, so Socket.getInputStream().read() can block
+ s.close();
+ thr.join();
+
+ if (isClosed()) {
+ return passed();
+ } else {
+ return failed("Socket.getInputStream().read() wasn't preempted");
+ }
+ } catch (Exception x) {
+ failed(x.getMessage());
+ throw new RuntimeException(x);
}
-
}
}
diff --git a/test/java/net/Socket/asyncClose/Socket_getOutputStream_write.java b/test/java/net/Socket/asyncClose/Socket_getOutputStream_write.java
index 841861d919..78cbf45014 100644
--- a/test/java/net/Socket/asyncClose/Socket_getOutputStream_write.java
+++ b/test/java/net/Socket/asyncClose/Socket_getOutputStream_write.java
@@ -27,9 +27,16 @@
*/
import java.net.*;
import java.io.*;
+import java.util.concurrent.CountDownLatch;
public class Socket_getOutputStream_write extends AsyncCloseTest implements Runnable {
- Socket s;
+ private final Socket s;
+ private final CountDownLatch latch;
+
+ public Socket_getOutputStream_write() {
+ latch = new CountDownLatch(1);
+ s = new Socket();
+ }
public String description() {
return "Socket.getOutputStream().write()";
@@ -38,40 +45,45 @@ public class Socket_getOutputStream_write extends AsyncCloseTest implements Runn
public void run() {
try {
OutputStream out = s.getOutputStream();
+ byte b[] = new byte[8192];
+ latch.countDown();
for (;;) {
- byte b[] = new byte[8192];
out.write(b);
}
} catch (SocketException se) {
- closed();
+ if (latch.getCount() != 1) {
+ closed();
+ }
} catch (Exception e) {
failed(e.getMessage());
+ } finally {
+ if (latch.getCount() == 1) {
+ latch.countDown();
+ }
}
}
- public boolean go() throws Exception {
- ServerSocket ss = new ServerSocket(0);
-
- InetAddress lh = InetAddress.getLocalHost();
- s = new Socket();
- s.connect( new InetSocketAddress(lh, ss.getLocalPort()) );
-
- Socket s2 = ss.accept();
-
- Thread thr = new Thread(this);
- thr.start();
-
- Thread.currentThread().sleep(2000);
-
- s.close();
-
- Thread.currentThread().sleep(2000);
+ public AsyncCloseTest go() {
+ try {
+ ServerSocket ss = new ServerSocket(0);
+ InetAddress lh = InetAddress.getLocalHost();
+ s.connect( new InetSocketAddress(lh, ss.getLocalPort()) );
+ Socket s2 = ss.accept();
+ Thread thr = new Thread(this);
+ thr.start();
+ latch.await();
+ Thread.sleep(1000);
+ s.close();
+ thr.join();
- if (isClosed()) {
- return true;
- } else {
- failed("getOutputStream().write() wasn't preempted");
- return false;
+ if (isClosed()) {
+ return passed();
+ } else {
+ return failed("Socket.getOutputStream().write() wasn't preempted");
+ }
+ } catch (Exception x) {
+ failed(x.getMessage());
+ throw new RuntimeException(x);
}
}
}
diff --git a/test/java/net/Socks/SocksIPv6Test.java b/test/java/net/Socks/SocksIPv6Test.java
new file mode 100644
index 0000000000..1b4dc82ff5
--- /dev/null
+++ b/test/java/net/Socks/SocksIPv6Test.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013, 2014, 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 7100957
+ * @summary Java doesn't correctly handle the SOCKS protocol when used over IPv6.
+ * @run testng SocksIPv6Test
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.Authenticator;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.net.Proxy;
+import java.lang.Override;
+import java.net.InetAddress;
+import java.net.Inet6Address;
+import java.net.ServerSocket;
+import java.net.SocketException;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.Collections;
+import java.util.List;
+import com.sun.net.httpserver.*;
+import java.io.BufferedWriter;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.*;
+
+public class SocksIPv6Test {
+
+ private HttpServer server;
+ private SocksServer socks;
+ private String response = "Hello.";
+ private static boolean shouldRun = false;
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ shouldRun = ensureInet6AddressFamily() && ensureIPv6OnLoopback();
+
+ server = HttpServer.create(new InetSocketAddress(0), 0);
+ server.createContext("/", ex -> {
+ ex.sendResponseHeaders(200, response.length());
+ try (BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(ex.getResponseBody(), "UTF-8"))) {
+ writer.write(response);
+ }
+ ex.close();
+ });
+ server.start();
+
+ socks = new SocksServer(0, false);
+ socks.addUser("user", "pass");
+ socks.start();
+
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected java.net.PasswordAuthentication getPasswordAuthentication() {
+ return new java.net.PasswordAuthentication(
+ "user", "pass".toCharArray());
+ }
+ });
+ }
+
+ private boolean ensureIPv6OnLoopback() throws Exception {
+ boolean ipv6 = false;
+
+ List<NetworkInterface> nics = Collections.list(NetworkInterface.getNetworkInterfaces());
+ for (NetworkInterface nic : nics) {
+ if (!nic.isLoopback()) {
+ continue;
+ }
+ List<InetAddress> addrs = Collections.list(nic.getInetAddresses());
+ for (InetAddress addr : addrs) {
+ if (addr instanceof Inet6Address) {
+ ipv6 = true;
+ break;
+ }
+ }
+ }
+ if (!ipv6)
+ System.out.println("IPv6 is not enabled on loopback. Skipping test suite.");
+ return ipv6;
+ }
+
+ private boolean ensureInet6AddressFamily() throws IOException {
+ try (ServerSocket s = new ServerSocket()) {
+ s.bind(new InetSocketAddress("::1", 0));
+ return true;
+ } catch (SocketException e) {
+ System.out.println("Inet 6 address family is not available. Skipping test suite.");
+ }
+ return false;
+ }
+
+ @Test(groups = "unit")
+ public void testSocksOverIPv6() throws Exception {
+ if (!shouldRun) return;
+
+ Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("::1",
+ socks.getPort()));
+ URL url = new URL("http://[::1]:" + server.getAddress().getPort());
+ java.net.URLConnection conn = url.openConnection(proxy);
+ String actual = "";
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(conn.getInputStream()))) {
+ actual = reader.readLine();
+ }
+ assertEquals(actual, response);
+ }
+
+ @Test(groups = "unit")
+ public void testSocksOverIPv6Hostname() throws Exception {
+ if (!shouldRun) return;
+
+ String ipv6Hostname = InetAddress.getByName("::1").getHostName();
+ String ipv4Hostname = InetAddress.getByName("127.0.0.1").getHostName();
+
+ if (ipv6Hostname.equals(InetAddress.getByName("::1").getHostAddress())) {
+ System.out.println("Unable to get the hostname of the IPv6 loopback "
+ + "address. Skipping test case.");
+ return;
+ }
+
+ if (ipv6Hostname.equals(ipv4Hostname)) {
+ System.out.println("IPv6 and IPv4 loopback addresses map to the"
+ + " same hostname. Skipping test case.");
+ return;
+ }
+
+ Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(ipv6Hostname,
+ socks.getPort()));
+ URL url = new URL("http://" + ipv6Hostname + ":" + server.getAddress().getPort());
+ java.net.URLConnection conn = url.openConnection(proxy);
+ String actual = "";
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(conn.getInputStream()))) {
+ actual = reader.readLine();
+ }
+ assertEquals(actual, response);
+ }
+
+ @AfterClass
+ public void tearDown() {
+ if (server != null) {
+ server.stop(1);
+ }
+ if (socks != null) {
+ socks.terminate();
+ }
+ }
+}
diff --git a/test/java/net/Socks/SocksServer.java b/test/java/net/Socks/SocksServer.java
index 6e27e342e9..f2d6ef82bf 100644
--- a/test/java/net/Socks/SocksServer.java
+++ b/test/java/net/Socks/SocksServer.java
@@ -89,6 +89,7 @@ public class SocksServer extends Thread {
return;
}
tout.write(b);
+ tout.flush();
} catch (IOException e) {
// actually exit from the thread
return;
@@ -99,8 +100,8 @@ public class SocksServer extends Thread {
ClientHandler(Socket s) throws IOException {
client = s;
- in = client.getInputStream();
- out = client.getOutputStream();
+ in = new BufferedInputStream(client.getInputStream());
+ out = new BufferedOutputStream(client.getOutputStream());
}
private void readBuf(InputStream is, byte[] buf) throws IOException {
@@ -230,8 +231,8 @@ public class SocksServer extends Thread {
out.write(port & 0xff);
out.write(buf);
out.flush();
- InputStream in2 = dest.getInputStream();
- OutputStream out2 = dest.getOutputStream();
+ InputStream in2 = new BufferedInputStream(dest.getInputStream());
+ OutputStream out2 = new BufferedOutputStream(dest.getOutputStream());
Tunnel tunnel = new Tunnel(in2, out);
tunnel.start();
@@ -246,6 +247,7 @@ public class SocksServer extends Thread {
return;
}
out2.write(b);
+ out2.flush();
} catch (IOException ex) {
}
} while (!client.isClosed());
@@ -323,8 +325,8 @@ public class SocksServer extends Thread {
out.write((addr.getPort() >> 0) & 0xff);
out.flush();
- InputStream in2 = dest.getInputStream();
- OutputStream out2 = dest.getOutputStream();
+ InputStream in2 = new BufferedInputStream(dest.getInputStream());
+ OutputStream out2 = new BufferedOutputStream(dest.getOutputStream());
Tunnel tunnel = new Tunnel(in2, out);
tunnel.start();
@@ -340,6 +342,7 @@ public class SocksServer extends Thread {
return;
}
out2.write(b);
+ out2.flush();
} catch(IOException ioe) {
}
} while (!client.isClosed());
@@ -384,6 +387,7 @@ public class SocksServer extends Thread {
return;
}
out2.write(b);
+ out2.flush();
} catch(IOException ioe) {
}
} while (!client.isClosed());
@@ -410,14 +414,7 @@ public class SocksServer extends Thread {
{
byte[] buf = new byte[4];
readBuf(in, buf);
- int i = 0;
- StringBuffer sb = new StringBuffer();
- for (i = 0; i < 4; i++) {
- sb.append(buf[i]&0xff);
- if (i < 3)
- sb.append('.');
- }
- addr = sb.toString();
+ addr = InetAddress.getByAddress(buf).getHostAddress();
}
break;
case DOMAIN_NAME:
@@ -432,14 +429,7 @@ public class SocksServer extends Thread {
{
byte[] buf = new byte[16];
readBuf(in, buf);
- int i = 0;
- StringBuffer sb = new StringBuffer();
- for (i = 0; i<16; i++) {
- sb.append(Integer.toHexString(buf[i]&0xff));
- if (i < 15)
- sb.append(':');
- }
- addr = sb.toString();
+ addr = InetAddress.getByAddress(buf).getHostAddress();
}
break;
}
diff --git a/test/java/net/ipv6tests/Tests.java b/test/java/net/ipv6tests/Tests.java
index 8f1793bb38..dd8679403e 100644
--- a/test/java/net/ipv6tests/Tests.java
+++ b/test/java/net/ipv6tests/Tests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -136,11 +136,17 @@ public class Tests {
/* check the time got is within 50% of the time expected */
public static void checkTime (long got, long expected) {
- dprintln ("checkTime: got " + got + " expected " + expected);
- long upper = expected + (expected / 2);
- long lower = expected - (expected / 2);
+ checkTime(got, expected, expected);
+ }
+
+ /* check the time got is between start and end, given 50% tolerance */
+ public static void checkTime(long got, long start, long end) {
+ dprintln("checkTime: got = " + got + " start = " + start + " end = " + end);
+ long upper = end + (end / 2);
+ long lower = start - (start / 2);
if (got > upper || got < lower) {
- throw new RuntimeException ("checkTime failed: got " + got + " expected " + expected);
+ throw new RuntimeException("checkTime failed: got " + got
+ + ", expected between " + start + " and " + end);
}
}
diff --git a/test/java/net/ipv6tests/UdpTest.java b/test/java/net/ipv6tests/UdpTest.java
index 8f91ade020..4b3f9b0270 100644
--- a/test/java/net/ipv6tests/UdpTest.java
+++ b/test/java/net/ipv6tests/UdpTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -147,6 +147,7 @@ public class UdpTest extends Tests {
final InetAddress ia6 = ia6addr;
final int port = s1.getLocalPort();
+ s1.setSoTimeout(10000);
runAfter (2000, new Runnable () {
public void run () {
try {
@@ -157,7 +158,7 @@ public class UdpTest extends Tests {
});
t1 = System.currentTimeMillis();
s1.receive (new DatagramPacket (new byte [128], 128));
- checkTime (System.currentTimeMillis() - t1, 2000);
+ checkTime (System.currentTimeMillis() - t1, 2000, 10000);
s1.close ();
s2.close ();
System.out.println ("Test2: OK");
diff --git a/test/java/nio/Buffer/Chars.java b/test/java/nio/Buffer/Chars.java
index e91b6a7388..ef2df66ac1 100644
--- a/test/java/nio/Buffer/Chars.java
+++ b/test/java/nio/Buffer/Chars.java
@@ -51,8 +51,8 @@ public class Chars {
*/
static CharBuffer randomizeRange(CharBuffer cb) {
int mid = cb.capacity() >>> 1;
- int start = RAND.nextInt(mid);
- int end = mid + RAND.nextInt(mid);
+ int start = RAND.nextInt(mid + 1); // from 0 to mid
+ int end = mid + RAND.nextInt(cb.capacity() - mid + 1); // from mid to capacity
cb.position(start);
cb.limit(end);
return cb;
diff --git a/test/java/nio/channels/AsynchronousChannelGroup/Basic.java b/test/java/nio/channels/AsynchronousChannelGroup/Basic.java
index 8c6b5cb702..1c5da1309b 100644
--- a/test/java/nio/channels/AsynchronousChannelGroup/Basic.java
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Basic.java
@@ -24,8 +24,6 @@
/* @test
* @bug 4607272
* @summary Unit test for AsynchronousChannelGroup
- * @build Basic
- * @run main/othervm -XX:-UseVMInterruptibleIO Basic
*/
import java.nio.ByteBuffer;
@@ -37,12 +35,9 @@ import java.io.IOException;
public class Basic {
static final Random rand = new Random();
- static final ThreadFactory threadFactory = new ThreadFactory() {
- @Override
- public Thread newThread(final Runnable r) {
- return new Thread(r);
- }};
-
+ static final ThreadFactory threadFactory = (Runnable r) -> {
+ return new Thread(r);
+ };
public static void main(String[] args) throws Exception {
shutdownTests();
@@ -51,6 +46,12 @@ public class Basic {
miscTests();
}
+ static void awaitTermination(AsynchronousChannelGroup group) throws InterruptedException {
+ boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
+ if (!terminated)
+ throw new RuntimeException("Group should have terminated");
+ }
+
static void testShutdownWithNoChannels(ExecutorService pool,
AsynchronousChannelGroup group)
throws Exception
@@ -59,9 +60,7 @@ public class Basic {
if (!group.isShutdown())
throw new RuntimeException("Group should be shutdown");
// group should terminate quickly
- boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
- if (!terminated)
- throw new RuntimeException("Group should have terminated");
+ awaitTermination(group);
if (pool != null && !pool.isTerminated())
throw new RuntimeException("Executor should have terminated");
}
@@ -86,9 +85,7 @@ public class Basic {
ch.close();
// group should terminate quickly
- boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
- if (!terminated)
- throw new RuntimeException("Group should have terminated");
+ awaitTermination(group);
if (pool != null && !pool.isTerminated())
throw new RuntimeException("Executor should have terminated");
}
@@ -153,9 +150,8 @@ public class Basic {
if (ch.isOpen())
throw new RuntimeException("Channel should be closed");
- boolean terminated = group.awaitTermination(3, TimeUnit.SECONDS);
- if (!terminated)
- throw new RuntimeException("Group should have terminated");
+ awaitTermination(group);
+
if (pool != null && !pool.isTerminated())
throw new RuntimeException("Executor should have terminated");
}
@@ -260,9 +256,7 @@ public class Basic {
// close channel; group should terminate quickly
ch.close();
listener.close();
- terminated = group.awaitTermination(3, TimeUnit.SECONDS);
- if (!terminated)
- throw new RuntimeException("Group should have terminated");
+ awaitTermination(group);
}
static void miscTests() throws Exception {
diff --git a/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java b/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java
index 2945343bfe..ce7d3f6355 100644
--- a/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java
+++ b/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java
@@ -136,7 +136,7 @@ public class GroupOfOne {
// clean-up
group.shutdown();
- boolean terminated = group.awaitTermination(5, TimeUnit.SECONDS);
+ boolean terminated = group.awaitTermination(20, TimeUnit.SECONDS);
if (!terminated)
throw new RuntimeException("Group did not terminate");
diff --git a/test/java/nio/channels/AsynchronousChannelGroup/Restart.java b/test/java/nio/channels/AsynchronousChannelGroup/Restart.java
index 5fb2f123b0..456f66a2ee 100644
--- a/test/java/nio/channels/AsynchronousChannelGroup/Restart.java
+++ b/test/java/nio/channels/AsynchronousChannelGroup/Restart.java
@@ -24,8 +24,6 @@
/* @test
* @bug 4607272 6842687
* @summary Unit test for AsynchronousChannelGroup
- * @build Restart
- * @run main/othervm -XX:-UseVMInterruptibleIO Restart
*/
import java.nio.channels.*;
diff --git a/test/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java b/test/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java
new file mode 100644
index 0000000000..7abbf064b4
--- /dev/null
+++ b/test/java/nio/channels/AsynchronousSocketChannel/CompletionHandlerRelease.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2018, 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 8202252
+ * @run testng CompletionHandlerRelease
+ * @summary Verify that reference to CompletionHandler is cleared after use
+ */
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import static java.net.StandardSocketOptions.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousChannelGroup;
+import java.nio.channels.AsynchronousServerSocketChannel;
+import java.nio.channels.AsynchronousSocketChannel;
+import java.nio.channels.CompletionHandler;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class CompletionHandlerRelease {
+ @Test
+ public void testConnect() throws Exception {
+ try (Server server = new Server()) {
+ try (AsynchronousSocketChannel ch =
+ AsynchronousSocketChannel.open(GROUP)) {
+ CountDownLatch latch = new CountDownLatch(1);
+ Handler<Void,Object> handler =
+ new Handler<Void,Object>("connect", latch);
+ ReferenceQueue queue = new ReferenceQueue<WeakReference>();
+ WeakReference<Object> ref =
+ new WeakReference<Object>(handler, queue);
+
+ ch.connect(server.address(), null, handler);
+
+ try { latch.await(); } catch (InterruptedException ignore) { }
+
+ handler = null;
+ waitForRefToClear(ref, queue);
+
+ server.accept().get().close();
+ }
+ }
+ }
+
+ @Test
+ public void testWrite() throws Exception {
+ try (Server server = new Server();
+ AsynchronousSocketChannel ch =
+ AsynchronousSocketChannel.open(GROUP)) {
+ ch.connect(server.address()).get();
+
+ try (AsynchronousSocketChannel sc = server.accept().get()) {
+ ByteBuffer src = ByteBuffer.wrap("hello".getBytes("UTF-8"));
+ sc.setOption(SO_SNDBUF, src.remaining());
+
+ CountDownLatch latch = new CountDownLatch(1);
+ Handler<Integer,Object> handler =
+ new Handler<Integer,Object>("write", latch);
+ ReferenceQueue queue = new ReferenceQueue<WeakReference>();
+ WeakReference<Object> ref =
+ new WeakReference<Object>(handler, queue);
+
+ sc.write(src, null, handler);
+
+ try { latch.await(); } catch (InterruptedException ignore) { }
+
+ handler = null;
+ waitForRefToClear(ref, queue);
+ }
+ }
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ try (Server server = new Server();
+ AsynchronousSocketChannel ch =
+ AsynchronousSocketChannel.open(GROUP)) {
+ ch.connect(server.address()).get();
+
+ try (AsynchronousSocketChannel sc = server.accept().get()) {
+ ByteBuffer src = ByteBuffer.wrap("hello".getBytes("UTF-8"));
+ sc.setOption(SO_SNDBUF, src.remaining());
+ sc.write(src).get();
+
+ CountDownLatch latch = new CountDownLatch(1);
+ Handler<Integer,Object> handler =
+ new Handler<Integer,Object>("read", latch);
+ ReferenceQueue queue = new ReferenceQueue<WeakReference>();
+ WeakReference<Object> ref =
+ new WeakReference<Object>(handler, queue);
+
+ ByteBuffer dst = ByteBuffer.allocate(64);
+ ch.read(dst, null, handler);
+
+ try { latch.await(); } catch (InterruptedException ignore) { }
+
+ handler = null;
+ waitForRefToClear(ref, queue);
+ }
+ }
+ }
+
+ private AsynchronousChannelGroup GROUP;
+
+ @BeforeTest
+ void setup() throws IOException {
+ GROUP = AsynchronousChannelGroup.withFixedThreadPool(2,
+ Executors.defaultThreadFactory());
+ }
+
+ @AfterTest
+ void cleanup() throws IOException {
+ GROUP.shutdownNow();
+ }
+
+ class Server implements Closeable {
+ private final AsynchronousServerSocketChannel ssc;
+ private final InetSocketAddress address;
+
+ Server() throws IOException {
+ this(0);
+ }
+
+ Server(int recvBufSize) throws IOException {
+ ssc = AsynchronousServerSocketChannel.open(GROUP);
+ if (recvBufSize > 0) {
+ ssc.setOption(SO_RCVBUF, recvBufSize);
+ }
+ ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(),
+ 0));
+ address = (InetSocketAddress)ssc.getLocalAddress();
+ }
+
+ InetSocketAddress address() {
+ return address;
+ }
+
+ Future<AsynchronousSocketChannel> accept() throws IOException {
+ return ssc.accept();
+ }
+
+ public void close() throws IOException {
+ ssc.close();
+ }
+ }
+
+ static class Handler<V,A> implements CompletionHandler<V,A> {
+ private final String name;
+ private final CountDownLatch latch;
+
+ Handler(String name, CountDownLatch latch) {
+ this.name = name;
+ this.latch = latch;
+ }
+
+ public void completed(V result, A attachment) {
+ System.out.format("%s completed(%s, %s)%n",
+ name, result, attachment);
+ latch.countDown();
+ }
+
+ public void failed(Throwable exc, A attachment) {
+ System.out.format("%s failed(%s, %s)%n",
+ name, exc, attachment);
+ exc.printStackTrace();
+ latch.countDown();
+ }
+ }
+
+ private void waitForRefToClear(Reference ref, ReferenceQueue queue)
+ throws InterruptedException {
+ Reference r;
+ while ((r = queue.remove(20)) == null) {
+ System.gc();
+ }
+ assertEquals(r, ref);
+ assertNull(r.get());
+ }
+}
diff --git a/test/java/nio/channels/Selector/ChangingInterests.java b/test/java/nio/channels/Selector/ChangingInterests.java
index 59f6210067..c3e1dbd096 100644
--- a/test/java/nio/channels/Selector/ChangingInterests.java
+++ b/test/java/nio/channels/Selector/ChangingInterests.java
@@ -138,8 +138,10 @@ public class ChangingInterests {
ServerSocketChannel.open().bind(new InetSocketAddress(0));
final SocketChannel sc = SocketChannel.open();
+ sc.setOption(StandardSocketOptions.TCP_NODELAY, true);
sc.connect(new InetSocketAddress(lh, ssc.socket().getLocalPort()));
SocketChannel peer = ssc.accept();
+ peer.setOption(StandardSocketOptions.TCP_NODELAY, true);
sc.configureBlocking(false);
diff --git a/test/java/nio/file/FileStore/Basic.java b/test/java/nio/file/FileStore/Basic.java
index 176efef87a..5c8e53f5d0 100644
--- a/test/java/nio/file/FileStore/Basic.java
+++ b/test/java/nio/file/FileStore/Basic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -24,7 +24,10 @@
/* @test
* @bug 4313887 6873621 6979526 7006126 7020517
* @summary Unit test for java.nio.file.FileStore
- * @library ..
+ * @key intermittent
+ * @library .. /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run main Basic
*/
import java.nio.file.*;
@@ -32,6 +35,7 @@ import java.nio.file.attribute.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
+import jdk.testlibrary.FileUtils;
public class Basic {
@@ -109,19 +113,36 @@ public class Basic {
/**
* Test: Enumerate all FileStores
*/
- FileStore prev = null;
- for (FileStore store: FileSystems.getDefault().getFileStores()) {
- System.out.format("%s (name=%s type=%s)\n", store, store.name(),
- store.type());
-
- // check space attributes are accessible
- store.getTotalSpace();
- store.getUnallocatedSpace();
- store.getUsableSpace();
-
- // two distinct FileStores should not be equal
- assertTrue(!store.equals(prev));
- prev = store;
+ if (FileUtils.areFileSystemsAccessible()) {
+ FileStore prev = null;
+ for (FileStore store: FileSystems.getDefault().getFileStores()) {
+ System.out.format("%s (name=%s type=%s)\n", store, store.name(),
+ store.type());
+
+ // check space attributes are accessible
+ try {
+ store.getTotalSpace();
+ store.getUnallocatedSpace();
+ store.getUsableSpace();
+ } catch (NoSuchFileException nsfe) {
+ // ignore exception as the store could have been
+ // deleted since the iterator was instantiated
+ System.err.format("%s was not found\n", store);
+ } catch (AccessDeniedException ade) {
+ // ignore exception as the lack of ability to access the
+ // store due to lack of file permission or similar does not
+ // reflect whether the space attributes would be accessible
+ // were access to be permitted
+ System.err.format("%s is inaccessible\n", store);
+ }
+
+ // two distinct FileStores should not be equal
+ assertTrue(!store.equals(prev));
+ prev = store;
+ }
+ } else {
+ System.err.println
+ ("Skipping FileStore check due to file system access failure");
}
}
}
diff --git a/test/java/nio/file/FileSystem/Basic.java b/test/java/nio/file/FileSystem/Basic.java
index 89903611b4..18f788ea1f 100644
--- a/test/java/nio/file/FileSystem/Basic.java
+++ b/test/java/nio/file/FileSystem/Basic.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, 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
@@ -24,12 +24,25 @@
/* @test
* @bug 4313887 6838333
* @summary Unit test for java.nio.file.FileSystem
- * @library ..
+ * @library .. /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run main Basic
*/
-import java.nio.file.*;
-import java.nio.file.attribute.*;
+import java.io.File;
import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.FileStore;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.util.HashMap;
+import java.util.concurrent.TimeUnit;
+import jdk.testlibrary.FileUtils;
/**
* Simple santity checks for java.nio.file.FileSystem
@@ -41,6 +54,20 @@ public class Basic {
throw new RuntimeException(msg);
}
+ static void checkFileStores(FileSystem fs) throws IOException {
+ // sanity check method
+ if (FileUtils.areFileSystemsAccessible()) {
+ System.out.println("\n--- Begin FileStores ---");
+ for (FileStore store: fs.getFileStores()) {
+ System.out.println(store);
+ }
+ System.out.println("--- EndFileStores ---\n");
+ } else {
+ System.err.println
+ ("Skipping FileStore check due to file system access failure");
+ }
+ }
+
static void checkSupported(FileSystem fs, String... views) {
for (String view: views) {
check(fs.supportedFileAttributeViews().contains(view),
@@ -48,7 +75,9 @@ public class Basic {
}
}
- public static void main(String[] args) throws IOException {
+ public static void main(String[] args)
+ throws IOException, URISyntaxException {
+ String os = System.getProperty("os.name");
FileSystem fs = FileSystems.getDefault();
// close should throw UOE
@@ -63,15 +92,11 @@ public class Basic {
check(fs.provider().getScheme().equals("file"),
"should use 'file' scheme");
- // santity check method - need to re-visit this in future as I/O errors
- // are possible
- for (FileStore store: fs.getFileStores()) {
- System.out.println(store);
- }
+ // sanity check FileStores
+ checkFileStores(fs);
// sanity check supportedFileAttributeViews
checkSupported(fs, "basic");
- String os = System.getProperty("os.name");
if (os.equals("SunOS"))
checkSupported(fs, "posix", "unix", "owner", "acl", "user");
if (os.equals("Linux"))
diff --git a/test/java/rmi/testlibrary/TestSocketFactory.java b/test/java/rmi/testlibrary/TestSocketFactory.java
index 59b527ceed..ba84de0935 100644
--- a/test/java/rmi/testlibrary/TestSocketFactory.java
+++ b/test/java/rmi/testlibrary/TestSocketFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, 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
@@ -92,7 +92,8 @@ public class TestSocketFactory extends RMISocketFactory
static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
- public static final boolean DEBUG = false;
+ // True to enable logging of matches and replacements.
+ private static volatile boolean debugLogging = false;
/**
* Debugging output can be synchronized with logging of RMI actions.
@@ -100,8 +101,8 @@ public class TestSocketFactory extends RMISocketFactory
* @param format a printf format
* @param args any args
*/
- private static void DEBUG(String format, Object... args) {
- if (DEBUG) {
+ public static void DEBUG(String format, Object... args) {
+ if (debugLogging) {
System.err.printf(format, args);
}
}
@@ -117,6 +118,17 @@ public class TestSocketFactory extends RMISocketFactory
}
/**
+ * Set debug to true to generate logging output of matches and substitutions.
+ * @param debug {@code true} to generate logging output
+ * @return the previous value
+ */
+ public static boolean setDebug(boolean debug) {
+ boolean oldDebug = debugLogging;
+ debugLogging = debug;
+ return oldDebug;
+ }
+
+ /**
* Set the match and replacement bytes, with an empty trigger.
* The match and replacements are propagated to all existing sockets.
*
diff --git a/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java b/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java
new file mode 100644
index 0000000000..9417ddbec4
--- /dev/null
+++ b/test/java/text/AttributedCharacterIterator/Attribute/ReadResolve.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4136620 4144590
+ @summary Make sure that Attribute & subclasses are serialized and deserialized correctly
+ @modules java.desktop
+ */
+
+import java.text.AttributedCharacterIterator.Attribute;
+import java.awt.font.TextAttribute;
+import java.io.*;
+
+public class ReadResolve {
+
+ public static void main(String[] args) throws Exception {
+ testSerializationCycle(Attribute.LANGUAGE);
+ testSerializationCycle(TextAttribute.INPUT_METHOD_HIGHLIGHT);
+
+ boolean gotException = false;
+ Attribute result = null;
+ try {
+ result = doSerializationCycle(FakeAttribute.LANGUAGE);
+ } catch (Throwable e) {
+ gotException = true;
+ }
+ if (!gotException) {
+ throw new RuntimeException("Attribute should throw an exception when given a fake \"language\" attribute. Deserialized object: " + result);
+ }
+ }
+
+ static Attribute doSerializationCycle(Attribute attribute) throws Exception {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(attribute);
+ oos.flush();
+
+ byte[] data = baos.toByteArray();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(data);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Attribute result = (Attribute) ois.readObject();
+
+ return result;
+ }
+
+ static void testSerializationCycle(Attribute attribute) throws Exception {
+ Attribute result = doSerializationCycle(attribute);
+ if (result != attribute) {
+ throw new RuntimeException("attribute changed identity during serialization/deserialization");
+ }
+ }
+
+ private static class FakeAttribute extends Attribute {
+
+ // This LANGUAGE attribute should never be confused with the
+ // Attribute.LANGUAGE attribute. However, we don't override
+ // readResolve here, so that deserialization goes
+ // to Attribute. Attribute has to catch this problem and reject
+ // the fake attribute.
+ static final FakeAttribute LANGUAGE = new FakeAttribute("language");
+
+ FakeAttribute(String name) {
+ super(name);
+ }
+ }
+}
diff --git a/test/java/text/AttributedString/AttributedStringTest.java b/test/java/text/AttributedString/AttributedStringTest.java
new file mode 100644
index 0000000000..bab3996235
--- /dev/null
+++ b/test/java/text/AttributedString/AttributedStringTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4139771
+ * @summary test all aspects of AttributedString class
+ */
+
+import java.text.Annotation;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedCharacterIterator.Attribute;
+import java.text.AttributedString;
+import java.text.CharacterIterator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+
+public class AttributedStringTest {
+
+ private static final String text = "Hello, world!";
+ private static final Annotation hi = new Annotation("hi");
+ private static final int[] array5_13 = {5, 13};
+ private static final int[] array3_9_13 = {3, 9, 13};
+ private static final int[] array5_9_13 = {5, 9, 13};
+ private static final int[] array3_5_9_13 = {3, 5, 9, 13};
+ private static final Attribute[] arrayLanguage = {Attribute.LANGUAGE};
+ private static final Attribute[] arrayLanguageReading = {Attribute.LANGUAGE, Attribute.READING};
+ private static final Set setLanguageReading = new HashSet();
+ static {
+ setLanguageReading.add(Attribute.LANGUAGE);
+ setLanguageReading.add(Attribute.READING);
+ }
+
+
+ public static final void main(String argv[]) throws Exception {
+
+
+ AttributedString string;
+ AttributedCharacterIterator iterator;
+
+ // create a string with text, but no attributes
+ string = new AttributedString(text);
+ iterator = string.getIterator();
+
+ // make sure the text is there and attributes aren't
+ checkIteratorText(iterator, text);
+ if (!iterator.getAllAttributeKeys().isEmpty()) {
+ throwException(iterator, "iterator provides attributes where none are defined");
+ }
+
+ // add an attribute to a subrange
+ string.addAttribute(Attribute.LANGUAGE, Locale.ENGLISH, 3, 9);
+ iterator = string.getIterator();
+
+ // make sure the attribute is defined, and it's on the correct subrange
+ checkIteratorAttributeKeys(iterator, arrayLanguage);
+ checkIteratorSubranges(iterator, array3_9_13);
+ checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null);
+ checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH);
+ checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+ // add an attribute to a subrange
+ string.addAttribute(Attribute.READING, hi, 0, 5);
+ iterator = string.getIterator();
+
+ // make sure the attribute is defined, and it's on the correct subrange
+ checkIteratorAttributeKeys(iterator, arrayLanguageReading);
+ checkIteratorSubranges(iterator, array3_5_9_13);
+ checkIteratorAttribute(iterator, 0, Attribute.READING, hi);
+ checkIteratorAttribute(iterator, 3, Attribute.READING, hi);
+ checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+ checkIteratorAttribute(iterator, 9, Attribute.READING, null);
+
+ // make sure the first attribute wasn't adversely affected
+ // in particular, we shouldn't see separate subranges (3,5) and (5,9).
+ checkIteratorSubranges(iterator, Attribute.LANGUAGE, array3_9_13);
+ checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, null);
+ checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.ENGLISH);
+ checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH);
+ checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+ // for the entire set of attributes, we expect four subranges
+ checkIteratorSubranges(iterator, setLanguageReading, array3_5_9_13);
+
+ // redefine the language attribute so that both language and reading are continuous from 0 to 5
+ string.addAttribute(Attribute.LANGUAGE, Locale.US, 0, 5);
+ iterator = string.getIterator();
+
+ // make sure attributes got changed and merged correctly
+ checkIteratorAttributeKeys(iterator, arrayLanguageReading);
+ checkIteratorSubranges(iterator, array3_5_9_13);
+ checkIteratorSubranges(iterator, Attribute.LANGUAGE, array5_9_13);
+ checkIteratorSubranges(iterator, Attribute.READING, array5_13);
+ checkIteratorSubranges(iterator, setLanguageReading, array5_9_13);
+ checkIteratorAttribute(iterator, 0, Attribute.LANGUAGE, Locale.US);
+ checkIteratorAttribute(iterator, 3, Attribute.LANGUAGE, Locale.US);
+ checkIteratorAttribute(iterator, 5, Attribute.LANGUAGE, Locale.ENGLISH);
+ checkIteratorAttribute(iterator, 9, Attribute.LANGUAGE, null);
+
+ // make sure an annotation is only returned if its range is contained in the iterator's range
+ iterator = string.getIterator(null, 3, 5);
+ checkIteratorAttribute(iterator, 3, Attribute.READING, null);
+ checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+ iterator = string.getIterator(null, 0, 4);
+ checkIteratorAttribute(iterator, 0, Attribute.READING, null);
+ checkIteratorAttribute(iterator, 3, Attribute.READING, null);
+ iterator = string.getIterator(null, 0, 5);
+ checkIteratorAttribute(iterator, 0, Attribute.READING, hi);
+ checkIteratorAttribute(iterator, 4, Attribute.READING, hi);
+ checkIteratorAttribute(iterator, 5, Attribute.READING, null);
+
+ }
+
+ private static final void checkIteratorText(AttributedCharacterIterator iterator, String expectedText) throws Exception {
+ if (iterator.getEndIndex() - iterator.getBeginIndex() != expectedText.length()) {
+ throwException(iterator, "text length doesn't match between original text and iterator");
+ }
+
+ char c = iterator.first();
+ for (int i = 0; i < expectedText.length(); i++) {
+ if (c != expectedText.charAt(i)) {
+ throwException(iterator, "text content doesn't match between original text and iterator");
+ }
+ c = iterator.next();
+ }
+ if (c != CharacterIterator.DONE) {
+ throwException(iterator, "iterator text doesn't end with DONE");
+ }
+ }
+
+ private static final void checkIteratorAttributeKeys(AttributedCharacterIterator iterator, Attribute[] expectedKeys) throws Exception {
+ Set iteratorKeys = iterator.getAllAttributeKeys();
+ if (iteratorKeys.size() != expectedKeys.length) {
+ throwException(iterator, "number of keys returned by iterator doesn't match expectation");
+ }
+ for (int i = 0; i < expectedKeys.length; i++) {
+ if (!iteratorKeys.contains(expectedKeys[i])) {
+ throwException(iterator, "expected key wasn't found in iterator's key set");
+ }
+ }
+ }
+
+ private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, int[] expectedLimits) throws Exception {
+ int previous = 0;
+ char c = iterator.first();
+ for (int i = 0; i < expectedLimits.length; i++) {
+ if (iterator.getRunStart() != previous || iterator.getRunLimit() != expectedLimits[i]) {
+ throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart() + ", " + iterator.getRunLimit());
+ }
+ previous = expectedLimits[i];
+ c = iterator.setIndex(previous);
+ }
+ if (c != CharacterIterator.DONE) {
+ throwException(iterator, "iterator's run sequence doesn't end with DONE");
+ }
+ }
+
+ private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Attribute key, int[] expectedLimits) throws Exception {
+ int previous = 0;
+ char c = iterator.first();
+ for (int i = 0; i < expectedLimits.length; i++) {
+ if (iterator.getRunStart(key) != previous || iterator.getRunLimit(key) != expectedLimits[i]) {
+ throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(key) + ", " + iterator.getRunLimit(key) + " for key " + key);
+ }
+ previous = expectedLimits[i];
+ c = iterator.setIndex(previous);
+ }
+ if (c != CharacterIterator.DONE) {
+ throwException(iterator, "iterator's run sequence doesn't end with DONE");
+ }
+ }
+
+ private static final void checkIteratorSubranges(AttributedCharacterIterator iterator, Set keys, int[] expectedLimits) throws Exception {
+ int previous = 0;
+ char c = iterator.first();
+ for (int i = 0; i < expectedLimits.length; i++) {
+ if (iterator.getRunStart(keys) != previous || iterator.getRunLimit(keys) != expectedLimits[i]) {
+ throwException(iterator, "run boundaries are not as expected: " + iterator.getRunStart(keys) + ", " + iterator.getRunLimit(keys) + " for keys " + keys);
+ }
+ previous = expectedLimits[i];
+ c = iterator.setIndex(previous);
+ }
+ if (c != CharacterIterator.DONE) {
+ throwException(iterator, "iterator's run sequence doesn't end with DONE");
+ }
+ }
+
+ private static final void checkIteratorAttribute(AttributedCharacterIterator iterator, int index, Attribute key, Object expectedValue) throws Exception {
+ iterator.setIndex(index);
+ Object value = iterator.getAttribute(key);
+ if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) {
+ throwException(iterator, "iterator returns wrong attribute value - " + value + " instead of " + expectedValue);
+ }
+ value = iterator.getAttributes().get(key);
+ if (!((expectedValue == null && value == null) || (expectedValue != null && expectedValue.equals(value)))) {
+ throwException(iterator, "iterator's map returns wrong attribute value - " + value + " instead of " + expectedValue);
+ }
+ }
+
+ private static final void throwException(AttributedCharacterIterator iterator, String details) throws Exception {
+ dumpIterator(iterator);
+ throw new Exception(details);
+ }
+
+ private static final void dumpIterator(AttributedCharacterIterator iterator) {
+ Set attributeKeys = iterator.getAllAttributeKeys();
+ System.out.print("All attributes: ");
+ Iterator keyIterator = attributeKeys.iterator();
+ while (keyIterator.hasNext()) {
+ Attribute key = (Attribute) keyIterator.next();
+ System.out.print(key);
+ }
+ for(char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) {
+ if (iterator.getIndex() == iterator.getBeginIndex() ||
+ iterator.getIndex() == iterator.getRunStart()) {
+ System.out.println();
+ Map attributes = iterator.getAttributes();
+ Set entries = attributes.entrySet();
+ Iterator attributeIterator = entries.iterator();
+ while (attributeIterator.hasNext()) {
+ Map.Entry entry = (Map.Entry) attributeIterator.next();
+ System.out.print("<" + entry.getKey() + ": "
+ + entry.getValue() + ">");
+ }
+ }
+ System.out.print(" ");
+ System.out.print(c);
+ }
+ System.out.println();
+ System.out.println("done");
+ System.out.println();
+ }
+
+}
diff --git a/test/java/text/AttributedString/TestAttributedStringCtor.java b/test/java/text/AttributedString/TestAttributedStringCtor.java
new file mode 100644
index 0000000000..0f9ed615ef
--- /dev/null
+++ b/test/java/text/AttributedString/TestAttributedStringCtor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4146853
+ * @summary Make sure we can construct an AttributedString from
+ * an AttributedCharacterIterator covering only a subrange
+ * @modules java.desktop
+ */
+
+import java.awt.font.TextAttribute;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.Hashtable;
+
+public class TestAttributedStringCtor {
+
+ public static void main(String[] args) {
+
+ // Create a new AttributedString with one attribute.
+ Hashtable attributes = new Hashtable();
+ attributes.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
+ AttributedString origString = new AttributedString("Hello world.", attributes);
+
+ // Create an iterator over part of the AttributedString.
+ AttributedCharacterIterator iter = origString.getIterator(null, 4, 6);
+
+ // Attempt to create a new AttributedString from the iterator.
+ // This will throw IllegalArgumentException.
+ AttributedString newString = new AttributedString(iter);
+
+ // Without the exception this would get executed.
+ System.out.println("DONE");
+ }
+}
diff --git a/test/java/text/AttributedString/getRunStartLimitTest.java b/test/java/text/AttributedString/getRunStartLimitTest.java
new file mode 100644
index 0000000000..c0acfcfb50
--- /dev/null
+++ b/test/java/text/AttributedString/getRunStartLimitTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4151160
+ * @summary Make sure to return correct run start and limit values
+ * when the iterator has been created with begin and end index values.
+ * @modules java.desktop
+ */
+
+import java.awt.font.TextAttribute;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.text.Annotation;
+
+public class getRunStartLimitTest {
+
+ public static void main(String[] args) throws Exception {
+
+ String text = "Hello world";
+ AttributedString as = new AttributedString(text);
+
+ // add non-Annotation attributes
+ as.addAttribute(TextAttribute.WEIGHT,
+ TextAttribute.WEIGHT_LIGHT,
+ 0,
+ 3);
+ as.addAttribute(TextAttribute.WEIGHT,
+ TextAttribute.WEIGHT_BOLD,
+ 3,
+ 5);
+ as.addAttribute(TextAttribute.WEIGHT,
+ TextAttribute.WEIGHT_EXTRABOLD,
+ 5,
+ text.length());
+
+ // add Annotation attributes
+ as.addAttribute(TextAttribute.WIDTH,
+ new Annotation(TextAttribute.WIDTH_EXTENDED),
+ 0,
+ 3);
+ as.addAttribute(TextAttribute.WIDTH,
+ new Annotation(TextAttribute.WIDTH_CONDENSED),
+ 3,
+ 4);
+
+ AttributedCharacterIterator aci = as.getIterator(null, 2, 4);
+
+ aci.first();
+ int runStart = aci.getRunStart();
+ if (runStart != 2) {
+ throw new Exception("1st run start is wrong. ("+runStart+" should be 2.)");
+ }
+
+ int runLimit = aci.getRunLimit();
+ if (runLimit != 3) {
+ throw new Exception("1st run limit is wrong. ("+runLimit+" should be 3.)");
+ }
+
+ Object value = aci.getAttribute(TextAttribute.WEIGHT);
+ if (value != TextAttribute.WEIGHT_LIGHT) {
+ throw new Exception("1st run attribute is wrong. ("
+ +value+" should be "+TextAttribute.WEIGHT_LIGHT+".)");
+ }
+
+ value = aci.getAttribute(TextAttribute.WIDTH);
+ if (value != null) {
+ throw new Exception("1st run annotation is wrong. ("
+ +value+" should be null.)");
+ }
+
+ aci.setIndex(runLimit);
+ runStart = aci.getRunStart();
+ if (runStart != 3) {
+ throw new Exception("2nd run start is wrong. ("+runStart+" should be 3.)");
+ }
+
+ runLimit = aci.getRunLimit();
+ if (runLimit != 4) {
+ throw new Exception("2nd run limit is wrong. ("+runLimit+" should be 4.)");
+ }
+ value = aci.getAttribute(TextAttribute.WEIGHT);
+ if (value != TextAttribute.WEIGHT_BOLD) {
+ throw new Exception("2nd run attribute is wrong. ("
+ +value+" should be "+TextAttribute.WEIGHT_BOLD+".)");
+ }
+
+ value = aci.getAttribute(TextAttribute.WIDTH);
+ if (!(value instanceof Annotation)
+ || (((Annotation)value).getValue() != TextAttribute.WIDTH_CONDENSED)) {
+ throw new Exception("2nd run annotation is wrong. (" + value + " should be "
+ + new Annotation(TextAttribute.WIDTH_CONDENSED)+".)");
+ }
+ }
+}
diff --git a/test/java/text/BreakIterator/BreakIteratorTest.java b/test/java/text/BreakIterator/BreakIteratorTest.java
new file mode 100644
index 0000000000..3c2498de48
--- /dev/null
+++ b/test/java/text/BreakIterator/BreakIteratorTest.java
@@ -0,0 +1,1438 @@
+/*
+ * Copyright (c) 1996, 2016, 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 4035266 4052418 4068133 4068137 4068139 4086052 4095322 4097779
+ * 4097920 4098467 4111338 4113835 4117554 4143071 4146175 4152117
+ * 4152416 4153072 4158381 4214367 4217703 4638433
+ * @library /java/text/testlib
+ * @run main/timeout=2000 BreakIteratorTest
+ * @summary test BreakIterator
+ */
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.Locale;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.io.*;
+
+public class BreakIteratorTest extends IntlTest
+{
+ private BreakIterator characterBreak;
+ private BreakIterator wordBreak;
+ private BreakIterator lineBreak;
+ private BreakIterator sentenceBreak;
+
+ public static void main(String[] args) throws Exception {
+ new BreakIteratorTest().run(args);
+ }
+
+ public BreakIteratorTest()
+ {
+ characterBreak = BreakIterator.getCharacterInstance();
+ wordBreak = BreakIterator.getWordInstance();
+ lineBreak = BreakIterator.getLineInstance();
+ sentenceBreak = BreakIterator.getSentenceInstance();
+ }
+
+ //=========================================================================
+ // general test subroutines
+ //=========================================================================
+
+ private void generalIteratorTest(BreakIterator bi, Vector expectedResult) {
+ StringBuffer buffer = new StringBuffer();
+ String text;
+ for (int i = 0; i < expectedResult.size(); i++) {
+ text = (String)expectedResult.elementAt(i);
+ buffer.append(text);
+ }
+ text = buffer.toString();
+
+ bi.setText(text);
+
+ Vector nextResults = testFirstAndNext(bi, text);
+ Vector previousResults = testLastAndPrevious(bi, text);
+
+ logln("comparing forward and backward...");
+ int errs = getErrorCount();
+ compareFragmentLists("forward iteration", "backward iteration", nextResults,
+ previousResults);
+ if (getErrorCount() == errs) {
+ logln("comparing expected and actual...");
+ compareFragmentLists("expected result", "actual result", expectedResult,
+ nextResults);
+ }
+
+ int[] boundaries = new int[expectedResult.size() + 3];
+ boundaries[0] = BreakIterator.DONE;
+ boundaries[1] = 0;
+ for (int i = 0; i < expectedResult.size(); i++)
+ boundaries[i + 2] = boundaries[i + 1] + ((String)expectedResult.elementAt(i)).
+ length();
+ boundaries[boundaries.length - 1] = BreakIterator.DONE;
+
+ testFollowing(bi, text, boundaries);
+ testPreceding(bi, text, boundaries);
+ testIsBoundary(bi, text, boundaries);
+
+ doMultipleSelectionTest(bi, text);
+ }
+
+ private Vector testFirstAndNext(BreakIterator bi, String text) {
+ int p = bi.first();
+ int lastP = p;
+ Vector<String> result = new Vector<String>();
+
+ if (p != 0)
+ errln("first() returned " + p + " instead of 0");
+ while (p != BreakIterator.DONE) {
+ p = bi.next();
+ if (p != BreakIterator.DONE) {
+ if (p <= lastP)
+ errln("next() failed to move forward: next() on position "
+ + lastP + " yielded " + p);
+
+ result.addElement(text.substring(lastP, p));
+ }
+ else {
+ if (lastP != text.length())
+ errln("next() returned DONE prematurely: offset was "
+ + lastP + " instead of " + text.length());
+ }
+ lastP = p;
+ }
+ return result;
+ }
+
+ private Vector testLastAndPrevious(BreakIterator bi, String text) {
+ int p = bi.last();
+ int lastP = p;
+ Vector<String> result = new Vector<String>();
+
+ if (p != text.length())
+ errln("last() returned " + p + " instead of " + text.length());
+ while (p != BreakIterator.DONE) {
+ p = bi.previous();
+ if (p != BreakIterator.DONE) {
+ if (p >= lastP)
+ errln("previous() failed to move backward: previous() on position "
+ + lastP + " yielded " + p);
+
+ result.insertElementAt(text.substring(p, lastP), 0);
+ }
+ else {
+ if (lastP != 0)
+ errln("previous() returned DONE prematurely: offset was "
+ + lastP + " instead of 0");
+ }
+ lastP = p;
+ }
+ return result;
+ }
+
+ private void compareFragmentLists(String f1Name, String f2Name, Vector f1, Vector f2) {
+ int p1 = 0;
+ int p2 = 0;
+ String s1;
+ String s2;
+ int t1 = 0;
+ int t2 = 0;
+
+ while (p1 < f1.size() && p2 < f2.size()) {
+ s1 = (String)f1.elementAt(p1);
+ s2 = (String)f2.elementAt(p2);
+ t1 += s1.length();
+ t2 += s2.length();
+
+ if (s1.equals(s2)) {
+ debugLogln(" >" + s1 + "<");
+ ++p1;
+ ++p2;
+ }
+ else {
+ int tempT1 = t1;
+ int tempT2 = t2;
+ int tempP1 = p1;
+ int tempP2 = p2;
+
+ while (tempT1 != tempT2 && tempP1 < f1.size() && tempP2 < f2.size()) {
+ while (tempT1 < tempT2 && tempP1 < f1.size()) {
+ tempT1 += ((String)f1.elementAt(tempP1)).length();
+ ++tempP1;
+ }
+ while (tempT2 < tempT1 && tempP2 < f2.size()) {
+ tempT2 += ((String)f2.elementAt(tempP2)).length();
+ ++tempP2;
+ }
+ }
+ logln("*** " + f1Name + " has:");
+ while (p1 <= tempP1 && p1 < f1.size()) {
+ s1 = (String)f1.elementAt(p1);
+ t1 += s1.length();
+ debugLogln(" *** >" + s1 + "<");
+ ++p1;
+ }
+ logln("***** " + f2Name + " has:");
+ while (p2 <= tempP2 && p2 < f2.size()) {
+ s2 = (String)f2.elementAt(p2);
+ t2 += s2.length();
+ debugLogln(" ***** >" + s2 + "<");
+ ++p2;
+ }
+ errln("Discrepancy between " + f1Name + " and " + f2Name + "\n---\n" + f1 +"\n---\n" + f2);
+ }
+ }
+ }
+
+ private void testFollowing(BreakIterator bi, String text, int[] boundaries) {
+ logln("testFollowing():");
+ int p = 2;
+ int i = 0;
+ try {
+ for (i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in
+ if (i == boundaries[p])
+ ++p;
+
+ int b = bi.following(i);
+ logln("bi.following(" + i + ") -> " + b);
+ if (b != boundaries[p])
+ errln("Wrong result from following() for " + i + ": expected " + boundaries[p]
+ + ", got " + b);
+ }
+ } catch (IllegalArgumentException illargExp) {
+ errln("IllegalArgumentException caught from following() for offset: " + i);
+ }
+ }
+
+ private void testPreceding(BreakIterator bi, String text, int[] boundaries) {
+ logln("testPreceding():");
+ int p = 0;
+ int i = 0;
+ try {
+ for (i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in
+ int b = bi.preceding(i);
+ logln("bi.preceding(" + i + ") -> " + b);
+ if (b != boundaries[p])
+ errln("Wrong result from preceding() for " + i + ": expected " + boundaries[p]
+ + ", got " + b);
+
+ if (i == boundaries[p + 1])
+ ++p;
+ }
+ } catch (IllegalArgumentException illargExp) {
+ errln("IllegalArgumentException caught from preceding() for offset: " + i);
+ }
+ }
+
+ private void testIsBoundary(BreakIterator bi, String text, int[] boundaries) {
+ logln("testIsBoundary():");
+ int p = 1;
+ boolean isB;
+ for (int i = 0; i <= text.length(); i++) { // change to <= when new BI code goes in
+ isB = bi.isBoundary(i);
+ logln("bi.isBoundary(" + i + ") -> " + isB);
+
+ if (i == boundaries[p]) {
+ if (!isB)
+ errln("Wrong result from isBoundary() for " + i + ": expected true, got false");
+ ++p;
+ }
+ else {
+ if (isB)
+ errln("Wrong result from isBoundary() for " + i + ": expected false, got true");
+ }
+ }
+ }
+
+ private void doMultipleSelectionTest(BreakIterator iterator, String testText)
+ {
+ logln("Multiple selection test...");
+ BreakIterator testIterator = (BreakIterator)iterator.clone();
+ int offset = iterator.first();
+ int testOffset;
+ int count = 0;
+
+ do {
+ testOffset = testIterator.first();
+ testOffset = testIterator.next(count);
+ logln("next(" + count + ") -> " + testOffset);
+ if (offset != testOffset)
+ errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);
+
+ if (offset != BreakIterator.DONE) {
+ count++;
+ offset = iterator.next();
+ }
+ } while (offset != BreakIterator.DONE);
+
+ // now do it backwards...
+ offset = iterator.last();
+ count = 0;
+
+ do {
+ testOffset = testIterator.last();
+ testOffset = testIterator.next(count);
+ logln("next(" + count + ") -> " + testOffset);
+ if (offset != testOffset)
+ errln("next(n) and next() not returning consistent results: for step " + count + ", next(n) returned " + testOffset + " and next() had " + offset);
+
+ if (offset != BreakIterator.DONE) {
+ count--;
+ offset = iterator.previous();
+ }
+ } while (offset != BreakIterator.DONE);
+ }
+
+ private void doBreakInvariantTest(BreakIterator tb, String testChars)
+ {
+ StringBuffer work = new StringBuffer("aaa");
+ int errorCount = 0;
+
+ // a break should always occur after CR (unless followed by LF), LF, PS, and LS
+ String breaks = /*"\r\n\u2029\u2028"*/"\n\u2029\u2028";
+ // change this back when new BI code is added
+
+ for (int i = 0; i < breaks.length(); i++) {
+ work.setCharAt(1, breaks.charAt(i));
+ for (int j = 0; j < testChars.length(); j++) {
+ work.setCharAt(0, testChars.charAt(j));
+ for (int k = 0; k < testChars.length(); k++) {
+ char c = testChars.charAt(k);
+
+ // if a cr is followed by lf, don't do the check (they stay together)
+ if (work.charAt(1) == '\r' && (c == '\n'))
+ continue;
+
+ // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+ // for breaking purposes as per UTR14
+ int type1 = Character.getType(work.charAt(1));
+ int type2 = Character.getType(c);
+ if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+ type2 == Character.CONTROL || type2 == Character.FORMAT) {
+ continue;
+ }
+
+ work.setCharAt(2, c);
+ tb.setText(work.toString());
+ boolean seen2 = false;
+ for (int l = tb.first(); l != BreakIterator.DONE; l = tb.next()) {
+ if (l == 2)
+ seen2 = true;
+ }
+ if (!seen2) {
+ errln("No break between U+" + Integer.toHexString((int)(work.charAt(1)))
+ + " and U+" + Integer.toHexString((int)(work.charAt(2))));
+ errorCount++;
+ if (errorCount >= 75)
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private void doOtherInvariantTest(BreakIterator tb, String testChars)
+ {
+ StringBuffer work = new StringBuffer("a\r\na");
+ int errorCount = 0;
+
+ // a break should never occur between CR and LF
+ for (int i = 0; i < testChars.length(); i++) {
+ work.setCharAt(0, testChars.charAt(i));
+ for (int j = 0; j < testChars.length(); j++) {
+ work.setCharAt(3, testChars.charAt(j));
+ tb.setText(work.toString());
+ for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next())
+ if (k == 2) {
+ errln("Break between CR and LF in string U+" + Integer.toHexString(
+ (int)(work.charAt(0))) + ", U+d U+a U+" + Integer.toHexString(
+ (int)(work.charAt(3))));
+ errorCount++;
+ if (errorCount >= 75)
+ return;
+ }
+ }
+ }
+
+ // a break should never occur before a non-spacing mark, unless it's preceded
+ // by a line terminator
+ work.setLength(0);
+ work.append("aaaa");
+ for (int i = 0; i < testChars.length(); i++) {
+ char c = testChars.charAt(i);
+ if (c == '\n' || c == '\r' || c == '\u2029' || c == '\u2028' || c == '\u0003')
+ continue;
+ work.setCharAt(1, c);
+ for (int j = 0; j < testChars.length(); j++) {
+ c = testChars.charAt(j);
+ if (Character.getType(c) != Character.NON_SPACING_MARK && Character.getType(c)
+ != Character.ENCLOSING_MARK)
+ continue;
+ work.setCharAt(2, c);
+
+ // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+ // for breaking purposes as per UTR14
+ int type1 = Character.getType(work.charAt(1));
+ int type2 = Character.getType(work.charAt(2));
+ if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+ type2 == Character.CONTROL || type2 == Character.FORMAT) {
+ continue;
+ }
+
+ tb.setText(work.toString());
+ for (int k = tb.first(); k != BreakIterator.DONE; k = tb.next())
+ if (k == 2) {
+ errln("Break between U+" + Integer.toHexString((int)(work.charAt(1)))
+ + " and U+" + Integer.toHexString((int)(work.charAt(2))));
+ errorCount++;
+ if (errorCount >= 75)
+ return;
+ }
+ }
+ }
+ }
+
+ public void debugLogln(String s) {
+ final String zeros = "0000";
+ String temp;
+ StringBuffer out = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ if (c >= ' ' && c < '\u007f')
+ out.append(c);
+ else {
+ out.append("\\u");
+ temp = Integer.toHexString((int)c);
+ out.append(zeros.substring(0, 4 - temp.length()));
+ out.append(temp);
+ }
+ }
+ logln(out.toString());
+ }
+
+ //=========================================================================
+ // tests
+ //=========================================================================
+
+ public void TestWordBreak() {
+
+ Vector<String> wordSelectionData = new Vector<String>();
+
+ wordSelectionData.addElement("12,34");
+
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\u00A2"); //cent sign
+ wordSelectionData.addElement("\u00A3"); //pound sign
+ wordSelectionData.addElement("\u00A4"); //currency sign
+ wordSelectionData.addElement("\u00A5"); //yen sign
+ wordSelectionData.addElement("alpha-beta-gamma");
+ wordSelectionData.addElement(".");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("Badges");
+ wordSelectionData.addElement("?");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("BADGES");
+ wordSelectionData.addElement("!");
+ wordSelectionData.addElement("?");
+ wordSelectionData.addElement("!");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("We");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("don't");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("need");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("no");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("STINKING");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("BADGES");
+ wordSelectionData.addElement("!");
+ wordSelectionData.addElement("!");
+ wordSelectionData.addElement("!");
+
+ wordSelectionData.addElement("012.566,5");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("123.3434,900");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("1000,233,456.000");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("1,23.322%");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("123.1222");
+
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\u0024123,000.20");
+
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("179.01\u0025");
+
+ wordSelectionData.addElement("Hello");
+ wordSelectionData.addElement(",");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("how");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("are");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("you");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("X");
+ wordSelectionData.addElement(" ");
+
+ wordSelectionData.addElement("Now");
+ wordSelectionData.addElement("\r");
+ wordSelectionData.addElement("is");
+ wordSelectionData.addElement("\n");
+ wordSelectionData.addElement("the");
+ wordSelectionData.addElement("\r\n");
+ wordSelectionData.addElement("time");
+ wordSelectionData.addElement("\n");
+ wordSelectionData.addElement("\r");
+ wordSelectionData.addElement("for");
+ wordSelectionData.addElement("\r");
+ wordSelectionData.addElement("\r");
+ wordSelectionData.addElement("all");
+ wordSelectionData.addElement(" ");
+
+ generalIteratorTest(wordBreak, wordSelectionData);
+ }
+
+ public void TestBug4097779() {
+ Vector<String> wordSelectionData = new Vector<String>();
+
+ wordSelectionData.addElement("aa\u0300a");
+ wordSelectionData.addElement(" ");
+
+ generalIteratorTest(wordBreak, wordSelectionData);
+ }
+
+ public void TestBug4098467Words() {
+ Vector<String> wordSelectionData = new Vector<String>();
+
+ // What follows is a string of Korean characters (I found it in the Yellow Pages
+ // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+ // it correctly), first as precomposed syllables, and then as conjoining jamo.
+ // Both sequences should be semantically identical and break the same way.
+ // precomposed syllables...
+ wordSelectionData.addElement("\uc0c1\ud56d");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\ud55c\uc778");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\uc5f0\ud569");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\uc7a5\ub85c\uad50\ud68c");
+ wordSelectionData.addElement(" ");
+ // conjoining jamo...
+ wordSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8");
+ wordSelectionData.addElement(" ");
+ wordSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c");
+ wordSelectionData.addElement(" ");
+
+ generalIteratorTest(wordBreak, wordSelectionData);
+ }
+
+ public void TestBug4117554Words() {
+ Vector<String> wordSelectionData = new Vector<String>();
+
+ // this is a test for bug #4117554: the ideographic iteration mark (U+3005) should
+ // count as a Kanji character for the purposes of word breaking
+ wordSelectionData.addElement("abc");
+ wordSelectionData.addElement("\u4e01\u4e02\u3005\u4e03\u4e03");
+ wordSelectionData.addElement("abc");
+
+ generalIteratorTest(wordBreak, wordSelectionData);
+ }
+
+ public void TestSentenceBreak() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ sentenceSelectionData.addElement("This is a simple sample sentence. ");
+ sentenceSelectionData.addElement("(This is it.) ");
+ sentenceSelectionData.addElement("This is a simple sample sentence. ");
+ sentenceSelectionData.addElement("\"This isn\'t it.\" ");
+ sentenceSelectionData.addElement("Hi! ");
+ sentenceSelectionData.addElement("This is a simple sample sentence. ");
+ sentenceSelectionData.addElement("It does not have to make any sense as you can see. ");
+ sentenceSelectionData.addElement("Nel mezzo del cammin di nostra vita, mi ritrovai in una selva oscura. ");
+ sentenceSelectionData.addElement("Che la dritta via aveo smarrita. ");
+ sentenceSelectionData.addElement("He said, that I said, that you said!! ");
+
+ sentenceSelectionData.addElement("Don't rock the boat.\u2029");
+
+ sentenceSelectionData.addElement("Because I am the daddy, that is why. ");
+ sentenceSelectionData.addElement("Not on my time (el timo.)! ");
+
+ sentenceSelectionData.addElement("So what!!\u2029");
+
+ sentenceSelectionData.addElement("\"But now,\" he said, \"I know!\" ");
+ sentenceSelectionData.addElement("Harris thumbed down several, including \"Away We Go\" (which became the huge success Oklahoma!). ");
+ sentenceSelectionData.addElement("One species, B. anthracis, is highly virulent.\n");
+ sentenceSelectionData.addElement("Wolf said about Sounder:\"Beautifully thought-out and directed.\" ");
+ sentenceSelectionData.addElement("Have you ever said, \"This is where \tI shall live\"? ");
+ sentenceSelectionData.addElement("He answered, \"You may not!\" ");
+ sentenceSelectionData.addElement("Another popular saying is: \"How do you do?\". ");
+ sentenceSelectionData.addElement("Yet another popular saying is: \'I\'m fine thanks.\' ");
+ sentenceSelectionData.addElement("What is the proper use of the abbreviation pp.? ");
+ sentenceSelectionData.addElement("Yes, I am definatelly 12\" tall!!");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4113835() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // test for bug #4113835: \n and \r count as spaces, not as paragraph breaks
+ sentenceSelectionData.addElement("Now\ris\nthe\r\ntime\n\rfor\r\rall\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4111338() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // test for bug #4111338: Don't break sentences at the boundary between CJK
+ // and other letters
+ sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165:\"JAVA\u821c"
+ + "\u8165\u7fc8\u51ce\u306d,\u2494\u56d8\u4ec0\u60b1\u8560\u51ba"
+ + "\u611d\u57b6\u2510\u5d46\".\u2029");
+ sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8"
+ + "\u97e4JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0"
+ + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+ sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8\u97e4"
+ + "\u6470\u8790JAVA\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8"
+ + "\u4ec0\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+ sentenceSelectionData.addElement("He said, \"I can go there.\"\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4117554Sentences() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // Treat fullwidth variants of .!? the same as their
+ // normal counterparts
+ sentenceSelectionData.addElement("I know I'm right\uff0e ");
+ sentenceSelectionData.addElement("Right\uff1f ");
+ sentenceSelectionData.addElement("Right\uff01 ");
+
+ // Don't break sentences at boundary between CJK and digits
+ sentenceSelectionData.addElement("\u5487\u67ff\ue591\u5017\u61b3\u60a1\u9510\u8165\u9de8"
+ + "\u97e48888\u821c\u8165\u7fc8\u51ce\u306d\ue30b\u2494\u56d8\u4ec0"
+ + "\u60b1\u8560\u51ba\u611d\u57b6\u2510\u5d46\u97e5\u7751\u2029");
+
+ // Break sentence between a sentence terminator and
+ // opening punctuation
+ sentenceSelectionData.addElement("no?");
+ sentenceSelectionData.addElement("(yes)");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4158381() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // Don't break sentence after period if it isn't followed by a space
+ sentenceSelectionData.addElement("Test <code>Flags.Flag</code> class. ");
+ sentenceSelectionData.addElement("Another test.\u2029");
+
+ // No breaks when there are no terminators around
+ sentenceSelectionData.addElement("<P>Provides a set of "
+ + "&quot;lightweight&quot; (all-java<FONT SIZE=\"-2\"><SUP>TM"
+ + "</SUP></FONT> language) components that, "
+ + "to the maximum degree possible, work the same on all platforms. ");
+ sentenceSelectionData.addElement("Another test.\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4143071() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // Make sure sentences that end with digits work right
+ sentenceSelectionData.addElement("Today is the 27th of May, 1998. ");
+ sentenceSelectionData.addElement("Tomorrow with be 28 May 1998. ");
+ sentenceSelectionData.addElement("The day after will be the 30th.\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4152416() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // Make sure sentences ending with a capital letter are treated correctly
+ sentenceSelectionData.addElement("The type of all primitive "
+ + "<code>boolean</code> values accessed in the target VM. ");
+ sentenceSelectionData.addElement("Calls to xxx will return an "
+ + "implementor of this interface.\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4152117() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // Make sure sentence breaking is handling punctuation correctly
+ // [COULD NOT REPRODUCE THIS BUG, BUT TEST IS HERE TO MAKE SURE
+ // IT DOESN'T CROP UP]
+ sentenceSelectionData.addElement("Constructs a randomly generated "
+ + "BigInteger, uniformly distributed over the range <tt>0</tt> "
+ + "to <tt>(2<sup>numBits</sup> - 1)</tt>, inclusive. ");
+ sentenceSelectionData.addElement("The uniformity of the distribution "
+ + "assumes that a fair source of random bits is provided in "
+ + "<tt>rnd</tt>. ");
+ sentenceSelectionData.addElement("Note that this constructor always "
+ + "constructs a non-negative BigInteger.\u2029");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestLineBreak() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ lineSelectionData.addElement("Multi-");
+ lineSelectionData.addElement("Level ");
+ lineSelectionData.addElement("example ");
+ lineSelectionData.addElement("of ");
+ lineSelectionData.addElement("a ");
+ lineSelectionData.addElement("semi-");
+ lineSelectionData.addElement("idiotic ");
+ lineSelectionData.addElement("non-");
+ lineSelectionData.addElement("sensical ");
+ lineSelectionData.addElement("(non-");
+ lineSelectionData.addElement("important) ");
+ lineSelectionData.addElement("sentence. ");
+
+ lineSelectionData.addElement("Hi ");
+ lineSelectionData.addElement("Hello ");
+ lineSelectionData.addElement("How\n");
+ lineSelectionData.addElement("are\r");
+ lineSelectionData.addElement("you\u2028");
+ lineSelectionData.addElement("fine.\t");
+ lineSelectionData.addElement("good. ");
+
+ lineSelectionData.addElement("Now\r");
+ lineSelectionData.addElement("is\n");
+ lineSelectionData.addElement("the\r\n");
+ lineSelectionData.addElement("time\n");
+ lineSelectionData.addElement("\r");
+ lineSelectionData.addElement("for\r");
+ lineSelectionData.addElement("\r");
+ lineSelectionData.addElement("all");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4068133() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ lineSelectionData.addElement("\u96f6");
+ lineSelectionData.addElement("\u4e00\u3002");
+ lineSelectionData.addElement("\u4e8c\u3001");
+ lineSelectionData.addElement("\u4e09\u3002\u3001");
+ lineSelectionData.addElement("\u56db\u3001\u3002\u3001");
+ lineSelectionData.addElement("\u4e94,");
+ lineSelectionData.addElement("\u516d.");
+ lineSelectionData.addElement("\u4e03.\u3001,\u3002");
+ lineSelectionData.addElement("\u516b");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4086052() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ lineSelectionData.addElement("foo\u00a0bar ");
+// lineSelectionData.addElement("foo\ufeffbar");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4097920() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ lineSelectionData.addElement("dog,");
+ lineSelectionData.addElement("cat,");
+ lineSelectionData.addElement("mouse ");
+ lineSelectionData.addElement("(one)");
+ lineSelectionData.addElement("(two)\n");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+ /*
+ public void TestBug4035266() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ lineSelectionData.addElement("The ");
+ lineSelectionData.addElement("balance ");
+ lineSelectionData.addElement("is ");
+ lineSelectionData.addElement("$-23,456.78, ");
+ lineSelectionData.addElement("not ");
+ lineSelectionData.addElement("-$32,456.78!\n");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+ */
+ public void TestBug4098467Lines() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ // What follows is a string of Korean characters (I found it in the Yellow Pages
+ // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+ // it correctly), first as precomposed syllables, and then as conjoining jamo.
+ // Both sequences should be semantically identical and break the same way.
+ // precomposed syllables...
+ lineSelectionData.addElement("\uc0c1");
+ lineSelectionData.addElement("\ud56d ");
+ lineSelectionData.addElement("\ud55c");
+ lineSelectionData.addElement("\uc778 ");
+ lineSelectionData.addElement("\uc5f0");
+ lineSelectionData.addElement("\ud569 ");
+ lineSelectionData.addElement("\uc7a5");
+ lineSelectionData.addElement("\ub85c");
+ lineSelectionData.addElement("\uad50");
+ lineSelectionData.addElement("\ud68c ");
+ // conjoining jamo...
+ lineSelectionData.addElement("\u1109\u1161\u11bc\u1112\u1161\u11bc ");
+ lineSelectionData.addElement("\u1112\u1161\u11ab\u110b\u1175\u11ab ");
+ lineSelectionData.addElement("\u110b\u1167\u11ab\u1112\u1161\u11b8 ");
+ lineSelectionData.addElement("\u110c\u1161\u11bc\u1105\u1169\u1100\u116d\u1112\u116c");
+
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4117554Lines() {
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ // Fullwidth .!? should be treated as postJwrd
+ lineSelectionData.addElement("\u4e01\uff0e");
+ lineSelectionData.addElement("\u4e02\uff01");
+ lineSelectionData.addElement("\u4e03\uff1f");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4217703() {
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ // There shouldn't be a line break between sentence-ending punctuation
+ // and a closing quote
+ lineSelectionData.addElement("He ");
+ lineSelectionData.addElement("said ");
+ lineSelectionData.addElement("\"Go!\" ");
+ lineSelectionData.addElement("I ");
+ lineSelectionData.addElement("went. ");
+
+ lineSelectionData.addElement("Hashtable$Enumeration ");
+ lineSelectionData.addElement("getText().");
+ lineSelectionData.addElement("getIndex()");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ private static final String graveS = "S\u0300";
+ private static final String acuteBelowI = "i\u0317";
+ private static final String acuteE = "e\u0301";
+ private static final String circumflexA = "a\u0302";
+ private static final String tildeE = "e\u0303";
+
+ public void TestCharacterBreak() {
+ Vector<String> characterSelectionData = new Vector<String>();
+
+ characterSelectionData.addElement(graveS);
+ characterSelectionData.addElement(acuteBelowI);
+ characterSelectionData.addElement("m");
+ characterSelectionData.addElement("p");
+ characterSelectionData.addElement("l");
+ characterSelectionData.addElement(acuteE);
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("s");
+ characterSelectionData.addElement(circumflexA);
+ characterSelectionData.addElement("m");
+ characterSelectionData.addElement("p");
+ characterSelectionData.addElement("l");
+ characterSelectionData.addElement(tildeE);
+ characterSelectionData.addElement(".");
+ characterSelectionData.addElement("w");
+ characterSelectionData.addElement(circumflexA);
+ characterSelectionData.addElement("w");
+ characterSelectionData.addElement("a");
+ characterSelectionData.addElement("f");
+ characterSelectionData.addElement("q");
+ characterSelectionData.addElement("\n");
+ characterSelectionData.addElement("\r");
+ characterSelectionData.addElement("\r\n");
+ characterSelectionData.addElement("\n");
+
+ generalIteratorTest(characterBreak, characterSelectionData);
+ }
+
+ public void TestBug4098467Characters() {
+ Vector<String> characterSelectionData = new Vector<String>();
+
+ // What follows is a string of Korean characters (I found it in the Yellow Pages
+ // ad for the Korean Presbyterian Church of San Francisco, and I hope I transcribed
+ // it correctly), first as precomposed syllables, and then as conjoining jamo.
+ // Both sequences should be semantically identical and break the same way.
+ // precomposed syllables...
+ characterSelectionData.addElement("\uc0c1");
+ characterSelectionData.addElement("\ud56d");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\ud55c");
+ characterSelectionData.addElement("\uc778");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\uc5f0");
+ characterSelectionData.addElement("\ud569");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\uc7a5");
+ characterSelectionData.addElement("\ub85c");
+ characterSelectionData.addElement("\uad50");
+ characterSelectionData.addElement("\ud68c");
+ characterSelectionData.addElement(" ");
+ // conjoining jamo...
+ characterSelectionData.addElement("\u1109\u1161\u11bc");
+ characterSelectionData.addElement("\u1112\u1161\u11bc");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\u1112\u1161\u11ab");
+ characterSelectionData.addElement("\u110b\u1175\u11ab");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\u110b\u1167\u11ab");
+ characterSelectionData.addElement("\u1112\u1161\u11b8");
+ characterSelectionData.addElement(" ");
+ characterSelectionData.addElement("\u110c\u1161\u11bc");
+ characterSelectionData.addElement("\u1105\u1169");
+ characterSelectionData.addElement("\u1100\u116d");
+ characterSelectionData.addElement("\u1112\u116c");
+
+ generalIteratorTest(characterBreak, characterSelectionData);
+ }
+
+ public void TestBug4153072() {
+ BreakIterator iter = BreakIterator.getWordInstance();
+ String str = "...Hello, World!...";
+ int begin = 3;
+ int end = str.length() - 3;
+ boolean gotException = false;
+ boolean dummy;
+
+ iter.setText(new StringCharacterIterator(str, begin, end, begin));
+ for (int index = -1; index < begin + 1; ++index) {
+ try {
+ dummy = iter.isBoundary(index);
+ if (index < begin)
+ errln("Didn't get exception with offset = " + index +
+ " and begin index = " + begin);
+ }
+ catch (IllegalArgumentException e) {
+ if (index >= begin)
+ errln("Got exception with offset = " + index +
+ " and begin index = " + begin);
+ }
+ }
+ }
+
+ public void TestBug4146175Sentences() {
+ Vector<String> sentenceSelectionData = new Vector<String>();
+
+ // break between periods and opening punctuation even when there's no
+ // intervening space
+ sentenceSelectionData.addElement("end.");
+ sentenceSelectionData.addElement("(This is\u2029");
+
+ // treat the fullwidth period as an unambiguous sentence terminator
+ sentenceSelectionData.addElement("\u7d42\u308f\u308a\uff0e");
+ sentenceSelectionData.addElement("\u300c\u3053\u308c\u306f");
+
+ generalIteratorTest(sentenceBreak, sentenceSelectionData);
+ }
+
+ public void TestBug4146175Lines() {
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ Vector<String> lineSelectionData = new Vector<String>();
+
+ // the fullwidth comma should stick to the preceding Japanese character
+ lineSelectionData.addElement("\u7d42\uff0c");
+ lineSelectionData.addElement("\u308f");
+
+ generalIteratorTest(lineBreak, lineSelectionData);
+ }
+
+ public void TestBug4214367() {
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ Vector<String> wordSelectionData = new Vector<String>();
+
+ // the hiragana and katakana iteration marks and the long vowel mark
+ // are not being treated correctly by the word-break iterator
+ wordSelectionData.addElement("\u3042\u3044\u309d\u3042\u309e\u3042\u30fc\u3042");
+ wordSelectionData.addElement("\u30a2\u30a4\u30fd\u30a2\u30fe\u30a2\u30fc\u30a2");
+
+ generalIteratorTest(wordBreak, wordSelectionData);
+ }
+
+ private static final String cannedTestChars // characters fo the class Cc are ignorable for breaking
+ = /*"\u0000\u0001\u0002\u0003\u0004*/" !\"#$%&()+-01234<=>ABCDE[]^_`abcde{}|\u00a0\u00a2"
+ + "\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00ab\u00ad\u00ae\u00af\u00b0\u00b2\u00b3"
+ + "\u00b4\u00b9\u00bb\u00bc\u00bd\u02b0\u02b1\u02b2\u02b3\u02b4\u0300\u0301\u0302\u0303"
+ + "\u0304\u05d0\u05d1\u05d2\u05d3\u05d4\u0903\u093e\u093f\u0940\u0949\u0f3a\u0f3b\u2000"
+ + "\u2001\u2002\u200c\u200d\u200e\u200f\u2010\u2011\u2012\u2028\u2029\u202a\u203e\u203f"
+ + "\u2040\u20dd\u20de\u20df\u20e0\u2160\u2161\u2162\u2163\u2164";
+
+ public void TestSentenceInvariants()
+ {
+ BreakIterator e = BreakIterator.getSentenceInstance();
+ doOtherInvariantTest(e, cannedTestChars + ".,\u3001\u3002\u3041\u3042\u3043\ufeff");
+ }
+
+ public void TestWordInvariants()
+ {
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ BreakIterator e = BreakIterator.getWordInstance();
+ doBreakInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2"
+ + "\u30a3\u4e00\u4e01\u4e02");
+ doOtherInvariantTest(e, cannedTestChars + "\',.\u3041\u3042\u3043\u309b\u309c\u30a1\u30a2"
+ + "\u30a3\u4e00\u4e01\u4e02");
+ }
+
+ public void TestLineInvariants()
+ {
+ if (Locale.getDefault().getLanguage().equals("th")) {
+ logln("This test is skipped in th locale.");
+ return;
+ }
+
+ BreakIterator e = BreakIterator.getLineInstance();
+ String testChars = cannedTestChars + ".,;:\u3001\u3002\u3041\u3042\u3043\u3044\u3045"
+ + "\u30a3\u4e00\u4e01\u4e02";
+ doBreakInvariantTest(e, testChars);
+ doOtherInvariantTest(e, testChars);
+
+ int errorCount = 0;
+
+ // in addition to the other invariants, a line-break iterator should make sure that:
+ // it doesn't break around the non-breaking characters
+ String noBreak = "\u00a0\u2007\u2011\ufeff";
+ StringBuffer work = new StringBuffer("aaa");
+ for (int i = 0; i < testChars.length(); i++) {
+ char c = testChars.charAt(i);
+ if (c == '\r' || c == '\n' || c == '\u2029' || c == '\u2028' || c == '\u0003')
+ continue;
+ work.setCharAt(0, c);
+ for (int j = 0; j < noBreak.length(); j++) {
+ work.setCharAt(1, noBreak.charAt(j));
+ for (int k = 0; k < testChars.length(); k++) {
+ work.setCharAt(2, testChars.charAt(k));
+ // CONTROL (Cc) and FORMAT (Cf) Characters are to be ignored
+ // for breaking purposes as per UTR14
+ int type1 = Character.getType(work.charAt(1));
+ int type2 = Character.getType(work.charAt(2));
+ if (type1 == Character.CONTROL || type1 == Character.FORMAT ||
+ type2 == Character.CONTROL || type2 == Character.FORMAT) {
+ continue;
+ }
+ e.setText(work.toString());
+ for (int l = e.first(); l != BreakIterator.DONE; l = e.next()) {
+ if (l == 1 || l == 2) {
+ //errln("Got break between U+" + Integer.toHexString((int)
+ // (work.charAt(l - 1))) + " and U+" + Integer.toHexString(
+ // (int)(work.charAt(l))) + "\ntype1 = " + type1 + "\ntype2 = " + type2);
+ // as per UTR14 spaces followed by a GLUE character should allow
+ // line breaking
+ if (work.charAt(l-1) == '\u0020' && (work.charAt(l) == '\u00a0' ||
+ work.charAt(l) == '\u0f0c' ||
+ work.charAt(l) == '\u2007' ||
+ work.charAt(l) == '\u2011' ||
+ work.charAt(l) == '\u202f' ||
+ work.charAt(l) == '\ufeff')) {
+ continue;
+ }
+ errln("Got break between U+" + Integer.toHexString((int)
+ (work.charAt(l - 1))) + " and U+" + Integer.toHexString(
+ (int)(work.charAt(l))));
+ errorCount++;
+ if (errorCount >= 75)
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ // The following test has so many exceptions that it would be better to write a new set of data
+ // that tested exactly what should be tested
+ // Until that point it will be commented out
+ /*
+
+ // it does break after dashes (unless they're followed by a digit, a non-spacing mark,
+ // a currency symbol, a space, a format-control character, a regular control character,
+ // a line or paragraph separator, or another dash)
+ String dashes = "-\u00ad\u2010\u2012\u2013\u2014";
+ for (int i = 0; i < testChars.length(); i++) {
+ work.setCharAt(0, testChars.charAt(i));
+ for (int j = 0; j < dashes.length(); j++) {
+ work.setCharAt(1, dashes.charAt(j));
+ for (int k = 0; k < testChars.length(); k++) {
+ char c = testChars.charAt(k);
+ if (Character.getType(c) == Character.DECIMAL_DIGIT_NUMBER ||
+ Character.getType(c) == Character.OTHER_NUMBER ||
+ Character.getType(c) == Character.NON_SPACING_MARK ||
+ Character.getType(c) == Character.ENCLOSING_MARK ||
+ Character.getType(c) == Character.CURRENCY_SYMBOL ||
+ Character.getType(c) == Character.DASH_PUNCTUATION ||
+ Character.getType(c) == Character.SPACE_SEPARATOR ||
+ Character.getType(c) == Character.FORMAT ||
+ Character.getType(c) == Character.CONTROL ||
+ Character.getType(c) == Character.END_PUNCTUATION ||
+ Character.getType(c) == Character.FINAL_QUOTE_PUNCTUATION ||
+ Character.getType(c) == Character.OTHER_PUNCTUATION ||
+ c == '\'' || c == '\"' ||
+ // category EX as per UTR14
+ c == '!' || c == '?' || c == '\ufe56' || c == '\ufe57' || c == '\uff01' || c == '\uff1f' ||
+ c == '\n' || c == '\r' || c == '\u2028' || c == '\u2029' ||
+ c == '\u0003' || c == '\u2007' || c == '\u2011' ||
+ c == '\ufeff')
+ continue;
+ work.setCharAt(2, c);
+ e.setText(work.toString());
+ boolean saw2 = false;
+ for (int l = e.first(); l != BreakIterator.DONE; l = e.next())
+ if (l == 2)
+ saw2 = true;
+ if (!saw2) {
+ errln("Didn't get break between U+" + Integer.toHexString((int)
+ (work.charAt(1))) + " and U+" + Integer.toHexString(
+ (int)(work.charAt(2))));
+ errorCount++;
+ if (errorCount >= 75)
+ return;
+ }
+ }
+ }
+ }
+ */
+ }
+
+ public void TestCharacterInvariants()
+ {
+ BreakIterator e = BreakIterator.getCharacterInstance();
+ doBreakInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8"
+ + "\u11a9\u11aa");
+ doOtherInvariantTest(e, cannedTestChars + "\u1100\u1101\u1102\u1160\u1161\u1162\u11a8"
+ + "\u11a9\u11aa");
+ }
+
+ public void TestEmptyString()
+ {
+ String text = "";
+ Vector<String> x = new Vector<String>();
+ x.addElement(text);
+
+ generalIteratorTest(lineBreak, x);
+ }
+
+ public void TestGetAvailableLocales()
+ {
+ Locale[] locList = BreakIterator.getAvailableLocales();
+
+ if (locList.length == 0)
+ errln("getAvailableLocales() returned an empty list!");
+ // I have no idea how to test this function...
+ }
+
+
+ /**
+ * Bug 4095322
+ */
+ public void TestJapaneseLineBreak()
+ {
+ StringBuffer testString = new StringBuffer("\u4e00x\u4e8c");
+ // Breaking on <Kanji>$<Kanji> is inconsistent
+
+ /* Characters in precedingChars and followingChars have been updated
+ * from Unicode 2.0.14-based to 3.0.0-based when 4638433 was fixed.
+ * In concrete terms,
+ * 0x301F : Its category was changed from Ps to Pe since Unicode 2.1.
+ * 0x169B & 0x169C : added since Unicode 3.0.0.
+ */
+ String precedingChars =
+ /* Puctuation, Open */
+ "([{\u201a\u201e\u2045\u207d\u208d\u2329\u3008\u300a\u300c\u300e\u3010\u3014\u3016\u3018\u301a\u301d\ufe35\ufe37\ufe39\ufe3b\ufe3d\ufe3f\ufe41\ufe43\ufe59\ufe5b\ufe5d\uff08\uff3b\uff5b\uff62\u169b"
+ /* Punctuation, Initial quote */
+ + "\u00ab\u2018\u201b\u201c\u201f\u2039"
+ /* Symbol, Currency */
+ + "\u00a5\u00a3\u00a4\u20a0";
+
+ String followingChars =
+ /* Puctuation, Close */
+ ")]}\u2046\u207e\u208e\u232a\u3009\u300b\u300d\u300f\u3011\u3015\u3017\u3019\u301b\u301e\u301f\ufd3e\ufe36\ufe38\ufe3a\ufe3c\ufe3e\ufe40\ufe42\ufe44\ufe5a\ufe5c\ufe5e\uff09\uff3d\uff5d\uff63\u169c"
+ /* Punctuation, Final quote */
+ + "\u00bb\u2019\u201d\u203a"
+ /* Punctuation, Other */
+ + "!%,.:;\u3001\u3002\u2030\u2031\u2032\u2033\u2034"
+ /* Punctuation, Dash */
+ + "\u2103\u2109"
+ /* Symbol, Currency */
+ + "\u00a2"
+ /* Letter, Modifier */
+ + "\u3005\u309d\u309e"
+ /* Letter, Other */
+ + "\u3063\u3083\u3085\u3087\u30c3\u30e3\u30e5\u30e7\u30fc\u30fd\u30fe"
+ /* Mark, Non-Spacing */
+ + "\u0300\u0301\u0302"
+ /* Symbol, Modifier */
+ + "\u309b\u309c"
+ /* Symbol, Other */
+ + "\u00b0";
+
+ BreakIterator iter = BreakIterator.getLineInstance(Locale.JAPAN);
+
+ for (int i = 0; i < precedingChars.length(); i++) {
+ testString.setCharAt(1, precedingChars.charAt(i));
+ iter.setText(testString.toString());
+ int j = iter.first();
+ if (j != 0) {
+ errln("ja line break failure: failed to start at 0 and bounced at " + j);
+ }
+ j = iter.next();
+ if (j != 1) {
+ errln("ja line break failure: failed to stop before '"
+ + precedingChars.charAt(i) + "' (\\u"
+ + Integer.toString(precedingChars.charAt(i), 16)
+ + ") at 1 and bounded at " + j);
+ }
+ j = iter.next();
+ if (j != 3) {
+ errln("ja line break failure: failed to skip position after '"
+ + precedingChars.charAt(i) + "' (\\u"
+ + Integer.toString(precedingChars.charAt(i), 16)
+ + ") at 3 and bounded at " + j);
+ }
+ }
+
+ for (int i = 0; i < followingChars.length(); i++) {
+ testString.setCharAt(1, followingChars.charAt(i));
+ iter.setText(testString.toString());
+ int j = iter.first();
+ if (j != 0) {
+ errln("ja line break failure: failed to start at 0 and bounded at " + j);
+ }
+ j = iter.next();
+ if (j != 2) {
+ errln("ja line break failure: failed to skip position before '"
+ + followingChars.charAt(i) + "' (\\u"
+ + Integer.toString(followingChars.charAt(i), 16)
+ + ") at 2 and bounded at " + j);
+ }
+ j = iter.next();
+ if (j != 3) {
+ errln("ja line break failure: failed to stop after '"
+ + followingChars.charAt(i) + "' (\\u"
+ + Integer.toString(followingChars.charAt(i), 16)
+ + ") at 3 and bounded at " + j);
+ }
+ }
+ }
+
+ /**
+ * Bug 4638433
+ */
+ public void TestLineBreakBasedOnUnicode3_0_0()
+ {
+ BreakIterator iter;
+ int i;
+
+ /* Latin Extend-B characters
+ * 0x0218-0x0233 which have been added since Unicode 3.0.0.
+ */
+ iter = BreakIterator.getWordInstance(Locale.US);
+ iter.setText("\u0216\u0217\u0218\u0219\u021A");
+ i = iter.first();
+ i = iter.next();
+ if (i != 5) {
+ errln("Word break failure: failed to stop at 5 and bounded at " + i);
+ }
+
+
+ iter = BreakIterator.getLineInstance(Locale.US);
+
+ /* <Three(Nd)><Two(Nd)><Low Double Prime Quotation Mark(Pe)><One(Nd)>
+ * \u301f has changed its category from Ps to Pe since Unicode 2.1.
+ */
+ iter.setText("32\u301f1");
+ i = iter.first();
+ i = iter.next();
+ if (i != 3) {
+ errln("Line break failure: failed to skip before \\u301F(Pe) at 3 and bounded at " + i);
+ }
+
+ /* Mongolian <Letter A(Lo)><Todo Soft Hyphen(Pd)><Letter E(Lo)>
+ * which have been added since Unicode 3.0.0.
+ */
+ iter.setText("\u1820\u1806\u1821");
+ i = iter.first();
+ i = iter.next();
+ if (i != 2) {
+ errln("Mongolian line break failure: failed to skip position before \\u1806(Pd) at 2 and bounded at " + i);
+ }
+
+ /* Khmer <ZERO(Nd)><Currency Symbol(Sc)><ONE(Nd)> which have
+ * been added since Unicode 3.0.0.
+ */
+ iter.setText("\u17E0\u17DB\u17E1");
+ i = iter.first();
+ i = iter.next();
+ if (i != 1) {
+ errln("Khmer line break failure: failed to stop before \\u17DB(Sc) at 1 and bounded at " + i);
+ }
+ i = iter.next();
+ if (i != 3) {
+ errln("Khmer line break failure: failed to skip position after \\u17DB(Sc) at 3 and bounded at " + i);
+ }
+
+ /* Ogham <Letter UR(Lo)><Space Mark(Zs)><Letter OR(Lo)> which have
+ * been added since Unicode 3.0.0.
+ */
+ iter.setText("\u1692\u1680\u1696");
+ i = iter.first();
+ i = iter.next();
+ if (i != 2) {
+ errln("Ogham line break failure: failed to skip postion before \\u1680(Zs) at 2 and bounded at " + i);
+ }
+
+
+ // Confirm changes in BreakIteratorRules_th.java have been reflected.
+ iter = BreakIterator.getLineInstance(new Locale("th", ""));
+
+ /* Thai <Seven(Nd)>
+ * <Left Double Quotation Mark(Pi)>
+ * <Five(Nd)>
+ * <Right Double Quotation Mark(Pf)>
+ * <Three(Nd)>
+ */
+ iter.setText("\u0E57\u201C\u0E55\u201D\u0E53");
+ i = iter.first();
+ i = iter.next();
+ if (i != 1) {
+ errln("Thai line break failure: failed to stop before \\u201C(Pi) at 1 and bounded at " + i);
+ }
+ i = iter.next();
+ if (i != 4) {
+ errln("Thai line break failure: failed to stop after \\u201D(Pf) at 4 and bounded at " + i);
+ }
+ }
+
+ /**
+ * Bug 4068137
+ */
+ public void TestEndBehavior()
+ {
+ String testString = "boo.";
+ BreakIterator wb = BreakIterator.getWordInstance();
+ wb.setText(testString);
+
+ if (wb.first() != 0)
+ errln("Didn't get break at beginning of string.");
+ if (wb.next() != 3)
+ errln("Didn't get break before period in \"boo.\"");
+ if (wb.current() != 4 && wb.next() != 4)
+ errln("Didn't get break at end of string.");
+ }
+
+ // [serialization test has been removed pursuant to bug #4152965]
+
+ /**
+ * Bug 4450804
+ */
+ public void TestLineBreakContractions() {
+ Vector<String> expected = new Vector<String>();
+
+ expected.add("These ");
+ expected.add("are ");
+ expected.add("'foobles'. ");
+ expected.add("Don't ");
+ expected.add("you ");
+ expected.add("like ");
+ expected.add("them?");
+ generalIteratorTest(lineBreak, expected);
+ }
+
+}
diff --git a/test/java/text/BreakIterator/Bug4533872.java b/test/java/text/BreakIterator/Bug4533872.java
new file mode 100644
index 0000000000..64a4ccf569
--- /dev/null
+++ b/test/java/text/BreakIterator/Bug4533872.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4533872 4640853
+ * @library /java/text/testlib
+ * @summary Unit tests for supplementary character support (JSR-204) and Unicode 4.0 support
+ */
+
+import java.text.BreakIterator;
+import java.util.Locale;
+
+public class Bug4533872 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new Bug4533872().run(args);
+ }
+
+ static final String[] given = {
+ /* Lu Nd Lu Ll */
+ "XYZ12345 ABCDE abcde",
+ /* Nd Lo Nd Lu Po Lu Ll */
+ "123\uD800\uDC00345 ABC\uFF61XYZ abc",
+ /* Nd Lo Nd Lu Po Lu Ll */
+ "123\uD800\uDC00345 ABC\uD800\uDD00XYZ abc",
+ /* Lu Ll Cs Ll Cs Lu Lo Lu */
+ "ABCabc\uDC00xyz\uD800ABC\uD800\uDC00XYZ",
+ };
+
+ // Golden data for TestNext(), TestBoundar() and TestPrintEach*ward()
+ static final String[][] expected = {
+ {"XYZ12345", " ", "ABCDE", " ", "abcde"},
+ {"123\uD800\uDC00345", " ", "ABC", "\uFF61", "XYZ", " ", "abc"},
+ {"123\uD800\uDC00345", " ", "ABC", "\uD800\uDD00", "XYZ", " ", "abc"},
+ {"ABCabc", "\uDC00", "xyz", "\uD800", "ABC\uD800\uDC00XYZ"},
+ };
+
+ BreakIterator iter;
+ int start, end, current;
+
+ /*
+ * Test for next(int n)
+ */
+ void TestNext() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+ start = iter.first();
+ int j = expected[i].length - 1;
+ start = iter.next(j);
+ end = iter.next();
+
+ if (!expected[i][j].equals(given[i].substring(start, end))) {
+ errln("Word break failure: printEachForward() expected:<" +
+ expected[i][j] + ">, got:<" +
+ given[i].substring(start, end) +
+ "> start=" + start + " end=" + end);
+ }
+ }
+ }
+
+ /*
+ * Test for isBoundary(int n)
+ */
+ void TestIsBoundary() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+
+ start = iter.first();
+ end = iter.next();
+
+ while (end < given[i].length()) {
+ if (!iter.isBoundary(end)) {
+ errln("Word break failure: isBoundary() This should be a boundary. Index=" +
+ end + " for " + given[i]);
+ }
+ end = iter.next();
+ }
+ }
+ }
+
+
+ /*
+ * The followig test cases were made based on examples in BreakIterator's
+ * API Doc.
+ */
+
+ /*
+ * Test mainly for next() and current()
+ */
+ void TestPrintEachForward() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+ start = iter.first();
+
+ // Check current()'s return value - should be same as first()'s.
+ current = iter.current();
+ if (start != current) {
+ errln("Word break failure: printEachForward() Unexpected current value: current()=" +
+ current + ", expected(=first())=" + start);
+ }
+
+ int j = 0;
+ for (end = iter.next();
+ end != BreakIterator.DONE;
+ start = end, end = iter.next(), j++) {
+
+ // Check current()'s return value - should be same as next()'s.
+ current = iter.current();
+ if (end != current) {
+ errln("Word break failure: printEachForward() Unexpected current value: current()=" +
+ current + ", expected(=next())=" + end);
+ }
+
+ if (!expected[i][j].equals(given[i].substring(start, end))) {
+ errln("Word break failure: printEachForward() expected:<" +
+ expected[i][j] + ">, got:<" +
+ given[i].substring(start, end) +
+ "> start=" + start + " end=" + end);
+ }
+ }
+ }
+ }
+
+ /*
+ * Test mainly for previous() and current()
+ */
+ void TestPrintEachBackward() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+ end = iter.last();
+
+ // Check current()'s return value - should be same as last()'s.
+ current = iter.current();
+ if (end != current) {
+ errln("Word break failure: printEachBackward() Unexpected current value: current()=" +
+ current + ", expected(=last())=" + end);
+ }
+
+ int j;
+ for (start = iter.previous(), j = expected[i].length-1;
+ start != BreakIterator.DONE;
+ end = start, start = iter.previous(), j--) {
+
+ // Check current()'s return value - should be same as previous()'s.
+ current = iter.current();
+ if (start != current) {
+ errln("Word break failure: printEachBackward() Unexpected current value: current()=" +
+ current + ", expected(=previous())=" + start);
+ }
+
+ if (!expected[i][j].equals(given[i].substring(start, end))) {
+ errln("Word break failure: printEachBackward() expected:<" +
+ expected[i][j] + ">, got:<" +
+ given[i].substring(start, end) +
+ "> start=" + start + " end=" + end);
+ }
+ }
+ }
+ }
+
+ /*
+ * Test mainly for following() and previous()
+ */
+ void TestPrintAt_1() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ int[][] index = {
+ {2, 8, 10, 15, 17},
+ {1, 8, 10, 12, 15, 17, 20},
+ {3, 8, 10, 13, 16, 18, 20},
+ {4, 6, 9, 10, 16},
+ };
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+ for (int j = index[i].length-1; j >= 0; j--) {
+ end = iter.following(index[i][j]);
+ start = iter.previous();
+
+ if (!expected[i][j].equals(given[i].substring(start, end))) {
+ errln("Word break failure: printAt_1() expected:<" +
+ expected[i][j] + ">, got:<" +
+ given[i].substring(start, end) +
+ "> start=" + start + " end=" + end);
+ }
+ }
+ }
+ }
+
+ /*
+ * Test mainly for preceding() and next()
+ */
+ void TestPrintAt_2() {
+ iter = BreakIterator.getWordInstance(Locale.US);
+
+ int[][] index = {
+ {2, 9, 10, 15, 17},
+ {1, 9, 10, 13, 16, 18, 20},
+ {4, 9, 10, 13, 16, 18, 20},
+ {6, 7, 10, 11, 15},
+ };
+
+ for (int i = 0; i < given.length; i++) {
+ iter.setText(given[i]);
+
+ // Check preceding(0)'s return value - should equals BreakIterator.DONE.
+ if (iter.preceding(0) != BreakIterator.DONE) {
+ errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" +
+ iter.preceding(0));
+ }
+
+ for (int j = 0; j < index[i].length; j++) {
+ start = iter.preceding(index[i][j]);
+ end = iter.next();
+
+ if (!expected[i][j].equals(given[i].substring(start, end))) {
+ errln("Word break failure: printAt_2() expected:<" +
+ expected[i][j] + ">, got:<" +
+ given[i].substring(start, end) +
+ "> start=" + start + " end=" + end);
+ }
+ }
+
+ // Check next()'s return value - should equals BreakIterator.DONE.
+ end = iter.last();
+ start = iter.next();
+ if (start != BreakIterator.DONE) {
+ errln("Word break failure: printAt_2() expected:-1(BreakIterator.DONE), got:" + start);
+ }
+ }
+ }
+}
diff --git a/test/java/text/BreakIterator/Bug4740757.java b/test/java/text/BreakIterator/Bug4740757.java
new file mode 100644
index 0000000000..b60e70d0e8
--- /dev/null
+++ b/test/java/text/BreakIterator/Bug4740757.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2011, 2016, 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 4740757
+ * @summary Confirm line-breaking behavior of Hangul
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug4740757 {
+
+ private static boolean err = false;
+
+ public static void main(String[] args) {
+ Locale defaultLocale = Locale.getDefault();
+ if (defaultLocale.getLanguage().equals("th")) {
+ Locale.setDefault(Locale.KOREA);
+ test4740757();
+ Locale.setDefault(defaultLocale);
+ } else {
+ test4740757();
+ }
+
+ if (err) {
+ throw new RuntimeException("Incorrect Line-breaking");
+ }
+ }
+
+ private static void test4740757() {
+ String source = "\uc548\ub155\ud558\uc138\uc694? \uc88b\uc740 \uc544\uce68, \uc5ec\ubcf4\uc138\uc694! \uc548\ub155. End.";
+ String expected = "\uc548/\ub155/\ud558/\uc138/\uc694? /\uc88b/\uc740 /\uc544/\uce68, /\uc5ec/\ubcf4/\uc138/\uc694! /\uc548/\ub155. /End./";
+
+ BreakIterator bi = BreakIterator.getLineInstance(Locale.KOREAN);
+ bi.setText(source);
+ int start = bi.first();
+ int end = bi.next();
+ StringBuilder sb = new StringBuilder();
+
+ for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
+ sb.append(source.substring(start,end));
+ sb.append('/');
+ }
+
+ if (!expected.equals(sb.toString())) {
+ System.err.println("Failed: Hangul line-breaking failed." +
+ "\n\tExpected: " + expected +
+ "\n\tGot: " + sb +
+ "\nin " + Locale.getDefault() + " locale.");
+ err = true;
+ }
+ }
+
+}
diff --git a/test/java/text/BreakIterator/Bug4912404.java b/test/java/text/BreakIterator/Bug4912404.java
new file mode 100644
index 0000000000..07a2d0cb3c
--- /dev/null
+++ b/test/java/text/BreakIterator/Bug4912404.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4912404
+ * @summary Confirm that BreakIterator.equals(null) return false.
+ */
+
+import java.text.BreakIterator;
+
+public class Bug4912404 {
+
+ public static void main(String[] args) {
+ BreakIterator b = BreakIterator.getWordInstance();
+ b.setText("abc");
+ if (b.equals(null)) {
+ throw new RuntimeException("BreakIterator.equals(null) should return false.");
+ }
+ }
+}
diff --git a/test/java/text/BreakIterator/Bug4932583.java b/test/java/text/BreakIterator/Bug4932583.java
new file mode 100644
index 0000000000..a9d62d4439
--- /dev/null
+++ b/test/java/text/BreakIterator/Bug4932583.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003, 2016, 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
+ * @run main/timeout=60 Bug4932583
+ * @bug 4932583
+ * @summary Confirm that BreakIterator doesn't get caught in an infinite loop.
+ */
+
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class Bug4932583 {
+ public static void main(String[] args) {
+ BreakIterator iterator = BreakIterator.getCharacterInstance();
+ iterator.setText("\uDB40\uDFFF");
+ int boundary = iterator.next();
+ }
+}
diff --git a/test/java/text/BreakIterator/Bug6513074.java b/test/java/text/BreakIterator/Bug6513074.java
new file mode 100644
index 0000000000..736cde1768
--- /dev/null
+++ b/test/java/text/BreakIterator/Bug6513074.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2011, 2016, 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 6513074
+ * @summary Confirm that JIS X 0213 characters are processed in line-breaking properly.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug6513074 {
+
+ private static final String[][] source = {
+ {"\ufa30\ufa31 \ufa69\ufa6a",
+ "JIS X 0213 compatibility additions (\\uFA30-\\uFA6A)"},
+ };
+
+ private static final String[] expected_line = {
+ "\ufa30/\ufa31 /\ufa69/\ufa6a/",
+ };
+
+ private static final String[] expected_word = {
+ "\ufa30\ufa31/ /\ufa69\ufa6a/",
+ };
+
+ private static final String[] expected_char = {
+ "\ufa30/\ufa31/ /\ufa69/\ufa6a/",
+ };
+
+
+ private static boolean err = false;
+
+ public static void main(String[] args) {
+ Locale defaultLocale = Locale.getDefault();
+ if (defaultLocale.getLanguage().equals("th")) {
+ Locale.setDefault(Locale.JAPAN);
+ test6513074();
+ Locale.setDefault(defaultLocale);
+ } else {
+ test6513074();
+ }
+
+ if (err) {
+ throw new RuntimeException("Failed: Incorrect Text-breaking.");
+ }
+ }
+
+
+ private static void test6513074() {
+ BreakIterator bi = BreakIterator.getLineInstance(Locale.JAPAN);
+ for (int i = 0; i < source.length; i++) {
+ testBreakIterator(bi, "Line", source[i][0], expected_line[i], source[i][1]);
+ }
+
+ bi = BreakIterator.getWordInstance(Locale.JAPAN);
+ for (int i = 0; i < source.length; i++) {
+ testBreakIterator(bi, "Word", source[i][0], expected_word[i], source[i][1]);
+ }
+
+ bi = BreakIterator.getCharacterInstance(Locale.JAPAN);
+ for (int i = 0; i < source.length; i++) {
+ testBreakIterator(bi, "Character", source[i][0], expected_char[i], source[i][1]);
+ }
+ }
+
+ private static void testBreakIterator(BreakIterator bi,
+ String type,
+ String source,
+ String expected,
+ String description) {
+ bi.setText(source);
+ int start = bi.first();
+ int end = bi.next();
+ StringBuilder sb = new StringBuilder();
+
+ for (; end != BreakIterator.DONE; start = end, end = bi.next()) {
+ sb.append(source.substring(start,end));
+ sb.append('/');
+ }
+
+ if (!expected.equals(sb.toString())) {
+ System.err.println("Failed: Incorrect " + type + "-breaking for " +
+ description +
+ "\n\tExpected: " + toString(expected) +
+ "\n\tGot: " + toString(sb.toString()));
+ err = true;
+ }
+ }
+
+ private static String toString(String s) {
+ StringBuilder sb = new StringBuilder();
+
+ for (int i = 0; i < s.length(); i++) {
+ sb.append(" 0x" + Integer.toHexString(s.charAt(i)));
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/test/java/text/BreakIterator/NewVSOld_th_TH.java b/test/java/text/BreakIterator/NewVSOld_th_TH.java
new file mode 100644
index 0000000000..467cbc574c
--- /dev/null
+++ b/test/java/text/BreakIterator/NewVSOld_th_TH.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000, 2016, 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
+ @summary test Comparison of New Collators against Old Collators in the en_US locale
+*/
+
+import java.io.*;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.util.Locale;
+import java.text.BreakIterator;
+import java.lang.Math;
+
+public class NewVSOld_th_TH {
+ public static void main(String args[]) throws FileNotFoundException,
+ UnsupportedEncodingException,
+ IOException {
+ final String ENCODING = "UTF-8";
+ final Locale THAI_LOCALE = new Locale("th", "TH");
+
+ String rawFileName = "test_th_TH.txt";
+ String oldFileName = "broken_th_TH.txt";
+ StringBuilder rawText = new StringBuilder();
+ StringBuilder oldText = new StringBuilder();
+ StringBuilder cookedText = new StringBuilder();
+
+ File f;
+ f = new File(System.getProperty("test.src", "."), rawFileName);
+
+ try (InputStreamReader rawReader =
+ new InputStreamReader(new FileInputStream(f), ENCODING)) {
+ int c;
+ while ((c = rawReader.read()) != -1) {
+ rawText.append((char) c);
+ }
+ }
+
+ f = new File(System.getProperty("test.src", "."), oldFileName);
+ try (InputStreamReader oldReader =
+ new InputStreamReader(new FileInputStream(f), ENCODING)) {
+ int c;
+ while ((c = oldReader.read()) != -1) {
+ oldText.append((char) c);
+ }
+ }
+
+ BreakIterator breakIterator = BreakIterator.getWordInstance(THAI_LOCALE);
+ breakIterator.setText(rawText.toString());
+
+ int start = breakIterator.first();
+ for (int end = breakIterator.next();
+ end != BreakIterator.DONE;
+ start = end, end = breakIterator.next()) {
+ cookedText.append(rawText.substring(start, end));
+ cookedText.append("\n");
+ }
+
+ String cooked = cookedText.toString();
+ String old = oldText.toString();
+ if (cooked.compareTo(old) != 0) {
+ throw new RuntimeException("Text not broken the same as with the old BreakIterators");
+ }
+ }
+}
diff --git a/test/java/text/BreakIterator/broken_th_TH.txt b/test/java/text/BreakIterator/broken_th_TH.txt
new file mode 100644
index 0000000000..ca172c3333
--- /dev/null
+++ b/test/java/text/BreakIterator/broken_th_TH.txt
@@ -0,0 +1,13 @@
+การ
+เก็บ
+ภาษีประเทศ
+ไทยและ
+ประเทศ
+เดนมาร์ค
+อนุสัญญา
+ระหว่าง
+รัฐบาล
+แห่ง
+ประเทศ
+ไทย
+กับ
diff --git a/test/java/text/BreakIterator/test_th_TH.txt b/test/java/text/BreakIterator/test_th_TH.txt
new file mode 100644
index 0000000000..c423da033e
--- /dev/null
+++ b/test/java/text/BreakIterator/test_th_TH.txt
@@ -0,0 +1 @@
+การเก็บภาษีประเทศไทยและประเทศเดนมาร์คอนุสัญญาระหว่างรัฐบาลแห่งประเทศไทยกับ \ No newline at end of file
diff --git a/test/java/text/CharacterIterator/CharacterIteratorTest.java b/test/java/text/CharacterIterator/CharacterIteratorTest.java
new file mode 100644
index 0000000000..9d2d94b4d0
--- /dev/null
+++ b/test/java/text/CharacterIterator/CharacterIteratorTest.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test for Character Iterator
+ */
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+
+import java.text.*;
+
+public class CharacterIteratorTest extends IntlTest {
+ public static void main(String[] args) throws Exception {
+ new CharacterIteratorTest().run(args);
+ }
+
+ public CharacterIteratorTest() {
+ }
+
+ public void TestConstructionAndEquality() {
+ String testText = "Now is the time for all good men to come to the aid of their country.";
+ String testText2 = "Don't bother using this string.";
+
+ CharacterIterator test1 = new StringCharacterIterator(testText);
+ CharacterIterator test2 = new StringCharacterIterator(testText, 5);
+ CharacterIterator test3 = new StringCharacterIterator(testText, 2, 20, 5);
+ CharacterIterator test4 = new StringCharacterIterator(testText2);
+ CharacterIterator test5 = (CharacterIterator)test1.clone();
+
+ if (test1.equals(test2) || test1.equals(test3) || test1.equals(test4))
+ errln("Construation or equals() failed: Two unequal iterators tested equal");
+
+ if (!test1.equals(test5))
+ errln("clone() or equals() failed: Two clones tested unequal");
+
+ if (test1.hashCode() == test2.hashCode() || test1.hashCode() == test3.hashCode()
+ || test1.hashCode() == test4.hashCode())
+ errln("hash() failed: different objects have same hash code");
+
+ if (test1.hashCode() != test5.hashCode())
+ errln("hash() failed: identical objects have different hash codes");
+
+ test1.setIndex(5);
+ if (!test1.equals(test2) || test1.equals(test5))
+ errln("setIndex() failed");
+ }
+
+ public void TestIteration() {
+ String text = "Now is the time for all good men to come to the aid of their country.";
+
+ CharacterIterator iter = new StringCharacterIterator(text, 5);
+
+ if (iter.current() != text.charAt(5))
+ errln("Iterator didn't start out in the right place.");
+
+ char c = iter.first();
+ int i = 0;
+
+ if (iter.getBeginIndex() != 0 || iter.getEndIndex() != text.length())
+ errln("getBeginIndex() or getEndIndex() failed");
+
+ logln("Testing forward iteration...");
+ do {
+ if (c == CharacterIterator.DONE && i != text.length())
+ errln("Iterator reached end prematurely");
+ else if (c != text.charAt(i))
+ errln("Character mismatch at position " + i + ", iterator has " + c +
+ ", string has " + text.charAt(c));
+
+ if (iter.current() != c)
+ errln("current() isn't working right");
+ if (iter.getIndex() != i)
+ errln("getIndex() isn't working right");
+
+ if (c != CharacterIterator.DONE) {
+ c = iter.next();
+ i++;
+ }
+ } while (c != CharacterIterator.DONE);
+
+ c = iter.last();
+ i = text.length() - 1;
+
+ logln("Testing backward iteration...");
+ do {
+ if (c == CharacterIterator.DONE && i >= 0)
+ errln("Iterator reached end prematurely");
+ else if (c != text.charAt(i))
+ errln("Character mismatch at position " + i + ", iterator has " + c +
+ ", string has " + text.charAt(c));
+
+ if (iter.current() != c)
+ errln("current() isn't working right");
+ if (iter.getIndex() != i)
+ errln("getIndex() isn't working right");
+
+ if (c != CharacterIterator.DONE) {
+ c = iter.previous();
+ i--;
+ }
+ } while (c != CharacterIterator.DONE);
+
+ iter = new StringCharacterIterator(text, 5, 15, 10);
+ if (iter.getBeginIndex() != 5 || iter.getEndIndex() != 15)
+ errln("creation of a restricted-range iterator failed");
+
+ if (iter.getIndex() != 10 || iter.current() != text.charAt(10))
+ errln("starting the iterator in the middle didn't work");
+
+ c = iter.first();
+ i = 5;
+
+ logln("Testing forward iteration over a range...");
+ do {
+ if (c == CharacterIterator.DONE && i != 15)
+ errln("Iterator reached end prematurely");
+ else if (c != text.charAt(i))
+ errln("Character mismatch at position " + i + ", iterator has " + c +
+ ", string has " + text.charAt(c));
+
+ if (iter.current() != c)
+ errln("current() isn't working right");
+ if (iter.getIndex() != i)
+ errln("getIndex() isn't working right");
+
+ if (c != CharacterIterator.DONE) {
+ c = iter.next();
+ i++;
+ }
+ } while (c != CharacterIterator.DONE);
+
+ c = iter.last();
+ i = 14;
+
+ logln("Testing backward iteration over a range...");
+ do {
+ if (c == CharacterIterator.DONE && i >= 5)
+ errln("Iterator reached end prematurely");
+ else if (c != text.charAt(i))
+ errln("Character mismatch at position " + i + ", iterator has " + c +
+ ", string has " + text.charAt(c));
+
+ if (iter.current() != c)
+ errln("current() isn't working right");
+ if (iter.getIndex() != i)
+ errln("getIndex() isn't working right");
+
+ if (c != CharacterIterator.DONE) {
+ c = iter.previous();
+ i--;
+ }
+ } while (c != CharacterIterator.DONE);
+ }
+
+ /**
+ * @bug 4082050 4078261 4078255
+ */
+ public void TestPathologicalCases() {
+ String text = "This is only a test.";
+
+/*
+This test is commented out until API-change approval for bug #4082050 goes through.
+ // test for bug #4082050 (don't get an error if begin == end, even though all
+ // operations on the iterator will cause exceptions)
+ // [I actually fixed this so that you CAN create an iterator with begin == end,
+ // but all operations on it return DONE.]
+ CharacterIterator iter = new StringCharacterIterator(text, 5, 5, 5);
+ if (iter.first() != CharacterIterator.DONE
+ || iter.next() != CharacterIterator.DONE
+ || iter.last() != CharacterIterator.DONE
+ || iter.previous() != CharacterIterator.DONE
+ || iter.current() != CharacterIterator.DONE
+ || iter.getIndex() != 5)
+ errln("Got something other than DONE when performing operations on an empty StringCharacterIterator");
+*/
+CharacterIterator iter = null;
+
+ // if we try to construct a StringCharacterIterator with an endIndex that's off
+ // the end of the String under iterator, we're supposed to get an
+ // IllegalArgumentException
+ boolean gotException = false;
+ try {
+ iter = new StringCharacterIterator(text, 5, 100, 5);
+ }
+ catch (IllegalArgumentException e) {
+ gotException = true;
+ }
+ if (!gotException)
+ errln("StringCharacterIterator didn't throw an exception when given an invalid substring range.");
+
+ // test for bug #4078255 (getting wrong value from next() when we're at the end
+ // of the string)
+ iter = new StringCharacterIterator(text);
+ int expectedIndex = iter.getEndIndex();
+ int actualIndex;
+
+ iter.last();
+ actualIndex = iter.getIndex();
+ if (actualIndex != expectedIndex - 1)
+ errln("last() failed: expected " + (expectedIndex - 1) + ", got " + actualIndex);
+
+ iter.next();
+ actualIndex = iter.getIndex();
+ if (actualIndex != expectedIndex)
+ errln("next() after last() failed: expected " + expectedIndex + ", got " + actualIndex);
+
+ iter.next();
+ actualIndex = iter.getIndex();
+ if (actualIndex != expectedIndex)
+ errln("second next() after last() failed: expected " + expectedIndex + ", got " + actualIndex);
+ }
+
+ /*
+ * @bug 4123771 4051073
+ * #4123771 is actually a duplicate of bug #4051073, which was fixed some time ago, but
+ * no one ever added a regression test for it.
+ */
+ public void TestBug4123771() {
+ String text = "Some string for testing";
+ StringCharacterIterator iter = new StringCharacterIterator(text);
+ int index = iter.getEndIndex();
+ try {
+ char c = iter.setIndex(index);
+ }
+ catch (Exception e) {
+ System.out.println("method setIndex(int position) throws unexpected exception " + e);
+ System.out.println(" position: " + index);
+ System.out.println(" getEndIndex(): " + iter.getEndIndex());
+ System.out.println(" text.length(): " + text.length());
+ errln(""); // re-throw the exception through our test framework
+ }
+ }
+}
diff --git a/test/java/text/Collator/APITest.java b/test/java/text/Collator/APITest.java
new file mode 100644
index 0000000000..f2b0a019a2
--- /dev/null
+++ b/test/java/text/Collator/APITest.java
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Collation API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+import java.text.CollationElementIterator;
+
+public class APITest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new APITest().run(args);
+ }
+
+ final void doAssert(boolean condition, String message)
+ {
+ if (!condition) {
+ err("ERROR: ");
+ errln(message);
+ }
+ }
+
+ public final void TestProperty( )
+ {
+ Collator col = null;
+ try {
+ col = Collator.getInstance(Locale.ROOT);
+ logln("The property tests begin : ");
+ logln("Test ctors : ");
+ doAssert(col.compare("ab", "abc") < 0, "ab < abc comparison failed");
+ doAssert(col.compare("ab", "AB") < 0, "ab < AB comparison failed");
+ doAssert(col.compare("black-bird", "blackbird") > 0, "black-bird > blackbird comparison failed");
+ doAssert(col.compare("black bird", "black-bird") < 0, "black bird < black-bird comparison failed");
+ doAssert(col.compare("Hello", "hello") > 0, "Hello > hello comparison failed");
+
+ logln("Test ctors ends.");
+ logln("testing Collator.getStrength() method ...");
+ doAssert(col.getStrength() == Collator.TERTIARY, "collation object has the wrong strength");
+ doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+
+ logln("testing Collator.setStrength() method ...");
+ col.setStrength(Collator.SECONDARY);
+ doAssert(col.getStrength() != Collator.TERTIARY, "collation object's strength is secondary difference");
+ doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+ doAssert(col.getStrength() == Collator.SECONDARY, "collation object has the wrong strength");
+
+ logln("testing Collator.setDecomposition() method ...");
+ col.setDecomposition(Collator.NO_DECOMPOSITION);
+ doAssert(col.getDecomposition() != Collator.FULL_DECOMPOSITION, "collation object's strength is secondary difference");
+ doAssert(col.getDecomposition() != Collator.CANONICAL_DECOMPOSITION, "collation object's strength is primary difference");
+ doAssert(col.getDecomposition() == Collator.NO_DECOMPOSITION, "collation object has the wrong strength");
+ } catch (Exception foo) {
+ errln("Error : " + foo.getMessage());
+ errln("Default Collator creation failed.");
+ }
+ logln("Default collation property test ended.");
+ logln("Collator.getRules() testing ...");
+ doAssert(((RuleBasedCollator)col).getRules().length() != 0, "getRules() result incorrect" );
+ logln("getRules tests end.");
+ try {
+ col = Collator.getInstance(Locale.FRENCH);
+ col.setStrength(Collator.PRIMARY);
+ logln("testing Collator.getStrength() method again ...");
+ doAssert(col.getStrength() != Collator.TERTIARY, "collation object has the wrong strength");
+ doAssert(col.getStrength() == Collator.PRIMARY, "collation object's strength is not primary difference");
+
+ logln("testing French Collator.setStrength() method ...");
+ col.setStrength(Collator.TERTIARY);
+ doAssert(col.getStrength() == Collator.TERTIARY, "collation object's strength is not tertiary difference");
+ doAssert(col.getStrength() != Collator.PRIMARY, "collation object's strength is primary difference");
+ doAssert(col.getStrength() != Collator.SECONDARY, "collation object's strength is secondary difference");
+
+ } catch (Exception bar) {
+ errln("Error : " + bar.getMessage());
+ errln("Creating French collation failed.");
+ }
+
+ logln("Create junk collation: ");
+ Locale abcd = new Locale("ab", "CD", "");
+ Collator junk = null;
+ try {
+ junk = Collator.getInstance(abcd);
+ } catch (Exception err) {
+ errln("Error : " + err.getMessage());
+ errln("Junk collation creation failed, should at least return the collator for the base bundle.");
+ }
+ try {
+ col = Collator.getInstance(Locale.ROOT);
+ doAssert(col.equals(junk), "The base bundle's collation should be returned.");
+ } catch (Exception exc) {
+ errln("Error : " + exc.getMessage());
+ errln("Default collation comparison, caching not working.");
+ }
+
+ logln("Collator property test ended.");
+ }
+
+ public final void TestHashCode( )
+ {
+ logln("hashCode tests begin.");
+ Collator col1 = null;
+ try {
+ col1 = Collator.getInstance(Locale.ROOT);
+ } catch (Exception foo) {
+ errln("Error : " + foo.getMessage());
+ errln("Default collation creation failed.");
+ }
+ Collator col2 = null;
+ Locale dk = new Locale("da", "DK", "");
+ try {
+ col2 = Collator.getInstance(dk);
+ } catch (Exception bar) {
+ errln("Error : " + bar.getMessage());
+ errln("Danish collation creation failed.");
+ return;
+ }
+ Collator col3 = null;
+ try {
+ col3 = Collator.getInstance(Locale.ROOT);
+ } catch (Exception err) {
+ errln("Error : " + err.getMessage());
+ errln("2nd default collation creation failed.");
+ }
+ logln("Collator.hashCode() testing ...");
+
+ if (col1 != null) {
+ doAssert(col1.hashCode() != col2.hashCode(), "Hash test1 result incorrect");
+ if (col3 != null) {
+ doAssert(col1.hashCode() == col3.hashCode(), "Hash result not equal");
+ }
+ }
+
+ logln("hashCode tests end.");
+ }
+
+ //----------------------------------------------------------------------------
+ // ctor -- Tests the constructor methods
+ //
+ public final void TestCollationKey( )
+ {
+ logln("testing CollationKey begins...");
+ Collator col = null;
+ try {
+ col = Collator.getInstance(Locale.ROOT);
+ } catch (Exception foo) {
+ errln("Error : " + foo.getMessage());
+ errln("Default collation creation failed.");
+ }
+ if (col == null) {
+ return;
+ }
+
+ String test1 = "Abcda", test2 = "abcda";
+ logln("Use tertiary comparison level testing ....");
+ CollationKey sortk1 = col.getCollationKey(test1);
+ CollationKey sortk2 = col.getCollationKey(test2);
+ doAssert(sortk1.compareTo(sortk2) > 0,
+ "Result should be \"Abcda\" >>> \"abcda\"");
+ CollationKey sortk3 = sortk2;
+ CollationKey sortkNew = sortk1;
+ doAssert(sortk1 != sortk2, "The sort keys should be different");
+ doAssert(sortk1.hashCode() != sortk2.hashCode(), "sort key hashCode() failed");
+ doAssert(sortk2.compareTo(sortk3) == 0, "The sort keys should be the same");
+ doAssert(sortk1 == sortkNew, "The sort keys assignment failed");
+ doAssert(sortk1.hashCode() == sortkNew.hashCode(), "sort key hashCode() failed");
+ doAssert(sortkNew != sortk3, "The sort keys should be different");
+ doAssert(sortk1.compareTo(sortk3) > 0, "Result should be \"Abcda\" >>> \"abcda\"");
+ doAssert(sortk2.compareTo(sortk3) == 0, "Result should be \"abcda\" == \"abcda\"");
+ long cnt1, cnt2;
+ byte byteArray1[] = sortk1.toByteArray();
+ byte byteArray2[] = sortk2.toByteArray();
+ doAssert(byteArray1 != null && byteArray2 != null, "CollationKey.toByteArray failed.");
+ logln("testing sortkey ends...");
+ }
+ //----------------------------------------------------------------------------
+ // ctor -- Tests the constructor methods
+ //
+ public final void TestElemIter( )
+ {
+ logln("testing sortkey begins...");
+ Collator col = null;
+ try {
+ col = Collator.getInstance();
+ } catch (Exception foo) {
+ errln("Error : " + foo.getMessage());
+ errln("Default collation creation failed.");
+ }
+ RuleBasedCollator rbCol;
+ if (col instanceof RuleBasedCollator) {
+ rbCol = (RuleBasedCollator) col;
+ } else {
+ return;
+ }
+ String testString1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?";
+ String testString2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?";
+ logln("Constructors and comparison testing....");
+ CollationElementIterator iterator1 = rbCol.getCollationElementIterator(testString1);
+ CollationElementIterator iterator2 = rbCol.getCollationElementIterator(testString1);
+ CollationElementIterator iterator3 = rbCol.getCollationElementIterator(testString2);
+ int order1, order2, order3;
+ order1 = iterator1.next();
+ order2 = iterator2.next();
+ doAssert(order1 == order2, "The order result should be the same");
+
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.primaryOrder(order1)
+ == CollationElementIterator.primaryOrder(order3),
+ "The primary orders should be the same");
+ doAssert(CollationElementIterator.secondaryOrder(order1)
+ == CollationElementIterator.secondaryOrder(order3),
+ "The secondary orders should be the same");
+ doAssert(CollationElementIterator.tertiaryOrder(order1)
+ == CollationElementIterator.tertiaryOrder(order3),
+ "The tertiary orders should be the same");
+
+ order1 = iterator1.next();
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.primaryOrder(order1)
+ == CollationElementIterator.primaryOrder(order3),
+ "The primary orders should be identical");
+ doAssert(CollationElementIterator.tertiaryOrder(order1)
+ != CollationElementIterator.tertiaryOrder(order3),
+ "The tertiary orders should be different");
+
+ order1 = iterator1.next();
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.secondaryOrder(order1)
+ != CollationElementIterator.secondaryOrder(order3),
+ "The secondary orders should be different");
+ doAssert(order1 != CollationElementIterator.NULLORDER,
+ "Unexpected end of iterator reached");
+
+ iterator1.reset();
+ iterator2.reset();
+ iterator3.reset();
+ order1 = iterator1.next();
+ order2 = iterator2.next();
+ doAssert(order1 == order2, "The order result should be the same");
+
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.primaryOrder(order1)
+ == CollationElementIterator.primaryOrder(order3),
+ "The orders should be the same");
+ doAssert(CollationElementIterator.secondaryOrder(order1)
+ == CollationElementIterator.secondaryOrder(order3),
+ "The orders should be the same");
+ doAssert(CollationElementIterator.tertiaryOrder(order1)
+ == CollationElementIterator.tertiaryOrder(order3),
+ "The orders should be the same");
+
+ order1 = iterator1.next();
+ order2 = iterator2.next();
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.primaryOrder(order1)
+ == CollationElementIterator.primaryOrder(order3),
+ "The primary orders should be identical");
+ doAssert(CollationElementIterator.tertiaryOrder(order1)
+ != CollationElementIterator.tertiaryOrder(order3),
+ "The tertiary orders should be different");
+
+ order1 = iterator1.next();
+ order3 = iterator3.next();
+ doAssert(CollationElementIterator.secondaryOrder(order1)
+ != CollationElementIterator.secondaryOrder(order3),
+ "The secondary orders should be different");
+ doAssert(order1 != CollationElementIterator.NULLORDER, "Unexpected end of iterator reached");
+ logln("testing CollationElementIterator ends...");
+ }
+
+ public final void TestGetAll()
+ {
+ Locale[] list = Collator.getAvailableLocales();
+ for (int i = 0; i < list.length; ++i) {
+ log("Locale name: ");
+ log(list[i].toString());
+ log(" , the display name is : ");
+ logln(list[i].getDisplayName());
+ }
+ }
+}
diff --git a/test/java/text/Collator/Bug6271411.java b/test/java/text/Collator/Bug6271411.java
new file mode 100644
index 0000000000..16495d04be
--- /dev/null
+++ b/test/java/text/Collator/Bug6271411.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6271411
+ * @library /java/text/testlib
+ * @summary Confirm that three JCK testcases for CollationElementIterator pass.
+ */
+
+import java.text.*;
+
+/*
+ * Based on JCK-runtime-15/tests/api/java_text/CollationElementIterator/ColltnElmtIterTests.java.
+ */
+public class Bug6271411 extends IntlTest {
+
+ public static void main(String argv[]) throws Exception {
+ Bug6271411 test = new Bug6271411();
+ test.run(argv);
+ }
+
+ /*
+ * Rule for RuleBasedCollator
+ */
+ static final String rule = "< c, C < d; D";
+
+ /*
+ * Textdata
+ */
+ static final String[] values = {
+ "", "c", "cH522Yd", "Hi, high school", "abcchCHidD"
+ };
+
+
+ /*
+ * Confirm that setOffset() throws IllegalArgumentException
+ * (not IndexOutOfBoundsException) if the given offset is invalid.
+ * Use CollationElementIterator.setText(String).
+ */
+ public void Test_CollationElementIterator0007() throws Exception {
+ int[] offsets = {
+ Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000, -2, -1,
+ 100, 101, // These two are customized for every test data later.
+ 12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
+ };
+ boolean err = false;
+
+ RuleBasedCollator rbc = new RuleBasedCollator(rule);
+ CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+ for (int i = 0; i < values.length; i++) {
+ String source = values[i];
+ iterator.setText(source);
+
+ int len = source.length();
+ offsets[5] = len + 1;
+ offsets[6] = len + 2;
+
+ for (int j = 0; j < offsets.length; j++) {
+ try {
+ iterator.setOffset(offsets[j]);
+ System.out.println("IllegalArgumentException should be thrown for setOffset(" +
+ offsets[j] + ") for <" + source + ">.");
+ err = true;
+ }
+ catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ if (err) {
+ errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException.");
+ }
+ }
+
+ /*
+ * Confirm that setText() doesn't throw an exception and setOffset() throws
+ * IllegalArgumentException if the given offset is invalid.
+ * Use CollationElementIterator.setText(CharacterIterator).
+ */
+ public void Test_CollationElementIterator0010() throws Exception {
+ String prefix = "xyz abc";
+ String suffix = "1234567890";
+ int begin = prefix.length();
+ int[] offsets = {
+ Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -10000,
+ -2, -1, 0, 1, begin - 2, begin - 1, 9, 10, 11, 12, 13, 14,
+ 15, 12345, Integer.MAX_VALUE - 1, Integer.MAX_VALUE
+ };
+ boolean err = false;
+
+ RuleBasedCollator rbc = new RuleBasedCollator(rule);
+ CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+ for (int i = 0; i < values.length; i++) {
+ String str = prefix + values[i] + suffix;
+ int len = str.length();
+ int end = len - suffix.length();
+
+ CharacterIterator source =
+ new StringCharacterIterator(str, begin, end, begin);
+ iterator.setText(source);
+
+ offsets[9] = end + 1;
+ offsets[10] = end + 2;
+ offsets[11] = (end + len) / 2;
+ offsets[12] = len - 1;
+ offsets[13] = len;
+ offsets[14] = len + 1;
+ offsets[15] = len + 2;
+
+ for (int j = 0; j < offsets.length; j++) {
+ try {
+ iterator.setOffset(offsets[j]);
+
+ System.out.println("IllegalArgumentException should be thrown for setOffset(" +
+ offsets[j] + ") for <" + str + ">.");
+ err = true;
+ }
+ catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ if (err) {
+ errln("CollationElementIterator.setOffset() didn't throw an expected IllegalArguemntException.");
+ }
+ }
+
+ /*
+ * Confirm that setText() doesn't throw an exception and setOffset() sets
+ * an offset as expected.
+ * Use CollationElementIterator.setText(CharacterIterator).
+ */
+ public void Test_CollationElementIterator0011() throws Exception {
+ String prefix = "xyz abc";
+ String suffix = "1234567890";
+ int begin = prefix.length();
+ int[] offsets = { begin, begin + 1, 2, 3, 4 };
+
+ RuleBasedCollator rbc = new RuleBasedCollator(rule);
+ CollationElementIterator iterator = rbc.getCollationElementIterator("");
+
+ for (int i = 0; i < values.length; i++) {
+ String str = prefix + values[i] + suffix;
+ int len = str.length();
+ int end = len - suffix.length();
+ CharacterIterator source =
+ new StringCharacterIterator(str, begin, end, begin);
+ iterator.setText(source);
+
+ offsets[2] = (end + len) / 2;
+ offsets[3] = len - 1;
+ offsets[4] = len;
+
+ for (int j = 0; j < offsets.length; j++) {
+ int offset = offsets[j];
+
+ if (offset < begin || offset > end) {
+ break;
+ }
+
+ iterator.setOffset(offset);
+ int newOffset = iterator.getOffset();
+
+ if (newOffset != offset) {
+ throw new RuntimeException("setOffset() didn't set a correct offset. Got: " +
+ newOffset + " Expected: " + offset + " for <" + str + ">.");
+ }
+ }
+ }
+ }
+}
diff --git a/test/java/text/Collator/CollationKeyTest.java b/test/java/text/Collator/CollationKeyTest.java
new file mode 100644
index 0000000000..9146bf97e9
--- /dev/null
+++ b/test/java/text/Collator/CollationKeyTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4106263
+ * @summary Tests on the bug 4106263 - CollationKey became non-final extendable class.
+ * The implementation of CollationKey is moved to the new private class,
+ * RuleBasedCollationKey. This test basically tests on the two features:
+ * 1. Existing code using CollationKey works (backward compatiblility)
+ * 2. CollationKey can be extended by its subclass.
+ */
+
+
+public class CollationKeyTest {
+
+ public static void main(String[] args) {
+ CollationKeyTestImpl ck = new CollationKeyTestImpl("Testing the CollationKey");
+ ck.run();
+ }
+}
diff --git a/test/java/text/Collator/CollationKeyTestImpl.java b/test/java/text/Collator/CollationKeyTestImpl.java
new file mode 100644
index 0000000000..a017c81718
--- /dev/null
+++ b/test/java/text/Collator/CollationKeyTestImpl.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1997, 2016, 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.
+ */
+
+/*
+ *
+ * A part of tests on the bug 4106263. CollationKey became non-final extendable class.
+ * The implementation of CollationKey is moved to the new private class,
+ * RuleBasedCollationKey. This test basically tests on the two features:
+ * 1. Existing code using CollationKey works (backward compatiblility)
+ * 2. CollationKey can be extended by its subclass.
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.CollationKey;
+import java.io.*;
+
+import java.text.*;
+
+
+public class CollationKeyTestImpl extends CollationKey {
+
+ private static String[] sourceData_ja = {
+ "\u3042\u3044\u3046\u3048\u3048",
+ "\u3041\u3043\u3045\u3047\u3049",
+ "\u3052\u3054\u3056\u3058\u3058",
+ "\u3051\u3053\u3055\u3057\u3059",
+ "\u3062\u3064\u3066\u3068\u3068",
+ "\u3061\u3063\u3065\u3067\u3069",
+ "\u3072\u3074\u3075\u3078\u3078",
+ "\u3071\u3073\u3075\u3077\u3079",
+ "\u3082\u3084\u3085\u3088\u3088",
+ "\u3081\u3083\u3085\u3087\u3089",
+ "\u30a2\u30a4\u30a6\u30a8\u30aa",
+ "\u30a1\u30a3\u30a5\u30a7\u30a9",
+ "\u30c2\u30c4\u30c6\u30c8\u30ca",
+ "\u30c1\u30c3\u30c5\u30c7\u30c9",
+ "\u30b2\u30b4\u30b6\u30b8\u30ba",
+ "\u30b1\u30b3\u30b5\u30b7\u30b9",
+ "\u30d2\u30d4\u30d6\u30d8\u30da",
+ "\u30d1\u30d3\u30d5\u30d7\u30d9",
+ "\u30e2\u30e4\u30e6\u30e8\u30ea",
+ "\u30e1\u30e3\u30e5\u30e7\u30e9"
+ };
+ private static final String[] targetData_ja = {
+ "\u3042\u3044\u3046\u3048\u3048",
+ "\u3041\u3043\u3045\u3047\u3049",
+ "\u30a2\u30a4\u30a6\u30a8\u30aa",
+ "\u30a1\u30a3\u30a5\u30a7\u30a9",
+ "\u3052\u3054\u3056\u3058\u3058",
+ "\u3051\u3053\u3055\u3057\u3059",
+ "\u30b1\u30b3\u30b5\u30b7\u30b9",
+ "\u30b2\u30b4\u30b6\u30b8\u30ba",
+ "\u3061\u3063\u3065\u3067\u3069",
+ "\u30c1\u30c3\u30c5\u30c7\u30c9",
+ "\u3062\u3064\u3066\u3068\u3068",
+ "\u30c2\u30c4\u30c6\u30c8\u30ca",
+ "\u3071\u3073\u3075\u3077\u3079",
+ "\u30d1\u30d3\u30d5\u30d7\u30d9",
+ "\u3072\u3074\u3075\u3078\u3078",
+ "\u30d2\u30d4\u30d6\u30d8\u30da",
+ "\u3081\u3083\u3085\u3087\u3089",
+ "\u30e1\u30e3\u30e5\u30e7\u30e9",
+ "\u3082\u3084\u3085\u3088\u3088",
+ "\u30e2\u30e4\u30e6\u30e8\u30ea"
+ };
+
+ public void run() {
+ /** debug: printout the test data
+ for (int i=0; i<sourceData_ja.length; i++){
+ System.out.println(i+": "+sourceData_ja[i]);
+ }
+ **/
+ /*
+ * 1. Test the backward compatibility
+ * note: targetData_ja.length is equal to sourceData_ja.length
+ */
+ Collator myCollator = Collator.getInstance(Locale.JAPAN);
+ CollationKey[] keys = new CollationKey[sourceData_ja.length];
+ CollationKey[] target_keys = new CollationKey[targetData_ja.length];
+ for (int i=0; i<sourceData_ja.length; i++){
+ keys[i] = myCollator.getCollationKey(sourceData_ja[i]);
+ target_keys[i] = myCollator.getCollationKey(targetData_ja[i]); //used later
+ }
+ /* Sort the string using CollationKey */
+ InsertionSort(keys);
+ /** debug: printout the result after sort
+ System.out.println("--- After Sorting ---");
+ for (int i=0; i<sourceData_ja.length; i++){
+ System.out.println(i+" :"+keys[i].getSourceString());
+ }
+ **/
+ /*
+ * Compare the result using equals method and getSourceString method.
+ */
+ boolean pass = true;
+ for (int i=0; i<sourceData_ja.length; i++){
+ /* Comparing using String.equals: in order to use getStringSource() */
+ if (! targetData_ja[i].equals(keys[i].getSourceString())){
+ throw new RuntimeException("FAILED: CollationKeyTest backward compatibility "
+ +"while comparing" +targetData_ja[i]+" vs "
+ +keys[i].getSourceString());
+ }
+ /* Comparing using CollaionKey.equals: in order to use equals() */
+ if (! target_keys[i].equals(keys[i])){
+ throw new RuntimeException("FAILED: CollationKeyTest backward compatibility."
+ +" Using CollationKey.equals " +targetData_ja[i]
+ +" vs " +keys[i].getSourceString());
+ }
+ /* Comparing using CollaionKey.hashCode(): in order to use hashCode() */
+ if (target_keys[i].hashCode() != keys[i].hashCode()){
+ throw new RuntimeException("FAILED: CollationKeyTest backward compatibility."
+ +" Using CollationKey.hashCode " +targetData_ja[i]
+ +" vs " +keys[i].getSourceString());
+ }
+ /* Comparing using CollaionKey.toByteArray(): in order to use toByteArray() */
+ byte[] target_bytes = target_keys[i].toByteArray();
+ byte[] source_bytes = keys[i].toByteArray();
+ for (int j=0; j<target_bytes.length; j++){
+ Byte targetByte = new Byte(target_bytes[j]);
+ Byte sourceByte = new Byte(source_bytes[j]);
+ if (targetByte.compareTo(sourceByte)!=0){
+ throw new RuntimeException("FAILED: CollationKeyTest backward "
+ +"compatibility. Using Byte.compareTo from CollationKey.toByteArray "
+ +targetData_ja[i]
+ +" vs " +keys[i].getSourceString());
+ }
+ }
+ }
+ testSubclassMethods();
+ testConstructor();
+ }
+
+ /*
+ * Sort the array of CollationKey using compareTo method in insertion sort.
+ */
+ private void InsertionSort(CollationKey[] keys){
+ int f, i;
+ CollationKey tmp;
+
+ for (f=1; f < keys.length; f++){
+ if(keys[f].compareTo( keys[f-1]) > 0){
+ continue;
+ }
+ tmp = keys[f];
+ i = f-1;
+ while ( (i>=0) && (keys[i].compareTo(tmp) > 0) ) {
+ keys[i+1] = keys[i];
+ i--;
+ }
+ keys[i+1]=tmp;
+ }
+ }
+
+
+ /*
+ * From here is the bogus methods to test the subclass of
+ * the CollationKey class.
+ */
+ public CollationKeyTestImpl(String str){
+ super (str);
+ // debug: System.out.println("CollationKeyTest extends CollationKey class: "+str);
+ }
+ /* abstract method: needs to be implemented */
+ public byte[] toByteArray(){
+ String foo= "Hello";
+ return foo.getBytes();
+ }
+ /* abstract method: needs to be implemented */
+ public int compareTo(CollationKey target){
+ return 0;
+ }
+ public boolean equals(Object target){
+ return true;
+ }
+ public String getSourceString(){
+ return "CollationKeyTestImpl";
+ }
+ /*
+ * This method tests the collection of bugus methods from the extended
+ * subclass of CollationKey class.
+ */
+ private void testSubclassMethods() {
+ CollationKeyTestImpl clt1 = new CollationKeyTestImpl("testSubclassMethods-1");
+ CollationKeyTestImpl clt2 = new CollationKeyTestImpl("testSubclassMethods-2");
+ // extended method, equals always returns true
+ if (!clt1.equals(clt2)){
+ throw new RuntimeException("Failed: equals(CollationKeySubClass)");
+ }
+ // extended method, compareTo always returns 0
+ if (clt1.compareTo(clt2)!=0){
+ throw new RuntimeException("Failed: compareTo(CollationKeySubClass)");
+ }
+ // overriding extended method, getSourceString always returns "CollationKeyTestImpl"
+ if (! clt1.getSourceString().equals("CollationKeyTestImpl")){
+ throw new RuntimeException("Failed: CollationKey subclass overriding getSourceString()");
+ }
+ // extended method, toByteArray always returns bytes from "Hello"
+ String str2 = new String( clt2.toByteArray());
+ if (! clt2.equals("Hello")){
+ throw new RuntimeException("Failed: CollationKey subclass toByteArray()");
+ }
+ }
+
+ /*
+ * This method tests CollationKey constructor with null source string.
+ * It should throw NPE.
+ */
+ private void testConstructor() {
+ boolean npe=false;
+ try{
+ CollationKeyTestImpl cltNull = new CollationKeyTestImpl(null);
+ } catch (NullPointerException npException){
+ npe=true;
+ // debug: System.out.println("--- NPE is thrown with NULL arguement: PASS ---");
+ }
+ if(!npe){
+ throw new RuntimeException("Failed: CollationKey Constructor with null source"+
+ " didn't throw NPE!");
+ }
+ }
+
+}
diff --git a/test/java/text/Collator/CollatorTest.java b/test/java/text/Collator/CollatorTest.java
new file mode 100644
index 0000000000..bb6785b888
--- /dev/null
+++ b/test/java/text/Collator/CollatorTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1998, 2016, 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.reflect.*;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.Vector;
+import java.io.*;
+import java.text.*;
+
+/**
+ * CollatorTest is a base class for tests that can be run conveniently from
+ * the command line as well as under the Java test harness.
+ * <p>
+ * Sub-classes implement a set of methods named Test<something>. Each
+ * of these methods performs some test. Test methods should indicate
+ * errors by calling either err or errln. This will increment the
+ * errorCount field and may optionally print a message to the log.
+ * Debugging information may also be added to the log via the log
+ * and logln methods. These methods will add their arguments to the
+ * log only if the test is being run in verbose mode.
+ */
+public abstract class CollatorTest extends IntlTest {
+
+ //------------------------------------------------------------------------
+ // These methods are utilities specific to the Collation tests..
+ //------------------------------------------------------------------------
+
+ protected void assertEqual(CollationElementIterator i1, CollationElementIterator i2) {
+ int c1, c2, count = 0;
+ do {
+ c1 = i1.next();
+ c2 = i2.next();
+ if (c1 != c2) {
+ errln(" " + count + ": " + c1 + " != " + c2);
+ break;
+ }
+ count++;
+ } while (c1 != CollationElementIterator.NULLORDER);
+ }
+
+ // Replace nonprintable characters with unicode escapes
+ static protected String prettify(String str) {
+ StringBuffer result = new StringBuffer();
+
+ String zero = "0000";
+
+ for (int i = 0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ if (ch < 0x09 || (ch > 0x0A && ch < 0x20)|| (ch > 0x7E && ch < 0xA0) || ch > 0x100) {
+ String hex = Integer.toString((int)ch,16);
+
+ result.append("\\u" + zero.substring(0, 4 - hex.length()) + hex);
+ } else {
+ result.append(ch);
+ }
+ }
+ return result.toString();
+ }
+
+ // Produce a printable representation of a CollationKey
+ static protected String prettify(CollationKey key) {
+ StringBuffer result = new StringBuffer();
+ byte[] bytes = key.toByteArray();
+
+ for (int i = 0; i < bytes.length; i += 2) {
+ int val = (bytes[i] << 8) + bytes[i+1];
+ result.append(Integer.toString(val, 16) + " ");
+ }
+ return result.toString();
+ }
+
+ //------------------------------------------------------------------------
+ // Everything below here is boilerplate code that makes it possible
+ // to add a new test by simply adding a function to an existing class
+ //------------------------------------------------------------------------
+
+ protected void doTest(Collator col, int strength,
+ String[] source, String[] target, int[] result) {
+ if (source.length != target.length) {
+ errln("Data size mismatch: source = " +
+ source.length + ", target = " + target.length);
+
+ return; // Return if "-nothrow" is specified.
+ }
+ if (source.length != result.length) {
+ errln("Data size mismatch: source & target = " +
+ source.length + ", result = " + result.length);
+
+ return; // Return if "-nothrow" is specified.
+ }
+
+ col.setStrength(strength);
+ for (int i = 0; i < source.length ; i++) {
+ doTest(col, source[i], target[i], result[i]);
+ }
+ }
+
+ protected void doTest(Collator col,
+ String source, String target, int result) {
+ char relation = '=';
+ if (result <= -1) {
+ relation = '<';
+ } else if (result >= 1) {
+ relation = '>';
+ }
+
+ int compareResult = col.compare(source, target);
+ CollationKey sortKey1 = col.getCollationKey(source);
+ CollationKey sortKey2 = col.getCollationKey(target);
+ int keyResult = sortKey1.compareTo(sortKey2);
+ if (compareResult != keyResult) {
+ errln("Compare and Collation Key results are different! Source = " +
+ source + " Target = " + target);
+ }
+ if (keyResult != result) {
+ errln("Collation Test failed! Source = " + source + " Target = " +
+ target + " result should be " + relation);
+ }
+ }
+}
diff --git a/test/java/text/Collator/CurrencyCollate.java b/test/java/text/Collator/CurrencyCollate.java
new file mode 100644
index 0000000000..e8f5041859
--- /dev/null
+++ b/test/java/text/Collator/CurrencyCollate.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4114080 4150807
+ * @summary Test currency collation. For bug 4114080, make sure the collation
+ * of the euro sign behaves properly. For bug 4150807, make sure the collation
+ * order of ALL the current symbols is correct. This means they sort
+ * in English alphabetical order of their English names. This test can be
+ * easily extended to do simple spot checking. See other collation tests for
+ * more sophisticated testing.
+ */
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+
+/* Author: Alan Liu
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ */
+public class CurrencyCollate {
+ static Collator myCollation = Collator.getInstance(Locale.US);
+
+ public static void main(String[] args) {
+ String[] DATA = {
+ "\u20AC", ">", "$", // euro > dollar
+ "\u20AC", "<", "\u00A3", // euro < pound
+
+ // additional tests for general currency sort order (bug #4150807)
+ "\u00a4", "<", "\u0e3f", // generic currency < baht
+ "\u0e3f", "<", "\u00a2", // baht < cent
+ "\u00a2", "<", "\u20a1", // cent < colon
+ "\u20a1", "<", "\u20a2", // colon < cruzeiro
+ "\u20a2", "<", "\u0024", // cruzeiro < dollar
+ "\u0024", "<", "\u20ab", // dollar < dong
+ "\u20ab", "<", "\u20a3", // dong < franc
+ "\u20a3", "<", "\u20a4", // franc < lira
+ "\u20a4", "<", "\u20a5", // lira < mill
+ "\u20a5", "<", "\u20a6", // mill < naira
+ "\u20a6", "<", "\u20a7", // naira < peseta
+ "\u20a7", "<", "\u00a3", // peseta < pound
+ "\u00a3", "<", "\u20a8", // pound < rupee
+ "\u20a8", "<", "\u20aa", // rupee < shekel
+ "\u20aa", "<", "\u20a9", // shekel < won
+ "\u20a9", "<", "\u00a5" // won < yen
+ };
+ for (int i=0; i<DATA.length; i+=3) {
+ int expected = DATA[i+1].equals(">") ? 1 : (DATA[i+1].equals("<") ? -1 : 0);
+ int actual = myCollation.compare(DATA[i], DATA[i+2]);
+ if (actual != expected) {
+ throw new RuntimeException("Collation of " +
+ DATA[i] + " vs. " +
+ DATA[i+2] + " yields " + actual +
+ "; expected " + expected);
+ }
+ }
+ System.out.println("Ok");
+ }
+}
+
+//eof
diff --git a/test/java/text/Collator/DanishTest.java b/test/java/text/Collator/DanishTest.java
new file mode 100644
index 0000000000..b5194a83c2
--- /dev/null
+++ b/test/java/text/Collator/DanishTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4930708 4174436 5008498
+ * @library /java/text/testlib
+ * @summary test Danish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class DanishTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new DanishTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "Lvi",
+ "L\u00E4vi",
+ "L\u00FCbeck",
+ "ANDR\u00C9",
+ "ANDRE",
+ "ANNONCERER"
+ };
+
+ private static final String[] primaryTargetData = {
+ "Lwi",
+ "L\u00F6wi",
+ "Lybeck",
+ "ANDR\u00E9",
+ "ANDR\u00C9",
+ "ANN\u00D3NCERER"
+ };
+
+ private static final int[] primaryResults = {
+ -1, -1, 0, 0, 0, 0
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final String[] tertiarySourceData = {
+ "Luc",
+ "luck",
+ "L\u00FCbeck",
+ "L\u00E4vi",
+ "L\u00F6ww"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "luck",
+ "L\u00FCbeck",
+ "lybeck",
+ "L\u00F6we",
+ "mast"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, -1, 1, -1, -1
+ };
+
+ /*
+ * Data for TestExtra()
+ */
+ private static final String[] testData = {
+ "A/S",
+ "ANDRE",
+ "ANDR\u00C9", // E-acute
+ "ANDR\u00C8", // E-grave
+ "ANDR\u00E9", // e-acute
+ "ANDR\u00EA", // e-circ
+ "Andre",
+ "Andr\u00E9", // e-acute
+ "\u00C1NDRE", // A-acute
+ "\u00C0NDRE", // A-grave
+ "andre",
+ "\u00E1ndre", // a-acute
+ "\u00E0ndre", // a-grave
+ "ANDREAS",
+ "ANNONCERER",
+ "ANN\u00D3NCERER", // O-acute
+ "annoncerer",
+ "ann\u00F3ncerer", // o-acute
+ "AS",
+ "A\u00e6RO", // ae-ligature
+ "CA",
+ "\u00C7A", // C-cedilla
+ "CB",
+ "\u00C7C", // C-cedilla
+ "D.S.B.",
+ "DA",
+ "DB",
+ "\u00D0ORA", // capital eth
+ "DSB",
+ "\u00D0SB", // capital eth
+ "DSC",
+ "EKSTRA_ARBEJDE",
+ "EKSTRABUD",
+ "H\u00D8ST", // could the 0x00D8 be 0x2205?
+ "HAAG",
+ "H\u00C5NDBOG", // A-ring
+ "HAANDV\u00C6RKSBANKEN", // AE-ligature
+ "INTERNETFORBINDELSE",
+ "Internetforbindelse",
+ "\u00CDNTERNETFORBINDELSE", // I-acute
+ "internetforbindelse",
+ "\u00EDnternetforbindelse", // i-acute
+ "Karl",
+ "karl",
+ "NIELSEN",
+ "NIELS J\u00D8RGEN", // O-slash
+ "NIELS-J\u00D8RGEN", // O-slash
+ "OERVAL",
+ "\u0152RVAL", // OE-ligature
+ "\u0153RVAL", // oe-ligature
+ "R\u00C9E, A", // E-acute
+ "REE, B",
+ "R\u00C9E, L", // E-acute
+ "REE, V",
+ "SCHYTT, B",
+ "SCHYTT, H",
+ "SCH\u00DCTT, H", // U-diaeresis
+ "SCHYTT, L",
+ "SCH\u00DCTT, M", // U-diaeresis
+ "SS",
+ "ss",
+ "\u00DF", // sharp S
+ "SSA",
+ "\u00DFA", // sharp S
+ "STOREK\u00C6R", // AE-ligature
+ "STORE VILDMOSE",
+ "STORMLY",
+ "STORM PETERSEN",
+ "THORVALD",
+ "THORVARDUR",
+ "\u00DEORVAR\u0110UR", // capital thorn, capital d-stroke(like eth) (sami)
+ "THYGESEN",
+ "VESTERG\u00C5RD, A",
+ "VESTERGAARD, A",
+ "VESTERG\u00C5RD, B", // 50
+ "Westmalle",
+ "YALLE",
+ "Yderligere",
+ "\u00DDderligere", // Y-acute
+ "\u00DCderligere", // U-diaeresis
+ "\u00FDderligere", // y-acute
+ "\u00FCderligere", // u-diaeresis
+ "U\u0308ruk-hai",
+ "ZORO",
+ "\u00C6BLE", // AE-ligature
+ "\u00E6BLE", // ae-ligature
+ "\u00C4BLE", // A-diaeresis
+ "\u00E4BLE", // a-diaeresis
+ "\u00D8BERG", // O-stroke
+ "\u00F8BERG", // o-stroke
+ "\u00D6BERG", // O-diaeresis
+ "\u00F6BERG" // o-diaeresis
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+ for (int i = 0; i < testData.length-1; i++) {
+ for (int j = i+1; j < testData.length; j++) {
+ doTest(myCollation, testData[i], testData[j], -1);
+ }
+ }
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("da", "", ""));
+}
diff --git a/test/java/text/Collator/DummyTest.java b/test/java/text/Collator/DummyTest.java
new file mode 100644
index 0000000000..3e3124edb0
--- /dev/null
+++ b/test/java/text/Collator/DummyTest.java
@@ -0,0 +1,421 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Dummy Collation
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+public class DummyTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new DummyTest().run(args);
+ }
+
+ private static final String DEFAULTRULES =
+ "='\u200B'=\u200C=\u200D=\u200E=\u200F"
+ // Control Characters
+ + "=\u0000 =\u0001 =\u0002 =\u0003 =\u0004" //null, .. eot
+ + "=\u0005 =\u0006 =\u0007 =\u0008 ='\u0009'" //enq, ...
+ + "='\u000b' =\u000e" //vt,, so
+ + "=\u000f ='\u0010' =\u0011 =\u0012 =\u0013" //si, dle, dc1, dc2, dc3
+ + "=\u0014 =\u0015 =\u0016 =\u0017 =\u0018" //dc4, nak, syn, etb, can
+ + "=\u0019 =\u001a =\u001b =\u001c =\u001d" //em, sub, esc, fs, gs
+ + "=\u001e =\u001f =\u007f" //rs, us, del
+ //....then the C1 Latin 1 reserved control codes
+ + "=\u0080 =\u0081 =\u0082 =\u0083 =\u0084 =\u0085"
+ + "=\u0086 =\u0087 =\u0088 =\u0089 =\u008a =\u008b"
+ + "=\u008c =\u008d =\u008e =\u008f =\u0090 =\u0091"
+ + "=\u0092 =\u0093 =\u0094 =\u0095 =\u0096 =\u0097"
+ + "=\u0098 =\u0099 =\u009a =\u009b =\u009c =\u009d"
+ + "=\u009e =\u009f"
+ // IGNORE except for secondary, tertiary difference
+ // Spaces
+ + ";'\u0020';'\u00A0'" // spaces
+ + ";'\u2000';'\u2001';'\u2002';'\u2003';'\u2004'" // spaces
+ + ";'\u2005';'\u2006';'\u2007';'\u2008';'\u2009'" // spaces
+ + ";'\u200A';'\u3000';'\uFEFF'" // spaces
+ + ";'\r' ;'\t' ;'\n';'\f';'\u000b'" // whitespace
+
+ // Non-spacing accents
+
+ + ";\u0301" // non-spacing acute accent
+ + ";\u0300" // non-spacing grave accent
+ + ";\u0306" // non-spacing breve accent
+ + ";\u0302" // non-spacing circumflex accent
+ + ";\u030c" // non-spacing caron/hacek accent
+ + ";\u030a" // non-spacing ring above accent
+ + ";\u030d" // non-spacing vertical line above
+ + ";\u0308" // non-spacing diaeresis accent
+ + ";\u030b" // non-spacing double acute accent
+ + ";\u0303" // non-spacing tilde accent
+ + ";\u0307" // non-spacing dot above/overdot accent
+ + ";\u0304" // non-spacing macron accent
+ + ";\u0337" // non-spacing short slash overlay (overstruck diacritic)
+ + ";\u0327" // non-spacing cedilla accent
+ + ";\u0328" // non-spacing ogonek accent
+ + ";\u0323" // non-spacing dot-below/underdot accent
+ + ";\u0332" // non-spacing underscore/underline accent
+ // with the rest of the general diacritical marks in binary order
+ + ";\u0305" // non-spacing overscore/overline
+ + ";\u0309" // non-spacing hook above
+ + ";\u030e" // non-spacing double vertical line above
+ + ";\u030f" // non-spacing double grave
+ + ";\u0310" // non-spacing chandrabindu
+ + ";\u0311" // non-spacing inverted breve
+ + ";\u0312" // non-spacing turned comma above/cedilla above
+ + ";\u0313" // non-spacing comma above
+ + ";\u0314" // non-spacing reversed comma above
+ + ";\u0315" // non-spacing comma above right
+ + ";\u0316" // non-spacing grave below
+ + ";\u0317" // non-spacing acute below
+ + ";\u0318" // non-spacing left tack below
+ + ";\u0319" // non-spacing tack below
+ + ";\u031a" // non-spacing left angle above
+ + ";\u031b" // non-spacing horn
+ + ";\u031c" // non-spacing left half ring below
+ + ";\u031d" // non-spacing up tack below
+ + ";\u031e" // non-spacing down tack below
+ + ";\u031f" // non-spacing plus sign below
+ + ";\u0320" // non-spacing minus sign below
+ + ";\u0321" // non-spacing palatalized hook below
+ + ";\u0322" // non-spacing retroflex hook below
+ + ";\u0324" // non-spacing double dot below
+ + ";\u0325" // non-spacing ring below
+ + ";\u0326" // non-spacing comma below
+ + ";\u0329" // non-spacing vertical line below
+ + ";\u032a" // non-spacing bridge below
+ + ";\u032b" // non-spacing inverted double arch below
+ + ";\u032c" // non-spacing hacek below
+ + ";\u032d" // non-spacing circumflex below
+ + ";\u032e" // non-spacing breve below
+ + ";\u032f" // non-spacing inverted breve below
+ + ";\u0330" // non-spacing tilde below
+ + ";\u0331" // non-spacing macron below
+ + ";\u0333" // non-spacing double underscore
+ + ";\u0334" // non-spacing tilde overlay
+ + ";\u0335" // non-spacing short bar overlay
+ + ";\u0336" // non-spacing long bar overlay
+ + ";\u0338" // non-spacing long slash overlay
+ + ";\u0339" // non-spacing right half ring below
+ + ";\u033a" // non-spacing inverted bridge below
+ + ";\u033b" // non-spacing square below
+ + ";\u033c" // non-spacing seagull below
+ + ";\u033d" // non-spacing x above
+ + ";\u033e" // non-spacing vertical tilde
+ + ";\u033f" // non-spacing double overscore
+ + ";\u0340" // non-spacing grave tone mark
+ + ";\u0341" // non-spacing acute tone mark
+ + ";\u0342;\u0343;\u0344;\u0345;\u0360;\u0361" // newer
+ + ";\u0483;\u0484;\u0485;\u0486" // Cyrillic accents
+
+ + ";\u20D0;\u20D1;\u20D2" // symbol accents
+ + ";\u20D3;\u20D4;\u20D5" // symbol accents
+ + ";\u20D6;\u20D7;\u20D8" // symbol accents
+ + ";\u20D9;\u20DA;\u20DB" // symbol accents
+ + ";\u20DC;\u20DD;\u20DE" // symbol accents
+ + ";\u20DF;\u20E0;\u20E1" // symbol accents
+
+ + ",'\u002D';\u00AD" // dashes
+ + ";\u2010;\u2011;\u2012" // dashes
+ + ";\u2013;\u2014;\u2015" // dashes
+ + ";\u2212" // dashes
+
+ // other punctuation
+
+ + "<'\u005f'" // underline/underscore (spacing)
+ + "<\u00af" // overline or macron (spacing)
+// + "<\u00ad" // syllable hyphen (SHY) or soft hyphen
+ + "<'\u002c'" // comma (spacing)
+ + "<'\u003b'" // semicolon
+ + "<'\u003a'" // colon
+ + "<'\u0021'" // exclamation point
+ + "<\u00a1" // inverted exclamation point
+ + "<'\u003f'" // question mark
+ + "<\u00bf" // inverted question mark
+ + "<'\u002f'" // slash
+ + "<'\u002e'" // period/full stop
+ + "<\u00b4" // acute accent (spacing)
+ + "<'\u0060'" // grave accent (spacing)
+ + "<'\u005e'" // circumflex accent (spacing)
+ + "<\u00a8" // diaresis/umlaut accent (spacing)
+ + "<'\u007e'" // tilde accent (spacing)
+ + "<\u00b7" // middle dot (spacing)
+ + "<\u00b8" // cedilla accent (spacing)
+ + "<'\u0027'" // apostrophe
+ + "<'\"'" // quotation marks
+ + "<\u00ab" // left angle quotes
+ + "<\u00bb" // right angle quotes
+ + "<'\u0028'" // left parenthesis
+ + "<'\u0029'" // right parenthesis
+ + "<'\u005b'" // left bracket
+ + "<'\u005d'" // right bracket
+ + "<'\u007b'" // left brace
+ + "<'\u007d'" // right brace
+ + "<\u00a7" // section symbol
+ + "<\u00b6" // paragraph symbol
+ + "<\u00a9" // copyright symbol
+ + "<\u00ae" // registered trademark symbol
+ + "<'\u0040'" // at sign
+ + "<\u00a4" // international currency symbol
+ + "<\u00a2" // cent sign
+ + "<'\u0024'" // dollar sign
+ + "<\u00a3" // pound-sterling sign
+ + "<\u00a5" // yen sign
+ + "<'\u002a'" // asterisk
+ + "<'\\u005c'" // backslash
+ + "<'\u0026'" // ampersand
+ + "<'\u0023'" // number sign
+ + "<'\u0025'" // percent sign
+ + "<'\u002b'" // plus sign
+// + "<\u002d" // hyphen or minus sign
+ + "<\u00b1" // plus-or-minus sign
+ + "<\u00f7" // divide sign
+ + "<\u00d7" // multiply sign
+ + "<'\u003c'" // less-than sign
+ + "<'\u003d'" // equal sign
+ + "<'\u003e'" // greater-than sign
+ + "<\u00ac" // end of line symbol/logical NOT symbol
+ + "<'\u007c'" // vertical line/logical OR symbol
+ + "<\u00a6" // broken vertical line
+ + "<\u00b0" // degree symbol
+ + "<\u00b5" // micro symbol
+
+ // NUMERICS
+
+ + "<0<1<2<3<4<5<6<7<8<9"
+ + "<\u00bc<\u00bd<\u00be" // 1/4,1/2,3/4 fractions
+
+ // NON-IGNORABLES
+ + "<a,A"
+ + "<b,B"
+ + "<c,C"
+ + "<d,D"
+ + "<\u00F0,\u00D0" // eth
+ + "<e,E"
+ + "<f,F"
+ + "<g,G"
+ + "<h,H"
+ + "<i,I"
+ + "<j,J"
+ + "<k,K"
+ + "<l,L"
+ + "<m,M"
+ + "<n,N"
+ + "<o,O"
+ + "<p,P"
+ + "<q,Q"
+ + "<r,R"
+ + "<s, S & SS,\u00DF" // s-zet
+ + "<t,T"
+ + "&th, \u00FE & TH, \u00DE" // thorn
+ + "<u,U"
+ + "<v,V"
+ + "<w,W"
+ + "<x,X"
+ + "<y,Y"
+ + "<z,Z"
+ + "&AE,\u00C6" // ae & AE ligature
+ + "&AE,\u00E6"
+ + "&OE,\u0152" // oe & OE ligature
+ + "&OE,\u0153";
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "p\u00EAche",
+ "abc",
+ "abc",
+ "abc",
+ "abc",
+ "abc",
+ "a\u00E6c",
+ "acHc",
+ "black"
+ };
+
+ private static final String[] primaryTargetData = {
+ "p\u00E9ch\u00E9",
+ "abc",
+ "aBC",
+ "abch",
+ "abd",
+ "\u00E4bc",
+ "a\u00C6c",
+ "aCHc",
+ "black-bird"
+ };
+
+ private static final int[] primaryResults = {
+ 0, 0, 0, -1, -1, 0, 0, 0, -1
+ };
+
+ /*
+ * Data for TestSecondary()
+ */
+ private static final String[] secondarySourceData = {
+ "four",
+ "five",
+ "1",
+ "abc",
+ "abc",
+ "abcH",
+ "abc",
+ "acHc"
+ };
+
+ private static final String[] secondaryTargetData = {
+
+ "4",
+ "5",
+ "one",
+ "abc",
+ "aBc",
+ "abch",
+ "abd",
+ "aCHc"
+ };
+
+ private static final int[] secondaryResults = {
+ 0, 0, 0, 0, 0, 0, -1, 0
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final String[] tertiarySourceData = {
+ "ab'c",
+ "co-op",
+ "ab",
+ "ampersad",
+ "all",
+ "four",
+ "five",
+ "1",
+ "1",
+ "1",
+ "2",
+ "2",
+ "Hello",
+ "a<b",
+ "a<b",
+ "acc",
+ "acHc"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "abc",
+ "COOP",
+ "abc",
+ "&",
+ "&",
+ "4",
+ "5",
+ "one",
+ "nne",
+ "pne",
+ "two",
+ "uwo",
+ "hellO",
+ "a<=b",
+ "abc",
+ "aCHc",
+ "aCHc"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, 1, -1, -1, -1, -1, -1, 1, 1, -1,
+ 1, -1, 1, 1, -1, -1, -1
+ };
+
+
+ private static final String[] testData = {
+ "a",
+ "A",
+ "\u00e4",
+ "\u00c4",
+ "ae",
+ "aE",
+ "Ae",
+ "AE",
+ "\u00e6",
+ "\u00c6",
+ "b",
+ "c",
+ "z"
+ };
+
+ public void TestPrimary() {
+ doTest(getCollator(), Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestSecondary() {
+ doTest(getCollator(), Collator.SECONDARY,
+ secondarySourceData, secondaryTargetData, secondaryResults);
+ }
+
+ public void TestTertiary() {
+ Collator col = getCollator();
+
+ doTest(col, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+ for (int i = 0; i < testData.length-1; i++) {
+ for (int j = i+1; j < testData.length; j++) {
+ doTest(col, testData[i], testData[j], -1);
+ }
+ }
+ }
+
+ private RuleBasedCollator myCollation = null;
+ private Collator getCollator() {
+ if (myCollation == null) {
+ try {
+ myCollation = new RuleBasedCollator
+ (DEFAULTRULES + "& C < ch, cH, Ch, CH & Five, 5 & Four, 4 & one, 1 & Ampersand; '&' & Two, 2 ");
+ } catch (Exception foo) {
+ errln("Collator creation failed.");
+ myCollation = (RuleBasedCollator)Collator.getInstance();
+ }
+ }
+ return myCollation;
+ }
+}
diff --git a/test/java/text/Collator/EnglishTest.java b/test/java/text/Collator/EnglishTest.java
new file mode 100644
index 0000000000..3c4da57b75
--- /dev/null
+++ b/test/java/text/Collator/EnglishTest.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test English Collation
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+public class EnglishTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new EnglishTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "p\u00EAche",
+ "abc",
+ "abc",
+ "abc",
+ "a\u00E6c"
+ };
+
+ private static final String[] primaryTargetData = {
+ "p\u00E9ch\u00E9",
+ "aBC",
+ "abd",
+ "\u00E4bc",
+ "a\u00C6c"
+ };
+
+ private static final int[] primaryResults = {
+ 0, 0, -1, 0, 0,
+ };
+
+ /*
+ * Data for TestSecondary()
+ */
+ private static final String[] secondarySourceData = {
+ "abc",
+ "abc",
+ "a\u00E6c",
+ "abc",
+ "abc",
+ "p\u00e9ch\u00e9"
+ };
+
+ private static final String[] secondaryTargetData = {
+ "aBd",
+ "\u00E4bc",
+ "a\u00C6c",
+ "aBd",
+ "\u00E4bc",
+ "p\u00eache"
+ };
+
+ private static final int[] secondaryResults = {
+ -1, -1, 0, -1, -1, -1
+ };
+
+ /*
+ * Data for TestTertiary() {
+ */
+ private static final String[] tertiarySourceData = {
+ "ab",
+ "black-bird",
+ "black bird",
+ "black-bird",
+ "Hello",
+ "ABC",
+ "abc",
+ "blackbird",
+ "black-bird",
+ "black-bird",
+ "p\u00EAche",
+ "p\u00E9ch\u00E9",
+ "\u00C4B\u0308C\u0308",
+ "a\u0308bc",
+ "p\u00E9cher",
+ "roles",
+ "abc",
+ "A",
+ "A",
+ "ab",
+ "tcompareplain",
+ "ab",
+ "a#b",
+ "a#b",
+ "abc",
+ "Abcda",
+ "abcda",
+ "abcda",
+ "\u00E6bcda",
+ "\u00E4bcda",
+ "abc",
+ "abc",
+ "abc",
+ "abc",
+ "abc",
+ "acHc",
+ "a\u0308bc",
+ "thi\u0302s"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "abc",
+ "blackbird",
+ "black-bird",
+ "black",
+ "hello",
+ "ABC",
+ "ABC",
+ "blackbirds",
+ "blackbirds",
+ "blackbird",
+ "p\u00E9ch\u00E9",
+ "p\u00E9cher",
+ "\u00C4B\u0308C\u0308",
+ "A\u0308bc",
+ "p\u00E9che",
+ "ro\u0302le",
+ "A\u00E1cd",
+ "A\u00E1cd",
+ "abc",
+ "abc",
+ "TComparePlain",
+ "aBc",
+ "a#B",
+ "a&b",
+ "a#c",
+ "abcda",
+ "\u00C4bcda",
+ "\u00E4bcda",
+ "\u00C4bcda",
+ "\u00C4bcda",
+ "ab#c",
+ "abc",
+ "ab=c",
+ "abd",
+ "\u00E4bc",
+ "aCHc",
+ "\u00E4bc",
+ "th\u00EEs"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, 1, -1, 1, 1, 0, -1, -1, -1, 1,
+ 1, -1, 0, -1, 1, 1, 1, -1, -1, -1,
+ -1, -1, -1, 1, 1, 1, -1, -1, 1, -1,
+ 1, 0, 1, -1, -1, -1, 0, 0
+ };
+
+ private static final String testData[] = {
+ "a",
+ "A",
+ "e",
+ "E",
+ "\u00e9",
+ "\u00e8",
+ "\u00ea",
+ "\u00eb",
+ "ea",
+ "x"
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestSecondary() {
+ doTest(myCollation, Collator.SECONDARY,
+ secondarySourceData, secondaryTargetData, secondaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+ for (int i = 0; i < testData.length-1; i++) {
+ for (int j = i+1; j < testData.length; j++) {
+ doTest(myCollation, testData[i], testData[j], -1);
+ }
+ }
+ }
+
+ private final Collator myCollation = Collator.getInstance(Locale.ENGLISH);
+}
diff --git a/test/java/text/Collator/FinnishTest.java b/test/java/text/Collator/FinnishTest.java
new file mode 100644
index 0000000000..6df18ef014
--- /dev/null
+++ b/test/java/text/Collator/FinnishTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Finnish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class FinnishTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new FinnishTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "L\u00E5vi",
+ "wat"
+ };
+
+ private static final String[] primaryTargetData = {
+ "L\u00E4we",
+ "vat"
+ };
+
+ private static final int[] primaryResults = {
+ -1, 0
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final String tertiarySourceData[] = {
+ "wat",
+ "vat",
+ "a\u00FCbeck"
+ };
+
+ private static final String tertiaryTargetData[] = {
+ "vat",
+ "way",
+ "axbeck"
+ };
+
+ private static final int[] tertiaryResults = {
+ 1, -1, 1
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("fi", "FI", ""));
+}
diff --git a/test/java/text/Collator/FrenchTest.java b/test/java/text/Collator/FrenchTest.java
new file mode 100644
index 0000000000..939ef32225
--- /dev/null
+++ b/test/java/text/Collator/FrenchTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test French Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class FrenchTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new FrenchTest().run(args);
+ }
+
+ private static final String[] tertiarySourceData = {
+ "abc",
+ "COTE",
+ "p\u00EAche",
+ "p\u00EAcher",
+ "p\u00E9cher",
+ "p\u00E9cher",
+ "Hello"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "ABC",
+ "c\u00f4te",
+ "p\u00E9ch\u00E9",
+ "p\u00E9ch\u00E9",
+ "p\u00EAche",
+ "p\u00EAcher",
+ "hellO"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, -1, -1, 1, 1, -1, 1
+ };
+
+ private static final String[] testData = {
+ "a",
+ "A",
+ "e",
+ "E",
+ "\u00e9",
+ "\u00e8",
+ "\u00ea",
+ "\u00eb",
+ "ea",
+ "x"
+ };
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+
+ for (int i = 0; i < testData.length-1; i++) {
+ for (int j = i+1; j < testData.length; j++) {
+ doTest(myCollation, testData[i], testData[j], -1);
+ }
+ }
+ }
+
+ private final Collator myCollation = Collator.getInstance(Locale.FRANCE);
+}
diff --git a/test/java/text/Collator/G7Test.java b/test/java/text/Collator/G7Test.java
new file mode 100644
index 0000000000..0b41566bd2
--- /dev/null
+++ b/test/java/text/Collator/G7Test.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test G7 Collation
+ */
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
+ * materials are provided under terms of a License Agreement between Taligent
+ * and Sun. This technology is protected by multiple US and International
+ * patents. This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+*/
+
+/**
+ * G7 Test cases
+ *
+ * @author Helena Shih
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.util.Locale;
+
+// G7 test program for printing out test results
+
+public class G7Test extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new G7Test().run(args);
+ }
+
+ private static final String testCases[] = {
+ "black-birds", // 0
+ "Pat", // 1
+ "p\u00E9ch\u00E9", // 2
+ "p\u00EAche", // 3
+ "p\u00E9cher", // 4
+ "p\u00EAcher", // 5
+ "Tod", // 6
+ "T\u00F6ne", // 7
+ "Tofu", // 8
+ "blackbirds", // 9
+ "Ton", // 10
+ "PAT", // 11
+ "blackbird", // 12
+ "black-bird", // 13
+ "pat", // 14
+ // Additional tests
+ "czar", // 15
+ "churo", // 16
+ "cat", // 17
+ "darn", // 18
+ "?", // 19
+ "quick", // 20
+ "#", // 21
+ "&", // 22
+ "aardvark", // 23
+ "a-rdvark", // 24
+ "abbot", // 25
+ "coop", // 26
+ "co-p", // 27
+ "cop", // 28
+ "zebra" // 29
+ };
+
+ // loop to TOTALTESTSET
+ private static final int[][] G7Results = {
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_US
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_GB
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // en_CA
+ { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // fr_FR
+ { 12, 13, 9, 0, 14, 1, 11, 3, 2, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // fr_CA
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // de_DE
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // it_IT
+ { 12, 13, 9, 0, 14, 1, 11, 2, 3, 4,
+ 5, 6, 8, 10, 7, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 }, // ja_JP
+ };
+
+ // new table collation with rules "& Z < p, P"
+ // loop to FIXEDTESTSET
+ private static final int[] Test1Results = {
+ 12, 13, 9, 0, 6, 8, 10, 7, 14, 1,
+ 11, 2, 3, 4, 5, 31, 31, 31, 31, 31,
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
+ };
+
+ // new table collation with rules "& C < ch , cH, Ch, CH "
+ // loop to TOTALTESTSET
+ private static final int[] Test2Results = {
+ 19, 22, 21, 23, 25, 24, 12, 13, 9, 0,
+ 17, 26, 28, 27, 15, 16, 18, 14, 1, 11,
+ 2, 3, 4, 5, 20, 6, 8, 10, 7, 29
+ };
+
+ // new table collation with rules
+ // "& Question-mark ; ? & Hash-mark ; # & Ampersand ; '&' "
+ // loop to TOTALTESTSET
+ private static final int[] Test3Results = {
+ 23, 25, 22, 24, 12, 13, 9, 0, 17, 16,
+ 26, 28, 27, 15, 18, 21, 14, 1, 11, 2,
+ 3, 4, 5, 19, 20, 6, 8, 10, 7, 29
+ };
+
+ // analogous to Japanese rules
+ // " & aa ; a- & ee ; e- & ii ; i- & oo ; o- & uu ; u- "
+ // loop to TOTALTESTSET
+ private static final int[] Test4Results = {
+ 19, 22, 21, 23, 24, 25, 12, 13, 9, 0,
+ 17, 16, 26, 27, 28, 15, 18, 14, 1, 11,
+ 2, 3, 4, 5, 20, 6, 8, 10, 7, 29
+ };
+
+ public void TestG7Data() {
+ for (int i = 0; i < locales.length; i++) {
+ Collator myCollation= null;
+ RuleBasedCollator tblColl1 = null;
+
+ try {
+ myCollation = Collator.getInstance(locales[i]);
+ tblColl1 = new RuleBasedCollator(((RuleBasedCollator)myCollation).getRules());
+ } catch (Exception foo) {
+ errln("Exception: " + foo.getMessage() +
+ " Locale : " + locales[i].getDisplayName() +
+ " getRules failed\n");
+ continue;
+ }
+ for (int j = 0; j < FIXEDTESTSET; j++) {
+ for (int n = j+1; n < FIXEDTESTSET; n++) {
+ doTest(tblColl1, testCases[G7Results[i][j]],
+ testCases[G7Results[i][n]], -1);
+ }
+ }
+ myCollation = null;
+ }
+ }
+
+ /*
+ * Demo Test 1 : Create a new table collation with rules "& Z < p, P"
+ */
+ public void TestDemoTest1() {
+ int j = 0;
+ final Collator myCollation = Collator.getInstance(Locale.US);
+ final String defRules = ((RuleBasedCollator)myCollation).getRules();
+ RuleBasedCollator tblColl = null;
+ String newRules = defRules + " & Z < p, P";
+
+ try {
+ tblColl = new RuleBasedCollator(newRules);
+ for (j = 0; j < FIXEDTESTSET; j++) {
+ for (int n = j+1; n < FIXEDTESTSET; n++) {
+ doTest(tblColl, testCases[Test1Results[j]],
+ testCases[Test1Results[n]], -1);
+ }
+ }
+ tblColl = null;
+ } catch (Exception foo) {
+ errln("Exception: " + foo.getMessage() +
+ "\nDemo Test 1 Table Collation object creation failed.");
+ }
+ }
+
+ /*
+ * Demo Test 2 : Create a new table collation with rules
+ * "& C < ch , cH, Ch, CH"
+ */
+ public void TestDemoTest2() {
+ final Collator myCollation = Collator.getInstance(Locale.US);
+ final String defRules = ((RuleBasedCollator)myCollation).getRules();
+ String newRules = defRules + "& C < ch , cH, Ch, CH";
+
+ try {
+ RuleBasedCollator tblColl = new RuleBasedCollator(newRules);
+ for (int j = 0; j < TOTALTESTSET; j++) {
+ for (int n = j+1; n < TOTALTESTSET; n++) {
+ doTest(tblColl, testCases[Test2Results[j]],
+ testCases[Test2Results[n]], -1);
+ }
+ }
+ } catch (Exception foo) {
+ errln("Exception: " + foo.getMessage() +
+ "\nDemo Test 2 Table Collation object creation failed.\n");
+ }
+ }
+
+ /*
+ * Demo Test 3 : Create a new table collation with rules
+ * "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&'"
+ */
+ public void TestDemoTest3() {
+ final Collator myCollation = Collator.getInstance(Locale.US);
+ final String defRules = ((RuleBasedCollator)myCollation).getRules();
+ RuleBasedCollator tblColl = null;
+ String newRules = defRules + "& Question'-'mark ; '?' & Hash'-'mark ; '#' & Ampersand ; '&";
+
+ try {
+ tblColl = new RuleBasedCollator(newRules);
+ for (int j = 0; j < TOTALTESTSET; j++) {
+ for (int n = j+1; n < TOTALTESTSET; n++) {
+ doTest(tblColl, testCases[Test3Results[j]],
+ testCases[Test3Results[n]], -1);
+ }
+ }
+ } catch (Exception foo) {
+ errln("Exception: " + foo.getMessage() +
+ "\nDemo Test 3 Table Collation object creation failed.");
+ }
+ }
+
+ /*
+ * Demo Test 4 : Create a new table collation with rules
+ * " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' "
+ */
+ public void TestDemoTest4() {
+ final Collator myCollation = Collator.getInstance(Locale.US);
+ final String defRules = ((RuleBasedCollator)myCollation).getRules();
+ RuleBasedCollator tblColl = null;
+ String newRules = defRules + " & aa ; a'-' & ee ; e'-' & ii ; i'-' & oo ; o'-' & uu ; u'-' ";
+
+ try {
+ tblColl = new RuleBasedCollator(newRules);
+ for (int j = 0; j < TOTALTESTSET; j++) {
+ for (int n = j+1; n < TOTALTESTSET; n++) {
+ doTest(tblColl, testCases[Test4Results[j]],
+ testCases[Test4Results[n]], -1);
+ }
+ }
+ } catch (Exception foo) {
+ errln("Exception: " + foo.getMessage() +
+ "\nDemo Test 4 Table Collation object creation failed.");
+ }
+ tblColl = null;
+ }
+
+ private static final int FIXEDTESTSET = 15;
+ private static final int TOTALTESTSET = 30;
+
+ private static final Locale locales[] = {
+ Locale.US,
+ Locale.UK,
+ Locale.CANADA,
+ Locale.FRANCE,
+ Locale.CANADA_FRENCH,
+ Locale.GERMANY,
+ Locale.JAPAN,
+ Locale.ITALY
+ };
+}
diff --git a/test/java/text/Collator/GermanTest.java b/test/java/text/Collator/GermanTest.java
new file mode 100644
index 0000000000..74129e96f9
--- /dev/null
+++ b/test/java/text/Collator/GermanTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test German Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class GermanTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new GermanTest().run(args);
+ }
+
+ /*
+ * Shared data for TestPrimary() and TestTertiary()
+ */
+ private static final String testSourceData[] = {
+ "Gr\u00F6\u00DFe",
+ "abc",
+ "T\u00F6ne",
+ "T\u00F6ne",
+ "T\u00F6ne",
+ "a\u0308bc",
+ "\u00E4bc",
+ "\u00E4bc",
+ "Stra\u00DFe",
+ "efg",
+ "\u00E4bc",
+ "Stra\u00DFe"
+ };
+
+ private static final String testTargetData[] = {
+ "Grossist",
+ "a\u0308bc",
+ "Ton",
+ "Tod",
+ "Tofu",
+ "A\u0308bc",
+ "a\u0308bc",
+ "aebc",
+ "Strasse",
+ "efg",
+ "aebc",
+ "Strasse"
+ };
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final int[] primaryResults = {
+ -1, 0, 1, 1, 1, 0, 0, -1, 0, 0,
+ -1, 0
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final int[] tertiaryResults = {
+ -1, -1, 1, 1, 1, -1, 0, -1, 1, 0,
+ -1, 1
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ testSourceData, testTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ testSourceData, testTargetData, tertiaryResults);
+ }
+
+ private final Collator myCollation = Collator.getInstance(Locale.GERMAN);
+}
diff --git a/test/java/text/Collator/IteratorTest.java b/test/java/text/Collator/IteratorTest.java
new file mode 100644
index 0000000000..a5c7f9bedf
--- /dev/null
+++ b/test/java/text/Collator/IteratorTest.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4062985 4108758 4108762 4157299
+ * @library /java/text/testlib
+ * @summary Test CollationElementIterator, particularly the new methods in 1.2
+ */
+/*
+ * (C) Copyright IBM Corp. 1998 - All Rights Reserved
+ *
+ * The original version of this source code and documentation is copyrighted
+ * and owned by IBM, Inc. These materials are provided under terms of a
+ * License Agreement between IBM and Sun. This technology is protected by
+ * multiple US and International patents. This notice and attribution to IBM
+ * may not be removed.
+ */
+
+import java.util.Locale;
+import java.text.*;
+
+public class IteratorTest extends CollatorTest {
+ // TODO:
+ // - Test previous() with contracting character sequences, which don't work
+ // at the moment.
+ // - Test edge cases on setOffset(), e.g. offset > length, etc.
+ //
+ public static void main(String[] args) throws Exception {
+ new IteratorTest().run(args);
+ }
+
+ /**
+ * Test for CollationElementIterator.previous()
+ *
+ * @bug 4108758 - Make sure it works with contracting characters
+ *
+ */
+ public void TestPrevious() throws ParseException {
+ // A basic test to see if it's working at all
+ backAndForth(en_us.getCollationElementIterator(test1));
+
+ // Test with a contracting character sequence
+ RuleBasedCollator c1 = new RuleBasedCollator(
+ "< a,A < b,B < c,C, d,D < z,Z < ch,cH,Ch,CH" );
+
+ backAndForth(c1.getCollationElementIterator("abchdcba"));
+
+ // Test with an expanding character sequence
+ RuleBasedCollator c2 = new RuleBasedCollator(
+ "< a < b < c/abd < d" );
+
+ backAndForth(c2.getCollationElementIterator("abcd"));
+
+ // Now try both
+ RuleBasedCollator c3 = new RuleBasedCollator(
+ "< a < b < c/aba < d < z < ch" );
+
+ backAndForth(c3.getCollationElementIterator("abcdbchdc"));
+ }
+
+ /**
+ * Test for getOffset() and setOffset()
+ */
+ public void TestOffset() {
+ CollationElementIterator iter = en_us.getCollationElementIterator(test1);
+
+ // Run all the way through the iterator, then get the offset
+ int orders[] = getOrders(iter);
+
+ int offset = iter.getOffset();
+ if (offset != test1.length()) {
+ System.out.println("offset at end != length: "
+ + offset + " vs " + test1.length());
+ }
+
+ // Now set the offset back to the beginning and see if it works
+ iter.setOffset(0);
+ assertEqual(iter, en_us.getCollationElementIterator(test1));
+
+ // TODO: try iterating halfway through a messy string.
+ }
+
+ /**
+ * Test for setText()
+ */
+ public void TestSetText() {
+ CollationElementIterator iter1 = en_us.getCollationElementIterator(test1);
+ CollationElementIterator iter2 = en_us.getCollationElementIterator(test2);
+
+ // Run through the second iterator just to exercise it
+ int c = iter2.next();
+ int i = 0;
+ while ( ++i < 10 && c != CollationElementIterator.NULLORDER) {
+ c = iter2.next();
+ }
+
+ // Now set it to point to the same string as the first iterator
+ iter2.setText(test1);
+ assertEqual(iter1, iter2);
+ }
+
+ /** @bug 4108762
+ * Test for getMaxExpansion()
+ */
+ public void TestMaxExpansion() throws ParseException {
+ // Try a simple one first:
+ // The only expansion ends with 'e' and has length 2
+ String[][] test1 = {
+ { "< a & ae = \u00e4 < b < e", "" },
+ { "a", "1" },
+ { "b", "1" },
+ { "e", "2" },
+ };
+ verifyExpansion(test1);
+
+ // Now a more complicated one:
+ // "a1" --> "ae"
+ // "z" --> "aeef"
+ //
+ String[][] test2 = {
+ { "< a & ae = a1 & aeef = z < b < e < f", "" },
+ { "a", "1" },
+ { "b", "1" },
+ { "e", "2" },
+ { "f", "4" },
+ };
+ verifyExpansion(test2);
+ }
+
+ /*
+ * @bug 4157299
+ */
+ public void TestClearBuffers() throws ParseException {
+ RuleBasedCollator c = new RuleBasedCollator("< a < b < c & ab = d");
+ CollationElementIterator i = c.getCollationElementIterator("abcd");
+ int e0 = i.next(); // save the first collation element
+ i.setOffset(3); // go to the expanding character
+ i.next(); // but only use up half of it
+ i.setOffset(0); // go back to the beginning
+ int e = i.next(); // and get this one again
+ if (e != e0) {
+ errln("got " + Integer.toString(e, 16) + ", expected " +
+ Integer.toString(e0, 16));
+ }
+ }
+
+ //------------------------------------------------------------------------
+ // Internal utilities
+ //
+
+ private void backAndForth(CollationElementIterator iter) {
+ // Run through the iterator forwards and stick it into an array
+ int [] orders = getOrders(iter);
+
+ // Now go through it backwards and make sure we get the same values
+ int index = orders.length;
+ int o;
+
+ while ((o = iter.previous()) != CollationElementIterator.NULLORDER) {
+ if (o != orders[--index]) {
+ errln("Mismatch at index " + index + ": "
+ + orders[index] + " vs " + o);
+ break;
+ }
+ }
+ if (index != 0) {
+ errln("Didn't get back to beginning - index is " + index);
+
+ iter.reset();
+ err("next: ");
+ while ((o = iter.next()) != NULLORDER) {
+ err( Integer.toHexString(o) + " ");
+ }
+ errln("");
+
+ err("prev: ");
+ while ((o = iter.previous()) != NULLORDER) {
+ err( Integer.toHexString(o) + " ");
+ }
+ errln("");
+ }
+ }
+
+ /**
+ * Verify that getMaxExpansion works on a given set of collation rules
+ *
+ * The first row of the "tests" array contains the collation rules
+ * at index 0, and the string at index 1 is ignored.
+ *
+ * Subsequent rows of the array contain a character and a number, both
+ * represented as strings. The character's collation order is determined,
+ * and getMaxExpansion is called for that character. If its value is
+ * not equal to the specified number, an error results.
+ */
+ private void verifyExpansion(String[][] tests) throws ParseException
+ {
+ RuleBasedCollator coll = new RuleBasedCollator(tests[0][0]);
+ CollationElementIterator iter = coll.getCollationElementIterator("");
+
+ for (int i = 1; i < tests.length; i++) {
+ // First get the collation key that the test string expands to
+ iter.setText(tests[i][0]);
+
+ int order = iter.next();
+
+ if (order == NULLORDER || iter.next() != NULLORDER) {
+ iter.reset();
+ errln("verifyExpansion: '" + tests[i][0] +
+ "' has multiple orders:" + orderString(iter));
+ }
+
+ int expansion = iter.getMaxExpansion(order);
+ int expect = new Integer(tests[i][1]).intValue();
+
+ if (expansion != expect) {
+ errln("expansion for '" + tests[i][0] + "' is wrong: " +
+ "expected " + expect + ", got " + expansion);
+ }
+ }
+ }
+
+ /**
+ * Return an integer array containing all of the collation orders
+ * returned by calls to next on the specified iterator
+ */
+ private int[] getOrders(CollationElementIterator iter)
+ {
+ int maxSize = 100;
+ int size = 0;
+ int[] orders = new int[maxSize];
+
+ int order;
+ while ((order = iter.next()) != NULLORDER) {
+ if (size == maxSize) {
+ maxSize *= 2;
+ int[] temp = new int[maxSize];
+ System.arraycopy(orders, 0, temp, 0, size);
+ orders = temp;
+ }
+ orders[size++] = order;
+ }
+
+ if (orders.length > size) {
+ int[] temp = new int[size];
+ System.arraycopy(orders, 0, temp, 0, size);
+ orders = temp;
+ }
+ return orders;
+ };
+
+ /**
+ * Return a string containing all of the collation orders
+ * returned by calls to next on the specified iterator
+ */
+ private String orderString(CollationElementIterator iter) {
+ StringBuffer buf = new StringBuffer();
+
+ int order;
+ while ((order = iter.next()) != NULLORDER) {
+ buf.append( Integer.toHexString(order) + " ");
+ }
+ return buf.toString();
+ }
+
+ static final private int NULLORDER = CollationElementIterator.NULLORDER;
+ RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US);
+
+ String test1 = "What subset of all possible test cases?";
+ String test2 = "has the highest probability of detecting";
+}
diff --git a/test/java/text/Collator/JapaneseTest.java b/test/java/text/Collator/JapaneseTest.java
new file mode 100644
index 0000000000..2bd5f6d017
--- /dev/null
+++ b/test/java/text/Collator/JapaneseTest.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 1997, 2016, 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 1.1 02/09/11
+ * @bug 4176141 4655819
+ * @summary Regression tests for Japanese Collation
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class JapaneseTest {
+
+ // NOTE:
+ // Golden data in this test case is locale data dependent and
+ // may need to be changed if the Japanese locale collation rules
+ // are changed.
+
+ /*
+ * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+ * -------------------+--------------------+------------------+-------------
+ * PRIMARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ */
+ static final int[][] results1 = {
+ { -1, -1, -1},
+ { -1, -1, -1},
+ { -1, -1, -1},
+ };
+ static final String[][] compData1 = {
+ /*
+ * Data to verify '<' relationship in LocaleElements_ja.java
+ */
+ {"\u3084", "\u30E6",
+ "Hiragana \"YA\"(0x3084) <---> Katakana \"YU\"(0x30E6)"},
+ {"\u30E6", "\u3088",
+ "Katakana \"YU\"(0x30E6) <---> Hiragana \"YO\"(0x3088)"},
+ {"\u00B1", "\u2260",
+ "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"},
+ {"\u3011", "\u2260",
+ "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"},
+ {"\u2260", "\u2103",
+ "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"},
+ {"\u2260", "\u2606",
+ "Not Equal To(0x2260) <---> White Star(0x2606)"},
+ {"\u30FD", "\u309E",
+ "Katakana Iteration Mark(0x30FD) <---> Hiragana Voiced Iteration Mark(0x309E)"},
+ {"\u3059\u309D", "\u3059\u309E",
+ "Hiragana \"SU\"(0x3059)Hiragana Iteration Mark(0x309D) <---> Hiragana \"SU\"(0x3059)Hiragana Voiced Iteration Mark(0x309E)"},
+ {"\u821E", "\u798F",
+ "CJK Unified Ideograph(0x821E) <---> CJK Unified Ideograph(0x798F)"},
+
+ /*
+ * Data to verify normalization
+ */
+ {"\u2260", "\u225F",
+ "Not Equal To(0x2260) <---> Questioned Equal To(0x225F)"},
+ {"\u226E", "\u2260",
+ "Not Less-than(0x226E) <---> Not Equal To(0x2260)"},
+ {"\u226E", "\u226D",
+ "Not Less-than(0x226E) <---> Not Equivalent To(0x226D)"},
+ };
+
+ /*
+ * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+ * -------------------+--------------------+------------------+-------------
+ * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ * SECONDARY | s1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ */
+ static final int[][] results2 = {
+ { 0, 0, 0},
+ { -1, -1, -1},
+ { -1, -1, -1},
+ };
+ static final String[][] compData2 = {
+ /*
+ * Data to verify ';' relationship in LocaleElements_ja.java
+ */
+ {"\u3099", "\u309A",
+ "Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A)"},
+ {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3068\u3099\u3046",
+ "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUTO\"(0x3053 0x3046 0x3068)Combining Katakana-Hiragana Voiced Sound Mark(0X3099)\"U\"(0x3046)"},
+ {"\u3053\u3046\u3068\u3046", "\u3053\u3046\u3069\u3046",
+ "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3068 0x3046) <---> Hiragana \"KOUDOU\"(0x3053 0x3046 0x3069 0x3046)"},
+ {"\u3053\u3046\u3069\u3046", "\u3054\u3046\u3068\u3046",
+ "Hiragana \"KOUTOU\"(0x3053 0x3046 0x3069 0x3046) <---> Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046)"},
+ {"\u3054\u3046\u3068\u3046", "\u3054\u3046\u3069\u3046",
+ "Hiragana \"GOUTOU\"(0x3054 0x3046 0x3068 0x3046) <---> Hiragana \"GOUDOU\"(0x3054 0x3046 0x3069 0x3046)"},
+ };
+
+ /*
+ * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+ * -------------------+--------------------+------------------+-------------
+ * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ * TERTIARY(default) | S1 < s2 (-1) | s1 < s2 (-1) | s1 < s2 (-1)
+ */
+ static final int[][] results3 = {
+ { 0, 0, 0},
+ { 0, 0, 0},
+ { -1, -1, -1},
+ };
+ static final String[][] compData3 = {
+ /*
+ * Data to verify ',' relationship in LocaleElements_ja.java
+ */
+ {"\u3042", "\u3041",
+ "Hiragana \"A\"(0x3042) <---> Hiragana \"a\"(0x3041)"},
+ {"\u3041", "\u30A2",
+ "Hiragana \"a\"(0x3041) <---> Katakana \"A\"(0x30A2)"},
+ {"\u30A2", "\u30A1",
+ "Katakana \"A\"(0x30A2) <---> Katakana \"a\"(0x30A1)"},
+ {"\u3094", "\u30F4",
+ "Hiragana \"VU\"(0x3094) <---> Katakana \"VU\"(0x30F4)"},
+ {"\u3094", "\u30A6\u3099",
+ "Hiragana \"VU\"(0x3094) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+ {"\u3046\u3099", "\u30F4",
+ "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"},
+ {"\u3046\u3099", "\u30A6\u3099",
+ "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+ {"\u30AB\u30A2", "\u30AB\u30FC",
+ "Katakana \"KAA\"(0x30AB 0x30A2) <---> Katakana \"KA-\"(0x30AB 0x30FC)"},
+ {"\u30CB\u30A1\u30A2", "\u30CB\u30A1\u30FC",
+ "Katakana \"NyaA\"(0x30CB 0x30A1 0x30A2) <---> Katakana \"Nya-\"(0x30CB 0x30A1 0x30FC)"},
+ {"\u30B3\u30AA\u30D2\u30A4", "\u30B3\u30FC\u30D2\u30FC",
+ "Katakana \"KOOHII\"(0x30B3 0x30AA 0x30D2 0x30A4) <---> Katakana \"KO-HI-\"(0x30B3 0x30FC 0x30D2 0x30FC)"},
+ {"\u308A\u3088\u3046", "\u308A\u3087\u3046",
+ "Hiragana \"RIYOU\"(0x308A 0x3088 0x3046) <---> Hiragana \"Ryou\"(0x308A 0x3087 0x3046)"},
+ {"\u3081\u3064\u304D", "\u3081\u3063\u304D",
+ "Hiragana \"METSUKI\"(0x3081 0x3064 0x304D) <---> Hiragana \"MEKKI\"(0x3081 0x3063 0x304D)"},
+ {"\u3075\u3042\u3093", "\u30D5\u30A1\u30F3",
+ "Hiragana \"FUAN\"(0x3075 0x3042 0x3093) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"},
+ {"\u3075\u3041\u3093", "\u30D5\u30A2\u30F3",
+ "Hiragana \"FUaN\"(0x3075 0x3041 0x3093) <---> Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3)"},
+ {"\u30D5\u30A2\u30F3", "\u30D5\u30A1\u30F3",
+ "Katakana \"FUAN\"(0x30D5 0x30A2 0x30F3) <---> Katakana \"FUaN\"(0x30D5 0x30A1 0x30F3)"},
+ };
+
+ /*
+ * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+ * -------------------+--------------------+------------------+-------------
+ * PRIMARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ * SECONDARY | s1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ * TERTIARY(default) | S1 = s2 (0) | s1 = s2 (0) | s1 = s2 (0)
+ */
+ static final int[][] results4 = {
+ { 0, 0, 0},
+ { 0, 0, 0},
+ { 0, 0, 0},
+ };
+ static final String[][] compData4 = {
+ /*
+ * Data to verify Japanese normalization
+ */
+ {"\u309E", "\u309D\u3099",
+ "Hiragana Voiced Iteration Mark(0x309E) <---> Hiragana Iteration Mark(0x309D)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+ {"\u30FE", "\u30FD\u3099",
+ "Katakana Voiced Iteration Mark(0x30FE) <---> Katakana iteration mark(0x30FD)Combining Katakana-Hiragana Voiced Sound Mark(0x3099)"},
+ {"\u306F\u3099", "\u3070",
+ "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"BA\"(0x3070)"},
+ {"\u306F\u309A", "\u3071",
+ "Hiragana \"HA\"(0x306F)Combining Katakana-Hiragana Semi-voiced Sound Mark(0x309A) <---> Hiragana \"PA\"(0x3071)"},
+ {"\u30EF\u3099", "\u30F7",
+ "Katakana \"WA\"(0x306F)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VA\"(0x30F7)"},
+ {"\u30F0\u3099", "\u30F8",
+ "Katakana \"WI\"(0x30F0)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VI\"(0x30F8)"},
+ {"\u30F1\u3099", "\u30F9",
+ "Katakana \"WE\"(0x30F1)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VE\"(0x30F9)"},
+ {"\u30F2\u3099", "\u30FA",
+ "Katakana \"WO\"(0x30F2)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VO\"(0x30FA)"},
+ {"\u3046\u3099", "\u3094",
+ "Hiragana \"U\"(0x3046)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Hiragana \"VU\"(0x3094)"},
+ {"\u30A6\u3099", "\u30F4",
+ "Katakana \"U\"(0x30A6)Combining Katakana-Hiragana Voiced Sound Mark(0x3099) <---> Katakana \"VU\"(0x30F4)"},
+
+ // verify normalization
+ {"\u2260", "\u003D\u0338",
+ "Not Equal To(0x2260) <---> Equal(0x003D)Combining Long Solidus Overlay(0x0338)"},
+ {"\u2262", "\u2261\u0338",
+ "Not Identical To(0x2262) <---> Identical To(0x2261)Combining Long Solidus Overlay(0x0338)"},
+ {"\u226E", "\u003C\u0338",
+ "Not Less-than(0x226E) <---> Less-than Sign(0x003C)Combining Long Solidus Overlay(0x0338)"},
+
+ // Verify a character which has been added since Unicode 2.1.X.
+ {"\u798F", "\uFA1B",
+ "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"},
+ };
+
+ /*
+ * | NO_DECOMP(default) | CANONICAL_DECOMP | FULL_DECOMP
+ * -------------------+--------------------+------------------+-------------
+ * PRIMARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0)
+ * SECONDARY | s1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0)
+ * TERTIARY(default) | S1 > s2 (1) | s1 = s2 (0) | s1 = s2 (0)
+ */
+ static final int[][] results5 = {
+ { 1, 0, 0},
+ { 1, 0, 0},
+ { 1, 0, 0},
+ };
+ static final String[][] compData5 = {
+ /*
+ * Data to verify normalization
+ */
+ {"\u226D", "\u224D\u0338",
+ "Not Equivalent To(0x226D) <---> Equivalent To(0x224D)Combining Long Solidus Overlay(0x0338)"},
+ };
+
+ static final int[][] results6 = {
+ { 1, -1, -1},
+ { 1, -1, -1},
+ { 1, -1, -1},
+ };
+ static final String[][] compData6 = {
+ /*
+ * Data to verify normalization
+ */
+ {"\u226D", "\u226C",
+ "Not Equivalent To(0x226D) <---> Between(0x226C)"},
+ {"\u226D", "\u225F",
+ "Not Equivalent To(0x226D) <---> Questioned Equal To(0x225F)"},
+ };
+
+
+ /*
+ * The following data isn't used at the moment because iteration marks
+ * aren't supported now.
+ */
+ static final String[][] compData0 = {
+ {"\u307F\u307F", "\u307F\u309D",
+ "Hiragana \"MIMI\"(0x307F 0x307F) <---> Hiragana \"MI\"(0x307F)Hiragana Iteration Mark(0x309D)"},
+ {"\u3044\u3059\u305A", "\u3044\u3059\u309E",
+ "Hiragana \"ISUZU\"(0x3044 0x3059 0x305A) <---> Hiragana \"ISU\"(0x3044 0x3059)Hiragana Voiced Iteration Mark(0x309E)"},
+ {"\u30DF\u30DF", "\u30DF\u30FD",
+ "Katakana \"MIMI\"(0x30DF 0x30DF) <---> Katakana \"MI\"(0x30DF)Katakana Iteration Mark(0x30FD)"},
+ {"\u30A4\u30B9\u30BA", "\u30A4\u30B9\u30FE",
+ "Katakana \"ISUZU\"(0x30A4 0x30B9 0x30BA) <---> Katakana \"ISU\"(0x30A4 0x30B9)Katakana Voiced Iteration Mark(0x30FE)"},
+ };
+
+
+ static final String[] decomp_name = {
+ "NO_DECOMP", "CANONICAL_DECOMP", "FULL_DECOMP"
+ };
+
+ static final String[] strength_name = {
+ "PRIMARY", "SECONDARY", "TERTIARY"
+ };
+
+
+ Collator col = Collator.getInstance(Locale.JAPAN);
+ int result = 0;
+
+ public static void main(String[] args) throws Exception {
+ new JapaneseTest().run();
+ }
+
+ public void run() {
+ // Use all available localse on the initial testing....
+ // Locale[] locales = Locale.getAvailableLocales();
+ Locale[] locales = { Locale.getDefault() };
+
+ for (int l = 0; l < locales.length; l++) {
+ Locale.setDefault(locales[l]);
+
+ for (int decomp = 0; decomp < 3; decomp++) {// See decomp_name.
+ col.setDecomposition(decomp);
+
+ for (int strength = 0; strength < 3; strength++) {// See strength_name.
+// System.err.println("\n" + locales[l] + ": " + strength_name[strength] + " --- " + decomp_name[decomp]);
+
+ col.setStrength(strength);
+ doCompare(compData1, results1[strength][decomp], strength, decomp);
+ doCompare(compData2, results2[strength][decomp], strength, decomp);
+ doCompare(compData3, results3[strength][decomp], strength, decomp);
+ doCompare(compData4, results4[strength][decomp], strength, decomp);
+ doCompare(compData5, results5[strength][decomp], strength, decomp);
+ doCompare(compData6, results6[strength][decomp], strength, decomp);
+ }
+ }
+ }
+
+ /* Check result */
+ if (result !=0) {
+ throw new RuntimeException("Unexpected results on Japanese collation.");
+ }
+ }
+
+ void doCompare(String[][] s, int expectedValue, int strength, int decomp) {
+ int value;
+ for (int i=0; i < s.length; i++) {
+ if ((value = col.compare(s[i][0], s[i][1])) != expectedValue) {
+ result++;
+ System.err.println(strength_name[strength] +
+ ": compare() returned unexpected value.(" +
+ value + ") on " + decomp_name[decomp] +
+ " Expected(" + expectedValue +
+ ") for " + s[i][2]);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Collator/KoreanTest.java b/test/java/text/Collator/KoreanTest.java
new file mode 100644
index 0000000000..fd314ee13e
--- /dev/null
+++ b/test/java/text/Collator/KoreanTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1997, 2016, 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 1.1 02/09/12
+ * @bug 4176141 4655819
+ * @summary Regression tests for Korean Collation
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class KoreanTest {
+
+ // NOTE:
+ // Golden data in this test case is locale data dependent and
+ // may need to be changed if the Korean locale collation rules
+ // are changed.
+
+ // And, CollationDecomp has been set to 0(NO_DECOMPOSITION) in
+ // LocaleElements_ko.java.
+ // This is very important to consider what is correct behavior in
+ // Korean Collator. Sometimes different from other locales.
+
+ /*
+ * TERTIARY(default): s1 < s2, SECONDARY: s1 < s2, PRIMARY: s1 < s2
+ */
+ static final String[][] compData1 = {
+ /*
+ * Data to verify '<' relationship in LocaleElements_ja.java
+ */
+ {"\uACE0\uC591\uC774", "\u732B",
+ "Hangul \"Cat\"(0xACE0 0xC591 0xC774) <---> Chinese Kanji \"Cat\"(0x732B)"},
+ {"\u30FB", "\u2025",
+ "Katakana middle dot(0x30FB) <---> Two dot leader(0x2025)"},
+
+ {"\u00B1", "\u2260",
+ "Plus-Minus Sign(0x00B1) <---> Not Equal To(0x2260)"},
+ {"\u3011", "\u2260",
+ "Right Black Lenticular Bracket(0x3011) <---> Not Equal To(0x2260)"},
+ {"\u2260", "\u2103",
+ "Not Equal To(0x2260) <---> Degree Celsius(0x2103)"},
+ {"\u2260", "\u2606",
+ "Not Equal To(0x2260) <---> White Star(0x2606)"},
+
+ // Unlike other locales' Collator, compare() returns -1 because of
+ // NO_DECOMPOSITION.
+ /* above "assumption" is no longer true, now we do normalize ("decomposition")
+ for the pattern in ko locale, but exclude those hangul syllables, so the
+ test case below need to be excluded from tiger/1.5
+ {"\u003D\u0338", "\u2260",
+ "Equal(0x003D)Combining Long Solidus Overlay(0x0338) <---> Not Equal To(0x2260)"},
+ */
+ };
+
+ /*
+ * TERTIARY(default): s1 = s2, SECONDARY: s1 = s2, PRIMARY: s1 = s2
+ */
+ static final String[][] compData2 = {
+ // Verify a character which has been added since Unicode 2.1.X.
+ {"\u798F", "\uFA1B",
+ "CJK Unified Ideograph \"FUKU\"(0x798F) <---> CJK Compatibility Ideograph \"FUKU\"(0xFA1B)"},
+
+ };
+
+ Collator col = Collator.getInstance(Locale.KOREA);
+ int result = 0;
+
+ public static void main(String[] args) throws Exception {
+ new KoreanTest().run();
+ }
+
+ public void run() {
+ //
+ // Test for TERTIARY(default)
+ //
+ doCompare(compData1);
+ doEquals(compData2);
+
+ //
+ // Test for SECONDARY
+ //
+ col.setStrength(Collator.SECONDARY);
+ doCompare(compData1);
+ doEquals(compData2);
+
+ //
+ // Test for PRIMARY
+ //
+ col.setStrength(Collator.PRIMARY);
+ doCompare(compData1);
+ doEquals(compData2);
+
+ if (result !=0) {
+ throw new RuntimeException("Unexpected results on Korean collation.");
+ }
+ }
+
+ /* compare() should return -1 for each combination. */
+ void doCompare(String[][] s) {
+ int value;
+ for (int i=0; i < s.length; i++) {
+ if ((value = col.compare(s[i][0], s[i][1])) > -1) {
+ result++;
+ System.err.println("TERTIARY: The first string should be less than the second string: " +
+ s[i][2] + " compare() returned " + value + ".");
+ }
+ }
+ }
+
+ /* equals() should return true for each combination. */
+ void doEquals(String[][] s) {
+ for (int i=0; i < s.length; i++) {
+ if (!col.equals(s[i][0], s[i][1])) {
+ result++;
+ System.err.println("TERTIARY: The first string should be equals to the second string: " +
+ s[i][2] + " compare() returned " +
+ col.compare(s[i][0], s[i][1] + "."));
+ }
+ }
+ }
+}
diff --git a/test/java/text/Collator/MonkeyTest.java b/test/java/text/Collator/MonkeyTest.java
new file mode 100644
index 0000000000..9539bf5f5a
--- /dev/null
+++ b/test/java/text/Collator/MonkeyTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Collation, Monkey style
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.io.IOException;
+import java.util.Random;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+import java.text.CollationKey;
+
+public class MonkeyTest extends CollatorTest
+{
+ public static void main(String[] args) throws Exception {
+ new MonkeyTest().run(args);
+ }
+
+ public void report(String s, String t, int result, int revResult)
+ {
+ if (result == -1)
+ {
+ if (revResult != 1)
+ errln(" --> Test Failed");
+ }
+ else if (result == 1)
+ {
+ if (revResult != -1)
+ errln(" --> Test Failed");
+ }
+ else if (result == 0)
+ {
+ if (revResult != 0)
+ errln(" --> Test Failed");
+ }
+ }
+
+ public void TestCollationKey()
+ {
+ String source = "-abcdefghijklmnopqrstuvwxyz#&^$@";
+ Random r = new Random(3);
+ int s = checkValue(r.nextInt() % source.length());
+ int t = checkValue(r.nextInt() % source.length());
+ int slen = checkValue((r.nextInt() - source.length()) % source.length());
+ int tlen = checkValue((r.nextInt() - source.length()) % source.length());
+ String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen));
+ String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen));
+ myCollator.setStrength(Collator.TERTIARY);
+ CollationKey CollationKey1 = myCollator.getCollationKey(subs);
+ CollationKey CollationKey2 = myCollator.getCollationKey(subt);
+ int result = CollationKey1.compareTo(CollationKey2); // Tertiary
+ int revResult = CollationKey2.compareTo(CollationKey1); // Tertiary
+ report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult);
+ myCollator.setStrength(Collator.SECONDARY);
+ CollationKey1 = myCollator.getCollationKey(subs);
+ CollationKey2 = myCollator.getCollationKey(subt);
+ result = CollationKey1.compareTo(CollationKey2); // Secondary
+ revResult = CollationKey2.compareTo(CollationKey1); // Secondary
+ report(("CollationKey(" + subs + ")") , ("CollationKey(" + subt + ")"), result, revResult);
+ myCollator.setStrength(Collator.PRIMARY);
+ CollationKey1 = myCollator.getCollationKey(subs);
+ CollationKey2 = myCollator.getCollationKey(subt);
+ result = CollationKey1.compareTo(CollationKey2); // Primary
+ revResult = CollationKey2.compareTo(CollationKey1); // Primary
+ report(("CollationKey(" + subs + ")"), ("CollationKey(" + subt + ")"), result, revResult);
+ String addOne = subs + "\uE000";
+ CollationKey1 = myCollator.getCollationKey(subs);
+ CollationKey2 = myCollator.getCollationKey(addOne);
+ result = CollationKey1.compareTo(CollationKey2);
+ if (result != -1)
+ errln("CollationKey(" + subs + ")" + ".LT." + "CollationKey(" + addOne + ") Failed.");
+ result = CollationKey2.compareTo(CollationKey1);
+ if (result != 1)
+ errln("CollationKey(" + addOne + ")" + ".GT." + "CollationKey(" + subs + ") Failed.");
+ }
+ private static int checkValue(int value)
+ {
+ value *= (value > 0) ? 1 : -1;
+ return value;
+ }
+ public void TestCompare()
+ {
+ String source = "-abcdefghijklmnopqrstuvwxyz#&^$@";
+ Random r = new Random(3);
+ int s = checkValue(r.nextInt() % source.length());
+ int t = checkValue(r.nextInt() % source.length());
+ int slen = checkValue((r.nextInt() - source.length()) % source.length());
+ int tlen = checkValue((r.nextInt() - source.length()) % source.length());
+ String subs = source.substring((s > slen ? slen : s), (s >= slen ? s : slen));
+ String subt = source.substring((t > tlen ? tlen : t), (t >= tlen ? t : tlen));
+ myCollator.setStrength(Collator.TERTIARY);
+ int result = myCollator.compare(subs, subt); // Tertiary
+ int revResult = myCollator.compare(subt, subs); // Tertiary
+ report(subs, subt, result, revResult);
+ myCollator.setStrength(Collator.SECONDARY);
+ result = myCollator.compare(subs, subt); // Secondary
+ revResult = myCollator.compare(subt, subs); // Secondary
+ report(subs, subt, result, revResult);
+ myCollator.setStrength(Collator.PRIMARY);
+ result = myCollator.compare(subs, subt); // Primary
+ revResult = myCollator.compare(subt, subs); // Primary
+ report(subs, subt, result, revResult);
+ String addOne = subs + "\uE000";
+ result = myCollator.compare(subs, addOne);
+ if (result != -1)
+ errln("Test : " + subs + " .LT. " + addOne + " Failed.");
+ result = myCollator.compare(addOne, subs);
+ if (result != 1)
+ errln("Test : " + addOne + " .GE. " + subs + " Failed.");
+ }
+ private static Collator myCollator = Collator.getInstance();
+}
diff --git a/test/java/text/Collator/Regression.java b/test/java/text/Collator/Regression.java
new file mode 100644
index 0000000000..958ce29c52
--- /dev/null
+++ b/test/java/text/Collator/Regression.java
@@ -0,0 +1,940 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4048446 4051866 4053636 4054238 4054734 4054736 4058613 4059820 4060154
+ * 4062418 4065540 4066189 4066696 4076676 4078588 4079231 4081866 4087241
+ * 4087243 4092260 4095316 4101940 4103436 4114076 4114077 4124632 4132736
+ * 4133509 4139572 4141640 4179126 4179686 4244884 4663220
+ * @library /java/text/testlib
+ * @summary Regression tests for Collation and associated classes
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.Locale;
+import java.util.Vector;
+
+
+public class Regression extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new Regression().run(args);
+ }
+
+ // CollationElementIterator.reset() doesn't work
+ //
+ public void Test4048446() {
+ CollationElementIterator i1 = en_us.getCollationElementIterator(test1);
+ CollationElementIterator i2 = en_us.getCollationElementIterator(test1);
+
+ while ( i1.next() != CollationElementIterator.NULLORDER ) {
+ }
+ i1.reset();
+
+ assertEqual(i1, i2);
+ }
+
+
+ // Collator -> rules -> Collator round-trip broken for expanding characters
+ //
+ public void Test4051866() throws ParseException {
+ // Build a collator containing expanding characters
+ RuleBasedCollator c1 = new RuleBasedCollator("< o "
+ +"& oe ,o\u3080"
+ +"& oe ,\u1530 ,O"
+ +"& OE ,O\u3080"
+ +"& OE ,\u1520"
+ +"< p ,P");
+
+ // Build another using the rules from the first
+ RuleBasedCollator c2 = new RuleBasedCollator(c1.getRules());
+
+ // Make sure they're the same
+ if (!c1.getRules().equals(c2.getRules())) {
+ errln("Rules are not equal");
+ }
+ }
+
+ // Collator thinks "black-bird" == "black"
+ //
+ public void Test4053636() {
+ if (en_us.equals("black-bird","black")) {
+ errln("black-bird == black");
+ }
+ }
+
+
+ // CollationElementIterator will not work correctly if the associated
+ // Collator object's mode is changed
+ //
+ public void Test4054238() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ CollationElementIterator i1 = en_us.getCollationElementIterator(test3);
+
+ c.setDecomposition(Collator.NO_DECOMPOSITION);
+ CollationElementIterator i2 = en_us.getCollationElementIterator(test3);
+
+ // At this point, BOTH iterators should use NO_DECOMPOSITION, since the
+ // collator itself is in that mode
+ assertEqual(i1, i2);
+ }
+
+ // Collator.IDENTICAL documented but not implemented
+ //
+ public void Test4054734() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ try {
+ c.setStrength(Collator.IDENTICAL);
+ }
+ catch (Exception e) {
+ errln("Caught " + e.toString() + " setting Collator.IDENTICAL");
+ }
+
+ String[] decomp = {
+ "\u0001", "<", "\u0002",
+ "\u0001", "=", "\u0001",
+ "A\u0001", ">", "~\u0002", // Ensure A and ~ are not compared bitwise
+ "\u00C0", "=", "A\u0300" // Decomp should make these equal
+ };
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ compareArray(c, decomp);
+
+ String[] nodecomp = {
+ "\u00C0", ">", "A\u0300" // A-grave vs. A combining-grave
+ };
+ c.setDecomposition(Collator.NO_DECOMPOSITION);
+ compareArray(c, nodecomp);
+ }
+
+ // Full Decomposition mode not implemented
+ //
+ public void Test4054736() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+ String[] tests = {
+ "\uFB4f", "=", "\u05D0\u05DC", // Alef-Lamed vs. Alef, Lamed
+ };
+
+ compareArray(c, tests);
+ }
+
+ // Collator.getInstance() causes an ArrayIndexOutofBoundsException for Korean
+ //
+ public void Test4058613() {
+ // Creating a default collator doesn't work when Korean is the default
+ // locale
+
+ Locale oldDefault = Locale.getDefault();
+
+ Locale.setDefault( Locale.KOREAN );
+ try {
+ Collator c = Collator.getInstance();
+
+ // Since the fix to this bug was to turn of decomposition for Korean collators,
+ // ensure that's what we got
+ if (c.getDecomposition() != Collator.NO_DECOMPOSITION) {
+ errln("Decomposition is not set to NO_DECOMPOSITION");
+ }
+ }
+ finally {
+ Locale.setDefault(oldDefault);
+ }
+ }
+
+ // RuleBasedCollator.getRules does not return the exact pattern as input
+ // for expanding character sequences
+ //
+ public void Test4059820() {
+ RuleBasedCollator c = null;
+ try {
+ c = new RuleBasedCollator("< a < b , c/a < d < z");
+ } catch (ParseException e) {
+ errln("Exception building collator: " + e.toString());
+ return;
+ }
+ if ( c.getRules().indexOf("c/a") == -1) {
+ errln("returned rules do not contain 'c/a'");
+ }
+ }
+
+ // MergeCollation::fixEntry broken for "& H < \u0131, \u0130, i, I"
+ //
+ public void Test4060154() {
+ RuleBasedCollator c = null;
+ try {
+ c = new RuleBasedCollator("< g, G < h, H < i, I < j, J"
+ + " & H < \u0131, \u0130, i, I" );
+ } catch (ParseException e) {
+ errln("Exception building collator: " + e.toString());
+ return;
+ }
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+
+ String[] tertiary = {
+ "A", "<", "B",
+ "H", "<", "\u0131",
+ "H", "<", "I",
+ "\u0131", "<", "\u0130",
+ "\u0130", "<", "i",
+ "\u0130", ">", "H",
+ };
+ c.setStrength(Collator.TERTIARY);
+ compareArray(c, tertiary);
+
+ String[] secondary = {
+ "H", "<", "I",
+ "\u0131", "=", "\u0130",
+ };
+ c.setStrength(Collator.PRIMARY);
+ compareArray(c, secondary);
+ };
+
+ // Secondary/Tertiary comparison incorrect in French Secondary
+ //
+ public void Test4062418() throws ParseException {
+ RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE);
+ c.setStrength(Collator.SECONDARY);
+
+ String[] tests = {
+ "p\u00eache", "<", "p\u00e9ch\u00e9", // Comparing accents from end, p\u00e9ch\u00e9 is greater
+ };
+
+ compareArray(c, tests);
+ }
+
+ // Collator.compare() method broken if either string contains spaces
+ //
+ public void Test4065540() {
+ if (en_us.compare("abcd e", "abcd f") == 0) {
+ errln("'abcd e' == 'abcd f'");
+ }
+ }
+
+ // Unicode characters need to be recursively decomposed to get the
+ // correct result. For example,
+ // u1EB1 -> \u0103 + \u0300 -> a + \u0306 + \u0300.
+ //
+ public void Test4066189() {
+ String test1 = "\u1EB1";
+ String test2 = "a\u0306\u0300";
+
+ RuleBasedCollator c1 = (RuleBasedCollator) en_us.clone();
+ c1.setDecomposition(Collator.FULL_DECOMPOSITION);
+ CollationElementIterator i1 = en_us.getCollationElementIterator(test1);
+
+ RuleBasedCollator c2 = (RuleBasedCollator) en_us.clone();
+ c2.setDecomposition(Collator.NO_DECOMPOSITION);
+ CollationElementIterator i2 = en_us.getCollationElementIterator(test2);
+
+ assertEqual(i1, i2);
+ }
+
+ // French secondary collation checking at the end of compare iteration fails
+ //
+ public void Test4066696() {
+ RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(Locale.FRANCE);
+ c.setStrength(Collator.SECONDARY);
+
+ String[] tests = {
+ "\u00e0", "<", "\u01fa", // a-grave < A-ring-acute
+ };
+
+ compareArray(c, tests);
+ }
+
+
+ // Bad canonicalization of same-class combining characters
+ //
+ public void Test4076676() {
+ // These combining characters are all in the same class, so they should not
+ // be reordered, and they should compare as unequal.
+ String s1 = "A\u0301\u0302\u0300";
+ String s2 = "A\u0302\u0300\u0301";
+
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ if (c.compare(s1,s2) == 0) {
+ errln("Same-class combining chars were reordered");
+ }
+ }
+
+
+ // RuleBasedCollator.equals(null) throws NullPointerException
+ //
+ public void Test4079231() {
+ try {
+ if (en_us.equals(null)) {
+ errln("en_us.equals(null) returned true");
+ }
+ }
+ catch (Exception e) {
+ errln("en_us.equals(null) threw " + e.toString());
+ }
+ }
+
+ // RuleBasedCollator breaks on "< a < bb" rule
+ //
+ public void Test4078588() throws ParseException {
+ RuleBasedCollator rbc=new RuleBasedCollator("< a < bb");
+
+ int result = rbc.compare("a","bb");
+
+ if (result != -1) {
+ errln("Compare(a,bb) returned " + result + "; expected -1");
+ }
+ }
+
+ // Combining characters in different classes not reordered properly.
+ //
+ public void Test4081866() throws ParseException {
+ // These combining characters are all in different classes,
+ // so they should be reordered and the strings should compare as equal.
+ String s1 = "A\u0300\u0316\u0327\u0315";
+ String s2 = "A\u0327\u0316\u0315\u0300";
+
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ // Now that the default collators are set to NO_DECOMPOSITION
+ // (as a result of fixing bug 4114077), we must set it explicitly
+ // when we're testing reordering behavior. -- lwerner, 5/5/98
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+
+ if (c.compare(s1,s2) != 0) {
+ errln("Combining chars were not reordered");
+ }
+ }
+
+ // string comparison errors in Scandinavian collators
+ //
+ public void Test4087241() {
+ RuleBasedCollator c = (RuleBasedCollator) Collator.getInstance(
+ new Locale("da", "DK"));
+ c.setStrength(Collator.SECONDARY);
+
+ String[] tests = {
+ "\u007a", "<", "\u00e6", // z < ae
+ "a\u0308", "<", "a\u030a", // a-unlaut < a-ring
+ "Y", "<", "u\u0308", // Y < u-umlaut
+ };
+
+ compareArray(c, tests);
+ }
+
+ // CollationKey takes ignorable strings into account when it shouldn't
+ //
+ public void Test4087243() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ String[] tests = {
+ "123", "=", "123\u0001", // 1 2 3 = 1 2 3 ctrl-A
+ };
+
+ compareArray(c, tests);
+ }
+
+ // Mu/micro conflict
+ // Micro symbol and greek lowercase letter Mu should sort identically
+ //
+ public void Test4092260() {
+ Collator c = Collator.getInstance(new Locale("el", ""));
+
+ // will only be equal when FULL_DECOMPOSITION is used
+ c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+ String[] tests = {
+ "\u00B5", "=", "\u03BC",
+ };
+
+ compareArray(c, tests);
+ }
+
+ void Test4095316() {
+ Collator c = Collator.getInstance(new Locale("el", "GR"));
+ c.setStrength(Collator.TERTIARY);
+ // javadocs for RuleBasedCollator clearly specify that characters containing compatability
+ // chars MUST use FULL_DECOMPOSITION to get accurate comparisons.
+ c.setDecomposition(Collator.FULL_DECOMPOSITION);
+
+ String[] tests = {
+ "\u03D4", "=", "\u03AB",
+ };
+
+ compareArray(c, tests);
+ }
+
+ public void Test4101940() {
+ try {
+ RuleBasedCollator c = new RuleBasedCollator("< a < b");
+ CollationElementIterator i = c.getCollationElementIterator("");
+ i.reset();
+
+ if (i.next() != i.NULLORDER) {
+ errln("next did not return NULLORDER");
+ }
+ }
+ catch (Exception e) {
+ errln("Caught " + e );
+ }
+ }
+
+ // Collator.compare not handling spaces properly
+ //
+ public void Test4103436() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ String[] tests = {
+ "file", "<", "file access",
+ "file", "<", "fileaccess",
+ };
+
+ compareArray(c, tests);
+ }
+
+ // Collation not Unicode conformant with Hangul syllables
+ //
+ public void Test4114076() {
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ //
+ // With Canonical decomposition, Hangul syllables should get decomposed
+ // into Jamo, but Jamo characters should not be decomposed into
+ // conjoining Jamo
+ //
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ String[] test1 = {
+ "\ud4db", "=", "\u1111\u1171\u11b6",
+ };
+ compareArray(c, test1);
+
+ // Full decomposition result should be the same as canonical decomposition
+ // for all hangul.
+ c.setDecomposition(Collator.FULL_DECOMPOSITION);
+ compareArray(c, test1);
+
+ }
+
+
+ // Collator.getCollationKey was hanging on certain character sequences
+ //
+ public void Test4124632() throws Exception {
+ Collator coll = Collator.getInstance(Locale.JAPAN);
+
+ try {
+ coll.getCollationKey("A\u0308bc");
+ } catch (OutOfMemoryError e) {
+ errln("Ran out of memory -- probably an infinite loop");
+ }
+ }
+
+ // sort order of french words with multiple accents has errors
+ //
+ public void Test4132736() {
+ Collator c = Collator.getInstance(Locale.FRANCE);
+
+ String[] test1 = {
+ "e\u0300e\u0301", "<", "e\u0301e\u0300",
+ "e\u0300\u0301", ">", "e\u0301\u0300",
+ };
+ compareArray(c, test1);
+ }
+
+ // The sorting using java.text.CollationKey is not in the exact order
+ //
+ public void Test4133509() {
+ String[] test1 = {
+ "Exception", "<", "ExceptionInInitializerError",
+ "Graphics", "<", "GraphicsEnvironment",
+ "String", "<", "StringBuffer",
+ };
+ compareArray(en_us, test1);
+ }
+
+ // Collation with decomposition off doesn't work for Europe
+ //
+ public void Test4114077() {
+ // Ensure that we get the same results with decomposition off
+ // as we do with it on....
+
+ RuleBasedCollator c = (RuleBasedCollator) en_us.clone();
+ c.setStrength(Collator.TERTIARY);
+
+ String[] test1 = {
+ "\u00C0", "=", "A\u0300", // Should be equivalent
+ "p\u00eache", ">", "p\u00e9ch\u00e9",
+ "\u0204", "=", "E\u030F",
+ "\u01fa", "=", "A\u030a\u0301", // a-ring-acute -> a-ring, acute
+ // -> a, ring, acute
+ "A\u0300\u0316", "<", "A\u0316\u0300", // No reordering --> unequal
+ };
+ c.setDecomposition(Collator.NO_DECOMPOSITION);
+ compareArray(c, test1);
+
+ String[] test2 = {
+ "A\u0300\u0316", "=", "A\u0316\u0300", // Reordering --> equal
+ };
+ c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
+ compareArray(c, test2);
+ }
+
+ // Support for Swedish gone in 1.1.6 (Can't create Swedish collator)
+ //
+ public void Test4141640() {
+ //
+ // Rather than just creating a Swedish collator, we might as well
+ // try to instantiate one for every locale available on the system
+ // in order to prevent this sort of bug from cropping up in the future
+ //
+ Locale[] locales = Collator.getAvailableLocales();
+
+ for (int i = 0; i < locales.length; i++) {
+ try {
+ Collator c = Collator.getInstance(locales[i]);
+ } catch (Exception e) {
+ errln("Caught " + e + " creating collator for " + locales[i]);
+ }
+ }
+ }
+
+ // getCollationKey throws exception for spanish text
+ // Cannot reproduce this bug on 1.2, however it DOES fail on 1.1.6
+ //
+ public void Test4139572() {
+ //
+ // Code pasted straight from the bug report
+ //
+ // create spanish locale and collator
+ Locale l = new Locale("es", "es");
+ Collator col = Collator.getInstance(l);
+
+ // this spanish phrase kills it!
+ col.getCollationKey("Nombre De Objeto");
+ }
+
+ // RuleBasedCollator doesn't use getCollationElementIterator internally
+ //
+ public void Test4146160() throws ParseException {
+ //
+ // Use a custom collator class whose getCollationElementIterator
+ // methods increment a count....
+ //
+ My4146160Collator.count = 0;
+ new My4146160Collator().getCollationKey("1");
+ if (My4146160Collator.count < 1) {
+ errln("getCollationElementIterator not called");
+ }
+
+ My4146160Collator.count = 0;
+ new My4146160Collator().compare("1", "2");
+ if (My4146160Collator.count < 1) {
+ errln("getCollationElementIterator not called");
+ }
+ }
+
+ static class My4146160Collator extends RuleBasedCollator {
+ public My4146160Collator() throws ParseException {
+ super(Regression.en_us.getRules());
+ }
+
+ public CollationElementIterator getCollationElementIterator(
+ String text) {
+ count++;
+ return super.getCollationElementIterator(text);
+ }
+ public CollationElementIterator getCollationElementIterator(
+ CharacterIterator text) {
+ count++;
+ return super.getCollationElementIterator(text);
+ }
+
+ public static int count = 0;
+ };
+
+ // CollationElementIterator.previous broken for expanding char sequences
+ //
+ public void Test4179686() throws ParseException {
+
+ // Create a collator with a few expanding character sequences in it....
+ RuleBasedCollator coll = new RuleBasedCollator(en_us.getRules()
+ + " & ae ; \u00e4 & AE ; \u00c4"
+ + " & oe ; \u00f6 & OE ; \u00d6"
+ + " & ue ; \u00fc & UE ; \u00dc");
+
+ String text = "T\u00f6ne"; // o-umlaut
+
+ CollationElementIterator iter = coll.getCollationElementIterator(text);
+ Vector elements = new Vector();
+ int elem;
+
+ // Iterate forward and collect all of the elements into a Vector
+ while ((elem = iter.next()) != iter.NULLORDER) {
+ elements.addElement(new Integer(elem));
+ }
+
+ // Now iterate backward and make sure they're the same
+ int index = elements.size() - 1;
+ while ((elem = iter.previous()) != iter.NULLORDER) {
+ int expect = ((Integer)elements.elementAt(index)).intValue();
+
+ if (elem != expect) {
+ errln("Mismatch at index " + index
+ + ": got " + Integer.toString(elem,16)
+ + ", expected " + Integer.toString(expect,16));
+ }
+ index--;
+ }
+ }
+
+ public void Test4244884() throws ParseException {
+ RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US);
+ coll = new RuleBasedCollator(coll.getRules()
+ + " & C < ch , cH , Ch , CH < cat < crunchy");
+
+ String[] testStrings = new String[] {
+ "car",
+ "cave",
+ "clamp",
+ "cramp",
+ "czar",
+ "church",
+ "catalogue",
+ "crunchy",
+ "dog"
+ };
+
+ for (int i = 1; i < testStrings.length; i++) {
+ if (coll.compare(testStrings[i - 1], testStrings[i]) >= 0) {
+ errln("error: \"" + testStrings[i - 1]
+ + "\" is greater than or equal to \"" + testStrings[i]
+ + "\".");
+ }
+ }
+ }
+
+ public void Test4179216() throws ParseException {
+ // you can position a CollationElementIterator in the middle of
+ // a contracting character sequence, yielding a bogus collation
+ // element
+ RuleBasedCollator coll = (RuleBasedCollator)Collator.getInstance(Locale.US);
+ coll = new RuleBasedCollator(coll.getRules()
+ + " & C < ch , cH , Ch , CH < cat < crunchy");
+ String testText = "church church catcatcher runcrunchynchy";
+ CollationElementIterator iter = coll.getCollationElementIterator(
+ testText);
+
+ // test that the "ch" combination works properly
+ iter.setOffset(4);
+ int elt4 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.reset();
+ int elt0 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(5);
+ int elt5 = CollationElementIterator.primaryOrder(iter.next());
+
+ if (elt4 != elt0 || elt5 != elt0)
+ errln("The collation elements at positions 0 (" + elt0 + "), 4 ("
+ + elt4 + "), and 5 (" + elt5 + ") don't match.");
+
+ // test that the "cat" combination works properly
+ iter.setOffset(14);
+ int elt14 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(15);
+ int elt15 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(16);
+ int elt16 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(17);
+ int elt17 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(18);
+ int elt18 = CollationElementIterator.primaryOrder(iter.next());
+
+ iter.setOffset(19);
+ int elt19 = CollationElementIterator.primaryOrder(iter.next());
+
+ if (elt14 != elt15 || elt14 != elt16 || elt14 != elt17
+ || elt14 != elt18 || elt14 != elt19)
+ errln("\"cat\" elements don't match: elt14 = " + elt14 + ", elt15 = "
+ + elt15 + ", elt16 = " + elt16 + ", elt17 = " + elt17
+ + ", elt18 = " + elt18 + ", elt19 = " + elt19);
+
+ // now generate a complete list of the collation elements,
+ // first using next() and then using setOffset(), and
+ // make sure both interfaces return the same set of elements
+ iter.reset();
+
+ int elt = iter.next();
+ int count = 0;
+ while (elt != CollationElementIterator.NULLORDER) {
+ ++count;
+ elt = iter.next();
+ }
+
+ String[] nextElements = new String[count];
+ String[] setOffsetElements = new String[count];
+ int lastPos = 0;
+
+ iter.reset();
+ elt = iter.next();
+ count = 0;
+ while (elt != CollationElementIterator.NULLORDER) {
+ nextElements[count++] = testText.substring(lastPos, iter.getOffset());
+ lastPos = iter.getOffset();
+ elt = iter.next();
+ }
+ count = 0;
+ for (int i = 0; i < testText.length(); ) {
+ iter.setOffset(i);
+ lastPos = iter.getOffset();
+ elt = iter.next();
+ setOffsetElements[count++] = testText.substring(lastPos, iter.getOffset());
+ i = iter.getOffset();
+ }
+ for (int i = 0; i < nextElements.length; i++) {
+ if (nextElements[i].equals(setOffsetElements[i])) {
+ logln(nextElements[i]);
+ } else {
+ errln("Error: next() yielded " + nextElements[i] + ", but setOffset() yielded "
+ + setOffsetElements[i]);
+ }
+ }
+ }
+
+ public void Test4216006() throws Exception {
+ // rule parser barfs on "<\u00e0=a\u0300", and on other cases
+ // where the same token (after normalization) appears twice in a row
+ boolean caughtException = false;
+ try {
+ RuleBasedCollator dummy = new RuleBasedCollator("\u00e0<a\u0300");
+ }
+ catch (ParseException e) {
+ caughtException = true;
+ }
+ if (!caughtException) {
+ throw new Exception("\"a<a\" collation sequence didn't cause parse error!");
+ }
+
+ RuleBasedCollator collator = new RuleBasedCollator("<\u00e0=a\u0300");
+ collator.setDecomposition(Collator.FULL_DECOMPOSITION);
+ collator.setStrength(Collator.IDENTICAL);
+
+ String[] tests = {
+ "a\u0300", "=", "\u00e0",
+ "\u00e0", "=", "a\u0300"
+ };
+
+ compareArray(collator, tests);
+ }
+
+ public void Test4171974() {
+ // test French accent ordering more thoroughly
+ String[] frenchList = {
+ "\u0075\u0075", // u u
+ "\u00fc\u0075", // u-umlaut u
+ "\u01d6\u0075", // u-umlaut-macron u
+ "\u016b\u0075", // u-macron u
+ "\u1e7b\u0075", // u-macron-umlaut u
+ "\u0075\u00fc", // u u-umlaut
+ "\u00fc\u00fc", // u-umlaut u-umlaut
+ "\u01d6\u00fc", // u-umlaut-macron u-umlaut
+ "\u016b\u00fc", // u-macron u-umlaut
+ "\u1e7b\u00fc", // u-macron-umlaut u-umlaut
+ "\u0075\u01d6", // u u-umlaut-macron
+ "\u00fc\u01d6", // u-umlaut u-umlaut-macron
+ "\u01d6\u01d6", // u-umlaut-macron u-umlaut-macron
+ "\u016b\u01d6", // u-macron u-umlaut-macron
+ "\u1e7b\u01d6", // u-macron-umlaut u-umlaut-macron
+ "\u0075\u016b", // u u-macron
+ "\u00fc\u016b", // u-umlaut u-macron
+ "\u01d6\u016b", // u-umlaut-macron u-macron
+ "\u016b\u016b", // u-macron u-macron
+ "\u1e7b\u016b", // u-macron-umlaut u-macron
+ "\u0075\u1e7b", // u u-macron-umlaut
+ "\u00fc\u1e7b", // u-umlaut u-macron-umlaut
+ "\u01d6\u1e7b", // u-umlaut-macron u-macron-umlaut
+ "\u016b\u1e7b", // u-macron u-macron-umlaut
+ "\u1e7b\u1e7b" // u-macron-umlaut u-macron-umlaut
+ };
+ Collator french = Collator.getInstance(Locale.FRENCH);
+
+ logln("Testing French order...");
+ checkListOrder(frenchList, french);
+
+ logln("Testing French order without decomposition...");
+ french.setDecomposition(Collator.NO_DECOMPOSITION);
+ checkListOrder(frenchList, french);
+
+ String[] englishList = {
+ "\u0075\u0075", // u u
+ "\u0075\u00fc", // u u-umlaut
+ "\u0075\u01d6", // u u-umlaut-macron
+ "\u0075\u016b", // u u-macron
+ "\u0075\u1e7b", // u u-macron-umlaut
+ "\u00fc\u0075", // u-umlaut u
+ "\u00fc\u00fc", // u-umlaut u-umlaut
+ "\u00fc\u01d6", // u-umlaut u-umlaut-macron
+ "\u00fc\u016b", // u-umlaut u-macron
+ "\u00fc\u1e7b", // u-umlaut u-macron-umlaut
+ "\u01d6\u0075", // u-umlaut-macron u
+ "\u01d6\u00fc", // u-umlaut-macron u-umlaut
+ "\u01d6\u01d6", // u-umlaut-macron u-umlaut-macron
+ "\u01d6\u016b", // u-umlaut-macron u-macron
+ "\u01d6\u1e7b", // u-umlaut-macron u-macron-umlaut
+ "\u016b\u0075", // u-macron u
+ "\u016b\u00fc", // u-macron u-umlaut
+ "\u016b\u01d6", // u-macron u-umlaut-macron
+ "\u016b\u016b", // u-macron u-macron
+ "\u016b\u1e7b", // u-macron u-macron-umlaut
+ "\u1e7b\u0075", // u-macron-umlaut u
+ "\u1e7b\u00fc", // u-macron-umlaut u-umlaut
+ "\u1e7b\u01d6", // u-macron-umlaut u-umlaut-macron
+ "\u1e7b\u016b", // u-macron-umlaut u-macron
+ "\u1e7b\u1e7b" // u-macron-umlaut u-macron-umlaut
+ };
+ Collator english = Collator.getInstance(Locale.ENGLISH);
+
+ logln("Testing English order...");
+ checkListOrder(englishList, english);
+
+ logln("Testing English order without decomposition...");
+ english.setDecomposition(Collator.NO_DECOMPOSITION);
+ checkListOrder(englishList, english);
+ }
+
+ private void checkListOrder(String[] sortedList, Collator c) {
+ // this function uses the specified Collator to make sure the
+ // passed-in list is already sorted into ascending order
+ for (int i = 0; i < sortedList.length - 1; i++) {
+ if (c.compare(sortedList[i], sortedList[i + 1]) >= 0) {
+ errln("List out of order at element #" + i + ": "
+ + prettify(sortedList[i]) + " >= "
+ + prettify(sortedList[i + 1]));
+ }
+ }
+ }
+
+ // CollationElementIterator set doesn't work propertly with next/prev
+ public void Test4663220() {
+ RuleBasedCollator collator = (RuleBasedCollator)Collator.getInstance(Locale.US);
+ CharacterIterator stringIter = new StringCharacterIterator("fox");
+ CollationElementIterator iter = collator.getCollationElementIterator(stringIter);
+
+ int[] elements_next = new int[3];
+ logln("calling next:");
+ for (int i = 0; i < 3; ++i) {
+ logln("[" + i + "] " + (elements_next[i] = iter.next()));
+ }
+
+ int[] elements_fwd = new int[3];
+ logln("calling set/next:");
+ for (int i = 0; i < 3; ++i) {
+ iter.setOffset(i);
+ logln("[" + i + "] " + (elements_fwd[i] = iter.next()));
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ if (elements_next[i] != elements_fwd[i]) {
+ errln("mismatch at position " + i +
+ ": " + elements_next[i] +
+ " != " + elements_fwd[i]);
+ }
+ }
+ }
+
+ //------------------------------------------------------------------------
+ // Internal utilities
+ //
+ private void compareArray(Collator c, String[] tests) {
+ for (int i = 0; i < tests.length; i += 3) {
+
+ int expect = 0;
+ if (tests[i+1].equals("<")) {
+ expect = -1;
+ } else if (tests[i+1].equals(">")) {
+ expect = 1;
+ } else if (tests[i+1].equals("=")) {
+ expect = 0;
+ } else {
+ expect = Integer.decode(tests[i+1]).intValue();
+ }
+
+ int result = c.compare(tests[i], tests[i+2]);
+ if (sign(result) != sign(expect))
+ {
+ errln( i/3 + ": compare(" + prettify(tests[i])
+ + " , " + prettify(tests[i+2])
+ + ") got " + result + "; expected " + expect);
+ }
+ else
+ {
+ // Collator.compare worked OK; now try the collation keys
+ CollationKey k1 = c.getCollationKey(tests[i]);
+ CollationKey k2 = c.getCollationKey(tests[i+2]);
+
+ result = k1.compareTo(k2);
+ if (sign(result) != sign(expect)) {
+ errln( i/3 + ": key(" + prettify(tests[i])
+ + ").compareTo(key(" + prettify(tests[i+2])
+ + ")) got " + result + "; expected " + expect);
+
+ errln(" " + prettify(k1) + " vs. " + prettify(k2));
+ }
+ }
+ }
+ }
+
+ private static final int sign(int i) {
+ if (i < 0) return -1;
+ if (i > 0) return 1;
+ return 0;
+ }
+
+
+ static RuleBasedCollator en_us = (RuleBasedCollator)Collator.getInstance(Locale.US);
+
+ String test1 = "XFILE What subset of all possible test cases has the highest probability of detecting the most errors?";
+ String test2 = "Xf ile What subset of all possible test cases has the lowest probability of detecting the least errors?";
+ String test3 = "a\u00FCbeck Gr\u00F6\u00DFe L\u00FCbeck";
+}
diff --git a/test/java/text/Collator/SpanishTest.java b/test/java/text/Collator/SpanishTest.java
new file mode 100644
index 0000000000..fab4ef0d66
--- /dev/null
+++ b/test/java/text/Collator/SpanishTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Spanish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class SpanishTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new SpanishTest().run(args);
+ }
+
+ /*
+ * TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "alias",
+ "acHc",
+ "acc",
+ "Hello"
+ };
+
+ private static final String[] primaryTargetData = {
+ "allias",
+ "aCHc",
+ "aCHc",
+ "hellO"
+ };
+
+ private static final int[] primaryResults = {
+ -1, 0, -1, 0
+ };
+
+ /*
+ * TestTertiary()
+ */
+ private static final String[] tertiarySourceData = {
+ "alias",
+ "Elliot",
+ "Hello",
+ "acHc",
+ "acc"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "allias",
+ "Emiot",
+ "hellO",
+ "aCHc",
+ "aCHc"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, -1, 1, -1, -1
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("es", "ES", ""));
+}
diff --git a/test/java/text/Collator/SurrogatesTest.java b/test/java/text/Collator/SurrogatesTest.java
new file mode 100644
index 0000000000..87df904e88
--- /dev/null
+++ b/test/java/text/Collator/SurrogatesTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2003, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Supplementary Character Collation
+ */
+
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+// Quick dummy program for printing out test results
+public class SurrogatesTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new SurrogatesTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "A\ud800\udc04BCD"
+ };
+
+ private static final String[] primaryTargetData = {
+ "A\ud800\udc05BCD"
+ };
+
+ private static final int[] primaryResults = {
+ 0
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final String[] tertiarySourceData = {
+ "ABCD",
+ "ABCD",
+ "A\ud800\udc00CD",
+ "WXYZ",
+ "WXYZ",
+ "AFEM",
+ "FGM",
+ "BB",
+ "BB"
+ };
+
+ private static final String[] tertiaryTargetData = {
+ "A\ud800\udc00CD",
+ "AB\ud800\udc00D",
+ "A\ud800\udc01CD",
+ "W\ud800\udc0aYZ",
+ "W\ud800\udc0bYZ",
+ "A\ud800\udc08M",
+ "\ud800\udc08M",
+ "\ud800\udc04\ud800\udc02",
+ "\ud800\udc04\ud800\udc05"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, 1, 1, 1, -1, -1, -1, -1, 1
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+ }
+
+ private Collator getCollator() {
+ RuleBasedCollator base = (RuleBasedCollator)Collator.getInstance();
+ String rule = base.getRules();
+ try {
+ return new RuleBasedCollator(rule
+ + "&B < \ud800\udc01 < \ud800\udc00"
+ + ", \ud800\udc02, \ud800\udc03"
+ + "; \ud800\udc04, \ud800\udc05"
+ + "< \ud800\udc06 < \ud800\udc07"
+ + "&FE < \ud800\udc08"
+ + "&PE, \ud800\udc09"
+ + "&Z < \ud800\udc0a < \ud800\udc0b < \ud800\udc0c"
+ + "&\ud800\udc0a < x, X"
+ + "&A < \ud800\udc04\ud800\udc05");
+ } catch (Exception e) {
+ errln("Failed to create new RulebasedCollator object");
+ return null;
+ }
+ }
+
+ private Collator myCollation = getCollator();
+}
diff --git a/test/java/text/Collator/Test4401726.java b/test/java/text/Collator/Test4401726.java
new file mode 100644
index 0000000000..6f9e9ed945
--- /dev/null
+++ b/test/java/text/Collator/Test4401726.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4401726
+ * @author John O'Conner
+ * @library /java/text/testlib
+ * @summary Regression tests for Collation and associated classes
+ */
+
+
+import java.text.*;
+import java.util.Locale;
+import java.util.Vector;
+
+public class Test4401726 extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new Test4401726().run(args);
+ }
+
+ public void TestSetOffSet() {
+
+ int[] expected = {0, -1, 65536};
+ int[] actual = new int[expected.length];
+
+ try {
+ String rule = "< a, A < d; D";
+
+ RuleBasedCollator rbc = new RuleBasedCollator(rule);
+ String str = "aD";
+ CollationElementIterator iterator =
+ rbc.getCollationElementIterator(str);
+
+ iterator.setOffset(0);
+ actual[0] = iterator.getOffset();
+ actual[1] = iterator.previous();
+ iterator.setOffset(0);
+ actual[2] = iterator.next();
+
+ if (compareArray(expected, actual) == false) {
+ errln("Failed.");
+ }
+
+ str = "a";
+ iterator = rbc.getCollationElementIterator(str);
+ iterator.setOffset(0);
+ actual[0] = iterator.getOffset();
+ actual[1] = iterator.previous();
+ iterator.setOffset(0);
+ actual[2] = iterator.next();
+
+ if (compareArray(expected, actual) == false) {
+ errln("Failed.");
+ }
+
+ } catch (ParseException e) {
+ errln("Unexpected ParseException: " + e);
+ }
+
+
+ }
+
+ boolean compareArray(int[] expected, int[] actual) {
+ boolean retVal = false;
+ if (expected.length == actual.length) {
+ int errors = 0;
+ for(int x=0; x< expected.length; ++x) {
+ if (expected[x] != actual[x]) {
+ ++errors;
+ }
+ }
+ if (errors == 0) retVal = true;
+ }
+ return retVal;
+ }
+}
diff --git a/test/java/text/Collator/ThaiTest.java b/test/java/text/Collator/ThaiTest.java
new file mode 100644
index 0000000000..7d64344643
--- /dev/null
+++ b/test/java/text/Collator/ThaiTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Thai Collation
+ */
+/*
+ * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+ *
+ * This software is the proprietary information of Oracle.
+ * Use is subject to license terms.
+ *
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+import java.text.RuleBasedCollator;
+
+public class ThaiTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new ThaiTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "\u0e01\u0e01",
+ "\u0e07\u0e42\u0e01\u0e49",
+ "\u0e10\u0e34\u0e19",
+ "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32",
+ "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22",
+ "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22",
+ "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30",
+ "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07",
+ "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c",
+ "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07",
+ "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25",
+ "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c",
+ "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21",
+ "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19",
+ "\u0e2a\u0e49\u0e28\u0e36\u0e01",
+ "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27",
+ "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19",
+ "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19",
+ "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19",
+ "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07",
+ "\u0e2a\u0e49\u0e44\u0e01\u0e48",
+ "\u0e2b",
+ "\u0e2b\u0e0b\u0e2d\u0e07",
+ "\u0e2b\u0e19",
+ "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32",
+ "\u0e2b\u0e21",
+ "\u0e2b\u0e21\u0e17\u0e2d\u0e07",
+ "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14",
+ "\u0e2b\u0e21\u0e49",
+ "\u0e2b\u0e23\u0e13\u0e22\u0e4c",
+ "\u0e2b\u0e25",
+ "\u0e2b\u0e25\u0e19\u0e49\u0e33",
+ "\u0e2b\u0e25\u0e48",
+ "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19",
+ "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b",
+ "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07",
+ "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a",
+ "\u0e2b\u0e49",
+ "\u0e2d",
+ "\u0e2d\u0e49",
+ "\u0e2e\u0e42\u0e25",
+ "\u0e2e\u0e44\u0e1f",
+ "\u0e2e\u0e49"
+ };
+
+ private static final String[] primaryTargetData = {
+ "\u0e01\u0e01",
+ "\u0e07\u0e42\u0e01\u0e49",
+ "\u0e10\u0e34\u0e19",
+ "\u0e16\u0e32\u0e21\u0e23\u0e23\u0e04\u0e40\u0e17\u0e28\u0e19\u0e32",
+ "\u0e23\u0e21\u0e18\u0e23\u0e23\u0e21\u0e4c\u0e1b\u0e23\u0e30\u0e01\u0e31\u0e19\u0e20\u0e31\u0e22",
+ "\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c\u0e40\u0e04\u0e23\u0e37\u0e48\u0e2d\u0e07\u0e2b\u0e21\u0e32\u0e22\u0e41\u0e25\u0e30\u0e22\u0e35\u0e48\u0e2b\u0e49\u0e2d\u0e01\u0e32\u0e23\u0e04\u0e49\u0e32\u0e02\u0e32\u0e22",
+ "\u0e23\u0e23\u0e25\u0e38\u0e19\u0e34\u0e15\u0e34\u0e20\u0e32\u0e27\u0e30",
+ "\u0e01\u0e25\u0e37\u0e2d\u0e41\u0e01\u0e07",
+ "\u0e21\u0e17\u0e34\u0e25\u0e41\u0e2d\u0e25\u0e01\u0e2d\u0e2e\u0e2d\u0e25\u0e4c",
+ "\u0e40\u0e2d\u0e35\u0e48\u0e22\u0e21\u0e2d\u0e48\u0e2d\u0e07",
+ "\u0e2a\u0e14\u0e32\u0e1b\u0e31\u0e15\u0e15\u0e34\u0e1c\u0e25",
+ "\u0e2d\u0e19\u0e01\u0e23\u0e23\u0e21\u0e2a\u0e34\u0e17\u0e18\u0e34\u0e4c",
+ "\u0e21\u0e49\u0e40\u0e17\u0e49\u0e32\u0e22\u0e32\u0e22\u0e21\u0e48\u0e2d\u0e21",
+ "\u0e2a\u0e49\u0e25\u0e30\u0e21\u0e32\u0e19",
+ "\u0e2a\u0e49\u0e28\u0e36\u0e01",
+ "\u0e2a\u0e49\u0e2d\u0e31\u0e48\u0e27",
+ "\u0e2a\u0e49\u0e40\u0e14\u0e37\u0e2d\u0e19",
+ "\u0e2a\u0e49\u0e40\u0e25\u0e37\u0e48\u0e2d\u0e19",
+ "\u0e2a\u0e49\u0e41\u0e02\u0e27\u0e19",
+ "\u0e2a\u0e49\u0e41\u0e2b\u0e49\u0e07",
+ "\u0e2a\u0e49\u0e44\u0e01\u0e48",
+ "\u0e2b",
+ "\u0e2b\u0e0b\u0e2d\u0e07",
+ "\u0e2b\u0e19",
+ "\u0e2b\u0e1b\u0e25\u0e32\u0e23\u0e49\u0e32",
+ "\u0e2b\u0e21",
+ "\u0e2b\u0e21\u0e17\u0e2d\u0e07",
+ "\u0e2b\u0e21\u0e2a\u0e31\u0e1a\u0e1b\u0e30\u0e23\u0e14",
+ "\u0e2b\u0e21\u0e49",
+ "\u0e2b\u0e23\u0e13\u0e22\u0e4c",
+ "\u0e2b\u0e25",
+ "\u0e2b\u0e25\u0e19\u0e49\u0e33",
+ "\u0e2b\u0e25\u0e48",
+ "\u0e2b\u0e25\u0e48\u0e16\u0e19\u0e19",
+ "\u0e2b\u0e25\u0e48\u0e17\u0e27\u0e35\u0e1b",
+ "\u0e2b\u0e25\u0e48\u0e17\u0e32\u0e07",
+ "\u0e2b\u0e25\u0e48\u0e23\u0e27\u0e1a",
+ "\u0e2b\u0e49",
+ "\u0e2d",
+ "\u0e2d\u0e49",
+ "\u0e2e\u0e42\u0e25",
+ "\u0e2e\u0e44\u0e1f",
+ "\u0e2e\u0e49"
+ };
+
+ private static final int[] primaryResults = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("th"));
+}
diff --git a/test/java/text/Collator/TurkishTest.java b/test/java/text/Collator/TurkishTest.java
new file mode 100644
index 0000000000..f83ef228e0
--- /dev/null
+++ b/test/java/text/Collator/TurkishTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Turkish Collation
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class TurkishTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new TurkishTest().run(args);
+ }
+
+ /*
+ * Data for TestPrimary()
+ */
+ private static final String[] primarySourceData = {
+ "\u00FCoid",
+ "vo\u0131d",
+ "idea",
+ "Idea",
+ "\u0130dea"
+ };
+
+ private static final String[] primaryTargetData = {
+ "void",
+ "void",
+ "Idea",
+ "\u0130dea",
+ "\u0131dea"
+ };
+
+ private static final int[] primaryResults = {
+ -1, -1, 1, -1, 1
+ };
+
+ /*
+ * Data for TestTertiary()
+ */
+ private static final String[] tertiarySourceData = {
+ "s\u0327",
+ "v\u00E4t",
+ "old",
+ "\u00FCoid",
+ "h\u011Ealt",
+ "stres\u015E",
+ "vo\u0131d",
+ "idea",
+ "idea",
+ "\u0131dea"
+ };
+
+ private static final String tertiaryTargetData[] = {
+ "u\u0308",
+ "vbt",
+ "\u00D6ay",
+ "void",
+ "halt",
+ "\u015Etre\u015Es",
+ "void",
+ "Idea",
+ "\u0130dea",
+ "Idea"
+ };
+
+ private static final int[] tertiaryResults = {
+ -1, -1, -1, -1, 1, -1, -1, 1, -1, -1
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY,
+ primarySourceData, primaryTargetData, primaryResults);
+ }
+
+ public void TestTertiary() {
+ doTest(myCollation, Collator.TERTIARY,
+ tertiarySourceData, tertiaryTargetData, tertiaryResults);
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("tr", "TR", ""));
+}
diff --git a/test/java/text/Collator/VietnameseTest.java b/test/java/text/Collator/VietnameseTest.java
new file mode 100644
index 0000000000..faa4921073
--- /dev/null
+++ b/test/java/text/Collator/VietnameseTest.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4932968 5015215
+ * @library /java/text/testlib
+ * @summary test Vietnamese Collation
+ */
+
+/*
+ *******************************************************************************
+ * (C) Copyright IBM Corp. 1996-2003 - All Rights Reserved *
+ * *
+ * The original version of this source code and documentation is copyrighted *
+ * and owned by IBM, These materials are provided under terms of a License *
+ * Agreement between IBM and Sun. This technology is protected by multiple *
+ * US and International patents. This notice and attribution to IBM may not *
+ * to removed. *
+ *******************************************************************************
+ */
+
+import java.util.Locale;
+import java.text.Collator;
+
+// Quick dummy program for printing out test results
+public class VietnameseTest extends CollatorTest {
+
+ public static void main(String[] args) throws Exception {
+ new VietnameseTest().run(args);
+ }
+
+ private final static String testPS[] = {
+ "a",
+ "a",
+ "\u00c2",
+ "Cz",
+ "d",
+ "e",
+ "e",
+ "\u1ec7",
+ "gz",
+ "i",
+ "kz",
+ "nz",
+ "nh",
+ "o",
+ "o",
+ "\u01a0",
+ "pz",
+ "tz",
+ "tr",
+ "u",
+ "u",
+ "y"
+ };
+
+ private final static String testPT[] = {
+ "\u00e0",
+ "\u0102",
+ "\u0102",
+ "Ch",
+ "\u0110",
+ "\u0111",
+ "\u1eb9",
+ "\u1eb9",
+ "gi",
+ "\u0128",
+ "kh",
+ "ng",
+ "ng",
+ "\u00f2",
+ "\u00f4",
+ "\u00f4",
+ "ph",
+ "th",
+ "th",
+ "\u1ee5",
+ "\u01b0",
+ "\u1ef4"
+ };
+
+ private final static int testPR[] = {
+ 0,
+ -1,
+ 1,
+ 1,
+ -1,
+ 1,
+ 0,
+ 1,
+ 1,
+ 0,
+ 1,
+ 1,
+ 1,
+ 0,
+ -1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ -1,
+ 0
+ };
+
+ private final static String testT[] = {
+ "a",
+ "A",
+ "\u00e0",
+ "\u00c0",
+ "\u1ea3",
+ "\u1ea2",
+ "\u00e3",
+ "\u00c3",
+ "\u00e1",
+ "\u00c1",
+ "\u1ea1",
+ "\u1ea0",
+ "\u0103",
+ "\u0102",
+ "\u1eb1",
+ "\u1eb0",
+ "\u1eb3",
+ "\u1eb2",
+ "\u1eb5",
+ "\u1eb4",
+ "\u1eaf",
+ "\u1eae",
+ "\u1eb7",
+ "\u1eb6",
+ "\u00e2",
+ "\u00c2",
+ "\u1ea7",
+ "\u1ea6",
+ "\u1ea9",
+ "\u1ea8",
+ "\u1eab",
+ "\u1eaa",
+ "\u1ea5",
+ "\u1ea4",
+ "\u1ead",
+ "\u1eac",
+ "b",
+ "B",
+ "c",
+ "C",
+ "ch",
+ "Ch",
+ "CH",
+ "d",
+ "D",
+ "\u0111",
+ "\u0110",
+ "e",
+ "E",
+ "\u00e8",
+ "\u00c8",
+ "\u1ebb",
+ "\u1eba",
+ "\u1ebd",
+ "\u1ebc",
+ "\u00e9",
+ "\u00c9",
+ "\u1eb9",
+ "\u1eb8",
+ "\u00ea",
+ "\u00ca",
+ "\u1ec1",
+ "\u1ec0",
+ "\u1ec3",
+ "\u1ec2",
+ "\u1ec5",
+ "\u1ec4",
+ "\u1ebf",
+ "\u1ebe",
+ "\u1ec7",
+ "\u1ec6",
+ "f",
+ "F",
+ "g",
+ "G",
+ "gi",
+ "Gi",
+ "GI",
+ "gz",
+ "h",
+ "H",
+ "i",
+ "I",
+ "\u00ec",
+ "\u00cc",
+ "\u1ec9",
+ "\u1ec8",
+ "\u0129",
+ "\u0128",
+ "\u00ed",
+ "\u00cd",
+ "\u1ecb",
+ "\u1eca",
+ "j",
+ "J",
+ "k",
+ "K",
+ "kh",
+ "Kh",
+ "KH",
+ "kz",
+ "l",
+ "L",
+ "m",
+ "M",
+ "n",
+ "N",
+ "ng",
+ "Ng",
+ "NG",
+ "ngz",
+ "nh",
+ "Nh",
+ "NH",
+ "nz",
+ "o",
+ "O",
+ "\u00f2",
+ "\u00d2",
+ "\u1ecf",
+ "\u1ece",
+ "\u00f5",
+ "\u00d5",
+ "\u00f3",
+ "\u00d3",
+ "\u1ecd",
+ "\u1ecc",
+ "\u00f4",
+ "\u00d4",
+ "\u1ed3",
+ "\u1ed2",
+ "\u1ed5",
+ "\u1ed4",
+ "\u1ed7",
+ "\u1ed6",
+ "\u1ed1",
+ "\u1ed0",
+ "\u1ed9",
+ "\u1ed8",
+ "\u01a1",
+ "\u01a0",
+ "\u1edd",
+ "\u1edc",
+ "\u1edf",
+ "\u1ede",
+ "\u1ee1",
+ "\u1ee0",
+ "\u1edb",
+ "\u1eda",
+ "\u1ee3",
+ "\u1ee2",
+ "p",
+ "P",
+ "ph",
+ "Ph",
+ "PH",
+ "pz",
+ "q",
+ "Q",
+ "r",
+ "R",
+ "s",
+ "S",
+ "t",
+ "T",
+ "th",
+ "Th",
+ "TH",
+ "thz",
+ "tr",
+ "Tr",
+ "TR",
+ "tz",
+ "u",
+ "U",
+ "\u00f9",
+ "\u00d9",
+ "\u1ee7",
+ "\u1ee6",
+ "\u0169",
+ "\u0168",
+ "\u00fa",
+ "\u00da",
+ "\u1ee5",
+ "\u1ee4",
+ "\u01b0",
+ "\u01af",
+ "\u1eeb",
+ "\u1eea",
+ "\u1eed",
+ "\u1eec",
+ "\u1eef",
+ "\u1eee",
+ "\u1ee9",
+ "\u1ee8",
+ "\u1ef1",
+ "\u1ef0",
+ "v",
+ "V",
+ "w",
+ "W",
+ "x",
+ "X",
+ "y",
+ "Y",
+ "\u1ef3",
+ "\u1ef2",
+ "\u1ef7",
+ "\u1ef6",
+ "\u1ef9",
+ "\u1ef8",
+ "\u00fd",
+ "\u00dd",
+ "\u1ef5",
+ "\u1ef4",
+ "z",
+ "Z"
+ };
+
+ public void TestPrimary() {
+ doTest(myCollation, Collator.PRIMARY, testPS, testPT, testPR);
+ }
+
+ public void TestTertiary() {
+ int testLength = testT.length;
+
+ myCollation.setStrength(Collator.TERTIARY);
+ for (int i = 0; i < testLength - 1; i++) {
+ for (int j = i+1; j < testLength; j++) {
+ doTest(myCollation, testT[i], testT[j], -1);
+ }
+ }
+ }
+
+ private final Collator myCollation = Collator.getInstance(new Locale("vi", "VN"));
+}
diff --git a/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt b/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt
new file mode 100644
index 0000000000..23c4e4607f
--- /dev/null
+++ b/test/java/text/Format/ChoiceFormat/Bug4185732.ser.txt
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a serialized ChiceFormat for Bug4185732Test.
+
+aced0005737200166a6176612e746578742e43686f696365466f726d617418e9
+c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61
+76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400
+025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3
+bf137d07e803000b5a000c67726f7570696e67557365644200116d6178467261
+6374696f6e4469676974734200106d6178496e74656765724469676974734900
+156d6178696d756d4672616374696f6e4469676974734900146d6178696d756d
+496e74656765724469676974734200116d696e4672616374696f6e4469676974
+734200106d696e496e74656765724469676974734900156d696e696d756d4672
+616374696f6e4469676974734900146d696e696d756d496e7465676572446967
+6974735a00107061727365496e74656765724f6e6c7949001573657269616c56
+657273696f6e4f6e53747265616d787200106a6176612e746578742e466f726d
+6174fbd8bc12e90f184302000078700103280000000300000028000100000000
+00000001000000000178757200135b4c6a6176612e6c616e672e537472696e67
+3badd256e7e91d7b470200007870000000067400034d6f6e7400035475657400
+0357656474000454687572740003467269740003536174757200025b443ea68c
+14ab635a1e0200007870000000073ff000000000000040000000000000004008
+000000000000401000000000000040140000000000004018000000000000401c
+000000000000
diff --git a/test/java/text/Format/ChoiceFormat/Bug4185732Test.java b/test/java/text/Format/ChoiceFormat/Bug4185732Test.java
new file mode 100644
index 0000000000..06c5dea1f5
--- /dev/null
+++ b/test/java/text/Format/ChoiceFormat/Bug4185732Test.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1999, 2016, 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 4185732
+ * @library /java/text/testlib
+ * @build Bug4185732Test IntlTest HexDumpReader
+ * @run main Bug4185732Test
+ * @summary test that ChoiceFormat invariants are preserved across serialization
+ */
+/*
+ *
+ *
+ * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.ChoiceFormat;
+
+/**
+ * A Locale can never contains language codes of he, yi or id.
+ */
+public class Bug4185732Test extends IntlTest {
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1 && args[0].equals("prepTest")) {
+ prepTest();
+ } else {
+ new Bug4185732Test().run(args);
+ }
+ }
+
+ public void testIt() throws Exception {
+ try {
+ final ObjectInputStream in
+ = new ObjectInputStream(HexDumpReader.getStreamFromHexDump("Bug4185732.ser.txt"));
+ final ChoiceFormat loc = (ChoiceFormat)in.readObject();
+ if (loc.getFormats().length != loc.getLimits().length) {
+ errln("ChoiceFormat did not properly check stream");
+ } else {
+ //for some reason, the data file was VALID. This test
+ //requires a corrupt data file the format and limit
+ //arrays are of different length.
+ errln("Test data file was not properly created");
+ }
+ } catch (InvalidObjectException e) {
+ //this is what we want to have happen
+ } catch (Exception e) {
+ errln(e.toString());
+ }
+ }
+
+ /**
+ * Create a data file for this test. The data file must be corrupted by hand.
+ */
+ private static void prepTest() {
+ try {
+ ObjectOutputStream out = new ObjectOutputStream(
+ new FileOutputStream("Bug4185732.ser"));
+ final double[] limits = {1,2,3,4,5,6,7};
+ final String[] formats = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
+ final ChoiceFormat fmt = new ChoiceFormat(limits, formats);
+ out.writeObject(fmt);
+ out.close();
+ System.out.println("You must invalidate the output file before running the test");
+ System.out.println("by modifying the length of one of the array");
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+}
diff --git a/test/java/text/Format/ChoiceFormat/Bug4387255.java b/test/java/text/Format/ChoiceFormat/Bug4387255.java
new file mode 100644
index 0000000000..d211bb6976
--- /dev/null
+++ b/test/java/text/Format/ChoiceFormat/Bug4387255.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4387255
+ * @summary Verifies that ChoiceFormat can handle large numbers of choices
+ */
+
+import java.text.ChoiceFormat;
+
+public class Bug4387255 {
+
+ private static final double[] doubles = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35};
+
+ private static final String[] strings = {
+ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
+ "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
+ "U", "V", "W", "X", "Y", "Z"};
+
+ private static final String pattern =
+ "0#0|1#1|2#2|3#3|4#4|5#5|6#6|7#7|8#8|9#9" +
+ "|10#A|11#B|12#C|13#D|14#E|15#F|16#G|17#H|18#I|19#J" +
+ "|20#K|21#L|22#M|23#N|24#O|25#P|26#Q|27#R|28#S|29#T" +
+ "|30#U|31#V|32#W|33#X|34#Y|35#Z";
+
+ public static void main(String[] args) throws Exception {
+ ChoiceFormat choiceFormat1 = new ChoiceFormat(doubles, strings);
+ ChoiceFormat choiceFormat2 = new ChoiceFormat(pattern);
+ if (!choiceFormat1.equals(choiceFormat2)) {
+ System.out.println("choiceFormat1: " + choiceFormat1.toPattern());
+ System.out.println("choiceFormat2: " + choiceFormat2.toPattern());
+ throw new RuntimeException();
+ }
+
+ for (int i = 0; i < doubles.length; i++) {
+ String result = choiceFormat2.format(doubles[i]);
+ if (!result.equals(strings[i])) {
+ throw new RuntimeException("Wrong format result - expected " +
+ strings[i] + ", got " + result);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug4322313.java b/test/java/text/Format/DateFormat/Bug4322313.java
new file mode 100644
index 0000000000..1998702266
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug4322313.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4322313 4833268 6302990 6304305
+ * @library /java/text/testlib
+ * @summary Make sure that new implementation for
+ * SimpleDateFormat.parse('z' or 'Z') and format('z' or 'Z') work correctly.
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4322313 extends IntlTest {
+
+ public void Test4322313() {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ boolean err = false;
+ long mpm = 60 * 1000; /* Milliseconds per a minute */
+
+ Locale[] locs = {Locale.US, Locale.JAPAN, Locale.UK, new Locale("ar")};
+
+ String[] formats = {
+ "z",
+ "Z",
+ };
+
+ Object[][] valids = {
+ /* given ID offset format('z'), ('Z') index */
+ {"GMT+03:04", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(9)},
+ {"GMT+13:42", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(9)},
+ {"GMT+00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)},
+ {"GMT+1:11", new Long(-71 * mpm), "GMT+01:11", "+0111", new Integer(8)},
+ {"GMT +13:42", new Long(0), "GMT", "+0000", new Integer(3)},
+ {" GMT", new Long(0), "GMT", "+0000", new Integer(4)},
+ {"+0304", new Long(-184 * mpm), "GMT+03:04", "+0304", new Integer(5)},
+ {"+1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(5)},
+ {"+0000", new Long(0), "GMT+00:00", "+0000", new Integer(5)},
+ {" +1342", new Long(-822 * mpm), "GMT+13:42", "+1342", new Integer(6)},
+ /* ISO-LATIN-1 digits */
+ {"GMT+\u0030\u0031:\u0032\u0033", new Long(-83 * mpm), "GMT+01:23", "+0123", new Integer(9)},
+
+ /* In fact, this test case is skipped because TimeZone class can't
+ * recognize TimeZone IDs like "+00234" or "-00234".
+ */
+ {"+00234", new Long(-23 * mpm), "GMT+00:23", "+0023", new Integer(5)},
+
+ {"GMT-03:04", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(9)},
+ {"GMT-13:42", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(9)},
+ {"GMT-00:00", new Long(0), "GMT+00:00", "+0000", new Integer(9)},
+ {"GMT-1:11", new Long(71 * mpm), "GMT-01:11", "-0111", new Integer(8)},
+ {"GMT -13:42", new Long(0), "GMT", "+0000", new Integer(3)},
+ {"-0304", new Long(184 * mpm), "GMT-03:04", "-0304", new Integer(5)},
+ {"-1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(5)},
+ {" -1342", new Long(822 * mpm), "GMT-13:42", "-1342", new Integer(6)},
+ /* ISO-LATIN-1 digits */
+ {"GMT-\u0030\u0031:\u0032\u0033", new Long(83 * mpm), "GMT-01:23", "-0123", new Integer(9)},
+ /* In fact, this test case is skipped because TimeZone class can't
+ * recognize TimeZone IDs like "+00234" or "-00234".
+ */
+ {"-00234", new Long(23 * mpm), "GMT+00:23", "-0023", new Integer(5)},
+ };
+
+ Object[][] invalids = {
+ /* given ID error index */
+ {"GMT+8", new Integer(5)},
+ {"GMT+18", new Integer(6)},
+ {"GMT+208", new Integer(6)},
+ {"GMT+0304", new Integer(6)},
+ {"GMT+42195", new Integer(5)},
+ {"GMT+5:8", new Integer(7)},
+ {"GMT+23:60", new Integer(8)},
+ {"GMT+11:1", new Integer(8)},
+ {"GMT+24:13", new Integer(5)},
+ {"GMT+421:950", new Integer(5)},
+ {"GMT+0a:0A", new Integer(5)},
+ {"GMT+ 13:42", new Integer(4)},
+ {"GMT+13 :42", new Integer(6)},
+ {"GMT+13: 42", new Integer(7)},
+ {"GMT+-13:42", new Integer(4)},
+ {"G M T", new Integer(0)},
+ {"+8", new Integer(2)},
+ {"+18", new Integer(3)},
+ {"+208", new Integer(4)},
+ {"+2360", new Integer(4)},
+ {"+2413", new Integer(2)},
+ {"+42195", new Integer(2)},
+ {"+0AbC", new Integer(2)},
+ {"+ 1342", new Integer(1)},
+ {"+-1342", new Integer(1)},
+ {"1342", new Integer(0)},
+ /* Arabic-Indic digits */
+ {"GMT+\u0660\u0661:\u0662\u0663", new Integer(4)},
+ /* Extended Arabic-Indic digits */
+ {"GMT+\u06f0\u06f1:\u06f2\u06f3", new Integer(4)},
+ /* Devanagari digits */
+ {"GMT+\u0966\u0967:\u0968\u0969", new Integer(4)},
+ /* Fullwidth digits */
+ {"GMT+\uFF10\uFF11:\uFF12\uFF13", new Integer(4)},
+
+ {"GMT-8", new Integer(5)},
+ {"GMT-18", new Integer(6)},
+ {"GMT-208", new Integer(6)},
+ {"GMT-0304", new Integer(6)},
+ {"GMT-42195", new Integer(5)},
+ {"GMT-5:8", new Integer(7)},
+ {"GMT-23:60", new Integer(8)},
+ {"GMT-11:1", new Integer(8)},
+ {"GMT-24:13", new Integer(5)},
+ {"GMT-421:950", new Integer(5)},
+ {"GMT-0a:0A", new Integer(5)},
+ {"GMT- 13:42", new Integer(4)},
+ {"GMT-13 :42", new Integer(6)},
+ {"GMT-13: 42", new Integer(7)},
+ {"GMT-+13:42", new Integer(4)},
+ {"-8", new Integer(2)},
+ {"-18", new Integer(3)},
+ {"-208", new Integer(4)},
+ {"-2360", new Integer(4)},
+ {"-2413", new Integer(2)},
+ {"-42195", new Integer(2)},
+ {"-0AbC", new Integer(2)},
+ {"- 1342", new Integer(1)},
+ {"--1342", new Integer(1)},
+ {"-802", new Integer(2)},
+ /* Arabic-Indic digits */
+ {"GMT-\u0660\u0661:\u0662\u0663", new Integer(4)},
+ /* Extended Arabic-Indic digits */
+ {"GMT-\u06f0\u06f1:\u06f2\u06f3", new Integer(4)},
+ /* Devanagari digits */
+ {"GMT-\u0966\u0967:\u0968\u0969", new Integer(4)},
+ /* Fullwidth digits */
+ {"GMT-\uFF10\uFF11:\uFF12\uFF13", new Integer(4)},
+ };
+
+ try {
+ for (int i=0; i < locs.length; i++) {
+ Locale.setDefault(locs[i]);
+
+ for (int j=0; j < formats.length; j++) {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ SimpleDateFormat sdf = new SimpleDateFormat(formats[j]);
+ Date date;
+
+ /* Okay case */
+ for (int k=0; k < valids.length; k++) {
+ ParsePosition pos = new ParsePosition(0);
+ try {
+ date = sdf.parse((String)valids[k][0], pos);
+ }
+ catch (Exception e) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + valids[k][0] +
+ "\"] Unexpected Exception occurred: " + e);
+ continue;
+ }
+
+ int offset = pos.getIndex();
+ if (offset != ((Integer)valids[k][4]).intValue()) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + valids[k][0] +
+ "\"] invalid index: expected:" + valids[k][4] +
+ ", got:" + offset);
+ }
+
+ if (date.getTime() != ((Long)valids[k][1]).longValue()) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + valids[k][0] +
+ "\"] expected:" + valids[k][1] +
+ ", got:" + date.getTime() + ", " + date);
+ } else {
+/*
+ logln("\tParse Okay [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + valids[k][0] +
+ "\"] expected:" + valids[k][1] +
+ ", got:" + date.getTime() + ", " + date);
+*/
+
+ try {
+ date = sdf.parse((String)valids[k][0]);
+ }
+ catch (Exception e) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + valids[k][0] +
+ "\"] Unexpected Exception occurred: " + e);
+ continue;
+ }
+
+ /* Since TimeZone.getTimeZone() don't treat
+ * "+00234" or "-00234" as a valid ID, skips.
+ */
+ if (((String)valids[k][0]).length() == 6) {
+ continue;
+ }
+
+ /* Since TimeZone.getTimeZone() don't recognize
+ * +hhmm/-hhmm format, add "GMT" as prefix.
+ */
+ sdf.setTimeZone(TimeZone.getTimeZone(
+ (((((String)valids[k][0]).charAt(0) != 'G') ?
+ "GMT" : "") + valids[k][0])));
+ StringBuffer s = new StringBuffer();
+ sdf.format(date, s, new FieldPosition(0));
+ sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+ String got = s.toString();
+ String expected = (String)valids[k][2+j];
+ if (!got.equals(expected) &&
+ // special case to allow the difference between
+ // DateFormatSymbols.getZoneStrings() and
+ // TimeZone.getDisplayName() for "GMT+-00:00"
+ !(got.equals("GMT-00:00") &&
+ expected.equals("GMT+00:00"))) {
+ err = true;
+ System.err.println("\tFormat Error [Locale=" +
+ Locale.getDefault() + ", " +
+ formats[j] + "/\"" + valids[k][0] +
+ "\"] expected:" + valids[k][2+j] +
+ ", got:" + s + ", " + date);
+ } else {
+/*
+ logln("\tFormat Okay [Locale=" +
+ Locale.getDefault() + ", " +
+ formats[j] + "/\"" + valids[k][0] +
+ "\"] expected:" + valids[k][2+j] +
+ ", got:" + s + ", " + date);
+*/
+ }
+ }
+ }
+
+ /* Error case 1
+ * using SimpleDateFormat.parse(String, ParsePosition)
+ */
+ for (int k=0; k < invalids.length; k++) {
+ ParsePosition pos = new ParsePosition(0);
+ try {
+ date = sdf.parse((String)invalids[k][0], pos);
+ if (date != null) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] expected:null , got:" + date);
+ }
+ int offset = pos.getErrorIndex();
+ if (offset != ((Integer)invalids[k][1]).intValue()) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] incorrect offset. expected:" +
+ invalids[k][1] + ", got: " + offset);
+ } else {
+/*
+ logln("\tParse Okay [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] correct offset: " + offset);
+*/
+ }
+ }
+ catch (Exception e) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] Unexpected Exception occurred: " + e);
+ }
+ }
+
+ /* Error case 2
+ * using DateFormat.parse(String)
+ */
+ boolean correctParseException = false;
+ for (int k=0; k < invalids.length; k++) {
+ try {
+ date = sdf.parse((String)invalids[k][0]);
+ }
+ catch (ParseException e) {
+ correctParseException = true;
+ int offset = e.getErrorOffset();
+ if (offset != ((Integer)invalids[k][1]).intValue()) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] Expected exception occurred with an incorrect offset. expected:" +
+ invalids[k][1] + ", got: " + offset);
+ } else {
+/*
+ logln("\tParse Okay [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] Expected exception occurred with an correct offset: "
+ + offset);
+*/
+ }
+ }
+ catch (Exception e) {
+ err = true;
+ System.err.println("\tParse Error [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] Invalid exception occurred: " + e);
+ }
+ finally {
+ if (!correctParseException) {
+ err = true;
+ System.err.println("\tParse Error: [Locale=" +
+ Locale.getDefault() + ", " + formats[j] +
+ "/\"" + invalids[k][0] +
+ "\"] Expected exception didn't occur.");
+ }
+ }
+ }
+ }
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ if (err) {
+ errln("SimpleDateFormat.parse()/format() test failed");
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ new Bug4322313().run(args);
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug4407042.java b/test/java/text/Format/DateFormat/Bug4407042.java
new file mode 100644
index 0000000000..8cc557e5a9
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug4407042.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4407042
+ * @summary Make sure that cloned SimpleDateFormat objects work
+ * independently in multiple threads.
+ * @run main Bug4407042 10
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+// Usage: java Bug4407042 [duration]
+public class Bug4407042 {
+
+ static final String TIME_STRING = "2000/11/18 00:01:00";
+ static final long UTC_LONG = 974534460000L;
+ static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+ static boolean runrun = true;
+ static int duration = 100;
+
+ void test() {
+ Locale locale = Locale.getDefault();
+ if (locale.equals(new Locale("th", "TH")) ||
+ locale.equals(new Locale("hi", "IN"))) {
+ return;
+ }
+
+ masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+ DateParseThread d1 = new DateParseThread();
+ DateFormatThread d2 = new DateFormatThread();
+ d1.start();
+ d2.start();
+ int n = Thread.activeCount();
+ boolean failed = false;
+
+ for (int i = 0; i < duration; i++) {
+ try {
+ Thread.sleep(1000);
+ if (Thread.activeCount() != n) {
+ failed = true;
+ break;
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+ runrun = false;
+ try {
+ d1.join();
+ d2.join();
+ } catch (InterruptedException e) {
+ }
+ if (failed) {
+ throw new RuntimeException("Failed");
+ }
+ }
+
+ synchronized static SimpleDateFormat getFormatter() {
+ return (SimpleDateFormat) masterFormat.clone();
+ }
+
+ static class DateParseThread extends Thread {
+ public void run() {
+ SimpleDateFormat sdf = getFormatter();
+ Calendar cal = null;
+
+ try {
+ int i = 0;
+ while (runrun) {
+ Date date =sdf.parse(TIME_STRING);
+ long t = date.getTime();
+ i++;
+ if (t != UTC_LONG) {
+ throw new RuntimeException("Parse Error: " + i +
+ " (" + sdf.format(date) + ") " + t +
+ " != " + UTC_LONG);
+ }
+ }
+ } catch (ParseException e) {
+ e.printStackTrace();
+ throw new RuntimeException("Parse Error");
+ }
+ }
+ }
+
+ static class DateFormatThread extends Thread {
+ public void run () {
+ SimpleDateFormat sdf = getFormatter();
+ Calendar cal = null;
+
+ int i = 0;
+ while (runrun) {
+ i++;
+ String s = sdf.format(new Date(UTC_LONG));
+ if (!s.equals(TIME_STRING)) {
+ throw new RuntimeException("Format Error: " + i + " " +
+ s + " != " + TIME_STRING);
+ }
+ }
+ }
+ }
+
+ public static void main (String[] args) {
+ if (args.length == 1) {
+ duration = Math.max(10, Integer.parseInt(args[0]));
+ }
+ new Bug4407042().test();
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug4736959.java b/test/java/text/Format/DateFormat/Bug4736959.java
new file mode 100644
index 0000000000..cdb9cad20b
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug4736959.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4736959
+ * @summary Make sure to parse "PM" (only) and produce the correct value.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug4736959 {
+ /**
+ * 4736959: JSpinner won't work for AM/PM field
+ */
+ public static void main(String[] args) {
+ SimpleDateFormat f = new SimpleDateFormat("a", Locale.US);
+
+ Date d1 = f.parse("AM", new ParsePosition(0));
+ System.out.println("d1: " + d1);
+ if (d1.getHours() != 0) {
+ throw new RuntimeException("Parsing \"AM\": expected 0 (midnight), got " +
+ d1.getHours());
+ }
+ Date d2 = f.parse("PM", new ParsePosition(0));
+ System.out.println("d2: " + d2);
+ if (d2.getHours() != 12) {
+ throw new RuntimeException("Parsing \"PM\": expected 12 (noon), got " +
+ d2.getHours());
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug4845901.java b/test/java/text/Format/DateFormat/Bug4845901.java
new file mode 100644
index 0000000000..8ed8bd4764
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug4845901.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2004, 2016, 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 4845901
+ * @summary Make sure that SimpleDateFormat.parse() can distinguish
+ * the same time zone abbreviation for standard and daylight saving
+ * time.
+ */
+
+import java.util.*;
+import java.text.SimpleDateFormat;
+
+public class Bug4845901 {
+ public static void main (String args[]) {
+ TimeZone savedTZ = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney"));
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss.SSS z");
+ try {
+ testParse(sdf, "2003.01.13 11:10:00.802 AEDT", 11);
+ testParse(sdf, "2003.06.12 11:10:00.802 AEST", 11);
+ testParse(sdf, "2004.12.24 10:10:00.002 AEDT", 10);
+ testParse(sdf, "2004.08.10 10:10:00.002 AEST", 10);
+ } finally {
+ TimeZone.setDefault(savedTZ);
+ }
+ }
+
+ static void testParse(SimpleDateFormat sdf, String str, int expectedHour) {
+ try {
+ Date parsedDate = sdf.parse(str);
+ if (parsedDate.getHours() != expectedHour) {
+ throw new RuntimeException(
+ "parsed date has wrong hour: " + parsedDate.getHours()
+ + ", expected: " + expectedHour
+ + "\ngiven string: " + str
+ + "\nparsedDate = " + parsedDate);
+ }
+ } catch (java.text.ParseException e) {
+ throw new RuntimeException("parse exception", e);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug6251817.java b/test/java/text/Format/DateFormat/Bug6251817.java
new file mode 100644
index 0000000000..b0dd7fc9c2
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug6251817.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6251817
+ * @summary Confirm that a typo was corrected.
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class Bug6251817 {
+
+ public static void main(String[] args) {
+ SimpleDateFormat sdf = new SimpleDateFormat("zzzz", Locale.US);
+ sdf.setTimeZone(TimeZone.getTimeZone("Australia/Lord_Howe"));
+ String got = sdf.format(new Date());
+
+ if (!got.equals("Lord Howe Standard Time") &&
+ !got.equals("Lord Howe Daylight Time")) {
+ throw new RuntimeException("Timezone display name for Australia/Lord_Howe is incorrect. Got:" + got);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug6335238.java b/test/java/text/Format/DateFormat/Bug6335238.java
new file mode 100644
index 0000000000..201a1af8f9
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug6335238.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2006, 2016, 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 1.1 06/01/24
+ * @bug 6335238
+ * @summary Make sure that both the original and cloned SimpleDateFormat coexistindependently and don't cut off each other.
+ * @run main Bug6335238 10
+ */
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+// Usage: java Bug6335238 [duration]
+public class Bug6335238 {
+
+ static final long UTC_LONG = 974534460000L;
+ static final String TIME_STRING = "2000/11/18 00:01:00";
+ static SimpleDateFormat masterSdf;
+ static int duration = 180;
+ static boolean stopped = false;
+ static boolean err = false;
+
+ public static void main(String[] args) {
+ if (args.length == 1) {
+ duration = Math.max(10, Integer.parseInt(args[0]));
+ }
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific"));
+ Locale.setDefault(Locale.US);
+
+ masterSdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+
+ try {
+ // Once it is used, DecimalFormat becomes not thread-safe.
+ Date d = masterSdf.parse(TIME_STRING);
+
+ new Bug6335238();
+ } catch (Exception e) {
+ System.err.println(e);
+ err = true;
+ } finally {
+ TimeZone.setDefault(savedTimeZone);
+ Locale.setDefault(savedLocale);
+
+ if (err) {
+ throw new RuntimeException("Failed: Multiple DateFormat instances didn't work correctly.");
+ } else {
+ System.out.println("Passed.");
+ }
+ }
+ }
+
+ public Bug6335238() {
+ stopped = false;
+
+ DateParseThread d1 = new DateParseThread();
+ DateFormatThread d2 = new DateFormatThread();
+ DateParseThread d3 = new DateParseThread();
+ DateFormatThread d4 = new DateFormatThread();
+
+ d1.start();
+ d2.start();
+ d3.start();
+ d4.start();
+
+ try {
+ Thread.sleep(duration * 1000);
+ }
+ catch (Exception e) {
+ System.err.println(e);
+ err = true;
+ }
+
+ stopped = true;
+ }
+
+ class DateFormatThread extends Thread {
+
+ public void run() {
+ int i = 0;
+
+ while (!stopped) {
+ SimpleDateFormat sdf;
+ synchronized (masterSdf) {
+ sdf = (SimpleDateFormat)masterSdf.clone();
+ }
+
+ i++;
+ String s = sdf.format(new Date(UTC_LONG));
+
+ if (!s.equals(TIME_STRING)) {
+ stopped = true;
+ err = true;
+
+ throw new RuntimeException("Formatting Date Error: counter=" +
+ i + ", Got<" + s + "> != Expected<" + TIME_STRING + ">");
+ }
+ }
+ }
+ }
+
+ class DateParseThread extends Thread {
+
+ public void run() {
+ int i = 0;
+
+ while (!stopped) {
+ SimpleDateFormat sdf;
+ synchronized (masterSdf) {
+ sdf = (SimpleDateFormat)masterSdf.clone();
+ }
+
+ i++;
+ Date date;
+ try {
+ date = sdf.parse(TIME_STRING);
+ long t = date.getTime();
+
+ if (t != UTC_LONG) {
+ stopped = true;
+ err = true;
+
+ throw new RuntimeException("Parsing Date Error: counter=" +
+ i + " Got:" + t + "<" + sdf.format(date) +
+ "> != " + UTC_LONG);
+ }
+ }
+ catch (ParseException e) {
+ stopped = true;
+ err = true;
+
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/Bug6530336.java b/test/java/text/Format/DateFormat/Bug6530336.java
new file mode 100644
index 0000000000..d01a96aba9
--- /dev/null
+++ b/test/java/text/Format/DateFormat/Bug6530336.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007, 2016, 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 6530336 6537997 8008577
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug6530336
+ */
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class Bug6530336 {
+
+ public static void main(String[] args) throws Exception {
+ Locale defaultLocale = Locale.getDefault();
+ TimeZone defaultTimeZone = TimeZone.getDefault();
+
+ boolean err = false;
+
+ try {
+ Locale locales[] = Locale.getAvailableLocales();
+ Locale locale_Japan = new Locale("ja", "JP", "JP");
+ TimeZone timezone_LA = TimeZone.getTimeZone("America/Los_Angeles");
+ TimeZone.setDefault(timezone_LA);
+
+ TimeZone timezones[] = {
+ TimeZone.getTimeZone("America/New_York"),
+ TimeZone.getTimeZone("America/Denver"),
+ };
+
+ String[] expected = {
+ "Sun Jul 15 12:00:00 PDT 2007",
+ "Sun Jul 15 14:00:00 PDT 2007",
+ };
+
+ Date[] dates = new Date[2];
+
+ for (int i = 0; i < locales.length; i++) {
+ if (locales[i].getLanguage().equals("th") ||
+ locales[i].equals(locale_Japan)) {
+ continue;
+ }
+
+ Locale.setDefault(locales[i]);
+
+ for (int j = 0; j < timezones.length; j++) {
+ Calendar cal = Calendar.getInstance(timezones[j]);
+ cal.set(2007, 6, 15, 15, 0, 0);
+ dates[j] = cal.getTime();
+ }
+
+ SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
+
+ for (int j = 0; j < timezones.length; j++) {
+ sdf.setTimeZone(timezones[j]);
+ String date = sdf.format(dates[j]);
+ sdf.setTimeZone(timezone_LA);
+ String date_LA = sdf.parse(date).toString();
+
+ if (!expected[j].equals(date_LA)) {
+ System.err.println("Got wrong Pacific time (" +
+ date_LA + ") for (" + date + ") in " + locales[i] +
+ " in " + timezones[j] +
+ ".\nExpected=" + expected[j]);
+ err = true;
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ err = true;
+ }
+ finally {
+ Locale.setDefault(defaultLocale);
+ TimeZone.setDefault(defaultTimeZone);
+
+ if (err) {
+ throw new RuntimeException("Failed.");
+ }
+ }
+ }
+
+}
diff --git a/test/java/text/Format/DateFormat/DateFormatRegression.java b/test/java/text/Format/DateFormat/DateFormatRegression.java
new file mode 100644
index 0000000000..d276aac088
--- /dev/null
+++ b/test/java/text/Format/DateFormat/DateFormatRegression.java
@@ -0,0 +1,1098 @@
+/*
+ * Copyright (c) 1998, 2016, 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.text.*;
+import java.util.*;
+import java.io.*;
+
+/**
+ * @test
+ * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003
+ * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407
+ * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209
+ * 4213086 4250359 4253490 4266432 4406615 4413980 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression
+ */
+public class DateFormatRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new DateFormatRegression().run(args);
+ }
+
+ public void Test4029195() {
+
+ Date today = new Date();
+
+ logln("today: " + today);
+
+ SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance();
+ logln("pattern: " + sdf.toPattern());
+ logln("today: " + sdf.format(today));
+
+ sdf.applyPattern("G yyyy DDD");
+ String todayS = sdf.format(today);
+ logln("today: " + todayS);
+ try {
+ today = sdf.parse(todayS);
+ logln("today date: " + today);
+ } catch(Exception e) {
+ logln("Error reparsing date: " + e.getMessage());
+ }
+
+ try {
+ String rt = sdf.format(sdf.parse(todayS));
+ logln("round trip: " + rt);
+ if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt);
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public void Test4052408() {
+
+ DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+ DateFormat.SHORT, Locale.US);
+ Date date = new Date(97, Calendar.MAY, 3, 8, 55);
+ String str;
+ logln(str = fmt.format(date));
+
+ if (!str.equals("5/3/97 8:55 AM"))
+ errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str);
+ Hashtable expected = new Hashtable();
+ expected.put(new Integer(DateFormat.MONTH_FIELD), "5");
+ expected.put(new Integer(DateFormat.DATE_FIELD), "3");
+ expected.put(new Integer(DateFormat.YEAR_FIELD), "97");
+ expected.put(new Integer(DateFormat.HOUR1_FIELD), "8");
+ expected.put(new Integer(DateFormat.MINUTE_FIELD), "55");
+ expected.put(new Integer(DateFormat.AM_PM_FIELD), "AM");
+
+ StringBuffer buf = new StringBuffer();
+ String fieldNames[] = {
+ "ERA_FIELD",
+ "YEAR_FIELD",
+ "MONTH_FIELD",
+ "DATE_FIELD",
+ "HOUR_OF_DAY1_FIELD",
+ "HOUR_OF_DAY0_FIELD",
+ "MINUTE_FIELD",
+ "SECOND_FIELD",
+ "MILLISECOND_FIELD",
+ "DAY_OF_WEEK_FIELD",
+ "DAY_OF_YEAR_FIELD",
+ "DAY_OF_WEEK_IN_MONTH_FIELD",
+ "WEEK_OF_YEAR_FIELD",
+ "WEEK_OF_MONTH_FIELD",
+ "AM_PM_FIELD",
+ "HOUR1_FIELD",
+ "HOUR0_FIELD",
+ "TIMEZONE_FIELD",
+ };
+ boolean pass = true;
+ for (int i=0; i<=17; ++i) {
+ FieldPosition pos = new FieldPosition(i);
+ fmt.format(date, buf, pos);
+ char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()];
+ buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0);
+ str = new String(dst);
+ log(i + ": " + fieldNames[i] +
+ ", \"" + str + "\", " +
+ pos.getBeginIndex() + ", " +
+ pos.getEndIndex());
+ String exp = (String) expected.get(new Integer(i));
+ if ((exp == null && str.length() == 0) ||
+ str.equals(exp))
+ logln(" ok");
+ else {
+ logln(" expected " + exp);
+ pass = false;
+ }
+ }
+ if (!pass) errln("Fail: FieldPosition not set right by DateFormat");
+ }
+
+ /**
+ * Verify the function of the [s|g]et2DigitYearStart() API.
+ */
+ public void Test4056591() {
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US);
+ Date start = new Date(1809-1900, Calendar.DECEMBER, 25);
+ fmt.set2DigitYearStart(start);
+ if (!fmt.get2DigitYearStart().equals(start))
+ errln("get2DigitYearStart broken");
+ Object[] DATA = {
+ "091225", new Date(1809-1900, Calendar.DECEMBER, 25),
+ "091224", new Date(1909-1900, Calendar.DECEMBER, 24),
+ "091226", new Date(1809-1900, Calendar.DECEMBER, 26),
+ "611225", new Date(1861-1900, Calendar.DECEMBER, 25),
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ String s = (String) DATA[i];
+ Date exp = (Date) DATA[i+1];
+ Date got = fmt.parse(s);
+ logln(s + " -> " + got + "; exp " + exp);
+ if (!got.equals(exp)) errln("set2DigitYearStart broken");
+ }
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public void Test4059917() {
+ if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+ return;
+ }
+
+ SimpleDateFormat fmt;
+ String myDate;
+
+ fmt = new SimpleDateFormat( "yyyy/MM/dd" );
+ myDate = "1997/01/01";
+ aux917( fmt, myDate );
+
+ fmt = new SimpleDateFormat( "yyyyMMdd" );
+ myDate = "19970101";
+ aux917( fmt, myDate );
+ }
+
+ void aux917( SimpleDateFormat fmt, String str ) {
+ try {
+ logln( "==================" );
+ logln( "testIt: pattern=" + fmt.toPattern() +
+ " string=" + str );
+
+ Object o;
+ o = fmt.parseObject( str );
+ logln( "Parsed object: " + o );
+
+ String formatted = fmt.format( o );
+ logln( "Formatted string: " + formatted );
+ if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted);
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public void Test4060212() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ try {
+ String dateString = "1995-040.05:01:29";
+
+ logln( "dateString= " + dateString );
+ logln("Using yyyy-DDD.hh:mm:ss");
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss");
+ ParsePosition pos = new ParsePosition(0);
+ Date myDate = formatter.parse( dateString, pos );
+ String myString = DateFormat.getDateTimeInstance( DateFormat.FULL,
+ DateFormat.LONG).format( myDate );
+ logln( myString );
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(myDate);
+ if (cal.get(Calendar.DAY_OF_YEAR) != 40)
+ errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) +
+ " Want 40");
+
+ logln("Using yyyy-ddd.hh:mm:ss");
+ formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss");
+ pos = new ParsePosition(0);
+ myDate = formatter.parse( dateString, pos );
+ myString = DateFormat.getDateTimeInstance( DateFormat.FULL,
+ DateFormat.LONG).format( myDate );
+ logln( myString );
+ cal.setTime(myDate);
+ if (cal.get(Calendar.DAY_OF_YEAR) != 40)
+ errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) +
+ " Want 40");
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ public void Test4061287() {
+ SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
+ try {
+ logln(df.parse("35/01/1971").toString());
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ df.setLenient(false);
+ boolean ok = false;
+ try {
+ logln(df.parse("35/01/1971").toString());
+ } catch (ParseException e) {ok=true;}
+ if (!ok) errln("Fail: Lenient not working");
+ }
+
+ public void Test4065240() {
+ Date curDate;
+ DateFormat shortdate, fulldate;
+ String strShortDate, strFullDate;
+ Locale saveLocale = Locale.getDefault();
+ TimeZone saveZone = TimeZone.getDefault();
+ try {
+ Locale curLocale = new Locale("de","DE");
+ Locale.setDefault(curLocale);
+ TimeZone.setDefault(TimeZone.getTimeZone("EST"));
+ curDate = new Date(98, 0, 1);
+ shortdate = DateFormat.getDateInstance(DateFormat.SHORT);
+ fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG
+ );
+ strShortDate = new String("The current date (short form) is " + shortdate.
+ format(curDate));
+ strFullDate = new String("The current date (long form) is " + fulldate.format(curDate));
+
+ logln(strShortDate);
+ logln(strFullDate);
+
+ // UPDATE THIS AS ZONE NAME RESOURCE FOR <EST> in de_DE is updated
+ if (!strFullDate.endsWith("EST")
+ && !strFullDate.endsWith("GMT-05:00")) {
+ errln("Fail: Want GMT-05:00");
+ }
+ }
+ finally {
+ Locale.setDefault(saveLocale);
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ /*
+ DateFormat.equals is too narrowly defined. As a result, MessageFormat
+ does not work correctly. DateFormat.equals needs to be written so
+ that the Calendar sub-object is not compared using Calendar.equals,
+ but rather compared for equivalency. This may necessitate adding a
+ (package private) method to Calendar to test for equivalency.
+
+ Currently this bug breaks MessageFormat.toPattern
+ */
+ public void Test4071441() {
+ DateFormat fmtA = DateFormat.getInstance();
+ DateFormat fmtB = DateFormat.getInstance();
+ Calendar calA = fmtA.getCalendar();
+ Calendar calB = fmtB.getCalendar();
+ Date epoch = new Date(0);
+ Date xmas = new Date(61, Calendar.DECEMBER, 25);
+ calA.setTime(epoch);
+ calB.setTime(epoch);
+ if (!calA.equals(calB))
+ errln("Fail: Can't complete test; Calendar instances unequal");
+ if (!fmtA.equals(fmtB))
+ errln("Fail: DateFormat unequal when Calendars equal");
+ calB.setTime(xmas);
+ if (calA.equals(calB))
+ errln("Fail: Can't complete test; Calendar instances equal");
+ if (!fmtA.equals(fmtB))
+ errln("Fail: DateFormat unequal when Calendars equivalent");
+ logln("DateFormat.equals ok");
+ }
+
+ /* The java.text.DateFormat.parse(String) method expects for the
+ US locale a string formatted according to mm/dd/yy and parses it
+ correctly.
+
+ When given a string mm/dd/yyyy it only parses up to the first
+ two y's, typically resulting in a date in the year 1919.
+
+ Please extend the parsing method(s) to handle strings with
+ four-digit year values (probably also applicable to various
+ other locales. */
+ public void Test4073003() {
+ try {
+ DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
+ String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" };
+ for (int i=0; i<tests.length; i+=2) {
+ Date d = fmt.parse(tests[i]);
+ Date dd = fmt.parse(tests[i+1]);
+ String s = fmt.format(d);
+ String ss = fmt.format(dd);
+ if (!d.equals(dd))
+ errln("Fail: " + d + " != " + dd);
+ if (!s.equals(ss))
+ errln("Fail: " + s + " != " + ss);
+ logln("Ok: " + s + " " + d);
+ }
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public void Test4089106() {
+ TimeZone def = TimeZone.getDefault();
+ try {
+ TimeZone z = new SimpleTimeZone((int)(1.25 * 3600000), "FAKEZONE");
+ TimeZone.setDefault(z);
+ SimpleDateFormat f = new SimpleDateFormat();
+ if (!f.getTimeZone().equals(z))
+ errln("Fail: SimpleTimeZone should use TimeZone.getDefault()");
+ }
+ finally {
+ TimeZone.setDefault(def);
+ }
+ }
+
+ public void Test4100302() {
+ Locale[] locales = new Locale[] {
+ Locale.CANADA,
+ Locale.CANADA_FRENCH,
+ Locale.CHINA,
+ Locale.CHINESE,
+ Locale.ENGLISH,
+ Locale.FRANCE,
+ Locale.FRENCH,
+ Locale.GERMAN,
+ Locale.GERMANY,
+ Locale.ITALIAN,
+ Locale.ITALY,
+ Locale.JAPAN,
+ Locale.JAPANESE,
+ Locale.KOREA,
+ Locale.KOREAN,
+ Locale.PRC,
+ Locale.SIMPLIFIED_CHINESE,
+ Locale.TAIWAN,
+ Locale.TRADITIONAL_CHINESE,
+ Locale.UK,
+ Locale.US
+ };
+ try {
+ boolean pass = true;
+ for(int i = 0; i < locales.length; i++) {
+
+ Format format = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL, locales[i]);
+ byte[] bytes;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(format);
+ oos.flush();
+
+ baos.close();
+ bytes = baos.toByteArray();
+
+ ObjectInputStream ois =
+ new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+ if (!format.equals(ois.readObject())) {
+ pass = false;
+ logln("DateFormat instance for locale " +
+ locales[i] + " is incorrectly serialized/deserialized.");
+ } else {
+ logln("DateFormat instance for locale " +
+ locales[i] + " is OKAY.");
+ }
+ }
+ if (!pass) errln("Fail: DateFormat serialization/equality bug");
+ }
+ catch (IOException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ catch (ClassNotFoundException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Test whether DataFormat can be serialized/deserialized correctly
+ * even if invalid/customized TimeZone is used.
+ */
+ public void Test4413980() {
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ try {
+ boolean pass = true;
+ String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",
+ "GMT+3:00", "GMT-01:30"};
+ for (int i = 0; i < IDs.length; i++) {
+ TimeZone tz = TimeZone.getTimeZone(IDs[i]);
+ TimeZone.setDefault(tz);
+
+ Format format = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL);
+ byte[] bytes;
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(format);
+ oos.flush();
+
+ baos.close();
+ bytes = baos.toByteArray();
+
+ ObjectInputStream ois =
+ new ObjectInputStream(new ByteArrayInputStream(bytes));
+
+ if (!format.equals(ois.readObject())) {
+ pass = false;
+ logln("DateFormat instance which uses TimeZone <" +
+ IDs[i] + "> is incorrectly serialized/deserialized.");
+ } else {
+ logln("DateFormat instance which uses TimeZone <" +
+ IDs[i] + "> is correctly serialized/deserialized.");
+ }
+ }
+ if (!pass) {
+ errln("Fail: DateFormat serialization/equality bug");
+ }
+ }
+ catch (IOException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ catch (ClassNotFoundException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ finally {
+ TimeZone.setDefault(savedTimeZone);
+ }
+ }
+
+ public void Test4101483() {
+ SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US);
+ FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD);
+ Date d= new Date(9234567890L);
+ StringBuffer buf = new StringBuffer("");
+ logln(sdf.format(d, buf, fp).toString());
+ logln(d + " => " + buf);
+ logln("beginIndex = " + fp.getBeginIndex());
+ logln("endIndex = " + fp.getEndIndex());
+ if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field");
+ }
+
+ /**
+ * Bug 4103340
+ * Bug 4138203
+ * This bug really only works in Locale.US, since that's what the locale
+ * used for Date.toString() is. Bug 4138203 reports that it fails on Korean
+ * NT; it would actually have failed on any non-US locale. Now it should
+ * work on all locales.
+ */
+ public void Test4103340() {
+ // choose a date that is the FIRST of some month
+ // and some arbitrary time
+ Date d=new Date(97, 3, 1, 1, 1, 1);
+ SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US);
+
+ String s = d.toString();
+ String s2 = df.format(d);
+ logln("Date="+s);
+ logln("DF="+s2);
+ if (s.indexOf(s2.substring(0,2)) == -1)
+ errln("Months should match");
+ }
+
+ public void Test4103341() {
+ TimeZone saveZone =TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("CST"));
+ SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm");
+ if (!simple.getTimeZone().equals(TimeZone.getDefault()))
+ errln("Fail: SimpleDateFormat not using default zone");
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ public void Test4104136() {
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ String pattern = "'time' hh:mm";
+ sdf.applyPattern(pattern);
+ logln("pattern: \"" + pattern + "\"");
+
+ Object[] DATA = {
+ "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30),
+ "time 10:x", new ParsePosition(0), null,
+ "time 10x", new ParsePosition(0), null,
+ };
+ for (int i=0; i<DATA.length; i+=3) {
+ String text = (String) DATA[i];
+ ParsePosition finish = (ParsePosition) DATA[i+1];
+ Date exp = (Date) DATA[i+2];
+
+ ParsePosition pos = new ParsePosition(0);
+ Date d = sdf.parse(text, pos);
+ logln(" text: \"" + text + "\"");
+ logln(" index: " + pos.getIndex());
+ logln(" result: " + d);
+ if (pos.getIndex() != finish.getIndex())
+ errln("Fail: Expected pos " + finish.getIndex());
+ if (!((d == null && exp == null) ||
+ d.equals(exp)))
+ errln("Fail: Expected result " + exp);
+ }
+ }
+
+ /**
+ * CANNOT REPRODUCE
+ * According to the bug report, this test should throw a
+ * StringIndexOutOfBoundsException during the second parse. However,
+ * this is not seen.
+ */
+ public void Test4104522() {
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ String pattern = "'time' hh:mm";
+ sdf.applyPattern(pattern);
+ logln("pattern: \"" + pattern + "\"");
+
+ // works correctly
+ ParsePosition pp = new ParsePosition(0);
+ String text = "time ";
+ Date date = sdf.parse(text, pp);
+ logln(" text: \"" + text + "\"" +
+ " date: " + date);
+
+ // works wrong
+ pp = new ParsePosition(0);
+ text = "time";
+ date = sdf.parse(text, pp);
+ logln(" text: \"" + text + "\"" +
+ " date: " + date);
+ }
+
+ public void Test4106807() {
+ Date date;
+ DateFormat df = DateFormat.getDateTimeInstance();
+ Object[] data = {
+ new SimpleDateFormat("yyyyMMddHHmmss"), "19980211140000",
+ new SimpleDateFormat("yyyyMMddHHmmss'Z'"), "19980211140000",
+ new SimpleDateFormat("yyyyMMddHHmmss''"), "19980211140000",
+ new SimpleDateFormat("yyyyMMddHHmmss'a''a'"), "19980211140000a",
+ new SimpleDateFormat("yyyyMMddHHmmss %"), "19980211140000 ",
+ };
+ GregorianCalendar gc = new GregorianCalendar();
+ TimeZone timeZone = TimeZone.getDefault();
+
+ TimeZone gmt = (TimeZone)timeZone.clone();
+
+ gmt.setRawOffset(0);
+
+ for (int i=0; i<data.length; i+=2) {
+ SimpleDateFormat format = (SimpleDateFormat) data[i];
+ String dateString = (String) data[i+1];
+ try {
+ format.setTimeZone(gmt);
+ date = format.parse(dateString);
+ logln(df.format(date));
+ gc.setTime(date);
+ logln("" + gc.get(Calendar.ZONE_OFFSET));
+ logln(format.format(date));
+ }
+ catch (ParseException e) {
+ logln("No way Jose");
+ }
+ }
+ }
+
+ /*
+ Synopsis: Chinese time zone CTT is not recogonized correctly.
+ Description: Platform Chinese Windows 95 - ** Time zone set to CST **
+ */
+ public void Test4108407() {
+
+ long l = System.currentTimeMillis();
+ logln("user.timezone = " + System.getProperty("user.timezone", "?"));
+ logln("Time Zone :" +
+ DateFormat.getDateInstance().getTimeZone().getID());
+ logln("Default format :" +
+ DateFormat.getDateInstance().format(new Date(l)));
+ logln("Full format :" +
+ DateFormat.getDateInstance(DateFormat.FULL).format(new
+ Date(l)));
+ logln("*** Set host TZ to CST ***");
+ logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
+ }
+
+ /**
+ * SimpleDateFormat won't parse "GMT"
+ */
+ public void Test4134203() {
+ String dateFormat = "MM/dd/yy HH:mm:ss zzz";
+ SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
+ ParsePosition p0 = new ParsePosition(0);
+ Date d = fmt.parse("01/22/92 04:52:00 GMT", p0);
+ logln(d.toString());
+ // In the failure case an exception is thrown by parse();
+ // if no exception is thrown, the test passes.
+ }
+
+ /**
+ * Another format for GMT string parse
+ */
+ public void Test4266432() {
+ String dateFormat = "MM/dd HH:mm:ss zzz yyyy";
+ SimpleDateFormat fmt = new SimpleDateFormat(dateFormat);
+ ParsePosition p0 = new ParsePosition(0);
+ Date d = fmt.parse("01/22 04:52:00 GMT 1992", p0);
+ logln(d.toString());
+ // In the failure case an exception is thrown by parse();
+ // if no exception is thrown, the test passes.
+ }
+
+ /**
+ * Millisecond field is limited to 3 digits; also test general millisecond
+ * handling.
+ *
+ * NOTE: Updated for fixed semantics as of Kestrel. See
+ * 4253490
+ */
+ public void Test4148168() throws ParseException {
+ SimpleDateFormat fmt = new SimpleDateFormat("", Locale.US);
+ int ms = 456;
+ String[] PAT = { "S", "SS", "SSS", "SSSS", "SSSSS",
+ "SSSSSSSSSSSSSSSSSSSS" };
+ String[] OUT = { "456", "456", "456", "0456", "00456",
+ "00000000000000000456" };
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(Calendar.MILLISECOND, ms);
+ Date d = cal.getTime();
+ for (int i=0; i<OUT.length; ++i) {
+ fmt.applyPattern(PAT[i]);
+ String str = fmt.format(d);
+ if (!str.equals(OUT[i])) {
+ errln("FAIL: " + ms + " ms x \"" + PAT[i] + "\" -> \"" +
+ str + "\", exp \"" + OUT[i] + '"');
+ }
+ }
+
+ // Test parsing
+ fmt.applyPattern("s.S");
+ String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456",
+ "1.4567", "1.45678" };
+ int[] MS = { 4, 4, 4, 45, 456, 567, 678 };
+ for (int i=0; i<IN.length; ++i) {
+ d = fmt.parse(IN[i]);
+ cal.setTime(d);
+ ms = cal.get(Calendar.MILLISECOND);
+ if (ms != MS[i]) {
+ errln("FAIL: parse(\"" + IN[i] + "\" x \"s.S\") -> " +
+ ms + " ms, exp " + MS[i] + " ms");
+ }
+ }
+ }
+
+ /**
+ * SimpleDateFormat incorrect handling of 2 single quotes in format()
+ */
+ public void Test4151631() {
+ String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'";
+ logln("pattern=" + pattern);
+ SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
+ String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0));
+ if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) {
+ errln("Fail: result=" + result);
+ }
+ else {
+ logln("Pass: result=" + result);
+ }
+ }
+
+ /**
+ * 'z' at end of date format throws index exception in SimpleDateFormat
+ * CANNOT REPRODUCE THIS BUG ON 1.2FCS
+ */
+ public void Test4151706() {
+ SimpleDateFormat fmt =
+ new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US);
+ try {
+ Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT");
+ if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0))
+ errln("Incorrect value: " + d);
+ } catch (Exception e) {
+ errln("Fail: " + e);
+ }
+ }
+
+ /**
+ * SimpleDateFormat fails to parse redundant data.
+ * This is actually a bug down in GregorianCalendar, but it was reported
+ * as follows...
+ */
+ public void Test4153860() throws ParseException {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ try {
+ SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance();
+ // Set the pattern
+ sf.applyPattern("yyyy.MM-dd");
+ // Try to create a Date for February 4th
+ Date d1 = sf.parse("1998.02-04");
+ // Set the pattern, this time to use the W value
+ sf.applyPattern("yyyy.MM-dd W");
+ // Try to create a Date for February 4th
+ Date d2 = sf.parse("1998.02-04 1");
+ if (!d1.equals(d2)) {
+ errln("Parse failed, got " + d2 +
+ ", expected " + d1);
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ /**
+ * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US
+ * as "EST" or "CST", not Australian "EST" and "CST".
+ */
+ public void Test4406615() {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+ Date d1, d2;
+ String dt = "Mon, 1 Jan 2001 00:00:00";
+ SimpleDateFormat sdf =
+ new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
+
+ try {
+ d1 = sdf.parse(dt+" EST");
+ d2 = sdf.parse(dt+" CST");
+
+ if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 ||
+ d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 ||
+ d2.getYear() != (2000-1900) || d2.getMonth() != 11 ||
+ d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) {
+ errln("Parse failed, d1 = " + d1 + ", d2 = " + d2);
+ } else {
+ logln("Parse passed");
+ }
+ }
+ catch (Exception e) {
+ errln("Parse failed, got Exception " + e);
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+ }
+
+ /**
+ * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate
+ * of some other bug that has been fixed.
+ */
+ public void Test4162071() {
+ String dateString = "Thu, 30-Jul-1999 11:51:14 GMT";
+ String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123
+ SimpleDateFormat df = new
+ SimpleDateFormat(format, Locale.US);
+
+ try {
+ Date x = df.parse(dateString);
+ logln("Parse format \"" + format + "\" ok");
+ logln(dateString + " -> " + df.format(x));
+ } catch (Exception e) {
+ errln("Parse format \"" + format + "\" failed.");
+ }
+ }
+
+ /**
+ * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999).
+ */
+ public void Test4182066() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy",
+ DateFormatSymbols.getInstance(Locale.US));
+ SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG",
+ DateFormatSymbols.getInstance(Locale.US));
+ /* We expect 2-digit year formats to put 2-digit years in the right
+ * window. Out of range years, that is, anything less than "00" or
+ * greater than "99", are treated as literal years. So "1/2/3456"
+ * becomes 3456 AD. Likewise, "1/2/-3" becomes -3 AD == 2 BC.
+ */
+ Object[] DATA = {
+ "02/29/00", new Date(2000-1900, Calendar.FEBRUARY, 29),
+ "01/23/01", new Date(2001-1900, Calendar.JANUARY, 23),
+ "04/05/-1", new Date( -1-1900, Calendar.APRIL, 5),
+ "01/23/-9", new Date( -9-1900, Calendar.JANUARY, 23),
+ "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12),
+ "10/31/1", new Date( 1-1900, Calendar.OCTOBER, 31),
+ "09/12/+1", null, // "+1" isn't recognized by US NumberFormat
+ "09/12/001", new Date( 1-1900, Calendar.SEPTEMBER,12),
+ };
+ StringBuffer out = new StringBuffer();
+ boolean pass = true;
+ for (int i=0; i<DATA.length; i+=2) {
+ String str = (String) DATA[i];
+ Date expected = (Date) DATA[i+1];
+ Date actual;
+ try {
+ actual = fmt.parse(str);
+ } catch (ParseException e) {
+ actual = null;
+ }
+ String actStr = actual != null
+ ? dispFmt.format(actual) : String.valueOf(actual);
+ if (expected == actual
+ || (expected != null && expected.equals(actual))) {
+ out.append(str + " => " + actStr + "\n");
+ } else {
+ String expStr = expected != null
+ ? dispFmt.format(expected) : String.valueOf(expected);
+ out.append("FAIL: " + str + " => " + actStr
+ + ", expected " + expStr + "\n");
+ pass = false;
+ }
+ }
+ if (pass) {
+ log(out.toString());
+ } else {
+ err(out.toString());
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ /**
+ * Bug 4210209
+ * Bug 4209272
+ * DateFormat cannot parse Feb 29 2000 when setLenient(false)
+ */
+ public void Test4210209() {
+ String pattern = "MMM d, yyyy";
+ DateFormat fmt = new SimpleDateFormat(pattern,
+ DateFormatSymbols.getInstance(Locale.US));
+ fmt.getCalendar().setLenient(false);
+ Date d = new Date(2000-1900, Calendar.FEBRUARY, 29);
+ String s = fmt.format(d);
+ logln(d + " x " + pattern + " => " + s);
+ ParsePosition pos = new ParsePosition(0);
+ d = fmt.parse(s, pos);
+ logln(d + " <= " + pattern + " x " + s);
+ logln("Parse pos = " + pos);
+ if (pos.getErrorIndex() != -1) {
+ errln("FAIL");
+ }
+
+ // The underlying bug is in GregorianCalendar. If the following lines
+ // succeed, the bug is fixed. If the bug isn't fixed, they will throw
+ // an exception.
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.clear();
+ cal.setLenient(false);
+ cal.set(2000, Calendar.FEBRUARY, 29); // This should work!
+ logln(cal.getTime().toString());
+ }
+
+ /**
+ * DateFormat.getDateTimeInstance() allows illegal parameters.
+ */
+ public void Test4213086() {
+ int[] DATA = {
+ // Style value, 0/1 for illegal/legal
+ -99, 0,
+ -1, 0,
+ 0, 1,
+ 1, 1,
+ 2, 1,
+ 3, 1,
+ 4, 0,
+ 99, 0,
+ };
+ String[] DESC = {
+ "getDateTimeInstance(date)",
+ "getDateTimeInstance(time)",
+ "getDateInstance",
+ "getTimeInstance",
+ };
+ String[] GOT = {
+ "disallowed", "allowed", "<invalid>"
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ int got = 2;
+ for (int j=0; j<4; ++j) {
+ Exception e = null;
+ try {
+ DateFormat df;
+ switch (j) {
+ case 0:
+ df = DateFormat.getDateTimeInstance(DATA[i], 0);
+ break;
+ case 1:
+ df = DateFormat.getDateTimeInstance(0, DATA[i]);
+ break;
+ case 2:
+ df = DateFormat.getDateInstance(DATA[i]);
+ break;
+ case 3:
+ df = DateFormat.getTimeInstance(DATA[i]);
+ break;
+ }
+ got = 1;
+ } catch (IllegalArgumentException iae) {
+ got = 0;
+ } catch (Exception ex) {
+ e = ex;
+ }
+ if (got != DATA[i+1] || e != null) {
+ errln("FAIL: DateFormat." + DESC[j] + " style " + DATA[i] + " " +
+ (e != null ? e.toString() : GOT[got]));
+ }
+ }
+ }
+ }
+
+ public void Test4253490() throws ParseException {
+ SimpleDateFormat fmt = new SimpleDateFormat("S", Locale.US);
+
+ GregorianCalendar cal = new GregorianCalendar();
+
+ int FORMAT_MS = 12;
+ String[] FORMAT_PAT = { "S", "SS", "SSS", "SSSS" };
+ String[] FORMAT_TO = { "12", "12", "012", "0012" };
+
+ String PARSE_PAT = "S";
+ String[] PARSE_STR = { "1", "12", "125", "1250" };
+ int[] PARSE_TO = { 1, 12, 125, 250 };
+ String PARSE_LPAT = "SSSSS";
+
+ // Test formatting. We want to make sure all digits are output
+ // and that they are zero-padded on the left if necessary.
+ cal.setTime(new Date(0L));
+ cal.set(Calendar.MILLISECOND, FORMAT_MS);
+ Date d = cal.getTime();
+ for (int i=0; i<FORMAT_PAT.length; ++i) {
+ fmt.applyPattern(FORMAT_PAT[i]);
+ String s = fmt.format(d);
+ if (s.equals(FORMAT_TO[i])) {
+ logln(String.valueOf(FORMAT_MS) + " ms f* \"" +
+ FORMAT_PAT[i] + "\" -> \"" + s + '"');
+ } else {
+ errln("FAIL: " + FORMAT_MS + " ms f* \"" +
+ FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" +
+ FORMAT_TO[i] + '"');
+ }
+ }
+
+ // Test parsing. We want to make sure all digits are read.
+ fmt.applyPattern(PARSE_PAT);
+ for (int i=0; i<PARSE_STR.length; ++i) {
+ cal.setTime(fmt.parse(PARSE_STR[i]));
+ int ms = cal.get(Calendar.MILLISECOND);
+ if (ms == PARSE_TO[i]) {
+ logln("\"" + PARSE_STR[i] + "\" p* \"" +
+ PARSE_PAT + "\" -> " + ms + " ms");
+ } else {
+ errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" +
+ PARSE_PAT + "\" -> " + ms + " ms, expect " +
+ PARSE_TO[i] + " ms");
+ }
+ }
+
+ // Test LONG parsing. We want to make sure all digits are read.
+ fmt.applyPattern(PARSE_LPAT);
+ for (int i=0; i<PARSE_STR.length; ++i) {
+ cal.setTime(fmt.parse(PARSE_STR[i]));
+ int ms = cal.get(Calendar.MILLISECOND);
+ if (ms == PARSE_TO[i]) {
+ logln("\"" + PARSE_STR[i] + "\" p* \"" +
+ PARSE_LPAT + "\" -> " + ms + " ms");
+ } else {
+ errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" +
+ PARSE_LPAT + "\" -> " + ms + " ms, expect " +
+ PARSE_TO[i] + " ms");
+ }
+ }
+ }
+
+ /**
+ * Bug in handling of time instance; introduces in fix for 4213086.
+ */
+ public void Test4250359() {
+ DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT,
+ Locale.US);
+ Date d = new Date(1999-1900, Calendar.DECEMBER, 25,
+ 1, 2, 3);
+ String s = df.format(d);
+ // If the bug is present, we see "1:02 AM 1:02 AM".
+ // Look for more than one instance of "AM".
+ int i = s.indexOf("AM");
+ int j = s.indexOf("AM", i+1);
+ if (i < 0 || j >= 0) {
+ errln("FAIL: getTimeInstance().format(d) => \"" +
+ s + "\"");
+ }
+ }
+
+ /**
+ * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse
+ * non-localized time zones.
+ */
+ public void Test4261506() {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ Locale.setDefault(Locale.JAPAN);
+
+ // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to
+ // pick up another time zone when L10N is done to that file.
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN);
+ String result = fmt.format(new Date(1999, 0, 1));
+ logln("format()=>" + result);
+ if (!result.endsWith("PST")) {
+ errln("FAIL: SimpleDataFormat.format() did not retrun PST");
+ }
+
+ Date d = null;
+ try {
+ d = fmt.parse("99/1/1 10:10 PST");
+ } catch (ParseException e) {
+ errln("FAIL: SimpleDataFormat.parse() could not parse PST");
+ }
+
+ result = fmt.format(d);
+ logln("roundtrip:" + result);
+ if (!result.equals("99/01/01 10:10 PST")) {
+ errln("FAIL: SimpleDataFomat timezone roundtrip failed");
+ }
+
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+
+}
+
+//eof
diff --git a/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java b/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java
new file mode 100644
index 0000000000..73d023163f
--- /dev/null
+++ b/test/java/text/Format/DateFormat/DateFormatRoundTripTest.java
@@ -0,0 +1,727 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @summary test Date Format (Round Trip)
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest
+ */
+
+import java.text.*;
+import java.util.*;
+
+public class DateFormatRoundTripTest extends IntlTest {
+
+ static Random RANDOM = null;
+
+ static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value
+
+ // Useful for turning up subtle bugs: Use -infinite and run while at lunch.
+ boolean INFINITE = false; // Warning -- makes test run infinite loop!!!
+
+ boolean random = false;
+
+ // Options used to reproduce failures
+ Locale locale = null;
+ String pattern = null;
+ Date initialDate = null;
+
+ Locale[] avail;
+ TimeZone defaultZone;
+
+ // If SPARSENESS is > 0, we don't run each exhaustive possibility.
+ // There are 24 total possible tests per each locale. A SPARSENESS
+ // of 12 means we run half of them. A SPARSENESS of 23 means we run
+ // 1 of them. SPARSENESS _must_ be in the range 0..23.
+ static final int SPARSENESS = 18;
+
+ static final int TRIALS = 4;
+
+ static final int DEPTH = 5;
+
+ static SimpleDateFormat refFormat =
+ new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
+
+ public DateFormatRoundTripTest(boolean rand, long seed, boolean infinite,
+ Date date, String pat, Locale loc) {
+ random = rand;
+ if (random) {
+ RANDOM = new Random(seed);
+ }
+ INFINITE = infinite;
+
+ initialDate = date;
+ locale = loc;
+ pattern = pat;
+ }
+
+ /**
+ * Parse a name like "fr_FR" into new Locale("fr", "FR", "");
+ */
+ static Locale createLocale(String name) {
+ String country = "",
+ variant = "";
+ int i;
+ if ((i = name.indexOf('_')) >= 0) {
+ country = name.substring(i+1);
+ name = name.substring(0, i);
+ }
+ if ((i = country.indexOf('_')) >= 0) {
+ variant = country.substring(i+1);
+ country = country.substring(0, i);
+ }
+ return new Locale(name, country, variant);
+ }
+
+ public static void main(String[] args) throws Exception {
+ // Command-line parameters
+ Locale loc = null;
+ boolean infinite = false;
+ boolean random = false;
+ long seed = FIXED_SEED;
+ String pat = null;
+ Date date = null;
+
+ Vector newArgs = new Vector();
+ for (int i=0; i<args.length; ++i) {
+ if (args[i].equals("-locale")
+ && (i+1) < args.length) {
+ loc = createLocale(args[i+1]);
+ ++i;
+ } else if (args[i].equals("-date")
+ && (i+1) < args.length) {
+ date = new Date(Long.parseLong(args[i+1]));
+ ++i;
+ } else if (args[i].equals("-pattern")
+ && (i+1) < args.length) {
+ pat = args[i+1];
+ ++i;
+ } else if (args[i].equals("-INFINITE")) {
+ infinite = true;
+ } else if (args[i].equals("-random")) {
+ random = true;
+ } else if (args[i].equals("-randomseed")) {
+ random = true;
+ seed = System.currentTimeMillis();
+ } else if (args[i].equals("-seed")
+ && (i+1) < args.length) {
+ random = true;
+ seed = Long.parseLong(args[i+1]);
+ ++i;
+ } else {
+ newArgs.addElement(args[i]);
+ }
+ }
+
+ if (newArgs.size() != args.length) {
+ args = new String[newArgs.size()];
+ newArgs.copyInto(args);
+ }
+
+ new DateFormatRoundTripTest(random, seed, infinite, date, pat, loc).run(args);
+ }
+
+ /**
+ * Print a usage message for this test class.
+ */
+ void usage() {
+ System.out.println(getClass().getName() +
+ ": [-pattern <pattern>] [-locale <locale>] [-date <ms>] [-INFINITE]");
+ System.out.println(" [-random | -randomseed | -seed <seed>]");
+ System.out.println("* Warning: Some patterns will fail with some locales.");
+ System.out.println("* Do not use -pattern unless you know what you are doing!");
+ System.out.println("When specifying a locale, use a format such as fr_FR.");
+ System.out.println("Use -pattern, -locale, and -date to reproduce a failure.");
+ System.out.println("-random Random with fixed seed (same data every run).");
+ System.out.println("-randomseed Random with a random seed.");
+ System.out.println("-seed <s> Random using <s> as seed.");
+ super.usage();
+ }
+
+ static private class TestCase {
+ private int[] date;
+ TimeZone zone;
+ FormatFactory ff;
+ boolean timeOnly;
+ private Date _date;
+
+ TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) {
+ date = d;
+ zone = z;
+ ff = f;
+ this.timeOnly = timeOnly;
+ }
+
+ TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) {
+ date = null;
+ _date = d;
+ zone = z;
+ ff = f;
+ this.timeOnly = timeOnly;
+ }
+
+ /**
+ * Create a format for testing.
+ */
+ DateFormat createFormat() {
+ return ff.createFormat();
+ }
+
+ /**
+ * Return the Date of this test case; must be called with the default
+ * zone set to this TestCase's zone.
+ */
+ Date getDate() {
+ if (_date == null) {
+ // Date constructor will work right iff we are in the target zone
+ int h = 0;
+ int m = 0;
+ int s = 0;
+ if (date.length >= 4) {
+ h = date[3];
+ if (date.length >= 5) {
+ m = date[4];
+ if (date.length >= 6) {
+ s = date[5];
+ }
+ }
+ }
+ _date = new Date(date[0] - 1900, date[1] - 1, date[2],
+ h, m, s);
+ }
+ return _date;
+ }
+
+ public String toString() {
+ return String.valueOf(getDate().getTime()) + " " +
+ refFormat.format(getDate()) + " : " + ff.createFormat().format(getDate());
+ }
+ };
+
+ private interface FormatFactory {
+ DateFormat createFormat();
+ }
+
+ TestCase[] TESTS = {
+ // Feb 29 2004 -- ordinary leap day
+ new TestCase(new int[] {2004, 2, 29}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // Feb 29 2000 -- century leap day
+ new TestCase(new int[] {2000, 2, 29}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // 0:00:00 Jan 1 1999 -- first second of normal year
+ new TestCase(new int[] {1999, 1, 1}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance();
+ }}, false),
+
+ // 23:59:59 Dec 31 1999 -- last second of normal year
+ new TestCase(new int[] {1999, 12, 31, 23, 59, 59}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance();
+ }}, false),
+
+ // 0:00:00 Jan 1 2004 -- first second of leap year
+ new TestCase(new int[] {2004, 1, 1}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance();
+ }}, false),
+
+ // 23:59:59 Dec 31 2004 -- last second of leap year
+ new TestCase(new int[] {2004, 12, 31, 23, 59, 59}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance();
+ }}, false),
+
+ // October 25, 1998 1:59:59 AM PDT -- just before DST cessation
+ new TestCase(new Date(909305999000L), TimeZone.getTimeZone("PST"),
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // October 25, 1998 1:00:00 AM PST -- just after DST cessation
+ new TestCase(new Date(909306000000L), TimeZone.getTimeZone("PST"),
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // April 4, 1999 1:59:59 AM PST -- just before DST onset
+ new TestCase(new int[] {1999, 4, 4, 1, 59, 59},
+ TimeZone.getTimeZone("PST"),
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // April 4, 1999 3:00:00 AM PDT -- just after DST onset
+ new TestCase(new Date(923220000000L), TimeZone.getTimeZone("PST"),
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change
+ new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+
+ // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change
+ new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null,
+ new FormatFactory() { public DateFormat createFormat() {
+ return DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ }}, false),
+ };
+
+ public void TestDateFormatRoundTrip() {
+ avail = DateFormat.getAvailableLocales();
+ logln("DateFormat available locales: " + avail.length);
+ logln("Default TimeZone: " +
+ (defaultZone = TimeZone.getDefault()).getID());
+
+ if (random || initialDate != null) {
+ if (RANDOM == null) {
+ // Need this for sparse coverage to reduce combinatorial explosion,
+ // even for non-random looped testing (i.e., with explicit date but
+ // not pattern or locale).
+ RANDOM = new Random(FIXED_SEED);
+ }
+ loopedTest();
+ } else {
+ for (int i=0; i<TESTS.length; ++i) {
+ doTest(TESTS[i]);
+ }
+ }
+ }
+
+ /**
+ * TimeZone must be set to tc.zone before this method is called.
+ */
+ private void doTestInZone(TestCase tc) {
+ logln(escape(tc.toString()));
+ Locale save = Locale.getDefault();
+ try {
+ if (locale != null) {
+ Locale.setDefault(locale);
+ doTest(locale, tc.createFormat(), tc.timeOnly, tc.getDate());
+ } else {
+ for (int i=0; i<avail.length; ++i) {
+ Locale.setDefault(avail[i]);
+ doTest(avail[i], tc.createFormat(), tc.timeOnly, tc.getDate());
+ }
+ }
+ } finally {
+ Locale.setDefault(save);
+ }
+ }
+
+ private void doTest(TestCase tc) {
+ if (tc.zone == null) {
+ // Just run in the default zone
+ doTestInZone(tc);
+ } else {
+ try {
+ TimeZone.setDefault(tc.zone);
+ doTestInZone(tc);
+ } finally {
+ TimeZone.setDefault(defaultZone);
+ }
+ }
+ }
+
+ private void loopedTest() {
+ if (INFINITE) {
+ // Special infinite loop test mode for finding hard to reproduce errors
+ if (locale != null) {
+ logln("ENTERING INFINITE TEST LOOP, LOCALE " + locale.getDisplayName());
+ for (;;) doTest(locale);
+ } else {
+ logln("ENTERING INFINITE TEST LOOP, ALL LOCALES");
+ for (;;) {
+ for (int i=0; i<avail.length; ++i) {
+ doTest(avail[i]);
+ }
+ }
+ }
+ }
+ else {
+ if (locale != null) {
+ doTest(locale);
+ } else {
+ doTest(Locale.getDefault());
+
+ for (int i=0; i<avail.length; ++i) {
+ doTest(avail[i]);
+ }
+ }
+ }
+ }
+
+ void doTest(Locale loc) {
+ if (!INFINITE) logln("Locale: " + loc.getDisplayName());
+
+ if (pattern != null) {
+ doTest(loc, new SimpleDateFormat(pattern, loc));
+ return;
+ }
+
+ // Total possibilities = 24
+ // 4 date
+ // 4 time
+ // 16 date-time
+ boolean[] TEST_TABLE = new boolean[24];
+ for (int i=0; i<24; ++i) TEST_TABLE[i] = true;
+
+ // If we have some sparseness, implement it here. Sparseness decreases
+ // test time by eliminating some tests, up to 23.
+ if (!INFINITE) {
+ for (int i=0; i<SPARSENESS; ) {
+ int random = (int)(java.lang.Math.random() * 24);
+ if (random >= 0 && random < 24 && TEST_TABLE[i]) {
+ TEST_TABLE[i] = false;
+ ++i;
+ }
+ }
+ }
+
+ int itable = 0;
+ for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) {
+ if (TEST_TABLE[itable++])
+ doTest(loc, DateFormat.getDateInstance(style, loc));
+ }
+
+ for (int style=DateFormat.FULL; style<=DateFormat.SHORT; ++style) {
+ if (TEST_TABLE[itable++])
+ doTest(loc, DateFormat.getTimeInstance(style, loc), true);
+ }
+
+ for (int dstyle=DateFormat.FULL; dstyle<=DateFormat.SHORT; ++dstyle) {
+ for (int tstyle=DateFormat.FULL; tstyle<=DateFormat.SHORT; ++tstyle) {
+ if (TEST_TABLE[itable++])
+ doTest(loc, DateFormat.getDateTimeInstance(dstyle, tstyle, loc));
+ }
+ }
+ }
+
+ void doTest(Locale loc, DateFormat fmt) { doTest(loc, fmt, false); }
+
+ void doTest(Locale loc, DateFormat fmt, boolean timeOnly) {
+ doTest(loc, fmt, timeOnly, initialDate != null ? initialDate : generateDate());
+ }
+
+ void doTest(Locale loc, DateFormat fmt, boolean timeOnly, Date date) {
+ // Skip testing with the JapaneseImperialCalendar which
+ // doesn't support the Gregorian year semantices with 'y'.
+ if (fmt.getCalendar().getClass().getName().equals("java.util.JapaneseImperialCalendar")) {
+ return;
+ }
+
+ String pat = ((SimpleDateFormat)fmt).toPattern();
+ String deqPat = dequotePattern(pat); // Remove quoted elements
+
+ boolean hasEra = (deqPat.indexOf("G") != -1);
+ boolean hasZone = (deqPat.indexOf("z") != -1);
+
+ Calendar cal = fmt.getCalendar();
+
+ // Because patterns contain incomplete data representing the Date,
+ // we must be careful of how we do the roundtrip. We start with
+ // a randomly generated Date because they're easier to generate.
+ // From this we get a string. The string is our real starting point,
+ // because this string should parse the same way all the time. Note
+ // that it will not necessarily parse back to the original date because
+ // of incompleteness in patterns. For example, a time-only pattern won't
+ // parse back to the same date.
+
+ try {
+ for (int i=0; i<TRIALS; ++i) {
+ Date[] d = new Date[DEPTH];
+ String[] s = new String[DEPTH];
+ String error = null;
+
+ d[0] = date;
+
+ // We go through this loop until we achieve a match or until
+ // the maximum loop count is reached. We record the points at
+ // which the date and the string starts to match. Once matching
+ // starts, it should continue.
+ int loop;
+ int dmatch = 0; // d[dmatch].getTime() == d[dmatch-1].getTime()
+ int smatch = 0; // s[smatch].equals(s[smatch-1])
+ for (loop=0; loop<DEPTH; ++loop) {
+ if (loop > 0) d[loop] = fmt.parse(s[loop-1]);
+ s[loop] = fmt.format(d[loop]);
+
+ if (loop > 0) {
+ if (smatch == 0) {
+ boolean match = s[loop].equals(s[loop-1]);
+ if (smatch == 0) {
+ if (match) smatch = loop;
+ }
+ else if (!match) {
+ // This should never happen; if it does, fail.
+ smatch = -1;
+ error = "FAIL: String mismatch after match";
+ }
+ }
+
+ if (dmatch == 0) {
+ boolean match = d[loop].getTime() == d[loop-1].getTime();
+ if (dmatch == 0) {
+ if (match) dmatch = loop;
+ }
+ else if (!match) {
+ // This should never happen; if it does, fail.
+ dmatch = -1;
+ error = "FAIL: Date mismatch after match";
+ }
+ }
+
+ if (smatch != 0 && dmatch != 0) break;
+ }
+ }
+ // At this point loop == DEPTH if we've failed, otherwise loop is the
+ // max(smatch, dmatch), that is, the index at which we have string and
+ // date matching.
+
+ // Date usually matches in 2. Exceptions handled below.
+ int maxDmatch = 2;
+ int maxSmatch = 1;
+ if (dmatch > maxDmatch) {
+ // Time-only pattern with zone information and a starting date in PST.
+ if (timeOnly && hasZone && fmt.getTimeZone().inDaylightTime(d[0])) {
+ maxDmatch = 3;
+ maxSmatch = 2;
+ }
+ }
+
+ // String usually matches in 1. Exceptions are checked for here.
+ if (smatch > maxSmatch) { // Don't compute unless necessary
+ // Starts in BC, with no era in pattern
+ if (!hasEra && getField(cal, d[0], Calendar.ERA) == GregorianCalendar.BC)
+ maxSmatch = 2;
+ // Starts in DST, no year in pattern
+ else if (fmt.getTimeZone().inDaylightTime(d[0]) &&
+ deqPat.indexOf("yyyy") == -1)
+ maxSmatch = 2;
+ // Two digit year with zone and year change and zone in pattern
+ else if (hasZone &&
+ fmt.getTimeZone().inDaylightTime(d[0]) !=
+ fmt.getTimeZone().inDaylightTime(d[dmatch]) &&
+ getField(cal, d[0], Calendar.YEAR) !=
+ getField(cal, d[dmatch], Calendar.YEAR) &&
+ deqPat.indexOf("y") != -1 &&
+ deqPat.indexOf("yyyy") == -1)
+ maxSmatch = 2;
+ // Two digit year, year change, DST changeover hour. Example:
+ // FAIL: Pattern: dd/MM/yy HH:mm:ss
+ // Date matched in 2, wanted 2
+ // String matched in 2, wanted 1
+ // Thu Apr 02 02:35:52.110 PST 1795 AD F> 02/04/95 02:35:52
+ // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52
+ // P> Sun Apr 02 01:35:52.000 PST 1995 AD F> 02/04/95 01:35:52 d== s==
+ // The problem is that the initial time is not a DST onset day, but
+ // then the year changes, and the resultant parsed time IS a DST
+ // onset day. The hour "2:XX" makes no sense if 2:00 is the DST
+ // onset, so DateFormat interprets it as 1:XX (arbitrary -- could
+ // also be 3:XX, same problem). This results in an extra iteration
+ // for String match convergence.
+ else if (!justBeforeOnset(cal, d[0]) && justBeforeOnset(cal, d[dmatch]) &&
+ getField(cal, d[0], Calendar.YEAR) !=
+ getField(cal, d[dmatch], Calendar.YEAR) &&
+ deqPat.indexOf("y") != -1 &&
+ deqPat.indexOf("yyyy") == -1)
+ maxSmatch = 2;
+ // Another spurious failure:
+ // FAIL: Pattern: dd MMMM yyyy hh:mm:ss
+ // Date matched in 2, wanted 2
+ // String matched in 2, wanted 1
+ // Sun Apr 05 14:28:38.410 PDT 3998 AD F> 05 April 3998 02:28:38
+ // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38
+ // P> Sun Apr 05 01:28:38.000 PST 3998 AD F> 05 April 3998 01:28:38 d== s==
+ // The problem here is that with an 'hh' pattern, hour from 1-12,
+ // a lack of AM/PM -- that is, no 'a' in pattern, and an initial
+ // time in the onset hour + 12:00.
+ else if (deqPat.indexOf('h') >= 0
+ && deqPat.indexOf('a') < 0
+ && justBeforeOnset(cal, new Date(d[0].getTime() - 12*60*60*1000L))
+ && justBeforeOnset(cal, d[1]))
+ maxSmatch = 2;
+ }
+
+ if (dmatch > maxDmatch || smatch > maxSmatch
+ || dmatch < 0 || smatch < 0) {
+ StringBuffer out = new StringBuffer();
+ if (error != null) {
+ out.append(error + '\n');
+ }
+ out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n');
+ out.append(" Initial date (ms): " + d[0].getTime() + '\n');
+ out.append(" Date matched in " + dmatch
+ + ", wanted " + maxDmatch + '\n');
+ out.append(" String matched in " + smatch
+ + ", wanted " + maxSmatch);
+
+ for (int j=0; j<=loop && j<DEPTH; ++j) {
+ out.append("\n " +
+ (j>0?" P> ":" ") + refFormat.format(d[j]) + " F> " +
+ escape(s[j]) +
+ (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") +
+ (j>0&&s[j].equals(s[j-1])?" s==":""));
+ }
+ errln(escape(out.toString()));
+ }
+ }
+ }
+ catch (ParseException e) {
+ errln(e.toString());
+ }
+ }
+
+ /**
+ * Return a field of the given date
+ */
+ static int getField(Calendar cal, Date d, int f) {
+ // Should be synchronized, but we're single threaded so it's ok
+ cal.setTime(d);
+ return cal.get(f);
+ }
+
+ /**
+ * Return true if the given Date is in the 1 hour window BEFORE the
+ * change from STD to DST for the given Calendar.
+ */
+ static final boolean justBeforeOnset(Calendar cal, Date d) {
+ return nearOnset(cal, d, false);
+ }
+
+ /**
+ * Return true if the given Date is in the 1 hour window AFTER the
+ * change from STD to DST for the given Calendar.
+ */
+ static final boolean justAfterOnset(Calendar cal, Date d) {
+ return nearOnset(cal, d, true);
+ }
+
+ /**
+ * Return true if the given Date is in the 1 hour (or whatever the
+ * DST savings is) window before or after the onset of DST.
+ */
+ static boolean nearOnset(Calendar cal, Date d, boolean after) {
+ cal.setTime(d);
+ if ((cal.get(Calendar.DST_OFFSET) == 0) == after) {
+ return false;
+ }
+ int delta;
+ try {
+ delta = ((SimpleTimeZone) cal.getTimeZone()).getDSTSavings();
+ } catch (ClassCastException e) {
+ delta = 60*60*1000; // One hour as ms
+ }
+ cal.setTime(new Date(d.getTime() + (after ? -delta : delta)));
+ return (cal.get(Calendar.DST_OFFSET) == 0) == after;
+ }
+
+ static String escape(String s) {
+ StringBuffer buf = new StringBuffer();
+ for (int i=0; i<s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c < '\u0080') buf.append(c);
+ else {
+ buf.append("\\u");
+ if (c < '\u1000') {
+ buf.append('0');
+ if (c < '\u0100') {
+ buf.append('0');
+ if (c < '\u0010') {
+ buf.append('0');
+ }
+ }
+ }
+ buf.append(Integer.toHexString(c));
+ }
+ }
+ return buf.toString();
+ }
+
+ /**
+ * Remove quoted elements from a pattern. E.g., change "hh:mm 'o''clock'"
+ * to "hh:mm ?". All quoted elements are replaced by one or more '?'
+ * characters.
+ */
+ static String dequotePattern(String pat) {
+ StringBuffer out = new StringBuffer();
+ boolean inQuote = false;
+ for (int i=0; i<pat.length(); ++i) {
+ char ch = pat.charAt(i);
+ if (ch == '\'') {
+ if ((i+1)<pat.length()
+ && pat.charAt(i+1) == '\'') {
+ // Handle "''"
+ out.append('?');
+ ++i;
+ } else {
+ inQuote = !inQuote;
+ if (inQuote) {
+ out.append('?');
+ }
+ }
+ } else if (!inQuote) {
+ out.append(ch);
+ }
+ }
+ return out.toString();
+ }
+
+ static Date generateDate() {
+ double a = (RANDOM.nextLong() & 0x7FFFFFFFFFFFFFFFL ) /
+ ((double)0x7FFFFFFFFFFFFFFFL);
+
+ // Now 'a' ranges from 0..1; scale it to range from 0 to 8000 years
+ a *= 8000;
+
+ // Range from (4000-1970) BC to (8000-1970) AD
+ a -= 4000;
+
+ // Now scale up to ms
+ a *= 365.25 * 24 * 60 * 60 * 1000;
+
+ return new Date((long)a);
+ }
+}
+
+//eof
diff --git a/test/java/text/Format/DateFormat/DateFormatSymbolsSerializationTest.java b/test/java/text/Format/DateFormat/DateFormatSymbolsSerializationTest.java
new file mode 100644
index 0000000000..4f3797e85c
--- /dev/null
+++ b/test/java/text/Format/DateFormat/DateFormatSymbolsSerializationTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1999, 2016, 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 4278402
+ * @library /java/text/testlib
+ * @build DateFormatSymbolsSerializationTest HexDumpReader
+ * @run main DateFormatSymbolsSerializationTest
+ * @summary Make sure DateFormatSymbols serialization
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class DateFormatSymbolsSerializationTest {
+
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ boolean err = false;
+ Locale.setDefault(Locale.ENGLISH);
+ SimpleDateFormat sdf =
+ new SimpleDateFormat("yyyy.MM.dd E hh.mm.ss zzz",
+ Locale.ENGLISH);
+ Calendar calendar =
+ new GregorianCalendar(TimeZone.getTimeZone("GMT"),
+ Locale.ENGLISH);
+ calendar.setTime(new Date(0L));
+ DecimalFormat df = new DecimalFormat("");
+ df.setDecimalSeparatorAlwaysShown(true);
+ df.setGroupingSize(3);
+ df.setMultiplier(1);
+ df.setNegativePrefix("-");
+ df.setNegativeSuffix("");
+ df.setPositivePrefix("");
+ df.setPositiveSuffix("");
+ df.setMaximumFractionDigits(3); //
+ df.setMinimumIntegerDigits(1); // for compatibility 1.2 and 1.3
+ df.setMaximumIntegerDigits(40); //
+
+ sdf.setCalendar(calendar);
+ sdf.setNumberFormat(df);
+
+ SimpleDateFormat sdf1;
+
+ if (args.length > 0) {
+ try (FileOutputStream fos =
+ new FileOutputStream("SDFserialized.ser")) {
+ ObjectOutputStream oStream = new ObjectOutputStream(fos);
+ oStream.writeObject(sdf);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ } else {
+ try (InputStream is =
+ HexDumpReader.getStreamFromHexDump("SDFserialized.ser.txt")) {
+ ObjectInputStream iStream = new ObjectInputStream(is);
+ sdf1 = (SimpleDateFormat)iStream.readObject();
+ }
+
+ DateFormatSymbols dfs = sdf.getDateFormatSymbols();
+ DateFormatSymbols dfs1 = sdf1.getDateFormatSymbols();
+ System.out.println(sdf + "," + sdf.toPattern());
+ System.out.println(sdf1 + "," + sdf1.toPattern());
+
+ // time zone display names should not be a part of this
+ // compatibility test. See 4112924 and 4282899.
+ dfs.setZoneStrings(dfs1.getZoneStrings());
+ // localPatternChars should not be a part of this
+ // compatibility test. See 4322313.
+ dfs.setLocalPatternChars(dfs1.getLocalPatternChars());
+ sdf.setDateFormatSymbols(dfs);
+
+ // decimal format symbols should not be part of this
+ // compatibility test - old decimal format symbols get filled
+ // in with the root locale (4290801)
+ DecimalFormat df1 = (DecimalFormat) sdf1.getNumberFormat();
+ df1.setDecimalFormatSymbols(df.getDecimalFormatSymbols());
+
+ if (!dfs.equals(dfs1)) {
+ err = true;
+ System.err.println(
+ "Error: serialized DateFormatSymbols is different");
+ }
+ if (!sdf.equals(sdf1)) {
+ err = true;
+ System.err.println(
+ "Error: serialized SimpleDateFormat is different");
+ }
+ if (err) {
+ throw new Exception("Serialization failed.");
+ }
+ }
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/DateFormatTest.java b/test/java/text/Format/DateFormat/DateFormatTest.java
new file mode 100644
index 0000000000..c4f148f3d7
--- /dev/null
+++ b/test/java/text/Format/DateFormat/DateFormatTest.java
@@ -0,0 +1,1207 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571
+ * @summary test DateFormat and SimpleDateFormat.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest
+ */
+
+import java.util.*;
+import java.text.*;
+import static java.util.GregorianCalendar.*;
+
+public class DateFormatTest extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ new DateFormatTest().run(args);
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+
+ // Test 4 digit year parsing with pattern "yy"
+ @SuppressWarnings("deprecation")
+ public void TestYearParsing()
+ {
+ String str = "7/Sep/2001";
+ Date exp = new Date(2001-1900, SEPTEMBER, 7);
+ String pat = "d/MMM/yy";
+ SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US);
+ try {
+ Date d = sdf.parse(str);
+ logln(str + " parses with " + pat + " to " + d);
+ if (d.getTime() != exp.getTime()) {
+ errln("FAIL: Expected " + exp);
+ }
+ }
+ catch (ParseException e) {
+ errln(str + " parse fails with " + pat);
+ }
+ }
+
+ // Test written by Wally Wedel and emailed to me.
+ public void TestWallyWedel()
+ {
+ /*
+ * Instantiate a TimeZone so we can get the ids.
+ */
+ TimeZone tz = new SimpleTimeZone(7,"");
+ /*
+ * Computational variables.
+ */
+ int offset, hours, minutes;
+ /*
+ * Instantiate a SimpleDateFormat set up to produce a full time
+ zone name.
+ */
+ SimpleDateFormat sdf = new SimpleDateFormat("zzzz");
+ /*
+ * A String array for the time zone ids.
+ */
+ String[] ids = TimeZone.getAvailableIDs();
+ /*
+ * How many ids do we have?
+ */
+ logln("Time Zone IDs size: " + ids.length);
+ /*
+ * Column headings (sort of)
+ */
+ logln("Ordinal ID offset(h:m) name");
+ /*
+ * Loop through the tzs.
+ */
+ Date today = new Date();
+ Calendar cal = Calendar.getInstance();
+ for (int i = 0; i < ids.length; i++) {
+ // logln(i + " " + ids[i]);
+ TimeZone ttz = TimeZone.getTimeZone(ids[i]);
+ // offset = ttz.getRawOffset();
+ cal.setTimeZone(ttz);
+ cal.setTime(today);
+ offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
+ // logln(i + " " + ids[i] + " offset " + offset);
+ char sign = '+';
+ if (offset < 0) { sign = '-'; offset = -offset; }
+ hours = offset/3600000;
+ minutes = (offset%3600000)/60000;
+ String dstOffset = "" + sign + (hours < 10 ? "0" : "") +
+ hours + ':' + (minutes < 10 ? "0" : "") + minutes;
+ /*
+ * Instantiate a date so we can display the time zone name.
+ */
+ sdf.setTimeZone(ttz);
+ /*
+ * Format the output.
+ */
+ StringBuffer tzS = new StringBuffer();
+ sdf.format(today,tzS, new FieldPosition(0));
+ String fmtOffset = tzS.toString();
+ String fmtDstOffset = null;
+ if (fmtOffset.startsWith("GMT"))
+ {
+ fmtDstOffset = fmtOffset.substring(3);
+ }
+ /*
+ * Show our result.
+ */
+ boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset);
+ if (ok)
+ {
+ logln(i + " " + ids[i] + " " + dstOffset +
+ " " + fmtOffset +
+ (fmtDstOffset != null ? " ok" : " ?"));
+ }
+ else
+ {
+ errln(i + " " + ids[i] + " " + dstOffset +
+ " " + fmtOffset + " *** FAIL ***");
+ }
+ }
+ }
+
+ // Test equals
+ public void TestEquals()
+ {
+ DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
+
+ DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
+
+ if (!fmtA.equals(fmtB)) {
+ errln("FAIL");
+ }
+ }
+
+ // Check out some specific parsing problem
+ @SuppressWarnings("deprecation")
+ public void TestTwoDigitYearDSTParse()
+ {
+ SimpleDateFormat fullFmt =
+ new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
+
+ //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL,
+ // Locale.ENGLISH);
+ SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z",
+ Locale.ENGLISH);
+ //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47);
+ //logln(fmt.format(date)); // This shows what the current locale format is
+ //logln(((SimpleDateFormat)fmt).toPattern());
+ TimeZone save = TimeZone.getDefault();
+ TimeZone PST = TimeZone.getTimeZone("PST");
+ String s = "03-Apr-04 2:20:47 o'clock AM PST";
+ int hour = 2;
+ try {
+ TimeZone.setDefault(PST);
+ Date d = fmt.parse(s);
+ logln(s + " P> " + fullFmt.format(d));
+ if (d.getHours() != hour) {
+ errln("FAIL: Should parse to hour " + hour);
+ }
+ }
+ catch (ParseException e) { errln("FAIL: " + e.getMessage()); }
+ finally {
+ TimeZone.setDefault(save);
+ }
+ }
+
+ static String escape(String s)
+ {
+ StringBuilder buf = new StringBuilder();
+ for (int i=0; i<s.length(); ++i)
+ {
+ char c = s.charAt(i);
+ if (c <= (char)0x7F) {
+ buf.append(c);
+ } else {
+ buf.append("\\u");
+ buf.append(Integer.toHexString((c & 0xF000) >> 12));
+ buf.append(Integer.toHexString((c & 0x0F00) >> 8));
+ buf.append(Integer.toHexString((c & 0x00F0) >> 4));
+ buf.append(Integer.toHexString(c & 0x000F));
+ }
+ }
+ return buf.toString();
+ }
+
+ // Test field position return values
+ static String fieldNames[] = {
+ "ERA_FIELD", "YEAR_FIELD", "MONTH_FIELD",
+ "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD",
+ "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD",
+ "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD",
+ "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD",
+ "MINUTE_FIELD", "SECOND_FIELD",
+ "MILLISECOND_FIELD", "TIMEZONE_FIELD",
+ };
+ static int fieldIDs[] = {
+ DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
+ DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD,
+ DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD,
+ DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD,
+ DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
+ DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD,
+ DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD,
+ };
+
+ /**
+ * Bug 4089987
+ */
+ public void TestFieldPosition()
+ {
+ DateFormat[] dateFormats = {
+ DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,
+ Locale.US),
+
+ DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE),
+ new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
+ new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
+ new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " +
+ "SSSS, EEEE, DDDD, " +
+ "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz")
+ };
+ String[] expected =
+ {
+ "", "1997", "August", "", "", "13", "", "Wednesday", "",
+ "PM", "", "2", "", "", "34", "12", "", "PDT",
+
+ "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "",
+ "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/,
+
+ "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM",
+ "2", "2", "14", "14", "34", "12", "513", "PDT",
+
+ "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM",
+ "2", "2", "14", "14", "34", "12", "513", "PDT",
+
+ "AD", "1997", "August", "0033", "0003", "0013", "0225",
+ "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014",
+ "0034", "0012", "0513", "Pacific Daylight Time",
+ };
+ Date someDate = new Date(871508052513L);
+ TimeZone PST = TimeZone.getTimeZone("PST");
+ for (int j = 0, exp = 0; j < dateFormats.length; ++j) {
+ DateFormat df = dateFormats[j];
+ if (!(df instanceof SimpleDateFormat)) {
+ continue;
+ }
+ df.setTimeZone(PST);
+ logln(" Pattern = " + ((SimpleDateFormat)df).toPattern());
+ logln(" Result = " + df.format(someDate));
+ for (int i = 0; i < fieldIDs.length; ++i)
+ {
+ String field = getFieldText(df, fieldIDs[i], someDate);
+ if (!field.equals(expected[exp])) {
+ errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" +
+ escape(field) + "\", expected \"" + escape(expected[exp]) + "\"");
+ }
+ ++exp;
+ }
+ }
+ }
+ // get the string value for the given field for the given date
+ static String getFieldText(DateFormat df, int field, Date date)
+ {
+ StringBuffer buffer = new StringBuffer();
+ FieldPosition pos = new FieldPosition(field);
+ df.format(date, buffer, pos);
+ return buffer.toString().substring(pos.getBeginIndex(),
+ pos.getEndIndex());
+ }
+
+ // Test parsing of partial strings
+ @SuppressWarnings("deprecation")
+ public void TestPartialParse994()
+ {
+ SimpleDateFormat f = new SimpleDateFormat();
+ Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1);
+ f.set2DigitYearStart(cal.getTime());
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42));
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
+ tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
+ }
+
+ void tryPat994(SimpleDateFormat format, String pat, String str, Date expected)
+ {
+ logln("Pattern \"" + pat + "\" String \"" + str + "\"");
+ try {
+ format.applyPattern(pat);
+ Date date = format.parse(str);
+ String f = format.format(date);
+ logln(" parse(" + str + ") -> " + date.toString());
+ logln(" format -> " + f);
+ if (expected == null ||
+ !date.equals(expected)) {
+ errln("FAIL: Expected " + expected);
+ }
+ if (!f.equals(str)) {
+ errln("FAIL: Expected " + str);
+ }
+ }
+ catch(ParseException e) {
+ logln("ParseException: " + e.getMessage());
+ if (expected != null) {
+ errln("FAIL: Expected " + expected);
+ }
+ }
+ catch(Exception e) {
+ errln("*** Exception:");
+ e.printStackTrace();
+ }
+ }
+
+ // Test pattern with runs things together
+ public void TestRunTogetherPattern985()
+ {
+ String format = "yyyyMMddHHmmssSSS";
+ String now, then;
+
+ SimpleDateFormat formatter = new SimpleDateFormat(format);
+
+ Date date1 = new Date();
+ now = formatter.format(date1);
+
+ logln(now);
+
+ ParsePosition pos = new ParsePosition(0);
+
+ Date date2 = formatter.parse(now, pos);
+ if (date2 == null) {
+ then = "Parse stopped at " + pos.getIndex();
+ } else {
+ then = formatter.format(date2);
+ }
+
+ logln(then);
+
+ if (!date2.equals(date1)) {
+ errln("FAIL");
+ }
+ }
+
+ // Test patterns which run numbers together
+ @SuppressWarnings("deprecation")
+ public void TestRunTogetherPattern917()
+ {
+ SimpleDateFormat fmt;
+ String myDate;
+
+ fmt = new SimpleDateFormat( "yyyy/MM/dd" );
+ myDate = "1997/02/03";
+ _testIt917( fmt, myDate, new Date(97, 2-1, 3) );
+
+ fmt = new SimpleDateFormat( "yyyyMMdd" );
+ myDate = "19970304";
+ _testIt917( fmt, myDate, new Date(97, 3-1, 4) );
+
+ }
+ void _testIt917( SimpleDateFormat fmt, String str, Date expected )
+ {
+ logln( "pattern=" + fmt.toPattern() + " string=" + str );
+
+ Object o;
+ try {
+ o = fmt.parseObject( str );
+ } catch( ParseException e ) {
+ e.printStackTrace();
+ return;
+ }
+ logln( "Parsed object: " + o );
+ if (!o.equals(expected)) {
+ errln("FAIL: Expected " + expected);
+ }
+
+ String formatted = fmt.format( o );
+ logln( "Formatted string: " + formatted );
+ if (!formatted.equals(str)) {
+ errln("FAIL: Expected " + str);
+ }
+ }
+
+ // Test Czech month formatting -- this can cause a problem because the June and
+ // July month names share a common prefix.
+ @SuppressWarnings("deprecation")
+ public void TestCzechMonths459()
+ {
+ // Use Czech, which has month names with shared prefixes for June and July
+ DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, new Locale("cs", "", ""));
+ //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy");
+ logln("Pattern " + ((SimpleDateFormat)fmt).toPattern());
+
+ Date june = new Date(97, Calendar.JUNE, 15);
+ Date july = new Date(97, Calendar.JULY, 15);
+
+ String juneStr = fmt.format(june);
+ String julyStr = fmt.format(july);
+
+ try {
+ logln("format(June 15 1997) = " + juneStr);
+ Date d = fmt.parse(juneStr);
+ String s = fmt.format(d);
+ int month = d.getMonth();
+ logln(" -> parse -> " + s + " (month = " + month + ")");
+ if (month != JUNE) {
+ errln("FAIL: Month should be June");
+ }
+
+ logln("format(July 15 1997) = " + julyStr);
+ d = fmt.parse(julyStr);
+ s = fmt.format(d);
+ month = d.getMonth();
+ logln(" -> parse -> " + s + " (month = " + month + ")");
+ if (month != JULY) {
+ errln("FAIL: Month should be July");
+ }
+ }
+ catch (ParseException e) {
+ errln("Exception: " + e);
+ }
+ }
+
+ // Test big D (day of year) versus little d (day of month)
+ @SuppressWarnings("deprecation")
+ public void TestLetterDPattern212()
+ {
+ String dateString = "1995-040.05:01:29";
+ String bigD = "yyyy-DDD.hh:mm:ss";
+ String littleD = "yyyy-ddd.hh:mm:ss";
+ Date expLittleD = new Date(95, 0, 1, 5, 1, 29);
+ Date expBigD = new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days
+ expLittleD = expBigD; // Expect the same, with default lenient parsing
+ logln( "dateString= " + dateString );
+ SimpleDateFormat formatter = new SimpleDateFormat(bigD);
+ ParsePosition pos = new ParsePosition(0);
+ Date myDate = formatter.parse( dateString, pos );
+ logln("Using " + bigD + " -> " + myDate);
+ if (myDate.getTime() != expBigD.getTime()) {
+ errln("FAIL: Expected " + expBigD + " got " + myDate);
+ }
+
+ formatter = new SimpleDateFormat(littleD);
+ pos = new ParsePosition(0);
+ myDate = formatter.parse( dateString, pos );
+ logln("Using " + littleD + " -> " + myDate);
+ if (myDate.getTime() != expLittleD.getTime()) {
+ errln("FAIL: Expected " + expLittleD + " got " + myDate);
+ }
+ }
+
+ // Test the 'G' day of year pattern
+ @SuppressWarnings("deprecation")
+ public void TestDayOfYearPattern195()
+ {
+ Date today = new Date();
+ Date expected = new Date(today.getYear(), today.getMonth(), today.getDate());
+
+ logln("Test Date: " + today);
+
+ SimpleDateFormat sdf =
+ (SimpleDateFormat)SimpleDateFormat.getDateInstance();
+
+ tryPattern(sdf, today, null, expected);
+ tryPattern(sdf, today, "G yyyy DDD", expected);
+ }
+
+ void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected)
+ {
+ if (pattern != null) {
+ sdf.applyPattern(pattern);
+ }
+ logln("pattern: " + sdf.toPattern());
+
+ String formatResult = sdf.format(d);
+ logln(" format -> " + formatResult);
+ try {
+ Date d2 = sdf.parse(formatResult);
+ logln(" parse(" + formatResult + ") -> " + d2);
+ if (d2.getTime() != expected.getTime()) {
+ errln("FAIL: Expected " + expected);
+ }
+ String format2 = sdf.format(d2);
+ logln(" format -> " + format2);
+ if (!formatResult.equals(format2)) {
+ errln("FAIL: Round trip drift");
+ }
+ }
+ catch(Exception e) {
+ errln("Error: " + e.getMessage());
+ }
+ }
+
+ // Test a pattern with single quotes
+ @SuppressWarnings("deprecation")
+ public void TestQuotePattern161()
+ {
+ // This pattern used to end in " zzz" but that makes this test zone-dependent
+ SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz");
+ Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28);
+ String dateString = formatter.format(currentTime_1);
+ String exp = "08/13/1997 at 10:42:28 AM ";
+ logln("format(" + currentTime_1 + ") = " + dateString);
+ if (!dateString.regionMatches(0, exp, 0, exp.length())) {
+ errln("FAIL: Expected " + exp);
+ }
+ }
+
+ // Test the parsing of bad input strings
+ /** Demonstrates a number of bugs in DateFormat.parse(String) where
+ * either StringIndexOutOfBoundsException is thrown or null is
+ * returned instead of ParseException. To reproduce, run this program
+ * and notice all the "SHOULD NOT HAPPEN" errors. Note also that the
+ * 1 line that should be correct is off by 100 years. (In this day
+ * and age, no one would assume that 1/1/00 is Jan 1 1900.)
+ **/
+ public void TestBadInput135()
+ {
+ int looks[] = { DateFormat.SHORT, DateFormat.MEDIUM,
+ DateFormat.LONG, DateFormat.FULL };
+ String strings[] = { "Mar 15", "Mar 15 1997", "asdf",
+ "3/1/97 1:23:", "3/1/00 1:23:45 AM" };
+ DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG,
+ DateFormat.LONG);
+ String expected = "March 1, 2000 1:23:45 AM ";
+ for ( int i = 0; i < strings.length; ++i ){
+ String text = strings[i];
+ for ( int j = 0; j < looks.length; ++j ){
+ int dateLook = looks[j];
+ for ( int k = 0; k < looks.length; ++k ){
+ int timeLook = looks[k];
+ DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook);
+ String prefix = text + ", " + dateLook + "/" + timeLook + ": ";
+ try {
+ Date when = df.parse(text);
+ if ( when == null ){
+ errln(prefix +
+ "SHOULD NOT HAPPEN: parse returned null.");
+ continue;
+ }
+ String format = full.format(when);
+ logln(prefix + "OK: " + format);
+ // Only match the start -- not the zone, which could vary
+ if (!format.regionMatches(0, expected, 0, expected.length())) {
+ errln("FAIL: Expected " + expected);
+ }
+ }
+ catch ( ParseException e ){
+ //errln(prefix + e); // This is expected.
+ }
+ catch ( StringIndexOutOfBoundsException e ){
+ errln(prefix + "SHOULD NOT HAPPEN: " + e);
+ }
+ }
+ }
+ }
+ }
+
+ final private static String parseFormats[] =
+ {
+ "MMMM d, yyyy", // january 1, 1970 or jan 1, 1970
+ "MMMM d yyyy", // january 1 1970 or jan 1 1970
+ "M/d/yy", // 1/1/70
+ "d MMMM, yyyy", // 1 january, 1970 or 1 jan, 1970
+ "d MMMM yyyy", // 1 january 1970 or 1 jan 1970
+ "d MMMM", // 1 january or 1 jan
+ "MMMM d", // january 1 or jan 1
+ "yyyy", // 1970
+ "h:mm a MMMM d, yyyy" // Date and Time
+ };
+ final private static String inputStrings[] =
+ {
+ "bogus string", null, null, null, null, null, null, null, null, null,
+ "April 1, 1997", "April 1, 1997", null, null, null, null, null, "April 1", null, null,
+ "Jan 1, 1970", "January 1, 1970", null, null, null, null, null, "January 1", null, null,
+ "Jan 1 2037", null, "January 1 2037", null, null, null, null, "January 1", null, null,
+ "1/1/70", null, null, "1/1/70", null, null, null, null, "0001", null,
+ "5 May 1997", null, null, null, null, "5 May 1997", "5 May", null, "0005", null,
+ "16 May", null, null, null, null, null, "16 May", null, "0016", null,
+ "April 30", null, null, null, null, null, null, "April 30", null, null,
+ "1998", null, null, null, null, null, null, null, "1998", null,
+ "1", null, null, null, null, null, null, null, "0001", null, // Bug620
+ "3:00 pm Jan 1, 1997", null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997",
+ };
+ // More testing of the parsing of bad input
+ @SuppressWarnings("UnusedAssignment")
+ public void TestBadInput135a()
+ {
+ SimpleDateFormat dateParse = new SimpleDateFormat();
+ String s;
+ Date date;
+ int PFLENGTH = parseFormats.length;
+
+ dateParse.applyPattern("d MMMM, yyyy");
+ dateParse.setTimeZone(TimeZone.getDefault());
+ s = "not parseable";
+ logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
+ try {
+ date = dateParse.parse(s);
+ errln("FAIL: Expected exception during parse");
+ } catch (Exception ex) {
+ logln("Exception during parse: " + ex); // This is expected
+ }
+
+ for (int i=0; i<inputStrings.length; i += (PFLENGTH+1))
+ {
+ ParsePosition parsePosition = new ParsePosition(0);
+ s = inputStrings[i];
+
+ for (int index=0; index<PFLENGTH; ++index)
+ {
+ String expected = inputStrings[i + 1 + index];
+ dateParse.applyPattern(parseFormats[index]);
+ dateParse.setTimeZone(TimeZone.getDefault());
+ // logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
+ try {
+ parsePosition.setIndex(0);
+ date = dateParse.parse(s, parsePosition);
+ if (parsePosition.getIndex() != 0) {
+ if (date == null) {
+ errln("ERROR: null result with pos " +
+ parsePosition.getIndex() + " " +
+ s.substring(0, parsePosition.getIndex()) + "|" +
+ s.substring(parsePosition.getIndex()));
+ } else {
+ String result = dateParse.format(date);
+ logln("Parsed \"" + s + "\" using \"" + dateParse.toPattern() +
+ "\" to: " + result);
+ if (expected == null) {
+ errln("FAIL: Expected parse failure");
+ } else if (!expected.equals(result)) {
+ errln("FAIL: Expected " + expected);
+ }
+ }
+ } else {
+ // logln("Not parsed.");
+ if (expected != null) {
+ errln("FAIL: Expected " + expected);
+ }
+ }
+ } catch (Exception ex) {
+ errln("An exception was thrown during parse: " + ex);
+ }
+ }
+ }
+ }
+
+ // Test the handling of 2-digit dates
+ public void TestTwoDigitYear() {
+ SimpleDateFormat fmt = new SimpleDateFormat("M/d/yy");
+
+ // find out the expected 2-digit year values for "6/5/17" and "6/4/34"
+ long start = fmt.get2DigitYearStart().getTime();
+ Calendar cal = new Calendar.Builder().setInstant(start).build();
+ int startYear = cal.get(YEAR);
+ cal.add(YEAR, 100);
+ long end = cal.getTimeInMillis();
+ int endYear = cal.get(YEAR);
+ int xx17 = 0, xx34 = 0;
+ for (int year = startYear; year <= endYear; year++) {
+ int yy = year % 100;
+ if (yy == 17 && xx17 == 0) {
+ xx17 = yearValue(start, end, year, JUNE, 5);
+ } else if (yy == 34 && xx34 == 0) {
+ xx34 = yearValue(start, end, year, JUNE, 4);
+ }
+ if (xx17 != 0 && xx34 != 0) {
+ break;
+ }
+ }
+ if (xx17 == 0 || xx34 == 0) {
+ errln("Failed: producing expected values: 2DigitYearStart: " + new Date(start)
+ + ", xx17 = " + xx17 + ", xx34 = " + xx34);
+ }
+ logln("2DigitYearStart: " + new Date(start) + ", xx17 = " + xx17 + ", xx34 = " + xx34);
+
+ parse2DigitYear(fmt, "6/5/17", new GregorianCalendar(xx17, JUNE, 5).getTime());
+ parse2DigitYear(fmt, "6/4/34", new GregorianCalendar(xx34, JUNE, 4).getTime());
+ }
+
+ private int yearValue(long start, long end, int year, int month, int dayOfMonth) {
+ Calendar cal = new GregorianCalendar(year, month, dayOfMonth);
+ long time = cal.getTimeInMillis();
+ return (start <= time && time < end) ? year : 0;
+ }
+
+ private void parse2DigitYear(SimpleDateFormat fmt, String str, Date expected) {
+ try {
+ Date d = fmt.parse(str);
+ logln("Parsing \"" + str + "\" with " +
+ fmt.toPattern() +
+ " => " + d.toString());
+ if (d.getTime() != expected.getTime()) {
+ errln("FAIL: Expected " + expected);
+ }
+ } catch (ParseException e) {
+ errln("FAIL: Got exception");
+ }
+ }
+
+ // Test behavior of DateFormat with applied time zone
+ public void TestDateFormatZone061()
+ {
+ Date date;
+ DateFormat formatter;
+
+ // 25-Mar-97 00:00:00 GMT
+ date = new Date( 859248000000L );
+ logln( "Date 1997/3/25 00:00 GMT: " + date );
+ formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK);
+ formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
+
+ String temp = formatter.format( date );
+ logln( "Formatted in GMT to: " + temp );
+
+ /* Parse date string */
+ try {
+ Date tempDate = formatter.parse( temp );
+ logln( "Parsed to: " + tempDate );
+ if (tempDate.getTime() != date.getTime()) {
+ errln("FAIL: Expected " + date);
+ }
+ }
+ catch( Throwable t ) {
+ errln( "Date Formatter throws: " +
+ t.toString() );
+ }
+ }
+
+ // Make sure DateFormat uses the correct zone.
+ public void TestDateFormatZone146()
+ {
+ TimeZone saveDefault = TimeZone.getDefault();
+
+ try {
+ TimeZone thedefault = TimeZone.getTimeZone("GMT");
+ TimeZone.setDefault(thedefault);
+ // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
+
+ // check to be sure... its GMT all right
+ TimeZone testdefault = TimeZone.getDefault();
+ String testtimezone = testdefault.getID();
+ if (testtimezone.equals("GMT")) {
+ logln("Test timezone = " + testtimezone);
+ } else {
+ errln("Test timezone should be GMT, not " + testtimezone);
+ }
+
+ // now try to use the default GMT time zone
+ GregorianCalendar greenwichcalendar =
+ new GregorianCalendar(1997, 3, 4, 23, 0);
+ //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
+ //greenwichcalendar.set(1997, 3, 4, 23, 0);
+ // try anything to set hour to 23:00 !!!
+ greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23);
+ // get time
+ Date greenwichdate = greenwichcalendar.getTime();
+ // format every way
+ String[] DATA = {
+ "simple format: ", "04/04/97 23:00 GMT",
+ "MM/dd/yy HH:mm z",
+ "full format: ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT",
+ "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z",
+ "long format: ", "April 4, 1997 11:00:00 PM GMT",
+ "MMMM d, yyyy h:mm:ss a z",
+ "default format: ", "04-Apr-97 11:00:00 PM",
+ "dd-MMM-yy h:mm:ss a",
+ "short format: ", "4/4/97 11:00 PM",
+ "M/d/yy h:mm a",
+ };
+
+ for (int i=0; i<DATA.length; i+=3) {
+ DateFormat fmt = new SimpleDateFormat(DATA[i+2], Locale.ENGLISH);
+ fmt.setCalendar(greenwichcalendar);
+ String result = fmt.format(greenwichdate);
+ logln(DATA[i] + result);
+ if (!result.equals(DATA[i+1])) {
+ errln("FAIL: Expected " + DATA[i+1]
+ + ", got " + result);
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveDefault);
+ }
+ }
+
+/* HS : Commented out for now, need to be changed not to use hardcoded results.
+ public void TestLocaleDateFormat() // Bug 495
+ {
+ Date testDate = new Date (97, Calendar.SEPTEMBER, 15);
+ DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL, Locale.FRENCH);
+ DateFormat dfUS = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL, Locale.US);
+ String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 GMT-07:00";
+ String expectedUS = "Monday, September 15, 1997 12:00:00 o'clock AM PDT";
+ logln("Date set to : " + testDate);
+ String out = dfFrench.format(testDate);
+ logln("Date Formated with French Locale " + out);
+ if (!out.equals(expectedFRENCH)) errln("FAIL: Expected " + expectedFRENCH);
+ out = dfUS.format(testDate);
+ logln("Date Formated with US Locale " + out);
+ if (!out.equals(expectedUS)) errln("FAIL: Expected " + expectedUS);
+ }
+*/
+ /**
+ * Bug 4056591
+ */
+/*
+test commented out pending API-change approval
+ public void Test2YearStartDate() throws ParseException
+ {
+ // create a SimpleDateFormat to test with; dump out if it's not a SimpleDateFormat
+ DateFormat test = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
+
+ if (!(test instanceof SimpleDateFormat)) {
+ errln("DateFormat.getInstance() didn't return an instance of SimpleDateFormat!");
+ return;
+ }
+
+ SimpleDateFormat sdf = (SimpleDateFormat)test;
+ String testString1 = "3/10/67";
+ String testString2 = "3/16/43";
+ String testString3 = "7/21/43";
+
+ // set 2-digit start date to 1/1/1900
+ Calendar cal = Calendar.getInstance(Locale.US);
+ cal.set(1900, 0, 1);
+ sdf.set2DigitStartDate(cal.getTime());
+
+ // check to make sure get2DigitStartDate() returns the value we passed to
+ // set2DigitStartDate()
+ Date date = sdf.get2DigitStartDate();
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1900 || cal.get(Calendar.MONTH) != 0 ||
+ cal.get(Calendar.DATE) != 1)
+ errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
+ + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
+ " instead of 1/1/1900.");
+
+ // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1900
+ date = sdf.parse(testString1);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1967)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1967.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/10.");
+ date = sdf.parse(testString2);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1943)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1943.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/16.");
+
+ // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/2000
+ cal.set(2000, 0, 1);
+ sdf.set2DigitStartDate(cal.getTime());
+ date = sdf.parse(testString1);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 2067)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 2067.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/10.");
+ date = sdf.parse(testString2);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 2043)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1943.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/16.");
+
+ // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1950
+ cal.set(1950, 0, 1);
+ sdf.set2DigitStartDate(cal.getTime());
+ date = sdf.parse(testString1);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1967)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1967.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
+ errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/10.");
+ date = sdf.parse(testString2);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 2043)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1943.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/16.");
+
+ // try parsing "3/16/43" and "7/21/43" with the 2-digit start date set to 6/1/1943
+ cal.set(1943, 5, 1);
+ sdf.set2DigitStartDate(cal.getTime());
+ date = sdf.parse(testString2);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 2043)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 2043.");
+ if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
+ errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 3/16.");
+ date = sdf.parse(testString3);
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1943)
+ errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
+ + cal.get(Calendar.YEAR) + " instead of 1943.");
+ if (cal.get(Calendar.MONTH) != 6 || cal.get(Calendar.DATE) != 21)
+ errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 failed: got " +
+ (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
+ " instead of 7/21.");
+
+ // and finally, check one more time to make sure get2DigitStartDate() returns the last
+ // value we passed to set2DigitStartDate()
+ date = sdf.get2DigitStartDate();
+ cal.setTime(date);
+ if (cal.get(Calendar.YEAR) != 1943 || cal.get(Calendar.MONTH) != 5 ||
+ cal.get(Calendar.DATE) != 1)
+ errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
+ + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
+ " instead of 6/1/1943.");
+ }
+*/
+
+ /**
+ * ParsePosition.errorIndex tests.
+ */
+ @SuppressWarnings("deprecation")
+ public void Test4052223()
+ {
+ String str = "7/SOS/2001";
+ Date exp = new Date(101, Calendar.SEPTEMBER, 7);
+ String pat = "d/MMM/yy";
+ SimpleDateFormat sdf = new SimpleDateFormat(pat);
+ ParsePosition pos = new ParsePosition(0);
+ Date d = sdf.parse(str, pos);
+ logln(str + " parses with " + pat + " to " + d);
+ if (d == null && pos.getErrorIndex() == 2) {
+ logln("Expected null returned, failed at : " + pos.getErrorIndex());
+ } else {
+ errln("Failed, parse " + str + " got : " + d + ", index=" + pos.getErrorIndex());
+ }
+ }
+
+ /**
+ * Bug4469904 -- th_TH date format doesn't use Thai B.E.
+ */
+ public void TestBuddhistEraBugId4469904() {
+ String era = "\u0e1e.\u0e28.";
+ Locale loc = new Locale("th", "TH");
+ Calendar cal = Calendar.getInstance(Locale.US);
+ cal.set(2001, 7, 23);
+ Date date = cal.getTime();
+ DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, loc);
+ String output = df.format(date);
+ int index = output.indexOf(era);
+ if (index == -1) {
+ errln("Test4469904: Failed. Buddhist Era abbrev not present.");
+ }
+ }
+
+ /**
+ * 4326988: API: SimpleDateFormat throws NullPointerException when parsing with null pattern
+ */
+ @SuppressWarnings("UnusedAssignment")
+ public void Test4326988() {
+ String[] wrongPatterns = {
+ "hh o''clock",
+ "hh 'o''clock", // unterminated quote
+ "''''''''''''oclock",
+ "efgxyz",
+ };
+ String[] goodPatterns = {
+ "hh 'o''clock'",
+ "'''''''''''''o'",
+ "'efgxyz'",
+ ":;,.-",
+ };
+
+ // Check NullPointerException
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat(null);
+ errln("SimpleDateFormat() doesn't throw NPE with null pattern");
+ } catch (NullPointerException e) {
+ // Okay
+ }
+ try {
+ Locale loc = null;
+ SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", loc);
+ errln("SimpleDateFormat() doesn't throw NPE with null locale");
+ } catch (NullPointerException e) {
+ // Okay
+ }
+ try {
+ DateFormatSymbols symbols = null;
+ SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", symbols);
+ errln("SimpleDateFormat() doesn't throw NPE with null DateFormatSymbols");
+ } catch (NullPointerException e) {
+ // Okay
+ }
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat();
+ fmt.applyPattern(null);
+ errln("applyPattern() doesn't throw NPE with null pattern");
+ } catch (NullPointerException e) {
+ // Okay
+ }
+
+ // Check IllegalParameterException
+ for (int i = 0; i < wrongPatterns.length; i++) {
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i]);
+ errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\")" +
+ " doesn't throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Okay
+ }
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
+ DateFormatSymbols.getInstance());
+ errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\", DateFormatSymbols) doesn't " +
+ "throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Okay
+ }
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
+ Locale.US);
+ errln("SimpleDateFormat(\"" + wrongPatterns[i] +
+ "\", Locale) doesn't throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Okay
+ }
+ try {
+ SimpleDateFormat fmt = new SimpleDateFormat();
+ fmt.applyPattern(wrongPatterns[i]);
+ errln("SimpleDateFormat.applyPattern(\"" + wrongPatterns[i] +
+ "\") doesn't throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Okay
+ }
+ }
+
+ for (int i = 0; i < goodPatterns.length; i++) {
+ SimpleDateFormat fmt;
+ fmt = new SimpleDateFormat(goodPatterns[i]);
+ fmt = new SimpleDateFormat(goodPatterns[i],
+ DateFormatSymbols.getInstance());
+ fmt = new SimpleDateFormat(goodPatterns[i],
+ Locale.US);
+ fmt = new SimpleDateFormat();
+ fmt.applyPattern(goodPatterns[i]);
+ }
+ }
+
+ /**
+ * 4486735: RFE: SimpleDateFormat performance improvement
+ *
+ * Another round trip test
+ */
+ @SuppressWarnings("deprecation")
+ public void Test4486735() throws Exception {
+ TimeZone initialTimeZone = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Locale[] locales = Locale.getAvailableLocales();
+ String[] zones = { "GMT", "America/Los_Angeles", "Europe/London", "Asia/Tokyo" };
+
+ // Round to minutes. Some FULL formats don't have seconds.
+ long time = System.currentTimeMillis()/60000 * 60000;
+ Date date = new Date(time);
+ logln("the test date: " + date);
+
+ try {
+ for (int z = 0; z < zones.length; z++) {
+ TimeZone.setDefault(TimeZone.getTimeZone(zones[z]));
+ for (int i = 0; i < locales.length; i++) {
+ Locale loc = locales[i];
+ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL,
+ loc);
+ String s = df.format(date);
+ logln(s);
+ Date parsedDate = df.parse(s);
+ long parsedTime = parsedDate.getTime();
+ if (time != parsedTime) {
+ // See if the time is in daylight-standard time transition. (JDK-8140571)
+ // Date-time formats in some locales don't have time zone information.
+ TimeZone tz = TimeZone.getDefault();
+ if (tz.inDaylightTime(date) && !tz.inDaylightTime(parsedDate)) {
+ if (time == parsedTime - tz.getDSTSavings()) {
+ // OK (in "fall-back")
+ continue;
+ }
+ }
+ errln("round trip conversion failed: timezone="+zones[z]+
+ ", locale=" + loc +
+ ", expected=" + time + ", got=" + parsedTime);
+ }
+ }
+ }
+
+ // Long format test
+ String pat =
+ "'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // 100
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // 200
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // 300
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // 400
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + // 500
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593':'" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + // 100
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + // 200
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" +
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy" + // 300
+ "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\u5e74";
+
+ // Note that >4 y's produces just "2001" until 1.3.1. This
+ // was fixed in 1.4.
+ String expected =
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
+ "00000000000000000000000000000000000000000000000000" +
+ "00000000000000000000000000000000000000000000000000" +
+ "00000000000000000000000000000000000000000000000000" +
+ "00000000000000000000000000000000000000000000000000" +
+ "00000000000000000000000000000000000000000000000000" +
+ "00000000000000000000000000000000000000000000002001\u5e74";
+ SimpleDateFormat sdf = new SimpleDateFormat(pat);
+ String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1));
+ if (!expected.equals(s)) {
+ errln("wrong format result: expected="+expected+", got="+s);
+ }
+ Date longday = sdf.parse(s);
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(longday);
+ if (cal.get(YEAR) != 2001) {
+ errln("wrong parse result: expected=2001, got=" + cal.get(YEAR));
+ }
+ } catch (Exception e) {
+ throw e;
+ } finally {
+ // Restore the initial time zone
+ TimeZone.setDefault(initialTimeZone);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/IntlTestDateFormat.java b/test/java/text/Format/DateFormat/IntlTestDateFormat.java
new file mode 100644
index 0000000000..bc37d4f7fb
--- /dev/null
+++ b/test/java/text/Format/DateFormat/IntlTestDateFormat.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @summary test International Date Format
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat
+ * @key randomness
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormat extends IntlTest {
+ // Values in milliseconds (== Date)
+ private static final long ONESECOND = 1000;
+ private static final long ONEMINUTE = 60 * ONESECOND;
+ private static final long ONEHOUR = 60 * ONEMINUTE;
+ private static final long ONEDAY = 24 * ONEHOUR;
+ private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate
+
+ // EModes
+ private static final byte GENERIC = 0;
+ private static final byte TIME = GENERIC + 1;
+ private static final byte DATE = TIME + 1;
+ private static final byte DATE_TIME = DATE + 1;
+
+ private DateFormat fFormat = DateFormat.getInstance();
+ private String fTestName = new String("getInstance");
+ private int fLimit = 3; // How many iterations it should take to reach convergence
+
+ public static void main(String[] args) throws Exception {
+ new IntlTestDateFormat().run(args);
+ }
+
+ public void TestLocale() {
+ localeTest(Locale.getDefault(), "Default Locale");
+ }
+
+ // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat.
+ public void localeTest(final Locale locale, final String localeName) {
+ int timeStyle, dateStyle;
+
+ // For patterns including only time information and a timezone, it may take
+ // up to three iterations, since the timezone may shift as the year number
+ // is determined. For other patterns, 2 iterations should suffice.
+ fLimit = 3;
+
+ for(timeStyle = 0; timeStyle < 4; timeStyle++) {
+ fTestName = new String("Time test " + timeStyle + " (" + localeName + ")");
+ try {
+ fFormat = DateFormat.getTimeInstance(timeStyle, locale);
+ }
+ catch(StringIndexOutOfBoundsException e) {
+ errln("FAIL: localeTest time getTimeInstance exception");
+ throw e;
+ }
+ TestFormat();
+ }
+
+ fLimit = 2;
+
+ for(dateStyle = 0; dateStyle < 4; dateStyle++) {
+ fTestName = new String("Date test " + dateStyle + " (" + localeName + ")");
+ try {
+ fFormat = DateFormat.getDateInstance(dateStyle, locale);
+ }
+ catch(StringIndexOutOfBoundsException e) {
+ errln("FAIL: localeTest date getTimeInstance exception");
+ throw e;
+ }
+ TestFormat();
+ }
+
+ for(dateStyle = 0; dateStyle < 4; dateStyle++) {
+ for(timeStyle = 0; timeStyle < 4; timeStyle++) {
+ fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")");
+ try {
+ fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
+ }
+ catch(StringIndexOutOfBoundsException e) {
+ errln("FAIL: localeTest date/time getDateTimeInstance exception");
+ throw e;
+ }
+ TestFormat();
+ }
+ }
+ }
+
+ public void TestFormat() {
+ if (fFormat == null) {
+ errln("FAIL: DateFormat creation failed");
+ return;
+ }
+ // logln("TestFormat: " + fTestName);
+ Date now = new Date();
+ tryDate(new Date(0));
+ tryDate(new Date((long) 1278161801778.0));
+ tryDate(now);
+ // Shift 6 months into the future, AT THE SAME TIME OF DAY.
+ // This will test the DST handling.
+ tryDate(new Date(now.getTime() + 6*30*ONEDAY));
+
+ Date limit = new Date(now.getTime() * 10); // Arbitrary limit
+ for (int i=0; i<2; ++i)
+ // tryDate(new Date(floor(randDouble() * limit)));
+ tryDate(new Date((long) (randDouble() * limit.getTime())));
+ }
+
+ private void describeTest() {
+ if (fFormat == null) {
+ errln("FAIL: no DateFormat");
+ return;
+ }
+
+ // Assume it's a SimpleDateFormat and get some info
+ SimpleDateFormat s = (SimpleDateFormat) fFormat;
+ logln(fTestName + " Pattern " + s.toPattern());
+ }
+
+ private void tryDate(Date theDate) {
+ final int DEPTH = 10;
+ Date[] date = new Date[DEPTH];
+ StringBuffer[] string = new StringBuffer[DEPTH];
+
+ int dateMatch = 0;
+ int stringMatch = 0;
+ boolean dump = false;
+ int i;
+ for (i=0; i<DEPTH; ++i) string[i] = new StringBuffer();
+ for (i=0; i<DEPTH; ++i) {
+ if (i == 0) date[i] = theDate;
+ else {
+ try {
+ date[i] = fFormat.parse(string[i-1].toString());
+ }
+ catch (ParseException e) {
+ describeTest();
+ errln("********** FAIL: Parse of " + string[i-1] + " failed.");
+ dump = true;
+ break;
+ }
+ }
+ FieldPosition position = new FieldPosition(0);
+ fFormat.format(date[i], string[i], position);
+ if (i > 0) {
+ if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i;
+ else if (dateMatch > 0 && date[i] != date[i-1]) {
+ describeTest();
+ errln("********** FAIL: Date mismatch after match.");
+ dump = true;
+ break;
+ }
+ if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
+ else if (stringMatch > 0 && string[i] != string[i-1]) {
+ describeTest();
+ errln("********** FAIL: String mismatch after match.");
+ dump = true;
+ break;
+ }
+ }
+ if (dateMatch > 0 && stringMatch > 0) break;
+ }
+ if (i == DEPTH) --i;
+
+ if (stringMatch > fLimit || dateMatch > fLimit) {
+ describeTest();
+ errln("********** FAIL: No string and/or date match within " + fLimit + " iterations.");
+ dump = true;
+ }
+
+ if (dump) {
+ for (int k=0; k<=i; ++k) {
+ logln("" + k + ": " + date[k] + " F> " + string[k] + " P> ");
+ }
+ }
+ }
+
+ // Return a random double from 0.01 to 1, inclusive
+ private double randDouble() {
+ // Assume 8-bit (or larger) rand values. Also assume
+ // that the system rand() function is very poor, which it always is.
+ // double d;
+ // int i;
+ // do {
+ // for (i=0; i < sizeof(double); ++i)
+ // {
+ // char poke = (char*)&d;
+ // poke[i] = (rand() & 0xFF);
+ // }
+ // } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d));
+
+ // if (d < 0.0) d = -d;
+ // if (d > 0.0)
+ // {
+ // double e = floor(log10(d));
+ // if (e < -2.0) d *= pow(10.0, -e-2);
+ // else if (e > -1.0) d /= pow(10.0, e+1);
+ // }
+ // return d;
+ Random rand = new Random();
+ return rand.nextDouble();
+ }
+
+ public void TestAvailableLocales() {
+ final Locale[] locales = DateFormat.getAvailableLocales();
+ long count = locales.length;
+ logln("" + count + " available locales");
+ if (locales != null && count != 0) {
+ StringBuffer all = new StringBuffer();
+ for (int i=0; i<count; ++i) {
+ if (i!=0) all.append(", ");
+ all.append(locales[i].getDisplayName());
+ }
+ logln(all.toString());
+ }
+ else errln("********** FAIL: Zero available locales or null array pointer");
+ }
+
+ /* This test is too slow; we disable it for now
+ public void TestMonster() {
+ final Locale[] locales = DateFormat.getAvailableLocales();
+ long count = locales.length;
+ if (locales != null && count != 0) {
+ for (int i=0; i<count; ++i) {
+ String name = locales[i].getDisplayName();
+ logln("Testing " + name + "...");
+ try {
+ localeTest(locales[i], name);
+ }
+ catch(Exception e) {
+ errln("FAIL: TestMonster localeTest exception" + e);
+ }
+ }
+ }
+ }
+ */
+}
+
+//eof
diff --git a/test/java/text/Format/DateFormat/IntlTestDateFormatAPI.java b/test/java/text/Format/DateFormat/IntlTestDateFormatAPI.java
new file mode 100644
index 0000000000..98f5429e70
--- /dev/null
+++ b/test/java/text/Format/DateFormat/IntlTestDateFormatAPI.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @summary test International Date Format API
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormatAPI
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormatAPI extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ new IntlTestDateFormatAPI().run(args);
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+
+ // Test that the equals method works correctly.
+ public void TestEquals()
+ {
+ // Create two objects at different system times
+ DateFormat a = DateFormat.getInstance();
+ Date start = Calendar.getInstance().getTime();
+ while (start.equals(Calendar.getInstance().getTime())) ; // Wait for time to change
+ DateFormat b = DateFormat.getInstance();
+
+ if (!(a.equals(b)))
+ errln("FAIL: DateFormat objects created at different times are unequal.");
+
+ if (b instanceof SimpleDateFormat)
+ {
+ double ONE_YEAR = 365*24*60*60*1000.0;
+ try {
+// ((SimpleDateFormat)b).setTwoDigitStartDate(start.getTime() + 50*ONE_YEAR);
+// if (a.equals(b))
+// errln("FAIL: DateFormat objects with different two digit start dates are equal.");
+ }
+ catch (Exception e) {
+ errln("FAIL: setTwoDigitStartDate failed.");
+ }
+ }
+ }
+
+ // This test checks various generic API methods in DateFormat to achieve 100% API coverage.
+ public void TestAPI()
+ {
+ logln("DateFormat API test---"); logln("");
+ Locale.setDefault(Locale.ENGLISH);
+
+
+ // ======= Test constructors
+
+ logln("Testing DateFormat constructors");
+
+ DateFormat def = DateFormat.getInstance();
+ DateFormat fr = DateFormat.getTimeInstance(DateFormat.FULL, Locale.FRENCH);
+ DateFormat it = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.ITALIAN);
+ DateFormat de = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.GERMAN);
+
+ // ======= Test equality
+
+ logln("Testing equality operator");
+
+ if( fr.equals(it) ) {
+ errln("ERROR: equals failed");
+ }
+
+ // ======= Test various format() methods
+
+ logln("Testing various format() methods");
+
+ Date d = new Date((long)837039928046.0);
+
+ StringBuffer res1 = new StringBuffer();
+ StringBuffer res2 = new StringBuffer();
+ String res3 = new String();
+ FieldPosition pos1 = new FieldPosition(0);
+ FieldPosition pos2 = new FieldPosition(0);
+
+ res1 = fr.format(d, res1, pos1);
+ logln("" + d.getTime() + " formatted to " + res1);
+
+ res2 = it.format(d, res2, pos2);
+ logln("" + d.getTime() + " formatted to " + res2);
+
+ res3 = de.format(d);
+ logln("" + d.getTime() + " formatted to " + res3);
+
+ // ======= Test parse()
+
+ logln("Testing parse()");
+
+ String text = new String("02/03/76 2:50 AM, CST");
+ Object result1 = new Date();
+ Date result2 = new Date();
+ Date result3 = new Date();
+ ParsePosition pos = new ParsePosition(0);
+ ParsePosition pos01 = new ParsePosition(0);
+
+ result1 = def.parseObject(text, pos);
+ if (result1 == null) {
+ errln("ERROR: parseObject() failed for " + text);
+ }
+ logln(text + " parsed into " + ((Date)result1).getTime());
+
+ try {
+ result2 = def.parse(text);
+ }
+ catch (ParseException e) {
+ errln("ERROR: parse() failed");
+ }
+ logln(text + " parsed into " + result2.getTime());
+
+ result3 = def.parse(text, pos01);
+ if (result3 == null) {
+ errln("ERROR: parse() failed for " + text);
+ }
+ logln(text + " parsed into " + result3.getTime());
+
+
+ // ======= Test getters and setters
+
+ logln("Testing getters and setters");
+
+ final Locale[] locales = DateFormat.getAvailableLocales();
+ long count = locales.length;
+ logln("Got " + count + " locales" );
+ for(int i = 0; i < count; i++) {
+ String name;
+ name = locales[i].getDisplayName();
+ logln(name);
+ }
+
+ fr.setLenient(it.isLenient());
+ if(fr.isLenient() != it.isLenient()) {
+ errln("ERROR: setLenient() failed");
+ }
+
+ final Calendar cal = def.getCalendar();
+ Calendar newCal = (Calendar) cal.clone();
+ de.setCalendar(newCal);
+ it.setCalendar(newCal);
+ if( ! de.getCalendar().equals(it.getCalendar())) {
+ errln("ERROR: set Calendar() failed");
+ }
+
+ final NumberFormat nf = def.getNumberFormat();
+ NumberFormat newNf = (NumberFormat) nf.clone();
+ de.setNumberFormat(newNf);
+ it.setNumberFormat(newNf);
+ if( ! de.getNumberFormat().equals(it.getNumberFormat())) {
+ errln("ERROR: set NumberFormat() failed");
+ }
+
+ final TimeZone tz = def.getTimeZone();
+ TimeZone newTz = (TimeZone) tz.clone();
+ de.setTimeZone(newTz);
+ it.setTimeZone(newTz);
+ if( ! de.getTimeZone().equals(it.getTimeZone())) {
+ errln("ERROR: set TimeZone() failed");
+ }
+
+ // ======= Test getStaticClassID()
+
+// logln("Testing instanceof()");
+
+// try {
+// DateFormat test = new SimpleDateFormat();
+
+// if (! (test instanceof SimpleDateFormat)) {
+// errln("ERROR: instanceof failed");
+// }
+// }
+// catch (Exception e) {
+// errln("ERROR: Couldn't create a DateFormat");
+// }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/IntlTestDateFormatSymbols.java b/test/java/text/Format/DateFormat/IntlTestDateFormatSymbols.java
new file mode 100644
index 0000000000..dcc30fa261
--- /dev/null
+++ b/test/java/text/Format/DateFormat/IntlTestDateFormatSymbols.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @library /java/text/testlib
+ * @summary test International Date Format Symbols
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDateFormatSymbols extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new IntlTestDateFormatSymbols().run(args);
+ }
+
+ // Test getMonths
+ public void TestGetMonths()
+ {
+ final String[] month;
+ DateFormatSymbols symbol;
+
+ symbol=new DateFormatSymbols(Locale.getDefault());
+
+ month=symbol.getMonths();
+ int cnt = month.length;
+
+ logln("size = " + cnt);
+
+ for (int i=0; i<cnt; ++i)
+ {
+ logln(month[i]);
+ }
+ }
+
+ // Test the API of DateFormatSymbols; primarily a simple get/set set.
+ public void TestSymbols()
+ {
+ DateFormatSymbols fr = new DateFormatSymbols(Locale.FRENCH);
+
+ DateFormatSymbols en = new DateFormatSymbols(Locale.ENGLISH);
+
+ if(en.equals(fr)) {
+ errln("ERROR: English DateFormatSymbols equal to French");
+ }
+
+ // just do some VERY basic tests to make sure that get/set work
+
+ long count;
+ final String[] eras = en.getEras();
+ fr.setEras(eras);
+ final String[] eras1 = fr.getEras();
+ count = eras.length;
+ if( count != eras1.length) {
+ errln("ERROR: setEras() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! eras[i].equals(eras1[i])) {
+ errln("ERROR: setEras() failed (different string values)");
+ }
+ }
+ }
+
+
+ final String[] months = en.getMonths();
+ fr.setMonths(months);
+ final String[] months1 = fr.getMonths();
+ count = months.length;
+ if( count != months1.length) {
+ errln("ERROR: setMonths() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! months[i].equals(months1[i])) {
+ errln("ERROR: setMonths() failed (different string values)");
+ }
+ }
+ }
+
+ final String[] shortMonths = en.getShortMonths();
+ fr.setShortMonths(shortMonths);
+ final String[] shortMonths1 = fr.getShortMonths();
+ count = shortMonths.length;
+ if( count != shortMonths1.length) {
+ errln("ERROR: setShortMonths() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! shortMonths[i].equals(shortMonths1[i])) {
+ errln("ERROR: setShortMonths() failed (different string values)");
+ }
+ }
+ }
+
+ final String[] weekdays = en.getWeekdays();
+ fr.setWeekdays(weekdays);
+ final String[] weekdays1 = fr.getWeekdays();
+ count = weekdays.length;
+ if( count != weekdays1.length) {
+ errln("ERROR: setWeekdays() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! weekdays[i].equals(weekdays1[i])) {
+ errln("ERROR: setWeekdays() failed (different string values)");
+ }
+ }
+ }
+
+ final String[] shortWeekdays = en.getShortWeekdays();
+ fr.setShortWeekdays(shortWeekdays);
+ final String[] shortWeekdays1 = fr.getShortWeekdays();
+ count = shortWeekdays.length;
+ if( count != shortWeekdays1.length) {
+ errln("ERROR: setShortWeekdays() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! shortWeekdays[i].equals(shortWeekdays1[i])) {
+ errln("ERROR: setShortWeekdays() failed (different string values)");
+ }
+ }
+ }
+
+ final String[] ampms = en.getAmPmStrings();
+ fr.setAmPmStrings(ampms);
+ final String[] ampms1 = fr.getAmPmStrings();
+ count = ampms.length;
+ if( count != ampms1.length) {
+ errln("ERROR: setAmPmStrings() failed (different size array)");
+ }
+ else {
+ for(int i = 0; i < count; i++) {
+ if(! ampms[i].equals(ampms1[i])) {
+ errln("ERROR: setAmPmStrings() failed (different string values)");
+ }
+ }
+ }
+
+ long rowCount = 0, columnCount = 0;
+ final String[][] strings = en.getZoneStrings();
+ fr.setZoneStrings(strings);
+ final String[][] strings1 = fr.getZoneStrings();
+ rowCount = strings.length;
+ for(int i = 0; i < rowCount; i++) {
+ columnCount = strings[i].length;
+ for(int j = 0; j < columnCount; j++) {
+ if( strings[i][j] != strings1[i][j] ) {
+ errln("ERROR: setZoneStrings() failed");
+ }
+ }
+ }
+
+// final String pattern = DateFormatSymbols.getPatternChars();
+
+ String localPattern, pat1, pat2;
+ localPattern = en.getLocalPatternChars();
+ fr.setLocalPatternChars(localPattern);
+ if(! en.getLocalPatternChars().equals(fr.getLocalPatternChars())) {
+ errln("ERROR: setLocalPatternChars() failed");
+ }
+
+
+ DateFormatSymbols foo = new DateFormatSymbols();
+
+ en = (DateFormatSymbols) fr.clone();
+
+ if(! en.equals(fr)) {
+ errln("ERROR: Clone failed");
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/IntlTestSimpleDateFormatAPI.java b/test/java/text/Format/DateFormat/IntlTestSimpleDateFormatAPI.java
new file mode 100644
index 0000000000..a1f578f7a6
--- /dev/null
+++ b/test/java/text/Format/DateFormat/IntlTestSimpleDateFormatAPI.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @summary test International Simple Date Format API
+ * @bug 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestSimpleDateFormatAPI
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestSimpleDateFormatAPI extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ new IntlTestSimpleDateFormatAPI().run(args);
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+
+ // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+ public void TestAPI()
+ {
+ logln("SimpleDateFormat API test---"); logln("");
+
+ Locale.setDefault(Locale.ENGLISH);
+
+ // ======= Test constructors
+
+ logln("Testing SimpleDateFormat constructors");
+
+ SimpleDateFormat def = new SimpleDateFormat();
+
+ final String pattern = new String("yyyy.MM.dd G 'at' hh:mm:ss z");
+ SimpleDateFormat pat = new SimpleDateFormat(pattern);
+
+ SimpleDateFormat pat_fr = new SimpleDateFormat(pattern, Locale.FRENCH);
+
+ DateFormatSymbols symbols = new DateFormatSymbols(Locale.FRENCH);
+
+ SimpleDateFormat cust1 = new SimpleDateFormat(pattern, symbols);
+
+ // ======= Test clone() and equality
+
+ logln("Testing clone(), assignment and equality operators");
+
+ Format clone = (Format) def.clone();
+ if( ! clone.equals(def) ) {
+ errln("ERROR: Format clone or equals failed");
+ }
+
+ // ======= Test various format() methods
+
+ logln("Testing various format() methods");
+
+ Date d = new Date((long)837039928046.0);
+
+ StringBuffer res1 = new StringBuffer();
+ StringBuffer res2 = new StringBuffer();
+ FieldPosition pos1 = new FieldPosition(0);
+ FieldPosition pos2 = new FieldPosition(0);
+
+ res1 = def.format(d, res1, pos1);
+ logln( "" + d.getTime() + " formatted to " + res1);
+
+ res2 = cust1.format(d, res2, pos2);
+ logln("" + d.getTime() + " formatted to " + res2);
+
+ // ======= Test parse()
+
+ logln("Testing parse()");
+
+ String text = new String("02/03/76 2:50 AM, CST");
+ Date result1 = new Date();
+ Date result2 = new Date();
+ ParsePosition pos= new ParsePosition(0);
+ result1 = def.parse(text, pos);
+ logln(text + " parsed into " + result1);
+
+ try {
+ result2 = def.parse(text);
+ }
+ catch (ParseException e) {
+ errln("ERROR: parse() failed");
+ }
+ logln(text + " parsed into " + result2);
+
+ // ======= Test getters and setters
+
+ logln("Testing getters and setters");
+
+ final DateFormatSymbols syms = pat.getDateFormatSymbols();
+ def.setDateFormatSymbols(syms);
+ pat_fr.setDateFormatSymbols(syms);
+ if( ! pat.getDateFormatSymbols().equals(def.getDateFormatSymbols()) ) {
+ errln("ERROR: set DateFormatSymbols() failed");
+ }
+
+ Date startDate = null;
+ try {
+// startDate = pat.getTwoDigitStartDate();
+ }
+ catch (Exception e) {
+ errln("ERROR: getTwoDigitStartDate() failed");
+ }
+
+ try {
+// pat_fr.setTwoDigitStartDate(startDate);
+ }
+ catch (Exception e) {
+ errln("ERROR: setTwoDigitStartDate() failed");
+ }
+
+ // ======= Test applyPattern()
+
+ logln("Testing applyPattern()");
+
+ String p1 = new String("yyyy.MM.dd G 'at' hh:mm:ss z");
+ logln("Applying pattern " + p1);
+ pat.applyPattern(p1);
+
+ String s2 = pat.toPattern();
+ logln("Extracted pattern is " + s2);
+ if( ! s2.equals(p1) ) {
+ errln("ERROR: toPattern() result did not match pattern applied");
+ }
+
+ logln("Applying pattern " + p1);
+ pat.applyLocalizedPattern(p1);
+ String s3 = pat.toLocalizedPattern();
+ logln("Extracted pattern is " + s3);
+ if( ! s3.equals(p1) ) {
+ errln("ERROR: toLocalizedPattern() result did not match pattern applied");
+ }
+
+ // ======= Test getStaticClassID()
+
+// logln("Testing instanceof");
+
+// try {
+// DateFormat test = new SimpleDateFormat();
+
+// if (! (test instanceof SimpleDateFormat)) {
+// errln("ERROR: instanceof failed");
+// }
+// }
+// catch (Exception e) {
+// errln("ERROR: Couldn't create a SimpleDateFormat");
+// }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/NonGregorianFormatTest.java b/test/java/text/Format/DateFormat/NonGregorianFormatTest.java
new file mode 100644
index 0000000000..69808d4764
--- /dev/null
+++ b/test/java/text/Format/DateFormat/NonGregorianFormatTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4833268 6253991 8008577
+ * @summary Test formatting and parsing with non-Gregorian calendars
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NonGregorianFormatTest
+ */
+
+import java.util.*;
+import java.text.*;
+import static java.util.Calendar.*;
+
+public class NonGregorianFormatTest {
+ static int errors;
+
+ static final Object[][] JAPANESE_EN = {
+ { "GGGG yyyy MMMM d", "Showa 1 December 31", new Date(1926-1900, DECEMBER, 31) },
+ { "GGGG yyyy MMMM d", "Showa 64 January 6", new Date(1989-1900, JANUARY, 6) },
+ { "GGGG yyyy MMMM d", "Heisei 1 August 9", new Date(1989-1900, AUGUST, 9) },
+ { "GGGG yyyy MMMM d", "Heisei 17 June 10", new Date(2005-1900, JUNE, 10) },
+ { "Gy.MM.dd", "S1.12.31", new Date(1926-1900, DECEMBER, 31) },
+ { "Gy.MM.dd", "S64.01.06", new Date(1989-1900, JANUARY, 6) },
+ { "Gyy.MM.dd", "H01.08.09", new Date(1989-1900, AUGUST, 9) },
+ { "Gy.M.d", "H1.8.9", new Date(1989-1900, AUGUST, 9) },
+ { "Gy.MM.dd", "H17.06.10", new Date(2005-1900, JUNE, 10) },
+ };
+
+ // Invalid dates for parse exception tests
+ static final Object[][] EXCEPTION_JAPANESE_EN = {
+ { "GGGG yyyy MMMM d", "Showa 1 December 10" },
+ { "GGGG yyyy MMMM d", "Showa 64 January 16" },
+ { "GGGG yyyy MMMM d", "Heisei 1 January 1" },
+ { "Gy.MM.dd", "S1.12.10" },
+ { "Gy.MM.dd", "S64.01.16" },
+ { "Gyy.MM.dd", "H01.01.01" },
+ };
+
+ static final Object[][] BUDDHIST_EN = {
+ { "GGGG yyyy MMMM d", "B.E. 2469 December 31", new Date(1926-1900, DECEMBER, 31) },
+ { "GGGG yyyy MMMM d", "B.E. 2532 January 6", new Date(1989-1900, JANUARY, 6) },
+ { "GGGG yyyy MMMM d", "B.E. 2532 August 8", new Date(1989-1900, AUGUST, 8) },
+ { "GGGG yyyy MMMM d", "B.E. 2548 June 10", new Date(2005-1900, JUNE, 10) },
+ { "Gyyyy/MM/dd", "B.E.2469/12/31", new Date(1926-1900, DECEMBER, 31) },
+ { "Gyyyy/MM/dd", "B.E.2532/01/06", new Date(1989-1900, JANUARY, 6) },
+ { "Gyyyy/MM/dd", "B.E.2532/08/09", new Date(1989-1900, AUGUST, 9) },
+ { "Gyyyy/MM/dd", "B.E.2548/06/10", new Date(2005-1900, JUNE, 10) },
+ };
+
+ static final String FULL_DATE_FORMAT_JA = "GGGGyyyy'\u5e74'M'\u6708'd'\u65e5'";
+
+ static final Object[][] JAPANESE_JA = {
+ { FULL_DATE_FORMAT_JA, "\u662d\u548c\u5143\u5e7412\u670831\u65e5", new Date(1926-1900, DECEMBER, 31) },
+ { FULL_DATE_FORMAT_JA, "\u662d\u548c64\u5e741\u67086\u65e5", new Date(1989-1900, JANUARY, 6) },
+ { FULL_DATE_FORMAT_JA, "\u5e73\u6210\u5143\u5e748\u67089\u65e5", new Date(1989-1900, AUGUST, 9) },
+ { FULL_DATE_FORMAT_JA, "\u5e73\u621017\u5e746\u670810\u65e5", new Date(2005-1900, JUNE, 10) },
+ { "Gyy.MM.dd", "S01.12.31", new Date(1926-1900, DECEMBER, 31) },
+ { "Gyy.MM.dd", "S64.01.06", new Date(1989-1900, JANUARY, 6) },
+ { "Gyy.MM.dd", "H01.08.09", new Date(1989-1900, AUGUST, 9) },
+ { "Gy.M.d", "H1.8.9", new Date(1989-1900, AUGUST, 9) },
+ { "Gyy.MM.dd", "H17.06.10", new Date(2005-1900, JUNE, 10) },
+ };
+
+ // Invalid dates for parse exception tests
+ static final Object[][] EXCEPTION_JAPANESE_JA = {
+ { FULL_DATE_FORMAT_JA, "\u662d\u548c\u5143\u5e7412\u670810\u65e5" },
+ { FULL_DATE_FORMAT_JA, "\u662d\u548c64\u5e741\u670816\u65e5" },
+ { FULL_DATE_FORMAT_JA, "\u5e73\u6210\u5143\u5e741\u67081\u65e5" },
+ { "Gyy.MM.dd", "S01.12.10" },
+ { "Gyy.MM.dd", "S64.01.16" },
+ { "Gyy.MM.dd", "H01.01.01" },
+ };
+
+ static final Object[][] BUDDHIST_JA = {
+ { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62469\u5e7412\u670831\u65e5", new Date(1926-1900, DECEMBER, 31) },
+ { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62532\u5e741\u67086\u65e5", new Date(1989-1900, JANUARY, 6) },
+ { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62532\u5e748\u67089\u65e5", new Date(1989-1900, AUGUST, 9) },
+ { FULL_DATE_FORMAT_JA, "\u4ecf\u66a62548\u5e746\u670810\u65e5", new Date(2005-1900, JUNE, 10) },
+ { "Gyyyy/MM/dd", "B.E.2469/12/31", new Date(1926-1900, DECEMBER, 31) },
+ { "Gyyyy/MM/dd", "B.E.2532/01/06", new Date(1989-1900, JANUARY, 6) },
+ { "Gyyyy/MM/dd", "B.E.2532/08/09", new Date(1989-1900, AUGUST, 9) },
+ { "Gyyyy/MM/dd", "B.E.2548/06/10", new Date(2005-1900, JUNE, 10) },
+ };
+
+ public static void main(String[] args) throws ParseException {
+ Locale defaultLocale = Locale.getDefault();
+ Locale[] locales = { Locale.ENGLISH, Locale.JAPAN };
+ try {
+ for (Locale locale : locales) {
+ test(locale);
+ }
+ } finally {
+ Locale.setDefault(defaultLocale);
+ }
+ if (errors > 0) {
+ throw new RuntimeException("FAILED: " + errors + " error(s)");
+ }
+ }
+
+ private static void test(Locale locale) {
+ Locale.setDefault(locale);
+
+ // Tests with the Japanese imperial calendar
+ Locale calendarLocale = new Locale("ja", "JP", "JP");
+ testRoundTrip(calendarLocale);
+ testRoundTripSimple(calendarLocale,
+ locale == Locale.ENGLISH ? JAPANESE_EN : JAPANESE_JA);
+ testParseExceptions(calendarLocale,
+ locale == Locale.ENGLISH ? EXCEPTION_JAPANESE_EN : EXCEPTION_JAPANESE_JA);
+
+ // Tests with the Thai Buddhist calendar
+ calendarLocale = new Locale("th", "TH");
+ testRoundTrip(calendarLocale);
+ testRoundTripSimple(calendarLocale,
+ locale == Locale.ENGLISH ? BUDDHIST_EN : BUDDHIST_JA);
+ }
+
+ private static void testRoundTrip(Locale calendarLocale) {
+ DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
+ DateFormat.FULL,
+ calendarLocale);
+
+ long t = System.currentTimeMillis();
+ t = (t / 1000) * 1000; // discard milliseconds
+ testRoundTrip(df, new Date(t));
+
+ // H1.8.9
+ testRoundTrip(df, new Date(1989-1900, AUGUST, 9));
+
+ // H17.6.13
+ testRoundTrip(df, new Date(2005-1900, JUNE, 13));
+ }
+
+ private static void testRoundTrip(DateFormat df, Date orig) {
+ try {
+ String s = df.format(orig);
+ Date parsed = df.parse(s);
+ if (!orig.equals(parsed)) {
+ error("testRoundTrip: bad date: origianl: '%s', parsed '%s'%n", orig, parsed);
+ }
+ } catch (Exception e) {
+ error("Unexpected exception: %s%n", e);
+ }
+ }
+
+ private static void testRoundTripSimple(Locale calendarLocale, Object[][] data) {
+ try {
+ for (Object[] item : data) {
+ String pattern = (String) item[0];
+ String str = (String) item[1];
+ Date date = (Date) item[2];
+ SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+ Calendar cal = Calendar.getInstance(calendarLocale);
+ sdf.setCalendar(cal);
+ String s = sdf.format(date);
+ if (!s.equals(str)) {
+ error("testRoundTripSimple: Got '%s', expected '%s'%n", s, str);
+ }
+ Date d = sdf.parse(str);
+ if (!d.equals(date)) {
+ error("testRoundTripSimple: Got '%s', expected '%s'%n", d, date);
+ }
+ }
+ } catch (Exception e) {
+ error("Unexpected exception: %s%n", e);
+ }
+ }
+
+ private static void testParseExceptions(Locale calendarLocale, Object[][] data) {
+ for (Object[] item : data) {
+ String pattern = (String) item[0];
+ String str = (String) item[1];
+ SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+ Calendar cal = Calendar.getInstance(calendarLocale);
+ sdf.setCalendar(cal);
+ sdf.setLenient(false);
+ try {
+ Date d = sdf.parse(str);
+ error("testParseExceptions: parsing '%s' doesn't throw a ParseException.%n", str);
+ } catch (ParseException e) {
+ // OK
+ }
+ }
+ }
+
+ private static void error(String msg) {
+ System.out.println(msg);
+ errors++;
+ }
+
+ private static void error(String fmt, Object... args) {
+ System.out.printf(fmt, args);
+ errors++;
+ }
+}
diff --git a/test/java/text/Format/DateFormat/SDFserialized.ser.txt b/test/java/text/Format/DateFormat/SDFserialized.ser.txt
new file mode 100644
index 0000000000..c0ddced4fa
--- /dev/null
+++ b/test/java/text/Format/DateFormat/SDFserialized.ser.txt
@@ -0,0 +1,173 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a serialized DateFormatSymbols for
+# DateFormatSymbolsSerializationTest.
+
+aced00057372001a6a6176612e746578742e53696d706c6544617465466f726d
+61744243c9da9394359002000449001573657269616c56657273696f6e4f6e53
+747265616d4c001364656661756c7443656e7475727953746172747400104c6a
+6176612f7574696c2f446174653b4c000a666f726d61744461746174001d4c6a
+6176612f746578742f44617465466f726d617453796d626f6c733b4c00077061
+747465726e7400124c6a6176612f6c616e672f537472696e673b787200146a61
+76612e746578742e44617465466f726d6174642ca1e4c22615fc0200024c0008
+63616c656e6461727400144c6a6176612f7574696c2f43616c656e6461723b4c
+000c6e756d626572466f726d61747400184c6a6176612f746578742f4e756d62
+6572466f726d61743b787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f184302000078707372001b6a6176612e7574696c2e477265676f726961
+6e43616c656e6461728f3dd7d6e5b0d0c10200014a0010677265676f7269616e
+4375746f766572787200126a6176612e7574696c2e43616c656e646172e6ea4d
+1ec8dc5b8e03000b5a000c6172654669656c647353657449000e666972737444
+61794f665765656b5a0009697354696d655365745a00076c656e69656e744900
+166d696e696d616c44617973496e46697273745765656b4900096e6578745374
+616d7049001573657269616c56657273696f6e4f6e53747265616d4a00047469
+6d655b00066669656c64737400025b495b000569735365747400025b5a4c0004
+7a6f6e657400144c6a6176612f7574696c2f54696d655a6f6e653b7870010000
+000101010000000100000002000000010000000000000000757200025b494dba
+602676eab2a502000078700000001100000001000007b2000000000000000100
+0000010000000100000001000000050000000100000000000000000000000000
+00000000000000000000000000000000000000757200025b5a578f203914b85d
+e20200007870000000110101010101010101010101010101010101737200186a
+6176612e7574696c2e53696d706c6554696d655a6f6e65fa675d60d15ef5a603
+001049000a647374536176696e6773490006656e6444617949000c656e644461
+794f665765656b490007656e644d6f6465490008656e644d6f6e746849000765
+6e6454696d654900097261774f666673657449001573657269616c5665727369
+6f6e4f6e53747265616d490008737461727444617949000e7374617274446179
+4f665765656b49000973746172744d6f646549000a73746172744d6f6e746849
+0009737461727454696d654900097374617274596561725a000b757365446179
+6c696768745b000b6d6f6e74684c656e6774687400025b42787200126a617661
+2e7574696c2e54696d655a6f6e6531b3e9f57744aca10200014c000249447100
+7e00037870740003474d540036ee800000000000000000000000000000000000
+0000000000000000000001000000000000000000000000000000000000000000
+00000000757200025b42acf317f8060854e002000078700000000c1f1c1f1e1f
+1e1f1f1e1f1e1f770800000004000000007878fffff4e2f964ac00737200176a
+6176612e746578742e446563696d616c466f726d61740bff0362d872303a0200
+0b5a001b646563696d616c536570617261746f72416c7761797353686f776e42
+000c67726f7570696e6753697a654200116d696e4578706f6e656e7444696769
+747349000a6d756c7469706c69657249001573657269616c56657273696f6e4f
+6e53747265616d5a00167573654578706f6e656e7469616c4e6f746174696f6e
+4c000e6e6567617469766550726566697871007e00034c000e6e656761746976
+6553756666697871007e00034c000e706f73697469766550726566697871007e
+00034c000e706f73697469766553756666697871007e00034c000773796d626f
+6c737400204c6a6176612f746578742f446563696d616c466f726d617453796d
+626f6c733b787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000701032800000003000000
+2800010000000000000001000000000178010300000000010000000100740001
+2d74000071007e001f71007e001f7372001e6a6176612e746578742e44656369
+6d616c466f726d617453796d626f6c73501d17990868939c02000f4300106465
+63696d616c536570617261746f72430005646967697443000b6578706f6e656e
+7469616c43001167726f7570696e67536570617261746f724300096d696e7573
+5369676e4300116d6f6e6574617279536570617261746f724300107061747465
+726e536570617261746f724300077065724d696c6c43000770657263656e7449
+001573657269616c56657273696f6e4f6e53747265616d4300097a65726f4469
+6769744c00034e614e71007e00034c000e63757272656e637953796d626f6c71
+007e00034c0008696e66696e69747971007e00034c0012696e746c4375727265
+6e637953796d626f6c71007e00037870002e00230045002c002d002e003b2030
+0025000000010030740003efbfbd740002c2a4740003e2889e74000358585800
+0000017372000e6a6176612e7574696c2e44617465686a81014b597419030000
+78707708fffffe8f24e5cdd7787372001b6a6176612e746578742e4461746546
+6f726d617453796d626f6c73ace671c9351717c20200085b0005616d706d7374
+00135b4c6a6176612f6c616e672f537472696e673b5b00046572617371007e00
+294c00116c6f63616c5061747465726e436861727371007e00035b00066d6f6e
+74687371007e00295b000b73686f72744d6f6e74687371007e00295b000d7368
+6f72745765656b6461797371007e00295b00087765656b6461797371007e0029
+5b000b7a6f6e65537472696e67737400145b5b4c6a6176612f6c616e672f5374
+72696e673b7870757200135b4c6a6176612e6c616e672e537472696e673badd2
+56e7e91d7b47020000787000000002740002414d740002504d7571007e002c00
+0000027400024243740002414474001247794d646b486d735345444677576168
+4b7a7571007e002c0000000d7400074a616e7561727974000846656272756172
+797400054d61726368740005417072696c7400034d61797400044a756e657400
+044a756c7974000641756775737474000953657074656d6265727400074f6374
+6f6265727400084e6f76656d626572740008446563656d62657271007e001f75
+71007e002c0000000d7400034a616e7400034665627400034d61727400034170
+7271007e00397400034a756e7400034a756c7400034175677400035365707400
+034f63747400034e6f7674000344656371007e001f7571007e002c0000000871
+007e001f74000353756e7400034d6f6e74000354756574000357656474000354
+68757400034672697400035361747571007e002c0000000871007e001f740006
+53756e6461797400064d6f6e646179740007547565736461797400095765646e
+6573646179740008546875727364617974000646726964617974000853617475
+72646179757200145b5b4c6a6176612e6c616e672e537472696e673b324d09ad
+8432e45702000078700000001d7571007e002c00000005740003505354740015
+50616369666963205374616e646172642054696d6571007e0060740015506163
+69666963204461796c696768742054696d657400035044547571007e002c0000
+0005740013416d65726963612f4c6f735f416e67656c657371007e006171007e
+006071007e006271007e00637571007e002c000000057400034d53547400164d
+6f756e7461696e205374616e646172642054696d6571007e00677400164d6f75
+6e7461696e204461796c696768742054696d657400034d44547571007e002c00
+00000574000e416d65726963612f44656e76657271007e006871007e00677100
+7e006971007e006a7571007e002c00000005740003504e5471007e006871007e
+006771007e006871007e00677571007e002c0000000574000f416d6572696361
+2f50686f656e697871007e006871007e006771007e006871007e00677571007e
+002c0000000574000343535474001543656e7472616c205374616e6461726420
+54696d6571007e007274001543656e7472616c204461796c696768742054696d
+657400034344547571007e002c0000000574000f416d65726963612f43686963
+61676f71007e007371007e007271007e007471007e00757571007e002c000000
+057400034553547400154561737465726e205374616e646172642054696d6571
+007e00797400154561737465726e204461796c696768742054696d6574000345
+44547571007e002c00000005740010416d65726963612f4e65775f596f726b71
+007e007a71007e007971007e007b71007e007c7571007e002c00000005740003
+49455471007e007a71007e007971007e007a71007e00797571007e002c000000
+05740014416d65726963612f496e6469616e61706f6c697371007e007a71007e
+007971007e007a71007e00797571007e002c0000000574000348535474001448
+6177616969205374616e646172642054696d6571007e008471007e008571007e
+00847571007e002c00000005740010506163696669632f486f6e6f6c756c7571
+007e008571007e008471007e008571007e00847571007e002c00000005740003
+415354740014416c61736b61205374616e646172642054696d65740004414b53
+54740014416c61736b61204461796c696768742054696d65740004414b445475
+71007e002c00000005740011416d65726963612f416e63686f7261676571007e
+008a71007e008b71007e008c71007e008d7571007e002c0000000574000f416d
+65726963612f48616c6966617874001641746c616e746963205374616e646172
+642054696d6571007e008974001641746c616e746963204461796c6967687420
+54696d657400034144547571007e002c00000005740003434e5474001a4e6577
+666f756e646c616e64205374616e646172642054696d657400034e535474001a
+4e6577666f756e646c616e64204461796c696768742054696d657400034e4454
+7571007e002c00000005740010416d65726963612f53745f4a6f686e7371007e
+009771007e009871007e009971007e009a7571007e002c000000057400034543
+5474001e43656e7472616c204575726f7065616e205374616e64617264205469
+6d6574000343455474001e43656e7472616c204575726f7065616e204461796c
+696768742054696d65740004434553547571007e002c0000000574000c457572
+6f70652f506172697371007e009f71007e00a071007e00a171007e00a2757100
+7e002c0000000571007e0017740013477265656e77696368204d65616e205469
+6d6571007e001771007e00a671007e00177571007e002c000000057400114166
+726963612f43617361626c616e636171007e00a671007e001771007e00a67100
+7e00177571007e002c0000000574000e417369612f4a65727573616c656d7400
+1449737261656c205374616e646172642054696d657400034953547400144973
+7261656c204461796c696768742054696d657400034944547571007e002c0000
+00057400034a53547400134a6170616e205374616e646172642054696d657100
+7e00b071007e00b171007e00b07571007e002c0000000574000a417369612f54
+6f6b796f71007e00b171007e00b071007e00b171007e00b07571007e002c0000
+00057400104575726f70652f42756368617265737474001e4561737465726e20
+4575726f7065616e205374616e646172642054696d6574000345455474001e45
+61737465726e204575726f7065616e204461796c696768742054696d65740004
+454553547571007e002c000000057400034354547400134368696e6120537461
+6e646172642054696d6571007e007271007e00bc71007e00757571007e002c00
+00000574000d417369612f5368616e6768616971007e00bc71007e007271007e
+00bc71007e0075740019797979792e4d4d2e646420452068682e6d6d2e737320
+7a7a7a0a
diff --git a/test/java/text/Format/DateFormat/TimeZoneNameTest.java b/test/java/text/Format/DateFormat/TimeZoneNameTest.java
new file mode 100644
index 0000000000..9975672c80
--- /dev/null
+++ b/test/java/text/Format/DateFormat/TimeZoneNameTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000, 2016, 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 4348864 4112924 4425386 4495052 4836940 4851113 8008577
+ * @summary test time zone display names in en_US locale
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneNameTest
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class TimeZoneNameTest extends IntlTest
+{
+ static final String[] data = {
+ // Added to verify the fix for 4836940
+ "N", "Antarctica/Rothera", "ROTT", "Rothera Time", "ROTT", "Rothera Time",
+ "N", "Asia/Tehran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time",
+ "N", "Iran", "IRST", "Iran Standard Time", "IRDT", "Iran Daylight Time",
+
+ // Added to verify the fix for 4851113
+ "N", "America/Rankin_Inlet", "CST", "Central Standard Time", "CDT", "Central Daylight Time",
+ "N", "Asia/Samarkand", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time",
+ "N", "Asia/Tashkent", "UZT", "Uzbekistan Time", "UZT", "Uzbekistan Time",
+ "N", "Atlantic/Jan_Mayen", "CET", "Central European Time", "CEST", "Central European Summer Time",
+ "N", "Europe/Oslo", "CET", "Central European Time", "CEST", "Central European Summer Time",
+
+ "N", "Pacific/Honolulu", "HST", "Hawaii Standard Time", "HST", "Hawaii Standard Time",
+ "N", "America/Los_Angeles", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time",
+ "N", "US/Pacific", "PST", "Pacific Standard Time", "PDT", "Pacific Daylight Time",
+ "N", "America/Phoenix", "MST", "Mountain Standard Time", "MST", "Mountain Standard Time",
+ "N", "America/Denver", "MST", "Mountain Standard Time", "MDT", "Mountain Daylight Time",
+ "N", "America/Chicago", "CST", "Central Standard Time", "CDT", "Central Daylight Time",
+ "N", "America/Indianapolis", "EST", "Eastern Standard Time", "EST", "Eastern Standard Time",
+ "N", "America/Montreal", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+ "N", "America/Toronto", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+ "N", "America/New_York", "EST", "Eastern Standard Time", "EDT", "Eastern Daylight Time",
+ "S", "America/Manaus", "AMT", "Amazon Time", "AMT", "Amazon Time",
+ "S", "America/Campo_Grande", "AMT", "Amazon Time", "AMST", "Amazon Summer Time",
+ "S", "America/Bahia", "BRT", "Brasilia Time", "BRST", "Brasilia Summer Time",
+ "N", "America/Halifax", "AST", "Atlantic Standard Time", "ADT", "Atlantic Daylight Time",
+ "N", "GMT", "GMT", "Greenwich Mean Time", "GMT", "Greenwich Mean Time",
+ "N", "Europe/London", "GMT", "Greenwich Mean Time", "BST", "British Summer Time",
+ "N", "Europe/Paris", "CET", "Central European Time", "CEST", "Central European Summer Time",
+ "N", "WET", "WET", "Western European Time", "WEST", "Western European Summer Time",
+ "N", "Europe/Berlin", "CET", "Central European Time", "CEST", "Central European Summer Time",
+ "N", "Asia/Jerusalem", "IST", "Israel Standard Time", "IDT", "Israel Daylight Time",
+ "N", "Europe/Helsinki", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time",
+ "N", "Africa/Cairo", "EET", "Eastern European Time", "EEST", "Eastern European Summer Time",
+ "N", "Europe/Moscow", "MSK", "Moscow Standard Time", "MSD", "Moscow Daylight Time",
+ "N", "Asia/Omsk", "OMST", "Omsk Time", "OMSST", "Omsk Summer Time",
+ "N", "Asia/Shanghai", "CST", "China Standard Time", "CST", "China Standard Time",
+ "N", "Asia/Tokyo", "JST", "Japan Standard Time", "JST", "Japan Standard Time",
+ "N", "Japan", "JST", "Japan Standard Time", "JST", "Japan Standard Time",
+ "N", "Asia/Seoul", "KST", "Korea Standard Time", "KST", "Korea Standard Time",
+ "N", "ROK", "KST", "Korea Standard Time", "KST", "Korea Standard Time",
+ "S", "Australia/Darwin", "ACST", "Australian Central Standard Time (Northern Territory)",
+ "ACST", "Australian Central Standard Time (Northern Territory)",
+ "S", "Australia/Adelaide", "ACST", "Australian Central Standard Time (South Australia)",
+ "ACDT", "Australian Central Daylight Time (South Australia)",
+ "S", "Australia/Broken_Hill", "ACST", "Australian Central Standard Time (South Australia/New South Wales)",
+ "ACDT", "Australian Central Daylight Time (South Australia/New South Wales)",
+ "S", "Australia/Hobart", "AEST", "Australian Eastern Standard Time (Tasmania)",
+ "AEDT", "Australian Eastern Daylight Time (Tasmania)",
+ "S", "Australia/Brisbane", "AEST", "Australian Eastern Standard Time (Queensland)",
+ "AEST", "Australian Eastern Standard Time (Queensland)",
+ "S", "Australia/Sydney", "AEST", "Australian Eastern Standard Time (New South Wales)",
+ "AEDT", "Australian Eastern Daylight Time (New South Wales)",
+ "N", "Pacific/Guam", "ChST", "Chamorro Standard Time",
+ "ChST", "Chamorro Standard Time",
+ "N", "Pacific/Saipan", "ChST", "Chamorro Standard Time",
+ "ChST", "Chamorro Standard Time",
+ };
+
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ new TimeZoneNameTest().run(args);
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+
+ public void Test4112924() {
+ SimpleDateFormat lfmt = new SimpleDateFormat("zzzz");
+ SimpleDateFormat sfmt = new SimpleDateFormat("z");
+
+ GregorianCalendar june = new GregorianCalendar(2000, Calendar.JUNE, 21);
+ GregorianCalendar december = new GregorianCalendar(2000, Calendar.DECEMBER, 21);
+
+ int count = data.length;
+ for (int i = 0; i < count; i++) {
+ GregorianCalendar sol1, sol2;
+
+ // check hemisphere
+ if ("N".equals(data[i++])) {
+ sol1 = december;
+ sol2 = june;
+ } else {
+ sol1 = june;
+ sol2 = december;
+ }
+
+ TimeZone tz = TimeZone.getTimeZone(data[i++]);
+ lfmt.setTimeZone(tz);
+ sfmt.setTimeZone(tz);
+
+ logln(tz.getID() + ": " + sfmt.format(sol1.getTime()) + ", " + lfmt.format(sol1.getTime()));
+ logln(tz.getID() + ": " + sfmt.format(sol2.getTime()) + ", " + lfmt.format(sol2.getTime()));
+ String s = sfmt.format(sol1.getTime());
+ if (!data[i].equals(s)) {
+ errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")");
+ }
+ s = lfmt.format(sol1.getTime());
+ if (!data[++i].equals(s)) {
+ errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")");
+ }
+ s = sfmt.format(sol2.getTime());
+ if (!data[++i].equals(s)) {
+ errln(tz.getID() + ": wrong short name: \"" + s + "\" (expected \"" + data[i] + "\")");
+ }
+ s = lfmt.format(sol2.getTime());
+ if (!data[++i].equals(s)) {
+ errln(tz.getID() + ": wrong long name: \"" + s + "\" (expected \"" + data[i] + "\")");
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug4097450.java b/test/java/text/Format/DateFormat/bug4097450.java
new file mode 100644
index 0000000000..c70194bd87
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug4097450.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4097450
+ */
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+
+public class bug4097450
+{
+ public static void main(String args[])
+ {
+ //
+ // Date parse requiring 4 digit year.
+ //
+ String[] dstring = {"97","1997", "97","1997","01","2001", "01","2001"
+ , "1",
+ "1","11", "11","111", "111"};
+ String[] dformat = {"yy", "yy","yyyy","yyyy","yy", "yy","yyyy","yyyy"
+ ,
+ "yy","yyyy","yy","yyyy", "yy","yyyy"};
+ boolean[] dresult = {true, false, false, true,true, false, false, true
+ ,false,
+ false,true, false,false, false};
+ SimpleDateFormat formatter;
+ SimpleDateFormat resultFormatter = new SimpleDateFormat("yyyy");
+
+ System.out.println("Format\tSource\tResult");
+ System.out.println("-------\t-------\t-------");
+ for (int i = 0; i < dstring.length; i++)
+ {
+ System.out.print(dformat[i] + "\t" + dstring[i] + "\t");
+ formatter = new SimpleDateFormat(dformat[i]);
+ try {
+ System.out.print(resultFormatter.format(formatter.parse(dstring[
+ i])));
+ //if ( !dresult[i] ) System.out.print(" <-- error!");
+ }
+ catch (ParseException exception) {
+ //if ( dresult[i] ) System.out.print(" <-- error!");
+ System.out.print("exception --> " + exception);
+ }
+ System.out.println();
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug4099975.java b/test/java/text/Format/DateFormat/bug4099975.java
new file mode 100644
index 0000000000..812b4996c0
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug4099975.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4099975
+ */
+
+import java.text.*;
+import java.util.Date;
+public class bug4099975 {
+ public static void main (String args[]){
+ DateFormatSymbols symbols = new DateFormatSymbols();
+ SimpleDateFormat df = new SimpleDateFormat("E hh:mm", symbols);
+ System.out.println(df.toLocalizedPattern());
+ symbols.setLocalPatternChars("abcdefghijklmonpqr"); // change value of field
+ System.out.println(df.toLocalizedPattern());
+
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug4117335.java b/test/java/text/Format/DateFormat/bug4117335.java
new file mode 100644
index 0000000000..6c9af2a471
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug4117335.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4117335 4432617
+ */
+
+import java.text.DateFormatSymbols ;
+import java.util.Locale;
+
+public class bug4117335 {
+
+ public static void main(String[] args) throws Exception
+ {
+ DateFormatSymbols symbols = new DateFormatSymbols(Locale.JAPAN);
+ String[] eras = symbols.getEras();
+ System.out.println("BC = " + eras[0]);
+ if (!eras[0].equals(bc)) {
+ System.out.println("*** Should have been " + bc);
+ throw new Exception("Error in BC");
+ }
+ System.out.println("AD = " + eras[1]);
+ if (!eras[1].equals(ad)) {
+ System.out.println("*** Should have been " + ad);
+ throw new Exception("Error in AD");
+ }
+ String[][] zones = symbols.getZoneStrings();
+ for (int i = 0; i < zones.length; i++) {
+ if (!"Asia/Tokyo".equals(zones[i][0])) {
+ continue;
+ }
+ System.out.println("Long zone name = " + zones[i][1]);
+ if (!zones[i][1].equals(jstLong)) {
+ System.out.println("*** Should have been " + jstLong);
+ throw new Exception("Error in long TZ name");
+ }
+ System.out.println("Short zone name = " + zones[i][2]);
+ if (!zones[i][2].equals(jstShort)) {
+ System.out.println("*** Should have been " + jstShort);
+ throw new Exception("Error in short TZ name");
+ }
+ System.out.println("Long zone name = " + zones[i][3]);
+ if (!zones[i][3].equals(jdtLong)) {
+ System.out.println("*** Should have been " + jdtLong);
+ throw new Exception("Error in long TZ name");
+ }
+ System.out.println("SHORT zone name = " + zones[i][4]);
+ if (!zones[i][4].equals(jdtShort)) {
+ System.out.println("*** Should have been " + jdtShort);
+ throw new Exception("Error in short TZ name");
+ }
+ }
+ }
+
+ static final String bc = "\u7d00\u5143\u524d";
+ static final String ad = "\u897f\u66a6";
+ static final String jstLong = "\u65e5\u672c\u6a19\u6e96\u6642";
+ static final String jstShort = "JST";
+ static final String jdtLong = "\u65e5\u672c\u590f\u6642\u9593";
+ static final String jdtShort = "JDT";
+}
diff --git a/test/java/text/Format/DateFormat/bug4358730.java b/test/java/text/Format/DateFormat/bug4358730.java
new file mode 100644
index 0000000000..dc448ecd76
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug4358730.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2000, 2016, 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.io.*;
+import java.util.*;
+import java.text.*;
+
+/**
+ * @test
+ * @bug 4358730
+ * @library /java/text/testlib
+ * @summary test that confirms Zero-Padding on year.
+ */
+
+public class bug4358730 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new bug4358730().run(args);
+ }
+
+ String[] patterns = {"y", "yy", "yyy", "yyyy", "yyyyy"};
+ String[][] data = {
+ /* 2 A.D. */ {"2", "02", "002", "0002", "00002"},
+ /* 20 A.D. */ {"20", "20", "020", "0020", "00020"},
+ /* 200 A.D. */ {"200", "00", "200", "0200", "00200"},
+ /* 2000 A.D. */ {"2000", "00", "2000", "2000", "02000"},
+ };
+ int[] year = {2, 20, 200, 2000};
+
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ int datasize = data.length;
+ int nPatterns = data[0].length;
+
+ public void Test4358730() {
+ Locale locale = Locale.getDefault();
+ if (locale.equals(new Locale("th", "TH")) ||
+ locale.equals(new Locale("hi", "IN"))) {
+ return;
+ }
+
+ TimeZone saveZone = TimeZone.getDefault();
+ Locale saveLocale = Locale.getDefault();
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ Locale.setDefault(new Locale("en", "US"));
+
+ for (int i = 0; i < datasize; i++) {
+ Date d = new Date(year[i]-1900, 10, 15);
+ for (int j = 0; j < nPatterns; j++) {
+ sdf.applyPattern(patterns[j]);
+ if (!data[i][j].equals(sdf.format(d))) {
+ errln("Invalid format : " + sdf.format(d) +
+ ", expected : " + data[i][j]);
+ }
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ Locale.setDefault(saveLocale);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug6271375.java b/test/java/text/Format/DateFormat/bug6271375.java
new file mode 100644
index 0000000000..811470a01d
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug6271375.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6271375 7059546
+ * @summary Make sure DateFormatSymbols serialization works
+ * correctly for 'zoneStrings' field
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class bug6271375 {
+
+ public static void main(String[] args) throws Exception {
+ DateFormatSymbols dfsSrc = DateFormatSymbols.getInstance();
+
+ try (FileOutputStream fos = new FileOutputStream("dfs.ser");
+ ObjectOutputStream oStream = new ObjectOutputStream(fos)) {
+ oStream.writeObject(dfsSrc);
+ } catch (Exception e) {
+ throw new RuntimeException("An exception is thrown.", e);
+ }
+
+ try (FileInputStream fis = new FileInputStream("dfs.ser");
+ ObjectInputStream iStream = new ObjectInputStream(fis)) {
+ DateFormatSymbols dfsDest = (DateFormatSymbols)iStream.readObject();
+
+ String[][] zoneStringsSrc = dfsSrc.getZoneStrings();
+ String[][] zoneStringsDest = dfsDest.getZoneStrings();
+
+ if (!Arrays.deepEquals(zoneStringsSrc, zoneStringsDest)) {
+ throw new RuntimeException("src and dest zone strings are not equal");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("An exception is thrown.", e);
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug6317072.java b/test/java/text/Format/DateFormat/bug6317072.java
new file mode 100644
index 0000000000..d561422367
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug6317072.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6317072
+ * @summary Make sure NPE is thrown with "null" argumemnts in the
+ * SimpleDateFormat constructors.
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class bug6317072 {
+
+ public static void main(String[] args) {
+
+ try {
+ new SimpleDateFormat("yy", (Locale)null);
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new SimpleDateFormat((String)null, Locale.getDefault());
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new SimpleDateFormat("yy", (DateFormatSymbols)null);
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ new SimpleDateFormat((String)null, DateFormatSymbols.getInstance());
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ DateFormat.getTimeInstance(DateFormat.FULL, null);
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ DateFormat.getDateInstance(DateFormat.FULL, null);
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+
+ try {
+ DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, null);
+ throw new RuntimeException("should thrown a NullPointerException");
+ } catch (NullPointerException e) {
+ }
+ }
+}
diff --git a/test/java/text/Format/DateFormat/bug6412896.java b/test/java/text/Format/DateFormat/bug6412896.java
new file mode 100644
index 0000000000..b5422814ac
--- /dev/null
+++ b/test/java/text/Format/DateFormat/bug6412896.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006, 2016, 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 6412896
+ * @summary Make sure that an IllegalArgumentException is thrown
+ * if the length of any row in zoneStrings array is less than 5
+ */
+
+import java.text.*;
+
+public class bug6412896 {
+
+ static final String[][] zoneOK = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time", "PDT"}};
+ static final String[][] zoneNG = {{"America/Los_Angeles", "Pacific Standard Time", "PST", "Pacific Daylight Time"}};
+
+ public static void main(String[] args) {
+
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance();
+
+ dfs.setZoneStrings(zoneOK);
+
+ try {
+ dfs.setZoneStrings(zoneNG);
+ throw new RuntimeException("should throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/Bug4185816.ser.txt b/test/java/text/Format/MessageFormat/Bug4185816.ser.txt
new file mode 100644
index 0000000000..1fb54165c4
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/Bug4185816.ser.txt
@@ -0,0 +1,58 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a serialized MessageFormat for Bug4185816Test.
+
+aced0005737200176a6176612e746578742e4d657373616765466f726d617459
+ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e
+744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661
+2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75
+74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174
+7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176
+612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572
+00025b494dba602676eab2a502000078700000000a0000000100000000000000
+0000000000000000000000000000000000000000000000000000000000757200
+135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078
+700000000a70737200166a6176612e746578742e43686f696365466f726d6174
+18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c
+6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473
+7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000
+2800010000000000000001000000000178757200135b4c6a6176612e6c616e67
+2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066
+696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c
+6573757200025b443ea68c14ab635a1e02000078700000000300000000000000
+003ff000000000000040000000000000007070707070707070737200106a6176
+612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863
+6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e
+00044c000776617269616e7471007e00047870ffffffff740002555374000265
+6e740000787571007e00070000000a0000000a00000015000000000000000000
+0000000000000000000000000000000000000000000000740016546865206469
+736b20222220636f6e7461696e73202e
diff --git a/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt b/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt
new file mode 100644
index 0000000000..459d257339
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/Bug4185816Corrupt.ser.txt
@@ -0,0 +1,58 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a corrupted serialized MessageFormat for Bug4185732Test.
+
+aced0005737200176a6176612e746578742e4d657373616765466f726d617459
+ea973e12bd01a80200064900096d61784f66667365745b000f617267756d656e
+744e756d626572737400025b495b0007666f726d6174737400135b4c6a617661
+2f746578742f466f726d61743b4c00066c6f63616c657400124c6a6176612f75
+74696c2f4c6f63616c653b5b00076f66667365747371007e00014c0007706174
+7465726e7400124c6a6176612f6c616e672f537472696e673b787200106a6176
+612e746578742e466f726d6174fbd8bc12e90f18430200007870000000017572
+00025b494dba602676eab2a502000078700000000a0000000100000000000000
+0000000000000000000000000000000000000000000000000000000000757200
+135b4c6a6176612e746578742e466f726d61743b5eacf7515deec1f802000078
+700000000a70737200166a6176612e746578742e43686f696365466f726d6174
+18e9c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c
+6a6176612f6c616e672f537472696e673b5b000c63686f6963654c696d697473
+7400025b44787200166a6176612e746578742e4e756d626572466f726d6174df
+f6b3bf137d07e803000b5a000c67726f7570696e67557365644200116d617846
+72616374696f6e4469676974734200106d6178496e7465676572446967697473
+4900156d6178696d756d4672616374696f6e4469676974734900146d6178696d
+756d496e74656765724469676974734200116d696e4672616374696f6e446967
+6974734200106d696e496e74656765724469676974734900156d696e696d756d
+4672616374696f6e4469676974734900146d696e696d756d496e746567657244
+69676974735a00107061727365496e74656765724f6e6c794900157365726961
+6c56657273696f6e4f6e53747265616d7871007e000501032800000003000000
+2800010000000000000001000000000178757200135b4c6a6176612e6c616e67
+2e537472696e673badd256e7e91d7b470200007870000000037400086e6f2066
+696c65737400086f6e652066696c657400107b302c6e756d6265727d2066696c
+6573757200025b443ea68c14ab635a1e02000078700000000300000000000000
+003ff000000000000040000000000000007070707070707070737200106a6176
+612e7574696c2e4c6f63616c657ef811609c30f9ec0300044900086861736863
+6f64654c0007636f756e74727971007e00044c00086c616e677561676571007e
+00044c000776617269616e7471007e00047870ffffffff740002555374000265
+6e740000787571007e00070000000a0000000a00000015000000000000000000
+0000000000000000000000000000000000000000000000740010546865206469
+736b20222220636f6e74
diff --git a/test/java/text/Format/MessageFormat/Bug4185816Test.java b/test/java/text/Format/MessageFormat/Bug4185816Test.java
new file mode 100644
index 0000000000..65609941f5
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/Bug4185816Test.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 1999, 2016, 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 4185816
+ * @library /java/text/testlib
+ * @build Bug4185816Test IntlTest HexDumpReader
+ * @run main Bug4185816Test
+ * @summary test that MessageFormat invariants are preserved across serialization
+ */
+/*
+ *
+ *
+ * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.ChoiceFormat;
+import java.text.MessageFormat;
+
+/**
+ * A Locale can never contains language codes of he, yi or id.
+ */
+public class Bug4185816Test extends IntlTest {
+ private static final String FILE_NAME = "Bug4185816.ser";
+ private static final String CORRUPT_FILE_NAME = "Bug4185816Corrupt.ser";
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1 && args[0].equals("prepTest")) {
+ prepTest();
+ } else {
+ new Bug4185816Test().run(args);
+ }
+ }
+
+ public void testIt() throws Exception {
+ Exception e = checkStreaming(FILE_NAME);
+ if (e != null) {
+ errln("MessageFormat did not stream in valid stream: "+e);
+ e.printStackTrace();
+ }
+ e = checkStreaming(CORRUPT_FILE_NAME);
+ if (!(e instanceof InvalidObjectException)) {
+ errln("MessageFormat did NOT detect corrupt stream: "+e);
+ e.printStackTrace();
+ }
+ }
+
+ public Exception checkStreaming(final String fileName) {
+ try {
+ final InputStream is = HexDumpReader.getStreamFromHexDump(fileName + ".txt");
+ final ObjectInputStream in = new ObjectInputStream(is);
+ final MessageFormat form = (MessageFormat)in.readObject();
+ final Object[] testArgs = {new Long(12373), "MyDisk"};
+ final String result = form.format(testArgs);
+ in.close();
+ } catch (Exception e) {
+ return e;
+ }
+ return null;
+ }
+
+ /**
+ * Create a data file for this test. The data file must be corrupted by hand.
+ */
+ private static void prepTest() {
+ writeFormatToFile(FILE_NAME);
+ writeFormatToFile(CORRUPT_FILE_NAME);
+ }
+
+ private static void writeFormatToFile(final String name) {
+ try {
+ ObjectOutputStream out = new ObjectOutputStream(
+ new FileOutputStream(name));
+
+ MessageFormat fmt = new MessageFormat("The disk \"{1}\" contains {0}.");
+ double[] filelimits = {0,1,2};
+ String[] filepart = {"no files","one file","{0,number} files"};
+ ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
+ fmt.setFormat(1,fileform); // NOT zero, see below
+
+ out.writeObject(fmt);
+ out.close();
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/Bug6481179.java b/test/java/text/Format/MessageFormat/Bug6481179.java
new file mode 100644
index 0000000000..be8e9e29f1
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/Bug6481179.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2016, 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
+ * @summary Confirm that a bug in an error message has been fixed.
+ * @bug 6481179
+ */
+
+import java.text.MessageFormat;
+import java.text.ParseException;
+
+public class Bug6481179 {
+
+ public static void main(String[] args) {
+ boolean err = false;
+
+ try {
+ MessageFormat.format("Testdata {1,invalid_format_type}",
+ new Object[] { "val0", "val1" });
+
+ System.err.println("Error: IllegalArgumentException should be thrown.");
+ err = true;
+ }
+ catch (IllegalArgumentException e) {
+ String expected = "unknown format type: invalid_format_type";
+ String got = e.getMessage();
+
+ if (!expected.equals(got)) {
+ System.err.println("Error: Unexpected error message: " + got);
+ err = true;
+ }
+ }
+ catch (Exception e) {
+ System.err.println("Error: Unexpected exception was thrown: " + e);
+ err = true;
+ }
+
+ if (err) {
+ throw new RuntimeException("Failed.");
+ }
+ }
+
+}
diff --git a/test/java/text/Format/MessageFormat/LargeMessageFormat.java b/test/java/text/Format/MessageFormat/LargeMessageFormat.java
new file mode 100644
index 0000000000..1a4ca1d092
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/LargeMessageFormat.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2000, 2016, 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 4112090 8008577
+ * @summary verify that MessageFormat can handle large numbers of arguments
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI LargeMessageFormat
+ */
+
+import java.text.MessageFormat;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class LargeMessageFormat {
+
+ public static void main(String[] args) throws ParseException {
+ Locale reservedLocale = Locale.getDefault();
+ TimeZone reservedTimeZone = TimeZone.getDefault();
+ try {
+ Locale.setDefault(Locale.GERMANY);
+ TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
+ testFormat();
+ testParse();
+ } finally {
+ // restore the reserved locale and time zone
+ Locale.setDefault(reservedLocale);
+ TimeZone.setDefault(reservedTimeZone);
+ }
+ }
+
+ private static final int REPEATS = 89;
+
+ private static void testFormat() {
+ // construct large argument array
+ Object[] sample = {
+ new Integer(0), // replace with running count below
+ "hello",
+ new Date(89, 10, 9),
+ new Integer(567890),
+ new Double(1234.50)
+ };
+ int samples = sample.length;
+ Object[] arguments = new Object[REPEATS * (samples + 1)];
+ for (int i = 0; i < REPEATS; i++) {
+ System.arraycopy(sample, 0, arguments, i * samples, samples);
+ arguments[i * samples] = new Integer(i);
+ }
+
+ // construct large template
+ StringBuffer template = new StringBuffer();
+ for (int i = 0; i < REPEATS; i++) {
+ template.append("section {" + (i * samples) + ", number} - ");
+ template.append("string: {" + (i * samples + 1) + "}; ");
+ template.append("date: {" + (i * samples + 2) + ", date}; ");
+ template.append("integer: {" + (i * samples + 3) + ", number}; ");
+ template.append("currency: {" + (i * samples + 4) + ", number, currency};\n");
+ }
+
+ // construct expected result string
+ StringBuffer expected = new StringBuffer();
+ for (int i = 0; i < REPEATS; i++) {
+ expected.append("section " + i + " - ");
+ expected.append("string: hello; ");
+ expected.append("date: 09.11.1989; ");
+ expected.append("integer: 567.890; ");
+ expected.append("currency: 1.234,50 \u20AC;\n");
+ }
+
+ // create message format
+ MessageFormat format = new MessageFormat(template.toString());
+ String result = format.format(arguments);
+ if (!result.equals(expected.toString())) {
+ System.out.println("Template:");
+ System.out.println(template);
+ System.out.println("Expected result: ");
+ System.out.println(expected);
+ System.out.println("Actual result: ");
+ System.out.println(result);
+ throw new RuntimeException();
+ }
+ }
+
+ private static void testParse() throws ParseException {
+ StringBuffer parseTemplate = new StringBuffer();
+ StringBuffer parseInput = new StringBuffer();
+ for (int i = 0; i < REPEATS; i++) {
+ parseTemplate.append("{" + i + ", number} ");
+ parseInput.append(i + " ");
+ }
+ MessageFormat parseFormat = new MessageFormat(parseTemplate.toString());
+ Object[] parseResult = parseFormat.parse(parseInput.toString());
+ for (int i = 0; i < REPEATS; i++) {
+ if (((Number) parseResult[i]).intValue() != i) {
+ throw new RuntimeException("got wrong parse result");
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java b/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java
new file mode 100644
index 0000000000..1d69258f68
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/MessageFormatsByArgumentIndex.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2000, 2016, 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 4105380
+ * @summary basic tests for new methods getFormatsByArgumentIndex, setFormatByArgumentIndex, setFormatsByArgumentIndex
+ */
+
+import java.text.ChoiceFormat;
+import java.text.Format;
+import java.text.MessageFormat;
+import java.text.NumberFormat;
+
+public class MessageFormatsByArgumentIndex {
+
+ private static String choicePattern = "0.0#are no files|1.0#is one file|1.0<are {0,number,integer} files";
+
+ public static void main(String[] args) {
+ Format[] subformats;
+
+ MessageFormat format = new MessageFormat("{3, choice," + choicePattern + "}, {2}, {0}");
+
+ subformats = format.getFormatsByArgumentIndex();
+ checkSubformatLength(subformats, 4);
+ checkSubformat(subformats, 0, null);
+ checkSubformat(subformats, 1, null);
+ checkSubformat(subformats, 2, null);
+ checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+ subformats = format.getFormats();
+ checkSubformatLength(subformats, 3);
+ checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+ checkSubformat(subformats, 1, null);
+ checkSubformat(subformats, 2, null);
+
+ format.setFormatByArgumentIndex(0, NumberFormat.getInstance());
+
+ checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2}, {0,number}");
+
+ subformats = format.getFormatsByArgumentIndex();
+ checkSubformatLength(subformats, 4);
+ checkSubformat(subformats, 0, NumberFormat.getInstance());
+ checkSubformat(subformats, 1, null);
+ checkSubformat(subformats, 2, null);
+ checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+ subformats = format.getFormats();
+ checkSubformatLength(subformats, 3);
+ checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+ checkSubformat(subformats, 1, null);
+ checkSubformat(subformats, 2, NumberFormat.getInstance());
+
+ format.setFormatsByArgumentIndex(subformats);
+
+ checkPattern(format.toPattern(), "{3,choice," + choicePattern + "}, {2,number}, {0,choice," + choicePattern + "}");
+
+ subformats = format.getFormatsByArgumentIndex();
+ checkSubformatLength(subformats, 4);
+ checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+ checkSubformat(subformats, 1, null);
+ checkSubformat(subformats, 2, NumberFormat.getInstance());
+ checkSubformat(subformats, 3, new ChoiceFormat(choicePattern));
+
+ subformats = format.getFormats();
+ checkSubformatLength(subformats, 3);
+ checkSubformat(subformats, 0, new ChoiceFormat(choicePattern));
+ checkSubformat(subformats, 1, NumberFormat.getInstance());
+ checkSubformat(subformats, 2, new ChoiceFormat(choicePattern));
+
+ }
+
+ private static void checkPattern(String actual, String expected) {
+ if (!expected.equals(actual)) {
+ throw new RuntimeException("unexpected pattern:\n expected: " + expected + "\n actual: " + actual);
+ }
+ }
+
+ private static void checkSubformatLength(Format[] subformats, int expected) {
+ if (subformats.length != expected) {
+ throw new RuntimeException("unexpected subformat length:\n expected: " + expected + "\n actual: " + subformats.length);
+ }
+ }
+
+ private static void checkSubformat(Format[] subformats, int index, Format expected) {
+ Format subformat = subformats[index];
+ if (subformat == expected) {
+ return;
+ }
+ if ((subformat != null) && subformat.equals(expected)) {
+ return;
+ }
+ throw new RuntimeException("found unexpected subformat for argument " + index + ":\n expected: " + expected + "\n actual: " + subformat);
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/MessageRegression.java b/test/java/text/Format/MessageFormat/MessageRegression.java
new file mode 100644
index 0000000000..e0d8d80e36
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/MessageRegression.java
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 4106661
+ * 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 4120552
+ * 4142938 4169959 4232154 4293229
+ * @summary Regression tests for MessageFormat and associated classes
+ * @library /java/text/testlib
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.io.FileInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public class MessageRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new MessageRegression().run(args);
+ }
+
+ /* @bug 4074764
+ * Null exception when formatting pattern with MessageFormat
+ * with no parameters.
+ */
+ public void Test4074764() {
+ String[] pattern = {"Message without param",
+ "Message with param:{0}",
+ "Longer Message with param {0}"};
+ //difference between the two param strings are that
+ //in the first one, the param position is within the
+ //length of the string without param while it is not so
+ //in the other case.
+
+ MessageFormat messageFormatter = new MessageFormat("");
+
+ try {
+ //Apply pattern with param and print the result
+ messageFormatter.applyPattern(pattern[1]);
+ Object[] params = {new String("BUG"), new Date()};
+ String tempBuffer = messageFormatter.format(params);
+ if (!tempBuffer.equals("Message with param:BUG"))
+ errln("MessageFormat with one param test failed.");
+ logln("Formatted with one extra param : " + tempBuffer);
+
+ //Apply pattern without param and print the result
+ messageFormatter.applyPattern(pattern[0]);
+ tempBuffer = messageFormatter.format(null);
+ if (!tempBuffer.equals("Message without param"))
+ errln("MessageFormat with no param test failed.");
+ logln("Formatted with no params : " + tempBuffer);
+
+ tempBuffer = messageFormatter.format(params);
+ if (!tempBuffer.equals("Message without param"))
+ errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString());
+ logln("Formatted with extra params : " + tempBuffer);
+ //This statement gives an exception while formatting...
+ //If we use pattern[1] for the message with param,
+ //we get an NullPointerException in MessageFormat.java(617)
+ //If we use pattern[2] for the message with param,
+ //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614)
+ //Both are due to maxOffset not being reset to -1
+ //in applyPattern() when the pattern does not
+ //contain any param.
+ } catch (Exception foo) {
+ errln("Exception when formatting with no params.");
+ }
+ }
+
+ /* @bug 4058973
+ * MessageFormat.toPattern has weird rounding behavior.
+ */
+ public void Test4058973() {
+
+ MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");
+ String pat = fmt.toPattern();
+ if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) {
+ errln("MessageFormat.toPattern failed");
+ }
+ }
+ /* @bug 4031438
+ * More robust message formats.
+ */
+ public void Test4031438() {
+ String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}.";
+ String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.";
+
+ // If the current locale is hi_IN, skip this test case.
+ if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+ return;
+ }
+
+ MessageFormat messageFormatter = new MessageFormat("");
+
+ try {
+ logln("Apply with pattern : " + pattern1);
+ messageFormatter.applyPattern(pattern1);
+ Object[] params = {new Integer(7)};
+ String tempBuffer = messageFormatter.format(params);
+ if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}."))
+ errln("Tests arguments < substitution failed. Formatted text=" +
+ "<" + tempBuffer + ">");
+ logln("Formatted with 7 : " + tempBuffer);
+ ParsePosition status = new ParsePosition(0);
+ Object[] objs = messageFormatter.parse(tempBuffer, status);
+ if (objs[params.length] != null)
+ errln("Parse failed with more than expected arguments");
+ for (int i = 0; i < objs.length; i++) {
+ if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) {
+ errln("Parse failed on object " + objs[i] + " at index : " + i);
+ }
+ }
+ tempBuffer = messageFormatter.format(null);
+ if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}."))
+ errln("Tests with no arguments failed");
+ logln("Formatted with null : " + tempBuffer);
+ logln("Apply with pattern : " + pattern2);
+ messageFormatter.applyPattern(pattern2);
+ tempBuffer = messageFormatter.format(params);
+ if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff."))
+ errln("quote format test (w/ params) failed.");
+ logln("Formatted with params : " + tempBuffer);
+ tempBuffer = messageFormatter.format(null);
+ if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff."))
+ errln("quote format test (w/ null) failed.");
+ logln("Formatted with null : " + tempBuffer);
+ logln("toPattern : " + messageFormatter.toPattern());
+ } catch (Exception foo) {
+ errln("Exception when formatting in bug 4031438. "+foo.getMessage());
+ }
+ }
+ public void Test4052223()
+ {
+ ParsePosition pos = new ParsePosition(0);
+ if (pos.getErrorIndex() != -1) {
+ errln("ParsePosition.getErrorIndex initialization failed.");
+ }
+ MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree.");
+ String str = new String("There is one apple growing on the peach tree.");
+ Object[] objs = fmt.parse(str, pos);
+ logln("unparsable string , should fail at " + pos.getErrorIndex());
+ if (pos.getErrorIndex() == -1)
+ errln("Bug 4052223 failed : parsing string " + str);
+ pos.setErrorIndex(4);
+ if (pos.getErrorIndex() != 4)
+ errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4");
+ ChoiceFormat f = new ChoiceFormat(
+ "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2.");
+ pos.setIndex(0); pos.setErrorIndex(-1);
+ Number obj = f.parse("are negative", pos);
+ if (pos.getErrorIndex() != -1 && obj.doubleValue() == -1.0)
+ errln("Parse with \"are negative\" failed, at " + pos.getErrorIndex());
+ pos.setIndex(0); pos.setErrorIndex(-1);
+ obj = f.parse("are no or fraction ", pos);
+ if (pos.getErrorIndex() != -1 && obj.doubleValue() == 0.0)
+ errln("Parse with \"are no or fraction\" failed, at " + pos.getErrorIndex());
+ pos.setIndex(0); pos.setErrorIndex(-1);
+ obj = f.parse("go postal", pos);
+ if (pos.getErrorIndex() == -1 && !Double.isNaN(obj.doubleValue()))
+ errln("Parse with \"go postal\" failed, at " + pos.getErrorIndex());
+ }
+ /* @bug 4104976
+ * ChoiceFormat.equals(null) throws NullPointerException
+ */
+ public void Test4104976()
+ {
+ double[] limits = {1, 20};
+ String[] formats = {"xyz", "abc"};
+ ChoiceFormat cf = new ChoiceFormat(limits, formats);
+ try {
+ log("Compares to null is always false, returned : ");
+ logln(cf.equals(null) ? "TRUE" : "FALSE");
+ } catch (Exception foo) {
+ errln("ChoiceFormat.equals(null) throws exception.");
+ }
+ }
+ /* @bug 4106659
+ * ChoiceFormat.ctor(double[], String[]) doesn't check
+ * whether lengths of input arrays are equal.
+ */
+ public void Test4106659()
+ {
+ double[] limits = {1, 2, 3};
+ String[] formats = {"one", "two"};
+ ChoiceFormat cf = null;
+ try {
+ cf = new ChoiceFormat(limits, formats);
+ } catch (Exception foo) {
+ logln("ChoiceFormat constructor should check for the array lengths");
+ cf = null;
+ }
+ if (cf != null) errln(cf.format(5));
+ }
+
+ /* @bug 4106660
+ * ChoiceFormat.ctor(double[], String[]) allows unordered double array.
+ * This is not a bug, added javadoc to emphasize the use of limit
+ * array must be in ascending order.
+ */
+ public void Test4106660()
+ {
+ double[] limits = {3, 1, 2};
+ String[] formats = {"Three", "One", "Two"};
+ ChoiceFormat cf = new ChoiceFormat(limits, formats);
+ double d = 5.0;
+ String str = cf.format(d);
+ if (!str.equals("Two"))
+ errln("format(" + d + ") = " + cf.format(d));
+ }
+
+ /* @bug 4111739
+ * MessageFormat is incorrectly serialized/deserialized.
+ */
+ public void Test4111739()
+ {
+ MessageFormat format1 = null;
+ MessageFormat format2 = null;
+ ObjectOutputStream ostream = null;
+ ByteArrayOutputStream baos = null;
+ ObjectInputStream istream = null;
+
+ try {
+ baos = new ByteArrayOutputStream();
+ ostream = new ObjectOutputStream(baos);
+ } catch(IOException e) {
+ errln("Unexpected exception : " + e.getMessage());
+ return;
+ }
+
+ try {
+ format1 = new MessageFormat("pattern{0}");
+ ostream.writeObject(format1);
+ ostream.flush();
+
+ byte bytes[] = baos.toByteArray();
+
+ istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
+ format2 = (MessageFormat)istream.readObject();
+ } catch(Exception e) {
+ errln("Unexpected exception : " + e.getMessage());
+ }
+
+ if (!format1.equals(format2)) {
+ errln("MessageFormats before and after serialization are not" +
+ " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " +
+ format2 + "(" + format2.toPattern() + ")");
+ } else {
+ logln("Serialization for MessageFormat is OK.");
+ }
+ }
+ /* @bug 4114743
+ * MessageFormat.applyPattern allows illegal patterns.
+ */
+ public void Test4114743()
+ {
+ String originalPattern = "initial pattern";
+ MessageFormat mf = new MessageFormat(originalPattern);
+ try {
+ String illegalPattern = "ab { '}' de";
+ mf.applyPattern(illegalPattern);
+ errln("illegal pattern: \"" + illegalPattern + "\"");
+ } catch (IllegalArgumentException foo) {
+ if (!originalPattern.equals(mf.toPattern()))
+ errln("pattern after: \"" + mf.toPattern() + "\"");
+ }
+ }
+
+ /* @bug 4116444
+ * MessageFormat.parse has different behavior in case of null.
+ */
+ public void Test4116444()
+ {
+ String[] patterns = {"", "one", "{0,date,short}"};
+ MessageFormat mf = new MessageFormat("");
+
+ for (int i = 0; i < patterns.length; i++) {
+ String pattern = patterns[i];
+ mf.applyPattern(pattern);
+ try {
+ Object[] array = mf.parse(null, new ParsePosition(0));
+ logln("pattern: \"" + pattern + "\"");
+ log(" parsedObjects: ");
+ if (array != null) {
+ log("{");
+ for (int j = 0; j < array.length; j++) {
+ if (array[j] != null)
+ err("\"" + array[j].toString() + "\"");
+ else
+ log("null");
+ if (j < array.length - 1) log(",");
+ }
+ log("}") ;
+ } else {
+ log("null");
+ }
+ logln("");
+ } catch (Exception e) {
+ errln("pattern: \"" + pattern + "\"");
+ errln(" Exception: " + e.getMessage());
+ }
+ }
+
+ }
+ /* @bug 4114739 (FIX and add javadoc)
+ * MessageFormat.format has undocumented behavior about empty format objects.
+ */
+ public void Test4114739()
+ {
+
+ MessageFormat mf = new MessageFormat("<{0}>");
+ Object[] objs1 = null;
+ Object[] objs2 = {};
+ Object[] objs3 = {null};
+ try {
+ logln("pattern: \"" + mf.toPattern() + "\"");
+ log("format(null) : ");
+ logln("\"" + mf.format(objs1) + "\"");
+ log("format({}) : ");
+ logln("\"" + mf.format(objs2) + "\"");
+ log("format({null}) :");
+ logln("\"" + mf.format(objs3) + "\"");
+ } catch (Exception e) {
+ errln("Exception thrown for null argument tests.");
+ }
+ }
+
+ /* @bug 4113018
+ * MessageFormat.applyPattern works wrong with illegal patterns.
+ */
+ public void Test4113018()
+ {
+ String originalPattern = "initial pattern";
+ MessageFormat mf = new MessageFormat(originalPattern);
+ String illegalPattern = "format: {0, xxxYYY}";
+ logln("pattern before: \"" + mf.toPattern() + "\"");
+ logln("illegal pattern: \"" + illegalPattern + "\"");
+ try {
+ mf.applyPattern(illegalPattern);
+ errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern);
+ } catch (IllegalArgumentException e) {
+ if (!originalPattern.equals(mf.toPattern()))
+ errln("pattern after: \"" + mf.toPattern() + "\"");
+ }
+ }
+ /* @bug 4106661
+ * ChoiceFormat is silent about the pattern usage in javadoc.
+ */
+ public void Test4106661()
+ {
+ ChoiceFormat fmt = new ChoiceFormat(
+ "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2.");
+ logln("Formatter Pattern : " + fmt.toPattern());
+
+ logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
+ logln("Format with -1.0 : " + fmt.format(-1.0));
+ logln("Format with 0 : " + fmt.format(0));
+ logln("Format with 0.9 : " + fmt.format(0.9));
+ logln("Format with 1.0 : " + fmt.format(1));
+ logln("Format with 1.5 : " + fmt.format(1.5));
+ logln("Format with 2 : " + fmt.format(2));
+ logln("Format with 2.1 : " + fmt.format(2.1));
+ logln("Format with NaN : " + fmt.format(Double.NaN));
+ logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
+ }
+ /* @bug 4094906
+ * ChoiceFormat should accept \u221E as eq. to INF.
+ */
+ public void Test4094906()
+ {
+ ChoiceFormat fmt = new ChoiceFormat(
+ "-\u221E<are negative|0<are no or fraction|1#is one|1.0<is 1+|\u221E<are many.");
+ if (!fmt.toPattern().startsWith("-\u221E<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|\u221E<are many."))
+ errln("Formatter Pattern : " + fmt.toPattern());
+ logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
+ logln("Format with -1.0 : " + fmt.format(-1.0));
+ logln("Format with 0 : " + fmt.format(0));
+ logln("Format with 0.9 : " + fmt.format(0.9));
+ logln("Format with 1.0 : " + fmt.format(1));
+ logln("Format with 1.5 : " + fmt.format(1.5));
+ logln("Format with 2 : " + fmt.format(2));
+ logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
+ }
+
+ /* @bug 4118592
+ * MessageFormat.parse fails with ChoiceFormat.
+ */
+ public void Test4118592()
+ {
+ MessageFormat mf = new MessageFormat("");
+ String pattern = "{0,choice,1#YES|2#NO}";
+ String prefix = "";
+ for (int i = 0; i < 5; i++) {
+ String formatted = prefix + "YES";
+ mf.applyPattern(prefix + pattern);
+ prefix += "x";
+ Object[] objs = mf.parse(formatted, new ParsePosition(0));
+ logln(i + ". pattern :\"" + mf.toPattern() + "\"");
+ log(" \"" + formatted + "\" parsed as ");
+ if (objs == null) logln(" null");
+ else logln(" " + objs[0]);
+ }
+ }
+ /* @bug 4118594
+ * MessageFormat.parse fails for some patterns.
+ */
+ public void Test4118594()
+ {
+ MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
+ String forParsing = "x, y, z";
+ Object[] objs = mf.parse(forParsing, new ParsePosition(0));
+ logln("pattern: \"" + mf.toPattern() + "\"");
+ logln("text for parsing: \"" + forParsing + "\"");
+ if (!objs[0].toString().equals("z"))
+ errln("argument0: \"" + objs[0] + "\"");
+ mf.setLocale(Locale.US);
+ mf.applyPattern("{0,number,#.##}, {0,number,#.#}");
+ Object[] oldobjs = {new Double(3.1415)};
+ String result = mf.format( oldobjs );
+ logln("pattern: \"" + mf.toPattern() + "\"");
+ logln("text for parsing: \"" + result + "\"");
+ // result now equals "3.14, 3.1"
+ if (!result.equals("3.14, 3.1"))
+ errln("result = " + result);
+ Object[] newobjs = mf.parse(result, new ParsePosition(0));
+ // newobjs now equals {new Double(3.1)}
+ if (((Double)newobjs[0]).doubleValue() != 3.1)
+ errln( "newobjs[0] = " + newobjs[0]);
+ }
+ /* @bug 4105380
+ * When using ChoiceFormat, MessageFormat is not good for I18n.
+ */
+ public void Test4105380()
+ {
+ String patternText1 = "The disk \"{1}\" contains {0}.";
+ String patternText2 = "There are {0} on the disk \"{1}\"";
+ MessageFormat form1 = new MessageFormat(patternText1);
+ MessageFormat form2 = new MessageFormat(patternText2);
+ double[] filelimits = {0,1,2};
+ String[] filepart = {"no files","one file","{0,number} files"};
+ ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
+ form1.setFormat(1, fileform);
+ form2.setFormat(0, fileform);
+ Object[] testArgs = {new Long(12373), "MyDisk"};
+ logln(form1.format(testArgs));
+ logln(form2.format(testArgs));
+ }
+ /* @bug 4120552
+ * MessageFormat.parse incorrectly sets errorIndex.
+ */
+ public void Test4120552()
+ {
+ MessageFormat mf = new MessageFormat("pattern");
+ String texts[] = {"pattern", "pat", "1234"};
+ logln("pattern: \"" + mf.toPattern() + "\"");
+ for (int i = 0; i < texts.length; i++) {
+ ParsePosition pp = new ParsePosition(0);
+ Object[] objs = mf.parse(texts[i], pp);
+ log(" text for parsing: \"" + texts[i] + "\"");
+ if (objs == null) {
+ logln(" (incorrectly formatted string)");
+ if (pp.getErrorIndex() == -1)
+ errln("Incorrect error index: " + pp.getErrorIndex());
+ } else {
+ logln(" (correctly formatted string)");
+ }
+ }
+ }
+
+ /**
+ * @bug 4142938
+ * MessageFormat handles single quotes in pattern wrong.
+ * This is actually a problem in ChoiceFormat; it doesn't
+ * understand single quotes.
+ */
+ public void Test4142938() {
+ String pat = "''Vous'' {0,choice,0#n''|1#}avez s\u00E9lectionne\u00E9 " +
+ "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " +
+ "personnel{0,choice,0#s|1#|2#s}.";
+ MessageFormat mf = new MessageFormat(pat);
+
+ String[] PREFIX = {
+ "'Vous' n'avez s\u00E9lectionne\u00E9 aucun clients personnels.",
+ "'Vous' avez s\u00E9lectionne\u00E9 ",
+ "'Vous' avez s\u00E9lectionne\u00E9 "
+ };
+ String[] SUFFIX = {
+ null,
+ " client personnel.",
+ " clients personnels."
+ };
+
+ for (int i=0; i<3; i++) {
+ String out = mf.format(new Object[]{new Integer(i)});
+ if (SUFFIX[i] == null) {
+ if (!out.equals(PREFIX[i]))
+ errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"");
+ }
+ else {
+ if (!out.startsWith(PREFIX[i]) ||
+ !out.endsWith(SUFFIX[i]))
+ errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" +
+ SUFFIX[i] + "\"");
+ }
+ }
+ }
+
+ /**
+ * @bug 4142938
+ * Test the applyPattern and toPattern handling of single quotes
+ * by ChoiceFormat. (This is in here because this was a bug reported
+ * against MessageFormat.) The single quote is used to quote the
+ * pattern characters '|', '#', '<', and '\u2264'. Two quotes in a row
+ * is a quote literal.
+ */
+ public void TestChoicePatternQuote() {
+ String[] DATA = {
+ // Pattern 0 value 1 value
+ "0#can''t|1#can", "can't", "can",
+ "0#'pound(#)=''#'''|1#xyz", "pound(#)='#'", "xyz",
+ "0#'1<2 | 1\u22641'|1#''", "1<2 | 1\u22641", "'",
+ };
+ for (int i=0; i<DATA.length; i+=3) {
+ try {
+ ChoiceFormat cf = new ChoiceFormat(DATA[i]);
+ for (int j=0; j<=1; ++j) {
+ String out = cf.format(j);
+ if (!out.equals(DATA[i+1+j]))
+ errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " +
+ out + "; want \"" + DATA[i+1+j] + '"');
+ }
+ String pat = cf.toPattern();
+ String pat2 = new ChoiceFormat(pat).toPattern();
+ if (!pat.equals(pat2))
+ errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
+ else
+ logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
+ }
+ catch (IllegalArgumentException e) {
+ errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e);
+ }
+ }
+ }
+
+ /**
+ * @bug 4112104
+ * MessageFormat.equals(null) throws a NullPointerException. The JLS states
+ * that it should return false.
+ */
+ public void Test4112104() {
+ MessageFormat format = new MessageFormat("");
+ try {
+ // This should NOT throw an exception
+ if (format.equals(null)) {
+ // It also should return false
+ errln("MessageFormat.equals(null) returns false");
+ }
+ }
+ catch (NullPointerException e) {
+ errln("MessageFormat.equals(null) throws " + e);
+ }
+ }
+
+ /**
+ * @bug 4169959
+ * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG.
+ */
+ public void Test4169959() {
+ // This works
+ logln(MessageFormat.format( "This will {0}",
+ new String[]{"work"} ) );
+
+ // This fails
+ logln(MessageFormat.format( "This will {0}",
+ new Object[]{ null } ) );
+ }
+
+ public void test4232154() {
+ boolean gotException = false;
+ try {
+ MessageFormat format = new MessageFormat("The date is {0:date}");
+ } catch (Exception e) {
+ gotException = true;
+ if (!(e instanceof IllegalArgumentException)) {
+ throw new RuntimeException("got wrong exception type");
+ }
+ if ("argument number too large at ".equals(e.getMessage())) {
+ throw new RuntimeException("got wrong exception message");
+ }
+ }
+ if (!gotException) {
+ throw new RuntimeException("didn't get exception for invalid input");
+ }
+ }
+
+ public void test4293229() {
+ MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''");
+ Object[] args = { null };
+ String expected = "'{0}' '{0}'";
+ String result = format.format(args);
+ if (!result.equals(expected)) {
+ throw new RuntimeException("wrong format result - expected \"" +
+ expected + "\", got \"" + result + "\"");
+ }
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/MessageTest.java b/test/java/text/Format/MessageFormat/MessageTest.java
new file mode 100644
index 0000000000..9234ae90c9
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/MessageTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 2016, 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
+ * @library /java/text/testlib
+ * @summary test MessageFormat
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+
+import java.util.*;
+import java.io.*;
+import java.text.*;
+
+public class MessageTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new MessageTest().run(args);
+ }
+
+
+ public void TestMSGPatternTest() {
+ Object[] testArgs = {
+ new Double (1), new Double(3456),
+ "Disk", new Date(10000000000L)};
+
+ String[] testCases = {
+ "Quotes '', '{', 'a' {0} '{0}'",
+ "Quotes '', '{', 'a' {0,number} '{0}'",
+ "'{'1,number,'#',##} {1,number,'#',##}",
+ "There are {1} files on {2} at {3}",
+ "On {2}, there are {1} files, with {0,number,currency}.",
+ "'{1,number,percent}', {1,number,percent}, ",
+ "'{1,date,full}', {1,date,full}, ",
+ "'{3,date,full}', {3,date,full}, ",
+ "'{1,number,#,##}' {1,number,#,##}",
+ };
+
+ for (int i = 0; i < testCases.length; ++i) {
+ Locale save = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ logln("");
+ logln( i + " Pat in: " + testCases[i]);
+ MessageFormat form = new MessageFormat(testCases[i]);
+ logln( i + " Pat out: " + form.toPattern());
+ String result = form.format(testArgs);
+ logln( i + " Result: " + result);
+ Object[] values = form.parse(result);
+ for (int j = 0; j < testArgs.length; ++j) {
+ Object testArg = testArgs[j];
+ Object value = null;
+ if (j < values.length) {
+ value = values[j];
+ }
+ if ((testArg == null && value != null)
+ || (testArg != null && !testArg.equals(value))) {
+ logln( i + " " + j + " old: " + testArg);
+ logln( i + " " + j + " new: " + value);
+ }
+ }
+ }
+ catch(java.text.ParseException pe ) {
+ throw new RuntimeException("Error: MessageFormat.parse throws ParseException");
+ }
+ finally{
+ Locale.setDefault(save);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/MessageFormat/bug4492719.java b/test/java/text/Format/MessageFormat/bug4492719.java
new file mode 100644
index 0000000000..6a1d2184ff
--- /dev/null
+++ b/test/java/text/Format/MessageFormat/bug4492719.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4492719
+ * @library /java/text/testlib
+ * @summary Confirm that Message.parse() interprets time zone which uses "GMT+/-" format correctly and doesn't throw ParseException.
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class bug4492719 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ MessageFormat mf;
+ boolean err =false;
+
+ String[] formats = {
+ "short", "medium", "long", "full"
+ };
+ String[] timezones = {
+ "America/Los_Angeles", "GMT", "GMT+09:00", "GMT-8:00",
+ "GMT+123", "GMT-1234", "GMT+2", "GMT-13"
+ };
+ String text;
+
+ Locale.setDefault(Locale.US);
+
+ try {
+ for (int i = 0; i < timezones.length; i++) {
+ TimeZone.setDefault(TimeZone.getTimeZone(timezones[i]));
+
+ for (int j = 0; j < formats.length; j++) {
+ mf = new MessageFormat("{0,time," + formats[j] + "} - time");
+ text = MessageFormat.format("{0,time," + formats[j] + "} - time",
+ new Object [] { new Date(123456789012L)});
+ Object[] objs = mf.parse(text);
+ }
+ }
+ } catch (ParseException e) {
+ err = true;
+ System.err.println("Invalid ParseException occurred : " +
+ e.getMessage());
+ System.err.println(" TimeZone=" + TimeZone.getDefault());
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ if (err) {
+ throw new Exception("MessageFormat.parse(\"GMT format\") failed.");
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java b/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java
new file mode 100644
index 0000000000..1a2e7bf394
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/BigDecimalCompatibilityTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4018937
+ * @summary Confirm that DecimalFormat.parse() parses BigDecimal and BigInteger as expected.
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalCompatibilityTest {
+
+ static boolean err = false;
+
+ static final String[] input_data = {
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"
+ };
+ static final String[] exponents = {
+ "E-100", "E100", "E-900", "E900", ""
+ };
+ static final int[] multipliers = {
+ -1, 1, -100, 100, -9999, 9999
+ };
+
+ public static void main(String[] args) throws Exception {
+ Locale loc = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+
+ testBigDecimal();
+ testBigInteger();
+
+ Locale.setDefault(loc);
+
+ if (err) {
+ throw new RuntimeException("Error: Unexpected value");
+ }
+ }
+
+ static private void testBigDecimal() {
+ DecimalFormat df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+ df.setMaximumFractionDigits(Integer.MAX_VALUE);
+
+ for (int i = 0; i < input_data.length; i++) {
+ for (int j = 0; j < input_data.length; j++) {
+ for (int k = 0; k < input_data.length; k++) {
+ for (int l = 0; l < input_data.length; l++) {
+ for (int m = 0; m < exponents.length; m++) {
+ String s = input_data[i] + input_data[j] + '.' +
+ input_data[k] + input_data[l] +
+ exponents[m];
+ for (int n = 0; n < multipliers.length; n++) {
+ test(df, s, multipliers[n]);
+ test(df, '-'+s, multipliers[n]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ static private void testBigInteger() {
+ DecimalFormat df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+ df.setMaximumFractionDigits(Integer.MAX_VALUE);
+
+ for (int i = 0; i < input_data.length; i++) {
+ for (int j = 0; j < input_data.length; j++) {
+ String s = input_data[i] + input_data[j];
+ for (int k = 0; k < multipliers.length; k++) {
+ test(df, s, multipliers[k]);
+ test(df, '-'+s, multipliers[k]);
+ }
+ }
+ }
+ }
+
+ static void test(DecimalFormat df, String s, int multiplier) {
+ df.setMultiplier(multiplier);
+
+ Number num = null;
+ try {
+ num = df.parse(s);
+ }
+ catch (ParseException e) {
+ err = true;
+ System.err.println("Failed: Exception occurred: " + e.getMessage());
+ return;
+ }
+
+ BigDecimal bd = new BigDecimal(s);
+ try {
+ bd = bd.divide(new BigDecimal(multiplier));
+ }
+ catch (ArithmeticException e) {
+ bd = bd.divide(new BigDecimal(multiplier), BigDecimal.ROUND_HALF_EVEN);
+ }
+ check(num, bd, multiplier);
+ }
+
+ static void check(Number got, BigDecimal expected, int multiplier) {
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println("Failed: got:" + got +
+ ", expected: " + expected +
+ ", multiplier=" + multiplier);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/BigDecimalFormat.java b/test/java/text/Format/NumberFormat/BigDecimalFormat.java
new file mode 100644
index 0000000000..14b3a9fec6
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/BigDecimalFormat.java
@@ -0,0 +1,1044 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4018937 8008577
+ * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalFormat
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalFormat extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new BigDecimalFormat().run(args);
+ }
+
+ static final String nonsep_int =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ static final String sep_int =
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890";
+
+ static final String nonsep_zero =
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000";
+
+ static final String sep_zero =
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000";
+
+ static final String fra =
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789";
+
+
+ StringBuffer formatted = new StringBuffer(1000);
+ FieldPosition fp;
+
+ /**
+ * Test for normal big numbers which have the fraction part
+ */
+ void test_Format_in_NumberFormat_BigDecimal() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+ // From: 0.000...789
+ // To: 0.000...789 (same as From)
+ formatted.setLength(0);
+ from = "0." + nonsep_zero + "123456789";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -0.000...789
+ // To: -0.000...789 (same as From)
+ // ~ : FieldPosition(SIGN)
+ fp = new FieldPosition(NumberFormat.Field.SIGN);
+ formatted.setLength(0);
+ from = "-0." + nonsep_zero + "123456789";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, from, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 0, 1);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1234...7890.012...789
+ // To: 123,4...7,890.012...789
+ // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD)
+ fp = new FieldPosition(DecimalFormat.INTEGER_FIELD);
+ formatted.setLength(0);
+ from = nonsep_int + "." + fra;
+ to = sep_int + "." + fra;
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 0, 479);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...7890.012...789
+ // To: -123,4...7,890.012...789
+ // ~~~~~~~~~ : FieldPosition(FRACTION_FIELD)
+ fp = new FieldPosition(DecimalFormat.FRACTION_FIELD);
+ formatted.setLength(0);
+ from = "-" + nonsep_int + "." + fra;
+ to = "-" + sep_int + "." + fra;
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 481, 841);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1234...78900000...0000.000...789
+ // To: 123,4...7,890,000,0...0,000.000...789
+ formatted.setLength(0);
+ from = nonsep_int + nonsep_zero + "." + nonsep_zero + fra;
+ to = sep_int + "," + sep_zero + "." + nonsep_zero + fra;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...78900000...0000.000...789
+ // To: -123,4...7,890,000,0...0,000.000...789
+ formatted.setLength(0);
+ from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + fra;
+ to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + fra;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1234...78900000...0000
+ // To: 123,4...7,890,000,0...0,000
+ formatted.setLength(0);
+ from = nonsep_int + nonsep_zero;
+ to = sep_int + "," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...78900000...0000
+ // To: -123,4...7,890,000,0...0,000
+ formatted.setLength(0);
+ from = "-" + nonsep_int + nonsep_zero;
+ to = "-" + sep_int + "," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1234...78900000...0000.0...0
+ // To: 1,234...7,890,000,0...0,000
+ formatted.setLength(0);
+ from = nonsep_int + nonsep_zero + "." + nonsep_zero;
+ to = sep_int + "," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...78900000...0000.0...0
+ // To: -1,234...7,890,000,0...0,000
+ formatted.setLength(0);
+ from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero;
+ to = "-" + sep_int + "," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 000...0000
+ // To: 0
+ formatted.setLength(0);
+ from = nonsep_zero;
+ to = "0";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -000...0000
+ // To: 0
+ formatted.setLength(0);
+ from = "-" + nonsep_zero;
+ to = "0";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 000...00001234
+ // To: 1,234
+ formatted.setLength(0);
+ from = nonsep_zero + "1234";
+ to = "1,234";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -000...00001234
+ // To: -1,234
+ // ~ : FieldPosition(GROUPING_SEPARATOR)
+ fp = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
+ formatted.setLength(0);
+ from = "-" + nonsep_zero + "1234";
+ to = "-1,234";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 2, 3);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 000...0000.0...0
+ // To: 0
+ formatted.setLength(0);
+ from = nonsep_zero + "." + nonsep_zero;
+ to = "0";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.0");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1);
+
+ // From: -000...0000.0...0
+ // To: 0.0
+ formatted.setLength(0);
+ from = "-" + nonsep_zero + "." + nonsep_zero;
+ to = "0.0";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1234...7890.012...7890...0
+ // To: 1,234...7,890.0123...789
+ formatted.setLength(0);
+ from = nonsep_int + "." + fra + nonsep_zero;
+ to = sep_int + "." + fra;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...7890.012...7890...0
+ // To: -1,234...7,890.0123...789
+ formatted.setLength(0);
+ from = "-" + nonsep_int + "." + fra + nonsep_zero;
+ to = "-" + sep_int + "." + fra;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+ // From: 1123...890.012...789
+ // To : 1.123...8900123...789E360
+ // ~~~ : FieldPosition(EXPONENT)
+ fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+ formatted.setLength(0);
+ from = "1" + nonsep_int + "." + fra;
+ to = "1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 723, 726);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1123...890.012...789
+ // To : -1.123...8900123...789E360
+ formatted.setLength(0);
+ from = "-1" + nonsep_int + "." + fra;
+ to = "-1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+ // From: 0.000...0001123...890.012...789
+ // To : 1.123...8900123...789E-360
+ formatted.setLength(0);
+ from = "0." + nonsep_zero + "1" + fra;
+ to = "1." + fra + "E-361";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -0.000...0001123...890.012...789
+ // To : -1.123...8900123...789E-360
+ formatted.setLength(0);
+ from = "-0." + nonsep_zero + "1" + fra;
+ to = "-1." + fra + "E-361";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 1123...890.012...789000...000
+ // To : 1.123...8900123...789E360
+ formatted.setLength(0);
+ from = "1" + nonsep_int + "." + fra + nonsep_zero;
+ to = "1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1123...890.012...789000...000
+ // To : -1.123...8900123...789E360
+ // ~ : FieldPosition(EXPONENT_SYMBOL)
+ fp = new FieldPosition(NumberFormat.Field.EXPONENT_SYMBOL);
+ formatted.setLength(0);
+ from = "-1" + nonsep_int + "." + fra + nonsep_zero;
+ to = "-1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 723, 724);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 0.000...0001123...890.012...789000...000
+ // To : 1.123...8900123...789E-360
+ // ~ : FieldPosition(EXPONENT_SIGN)
+ fp = new FieldPosition(NumberFormat.Field.EXPONENT_SIGN);
+ formatted.setLength(0);
+ from = "0." + nonsep_zero + "1" + fra + nonsep_zero;
+ to = "1." + fra + "E-361";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 363, 364);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -0.000...0001123...890.012...789000...000
+ // To : -1.123...8900123...789E-360
+ formatted.setLength(0);
+ from = "-0." + nonsep_zero + "1" + fra + nonsep_zero;
+ to = "-1." + fra + "E-361";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: ABC1123...890.012...789
+ // To : ABC1.123...890.0123...789
+ formatted = new StringBuffer("ABC");
+ from = "1" + nonsep_int + "." + fra;
+ to = "ABC1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: ABC-1123...890.012...789
+ // To : ABC-1.123...890.0123...789
+ // ~ : FieldPosition(DECIMAL_SEPARATOR)
+ fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
+ formatted = new StringBuffer("ABC");
+ from = "-1" + nonsep_int + "." + fra;
+ to = "ABC-1." + nonsep_int + fra + "E360";
+ nf.format(new BigDecimal(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 5, 6);
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, 726, 0);
+
+ // From: 0.000...000012...7890123456789
+ // To: 0.000...000012...789012346 (Shorter than From)
+ formatted.setLength(0);
+ from = "0." + nonsep_zero + fra + fra;
+ to = "0." + nonsep_zero + fra + "012346";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, 723, 0);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -0.000...000012...7890123456789
+ // To: -0.000...000012...789012 (Shorter than From)
+ formatted.setLength(0);
+ from = "-0." + nonsep_zero + fra + fra;
+ to = "-0." + nonsep_zero + fra + "012";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("00000.###E0");
+ setDigits(nf, 5, 5, 370, 0);
+
+ // From: 1234567890.012...78901234567890
+ // To: 12345.67890012...789012346E5
+ formatted.setLength(0);
+ from = "1234567890." + fra + "0123456789";
+ to = "12345.67890" + fra + "01235E5";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, 364, 0);
+
+ // From: -0.000...0001012...7890123456789
+ // To: -1.012...789012E-361
+ formatted.setLength(0);
+ from = "-0." + nonsep_zero + "1" + fra + "0123456789";
+ to = "-1." + fra + "0123E-361";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, 366, 0);
+
+ // From: 1012...78901234567890
+ // To: 1.012...789012346E370
+ formatted.setLength(0);
+ from = "1" + fra + "0123456789";
+ to = "1." + fra + "012346E370";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, 363, 0);
+
+ // From: -1012...7890123456789
+ // To: -1.012...789012E370
+ formatted.setLength(0);
+ from = "-1" + fra + "0123456789";
+ to = "-1." + fra + "012E370";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 720);
+
+ // From: 1234...78900000...0000.0...0
+ // To: 1,234...7,890,000,0...0,000.0...0
+ formatted.setLength(0);
+ from = nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero;
+ to = sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...78900000...0000.0...0
+ // To: -1,234...7,890,000,0...0,000.0...0
+ formatted.setLength(0);
+ from = "-" + nonsep_int + nonsep_zero + "." + nonsep_zero + nonsep_zero;
+ to = "-" + sep_int + "," + sep_zero + "." + nonsep_zero + nonsep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ }
+
+ /**
+ * Test for normal big numbers which have the fraction part with multiplier
+ */
+ void test_Format_in_NumberFormat_BigDecimal_usingMultiplier() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+ ((DecimalFormat)nf).setMultiplier(250000000);
+ ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true);
+
+ // From: 1000...0000.000...000
+ // To: 250,0...0,000.
+ formatted.setLength(0);
+ from = "1" + nonsep_zero + "." + nonsep_zero;
+ to = "250,000,000," + sep_zero + ".";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false);
+
+ // From: -1000...0000.000...000
+ // To: -250,0...0,000
+ formatted.setLength(0);
+ from = "-1" + nonsep_zero + "." + nonsep_zero;
+ to = "-250,000,000," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+ ((DecimalFormat)nf).setMultiplier(-250000000);
+ ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(true);
+
+ // From: 1000...0000.000...000
+ // To: -250,0...0,000.
+ formatted.setLength(0);
+ from = "1" + nonsep_zero + "." + nonsep_zero;
+ to = "-250,000,000," + sep_zero + ".";
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).setDecimalSeparatorAlwaysShown(false);
+
+ // From: -1000...0000.000...000
+ // To: 250,0...0,000
+ formatted.setLength(0);
+ from = "-1" + nonsep_zero + "." + nonsep_zero;
+ to = "250,000,000," + sep_zero;
+ nf.format(new BigDecimal(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ }
+
+ /**
+ * Test for normal big numbers which don't have the fraction part
+ */
+ void test_Format_in_NumberFormat_BigInteger() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ if (!(nf instanceof DecimalFormat)) {
+ throw new RuntimeException("Couldn't get DecimalFormat instance.");
+ }
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+ // From: 1234...7890
+ // To: 123,4...7,890
+ formatted.setLength(0);
+ from = nonsep_int;
+ to = sep_int;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1234...7890
+ // To: -123,4...7,890
+ // ~~~~~~~~~~~~~ : FieldPosition(INTEGER_FIELD)
+ fp = new FieldPosition(DecimalFormat.INTEGER_FIELD);
+ formatted.setLength(0);
+ from = "-" + nonsep_int;
+ to = "-" + sep_int;
+ nf.format(new BigInteger(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 1, 480);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 000...0001234...7890
+ // To: 123,4...7,890
+ formatted.setLength(0);
+ from = nonsep_zero + nonsep_int;
+ to = sep_int;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -000...0001234...7890
+ // To: -123,4...7,890
+ // ~ : FieldPosition(SIGN)
+ fp = new FieldPosition(NumberFormat.Field.SIGN);
+ formatted.setLength(0);
+ from = "-" + nonsep_zero + nonsep_int;
+ to = "-" + sep_int;
+ nf.format(new BigInteger(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 0, 1);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: 000...0000
+ // To: 0
+ formatted.setLength(0);
+ from = nonsep_zero;
+ to = "0";
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.0");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 1);
+
+ // From: -000...0000
+ // To: 0.0
+ fp = new FieldPosition(NumberFormat.Field.DECIMAL_SEPARATOR);
+ formatted.setLength(0);
+ from = "-" + nonsep_zero;
+ to = "0.0";
+ nf.format(new BigInteger(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 1, 2);
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ setDigits(nf, 1, 1, Integer.MAX_VALUE, 0);
+
+ // From: 10123...789
+ // To : 1.0123...789E360
+ // ~~~ : FieldPosition(EXPONENT)
+ fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+ formatted.setLength(0);
+ from = "1" + fra;
+ to = "1." + fra + "E360";
+ nf.format(new BigInteger(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 363, 366);
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1012...789
+ // To : -1.012...789E360
+ formatted.setLength(0);
+ from = "-1" + fra;
+ to = "-1." + fra + "E360";
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("00000.###E0");
+ setDigits(nf, 5, 5, Integer.MAX_VALUE, 720);
+
+ // From: 12345012...789000...000
+ // To : 12345.012...789000...000E720
+ // ~~~ : FieldPosition(EXPONENT)
+ fp = new FieldPosition(NumberFormat.Field.EXPONENT);
+ formatted.setLength(0);
+ from = "12345" + fra + nonsep_zero;
+ to = "12345." + fra + nonsep_zero + "E720";
+ nf.format(new BigInteger(from), formatted, fp);
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ checkFieldPosition(from, fp, 727, 730);
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("00000.###E0");
+ setDigits(nf, 5, 5, Integer.MAX_VALUE, 365);
+
+ // From: -1234567890012...789000...000
+ // To : -12345.67890012...789E365
+ formatted.setLength(0);
+ from = "-1234567890" + fra;
+ to = "-12345.67890" + fra + "E365";
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ }
+
+ /**
+ * Test for normal big numbers which don't have the fraction part with
+ * multiplier
+ */
+ void test_Format_in_NumberFormat_BigInteger_usingMultiplier() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ ((DecimalFormat)nf).setMultiplier(250000000);
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+ // From: 1000...0000
+ // To: 250,0...0,000
+ formatted.setLength(0);
+ from = "1" + nonsep_zero;
+ to = "250,000,000," + sep_zero;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1000...0000
+ // To: -250,0...0,000
+ formatted.setLength(0);
+ from = "-1" + nonsep_zero;
+ to = "-250,000,000," + sep_zero;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ ((DecimalFormat)nf).setMultiplier(-250000000);
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+ // From: 1000...0000
+ // To: -250,0...0,000
+ formatted.setLength(0);
+ from = "1" + nonsep_zero;
+ to = "-250,000,000," + sep_zero;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ // From: -1000...0000
+ // To: 250,0...0,000
+ formatted.setLength(0);
+ from = "-1" + nonsep_zero;
+ to = "250,000,000," + sep_zero;
+ nf.format(new BigInteger(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ }
+
+ /**
+ * Test for normal Long numbers when maximum and minimum digits are
+ * specified
+ */
+ void test_Format_in_NumberFormat_Long_checkDigits() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ if (!(nf instanceof DecimalFormat)) {
+ throw new RuntimeException("Couldn't get DecimalFormat instance.");
+ }
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0);
+
+ // From: 1234567890
+ // To: 000,0...0,000,123,456,789
+ // -------------
+ // 300 zeros
+ formatted.setLength(0);
+ from = "123456789";
+ to = sep_zero.substring(0, 399) + ",123,456,789";
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("##0.###");
+ ((DecimalFormat)nf).setMultiplier(-1);
+ setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+ // From: 1234567890
+ // To: -0000...0000123456789.000...000
+ // -------------
+ // 300 zeros
+ formatted.setLength(0);
+ from = "123456789";
+ to = "-" + nonsep_zero.substring(0, 300) + "123456789." +
+ nonsep_zero.substring(0, 340);
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE);
+ setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 0);
+
+ // From: Long.MAX_VALUE
+ // To: 000,0...0,000,019,807,040,619,342,712,359,383,728,129
+ // ---------------
+ // 280 zeros
+ formatted.setLength(0);
+ from = Long.toString(Long.MAX_VALUE);
+ to = sep_zero.substring(0, 373) +
+ "19,807,040,619,342,712,359,383,728,129";
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("0.###E0");
+ ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE);
+ setDigits(nf, 1, 1, Integer.MAX_VALUE, 360);
+
+ // From: Long.MAX_VALUE
+ // To: -1.9807040628566084396238503936000...000E28
+ // ---------
+ // 312 zeros
+ formatted.setLength(0);
+ from = Long.toString(Long.MAX_VALUE);
+ to = "-1.9807040628566084396238503936" +
+ nonsep_zero.substring(0, 312) + "E28";
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("##0.###E0");
+ ((DecimalFormat)nf).setMultiplier(Integer.MAX_VALUE);
+ setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+ // From: Long.MIN_VALUE
+ // To: -198070406193427123615312117760000...0000.000...000E-280
+ // ----------- ---------
+ // 280 zeros 340 zeros
+ formatted.setLength(0);
+ from = Long.toString(Long.MIN_VALUE);
+ to = "-19807040619342712361531211776" +
+ nonsep_zero.substring(0, 280) + "." +
+ nonsep_zero.substring(0, 340) + "E-280";
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+
+ /* ------------------------------------------------------------------ */
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ ((DecimalFormat)nf).setMultiplier(Integer.MIN_VALUE);
+ setDigits(nf, Integer.MAX_VALUE, 360, Integer.MAX_VALUE, 360);
+
+ // From: Long.MIN_VALUE
+ // To: 000,0...0,000,019,807,040,628,566,084,398,385,987,584.000...000
+ // --------------- ---------
+ // 280 zeros 340 zeros
+ formatted.setLength(0);
+ from = Long.toString(Long.MIN_VALUE);
+ to = sep_zero.substring(0, 373) +
+ "19,807,040,628,566,084,398,385,987,584." +
+ nonsep_zero.substring(0, 340);
+ nf.format(new Long(from), formatted, new FieldPosition(0));
+ checkFormat(from, formatted, to, ((DecimalFormat)nf).getMultiplier());
+ }
+
+ /**
+ * Test for special numbers
+ * Double.NaN
+ * Double.POSITIVE_INFINITY
+ * Double.NEGATIVE_INFINITY
+ */
+ void test_Format_in_NumberFormat_SpecialNumber() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ if (!(nf instanceof DecimalFormat)) {
+ throw new RuntimeException("Couldn't get DecimalFormat instance.");
+ }
+
+ ((DecimalFormat)nf).applyPattern("#,##0.###");
+ setDigits(nf, Integer.MAX_VALUE, 1, Integer.MAX_VALUE, 0);
+
+ double[] numbers = {
+ -0.0, 0.0, Double.NaN,
+ Double.POSITIVE_INFINITY, 5.1, 5.0,
+ Double.NEGATIVE_INFINITY, -5.1, -5.0,
+ };
+ int multipliers[] = {0, 5, -5};
+ String[][] expected = {
+ {"-0", "0", "\ufffd", "\ufffd", "0", "0", "\ufffd", "-0", "-0"},
+ {"-0", "0", "\ufffd", "\u221e", "25.5", "25", "-\u221e", "-25.5",
+ "-25"},
+ {"0", "-0", "\ufffd", "-\u221e", "-25.5", "-25", "\u221e", "25.5",
+ "25"},
+ };
+
+ for (int i = 0; i < multipliers.length; i++) {
+ ((DecimalFormat)nf).setMultiplier(multipliers[i]);
+ for (int j = 0; j < numbers.length; j++) {
+ formatted.setLength(0);
+ from = String.valueOf(numbers[j]);
+ nf.format(numbers[j], formatted, new FieldPosition(0));
+ checkFormat(from, formatted, expected[i][j],
+ ((DecimalFormat)nf).getMultiplier());
+ }
+ }
+ }
+
+ /**
+ * Test for Long.MIN_VALUE
+ * (Formatting Long.MIN_VALUE w/ multiplier=-1 used to return a wrong
+ * number.)
+ */
+ void test_Format_in_NumberFormat_Other() {
+ String from, to;
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ if (!(nf instanceof DecimalFormat)) {
+ throw new RuntimeException("Couldn't get DecimalFormat instance.");
+ }
+
+ long[] numbers = {
+ Long.MIN_VALUE,
+ };
+ int multipliers[] = {1, -1};
+ String[][] expected = {
+ {"-9,223,372,036,854,775,808"}, // Long.MIN_VALUE
+ {"9,223,372,036,854,775,808"}, // Long.MIN_VALUE * (-1)
+ };
+
+ for (int i = 0; i < multipliers.length; i++) {
+ ((DecimalFormat)nf).setMultiplier(multipliers[i]);
+ for (int j = 0; j < numbers.length; j++) {
+ formatted.setLength(0);
+ from = String.valueOf(numbers[j]);
+ nf.format(numbers[j], formatted, new FieldPosition(0));
+ checkFormat(from, formatted, expected[i][j],
+ ((DecimalFormat)nf).getMultiplier());
+ }
+ }
+ }
+
+ /**
+ * Test for MessageFormat
+ */
+ void test_Format_in_MessageFormat() {
+ MessageFormat mf = new MessageFormat(
+ " {0, number}\n" +
+ " {0, number, integer}\n" +
+ " {0, number, currency}\n" +
+ " {0, number, percent}\n" +
+ " {0, number,0.###########E0}\n" +
+
+ " {1, number}\n" +
+ " {1, number, integer}\n" +
+ " {1, number, currency}\n" +
+ " {1, number, percent}\n" +
+ " {1, number,0.#######E0}\n",
+ Locale.US
+ );
+ Object[] testArgs = {
+ new BigInteger("9876543210987654321098765432109876543210"),
+ new BigDecimal("-12345678901234567890.98765432109876543210987654321"),
+ };
+ String expected =
+ " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" +
+ " 9,876,543,210,987,654,321,098,765,432,109,876,543,210\n" +
+ " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00\n" +
+ " 987,654,321,098,765,432,109,876,543,210,987,654,321,000%\n" +
+ " 9.87654321099E39\n" +
+
+ " -12,345,678,901,234,567,890.988\n" +
+ " -12,345,678,901,234,567,891\n" +
+ " ($12,345,678,901,234,567,890.99)\n" +
+ " -1,234,567,890,123,456,789,099%\n" +
+ " -1.2345679E19\n"
+ ;
+
+ if (!expected.equals(mf.format(testArgs))) {
+ errln("Wrong format.\n got:\n" + mf.format(testArgs) +
+ " expected:\n" + expected);
+ }
+ }
+
+ private void setDigits(NumberFormat nf,
+ int i_max, int i_min, int f_max, int f_min) {
+ nf.setMaximumIntegerDigits(i_max);
+ nf.setMinimumIntegerDigits(i_min);
+ nf.setMaximumFractionDigits(f_max);
+ nf.setMinimumFractionDigits(f_min);
+ }
+
+ private void checkFormat(String orig, StringBuffer got, String expected,
+ int multiplier) {
+ if (!expected.equals(new String(got))) {
+ errln("Formatting... failed." +
+ "\n original: " + orig +
+ "\n multiplier: " + multiplier +
+ "\n formatted: " + got +
+ "\n expected: " + expected + "\n");
+ }
+ }
+
+ private void checkFieldPosition(String orig, FieldPosition fp, int begin,
+ int end) {
+ int position;
+
+ if ((position = fp.getBeginIndex()) != begin) {
+ errln("Formatting... wrong Begin index returned for " +
+ fp.getFieldAttribute() + "." +
+ "\n original: " + orig +
+ "\n got: " + position +
+ "\n expected: " + begin + "\n");
+ }
+ if ((position = fp.getEndIndex()) != end) {
+ errln("Formatting... wrong End index returned for " +
+ fp.getFieldAttribute() + "." +
+ "\n original: " + orig +
+ "\n got: " + position +
+ "\n expected: " + end + "\n");
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/BigDecimalParse.java b/test/java/text/Format/NumberFormat/BigDecimalParse.java
new file mode 100644
index 0000000000..be206052d0
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/BigDecimalParse.java
@@ -0,0 +1,709 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4018937 8008577
+ * @summary Confirm that methods which are newly added to support BigDecimal and BigInteger work as expected.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI BigDecimalParse
+ */
+
+import java.math.BigDecimal;
+import java.text.*;
+import java.util.*;
+
+public class BigDecimalParse extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ Locale loc = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ new BigDecimalParse().run(args);
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(loc);
+ }
+ }
+
+ static final String nonsep_int =
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890" +
+ "123456789012345678901234567890123456789012345678901234567890";
+
+ static final String sep_int =
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890," +
+ "123,456,789,012,345,678,901,234,567,890";
+
+ static final String nonsep_zero =
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000" +
+ "000000000000000000000000000000000000000000000000000000000000";
+
+ static final String sep_zero =
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000," +
+ "000,000,000,000,000,000,000,000,000,000";
+
+ static final String fra =
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789" +
+ "012345678901234567890123456789012345678901234567890123456789";
+
+
+ Number parsed = null;
+ ParsePosition pp;
+ boolean exceptionOccurred;
+ String msg;
+ DecimalFormat df;
+
+ /**
+ * Test for normal big numbers which have the fraction part
+ */
+ void test_Parse_in_DecimalFormat_BigDecimal() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ // From: 1234...7890.012...789
+ // To: BigDecimal 1234...7890.012...789
+ check(nonsep_int + "." + fra, new BigDecimal(nonsep_int + "." + fra));
+
+ // From: -1,234...7,890.012...789
+ // To: BigDecimal -1234...7890.012...789
+ check("-" + sep_int + "." + fra,
+ new BigDecimal("-" + nonsep_int + "." + fra));
+
+ // From: 000...0000.0...0
+ // To: BigDecimal 0E-360
+ check(nonsep_zero + "." + nonsep_zero,
+ new BigDecimal(nonsep_zero + "." + nonsep_zero));
+
+ // From: 0.000...0000123...789E370
+ // To: BigDecimal 0.0123...789
+ check("0.0000000000" + nonsep_zero + fra + "E370",
+ new BigDecimal("0.0000000000" + nonsep_zero + fra + "E370"));
+
+ // From: 0.1123...890E-360
+ // To: BigDecimal 1.123...890E-361
+ check("0.1" + nonsep_int + "E-360",
+ new BigDecimal("0.1" + nonsep_int + "E-360"));
+
+ // From: 000...0000.0...0123...7890
+ // To: BigDecimal 1.234...890E-361
+ check(nonsep_zero + "." + nonsep_zero + nonsep_int,
+ new BigDecimal(nonsep_zero + "." + nonsep_zero + nonsep_int));
+
+ // From: 0.123...890E360
+ // To: BigDecimal 123...890
+ check("0." + nonsep_int + "E360",
+ new BigDecimal("0." + nonsep_int + "E360"));
+ }
+
+ /**
+ * Test for normal big numbers which have the fraction part with multiplier
+ */
+ void test_Parse_in_DecimalFormat_BigDecimal_usingMultiplier() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ // From: 250,0...0,000.000...000
+ // To: 1000...0000.000...000
+ df.setMultiplier(250000000);
+ check("250,000,000," + sep_zero + "." + nonsep_zero,
+ new BigDecimal("1" + nonsep_zero + "." + nonsep_zero));
+
+ // From: -250,0...0,000.000...000
+ // To: -1000...0000.000...000
+ check("-250,000,000," + sep_zero + "." + nonsep_zero,
+ new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+ // From: 250,0...0,000.000...000
+ // To: -1000...0000.000...000
+ df.setMultiplier(-250000000);
+ check("250,000,000," + sep_zero + "." + nonsep_zero,
+ new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+ // From: -250,0...0,000.000...000
+ // To: 1000...0000.000...000
+ check("-250,000,000," + sep_zero + "." + nonsep_zero,
+ new BigDecimal("1" + nonsep_zero + "." + nonsep_zero));
+
+ // Confirm that ArithmeticException is handled properly
+ // From: 1000.000
+ // To: 333.333
+ df.setMultiplier(3);
+ check("1000.000", new BigDecimal("333.333"));
+
+ // Confirm that ArithmeticException is handled properly
+ // From: 10000.0000
+ // To: 303.0303
+ df.setMultiplier(33);
+ check("10000.0000", new BigDecimal("303.0303"));
+ }
+
+ /**
+ * Test for division by zero (BigDecimal)
+ */
+ void test_Parse_in_DecimalFormat_BigDecimal_DivisionByZero() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+ df.setMultiplier(0);
+
+ // From: 1000.000
+ // To: Double.POSITIVE_INFINITY
+ check("1000.000", new Double(Double.POSITIVE_INFINITY));
+
+ // From: -1000
+ // To: Double.NEGATIVE_INFINITY
+ check("-1000", new Double(Double.NEGATIVE_INFINITY));
+
+ // From: -0.00
+ // To: Double.NaN
+ check("-0.00", new Double(Double.NaN));
+ }
+
+ /**
+ * Test for division by zero (Double)
+ */
+ void test_Parse_in_DecimalFormat_Double_DivisionByZero() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(false);
+ df.setMultiplier(0);
+
+ // From: 1000.000
+ // To: Double.POSITIVE_INFINITY
+ check("1000.000", new Double(Double.POSITIVE_INFINITY));
+
+ // From: -1000.000
+ // To: Double.NEGATIVE_INFINITY
+ check("-1000.000", new Double(Double.NEGATIVE_INFINITY));
+
+ // From: 0.0
+ // To: Double.NaN
+ check("0.0", new Double(Double.NaN));
+
+ // From: -0.0 (Double)
+ // To: Double.NaN
+ check("-0.0", new Double(Double.NaN));
+
+ // From: Double.NaN
+ // To: Double.NaN
+ check("\ufffd", new Double(Double.NaN));
+
+ // From: Double.POSITIVE_INFINITY
+ // To: Double.NaN
+ check("\u221e", new Double(Double.POSITIVE_INFINITY));
+
+ // From: Double.NEGATIVE_INFINITY
+ // To: Double.NaN
+ check("-\u221e", new Double(Double.NEGATIVE_INFINITY));
+ }
+
+ /**
+ * Test for division by zero (Long)
+ */
+ void test_Parse_in_DecimalFormat_Long_DivisionByZero() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(false);
+ df.setMultiplier(0);
+
+ // From: 1000
+ // To: Double.POSITIVE_INFINITY
+ check("1000", new Double(Double.POSITIVE_INFINITY));
+
+ // From: -1000
+ // To: Double.NEGATIVE_INFINITY
+ check("-1000", new Double(Double.NEGATIVE_INFINITY));
+
+ // From: -000 (Long)
+ // To: Double.NaN
+ check("-000", new Double(Double.NaN));
+ }
+
+ /**
+ * Test for normal big numbers which don't have the fraction part
+ */
+ void test_Parse_in_DecimalFormat_BigInteger() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ // From: 123...890
+ // To: BigDecimal 123...890
+ check(nonsep_int + nonsep_int, new BigDecimal(nonsep_int + nonsep_int));
+
+ // From: 123,4...7,890
+ // To: BigDecimal 1234...7890
+ check(sep_int + "," + sep_int, new BigDecimal(nonsep_int + nonsep_int));
+
+ // From: -000...000123...890
+ // To: BigDecimal -123...890
+ check("-" + nonsep_zero + nonsep_int, new BigDecimal("-" + nonsep_int));
+
+ // From: -000,0...0,000,123,4...7,890
+ // To: BigDecimal -123...890
+ check("-" + sep_zero + "," + sep_int, new BigDecimal("-" + nonsep_int));
+ }
+
+ /**
+ * Test for normal big numbers which don't have the fraction part with
+ * multiplier
+ */
+ void test_Parse_in_DecimalFormat_BigInteger_usingMultiplier() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ // From: 250,0...0,000
+ // To: 1000...0000
+ df.setMultiplier(250000000);
+ check("250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero));
+
+ // From: -250,0...0,000
+ // To: -1000...0000
+ check("-250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero));
+
+ // From: 250,0...0,000
+ // To: -1000...0000
+ df.setMultiplier(-250000000);
+ check("250,000,000," + sep_zero, new BigDecimal("-1" + nonsep_zero));
+
+ // From: -250,0...0,000
+ // To: 1000...0000
+ check("-250,000,000," + sep_zero, new BigDecimal("1" + nonsep_zero));
+
+ // From: 250,0...0,000E-360
+ // To: -1000...0000.000...000
+ check("250,000,000," + sep_zero + "," + sep_zero + "E-360",
+ new BigDecimal("-1" + nonsep_zero + "." + nonsep_zero));
+
+ // Confirm that a division which results in a irrational number is done
+ // properly
+ // From: 1000
+ // To: 333
+ df.setMultiplier(3);
+ check("1000", new BigDecimal("333"));
+ }
+
+ /**
+ * Test for special numbers
+ * Double.NaN
+ * Double.POSITIVE_INFINITY
+ * Double.NEGATIVE_INFINITY
+ */
+ void test_Parse_in_DecimalFormat_SpecialNumber() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ String[] numbers = {
+ "0", "0.0", "25", "25.0", "25.5", "\u221e", "\ufffd",
+ "-0", "-0.0", "-25", "-25.0", "-25.5", "-\u221e",
+ };
+ int multipliers[] = {5, -5};
+ Number[][] expected = {
+ {
+ new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"),
+ new BigDecimal("5.0"), new BigDecimal("5.1"),
+ new Double(Double.POSITIVE_INFINITY), new Double(Double.NaN),
+ new BigDecimal("0"), new BigDecimal("0.0"),
+ new BigDecimal("-5"), new BigDecimal("-5.0"),
+ new BigDecimal("-5.1"),
+ new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN),
+ },
+ {
+ new BigDecimal("0"), new BigDecimal("0.0"),
+ new BigDecimal("-5"), new BigDecimal("-5.0"),
+ new BigDecimal("-5.1"),
+ new Double(Double.NEGATIVE_INFINITY), new Double(Double.NaN),
+ new BigDecimal("0"), new BigDecimal("0.0"), new BigDecimal("5"),
+ new BigDecimal("5.0"), new BigDecimal("5.1"),
+ new Double(Double.POSITIVE_INFINITY),
+ },
+ };
+
+ for (int i = 0; i < multipliers.length; i++) {
+ df.setMultiplier(multipliers[i]);
+ for (int j = 0; j < numbers.length; j++) {
+ check(String.valueOf(numbers[j]), expected[i][j]);
+ }
+ }
+ }
+
+ /**
+ * Test for special numbers
+ */
+ void test_Parse_in_DecimalFormat_Other() {
+ df = new DecimalFormat();
+ df.setParseBigDecimal(true);
+
+ String[] numbers = {
+ "-9223372036854775808", // Long.MIN_VALUE
+ };
+ int multipliers[] = {1, -1};
+ String[][] expected = {
+ {"-9223372036854775808"}, // Long.MIN_VALUE
+ {"9223372036854775808"}, // Long.MAX_VALUE+1 = abs(MIN_VALUE)
+ };
+
+ for (int i = 0; i < multipliers.length; i++) {
+ df.setMultiplier(multipliers[i]);
+ for (int j = 0; j < numbers.length; j++) {
+ check(String.valueOf(numbers[j]),
+ new BigDecimal(expected[i][j]));
+ }
+ }
+ }
+
+ static final String[] patterns = {
+ " {0, number} ",
+ " {0, number} ",
+ " {0, number, currency} ",
+ " {0, number, currency} ",
+ " {0, number, percent} ",
+ " {0, number, percent} ",
+ " {0, number,#,##0.###E0} ",
+ " {0, number,#,##0.###E0} ",
+
+ " {0, number} ",
+ " {0, number} ",
+ " {0, number, integer} ",
+ " {0, number, integer} ",
+ " {0, number, currency} ",
+ " {0, number, currency} ",
+ " {0, number, percent} ",
+ " {0, number, percent} ",
+ " {0, number,#,##0.###E0} ",
+ " {0, number,#,##0.###E0} ",
+ };
+ static final String[] from = {
+ " 12,345,678,901,234,567,890.98765432109876543210987654321 ",
+ " -12,345,678,901,234,567,890.98765432109876543210987654321 ",
+ " $12,345,678,901,234,567,890.98765432109876543210987654321 ",
+ " ($12,345,678,901,234,567,890.98765432109876543210987654321) ",
+ " 1,234,567,890,123,456,789,098.76543210987654321098765432100% ",
+ " -1,234,567,890,123,456,789,098.76543210987654321098765432100% ",
+ " 12,345,678,901,234,567,890.98765432109876543210987654321E-20 ",
+ " -12,345,678,901,234,567,890.98765432109876543210987654321E-20 ",
+
+ " 9,876,543,210,987,654,321,098,765,432,109,876,543,210 ",
+ " -9,876,543,210,987,654,321,098,765,432,109,876,543,210 ",
+ " 9,876,543,210,987,654,321,098,765,432,109,876,543,210E5 ",
+ " -9,876,543,210,987,654,321,098,765,432,109,876,543,210E-5 ",
+ " $9,876,543,210,987,654,321,098,765,432,109,876,543,210.00 ",
+ " ($9,876,543,210,987,654,321,098,765,432,109,876,543,210.00) ",
+ " 987,654,321,098,765,432,109,876,543,210,987,654,321,012% ",
+ " -987,654,321,098,765,432,109,876,543,210,987,654,321,012% ",
+ " 98,765,432,109,876,543,210.98765432109876543210E20 ",
+ " -987,654,321,098,765,432,109,876,543,210,987,654,321,000,000,000,000,000,000,000E-20 ",
+ };
+
+ static final String[] expected1 = { // isParseIntegerOnly() == false
+ "12345678901234567890.98765432109876543210987654321",
+ "-12345678901234567890.98765432109876543210987654321",
+ "12345678901234567890.98765432109876543210987654321",
+ "-12345678901234567890.98765432109876543210987654321",
+ "12345678901234567890.98765432109876543210987654321",
+ "-12345678901234567890.98765432109876543210987654321",
+ "0.1234567890123456789098765432109876543210987654321",
+ "-0.1234567890123456789098765432109876543210987654321",
+
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210",
+ "9.876543210987654321098765432109876543210E44",
+ "-98765432109876543210987654321098765.43210",
+ "9876543210987654321098765432109876543210.00",
+ "-9876543210987654321098765432109876543210.00",
+ "9876543210987654321098765432109876543210.12",
+ "-9876543210987654321098765432109876543210.12",
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210.00000000000000000000",
+ };
+ static final int[] parsePosition1 = {
+ 60, 61, 61, 63, 64, 65, 64, 65,
+ 57, 58, 59, 61, 61, 63, 60, 61, 54, 88,
+ };
+
+ /**
+ * Test for MessageFormat: setParseIntegerOnly(false)
+ */
+ void test_Parse_in_MessageFormat_NotParseIntegerOnly() {
+ for (int i=0; i < patterns.length; i++) {
+ pp = new ParsePosition(0);
+ Object[] parsed = null;
+
+ try {
+ MessageFormat mf = new MessageFormat(patterns[i]);
+ Format[] formats = mf.getFormats();
+ for (int j=0; j < formats.length; j++) {
+ ((DecimalFormat)formats[j]).setParseBigDecimal(true);
+ }
+
+ parsed = mf.parse(from[i], pp);
+
+ if (pp.getErrorIndex() != -1) {
+ errln("Case" + (i+1) +
+ ": getErrorIndex() returns wrong value. expected:-1, got:"+
+ pp.getErrorIndex() + " for " + from[i]);
+ }
+ if (pp.getIndex() != parsePosition1[i]) {
+ errln("Case" + (i+1) +
+ ": getIndex() returns wrong value. expected:" +
+ parsePosition1[i] + ", got:"+ pp.getIndex() +
+ " for " + from[i]);
+ }
+ }
+ catch(Exception e) {
+ errln("Unexpected exception: " + e.getMessage());
+ }
+
+ checkType(from[i], getType(new BigDecimal(expected1[i])),
+ getType((Number)parsed[0]));
+ checkParse(from[i], new BigDecimal(expected1[i]),
+ (Number)parsed[0]);
+ }
+ }
+
+ static final String[] expected2 = { // isParseIntegerOnly() == true
+ "12345678901234567890",
+ "-12345678901234567890",
+ "12345678901234567890",
+ "-12345678901234567890",
+ "12345678901234567890",
+ "-12345678901234567890",
+ "0",
+ "0",
+
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210",
+ "9.876543210987654321098765432109876543210E44",
+ "-98765432109876543210987654321098765.43210",
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210",
+ "9876543210987654321098765432109876543210.12",
+ "-9876543210987654321098765432109876543210.12",
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210.00000000000000000000",
+ };
+ static final int[][] parsePosition2 = { // {errorIndex, index}
+ /*
+ * Should keep in mind that the expected result is different from
+ * DecimalFormat.parse() for some cases.
+ */
+ {28, 0}, // parsing stopped at '.'
+ {29, 0}, // parsing stopped at '.'
+ {29, 0}, // parsing stopped at '.'
+ {2, 0}, // parsing stopped at '(' because cannot find ')'
+ {2, 0}, // parsing stopped at the first numeric
+ // because cannot find '%'
+ {2, 0}, // parsing stopped at the first numeric
+ // because cannot find '%'
+ {28, 0}, // parsing stopped at '.'
+ {29, 0}, // parsing stopped at '.'
+
+ {-1, 57}, {-1, 58}, {-1, 59}, {-1, 61},
+ {56, 0}, // parsing stopped at '.'
+ // because cannot find '%'
+ {2, 0}, // parsing stopped at '(' because cannot find ')'
+ {-1, 60}, {-1, 61},
+ {28, 0}, // parsing stopped at '.'
+ {-1, 88},
+ };
+
+ /**
+ * Test for MessageFormat: setParseIntegerOnly(true)
+ */
+ void test_Parse_in_MessageFormat_ParseIntegerOnly() {
+ for (int i=0; i < patterns.length; i++) {
+ pp = new ParsePosition(0);
+ Object[] parsed = null;
+
+ try {
+ MessageFormat mf = new MessageFormat(patterns[i]);
+ Format[] formats = mf.getFormats();
+ for (int j=0; j < formats.length; j++) {
+ ((DecimalFormat)formats[j]).setParseBigDecimal(true);
+ ((DecimalFormat)formats[j]).setParseIntegerOnly(true);
+ }
+
+ parsed = mf.parse(from[i], pp);
+
+ if (pp.getErrorIndex() != parsePosition2[i][0]) {
+ errln("Case" + (i+1) +
+ ": getErrorIndex() returns wrong value. expected:" +
+ parsePosition2[i][0] + ", got:"+ pp.getErrorIndex() +
+ " for " + from[i]);
+ }
+ if (pp.getIndex() != parsePosition2[i][1]) {
+ errln("Case" + (i+1) +
+ ": getIndex() returns wrong value. expected:" +
+ parsePosition2[i][1] + ", got:"+ pp.getIndex() +
+ " for " + from[i]);
+ }
+ }
+ catch(Exception e) {
+ errln("Unexpected exception: " + e.getMessage());
+ }
+
+ if (parsePosition2[i][0] == -1) {
+ checkType(from[i], getType(new BigDecimal(expected2[i])),
+ getType((Number)parsed[0]));
+ checkParse(from[i], new BigDecimal(expected2[i]),
+ (Number)parsed[0]);
+ }
+ }
+ }
+
+ static final String[] from3 = {
+ "12,345,678,901,234,567,890.98765432109876543210987654321",
+ "-12,345,678,901,234,567,890.98765432109876543210987654321",
+ "9,876,543,210,987,654,321,098,765,432,109,876,543,210",
+ "-9,876,543,210,987,654,321,098,765,432,109,876,543,210",
+ "1234556790000E-8",
+ };
+ static final String[] expected3 = {
+ "12345678901234567890",
+ "-12345678901234567890",
+ "9876543210987654321098765432109876543210",
+ "-9876543210987654321098765432109876543210",
+ "12345.56790000",
+ };
+ static final int[][] parsePosition3 = { // {errorIndex, index}
+ {-1, 26},
+ {-1, 27},
+ {-1, 53},
+ {-1, 54},
+ {-1, 16},
+ };
+
+ /**
+ * Test for DecimalFormat: setParseIntegerOnly(true)
+ */
+ void test_Parse_in_DecimalFormat_ParseIntegerOnly() {
+ DecimalFormat df = (DecimalFormat)NumberFormat.getIntegerInstance();
+ df.setParseBigDecimal(true);
+
+ for (int i=0; i < from3.length; i++) {
+ pp = new ParsePosition(0);
+ Number parsed = null;
+
+ try {
+ parsed = df.parse(from3[i], pp);
+
+ if (pp.getErrorIndex() != parsePosition3[i][0]) {
+ errln("Case" + (i+1) +
+ ": getErrorIndex() returns wrong value. expected:" +
+ parsePosition3[i][0] + ", got:"+ pp.getErrorIndex() +
+ " for " + from3[i]);
+ }
+ if (pp.getIndex() != parsePosition3[i][1]) {
+ errln("Case" + (i+1) +
+ ": getIndex() returns wrong value. expected:" +
+ parsePosition3[i][1] + ", got:"+ pp.getIndex() +
+ " for " + from3[i]);
+ }
+ }
+ catch(Exception e) {
+ errln("Unexpected exception: " + e.getMessage());
+ }
+
+ if (parsePosition3[i][0] == -1) {
+ checkType(from3[i], getType(new BigDecimal(expected3[i])),
+ getType(parsed));
+ checkParse(from3[i], new BigDecimal(expected3[i]), parsed);
+ }
+ }
+ }
+
+ protected void check(String from, Number to) {
+ pp = new ParsePosition(0);
+ try {
+ parsed = df.parse(from, pp);
+ }
+ catch(Exception e) {
+ exceptionOccurred = true;
+ errln(e.getMessage());
+ }
+ if (!exceptionOccurred) {
+ checkParse(from, to, parsed);
+ checkType(from, getType(to), getType(parsed));
+ checkParsePosition(from, from.length(), pp.getIndex());
+ }
+ }
+
+ private void checkParse(String orig, Number expected, Number got) {
+ if (!expected.equals(got)) {
+ errln("Parsing... failed." +
+ "\n original: " + orig +
+ "\n parsed: " + got +
+ "\n expected: " + expected + "\n");
+ }
+ }
+
+ private void checkType(String orig, String expected, String got) {
+ if (!expected.equals(got)) {
+ errln("Parsing... unexpected Class returned." +
+ "\n original: " + orig +
+ "\n got: " + got +
+ "\n expected: " + expected + "\n");
+ }
+ }
+
+ private void checkParsePosition(String orig, int expected, int got) {
+ if (expected != got) {
+ errln("Parsing... wrong ParsePosition returned." +
+ "\n original: " + orig +
+ "\n got: " + got +
+ "\n expected: " + expected + "\n");
+ }
+ }
+
+ private String getType(Number number) {
+ return number.getClass().getName();
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug4208135.java b/test/java/text/Format/NumberFormat/Bug4208135.java
new file mode 100644
index 0000000000..3f5785b6f6
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug4208135.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2003, 2016, 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
+ * @summary Confirm that the decimal separator is shown when explicitly requested.
+ * @bug 4208135
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4208135 {
+
+ static DecimalFormat df;
+
+ static boolean err = false;
+
+ static public void main(String[] args){
+
+ Locale defaultLoc = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+
+ df = new DecimalFormat();
+
+ df.applyPattern("0.#E0");
+
+ df.setDecimalSeparatorAlwaysShown(true);
+ checkFormat(new Double(0.0), "0.E0");
+ checkFormat(new Double(10.0), "1.E1");
+ checkFormat(new Double(1000.0), "1.E3");
+ checkFormat(new Long(0), "0.E0");
+ checkFormat(new Long(10), "1.E1");
+ checkFormat(new Long(1000), "1.E3");
+ checkFormat(new BigDecimal("0.0"), "0.E0");
+ checkFormat(new BigDecimal("10.0"), "1.E1");
+ checkFormat(new BigDecimal("1000.0"), "1.E3");
+ checkFormat(new BigInteger("00"), "0.E0");
+ checkFormat(new BigInteger("10"), "1.E1");
+ checkFormat(new BigInteger("1000"), "1.E3");
+
+ df.setDecimalSeparatorAlwaysShown(false);
+ checkFormat(new Double(0.0), "0E0");
+ checkFormat(new Double(10.0), "1E1");
+ checkFormat(new Double(1000.0), "1E3");
+ checkFormat(new Long(0), "0E0");
+ checkFormat(new Long(10), "1E1");
+ checkFormat(new Long(1000), "1E3");
+ checkFormat(new BigDecimal("0.0"), "0E0");
+ checkFormat(new BigDecimal("10.0"), "1E1");
+ checkFormat(new BigDecimal("1000.0"), "1E3");
+ checkFormat(new BigInteger("0"), "0E0");
+ checkFormat(new BigInteger("10"), "1E1");
+ checkFormat(new BigInteger("1000"), "1E3");
+
+ df.applyPattern("0.###");
+
+ df.setDecimalSeparatorAlwaysShown(true);
+ checkFormat(new Double(0.0), "0.");
+ checkFormat(new Double(10.0), "10.");
+ checkFormat(new Double(1000.0), "1000.");
+ checkFormat(new Long(0), "0.");
+ checkFormat(new Long(10), "10.");
+ checkFormat(new Long(1000), "1000.");
+ checkFormat(new BigDecimal("0.0"), "0.");
+ checkFormat(new BigDecimal("10.0"), "10.");
+ checkFormat(new BigDecimal("1000.0"), "1000.");
+ checkFormat(new BigInteger("0"), "0.");
+ checkFormat(new BigInteger("10"), "10.");
+ checkFormat(new BigInteger("1000"), "1000.");
+
+ df.setDecimalSeparatorAlwaysShown(false);
+ checkFormat(new Double(0.0), "0");
+ checkFormat(new Double(10.0), "10");
+ checkFormat(new Double(1000.0), "1000");
+ checkFormat(new Long(0), "0");
+ checkFormat(new Long(10), "10");
+ checkFormat(new Long(1000), "1000");
+ checkFormat(new BigDecimal("0.0"), "0");
+ checkFormat(new BigDecimal("10.0"), "10");
+ checkFormat(new BigDecimal("1000.0"), "1000");
+ checkFormat(new BigInteger("0"), "0");
+ checkFormat(new BigInteger("10"), "10");
+ checkFormat(new BigInteger("1000"), "1000");
+
+ Locale.setDefault(defaultLoc);
+
+ if (err) {
+ throw new RuntimeException("Wrong format/parse with DecimalFormat");
+ }
+ }
+
+ static void checkFormat(Number num, String expected) {
+ String got = df.format(num);
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println(" DecimalFormat format(" +
+ num.getClass().getName() +
+ ") error:" +
+ "\n\tnumber: " + num +
+ "\n\tSeparatorShown? : " + df.isDecimalSeparatorAlwaysShown() +
+ "\n\tgot: " + got +
+ "\n\texpected: " + expected);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug4833877.java b/test/java/text/Format/NumberFormat/Bug4833877.java
new file mode 100644
index 0000000000..5f3c505601
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug4833877.java
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2003, 2016, 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
+ * @summary Confirm that the negative multiplier works as expected.
+ * @bug 4833877
+ */
+
+import java.math.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4833877 {
+
+ static DecimalFormat df;
+
+ static boolean err = false;
+
+ public static void main(String[] args) throws Exception {
+
+ Locale defaultLoc = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+
+ /* ================================================================ */
+
+ df = new DecimalFormat();
+ df.setMaximumFractionDigits(50);
+ df.setMultiplier(4);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(252.5252525252525), "1,010.10101010101");
+ checkParse("-1,010.10101010101", new Double(-252.5252525252525));
+
+ checkFormat(new Double(-2222.2222), "-8,888.8888");
+ checkParse("8888.8888", new Double(2222.2222));
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(1000), "4,000");
+ checkParse("-4,000", new Long(-1000));
+
+ checkFormat(new Long(-250), "-1,000");
+ checkParse("1000", new Long(250));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+ checkFormat(new BigDecimal("22222.222222222222222222222"),
+ "88,888.888888888888888888888");
+ checkParse("-88,888.888888888888888888888",
+ new BigDecimal("-22222.222222222222222222222"));
+
+ checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+ "-4,444,444,444,444,444,444.444444444444444444");
+ checkParse("4444444444444444444.444444444444444444",
+ new BigDecimal("1111111111111111111.111111111111111111"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("22222222222222222222222222"),
+ "88,888,888,888,888,888,888,888,888");
+ checkParse("-88,888,888,888,888,888,888,888,888",
+ new BigDecimal("-22222222222222222222222222"));
+
+ checkFormat(new BigInteger("-1111111111111111111111111"),
+ "-4,444,444,444,444,444,444,444,444");
+ checkParse("4444444444444444444444444",
+ new BigDecimal("1111111111111111111111111"));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(false);
+ df.setMultiplier(-4);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(252.5252525252525), "-1,010.10101010101");
+ checkParse("-1,010.10101010101", new Double(252.5252525252525));
+
+ checkFormat(new Double(-2222.2222), "8,888.8888");
+ checkParse("8888.8888", new Double(-2222.2222));
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(1000), "-4,000");
+ checkParse("-4,000", new Long(1000));
+
+ checkFormat(new Long(-250), "1,000");
+ checkParse("1000", new Long(-250));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+ checkFormat(new BigDecimal("22222.222222222222222222222"),
+ "-88,888.888888888888888888888");
+ checkParse("-88,888.888888888888888888888",
+ new BigDecimal("22222.222222222222222222222"));
+
+ checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+ "4,444,444,444,444,444,444.444444444444444444");
+ checkParse("4444444444444444444.444444444444444444",
+ new BigDecimal("-1111111111111111111.111111111111111111"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("22222222222222222222222222"),
+ "-88,888,888,888,888,888,888,888,888");
+ checkParse("-88,888,888,888,888,888,888,888,888",
+ new BigDecimal("22222222222222222222222222"));
+
+ checkFormat(new BigInteger("-1111111111111111111111111"),
+ "4,444,444,444,444,444,444,444,444");
+ checkParse("4444444444444444444444444",
+ new BigDecimal("-1111111111111111111111111"));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(false);
+ df.setMultiplier(-3);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(3333.3333333), "-9,999.9999999");
+ checkParse("-10,000.00000000000", new Double(3333.3333333333335));// rounding error
+
+ df.setParseIntegerOnly(true);
+ checkFormat(new Double(-3333.3333333), "9,999.9999999");
+ checkParse("10,000.00000000000", new Long(-3333));
+ df.setParseIntegerOnly(false);
+ checkFormat(new Double(-3333.3333333), "9,999.9999999");
+ checkParse("10,000.00000000000", new Double(-3333.3333333333335));// rounding error
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(3333), "-9,999");
+ df.setParseIntegerOnly(true);
+ checkParse("-10,000", new Long(3333));
+ df.setParseIntegerOnly(false);
+ checkParse("-10000", new Double(3333.3333333333335));// rounding error
+
+ checkFormat(new Long(-3333), "9,999");
+ df.setParseIntegerOnly(true);
+ checkParse("10,000", new Long(-3333));
+ df.setParseIntegerOnly(false);
+ checkParse("10000", new Double(-3333.3333333333335));// rounding error
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+ checkFormat(new BigDecimal("33333.333333333333333333333"),
+ "-99,999.999999999999999999999");
+ checkParse("-100,000.000000000000000000000",
+ new BigDecimal("33333.333333333333333333333"));
+
+ checkFormat(new BigDecimal("-33333.333333333333333333333"),
+ "99,999.999999999999999999999");
+ checkParse("100,000.000000000000000000000",
+ new BigDecimal("-33333.333333333333333333333"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("33333333333333333333333333"),
+ "-99,999,999,999,999,999,999,999,999");
+ checkParse("-100,000,000,000,000,000,000,000,000",
+ new BigDecimal("33333333333333333333333333"));
+
+ checkFormat(new BigInteger("-33333333333333333333333333"),
+ "99,999,999,999,999,999,999,999,999");
+ df.setParseIntegerOnly(true);
+ checkParse("100,000,000,000,000,000,000,000,000.000",
+ new BigDecimal("-33333333333333333333333333"));
+ df.setParseIntegerOnly(false);
+ checkParse("100,000,000,000,000,000,000,000,000.000",
+ new BigDecimal("-33333333333333333333333333.333"));
+
+ /* ================================================================ */
+
+ df = new DecimalFormat("0.#E0;-0.#E0");
+ df.setMaximumFractionDigits(50);
+ df.setMultiplier(4);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(252.5252525252525), "1.01010101010101E3");
+ checkParse("-1.01010101010101E3", new Double(-2.525252525252525E2));
+
+ checkFormat(new Double(-2222.2222), "-8.8888888E3");
+ checkParse("8888.8888", new Double(2.2222222E3));
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(1000), "4E3");
+ checkParse("-4E3", new Long(-1000));
+
+ checkFormat(new Long(-250), "-1E3");
+ checkParse("1000", new Long(250));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+
+ checkFormat(new BigDecimal("22222.222222222222222222222"),
+ "8.8888888888888888888888888E4");
+ checkParse("-8.8888888888888888888888888E4",
+ new BigDecimal("-2.2222222222222222222222222E4"));
+
+ checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+ "-4.444444444444444444444444444444444444E18");
+ checkParse("4444444444444444444.444444444444444444",
+ new BigDecimal("1111111111111111111.111111111111111111"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("22222222222222222222222222"),
+ "8.8888888888888888888888888E25");
+ checkParse("-8.8888888888888888888888888E25",
+ new BigDecimal("-22222222222222222222222222"));
+
+ checkFormat(new BigInteger("-1111111111111111111111111"),
+ "-4.444444444444444444444444E24");
+ checkParse("4444444444444444444444444",
+ new BigDecimal("1111111111111111111111111"));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(false);
+ df.setMultiplier(-4);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(252.5252525252525), "-1.01010101010101E3");
+ checkParse("-1.01010101010101E3", new Double(2.525252525252525E2));
+
+ checkFormat(new Double(-2222.2222), "8.8888888E3");
+ checkParse("8888.8888", new Double(-2.2222222E3));
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(1000), "-4E3");
+ checkParse("-4E3", new Long(1000));
+
+ checkFormat(new Long(-250), "1E3");
+ checkParse("1000", new Long(-250));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+
+ checkFormat(new BigDecimal("22222.222222222222222222222"),
+ "-8.8888888888888888888888888E4");
+ checkParse("-8.8888888888888888888888888E4",
+ new BigDecimal("2.2222222222222222222222222E4"));
+
+ checkFormat(new BigDecimal("-1111111111111111111.111111111111111111"),
+ "4.444444444444444444444444444444444444E18");
+ checkParse("4444444444444444444.444444444444444444",
+ new BigDecimal("-1111111111111111111.111111111111111111"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("22222222222222222222222222"),
+ "-8.8888888888888888888888888E25");
+ checkParse("-8.8888888888888888888888888E25",
+ new BigDecimal("22222222222222222222222222"));
+
+ checkFormat(new BigInteger("-1111111111111111111111111"),
+ "4.444444444444444444444444E24");
+ checkParse("4444444444444444444444444",
+ new BigDecimal("-1111111111111111111111111"));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(false);
+ df.setMultiplier(-3);
+
+ /*
+ * Test for double/Double
+ */
+ checkFormat(new Double(3333.3333333), "-9.9999999999E3");
+ checkParse("-1.00000000000000E3", new Double(3.33333333333333333E2));
+
+ df.setParseIntegerOnly(true);
+ checkFormat(new Double(-3333.3333333), "9.9999999999E3");
+ checkParse("10.00000000000000E3", new Long(-3));
+ df.setParseIntegerOnly(false);
+ checkFormat(new Double(-3333.3333333), "9.9999999999E3");
+ checkParse("10.00000000000000E3", new Double(-3.33333333333333333E3));
+
+ /*
+ * Test for long/Long
+ */
+ checkFormat(new Long(3333), "-9.999E3");
+ df.setParseIntegerOnly(true);
+ checkParse("-1.0E4", new Long(0));
+ df.setParseIntegerOnly(false);
+ checkParse("-1.0E4", new Double(3333.3333333333335));
+
+ checkFormat(new Long(-3333), "9.999E3");
+ df.setParseIntegerOnly(true);
+ checkParse("10.0E4", new Long(-3));
+ df.setParseIntegerOnly(false);
+ checkParse("10.0E4", new Double(-33333.3333333333336));
+
+ /* ---------------------------------------------------------------- */
+
+ df.setParseBigDecimal(true);
+
+ /*
+ * Test for BigDecimal
+ */
+
+ checkFormat(new BigDecimal("333.333333333333333333333333"),
+ "-9.99999999999999999999999999E2");
+ checkParse("-1.0000000000000000000000000E3",
+ new BigDecimal("3.333333333333333333333333E2"));
+
+ df.setParseIntegerOnly(true);
+ checkFormat(new BigDecimal("-333.333333333333333333333333"),
+ "9.99999999999999999999999999E2");
+ checkParse("10.0000000000000000000000000E3",
+ new BigDecimal("-3"));
+ df.setParseIntegerOnly(false);
+ checkFormat(new BigDecimal("-333.333333333333333333333333"),
+ "9.99999999999999999999999999E2");
+ checkParse("1.0000000000000000000000000E3",
+ new BigDecimal("-3.333333333333333333333333E2"));
+
+ /*
+ * Test for BigInteger
+ */
+ checkFormat(new BigInteger("33333333333333333333333333"),
+ "-9.9999999999999999999999999E25");
+ checkParse("-100000000000000000000000000",
+ new BigDecimal("33333333333333333333333333"));
+
+ checkFormat(new BigInteger("-33333333333333333333333333"),
+ "9.9999999999999999999999999E25");
+ df.setParseIntegerOnly(true);
+ checkParse("100000000000000000000000000000",
+ new BigDecimal("-33333333333333333333333333333"));
+ df.setParseIntegerOnly(false);
+ checkParse("100000000000000000000000000.000",
+ new BigDecimal("-33333333333333333333333333.333"));
+
+ /* ================================================================ */
+
+ Locale.setDefault(defaultLoc);
+
+ if (err) {
+ throw new RuntimeException("Wrong format/parse with DecimalFormat");
+ }
+ }
+
+ static void checkFormat(Number num, String expected) {
+ String got = df.format(num);
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println(" DecimalFormat format(" +
+ num.getClass().getName() +
+ ") error:" +
+ "\n\tnumber: " + num +
+ "\n\tpattern: " + df.toPattern() +
+ "\n\tmultiplier: " + df.getMultiplier() +
+ "\n\tgot: " + got +
+ "\n\texpected: " + expected);
+ }
+ }
+
+ static void checkParse(String text, Double expected) {
+ Double got = (Double)df.parse(text, new ParsePosition(0));
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println(" DecimalFormat parse(double) error:" +
+ "\n\ttext: " + text +
+ "\n\tpattern: " + df.toPattern() +
+ "\n\tmultiplier: " + df.getMultiplier() +
+ "\n\tgot: " + got +
+ "\n\texpected: " + expected);
+ }
+ }
+
+ static void checkParse(String text, Long expected) {
+ Long got = (Long)df.parse(text, new ParsePosition(0));
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println(" DecimalFormat parse(long) error:" +
+ "\n\ttext: " + text +
+ "\n\tpattern: " + df.toPattern() +
+ "\n\tmultiplier: " + df.getMultiplier() +
+ "\n\tgot: " + got +
+ "\n\texpected: " + expected);
+ }
+ }
+
+ static void checkParse(String text, BigDecimal expected) {
+ BigDecimal got = (BigDecimal)df.parse(text, new ParsePosition(0));
+ if (!got.equals(expected)) {
+ err = true;
+ System.err.println(" DecimalFormat parse(BigDecimal) error:" +
+ "\n\ttext: " + text +
+ "\n\tpattern: " + df.toPattern() +
+ "\n\tmultiplier: " + df.getMultiplier() +
+ "\n\tgot: " + got +
+ "\n\texpected: " + expected);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug4838107.java b/test/java/text/Format/NumberFormat/Bug4838107.java
new file mode 100644
index 0000000000..a15d537d8e
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug4838107.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4838107 8008577
+ * @summary Confirm that DecimalFormat can format a number with negative exponent number correctly.
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI Bug4838107
+ */
+
+import java.math.*;
+import java.util.*;
+import java.text.*;
+
+public class Bug4838107 extends IntlTest {
+
+ static DecimalFormat df;
+ static DecimalFormatSymbols dfs;
+ static boolean err = false;
+
+ static public void main(String[] args) {
+ Locale defaultLoc = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+
+ /**
+ * This bug is about exponential formatting. But I added test cases for:
+ * - Double and BigDecimal numbers which don't have exponent parts.
+ * - Long and BigInteger numbers which don't support exponential
+ * notation.
+ * because there are few test cases for suffix and prefix.
+ * And also, I added test cases to guarantee further formatting and
+ * parsing using the same DecimalFormat instance will not change the
+ * Number's value anymore.
+ */
+
+ test_double();
+ test_long();
+ test_BigDecimal();
+ test_BigInteger();
+
+ Locale.setDefault(defaultLoc);
+
+ if (err) {
+ throw new RuntimeException("Wrong format with DecimalFormat");
+ }
+ }
+
+ static void test_double() {
+ df = new DecimalFormat();
+ dfs = df.getDecimalFormatSymbols();
+
+ /* Test with default pattern */
+ test(new Double(1234), "1,234");
+ test(new Double(0.1234), "0.123"); // rounded
+ test(new Double(-1234), "-1,234");
+ test(new Double(-0.1234), "-0.123"); // rounded
+
+ test(new Double(Double.POSITIVE_INFINITY), "\u221e");
+ test(new Double(Double.NEGATIVE_INFINITY), "-\u221e");
+ test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
+ test(new Double(0.0), "0");
+ test(new Double(-0.0), "-0"); // with the minus sign
+
+ /* Specify a pattern and the minus sign. */
+ prepareFormatter("<P>#.###E00<S>", 'm');
+ test(new Double(1234), "<P>1.234E03<S>");
+ test(new Double(0.1234), "<P>1.234Em01<S>");
+ test(new Double(-1234), "m<P>1.234E03<S>");
+ test(new Double(-0.1234), "m<P>1.234Em01<S>");
+
+ prepareFormatter("<P>#.###E00<S>;#.###E00", 'm');
+ test(new Double(1234), "<P>1.234E03<S>");
+ test(new Double(0.1234), "<P>1.234Em01<S>");
+ test(new Double(-1234), "1.234E03");
+ test(new Double(-0.1234), "1.234Em01");
+
+ prepareFormatter("#.###E00;<P>#.###E00<S>", 'm');
+ test(new Double(1234), "1.234E03");
+ test(new Double(0.1234), "1.234Em01");
+ test(new Double(-1234), "<P>1.234E03<S>");
+ test(new Double(-0.1234), "<P>1.234Em01<S>");
+
+ prepareFormatter("<P>#.###E00<S>;<p>-#.###E00<s>", 'm');
+ test(new Double(1234), "<P>1.234E03<S>");
+ test(new Double(0.1234), "<P>1.234Em01<S>");
+ test(new Double(-1234), "<p>m1.234E03<s>");
+ test(new Double(-0.1234), "<p>m1.234Em01<s>");
+
+ test(new Double(Double.POSITIVE_INFINITY), "<P>\u221e<S>");
+ test(new Double(Double.NEGATIVE_INFINITY), "<p>m\u221e<s>");
+ test(new Double(Double.NaN), "\ufffd"); // without prefix and suffix
+ test(new Double(0.0), "<P>0E00<S>");
+ test(new Double(-0.0), "<p>m0E00<s>"); // with the minus sign
+ }
+
+ static void test_BigDecimal() {
+ df = new DecimalFormat();
+ dfs = df.getDecimalFormatSymbols();
+
+ /* Test with default pattern */
+ test(new BigDecimal("123456789012345678901234567890"),
+ "123,456,789,012,345,678,901,234,567,890");
+ test(new BigDecimal("0.000000000123456789012345678901234567890"),
+ "0");
+ test(new BigDecimal("-123456789012345678901234567890"),
+ "-123,456,789,012,345,678,901,234,567,890");
+ test(new BigDecimal("-0.000000000123456789012345678901234567890"),
+ "-0");
+
+ test(new BigDecimal("0"), "0");
+ test(new BigDecimal("-0"), "0");
+
+ /* Specify a pattern and the minus sign. */
+ prepareFormatter("<P>#.####################E00<S>;<p>-#.####################E00<s>", 'm');
+ test(new BigDecimal("123456789012345678901234567890"),
+ "<P>1.23456789012345678901E29<S>");
+ test(new BigDecimal("0.000000000123456789012345678901234567890"),
+ "<P>1.23456789012345678901Em10<S>");
+ test(new BigDecimal("-123456789012345678901234567890"),
+ "<p>m1.23456789012345678901E29<s>");
+ test(new BigDecimal("-0.000000000123456789012345678901234567890"),
+ "<p>m1.23456789012345678901Em10<s>");
+
+ test(new BigDecimal("0"), "<P>0E00<S>");
+ test(new BigDecimal("-0"), "<P>0E00<S>");
+ }
+
+ static void test_long() {
+ df = new DecimalFormat();
+ dfs = df.getDecimalFormatSymbols();
+
+ /* Test with default pattern */
+ test(new Long(123456789), "123,456,789");
+ test(new Long(-123456789), "-123,456,789");
+
+ test(new Long(0), "0");
+ test(new Long(-0), "0");
+
+ /* Specify a pattern and the minus sign. */
+ prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
+ test(new Long(123456789), "<P>123,456,789<S>");
+ test(new Long(-123456789), "<p>m123,456,789<s>");
+
+ test(new Long(0), "<P>0<S>");
+ test(new Long(-0), "<P>0<S>");
+ }
+
+ static void test_BigInteger() {
+ df = new DecimalFormat();
+ dfs = df.getDecimalFormatSymbols();
+
+ /* Test with default pattern */
+ test(new BigInteger("123456789012345678901234567890"),
+ "123,456,789,012,345,678,901,234,567,890");
+ test(new BigInteger("-123456789012345678901234567890"),
+ "-123,456,789,012,345,678,901,234,567,890");
+
+ test(new BigInteger("0"), "0");
+ test(new BigInteger("-0"), "0");
+
+ /* Specify a pattern and the minus sign. */
+ prepareFormatter("<P>#,###<S>;<p>-#,###<s>", 'm');
+ test(new BigInteger("123456789012345678901234567890"),
+ "<P>123,456,789,012,345,678,901,234,567,890<S>");
+ test(new BigInteger("-123456789012345678901234567890"),
+ "<p>m123,456,789,012,345,678,901,234,567,890<s>");
+
+ test(new BigInteger("0"), "<P>0<S>");
+ test(new BigInteger("-0"), "<P>0<S>");
+ }
+
+ static void prepareFormatter(String pattern, char minusSign) {
+ dfs = df.getDecimalFormatSymbols();
+ df.applyPattern(pattern);
+ dfs.setMinusSign(minusSign);
+ df.setDecimalFormatSymbols(dfs);
+ }
+
+ static void test(Number num, String str) {
+ String formatted = df.format(num);
+ if (!formatted.equals(str)) {
+ err = true;
+ System.err.println(" DecimalFormat format(" +
+ num.getClass().getName() +
+ ") error: \n\tnumber: " + num +
+ "\n\tminus sign: " + dfs.getMinusSign() +
+ "\n\tgot: " + formatted +
+ "\n\texpected: " + str);
+ return;
+ }
+
+ if (num instanceof BigDecimal || num instanceof BigInteger) {
+ df.setParseBigDecimal(true);
+ }
+ Number parsed1 = null, parsed2 = null;
+ try {
+ parsed1 = df.parse(formatted);
+ formatted = df.format(parsed1);
+ parsed2 = df.parse(formatted);
+ if (!parsed1.equals(parsed2)) {
+ err = true;
+ System.err.println(" DecimalFormat roundtrip parse(" +
+ num.getClass().getName() +
+ ") error: \n\toriginal number: " + str +
+ "\n\tparsed number: " + parsed1 +
+ " (" + parsed1.getClass().getName() + ")" +
+ "\n\tformatted number: " + formatted +
+ "\n\tre-parsed number: " + parsed2 +
+ " (" + parsed2.getClass().getName() + ")" +
+ "\n\tminus sign: " + dfs.getMinusSign());
+ }
+ }
+ catch (Exception e) {
+ err = true;
+ System.err.println(" DecimalFormat parse(" +
+ num.getClass().getName() +
+ ") threw an Exception: " + e.getMessage() +
+ "\n\toriginal number: " + str +
+ "\n\tparsed number : " + parsed1 +
+ " (" + parsed1.getClass().getName() + ")" +
+ "\n\tformatted number: " + formatted +
+ "\n\tre-parsed number: " + parsed2 +
+ " (" + parsed2.getClass().getName() + ")" +
+ "\n\tminus sign: " + dfs.getMinusSign());
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug4944439.java b/test/java/text/Format/NumberFormat/Bug4944439.java
new file mode 100644
index 0000000000..beb4d77c23
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug4944439.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4944439
+ * @summary Confirm that numbers where all digits after the decimal separator are 0
+ * and which are between Long.MIN_VALUE and Long.MAX_VALUE are returned as Long(not double).
+ */
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.text.DecimalFormat;
+import java.util.Locale;
+
+public class Bug4944439 {
+
+ static boolean err = false;
+ static DecimalFormat df;
+
+ public static void main(String[] args) throws Exception {
+
+ Locale defaultLoc = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+
+ df = new DecimalFormat();
+ String s = "-9223372036854775809"; // Long.MIN_VALUE-1
+ check_Double(s);
+
+ test(Long.MIN_VALUE, Long.MIN_VALUE+10);
+ test(-10, 10);
+ test(Long.MAX_VALUE-10, Long.MAX_VALUE-1);
+
+ s = "9223372036854775807.00"; // Long.MAX_VALUE
+ check_Long(s);
+ s = "9223372036854775808"; // Long.MAX_VALUE+1
+ check_Double(s);
+
+ s = "-0.0";
+ check_Double(s);
+ s = "0.0";
+ check_Long(s);
+
+ Locale.setDefault(defaultLoc);
+
+ if (err) {
+ throw new RuntimeException("Wrong parsing with DecimalFormat");
+ }
+ }
+
+ private static void test(long from, long to) throws Exception {
+ for (long l = from; l <= to; l++) {
+ check_Long(Long.toString(l) + ".00");
+ }
+ }
+
+ private static void check_Long(String s) throws Exception {
+ Number number = df.parse(s);
+ if (!(number instanceof Long)) {
+ err = true;
+ System.err.println("Failed: DecimalFormat.parse(\"" + s +
+ "\") should return a Long, but returned a " +
+ number.getClass().getName());
+ }
+
+ int index = s.indexOf('.');
+ Long l = new Long(s.substring(0, index));
+ if (!l.equals(number)) {
+ err = true;
+ System.err.println("Failed: DecimalFormat.parse(" + s +
+ ") should return a Long(" + l + "), but returned " + number);
+ }
+ }
+
+ private static void check_Double(String s) throws Exception {
+ Number number = df.parse(s);
+ if (!(number instanceof Double)) {
+ err = true;
+ System.err.println("Failed: DecimalFormat.parse(\"" + s +
+ "\") should return a Double, but returned a " +
+ number.getClass().getName());
+ }
+
+ Double d = new Double(s);
+ if (!d.equals(number)) {
+ err = true;
+ System.err.println("Failed: DecimalFormat.parse(" + s +
+ ") should return a Double(" + d + "), but returned " + number);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug4990596.java b/test/java/text/Format/NumberFormat/Bug4990596.java
new file mode 100644
index 0000000000..a8c03b8a03
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug4990596.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2004, 2016, 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 4990596
+ * @summary Make sure that any subclass of Number can be formatted using DecimalFormat.format().
+ */
+
+import java.text.DecimalFormat;
+
+public class Bug4990596 {
+
+ public static void main(String[] args) {
+ new DecimalFormat().format(new MutableInteger(0));
+ }
+
+ public static class MutableInteger extends Number {
+ public int value;
+
+ public MutableInteger() {
+ }
+ public MutableInteger(int value) {
+ this.value = value;
+ }
+ public double doubleValue() {
+ return this.value;
+ }
+ public float floatValue() {
+ return this.value;
+ }
+ public int intValue() {
+ return this.value;
+ }
+ public long longValue() {
+ return this.value;
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/Bug6278616.java b/test/java/text/Format/NumberFormat/Bug6278616.java
new file mode 100644
index 0000000000..9066a7da02
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/Bug6278616.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005, 2016, 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
+ * @summary Confirm that AtomicInteger and AtomicLong are formatted correctly.
+ * @bug 6278616
+ */
+
+import java.text.NumberFormat;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import java.util.Locale;
+
+public class Bug6278616 {
+
+ static final int[] ints = {
+ Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE
+ };
+
+ static final long[] longs = {
+ Long.MIN_VALUE, -1, 0, 1, Long.MAX_VALUE
+ };
+
+ public static void main(String[] args) {
+ NumberFormat nf = NumberFormat.getInstance();
+
+ for (int j = 0; j < ints.length; j++) {
+ String s_i = nf.format(new Integer(ints[j]));
+ String s_ai = nf.format(new AtomicInteger(ints[j]));
+ if (!s_i.equals(s_ai)) {
+ throw new RuntimeException("format(AtomicInteger " + s_ai +
+ ") doesn't equal format(Integer " +
+ s_i + ")");
+ }
+ }
+
+ for (int j = 0; j < longs.length; j++) {
+ String s_l = nf.format(new Long(longs[j]));
+ String s_al = nf.format(new AtomicLong(longs[j]));
+ if (!s_l.equals(s_al)) {
+ throw new RuntimeException("format(AtomicLong " + s_al +
+ ") doesn't equal format(Long " +
+ s_l + ")");
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/CurrencyFormat.java b/test/java/text/Format/NumberFormat/CurrencyFormat.java
new file mode 100644
index 0000000000..23d2ade193
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/CurrencyFormat.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2001, 2018, 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 4290801 4942982 5102005 8008577 8021121 8210153
+ * @summary Basic tests for currency formatting.
+ * @run main/othervm -Djava.locale.providers=JRE,SPI CurrencyFormat
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.util.Currency;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.util.TimeZone;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+
+public class CurrencyFormat {
+
+ public static void main(String[] args) throws Exception {
+ testFormatting();
+ testSymbols();
+ }
+
+ static void testFormatting() {
+ boolean failed = false;
+ Locale[] locales = {
+ Locale.US,
+ Locale.JAPAN,
+ Locale.GERMANY,
+ Locale.ITALY,
+ new Locale("it", "IT", "EURO") };
+ Currency[] currencies = {
+ null,
+ Currency.getInstance("USD"),
+ Currency.getInstance("JPY"),
+ Currency.getInstance("DEM"),
+ Currency.getInstance("EUR"),
+ };
+ String[][] expecteds = {
+ {"$1,234.56", "$1,234.56", "JPY1,235", "DEM1,234.56", "EUR1,234.56"},
+ {"\uFFE51,235", "USD1,234.56", "\uFFE51,235", "DEM1,234.56", "EUR1,234.56"},
+ {"1.234,56 \u20AC", "1.234,56 USD", "1.235 JPY", "1.234,56 DM", "1.234,56 \u20AC"},
+ {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"},
+ {"\u20AC 1.234,56", "USD 1.234,56", "JPY 1.235", "DEM 1.234,56", "\u20AC 1.234,56"},
+ };
+
+ for (int i = 0; i < locales.length; i++) {
+ Locale locale = locales[i];
+ NumberFormat format = NumberFormat.getCurrencyInstance(locale);
+ for (int j = 0; j < currencies.length; j++) {
+ Currency currency = currencies[j];
+ String expected = expecteds[i][j];
+ if (currency != null) {
+ format.setCurrency(currency);
+ int digits = currency.getDefaultFractionDigits();
+ format.setMinimumFractionDigits(digits);
+ format.setMaximumFractionDigits(digits);
+ }
+ String result = format.format(1234.56);
+ if (!result.equals(expected)) {
+ failed = true;
+ System.out.println("FAIL: Locale " + locale
+ + (currency == null ? ", default currency" : (", currency: " + currency))
+ + ", expected: " + expected
+ + ", actual: " + result);
+ }
+ }
+ }
+
+ if (failed) {
+ throw new RuntimeException();
+ }
+ }
+
+ static void testSymbols() throws Exception {
+ FileInputStream stream = new FileInputStream(new File(System.getProperty("test.src", "."), "CurrencySymbols.properties"));
+ Properties props = new Properties();
+ props.load(stream);
+ SimpleDateFormat format = null;
+
+ Locale[] locales = NumberFormat.getAvailableLocales();
+ for (int i = 0; i < locales.length; i++) {
+ Locale locale = locales[i];
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
+ String result = symbols.getCurrencySymbol();
+ String expected = (String) props.get(locale.toString());
+
+ if (expected == null) {
+ System.out.println("Warning: No expected currency symbol defined for locale " + locale);
+ } else {
+ if (expected.contains(";")) {
+ StringTokenizer tokens = new StringTokenizer(expected, ";");
+ int tokensCount = tokens.countTokens();
+
+ if (tokensCount == 3) {
+ expected = tokens.nextToken();
+ if (format == null) {
+ format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.US);
+ format.setTimeZone(TimeZone.getTimeZone("GMT"));
+ format.setLenient(false);
+ }
+
+ if (format.parse(tokens.nextToken()).getTime() < System.currentTimeMillis()) {
+ expected = tokens.nextToken();
+ }
+ }
+ }
+
+ if (!expected.equals(result)) {
+ throw new RuntimeException("Wrong currency symbol for locale " +
+ locale + ", expected: " + expected + ", got: " + result);
+ }
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/CurrencySymbols.properties b/test/java/text/Format/NumberFormat/CurrencySymbols.properties
new file mode 100644
index 0000000000..cf73a9c7e3
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/CurrencySymbols.properties
@@ -0,0 +1,134 @@
+ar=\u00A4
+ar_AE=\u062F.\u0625.\u200F
+ar_BH=\u062F.\u0628.\u200F
+ar_DZ=\u062F.\u062C.\u200F
+ar_EG=\u062C.\u0645.\u200F
+ar_IQ=\u062F.\u0639.\u200F
+ar_JO=\u062F.\u0623.\u200F
+ar_KW=\u062F.\u0643.\u200F
+ar_LB=\u0644.\u0644.\u200F
+ar_LY=\u062F.\u0644.\u200F
+ar_MA=\u062F.\u0645.\u200F
+ar_OM=\u0631.\u0639.\u200F
+ar_QA=\u0631.\u0642.\u200F
+ar_SA=\u0631.\u0633.\u200F
+# see bug 4412080
+# ar_SD=\u062C.\u0633.\u200F
+ar_SY=\u0644.\u0633.\u200F
+ar_TN=\u062F.\u062A.\u200F
+ar_YE=\u0631.\u064A.\u200F
+be=\u00A4
+# see bug 4412080
+# be_BY=\u0420\u0443\u0431
+bg=\u00A4
+# see bug 4412080
+# bg_BG=Lr
+ca=\u00A4
+ca_ES=\u20AC
+cs=\u00A4
+cs_CZ=K\u010D
+da=\u00A4
+da_DK=kr
+de=\u00A4
+de_AT=\u20AC
+de_CH=SFr.
+de_DE=\u20AC
+de_LU=\u20AC
+el=\u00A4
+el_GR=\u20AC
+en=\u00A4
+en_AU=$
+en_CA=$
+en_GB=\u00A3
+en_IE=\u20AC
+en_NZ=$
+en_US=$
+en_ZA=R
+es=\u00A4
+es_AR=$
+es_BO=B$
+es_CL=Ch$
+# 5102005
+es_CO=$
+es_CR=C
+es_CU=CU$
+es_DO=RD$
+# see bug 4412080
+# es_EC=S/
+es_ES=\u20AC
+es_GT=Q
+es_HN=L
+es_MX=$
+es_NI=$C
+es_PA=B
+es_PE=S/.
+es_PR=$
+es_PY=G
+es_SV=C
+es_UY=NU$
+es_VE=Bs.S.
+et=\u00A4
+et_EE=\u20AC
+fi=\u00A4
+fi_FI=\u20AC
+fr=\u00A4
+fr_BE=\u20AC
+fr_CA=$
+fr_CH=SFr.
+fr_FR=\u20AC
+fr_LU=\u20AC
+hi_IN=\u0930\u0942
+hr=\u00A4
+hr_HR=Kn
+hu=\u00A4
+hu_HU=Ft
+is=\u00A4
+is_IS=kr.
+it=\u00A4
+it_CH=SFr.
+it_IT=\u20AC
+iw=\u00A4
+iw_IL=\u05E9"\u05D7
+ja=\u00A4
+ja_JP=\uFFE5
+ko=\u00A4
+ko_KR=\uFFE6
+lt=\u00A4
+lt_LT=Lt;2014-12-31-22-00-00;\u20AC
+lv=\u00A4
+lv_LV=Ls;2013-12-31-22-00-00;\u20AC
+mk=\u00A4
+mk_MK=Den
+nl=\u00A4
+nl_BE=\u20AC
+nl_NL=\u20AC
+no=\u00A4
+no_NO=kr
+no_NO_NY=kr
+pl=\u00A4
+pl_PL=z\u0142
+pt=\u00A4
+pt_BR=R$
+pt_PT=\u20AC
+ro=\u00A4
+ro_RO=LEI
+ru=\u00A4
+ru_RU=\u0440\u0443\u0431.
+sk=\u00A4
+sk_SK=\u20AC
+sl=\u00A4
+sl_SI=\u20AC
+sq=\u00A4
+sq_AL=Lek
+sv=\u00A4
+sv_SE=kr
+th=\u00A4
+th_TH=\u0E3F
+tr=\u00A4
+tr_TR=TL
+uk=\u00A4
+uk_UA=\u0433\u0440\u043d.
+zh=\u00A4
+zh_CN=\uFFE5
+zh_HK=HK$
+zh_TW=NT$
diff --git a/test/java/text/Format/NumberFormat/DFSDeserialization142.java b/test/java/text/Format/NumberFormat/DFSDeserialization142.java
new file mode 100644
index 0000000000..2927f4e2c3
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DFSDeserialization142.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, 2016, 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on older version JDK than 1.6 to test.
+ * It was tested using 1.4.2. The file object was created using JDK1.6.
+ */
+
+
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSDeserialization142{
+
+ public static void main(String[] args)
+ {
+ try {
+
+ File file = new File("DecimalFormatSymbols.current");
+ FileInputStream istream = new FileInputStream(file);
+ ObjectInputStream p = new ObjectInputStream(istream);
+ DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
+ if (dfs.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+ System.out.println("Serialization/Deserialization Test Passed.");
+ }else{
+ throw new Exception("Serialization/Deserialization Test Failed:"+dfs.getCurrencySymbol());
+ }
+ istream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/DFSExponential.java b/test/java/text/Format/NumberFormat/DFSExponential.java
new file mode 100644
index 0000000000..898fb3fecc
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DFSExponential.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4068067
+ * @library /java/text/testlib
+ * @summary test NumberFormat with exponential separator symbols. It also tests the new
+ * public methods in DecimalFormatSymbols, setExponentSeparator() and
+ * getExponentSeparator()
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class DFSExponential extends IntlTest
+{
+
+ public static void main(String[] args) throws Exception {
+ new DFSExponential().run(args);
+ }
+
+
+ public void DFSExponenTest() throws Exception {
+ DecimalFormatSymbols sym = new DecimalFormatSymbols(Locale.US);
+ String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
+ double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
+ long lval[] = { 0, -1, 1, 123456789 };
+ String valFormat[][] = {
+ {"1.234x10^-2", "1.2346x10^8", "1.23x10^300", "-3.1416x10^-271"},
+ {"12.340x10^-03", "12.346x10^07", "12.300x10^299", "-31.416x10^-272"},
+ {"12.34x10^-003", "123.4568x10^006", "1.23x10^300", "-314.1593x10^-273"},
+ {"1.234x10^-2", "1.235x10^8", "1.23x10^300", "[3.142x10^-271]"},
+ };
+
+
+ int ival = 0, ilval = 0;
+ logln("Default exponent separator: "+sym.getExponentSeparator());
+ try {
+ sym.setExponentSeparator("x10^");
+ } catch (NullPointerException e){
+ errln("null String was passed to set an exponent separator symbol");
+ throw new RuntimeException("Test Malfunction: null String was passed to set an exponent separator symbol" );
+ }
+ logln("Current exponent separator: "+sym.getExponentSeparator());
+
+ for (int p=0; p<pat.length; ++p){
+ DecimalFormat fmt = new DecimalFormat(pat[p], sym);
+ logln(" Pattern: " + fmt.toPattern());
+ String locPattern = fmt.toLocalizedPattern();
+ logln(" Localized pattern: "+locPattern);
+ //fmt.applyLocalizedPattern(locPattern);
+ //System.out.println(" fmt.applyLocalizedPattern(): "+fmt.toLocalizedPattern());
+
+ for (int v=0; v<val.length; ++v) {
+ String s = fmt.format(val[v]);
+ logln(" " + val[v]+" --> "+s);
+ if(valFormat[p][v].equals(s)){
+ logln(": Passed");
+ }else{
+ errln(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s);
+ throw new RuntimeException(" Failed: Should be formatted as "+valFormat[p][v]+ "but got "+s);
+ }
+ }
+ } //end of the first for loop
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/DFSSerialization.java b/test/java/text/Format/NumberFormat/DFSSerialization.java
new file mode 100644
index 0000000000..40b40b39b8
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DFSSerialization.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4068067
+ * @library /java/text/testlib
+ * @build DFSSerialization IntlTest HexDumpReader
+ * @run main DFSSerialization
+ * @summary Three different tests are done. 1.read from the object created using jdk1.4.2 2.create a valid DecimalFormatSymbols object with current JDK, then read the object 3.Try to create an valid DecimalFormatSymbols object by passing null to set null for the exponent separator symbol. Expect the NullPointerException.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSSerialization extends IntlTest{
+ public static void main(String[] args) throws Exception {
+ new DFSSerialization().run(args);
+ }
+ public void TestDFSSerialization(){
+ /*
+ * 1. read from the object created using jdk1.4.2
+ */
+ File oldFile = new File(System.getProperty("test.src", "."), "DecimalFormatSymbols.142.txt");
+ DecimalFormatSymbols dfs142 = readTestObject(oldFile);
+ if (dfs142 != null){
+ if (dfs142.getExponentSeparator().equals("E") && dfs142.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+ System.out.println("\n Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
+ logln(" Deserialization of JDK1.4.2 Object from the current JDK: Passed.");
+ } else {
+ errln(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+ +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
+ /*
+ * logically should not throw this exception as errln throws exception
+ * if not thrown yet - but in case errln got changed
+ */
+ throw new RuntimeException(" Deserialization of JDK1.4.2 Object from the current JDK was Failed:"
+ +dfs142.getCurrencySymbol()+" "+dfs142.getExponentSeparator());
+ }
+ }
+ /*
+ * 2. create a valid DecimalFormatSymbols object with current JDK, then read the object
+ */
+ String validObject = "DecimalFormatSymbols.current";
+ File currentFile = createTestObject(validObject, "*SpecialExponentSeparator*");
+
+ DecimalFormatSymbols dfsValid = readTestObject(currentFile);
+ if (dfsValid != null){
+ if (dfsValid.getExponentSeparator().equals("*SpecialExponentSeparator*") &&
+ dfsValid.getCurrencySymbol().equals("*SpecialCurrencySymbol*")){
+ System.out.println(" Deserialization of current JDK Object from the current JDK: Passed.");
+ logln(" Deserialization of current JDK Object from the current JDK: Passed.");
+ } else {
+ errln(" Deserialization of current JDK Object from the current JDK was Failed:"
+ +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
+ /*
+ * logically should not throw this exception as errln throws exception
+ * if not thrown yet - but in case errln got changed
+ */
+ throw new RuntimeException(" Deserialization of current Object from the current JDK was Failed:"
+ +dfsValid.getCurrencySymbol()+" "+dfsValid.getExponentSeparator());
+ }
+ }
+ /*
+ * 3. Try to create an valid DecimalFormatSymbols object by passing null
+ * to set null for the exponent separator symbol. Expect the NullPointerException.
+ */
+ DecimalFormatSymbols symNPE = new DecimalFormatSymbols(Locale.US);
+ boolean npePassed = false;
+ try {
+ symNPE.setExponentSeparator(null);
+ } catch (NullPointerException npe){
+ npePassed = true;
+ System.out.println(" Trying to set exponent separator with null: Passed.");
+ logln(" Trying to set exponent separator with null: Passed.");
+ }
+ if (!npePassed){
+ System.out.println(" Trying to set exponent separator with null:Failed.");
+ errln(" Trying to set exponent separator with null:Failed.");
+ /*
+ * logically should not throw this exception as errln throws exception
+ * if not thrown yet - but in case errln got changed
+ */
+ throw new RuntimeException(" Trying to set exponent separator with null:Failed.");
+ }
+
+ }
+
+ private DecimalFormatSymbols readTestObject(File inputFile){
+ try (InputStream istream = inputFile.getName().endsWith(".txt") ?
+ HexDumpReader.getStreamFromHexDump(inputFile) :
+ new FileInputStream(inputFile)) {
+ ObjectInputStream p = new ObjectInputStream(istream);
+ DecimalFormatSymbols dfs = (DecimalFormatSymbols)p.readObject();
+ return dfs;
+ } catch (Exception e) {
+ errln("Test Malfunction in DFSSerialization: Exception while reading the object");
+ /*
+ * logically should not throw this exception as errln throws exception
+ * if not thrown yet - but in case errln got changed
+ */
+ throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
+ }
+ }
+
+ private File createTestObject(String objectName, String expString){
+ DecimalFormatSymbols dfs= new DecimalFormatSymbols();
+ dfs.setExponentSeparator(expString);
+ dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
+ logln(" The special exponent separator is set : " + dfs.getExponentSeparator());
+ logln(" The special currency symbol is set : " + dfs.getCurrencySymbol());
+
+ // 6345659: create a test object in the test.class dir where test user has a write permission.
+ File file = new File(System.getProperty("test.class", "."), objectName);
+ try (FileOutputStream ostream = new FileOutputStream(file)) {
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(dfs);
+ //System.out.println(" The special currency symbol is set : " + dfs.getCurrencySymbol());
+ return file;
+ } catch (Exception e){
+ errln("Test Malfunction in DFSSerialization: Exception while creating an object");
+ /*
+ * logically should not throw this exception as errln throws exception
+ * if not thrown yet - but in case errln got changed
+ */
+ throw new RuntimeException("Test Malfunction: re-throwing the exception", e);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/DFSSerialization142.java b/test/java/text/Format/NumberFormat/DFSSerialization142.java
new file mode 100644
index 0000000000..4a5e873ee2
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DFSSerialization142.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, 2016, 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on JDK 1.4.2
+ * Instead, the resulting serialized file
+ * DecimalFormatSymbols.142 is archived.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class DFSSerialization142 {
+
+ public static void main(String[] args)
+ {
+ try {
+
+ DecimalFormatSymbols dfs= new DecimalFormatSymbols();
+ System.out.println("Default currency symbol in the default locale : " + dfs.getCurrencySymbol());
+ dfs.setCurrencySymbol("*SpecialCurrencySymbol*");
+ System.out.println("The special currency symbol is set : " + dfs.getCurrencySymbol());
+ FileOutputStream ostream = new FileOutputStream("DecimalFormatSymbols.142");
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(dfs);
+ ostream.close();
+ System.out.println("DecimalFormatSymbols saved ok.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/DecimalFormat.114.txt b/test/java/text/Format/NumberFormat/DecimalFormat.114.txt
new file mode 100644
index 0000000000..efa6df4141
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DecimalFormat.114.txt
@@ -0,0 +1,54 @@
+#
+# Copyright (c) 1998, 2016, 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.
+#
+
+# Hex dump of a serialized DecimalFormat for SerializationLoadTest.
+
+aced000573720012436865636b446563696d616c466f726d6174aa9218d3b530
+540a0200014c000a5f646563466f726d61747400194c6a6176612f746578742f
+446563696d616c466f726d61743b7870737200176a6176612e746578742e4465
+63696d616c466f726d61740bff0362d872303a0200085a001b646563696d616c
+536570617261746f72416c7761797353686f776e42000c67726f7570696e6753
+697a6549000a6d756c7469706c6965724c000e6e656761746976655072656669
+787400124c6a6176612f6c616e672f537472696e673b4c000e6e656761746976
+655375666669787400124c6a6176612f6c616e672f537472696e673b4c000e70
+6f7369746976655072656669787400124c6a6176612f6c616e672f537472696e
+673b4c000e706f7369746976655375666669787400124c6a6176612f6c616e67
+2f537472696e673b4c000773796d626f6c737400204c6a6176612f746578742f
+446563696d616c466f726d617453796d626f6c733b787200166a6176612e7465
+78742e4e756d626572466f726d6174dff6b3bf137d07e80200065a000c67726f
+7570696e67557365644200116d61784672616374696f6e446967697473420010
+6d6178496e74656765724469676974734200116d696e4672616374696f6e4469
+676974734200106d696e496e74656765724469676974735a0010706172736549
+6e74656765724f6e6c79787200106a6176612e746578742e466f726d6174fbd8
+bc12e90f1843020000787001037f0001000003000000017400012d7400007400
+007400007372001e6a6176612e746578742e446563696d616c466f726d617453
+796d626f6c73501d17990868939c02000c430010646563696d616c5365706172
+61746f72430005646967697443001167726f7570696e67536570617261746f72
+4300096d696e75735369676e4300107061747465726e536570617261746f7243
+00077065724d696c6c43000770657263656e744300097a65726f44696769744c
+00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e637572
+72656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e673b
+4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e673b
+4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c61
+6e672f537472696e673b7870002e0023002c002d003b203000250030740003ef
+bfbd74000124740003e2889e740003555344
diff --git a/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt b/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt
new file mode 100644
index 0000000000..6707e375a9
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DecimalFormatSymbols.114.txt
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 1998, 2016, 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.
+#
+
+# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest.
+
+aced000573720019436865636b446563696d616c466f726d617453796d626f6c
+737763237e1aa359bb0200014c00115f646563466f726d617453796d626f6c73
+7400204c6a6176612f746578742f446563696d616c466f726d617453796d626f
+6c733b78707372001e6a6176612e746578742e446563696d616c466f726d6174
+53796d626f6c73501d17990868939c02000c430010646563696d616c53657061
+7261746f72430005646967697443001167726f7570696e67536570617261746f
+724300096d696e75735369676e4300107061747465726e536570617261746f72
+4300077065724d696c6c43000770657263656e744300097a65726f4469676974
+4c00034e614e7400124c6a6176612f6c616e672f537472696e673b4c000e6375
+7272656e637953796d626f6c7400124c6a6176612f6c616e672f537472696e67
+3b4c0008696e66696e6974797400124c6a6176612f6c616e672f537472696e67
+3b4c0012696e746c43757272656e637953796d626f6c7400124c6a6176612f6c
+616e672f537472696e673b7870002e0023002c002d003b203000250030740003
+efbfbd74000124740003e2889e740003555344
diff --git a/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt b/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt
new file mode 100644
index 0000000000..723f107b40
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/DecimalFormatSymbols.142.txt
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 1998, 2016, 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.
+#
+
+# Hex dump of a serialized DecimalFormatSymbols for SerializationLoadTest.
+
+aced00057372001e6a6176612e746578742e446563696d616c466f726d617453
+796d626f6c73501d17990868939c020010430010646563696d616c5365706172
+61746f72430005646967697443000b6578706f6e656e7469616c43001167726f
+7570696e67536570617261746f724300096d696e75735369676e4300116d6f6e
+6574617279536570617261746f724300107061747465726e536570617261746f
+724300077065724d696c6c43000770657263656e7449001573657269616c5665
+7273696f6e4f6e53747265616d4300097a65726f44696769744c00034e614e74
+00124c6a6176612f6c616e672f537472696e673b4c000e63757272656e637953
+796d626f6c71007e00014c0008696e66696e69747971007e00014c0012696e74
+6c43757272656e637953796d626f6c71007e00014c00066c6f63616c65740012
+4c6a6176612f7574696c2f4c6f63616c653b7870002e00230045002c002d002e
+003b20300025000000020030740003efbfbd7400172a5370656369616c437572
+72656e637953796d626f6c2a740003e2889e740003434e59737200106a617661
+2e7574696c2e4c6f63616c657ef811609c30f9ec03000449000868617368636f
+64654c0007636f756e74727971007e00014c00086c616e677561676571007e00
+014c000776617269616e7471007e00017870ffffffff740002434e7400027a68
+74000078
diff --git a/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java b/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java
new file mode 100644
index 0000000000..fcda5b863b
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/IntlTestDecimalFormatAPI.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @library /java/text/testlib
+ * @summary test International Decimal Format API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDecimalFormatAPI extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new IntlTestDecimalFormatAPI().run(args);
+ }
+
+ // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+ public void TestAPI()
+ {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ logln("DecimalFormat API test---"); logln("");
+ Locale.setDefault(Locale.ENGLISH);
+
+ // ======= Test constructors
+
+ logln("Testing DecimalFormat constructors");
+
+ DecimalFormat def = new DecimalFormat();
+
+ final String pattern = new String("#,##0.# FF");
+ DecimalFormat pat = null;
+ try {
+ pat = new DecimalFormat(pattern);
+ }
+ catch (IllegalArgumentException e) {
+ errln("ERROR: Could not create DecimalFormat (pattern)");
+ }
+
+ DecimalFormatSymbols symbols =
+ new DecimalFormatSymbols(Locale.FRENCH);
+
+ DecimalFormat cust1 = new DecimalFormat(pattern, symbols);
+
+ // ======= Test clone(), assignment, and equality
+
+ logln("Testing clone() and equality operators");
+
+ Format clone = (Format) def.clone();
+ if( ! def.equals(clone)) {
+ errln("ERROR: Clone() failed");
+ }
+
+ // ======= Test various format() methods
+
+ logln("Testing various format() methods");
+
+// final double d = -10456.0037; // this appears as
+ // -10456.003700000001 on NT
+// final double d = -1.04560037e-4; // this appears as
+ // -1.0456003700000002E-4 on NT
+ final double d = -10456.00370000000000; // this works!
+ final long l = 100000000;
+ logln("" + d + " is the double value");
+
+ StringBuffer res1 = new StringBuffer();
+ StringBuffer res2 = new StringBuffer();
+ StringBuffer res3 = new StringBuffer();
+ StringBuffer res4 = new StringBuffer();
+ FieldPosition pos1 = new FieldPosition(0);
+ FieldPosition pos2 = new FieldPosition(0);
+ FieldPosition pos3 = new FieldPosition(0);
+ FieldPosition pos4 = new FieldPosition(0);
+
+ res1 = def.format(d, res1, pos1);
+ logln("" + d + " formatted to " + res1);
+
+ res2 = pat.format(l, res2, pos2);
+ logln("" + l + " formatted to " + res2);
+
+ res3 = cust1.format(d, res3, pos3);
+ logln("" + d + " formatted to " + res3);
+
+ res4 = cust1.format(l, res4, pos4);
+ logln("" + l + " formatted to " + res4);
+
+ // ======= Test parse()
+
+ logln("Testing parse()");
+
+ String text = new String("-10,456.0037");
+ ParsePosition pos = new ParsePosition(0);
+ String patt = new String("#,##0.#");
+ pat.applyPattern(patt);
+ double d2 = pat.parse(text, pos).doubleValue();
+ if(d2 != d) {
+ errln("ERROR: Roundtrip failed (via parse(" +
+ d2 + " != " + d + ")) for " + text);
+ }
+ logln(text + " parsed into " + (long) d2);
+
+ // ======= Test getters and setters
+
+ logln("Testing getters and setters");
+
+ final DecimalFormatSymbols syms = pat.getDecimalFormatSymbols();
+ def.setDecimalFormatSymbols(syms);
+ if(!pat.getDecimalFormatSymbols().equals(
+ def.getDecimalFormatSymbols())) {
+ errln("ERROR: set DecimalFormatSymbols() failed");
+ }
+
+ String posPrefix;
+ pat.setPositivePrefix("+");
+ posPrefix = pat.getPositivePrefix();
+ logln("Positive prefix (should be +): " + posPrefix);
+ if(posPrefix != "+") {
+ errln("ERROR: setPositivePrefix() failed");
+ }
+
+ String negPrefix;
+ pat.setNegativePrefix("-");
+ negPrefix = pat.getNegativePrefix();
+ logln("Negative prefix (should be -): " + negPrefix);
+ if(negPrefix != "-") {
+ errln("ERROR: setNegativePrefix() failed");
+ }
+
+ String posSuffix;
+ pat.setPositiveSuffix("_");
+ posSuffix = pat.getPositiveSuffix();
+ logln("Positive suffix (should be _): " + posSuffix);
+ if(posSuffix != "_") {
+ errln("ERROR: setPositiveSuffix() failed");
+ }
+
+ String negSuffix;
+ pat.setNegativeSuffix("~");
+ negSuffix = pat.getNegativeSuffix();
+ logln("Negative suffix (should be ~): " + negSuffix);
+ if(negSuffix != "~") {
+ errln("ERROR: setNegativeSuffix() failed");
+ }
+
+ long multiplier = 0;
+ pat.setMultiplier(8);
+ multiplier = pat.getMultiplier();
+ logln("Multiplier (should be 8): " + multiplier);
+ if(multiplier != 8) {
+ errln("ERROR: setMultiplier() failed");
+ }
+
+ int groupingSize = 0;
+ pat.setGroupingSize(2);
+ groupingSize = pat.getGroupingSize();
+ logln("Grouping size (should be 2): " + (long) groupingSize);
+ if(groupingSize != 2) {
+ errln("ERROR: setGroupingSize() failed");
+ }
+
+ pat.setDecimalSeparatorAlwaysShown(true);
+ boolean tf = pat.isDecimalSeparatorAlwaysShown();
+ logln("DecimalSeparatorIsAlwaysShown (should be true) is " +
+ (tf ? "true" : "false"));
+ if(tf != true) {
+ errln("ERROR: setDecimalSeparatorAlwaysShown() failed");
+ }
+
+ String funkyPat;
+ funkyPat = pat.toPattern();
+ logln("Pattern is " + funkyPat);
+
+ String locPat;
+ locPat = pat.toLocalizedPattern();
+ logln("Localized pattern is " + locPat);
+
+ // ======= Test applyPattern()
+
+ logln("Testing applyPattern()");
+
+ String p1 = new String("#,##0.0#;(#,##0.0#)");
+ logln("Applying pattern " + p1);
+ pat.applyPattern(p1);
+ String s2;
+ s2 = pat.toPattern();
+ logln("Extracted pattern is " + s2);
+ if( ! s2.equals(p1) ) {
+ errln("ERROR: toPattern() result did not match " +
+ "pattern applied");
+ }
+
+ String p2 = new String("#,##0.0# FF;(#,##0.0# FF)");
+ logln("Applying pattern " + p2);
+ pat.applyLocalizedPattern(p2);
+ String s3;
+ s3 = pat.toLocalizedPattern();
+ logln("Extracted pattern is " + s3);
+ if( ! s3.equals(p2) ) {
+ errln("ERROR: toLocalizedPattern() result did not match " +
+ "pattern applied");
+ }
+
+ // ======= Test getStaticClassID()
+
+// logln("Testing instanceof()");
+
+// try {
+// NumberFormat test = new DecimalFormat();
+
+// if (! (test instanceof DecimalFormat)) {
+// errln("ERROR: instanceof failed");
+// }
+// }
+// catch (Exception e) {
+// errln("ERROR: Couldn't create a DecimalFormat");
+// }
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java b/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java
new file mode 100644
index 0000000000..cd19fee1e3
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/IntlTestDecimalFormatSymbols.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @library /java/text/testlib
+ * @summary test International Decimal Format Symbols
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestDecimalFormatSymbols extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new IntlTestDecimalFormatSymbols().run(args);
+ }
+
+ // Test the API of DecimalFormatSymbols; primarily a simple get/set set.
+ public void TestSymbols()
+ {
+ DecimalFormatSymbols fr = new DecimalFormatSymbols(Locale.FRENCH);
+
+ DecimalFormatSymbols en = new DecimalFormatSymbols(Locale.ENGLISH);
+
+ if(en.equals(fr)) {
+ errln("ERROR: English DecimalFormatSymbols equal to French");
+ }
+
+ // just do some VERY basic tests to make sure that get/set work
+
+ char zero = en.getZeroDigit();
+ fr.setZeroDigit(zero);
+ if(fr.getZeroDigit() != en.getZeroDigit()) {
+ errln("ERROR: get/set ZeroDigit failed");
+ }
+
+ char group = en.getGroupingSeparator();
+ fr.setGroupingSeparator(group);
+ if(fr.getGroupingSeparator() != en.getGroupingSeparator()) {
+ errln("ERROR: get/set GroupingSeparator failed");
+ }
+
+ char decimal = en.getDecimalSeparator();
+ fr.setDecimalSeparator(decimal);
+ if(fr.getDecimalSeparator() != en.getDecimalSeparator()) {
+ errln("ERROR: get/set DecimalSeparator failed");
+ }
+
+ char perMill = en.getPerMill();
+ fr.setPerMill(perMill);
+ if(fr.getPerMill() != en.getPerMill()) {
+ errln("ERROR: get/set PerMill failed");
+ }
+
+ char percent = en.getPercent();
+ fr.setPercent(percent);
+ if(fr.getPercent() != en.getPercent()) {
+ errln("ERROR: get/set Percent failed");
+ }
+
+ char digit = en.getDigit();
+ fr.setDigit(digit);
+ if(fr.getPercent() != en.getPercent()) {
+ errln("ERROR: get/set Percent failed");
+ }
+
+ char patternSeparator = en.getPatternSeparator();
+ fr.setPatternSeparator(patternSeparator);
+ if(fr.getPatternSeparator() != en.getPatternSeparator()) {
+ errln("ERROR: get/set PatternSeparator failed");
+ }
+
+ String infinity = en.getInfinity();
+ fr.setInfinity(infinity);
+ String infinity2 = fr.getInfinity();
+ if(! infinity.equals(infinity2)) {
+ errln("ERROR: get/set Infinity failed");
+ }
+
+ String nan = en.getNaN();
+ fr.setNaN(nan);
+ String nan2 = fr.getNaN();
+ if(! nan.equals(nan2)) {
+ errln("ERROR: get/set NaN failed");
+ }
+
+ char minusSign = en.getMinusSign();
+ fr.setMinusSign(minusSign);
+ if(fr.getMinusSign() != en.getMinusSign()) {
+ errln("ERROR: get/set MinusSign failed");
+ }
+
+// char exponential = en.getExponentialSymbol();
+// fr.setExponentialSymbol(exponential);
+// if(fr.getExponentialSymbol() != en.getExponentialSymbol()) {
+// errln("ERROR: get/set Exponential failed");
+// }
+
+ DecimalFormatSymbols foo = new DecimalFormatSymbols();
+
+ en = (DecimalFormatSymbols) fr.clone();
+
+ if(! en.equals(fr)) {
+ errln("ERROR: Clone failed");
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java b/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java
new file mode 100644
index 0000000000..ab1069bdfc
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/IntlTestNumberFormatAPI.java
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1998, 2016, 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
+ * @library /java/text/testlib
+ * @summary test International Number Format API
+ */
+/*
+(C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+(C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+
+public class IntlTestNumberFormatAPI extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new IntlTestNumberFormatAPI().run(args);
+ }
+
+ // This test checks various generic API methods in DecimalFormat to achieve 100% API coverage.
+ public void TestAPI()
+ {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ logln("NumberFormat API test---"); logln("");
+ Locale.setDefault(Locale.ENGLISH);
+
+ // ======= Test constructors
+
+ logln("Testing NumberFormat constructors");
+
+ NumberFormat def = NumberFormat.getInstance();
+
+ NumberFormat fr = NumberFormat.getInstance(Locale.FRENCH);
+
+ NumberFormat cur = NumberFormat.getCurrencyInstance();
+
+ NumberFormat cur_fr =
+ NumberFormat.getCurrencyInstance(Locale.FRENCH);
+
+ NumberFormat per = NumberFormat.getPercentInstance();
+
+ NumberFormat per_fr =
+ NumberFormat.getPercentInstance(Locale.FRENCH);
+
+ // ======= Test equality
+
+ logln("Testing equality operator");
+
+ if( per_fr.equals(cur_fr) ) {
+ errln("ERROR: == failed");
+ }
+
+ // ======= Test various format() methods
+
+ logln("Testing various format() methods");
+
+// final double d = -10456.0037; // this appears as
+ // -10456.003700000001 on NT
+// final double d = -1.04560037e-4; // this appears as
+ // -1.0456003700000002E-4 on NT
+ final double d = -10456.00370000000000; // this works!
+ final long l = 100000000;
+
+ String res1 = new String();
+ String res2 = new String();
+ StringBuffer res3 = new StringBuffer();
+ StringBuffer res4 = new StringBuffer();
+ StringBuffer res5 = new StringBuffer();
+ StringBuffer res6 = new StringBuffer();
+ FieldPosition pos1 = new FieldPosition(0);
+ FieldPosition pos2 = new FieldPosition(0);
+ FieldPosition pos3 = new FieldPosition(0);
+ FieldPosition pos4 = new FieldPosition(0);
+
+ res1 = cur_fr.format(d);
+ logln( "" + d + " formatted to " + res1);
+
+ res2 = cur_fr.format(l);
+ logln("" + l + " formatted to " + res2);
+
+ res3 = cur_fr.format(d, res3, pos1);
+ logln( "" + d + " formatted to " + res3);
+
+ res4 = cur_fr.format(l, res4, pos2);
+ logln("" + l + " formatted to " + res4);
+
+ res5 = cur_fr.format(d, res5, pos3);
+ logln("" + d + " formatted to " + res5);
+
+ res6 = cur_fr.format(l, res6, pos4);
+ logln("" + l + " formatted to " + res6);
+
+
+ // ======= Test parse()
+
+ logln("Testing parse()");
+
+// String text = new String("-10,456.0037");
+ String text = new String("-10456,0037");
+ ParsePosition pos = new ParsePosition(0);
+ ParsePosition pos01 = new ParsePosition(0);
+ double d1 = ((Number)fr.parseObject(text, pos)).doubleValue();
+ if(d1 != d) {
+ errln("ERROR: Roundtrip failed (via parse()) for " + text);
+ }
+ logln(text + " parsed into " + d1);
+
+ double d2 = fr.parse(text, pos01).doubleValue();
+ if(d2 != d) {
+ errln("ERROR: Roundtrip failed (via parse()) for " + text);
+ }
+ logln(text + " parsed into " + d2);
+
+ double d3 = 0;
+ try {
+ d3 = fr.parse(text).doubleValue();
+ }
+ catch (ParseException e) {
+ errln("ERROR: parse() failed");
+ }
+ if(d3 != d) {
+ errln("ERROR: Roundtrip failed (via parse()) for " + text);
+ }
+ logln(text + " parsed into " + d3);
+
+
+ // ======= Test getters and setters
+
+ logln("Testing getters and setters");
+
+ final Locale[] locales = NumberFormat.getAvailableLocales();
+ long count = locales.length;
+ logln("Got " + count + " locales" );
+ for(int i = 0; i < count; i++) {
+ String name;
+ name = locales[i].getDisplayName();
+ logln(name);
+ }
+
+ fr.setParseIntegerOnly( def.isParseIntegerOnly() );
+ if(fr.isParseIntegerOnly() != def.isParseIntegerOnly() ) {
+ errln("ERROR: setParseIntegerOnly() failed");
+ }
+
+ fr.setGroupingUsed( def.isGroupingUsed() );
+ if(fr.isGroupingUsed() != def.isGroupingUsed() ) {
+ errln("ERROR: setGroupingUsed() failed");
+ }
+
+ fr.setMaximumIntegerDigits( def.getMaximumIntegerDigits() );
+ if(fr.getMaximumIntegerDigits() != def.getMaximumIntegerDigits() ) {
+ errln("ERROR: setMaximumIntegerDigits() failed");
+ }
+
+ fr.setMinimumIntegerDigits( def.getMinimumIntegerDigits() );
+ if(fr.getMinimumIntegerDigits() != def.getMinimumIntegerDigits() ) {
+ errln("ERROR: setMinimumIntegerDigits() failed");
+ }
+
+ fr.setMaximumFractionDigits( def.getMaximumFractionDigits() );
+ if(fr.getMaximumFractionDigits() != def.getMaximumFractionDigits() ) {
+ errln("ERROR: setMaximumFractionDigits() failed");
+ }
+
+ fr.setMinimumFractionDigits( def.getMinimumFractionDigits() );
+ if(fr.getMinimumFractionDigits() != def.getMinimumFractionDigits() ) {
+ errln("ERROR: setMinimumFractionDigits() failed");
+ }
+
+ // ======= Test getStaticClassID()
+
+// logln("Testing instanceof()");
+
+// try {
+// NumberFormat test = new DecimalFormat();
+
+// if (! (test instanceof DecimalFormat)) {
+// errln("ERROR: instanceof failed");
+// }
+// }
+// catch (Exception e) {
+// errln("ERROR: Couldn't create a DecimalFormat");
+// }
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt b/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt
new file mode 100644
index 0000000000..d27bb94eb6
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberFormat4185761a.ser.txt
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a serialized NumberFormat for NumberRegression.
+
+aced0005737200176a6176612e746578742e446563696d616c466f726d61740b
+ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77
+61797353686f776e42000c67726f7570696e6753697a654200116d696e457870
+6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961
+6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961
+6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61
+76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978
+71007e00014c000e706f73697469766550726566697871007e00014c000e706f
+73697469766553756666697871007e00014c000773796d626f6c737400204c6a
+6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872
+00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8
+03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e
+4469676974734200106d6178496e74656765724469676974734900156d617869
+6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567
+65724469676974734200116d696e4672616374696f6e4469676974734200106d
+696e496e74656765724469676974734900156d696e696d756d4672616374696f
+6e4469676974734900146d696e696d756d496e74656765724469676974735a00
+107061727365496e74656765724f6e6c7949001573657269616c56657273696f
+6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f18430200007870017f7f00000123000001217f7f000001240000012200
+00000001780003000000000100000001007400012d7400007400007400007372
+001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73
+501d17990868939c02000f430010646563696d616c536570617261746f724300
+05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753
+6570617261746f724300096d696e75735369676e4300116d6f6e657461727953
+6570617261746f724300107061747465726e536570617261746f724300077065
+724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f
+6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00
+0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971
+007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870
+002e00230045002c002d002e003b20300025000000010030740003efbfbd7400
+0124740003e2889e740003555344
diff --git a/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt b/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt
new file mode 100644
index 0000000000..8da4dde6bd
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberFormat4185761b.ser.txt
@@ -0,0 +1,57 @@
+#
+# Copyright (c) 1999, 2016, 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.
+#
+
+# Hex dump of a serialized NumberFormat for NumberRegression.
+
+aced0005737200176a6176612e746578742e446563696d616c466f726d61740b
+ff0362d872303a02000b5a001b646563696d616c536570617261746f72416c77
+61797353686f776e42000c67726f7570696e6753697a654200116d696e457870
+6f6e656e7444696769747349000a6d756c7469706c6965724900157365726961
+6c56657273696f6e4f6e53747265616d5a00167573654578706f6e656e746961
+6c4e6f746174696f6e4c000e6e656761746976655072656669787400124c6a61
+76612f6c616e672f537472696e673b4c000e6e65676174697665537566666978
+71007e00014c000e706f73697469766550726566697871007e00014c000e706f
+73697469766553756666697871007e00014c000773796d626f6c737400204c6a
+6176612f746578742f446563696d616c466f726d617453796d626f6c733b7872
+00166a6176612e746578742e4e756d626572466f726d6174dff6b3bf137d07e8
+03000b5a000c67726f7570696e67557365644200116d61784672616374696f6e
+4469676974734200106d6178496e74656765724469676974734900156d617869
+6d756d4672616374696f6e4469676974734900146d6178696d756d496e746567
+65724469676974734200116d696e4672616374696f6e4469676974734200106d
+696e496e74656765724469676974734900156d696e696d756d4672616374696f
+6e4469676974734900146d696e696d756d496e74656765724469676974735a00
+107061727365496e74656765724f6e6c7949001573657269616c56657273696f
+6e4f6e53747265616d787200106a6176612e746578742e466f726d6174fbd8bc
+12e90f18430200007870017f7f00000314000003127f7f000003130000031100
+00000001780003000000000100000001007400012d7400007400007400007372
+001e6a6176612e746578742e446563696d616c466f726d617453796d626f6c73
+501d17990868939c02000f430010646563696d616c536570617261746f724300
+05646967697443000b6578706f6e656e7469616c43001167726f7570696e6753
+6570617261746f724300096d696e75735369676e4300116d6f6e657461727953
+6570617261746f724300107061747465726e536570617261746f724300077065
+724d696c6c43000770657263656e7449001573657269616c56657273696f6e4f
+6e53747265616d4300097a65726f44696769744c00034e614e71007e00014c00
+0e63757272656e637953796d626f6c71007e00014c0008696e66696e69747971
+007e00014c0012696e746c43757272656e637953796d626f6c71007e00017870
+002e00230045002c002d002e003b20300025000000010030740003efbfbd7400
+0124740003e2889e740003555344
diff --git a/test/java/text/Format/NumberFormat/NumberFormatRounding.java b/test/java/text/Format/NumberFormat/NumberFormatRounding.java
new file mode 100644
index 0000000000..895d885ff2
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberFormatRounding.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4092330 6246348
+ * @summary Tests for rounding mode in NumberFormat
+ */
+
+import java.math.*;
+import java.text.*;
+
+public class NumberFormatRounding {
+
+ static final String AE = "ArithmeticException";
+
+ static final double src[] = {5.5, 2.5, 1.6, 1.1, 1.0, -1.0, -1.1, -1.6, -2.5, -5.5,
+ 5.501, -5.501, 5.500, -5.500, 1.001, -1.001, 4.501, -4.501, 4.500, -4.500};
+ static final String up[] = {"6", "3", "2", "2", "1", "-1", "-2", "-2", "-3", "-6",
+ "6", "-6", "6", "-6", "2", "-2", "5", "-5", "5", "-5"};
+ static final String down[] = {"5", "2", "1", "1", "1", "-1", "-1", "-1", "-2", "-5",
+ "5", "-5", "5", "-5", "1", "-1", "4", "-4", "4", "-4"};
+ static final String ceiling[] = {"6", "3", "2", "2", "1", "-1", "-1", "-1", "-2", "-5",
+ "6", "-5", "6", "-5", "2", "-1", "5", "-4", "5", "-4"};
+ static final String floor[] = {"5", "2", "1", "1", "1", "-1", "-2", "-2", "-3", "-6",
+ "5", "-6", "5", "-6", "1", "-2", "4", "-5", "4", "-5"};
+ static final String half_up[] = {"6", "3", "2", "1", "1", "-1", "-1", "-2", "-3", "-6",
+ "6", "-6", "6", "-6", "1", "-1", "5", "-5", "5", "-5"};
+ static final String half_down[] = {"5", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-5",
+ "6", "-6", "5", "-5", "1", "-1", "5", "-5", "4", "-4"};
+ static final String half_even[] = {"6", "2", "2", "1", "1", "-1", "-1", "-2", "-2", "-6",
+ "6", "-6", "6", "-6", "1", "-1", "5", "-5", "4", "-4"};
+ static final String unnecessary[] = {AE, AE, AE, AE, "1", "-1", AE, AE, AE, AE,
+ AE, AE, AE, AE, AE, AE, AE, AE, AE, AE};
+
+ public static void main(String[] args) {
+ basicTest();
+
+ roundTest(RoundingMode.UP, up);
+ roundTest(RoundingMode.DOWN, down);
+ roundTest(RoundingMode.CEILING, ceiling);
+ roundTest(RoundingMode.FLOOR, floor);
+ roundTest(RoundingMode.HALF_UP, half_up);
+ roundTest(RoundingMode.HALF_DOWN, half_down);
+ roundTest(RoundingMode.HALF_EVEN, half_even);
+ roundTest(RoundingMode.UNNECESSARY, unnecessary);
+ }
+
+ static void basicTest() {
+ NumberFormat nf = NumberFormat.getIntegerInstance();
+
+ if (nf.getRoundingMode() != RoundingMode.HALF_EVEN) {
+ throw new RuntimeException("default rounding is not HALF_EVEN");
+ }
+
+ try {
+ nf.setRoundingMode(null);
+ throw new RuntimeException(
+ "NullPointerException is not thrown by calling setRoundingMode(null)");
+ } catch (NullPointerException npe) {
+ // continue testing
+ }
+
+ ChoiceFormat cf = new ChoiceFormat("");
+
+ try {
+ cf.setRoundingMode(RoundingMode.HALF_EVEN);
+ throw new RuntimeException(
+ "UnsupportedOperationException is not thrown by calling setRoundingMode()");
+ } catch (UnsupportedOperationException uoe) {
+ // continue testing
+ }
+
+ try {
+ cf.getRoundingMode();
+ throw new RuntimeException(
+ "UnsupportedOperationException is not thrown by calling getRoundingMode()");
+ } catch (UnsupportedOperationException uoe) {
+ // continue testing
+ }
+ }
+
+ static void roundTest(RoundingMode rm, String[] expected) {
+ NumberFormat nf = NumberFormat.getIntegerInstance();
+ nf.setRoundingMode(rm);
+
+ if (nf.getRoundingMode() != rm) {
+ throw new RuntimeException("set rounding mode is not returned by get method");
+ }
+
+ for (int i = 0; i < src.length; i ++) {
+ String result = null;
+ try {
+ result = nf.parse(nf.format(src[i])).toString();
+ if (!result.equals(expected[i])) {
+ throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result);
+ }
+ } catch (ArithmeticException ae) {
+ if (expected[i].equals(AE)) {
+ continue;
+ } else {
+ result = AE;
+ throw new RuntimeException("rounding test #"+i+" failed. mode: "+rm+" src: "+src[i]+" expected: "+expected[i]+" result: "+result);
+ }
+ } catch (ParseException pe) {
+ throw new RuntimeException("ParseException ocurred.", pe);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/NumberRegression.java b/test/java/text/Format/NumberFormat/NumberRegression.java
new file mode 100644
index 0000000000..674fdd619c
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberRegression.java
@@ -0,0 +1,1824 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4052223 4059870 4061302 4062486 4066646 4068693 4070798 4071005 4071014
+ * 4071492 4071859 4074454 4074620 4075713 4083018 4086575 4087244 4087245
+ * 4087251 4087535 4088161 4088503 4090489 4090504 4092480 4092561 4095713
+ * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840
+ * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198
+ * 4162852 4167494 4170798 4176114 4179818 4185761 4212072 4212073 4216742
+ * 4217661 4243011 4243108 4330377 4233840 4241880 4833877 8008577
+ * @summary Regression tests for NumberFormat and associated classes
+ * @library /java/text/testlib
+ * @build IntlTest HexDumpReader
+ * @modules java.base/sun.util.resources
+ * @compile -XDignore.symbol.file NumberRegression.java
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberRegression
+ */
+
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.util.*;
+import java.math.BigDecimal;
+import java.io.*;
+import java.math.BigInteger;
+import sun.util.resources.LocaleData;
+
+public class NumberRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new NumberRegression().run(args);
+ }
+
+ /**
+ * NumberFormat.equals comparing with null should always return false.
+ */
+ public void Test4075713(){
+
+ try {
+ MyNumberFormatTest tmp = new MyNumberFormatTest();
+ if (!tmp.equals(null))
+ logln("NumberFormat.equals passed");
+ } catch (NullPointerException e) {
+ errln("(new MyNumberFormatTest()).equals(null) throws unexpected exception");
+ }
+ }
+
+ /**
+ * NumberFormat.equals comparing two obj equal even the setGroupingUsed
+ * flag is different.
+ */
+ public void Test4074620() {
+
+ MyNumberFormatTest nf1 = new MyNumberFormatTest();
+ MyNumberFormatTest nf2 = new MyNumberFormatTest();
+
+ nf1.setGroupingUsed(false);
+ nf2.setGroupingUsed(true);
+
+ if (nf1.equals(nf2)) errln("Test for bug 4074620 failed");
+ else logln("Test for bug 4074620 passed.");
+ return;
+ }
+
+
+ /**
+ * DecimalFormat.format() incorrectly uses maxFractionDigits setting.
+ */
+
+ public void Test4088161 (){
+ DecimalFormat df = new DecimalFormat();
+ double d = 100;
+ df.setMinimumFractionDigits(0);
+ df.setMaximumFractionDigits(16);
+ StringBuffer sBuf1 = new StringBuffer("");
+ FieldPosition fp1 = new FieldPosition(0);
+ logln("d = " + d);
+ logln("maxFractionDigits = " + df.getMaximumFractionDigits());
+ logln(" format(d) = '" + df.format(d, sBuf1, fp1) + "'");
+ df.setMaximumFractionDigits(17);
+ StringBuffer sBuf2 = new StringBuffer("");
+ FieldPosition fp2 = new FieldPosition(0);
+ logln("maxFractionDigits = " + df.getMaximumFractionDigits());
+ df.format(d, sBuf2, fp2);
+ String expected = Locale.getDefault().equals(new Locale("hi", "IN")) ?
+ "\u0967\u0966\u0966" : "100";
+ if (!sBuf2.toString().equals(expected))
+ errln(" format(d) = '" + sBuf2 + "'");
+ }
+ /**
+ * DecimalFormatSymbols should be cloned in the ctor DecimalFormat.
+ * DecimalFormat(String, DecimalFormatSymbols).
+ */
+ public void Test4087245 (){
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance();
+ DecimalFormat df = new DecimalFormat("#,##0.0", symbols);
+ long n = 123;
+ StringBuffer buf1 = new StringBuffer();
+ StringBuffer buf2 = new StringBuffer();
+ logln("format(" + n + ") = " +
+ df.format(n, buf1, new FieldPosition(0)));
+ symbols.setDecimalSeparator('p'); // change value of field
+ logln("format(" + n + ") = " +
+ df.format(n, buf2, new FieldPosition(0)));
+ if (!buf1.toString().equals(buf2.toString()))
+ errln("Test for bug 4087245 failed");
+ }
+ /**
+ * DecimalFormat.format() incorrectly formats 0.0
+ */
+ public void Test4087535 ()
+ {
+ DecimalFormat df = new DecimalFormat();
+ df.setMinimumIntegerDigits(0);
+
+ double n = 0;
+ String buffer = new String();
+ buffer = df.format(n);
+ if (buffer.length() == 0)
+ errln(n + ": '" + buffer + "'");
+ n = 0.1;
+ buffer = df.format(n);
+ if (buffer.length() == 0)
+ errln(n + ": '" + buffer + "'");
+ }
+
+ /**
+ * DecimalFormat.format fails when groupingSize is set to 0.
+ */
+ public void Test4088503 (){
+ DecimalFormat df = new DecimalFormat();
+ df.setGroupingSize(0);
+ StringBuffer sBuf = new StringBuffer("");
+ FieldPosition fp = new FieldPosition(0);
+ try {
+ logln(df.format(123, sBuf, fp).toString());
+ } catch (Exception foo) {
+ errln("Test for bug 4088503 failed.");
+ }
+
+ }
+ /**
+ * NumberFormat.getCurrencyInstance is wrong.
+ */
+ public void Test4066646 () {
+ float returnfloat = 0.0f;
+ assignFloatValue(2.04f);
+ assignFloatValue(2.03f);
+ assignFloatValue(2.02f);
+ assignFloatValue(0.0f);
+ }
+
+ public float assignFloatValue(float returnfloat)
+ {
+ logln(" VALUE " + returnfloat);
+ NumberFormat nfcommon = NumberFormat.getCurrencyInstance(Locale.US);
+ nfcommon.setGroupingUsed(false);
+
+ String stringValue = nfcommon.format(returnfloat).substring(1);
+ if (Float.valueOf(stringValue).floatValue() != returnfloat)
+ errln(" DISPLAYVALUE " + stringValue);
+ return returnfloat;
+ } // End Of assignFloatValue()
+
+ /**
+ * DecimalFormat throws exception when parsing "0"
+ */
+ public void Test4059870() {
+ DecimalFormat format = new DecimalFormat("00");
+ try {
+ logln(format.parse("0").toString());
+ } catch (Exception e) { errln("Test for bug 4059870 failed : " + e); }
+ }
+ /**
+ * DecimalFormatSymbol.equals should always return false when
+ * comparing with null.
+ */
+
+ public void Test4083018 (){
+ DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance();
+ try {
+ if (!dfs.equals(null))
+ logln("Test Passed!");
+ } catch (Exception foo) {
+ errln("Test for bug 4083018 failed => Message : " + foo.getMessage());
+ }
+ }
+ /**
+ * DecimalFormat does not round up correctly.
+ */
+ public void Test4071492 (){
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ double x = 0.00159999;
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(4);
+ String out = nf.format(x);
+ logln("0.00159999 formats with 4 fractional digits to " + out);
+ String expected = "0.0016";
+ if (!out.equals(expected))
+ errln("FAIL: Expected " + expected);
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * A space as a group separator for localized pattern causes
+ * wrong format. WorkAround : use non-breaking space.
+ */
+ public void Test4086575() {
+
+ NumberFormat nf = NumberFormat.getInstance(Locale.FRANCE);
+ logln("nf toPattern1: " + ((DecimalFormat)nf).toPattern());
+ logln("nf toLocPattern1: " + ((DecimalFormat)nf).toLocalizedPattern());
+
+ // No group separator
+ logln("...applyLocalizedPattern ###,00;(###,00) ");
+ ((DecimalFormat)nf).applyLocalizedPattern("###,00;(###,00)");
+ logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
+ logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
+
+ logln("nf: " + nf.format(1234)); // 1234,00
+ logln("nf: " + nf.format(-1234)); // (1234,00)
+
+ // Space as group separator
+
+ logln("...applyLocalizedPattern # ###,00;(# ###,00) ");
+ ((DecimalFormat)nf).applyLocalizedPattern("#\u00a0###,00;(#\u00a0###,00)");
+ logln("nf toPattern2: " + ((DecimalFormat)nf).toPattern());
+ logln("nf toLocPattern2: " + ((DecimalFormat)nf).toLocalizedPattern());
+ String buffer = nf.format(1234);
+ if (!buffer.equals("1\u00a0234,00"))
+ errln("nf : " + buffer); // Expect 1 234,00
+ buffer = nf.format(-1234);
+ if (!buffer.equals("(1\u00a0234,00)"))
+ errln("nf : " + buffer); // Expect (1 234,00)
+
+ // Erroneously prints:
+ // 1234,00 ,
+ // (1234,00 ,)
+
+ }
+ /**
+ * DecimalFormat.parse returns wrong value
+ */
+ public void Test4068693()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ logln("----- Test Application -----");
+ ParsePosition pos;
+ DecimalFormat df = new DecimalFormat();
+ Double d = (Double)df.parse("123.55456", pos=new ParsePosition(0));
+ if (!d.toString().equals("123.55456")) {
+ errln("Result -> " + d.doubleValue());
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /* bugs 4069754, 4067878
+ * null pointer thrown when accessing a deserialized DecimalFormat
+ * object.
+ */
+ public void Test4069754()
+ {
+ try {
+ myformat it = new myformat();
+ logln(it.Now());
+ FileOutputStream ostream = new FileOutputStream("t.tmp");
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(it);
+ ostream.close();
+ logln("Saved ok.");
+
+ FileInputStream istream = new FileInputStream("t.tmp");
+ ObjectInputStream p2 = new ObjectInputStream(istream);
+ myformat it2 = (myformat)p2.readObject();
+ logln(it2.Now());
+ istream.close();
+ logln("Loaded ok.");
+ } catch (Exception foo) {
+ errln("Test for bug 4069754 or 4057878 failed => Exception: " + foo.getMessage());
+ }
+ }
+
+ /**
+ * DecimalFormat.applyPattern(String) allows illegal patterns
+ */
+ public void Test4087251 (){
+ DecimalFormat df = new DecimalFormat();
+ try {
+ df.applyPattern("#.#.#");
+ logln("toPattern() returns \"" + df.toPattern() + "\"");
+ errln("applyPattern(\"#.#.#\") doesn't throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ logln("Caught Illegal Argument Error !");
+ }
+ // Second test; added 5/11/98 when reported to fail on 1.2b3
+ try {
+ df.applyPattern("#0.0#0#0");
+ logln("toPattern() returns \"" + df.toPattern() + "\"");
+ errln("applyPattern(\"#0.0#0#0\") doesn't throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ logln("Ok - IllegalArgumentException for #0.0#0#0");
+ }
+ }
+
+ /**
+ * DecimalFormat.format() loses precision
+ */
+ public void Test4090489 (){
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat();
+ df.setMinimumFractionDigits(10);
+ df.setGroupingUsed(false);
+ double d = 1.000000000000001E7;
+ BigDecimal bd = new BigDecimal(d);
+ StringBuffer sb = new StringBuffer("");
+ FieldPosition fp = new FieldPosition(0);
+ logln("d = " + d);
+ logln("BigDecimal.toString(): " + bd.toString());
+ df.format(d, sb, fp);
+ if (!sb.toString().equals("10000000.0000000100")) {
+ errln("DecimalFormat.format(): " + sb.toString());
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * DecimalFormat.format() loses precision
+ */
+ public void Test4090504 ()
+ {
+ double d = 1;
+ logln("d = " + d);
+ DecimalFormat df = new DecimalFormat();
+ StringBuffer sb;
+ FieldPosition fp;
+ try {
+ for (int i = 17; i <= 20; i++) {
+ df.setMaximumFractionDigits(i);
+ sb = new StringBuffer("");
+ fp = new FieldPosition(0);
+ logln(" getMaximumFractionDigits() = " + i);
+ logln(" formated: " + df.format(d, sb, fp));
+ }
+ } catch (Exception foo) {
+ errln("Bug 4090504 regression test failed. Message : " + foo.getMessage());
+ }
+ }
+ /**
+ * DecimalFormat.parse(String str, ParsePosition pp) loses precision
+ */
+ public void Test4095713 ()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat();
+ String str = "0.1234";
+ Double d1 = new Double(str);
+ Double d2 = (Double) df.parse(str, new ParsePosition(0));
+ logln(d1.toString());
+ if (d2.doubleValue() != d1.doubleValue())
+ errln("Bug 4095713 test failed, new double value : " + d2.doubleValue());
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * DecimalFormat.parse() fails when multiplier is not set to 1
+ */
+ public void Test4092561 ()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat();
+
+ String str = Long.toString(Long.MIN_VALUE);
+ logln("Long.MIN_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
+ df.setMultiplier(100);
+ Number num = df.parse(str, new ParsePosition(0));
+ if (num.doubleValue() != -9.223372036854776E16) {
+ errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue());
+ }
+
+ df.setMultiplier(-100);
+ num = df.parse(str, new ParsePosition(0));
+ if (num.doubleValue() != 9.223372036854776E16) {
+ errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue());
+ }
+
+ str = Long.toString(Long.MAX_VALUE);
+ logln("Long.MAX_VALUE : " + df.parse(str, new ParsePosition(0)).toString());
+
+ df.setMultiplier(100);
+ num = df.parse(str, new ParsePosition(0));
+ if (num.doubleValue() != 9.223372036854776E16) {
+ errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: 9.223372036854776E16, got: " + num.doubleValue());
+ }
+
+ df.setMultiplier(-100);
+ num = df.parse(str, new ParsePosition(0));
+ if (num.doubleValue() != -9.223372036854776E16) {
+ errln("Bug 4092561 test failed when multiplier is not set to 1. Expected: -9.223372036854776E16, got: " + num.doubleValue());
+ }
+
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * DecimalFormat: Negative format ignored.
+ */
+ public void Test4092480 ()
+ {
+ DecimalFormat dfFoo = new DecimalFormat("000");
+
+ try {
+ dfFoo.applyPattern("0000;-000");
+ if (!dfFoo.toPattern().equals("#0000"))
+ errln("dfFoo.toPattern : " + dfFoo.toPattern());
+ logln(dfFoo.format(42));
+ logln(dfFoo.format(-42));
+ dfFoo.applyPattern("000;-000");
+ if (!dfFoo.toPattern().equals("#000"))
+ errln("dfFoo.toPattern : " + dfFoo.toPattern());
+ logln(dfFoo.format(42));
+ logln(dfFoo.format(-42));
+
+ dfFoo.applyPattern("000;-0000");
+ if (!dfFoo.toPattern().equals("#000"))
+ errln("dfFoo.toPattern : " + dfFoo.toPattern());
+ logln(dfFoo.format(42));
+ logln(dfFoo.format(-42));
+
+ dfFoo.applyPattern("0000;-000");
+ if (!dfFoo.toPattern().equals("#0000"))
+ errln("dfFoo.toPattern : " + dfFoo.toPattern());
+ logln(dfFoo.format(42));
+ logln(dfFoo.format(-42));
+ } catch (Exception foo) {
+ errln("Message " + foo.getMessage());
+ }
+ }
+ /**
+ * NumberFormat.getCurrencyInstance() produces format that uses
+ * decimal separator instead of monetary decimal separator.
+ *
+ * Rewrote this test not to depend on the actual pattern. Pattern should
+ * never contain the monetary separator! Decimal separator in pattern is
+ * interpreted as monetary separator if currency symbol is seen!
+ */
+ public void Test4087244 () {
+ Locale de = new Locale("pt", "PT");
+ DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(de);
+ DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
+ sym.setMonetaryDecimalSeparator('$');
+ df.setDecimalFormatSymbols(sym);
+ char decSep = sym.getDecimalSeparator();
+ char monSep = sym.getMonetaryDecimalSeparator();
+ char zero = sym.getZeroDigit();
+ if (decSep == monSep) {
+ errln("ERROR in test: want decimal sep != monetary sep");
+ } else {
+ df.setMinimumIntegerDigits(1);
+ df.setMinimumFractionDigits(2);
+ String str = df.format(1.23);
+ String monStr = "1" + monSep + "23";
+ String decStr = "1" + decSep + "23";
+ if (str.indexOf(monStr) >= 0 && str.indexOf(decStr) < 0) {
+ logln("OK: 1.23 -> \"" + str + "\" contains \"" +
+ monStr + "\" and not \"" + decStr + '"');
+ } else {
+ errln("FAIL: 1.23 -> \"" + str + "\", should contain \"" +
+ monStr +
+ "\" and not \"" + decStr + '"');
+ }
+ }
+ }
+ /**
+ * Number format data rounding errors for locale FR
+ */
+ public void Test4070798 () {
+ NumberFormat formatter;
+ String tempString;
+ /* User error :
+ String expectedDefault = "-5\u00a0789,987";
+ String expectedCurrency = "5\u00a0789,98 F";
+ String expectedPercent = "-578\u00a0998%";
+ */
+ String expectedDefault = "-5\u00a0789,988";
+ String expectedCurrency = "5\u00a0789,99 \u20AC";
+ // changed for bug 6547501
+ String expectedPercent = "-578\u00a0999 %";
+
+ formatter = NumberFormat.getNumberInstance(Locale.FRANCE);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedDefault)) {
+ logln ("Bug 4070798 default test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedDefault +
+ " Received " + tempString );
+ }
+
+
+ formatter = NumberFormat.getCurrencyInstance(Locale.FRANCE);
+ tempString = formatter.format( 5789.9876 );
+
+ if (tempString.equals(expectedCurrency) ) {
+ logln ("Bug 4070798 currency test assed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedCurrency +
+ " Received " + tempString );
+ }
+
+
+ formatter = NumberFormat.getPercentInstance(Locale.FRANCE);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedPercent) ) {
+ logln ("Bug 4070798 percentage test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedPercent +
+ " Received " + tempString );
+ }
+ }
+ /**
+ * Data rounding errors for French (Canada) locale
+ */
+ public void Test4071005 () {
+
+ NumberFormat formatter;
+ String tempString;
+ /* user error :
+ String expectedDefault = "-5 789,987";
+ String expectedCurrency = "5 789,98 $";
+ String expectedPercent = "-578 998%";
+ */
+ String expectedDefault = "-5\u00a0789,988";
+ String expectedCurrency = "5\u00a0789,99 $";
+ // changed for bug 6547501
+ String expectedPercent = "-578\u00a0999 %";
+
+ formatter = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
+ tempString = formatter.format (-5789.9876);
+ if (tempString.equals(expectedDefault)) {
+ logln ("Bug 4071005 default test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedDefault +
+ " Received " + tempString );
+ }
+
+ formatter = NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
+ tempString = formatter.format( 5789.9876 ) ;
+
+ if (tempString.equals(expectedCurrency) ) {
+ logln ("Bug 4071005 currency test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedCurrency +
+ " Received " + tempString );
+ }
+ formatter = NumberFormat.getPercentInstance(Locale.CANADA_FRENCH);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedPercent) ) {
+ logln ("Bug 4071005 percentage test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedPercent +
+ " Received " + tempString );
+ }
+ }
+
+ /**
+ * Data rounding errors for German (Germany) locale
+ */
+ public void Test4071014 () {
+ NumberFormat formatter;
+ String tempString;
+ /* user error :
+ String expectedDefault = "-5.789,987";
+ String expectedCurrency = "5.789,98 DM";
+ String expectedPercent = "-578.998%";
+ */
+ String expectedDefault = "-5.789,988";
+ String expectedCurrency = "5.789,99 \u20AC";
+ String expectedPercent = "-578.999%";
+
+ formatter = NumberFormat.getNumberInstance(Locale.GERMANY);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedDefault)) {
+ logln ("Bug 4071014 default test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedDefault +
+ " Received " + tempString );
+ }
+
+ formatter = NumberFormat.getCurrencyInstance(Locale.GERMANY);
+ tempString = formatter.format( 5789.9876 ) ;
+
+ if (tempString.equals(expectedCurrency) ) {
+ logln ("Bug 4071014 currency test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedCurrency +
+ " Received " + tempString );
+ }
+
+ formatter = NumberFormat.getPercentInstance(Locale.GERMANY);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedPercent) ) {
+ logln ("Bug 4071014 percentage test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedPercent +
+ " Received " + tempString );
+ }
+
+ }
+ /**
+ * Data rounding errors for Italian locale number formats
+ */
+ public void Test4071859 () {
+ NumberFormat formatter;
+ String tempString;
+ /* user error :
+ String expectedDefault = "-5.789,987";
+ String expectedCurrency = "-L. 5.789,98";
+ String expectedPercent = "-578.998%";
+ */
+ String expectedDefault = "-5.789,988";
+ String expectedCurrency = "-\u20AC 5.789,99";
+ String expectedPercent = "-578.999%";
+
+ formatter = NumberFormat.getNumberInstance(Locale.ITALY);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedDefault)) {
+ logln ("Bug 4071859 default test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedDefault +
+ " Received " + tempString );
+ }
+
+ formatter = NumberFormat.getCurrencyInstance(Locale.ITALY);
+ tempString = formatter.format( -5789.9876 ) ;
+
+ if (tempString.equals(expectedCurrency) ) {
+ logln ("Bug 4071859 currency test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedCurrency +
+ " Received " + tempString );
+ }
+
+ formatter = NumberFormat.getPercentInstance(Locale.ITALY);
+ tempString = formatter.format (-5789.9876);
+
+ if (tempString.equals(expectedPercent) ) {
+ logln ("Bug 4071859 percentage test passed.");
+ } else {
+ errln("Failed:" +
+ " Expected " + expectedPercent +
+ " Received " + tempString );
+ }
+
+ }
+
+ /* bug 4071859
+ * Test rounding for nearest even.
+ */
+ public void Test4093610()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat("#0.#");
+
+ roundingTest(df, 12.15, "12.2"); // Rounding-up. Above tie (12.150..)
+ roundingTest(df, 12.25, "12.2"); // No round-up. Exact + half-even rule.
+ roundingTest(df, 12.45, "12.4"); // No round-up. Below tie (12.449..)
+ roundingTest(df, 12.450000001,"12.5"); // Rounding-up. Above tie.
+ roundingTest(df, 12.55, "12.6"); // Rounding-up. Above tie (12.550..)
+ roundingTest(df, 12.650000001,"12.7"); // Rounding-up. Above tie.
+ roundingTest(df, 12.75, "12.8"); // Rounding-up. Exact + half-even rule.
+ roundingTest(df, 12.750000001,"12.8"); // Rounding-up. Above tie.
+ roundingTest(df, 12.85, "12.8"); // No round-up. Below tie (12.849..)
+ roundingTest(df, 12.850000001,"12.9"); // Rounding-up. Above tie.
+ roundingTest(df, 12.950000001,"13"); // Rounding-up. Above tie.
+
+ Locale.setDefault(savedLocale);
+ }
+
+ void roundingTest(DecimalFormat df, double x, String expected)
+ {
+ String out = df.format(x);
+ logln("" + x + " formats with 1 fractional digits to " + out);
+ if (!out.equals(expected)) errln("FAIL: Expected " + expected);
+ }
+ /**
+ * Tests the setMaximumFractionDigits limit.
+ */
+ public void Test4098741()
+ {
+ try {
+ NumberFormat fmt = NumberFormat.getPercentInstance();
+ fmt.setMaximumFractionDigits(20);
+ logln(fmt.format(.001));
+ } catch (Exception foo) {
+ errln("Bug 4098471 failed with exception thrown : " + foo.getMessage());
+ }
+ }
+ /**
+ * Tests illegal pattern exception.
+ * Fix comment : HShih A31 Part1 will not be fixed and javadoc needs to be updated.
+ * Part2 has been fixed.
+ */
+ public void Test4074454()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ try {
+ DecimalFormat fmt = new DecimalFormat("#,#00.00;-#.#");
+ logln("Inconsistent negative pattern is fine.");
+ DecimalFormat newFmt = new DecimalFormat("#,#00.00 p''ieces;-#,#00.00 p''ieces");
+ String tempString = newFmt.format(3456.78);
+ if (!tempString.equals("3,456.78 p'ieces"))
+ errln("Failed! 3,456.78 p'ieces expected, but got : " + tempString);
+ } catch (Exception foo) {
+ errln("An exception was thrown for any inconsistent negative pattern.");
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * Tests all different comments.
+ * Response to some comments :
+ * [1] DecimalFormat.parse API documentation is more than just one line.
+ * This is not a reproducable doc error in 116 source code.
+ * [2] See updated javadoc.
+ * [3] Fixed.
+ * [4] NumberFormat.parse(String, ParsePosition) : If parsing fails,
+ * a null object will be returned. The unchanged parse position also
+ * reflects an error.
+ * NumberFormat.parse(String) : If parsing fails, an ParseException
+ * will be thrown.
+ * See updated javadoc for more details.
+ * [5] See updated javadoc.
+ * [6] See updated javadoc.
+ * [7] This is a correct behavior if the DateFormat object is linient.
+ * Otherwise, an IllegalArgumentException will be thrown when formatting
+ * "January 35". See GregorianCalendar class javadoc for more details.
+ */
+ public void Test4099404()
+ {
+ try {
+ DecimalFormat fmt = new DecimalFormat("000.0#0");
+ errln("Bug 4099404 failed applying illegal pattern \"000.0#0\"");
+ } catch (Exception foo) {
+ logln("Bug 4099404 pattern \"000.0#0\" passed");
+ }
+ try {
+ DecimalFormat fmt = new DecimalFormat("0#0.000");
+ errln("Bug 4099404 failed applying illegal pattern \"0#0.000\"");
+ } catch (Exception foo) {
+ logln("Bug 4099404 pattern \"0#0.000\" passed");
+ }
+ }
+ /**
+ * DecimalFormat.applyPattern doesn't set minimum integer digits
+ */
+ public void Test4101481()
+ {
+ DecimalFormat sdf = new DecimalFormat("#,##0");
+ if (sdf.getMinimumIntegerDigits() != 1)
+ errln("Minimum integer digits : " + sdf.getMinimumIntegerDigits());
+ }
+ /**
+ * Tests ParsePosition.setErrorPosition() and ParsePosition.getErrorPosition().
+ */
+ public void Test4052223()
+ {
+ try {
+ DecimalFormat fmt = new DecimalFormat("#,#00.00");
+ Number num = fmt.parse("abc3");
+ errln("Bug 4052223 failed : can't parse string \"a\". Got " + num);
+ } catch (ParseException foo) {
+ logln("Caught expected ParseException : " + foo.getMessage() + " at index : " + foo.getErrorOffset());
+ }
+ }
+ /**
+ * API tests for API addition request A9.
+ */
+ public void Test4061302()
+ {
+ DecimalFormatSymbols fmt = DecimalFormatSymbols.getInstance();
+ String currency = fmt.getCurrencySymbol();
+ String intlCurrency = fmt.getInternationalCurrencySymbol();
+ char monDecSeparator = fmt.getMonetaryDecimalSeparator();
+ if (currency.equals("") ||
+ intlCurrency.equals("") ||
+ monDecSeparator == 0) {
+ errln("getCurrencySymbols failed, got empty string.");
+ }
+ logln("Before set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
+ fmt.setCurrencySymbol("XYZ");
+ fmt.setInternationalCurrencySymbol("ABC");
+ fmt.setMonetaryDecimalSeparator('*');
+ currency = fmt.getCurrencySymbol();
+ intlCurrency = fmt.getInternationalCurrencySymbol();
+ monDecSeparator = fmt.getMonetaryDecimalSeparator();
+ if (!currency.equals("XYZ") ||
+ !intlCurrency.equals("ABC") ||
+ monDecSeparator != '*') {
+ errln("setCurrencySymbols failed.");
+ }
+ logln("After set ==> Currency : " + currency + " Intl Currency : " + intlCurrency + " Monetary Decimal Separator : " + monDecSeparator);
+ }
+ /**
+ * API tests for API addition request A23. FieldPosition.getBeginIndex and
+ * FieldPosition.getEndIndex.
+ */
+ public void Test4062486()
+ {
+ DecimalFormat fmt = new DecimalFormat("#,##0.00");
+ StringBuffer formatted = new StringBuffer();
+ FieldPosition field = new FieldPosition(0);
+ Double num = new Double(1234.5);
+ fmt.format(num, formatted, field);
+ if (field.getBeginIndex() != 0 && field.getEndIndex() != 5)
+ errln("Format 1234.5 failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
+ field.setBeginIndex(7);
+ field.setEndIndex(4);
+ if (field.getBeginIndex() != 7 && field.getEndIndex() != 4)
+ errln("Set begin/end field indexes failed. Begin index: " + field.getBeginIndex() + " End index: " + field.getEndIndex());
+ }
+
+ /**
+ * DecimalFormat.parse incorrectly works with a group separator.
+ */
+ public void Test4108738()
+ {
+
+ DecimalFormat df = new DecimalFormat("#,##0.###",
+ DecimalFormatSymbols.getInstance(java.util.Locale.US));
+ String text = "1.222,111";
+ Number num = df.parse(text,new ParsePosition(0));
+ if (!num.toString().equals("1.222"))
+ errln("\"" + text + "\" is parsed as " + num);
+ text = "1.222x111";
+ num = df.parse(text,new ParsePosition(0));
+ if (!num.toString().equals("1.222"))
+ errln("\"" + text + "\" is parsed as " + num);
+ }
+
+ /**
+ * DecimalFormat.format() incorrectly formats negative doubles.
+ */
+ public void Test4106658()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat(); // Corrected; see 4147706
+ double d1 = -0.0;
+ double d2 = -0.0001;
+ StringBuffer buffer = new StringBuffer();
+ logln("pattern: \"" + df.toPattern() + "\"");
+ df.format(d1, buffer, new FieldPosition(0));
+ if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+ errln(d1 + " is formatted as " + buffer);
+ }
+ buffer.setLength(0);
+ df.format(d2, buffer, new FieldPosition(0));
+ if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+ errln(d2 + " is formatted as " + buffer);
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * DecimalFormat.parse returns 0 if string parameter is incorrect.
+ */
+ public void Test4106662()
+ {
+ DecimalFormat df = new DecimalFormat();
+ String text = "x";
+ ParsePosition pos1 = new ParsePosition(0), pos2 = new ParsePosition(0);
+
+ logln("pattern: \"" + df.toPattern() + "\"");
+ Number num = df.parse(text, pos1);
+ if (num != null) {
+ errln("Test Failed: \"" + text + "\" is parsed as " + num);
+ }
+ df = null;
+ df = new DecimalFormat("$###.00");
+ num = df.parse("$", pos2);
+ if (num != null){
+ errln("Test Failed: \"$\" is parsed as " + num);
+ }
+ }
+
+ /**
+ * NumberFormat.parse doesn't return null
+ */
+ public void Test4114639()
+ {
+ NumberFormat format = NumberFormat.getInstance();
+ String text = "time 10:x";
+ ParsePosition pos = new ParsePosition(8);
+ Number result = format.parse(text, pos);
+ if (result != null) errln("Should return null but got : " + result); // Should be null; it isn't
+ }
+
+ /**
+ * DecimalFormat.format(long n) fails if n * multiplier > MAX_LONG.
+ */
+ public void Test4106664()
+ {
+ DecimalFormat df = new DecimalFormat();
+ long n = 1234567890123456L;
+ int m = 12345678;
+ BigInteger bigN = BigInteger.valueOf(n);
+ bigN = bigN.multiply(BigInteger.valueOf(m));
+ df.setMultiplier(m);
+ df.setGroupingUsed(false);
+ logln("formated: " +
+ df.format(n, new StringBuffer(), new FieldPosition(0)));
+ logln("expected: " + bigN.toString());
+ }
+ /**
+ * DecimalFormat.format incorrectly formats -0.0.
+ */
+ public void Test4106667()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat();
+ df.setPositivePrefix("+");
+ double d = -0.0;
+ logln("pattern: \"" + df.toPattern() + "\"");
+ StringBuffer buffer = new StringBuffer();
+ df.format(d, buffer, new FieldPosition(0));
+ if (!buffer.toString().equals("-0")) { // Corrected; see 4147706
+ errln(d + " is formatted as " + buffer);
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * DecimalFormat.setMaximumIntegerDigits() works incorrectly.
+ */
+ public void Test4110936()
+ {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumIntegerDigits(128);
+ logln("setMaximumIntegerDigits(128)");
+ if (nf.getMaximumIntegerDigits() != 128)
+ errln("getMaximumIntegerDigits() returns " +
+ nf.getMaximumIntegerDigits());
+ }
+
+ /**
+ * Locale data should use generic currency symbol
+ *
+ * 1) Make sure that all currency formats use the generic currency symbol.
+ * 2) Make sure we get the same results using the generic symbol or a
+ * hard-coded one.
+ */
+ public void Test4122840()
+ {
+ Locale[] locales = NumberFormat.getAvailableLocales();
+
+ for (int i = 0; i < locales.length; i++) {
+ ResourceBundle rb = LocaleData.getBundle("sun.text.resources.FormatData",
+ locales[i]);
+ //
+ // Get the currency pattern for this locale. We have to fish it
+ // out of the ResourceBundle directly, since DecimalFormat.toPattern
+ // will return the localized symbol, not \00a4
+ //
+ String[] numPatterns = (String[])rb.getObject("NumberPatterns");
+ String pattern = numPatterns[1];
+
+ if (pattern.indexOf("\u00A4") == -1 ) {
+ errln("Currency format for " + locales[i] +
+ " does not contain generic currency symbol:" +
+ pattern );
+ }
+
+ // Create a DecimalFormat using the pattern we got and format a number
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locales[i]);
+ DecimalFormat fmt1 = new DecimalFormat(pattern, symbols);
+
+ String result1 = fmt1.format(1.111);
+
+ //
+ // Now substitute in the locale's currency symbol and create another
+ // pattern. Replace the decimal separator with the monetary separator.
+ //
+ char decSep = symbols.getDecimalSeparator();
+ char monSep = symbols.getMonetaryDecimalSeparator();
+ StringBuffer buf = new StringBuffer(pattern);
+ for (int j = 0; j < buf.length(); j++) {
+ if (buf.charAt(j) == '\u00a4') {
+ String cur = "'" + symbols.getCurrencySymbol() + "'";
+ buf.replace(j, j+1, cur);
+ j += cur.length() - 1;
+ }
+ }
+ symbols.setDecimalSeparator(monSep);
+ DecimalFormat fmt2 = new DecimalFormat(buf.toString(), symbols);
+
+ String result2 = fmt2.format(1.111);
+
+ if (!result1.equals(result2)) {
+ errln("Results for " + locales[i] + " differ: " +
+ result1 + " vs " + result2);
+ }
+ }
+ }
+
+ /**
+ * DecimalFormat.format() delivers wrong string.
+ */
+ public void Test4125885()
+ {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ double rate = 12.34;
+ DecimalFormat formatDec = new DecimalFormat ("000.00");
+ logln("toPattern: " + formatDec.toPattern());
+ String rateString= formatDec.format(rate);
+ if (!rateString.equals("012.34"))
+ errln("result : " + rateString + " expected : 012.34");
+ rate = 0.1234;
+ formatDec = null;
+ formatDec = new DecimalFormat ("+000.00%;-000.00%");
+ logln("toPattern: " + formatDec.toPattern());
+ rateString= formatDec.format(rate);
+ if (!rateString.equals("+012.34%"))
+ errln("result : " + rateString + " expected : +012.34%");
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ **
+ * DecimalFormat produces extra zeros when formatting numbers.
+ */
+ public void Test4134034() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat nf = new DecimalFormat("##,###,###.00");
+
+ String f = nf.format(9.02);
+ if (f.equals("9.02")) logln(f + " ok"); else errln("9.02 -> " + f + "; want 9.02");
+
+ f = nf.format(0);
+ if (f.equals(".00")) logln(f + " ok"); else errln("0 -> " + f + "; want .00");
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * CANNOT REPRODUCE - This bug could not be reproduced. It may be
+ * a duplicate of 4134034.
+ *
+ * JDK 1.1.6 Bug, did NOT occur in 1.1.5
+ * Possibly related to bug 4125885.
+ *
+ * This class demonstrates a regression in version 1.1.6
+ * of DecimalFormat class.
+ *
+ * 1.1.6 Results
+ * Value 1.2 Format #.00 Result '01.20' !!!wrong
+ * Value 1.2 Format 0.00 Result '001.20' !!!wrong
+ * Value 1.2 Format 00.00 Result '0001.20' !!!wrong
+ * Value 1.2 Format #0.0# Result '1.2'
+ * Value 1.2 Format #0.00 Result '001.20' !!!wrong
+ *
+ * 1.1.5 Results
+ * Value 1.2 Format #.00 Result '1.20'
+ * Value 1.2 Format 0.00 Result '1.20'
+ * Value 1.2 Format 00.00 Result '01.20'
+ * Value 1.2 Format #0.0# Result '1.2'
+ * Value 1.2 Format #0.00 Result '1.20'
+ */
+ public void Test4134300() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ String[] DATA = {
+ // Pattern Expected string
+ "#.00", "1.20",
+ "0.00", "1.20",
+ "00.00", "01.20",
+ "#0.0#", "1.2",
+ "#0.00", "1.20",
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ String result = new DecimalFormat(DATA[i]).format(1.2);
+ if (!result.equals(DATA[i+1])) {
+ errln("Fail: 1.2 x " + DATA[i] + " = " + result +
+ "; want " + DATA[i+1]);
+ }
+ else {
+ logln("Ok: 1.2 x " + DATA[i] + " = " + result);
+ }
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * Empty pattern produces double negative prefix.
+ */
+ public void Test4140009() {
+ for (int i=0; i<2; ++i) {
+ DecimalFormat f = null;
+ switch (i) {
+ case 0:
+ f = new DecimalFormat("",
+ DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+ break;
+ case 1:
+ f = new DecimalFormat("#.#",
+ DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+ f.applyPattern("");
+ break;
+ }
+ String s = f.format(123.456);
+ if (!s.equals("123.456"))
+ errln("Fail: Format empty pattern x 123.456 => " + s);
+ s = f.format(-123.456);
+ if (!s.equals("-123.456"))
+ errln("Fail: Format empty pattern x -123.456 => " + s);
+ }
+ }
+
+ /**
+ * BigDecimal numbers get their fractions truncated by NumberFormat.
+ */
+ public void Test4141750() {
+ try {
+ String str = "12345.67";
+ BigDecimal bd = new BigDecimal(str);
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ String sd = nf.format(bd);
+ if (!sd.endsWith("67")) {
+ errln("Fail: " + str + " x format -> " + sd);
+ }
+ }
+ catch (Exception e) {
+ errln(e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * DecimalFormat toPattern() doesn't quote special characters or handle
+ * single quotes.
+ */
+ public void Test4145457() {
+ try {
+ DecimalFormat nf = (DecimalFormat)NumberFormat.getInstance();
+ DecimalFormatSymbols sym = nf.getDecimalFormatSymbols();
+ sym.setDecimalSeparator('\'');
+ nf.setDecimalFormatSymbols(sym);
+ double pi = 3.14159;
+
+ String[] PATS = { "#.00 'num''ber'", "''#.00''" };
+
+ for (int i=0; i<PATS.length; ++i) {
+ nf.applyPattern(PATS[i]);
+ String out = nf.format(pi);
+ String pat = nf.toPattern();
+ double val = nf.parse(out).doubleValue();
+
+ nf.applyPattern(pat);
+ String out2 = nf.format(pi);
+ String pat2 = nf.toPattern();
+ double val2 = nf.parse(out2).doubleValue();
+
+ if (!pat.equals(pat2))
+ errln("Fail with \"" + PATS[i] + "\": Patterns should concur, \"" +
+ pat + "\" vs. \"" + pat2 + "\"");
+ else
+ logln("Ok \"" + PATS[i] + "\" toPattern() -> \"" + pat + '"');
+
+ if (val == val2 && out.equals(out2)) {
+ logln("Ok " + pi + " x \"" + PATS[i] + "\" -> \"" +
+ out + "\" -> " + val + " -> \"" +
+ out2 + "\" -> " + val2);
+ }
+ else {
+ errln("Fail " + pi + " x \"" + PATS[i] + "\" -> \"" +
+ out + "\" -> " + val + " -> \"" +
+ out2 + "\" -> " + val2);
+ }
+ }
+ }
+ catch (ParseException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * DecimalFormat.applyPattern() sets minimum integer digits incorrectly.
+ * CANNOT REPRODUCE
+ * This bug is a duplicate of 4139344, which is a duplicate of 4134300
+ */
+ public void Test4147295() {
+ DecimalFormat sdf = new DecimalFormat();
+ String pattern = "#,###";
+ logln("Applying pattern \"" + pattern + "\"");
+ sdf.applyPattern(pattern);
+ int minIntDig = sdf.getMinimumIntegerDigits();
+ if (minIntDig != 0) {
+ errln("Test failed");
+ errln(" Minimum integer digits : " + minIntDig);
+ errln(" new pattern: " + sdf.toPattern());
+ } else {
+ logln("Test passed");
+ logln(" Minimum integer digits : " + minIntDig);
+ }
+ }
+
+ /**
+ * DecimalFormat formats -0.0 as +0.0
+ * See also older related bug 4106658, 4106667
+ */
+ public void Test4147706() {
+ DecimalFormat df = new DecimalFormat("#,##0.0##");
+ df.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ENGLISH));
+ double d1 = -0.0;
+ double d2 = -0.0001;
+ StringBuffer f1 = df.format(d1, new StringBuffer(), new FieldPosition(0));
+ StringBuffer f2 = df.format(d2, new StringBuffer(), new FieldPosition(0));
+ if (!f1.toString().equals("-0.0")) {
+ errln(d1 + " x \"" + df.toPattern() + "\" is formatted as \"" + f1 + '"');
+ }
+ if (!f2.toString().equals("-0.0")) {
+ errln(d2 + " x \"" + df.toPattern() + "\" is formatted as \"" + f2 + '"');
+ }
+ }
+
+ /**
+ * NumberFormat cannot format Double.MAX_VALUE
+ */
+ public void Test4162198() {
+ double dbl = Double.MAX_VALUE;
+ NumberFormat f = NumberFormat.getInstance();
+ f.setMaximumFractionDigits(Integer.MAX_VALUE);
+ f.setMaximumIntegerDigits(Integer.MAX_VALUE);
+ String s = f.format(dbl);
+ logln("The number " + dbl + " formatted to " + s);
+ Number n = null;
+ try {
+ n = f.parse(s);
+ } catch (java.text.ParseException e) {
+ errln("Caught a ParseException:");
+ e.printStackTrace();
+ }
+ logln("The string " + s + " parsed as " + n);
+ if (n.doubleValue() != dbl) {
+ errln("Round trip failure");
+ }
+ }
+
+ /**
+ * NumberFormat does not parse negative zero.
+ */
+ public void Test4162852() throws ParseException {
+ for (int i=0; i<2; ++i) {
+ NumberFormat f = (i == 0) ? NumberFormat.getInstance()
+ : NumberFormat.getPercentInstance();
+ double d = -0.0;
+ String s = f.format(d);
+ double e = f.parse(s).doubleValue();
+ logln("" +
+ d + " -> " +
+ '"' + s + '"' + " -> " +
+ e);
+ if (e != 0.0 || 1.0/e > 0.0) {
+ logln("Failed to parse negative zero");
+ }
+ }
+ }
+
+ /**
+ * NumberFormat truncates data
+ */
+ public void Test4167494() throws Exception {
+ NumberFormat fmt = NumberFormat.getInstance(Locale.US);
+
+ double a = Double.MAX_VALUE;
+ String s = fmt.format(a);
+ double b = fmt.parse(s).doubleValue();
+ boolean match = a == b;
+ if (match) {
+ logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
+ } else {
+ errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
+ }
+
+ // We don't test Double.MIN_VALUE because the locale data for the US
+ // currently doesn't specify enough digits to display Double.MIN_VALUE.
+ // This is correct for now; however, we leave this here as a reminder
+ // in case we want to address this later.
+ if (false) {
+ a = Double.MIN_VALUE;
+ s = fmt.format(a);
+ b = fmt.parse(s).doubleValue();
+ match = a == b;
+ if (match) {
+ logln("" + a + " -> \"" + s + "\" -> " + b + " ok");
+ } else {
+ errln("" + a + " -> \"" + s + "\" -> " + b + " FAIL");
+ }
+ }
+ }
+
+ /**
+ * DecimalFormat.parse() fails when ParseIntegerOnly set to true
+ */
+ public void Test4170798() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat df = new DecimalFormat();
+ df.setParseIntegerOnly(true);
+ Number n = df.parse("-0.0", new ParsePosition(0));
+ if (!(n instanceof Long || n instanceof Integer)
+ || n.intValue() != 0) {
+ errln("FAIL: parse(\"-0.0\") returns " +
+ n + " (" + n.getClass().getName() + ')');
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * toPattern only puts the first grouping separator in.
+ */
+ public void Test4176114() {
+ String[] DATA = {
+ "00", "#00",
+ "000", "#000", // No grouping
+ "#000", "#000", // No grouping
+ "#,##0", "#,##0",
+ "#,000", "#,000",
+ "0,000", "#0,000",
+ "00,000", "#00,000",
+ "000,000", "#,000,000",
+ "0,000,000,000,000.0000", "#0,000,000,000,000.0000", // Reported
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ DecimalFormat df = new DecimalFormat(DATA[i]);
+ String s = df.toPattern();
+ if (!s.equals(DATA[i+1])) {
+ errln("FAIL: " + DATA[i] + " -> " + s + ", want " + DATA[i+1]);
+ }
+ }
+ }
+
+ /**
+ * DecimalFormat is incorrectly rounding numbers like 1.2501 to 1.2
+ */
+ public void Test4179818() {
+ String DATA[] = {
+ // Input Pattern Expected output
+ "1.2511", "#.#", "1.3",
+ "1.2501", "#.#", "1.3",
+ "0.9999", "#", "1",
+ };
+ DecimalFormat fmt = new DecimalFormat("#",
+ DecimalFormatSymbols.getInstance(Locale.US));
+ for (int i=0; i<DATA.length; i+=3) {
+ double in = Double.valueOf(DATA[i]).doubleValue();
+ String pat = DATA[i+1];
+ String exp = DATA[i+2];
+ fmt.applyPattern(pat);
+ String out = fmt.format(in);
+ if (out.equals(exp)) {
+ logln("Ok: " + in + " x " + pat + " = " + out);
+ } else {
+ errln("FAIL: " + in + " x " + pat + " = " + out +
+ ", expected " + exp);
+ }
+ }
+ }
+
+ public void Test4185761() throws IOException, ClassNotFoundException {
+ /* Code used to write out the initial files, which are
+ * then edited manually:
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ nf.setMinimumIntegerDigits(0x111); // Keep under 309
+ nf.setMaximumIntegerDigits(0x112); // Keep under 309
+ nf.setMinimumFractionDigits(0x113); // Keep under 340
+ nf.setMaximumFractionDigits(0x114); // Keep under 340
+ FileOutputStream ostream =
+ new FileOutputStream("NumberFormat4185761");
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(nf);
+ ostream.close();
+ */
+
+ // File minint maxint minfrac maxfrac
+ // NumberFormat4185761a 0x122 0x121 0x124 0x123
+ // NumberFormat4185761b 0x311 0x312 0x313 0x314
+ // File a is bad because the mins are smaller than the maxes.
+ // File b is bad because the values are too big for a DecimalFormat.
+ // These files have a sufix ".ser.txt".
+
+ InputStream istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761a.ser.txt");
+ ObjectInputStream p = new ObjectInputStream(istream);
+ try {
+ NumberFormat nf = (NumberFormat) p.readObject();
+ errln("FAIL: Deserialized bogus NumberFormat int:" +
+ nf.getMinimumIntegerDigits() + ".." +
+ nf.getMaximumIntegerDigits() + " frac:" +
+ nf.getMinimumFractionDigits() + ".." +
+ nf.getMaximumFractionDigits());
+ } catch (InvalidObjectException e) {
+ logln("Ok: " + e.getMessage());
+ }
+ istream.close();
+
+ istream = HexDumpReader.getStreamFromHexDump("NumberFormat4185761b.ser.txt");
+ p = new ObjectInputStream(istream);
+ try {
+ NumberFormat nf = (NumberFormat) p.readObject();
+ errln("FAIL: Deserialized bogus DecimalFormat int:" +
+ nf.getMinimumIntegerDigits() + ".." +
+ nf.getMaximumIntegerDigits() + " frac:" +
+ nf.getMinimumFractionDigits() + ".." +
+ nf.getMaximumFractionDigits());
+ } catch (InvalidObjectException e) {
+ logln("Ok: " + e.getMessage());
+ }
+ istream.close();
+ }
+
+
+ /**
+ * Some DecimalFormatSymbols changes are not picked up by DecimalFormat.
+ * This includes the minus sign, currency symbol, international currency
+ * symbol, percent, and permille. This is filed as bugs 4212072 and
+ * 4212073.
+ */
+ public void Test4212072() throws IOException, ClassNotFoundException {
+ DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+ DecimalFormat fmt = new DecimalFormat("#", sym);
+
+ sym.setMinusSign('^');
+ fmt.setDecimalFormatSymbols(sym);
+ if (!fmt.format(-1).equals("^1")) {
+ errln("FAIL: -1 x (minus=^) -> " + fmt.format(-1) +
+ ", exp ^1");
+ }
+ if (!fmt.getNegativePrefix().equals("^")) {
+ errln("FAIL: (minus=^).getNegativePrefix -> " +
+ fmt.getNegativePrefix() + ", exp ^");
+ }
+ sym.setMinusSign('-');
+
+ fmt.applyPattern("#%");
+ sym.setPercent('^');
+ fmt.setDecimalFormatSymbols(sym);
+ if (!fmt.format(0.25).equals("25^")) {
+ errln("FAIL: 0.25 x (percent=^) -> " + fmt.format(0.25) +
+ ", exp 25^");
+ }
+ if (!fmt.getPositiveSuffix().equals("^")) {
+ errln("FAIL: (percent=^).getPositiveSuffix -> " +
+ fmt.getPositiveSuffix() + ", exp ^");
+ }
+ sym.setPercent('%');
+
+ fmt.applyPattern("#\u2030");
+ sym.setPerMill('^');
+ fmt.setDecimalFormatSymbols(sym);
+ if (!fmt.format(0.25).equals("250^")) {
+ errln("FAIL: 0.25 x (permill=^) -> " + fmt.format(0.25) +
+ ", exp 250^");
+ }
+ if (!fmt.getPositiveSuffix().equals("^")) {
+ errln("FAIL: (permill=^).getPositiveSuffix -> " +
+ fmt.getPositiveSuffix() + ", exp ^");
+ }
+ sym.setPerMill('\u2030');
+
+ fmt.applyPattern("\u00A4#.00");
+ sym.setCurrencySymbol("usd");
+ fmt.setDecimalFormatSymbols(sym);
+ if (!fmt.format(12.5).equals("usd12.50")) {
+ errln("FAIL: 12.5 x (currency=usd) -> " + fmt.format(12.5) +
+ ", exp usd12.50");
+ }
+ if (!fmt.getPositivePrefix().equals("usd")) {
+ errln("FAIL: (currency=usd).getPositivePrefix -> " +
+ fmt.getPositivePrefix() + ", exp usd");
+ }
+ sym.setCurrencySymbol("$");
+
+ fmt.applyPattern("\u00A4\u00A4#.00");
+ sym.setInternationalCurrencySymbol("DOL");
+ fmt.setDecimalFormatSymbols(sym);
+ if (!fmt.format(12.5).equals("DOL12.50")) {
+ errln("FAIL: 12.5 x (intlcurrency=DOL) -> " + fmt.format(12.5) +
+ ", exp DOL12.50");
+ }
+ if (!fmt.getPositivePrefix().equals("DOL")) {
+ errln("FAIL: (intlcurrency=DOL).getPositivePrefix -> " +
+ fmt.getPositivePrefix() + ", exp DOL");
+ }
+ sym.setInternationalCurrencySymbol("USD");
+
+ // Since the pattern logic has changed, make sure that patterns round
+ // trip properly. Test stream in/out integrity too.
+ Locale[] avail = NumberFormat.getAvailableLocales();
+ for (int i=0; i<avail.length; ++i) {
+ for (int j=0; j<3; ++j) {
+ NumberFormat nf;
+ switch (j) {
+ case 0:
+ nf = NumberFormat.getInstance(avail[i]);
+ break;
+ case 1:
+ nf = NumberFormat.getCurrencyInstance(avail[i]);
+ break;
+ default:
+ nf = NumberFormat.getPercentInstance(avail[i]);
+ break;
+ }
+ DecimalFormat df = (DecimalFormat) nf;
+
+ // Test toPattern/applyPattern round trip
+ String pat = df.toPattern();
+ DecimalFormatSymbols symb = DecimalFormatSymbols.getInstance(avail[i]);
+ DecimalFormat f2 = new DecimalFormat(pat, symb);
+ if (!df.equals(f2)) {
+ errln("FAIL: " + avail[i] + " -> \"" + pat +
+ "\" -> \"" + f2.toPattern() + '"');
+ }
+
+ // Test toLocalizedPattern/applyLocalizedPattern round trip
+ pat = df.toLocalizedPattern();
+ f2.applyLocalizedPattern(pat);
+ if (!df.equals(f2)) {
+ errln("FAIL: " + avail[i] + " -> localized \"" + pat +
+ "\" -> \"" + f2.toPattern() + '"');
+ }
+
+ // Test writeObject/readObject round trip
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(df);
+ oos.flush();
+ baos.close();
+ byte[] bytes = baos.toByteArray();
+ ObjectInputStream ois =
+ new ObjectInputStream(new ByteArrayInputStream(bytes));
+ f2 = (DecimalFormat) ois.readObject();
+ if (!df.equals(f2)) {
+ errln("FAIL: Stream in/out " + avail[i] + " -> \"" + pat +
+ "\" -> " +
+ (f2 != null ? ("\""+f2.toPattern()+'"') : "null"));
+ }
+
+ }
+ }
+ }
+
+ /**
+ * DecimalFormat.parse() fails for mulipliers 2^n.
+ */
+ public void Test4216742() throws ParseException {
+ DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance(Locale.US);
+ long[] DATA = { Long.MIN_VALUE, Long.MAX_VALUE, -100000000L, 100000000L};
+ for (int i=0; i<DATA.length; ++i) {
+ String str = Long.toString(DATA[i]);
+ for (int m = 1; m <= 100; m++) {
+ fmt.setMultiplier(m);
+ long n = ((Number) fmt.parse(str)).longValue();
+ if (n > 0 != DATA[i] > 0) {
+ errln("\"" + str + "\" parse(x " + fmt.getMultiplier() +
+ ") => " + n);
+ }
+ }
+ }
+ }
+
+ /**
+ * DecimalFormat formats 1.001 to "1.00" instead of "1" with 2 fraction
+ * digits.
+ */
+ public void Test4217661() {
+ Object[] DATA = {
+ new Double(0.001), "0",
+ new Double(1.001), "1",
+ new Double(0.006), "0.01",
+ new Double(1.006), "1.01",
+ };
+ NumberFormat fmt = NumberFormat.getInstance(Locale.US);
+ fmt.setMaximumFractionDigits(2);
+ for (int i=0; i<DATA.length; i+=2) {
+ String s = fmt.format(((Double) DATA[i]).doubleValue());
+ if (!s.equals(DATA[i+1])) {
+ errln("FAIL: Got " + s + ", exp " + DATA[i+1]);
+ }
+ }
+ }
+
+ /**
+ * 4243011: Formatting .5 rounds to "1" instead of "0"
+ */
+ public void Test4243011() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ double DATA[] = {0.5, 1.5, 2.5, 3.5, 4.5};
+ String EXPECTED[] = {"0.", "2.", "2.", "4.", "4."};
+
+ DecimalFormat format = new DecimalFormat("0.");
+ for (int i = 0; i < DATA.length; i++) {
+ String result = format.format(DATA[i]);
+ if (result.equals(EXPECTED[i])) {
+ logln("OK: got " + result);
+ } else {
+ errln("FAIL: got " + result);
+ }
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * 4243108: format(0.0) gives "0.1" if preceded by parse("99.99")
+ */
+ public void Test4243108() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ DecimalFormat f = new DecimalFormat("#.#");
+ String result = f.format(0.0);
+ if (result.equals("0")) {
+ logln("OK: got " + result);
+ } else {
+ errln("FAIL: got " + result);
+ }
+ try {
+ double dResult = f.parse("99.99").doubleValue();
+ if (dResult == 99.99) {
+ logln("OK: got " + dResult);
+ } else {
+ errln("FAIL: got " + dResult);
+ }
+ } catch (ParseException e) {
+ errln("Caught a ParseException:");
+ e.printStackTrace();
+ }
+ result = f.format(0.0);
+ if (result.equals("0")) {
+ logln("OK: got " + result);
+ } else {
+ errln("FAIL: got " + result);
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * 4330377: DecimalFormat engineering notation gives incorrect results
+ */
+ public void test4330377() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ double[] input = {5000.0, 500.0, 50.0, 5.0, 0.5, 0.05, 0.005, 0.0005,
+ 5050.0, 505.0, 50.5, 5.05, 0.505, 0.0505, 0.00505, 0.000505};
+ String[] pattern = {"000.#E0", "##0.#E0", "#00.#E0"};
+ String[][] expected = {
+ // it's questionable whether "#00.#E0" should result in post-decimal
+ // zeroes, i.e., whether "5.0E3", "5.0E0", "5.0E-3" are really good
+ {"500E1", "5E3", "5.0E3"},
+ {"500E0", "500E0", "500E0"},
+ {"500E-1", "50E0", "50E0"},
+ {"500E-2", "5E0", "5.0E0"},
+ {"500E-3", "500E-3", "500E-3"},
+ {"500E-4", "50E-3", "50E-3"},
+ {"500E-5", "5E-3", "5.0E-3"},
+ {"500E-6", "500E-6", "500E-6"},
+ {"505E1", "5.05E3", "5.05E3"},
+ {"505E0", "505E0", "505E0"},
+ {"505E-1", "50.5E0", "50.5E0"},
+ {"505E-2", "5.05E0", "5.05E0"},
+ {"505E-3", "505E-3", "505E-3"},
+ {"505E-4", "50.5E-3", "50.5E-3"},
+ {"505E-5", "5.05E-3", "5.05E-3"},
+ {"505E-6", "505E-6", "505E-6"}
+ };
+ for (int i = 0; i < input.length; i++) {
+ for (int j = 0; j < pattern.length; j++) {
+ DecimalFormat format = new DecimalFormat(pattern[j]);
+ String result = format.format(input[i]);
+ if (!result.equals(expected[i][j])) {
+ errln("FAIL: input: " + input[i] +
+ ", pattern: " + pattern[j] +
+ ", expected: " + expected[i][j] +
+ ", got: " + result);
+ }
+ }
+ }
+ Locale.setDefault(savedLocale);
+ }
+
+ /**
+ * 4233840: NumberFormat does not round correctly
+ */
+ public void test4233840() {
+ float f = 0.0099f;
+
+ NumberFormat nf = new DecimalFormat("0.##", DecimalFormatSymbols.getInstance(Locale.US));
+ nf.setMinimumFractionDigits(2);
+
+ String result = nf.format(f);
+
+ if (!result.equals("0.01")) {
+ errln("FAIL: input: " + f + ", expected: 0.01, got: " + result);
+ }
+ }
+
+ /**
+ * 4241880: Decimal format doesnt round a double properly when the number is less than 1
+ */
+ public void test4241880() {
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ double[] input = {
+ .019, .009, .015, .016, .014,
+ .004, .005, .006, .007, .008,
+ .5, 1.5, .25, .55, .045,
+ .035, .0005, .0015,
+ };
+ String[] pattern = {
+ "##0%", "##0%", "##0%", "##0%", "##0%",
+ "##0%", "##0%", "##0%", "##0%", "##0%",
+ "#,##0", "#,##0", "#,##0.0", "#,##0.0", "#,##0.00",
+ "#,##0.00", "#,##0.000", "#,##0.000",
+ };
+ String[] expected = {
+ "2%", "1%", "2%", "2%", "1%",
+ "0%", "0%", "1%", "1%", "1%",
+ "0", "2", "0.2", "0.6", "0.04",
+ "0.04", "0.000", "0.002",
+ };
+ for (int i = 0; i < input.length; i++) {
+ DecimalFormat format = new DecimalFormat(pattern[i]);
+ String result = format.format(input[i]);
+ if (!result.equals(expected[i])) {
+ errln("FAIL: input: " + input[i] +
+ ", pattern: " + pattern[i] +
+ ", expected: " + expected[i] +
+ ", got: " + result);
+ }
+ }
+ Locale.setDefault(savedLocale);
+ }
+}
+
+class myformat implements Serializable
+{
+ DateFormat _dateFormat = DateFormat.getDateInstance();
+
+ public String Now()
+ {
+ GregorianCalendar calendar = new GregorianCalendar();
+ Date t = calendar.getTime();
+ String nowStr = _dateFormat.format(t);
+ return nowStr;
+ }
+}
+
+class MyNumberFormatTest extends NumberFormat {
+ public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
+ return new StringBuffer("");
+ }
+ public StringBuffer format(long number,StringBuffer toAppendTo, FieldPosition pos) {
+ return new StringBuffer("");
+ }
+ public Number parse(String text, ParsePosition parsePosition) {
+ return new Integer(0);
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/NumberRoundTrip.java b/test/java/text/Format/NumberFormat/NumberRoundTrip.java
new file mode 100644
index 0000000000..8d0b586bea
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberRoundTrip.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @summary round trip test NumberFormat
+ * @library /java/text/testlib
+ * @key randomness
+ */
+
+import java.text.*;
+import java.util.*;
+
+/**
+ * This class tests the round-trip behavior of NumberFormat, DecimalFormat, and DigitList.
+ * Round-trip behavior is tested by taking a numeric value and formatting it, then
+ * parsing the resulting string, and comparing this result with the original value.
+ * Two tests are applied: String preservation, and numeric preservation. String
+ * preservation is exact; numeric preservation is not. However, numeric preservation
+ * should extend to the few least-significant bits.
+ * //bug472
+ */
+public class NumberRoundTrip extends IntlTest {
+ static final boolean STRING_COMPARE = true;
+ static final boolean EXACT_NUMERIC_COMPARE = false;
+ static final double MAX_ERROR = 1e-14;
+ static boolean DEBUG = false;
+ static double max_numeric_error = 0;
+ static double min_numeric_error = 1;
+
+ String localeName, formatName;
+
+ public static void main(String[] args) throws Exception {
+ if (args.length > 0 && args[0].equals("-debug")) {
+ DEBUG = true;
+ String[] newargs = new String[args.length - 1];
+ System.arraycopy(args, 1, newargs, 0, newargs.length);
+ args = newargs;
+ }
+ new NumberRoundTrip().run(args);
+ }
+
+ public void TestNumberFormatRoundTrip() {
+ logln("Default Locale");
+ localeName = "Default Locale";
+ formatName = "getInstance";
+ doTest(NumberFormat.getInstance());
+ formatName = "getNumberInstance";
+ doTest(NumberFormat.getNumberInstance());
+ formatName = "getCurrencyInstance";
+ doTest(NumberFormat.getCurrencyInstance());
+ formatName = "getPercentInstance";
+ doTest(NumberFormat.getPercentInstance());
+
+ Locale[] loc = NumberFormat.getAvailableLocales();
+ for (int i=0; i<loc.length; ++i) {
+ logln(loc[i].getDisplayName());
+ localeName = loc[i].toString();
+ formatName = "getInstance";
+ doTest(NumberFormat.getInstance(loc[i]));
+ formatName = "getNumberInstance";
+ doTest(NumberFormat.getNumberInstance(loc[i]));
+ formatName = "getCurrencyInstance";
+ doTest(NumberFormat.getCurrencyInstance(loc[i]));
+ formatName = "getPercentInstance";
+ doTest(NumberFormat.getPercentInstance(loc[i]));
+ }
+
+ logln("Numeric error " +
+ min_numeric_error + " to " +
+ max_numeric_error);
+ }
+
+ public void doTest(NumberFormat fmt) {
+ doTest(fmt, Double.NaN);
+ doTest(fmt, Double.POSITIVE_INFINITY);
+ doTest(fmt, Double.NEGATIVE_INFINITY);
+
+ doTest(fmt, 500);
+ doTest(fmt, 0);
+ doTest(fmt, 5555555555555555L);
+ doTest(fmt, 55555555555555555L);
+ doTest(fmt, 9223372036854775807L);
+ doTest(fmt, 9223372036854775808.0);
+ doTest(fmt, -9223372036854775808L);
+ doTest(fmt, -9223372036854775809.0);
+
+ for (int i=0; i<2; ++i) {
+ doTest(fmt, randomDouble(1));
+ doTest(fmt, randomDouble(10000));
+ doTest(fmt, Math.floor(randomDouble(10000)));
+ doTest(fmt, randomDouble(1e50));
+ doTest(fmt, randomDouble(1e-50));
+ doTest(fmt, randomDouble(1e100));
+ // The use of double d such that isInfinite(100d) causes the
+ // numeric test to fail with percent formats (bug 4266589).
+ // Largest double s.t. 100d < Inf: d=1.7976931348623156E306
+ doTest(fmt, randomDouble(1e306));
+ doTest(fmt, randomDouble(1e-323));
+ doTest(fmt, randomDouble(1e-100));
+ }
+ }
+
+ /**
+ * Return a random value from -range..+range.
+ */
+ public double randomDouble(double range) {
+ double a = Math.random();
+ return (2.0 * range * a) - range;
+ }
+
+ public void doTest(NumberFormat fmt, double value) {
+ doTest(fmt, new Double(value));
+ }
+
+ public void doTest(NumberFormat fmt, long value) {
+ doTest(fmt, new Long(value));
+ }
+
+ static double proportionalError(Number a, Number b) {
+ double aa = a.doubleValue(), bb = b.doubleValue();
+ double error = aa - bb;
+ if (aa != 0 && bb != 0) error /= aa;
+ return Math.abs(error);
+ }
+
+ public void doTest(NumberFormat fmt, Number value) {
+ fmt.setMaximumFractionDigits(Integer.MAX_VALUE);
+ String s = fmt.format(value), s2 = null;
+ Number n = null;
+ String err = "";
+ try {
+ if (DEBUG) logln(" " + value + " F> " + escape(s));
+ n = fmt.parse(s);
+ if (DEBUG) logln(" " + escape(s) + " P> " + n);
+ s2 = fmt.format(n);
+ if (DEBUG) logln(" " + n + " F> " + escape(s2));
+
+ if (STRING_COMPARE) {
+ if (!s.equals(s2)) {
+ if (fmt instanceof DecimalFormat) {
+ logln("Text mismatch: expected: " + s + ", got: " + s2 + " --- Try BigDecimal parsing.");
+ ((DecimalFormat)fmt).setParseBigDecimal(true);
+ n = fmt.parse(s);
+ if (DEBUG) logln(" " + escape(s) + " P> " + n);
+ s2 = fmt.format(n);
+ if (DEBUG) logln(" " + n + " F> " + escape(s2));
+ ((DecimalFormat)fmt).setParseBigDecimal(false);
+
+ if (!s.equals(s2)) {
+ err = "STRING ERROR(DecimalFormat): ";
+ }
+ } else {
+ err = "STRING ERROR(NumberFormat): ";
+ }
+ }
+ }
+
+ if (EXACT_NUMERIC_COMPARE) {
+ if (value.doubleValue() != n.doubleValue()) {
+ err += "NUMERIC ERROR: ";
+ }
+ } else {
+ // Compute proportional error
+ double error = proportionalError(value, n);
+
+ if (error > MAX_ERROR) {
+ err += "NUMERIC ERROR " + error + ": ";
+ }
+
+ if (error > max_numeric_error) max_numeric_error = error;
+ if (error < min_numeric_error) min_numeric_error = error;
+ }
+
+ String message = value + typeOf(value) + " F> " +
+ escape(s) + " P> " +
+ n + typeOf(n) + " F> " +
+ escape(s2);
+ if (err.length() > 0) {
+ errln("*** " + err + " with " +
+ formatName + " in " + localeName +
+ " " + message);
+ } else {
+ logln(message);
+ }
+ } catch (ParseException e) {
+ errln("*** " + e.toString() + " with " +
+ formatName + " in " + localeName);
+ }
+ }
+
+ static String typeOf(Number n) {
+ if (n instanceof Long) return " Long";
+ if (n instanceof Double) return " Double";
+ return " Number";
+ }
+
+ static String escape(String s) {
+ StringBuffer buf = new StringBuffer();
+ for (int i=0; i<s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c < (char)0xFF) {
+ buf.append(c);
+ } else {
+ buf.append("\\U");
+ buf.append(Integer.toHexString((c & 0xF000) >> 12));
+ buf.append(Integer.toHexString((c & 0x0F00) >> 8));
+ buf.append(Integer.toHexString((c & 0x00F0) >> 4));
+ buf.append(Integer.toHexString(c & 0x000F));
+ }
+ }
+ return buf.toString();
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/NumberTest.java b/test/java/text/Format/NumberFormat/NumberTest.java
new file mode 100644
index 0000000000..ca519bb6da
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/NumberTest.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4122840 4135202 4408066 4838107 8008577
+ * @summary test NumberFormat
+ * @library /java/text/testlib
+ * @modules java.base/sun.util.resources
+ * @compile -XDignore.symbol.file NumberTest.java
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI NumberTest
+ */
+
+import java.util.*;
+import java.text.*;
+import sun.util.resources.LocaleData;
+
+public class NumberTest extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new NumberTest().run(args);
+ }
+
+ // Test pattern handling
+ public void TestPatterns()
+ {
+ DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+ String pat[] = { "#.#", "#.", ".#", "#" };
+ String newpat[] = { "#0.#", "#0.", "#.0", "#" };
+ String num[] = { "0", "0.", ".0", "0" };
+ for (int i=0; i<pat.length; ++i)
+ {
+ DecimalFormat fmt = new DecimalFormat(pat[i], sym);
+ String newp = fmt.toPattern();
+ if (!newp.equals(newpat[i]))
+ errln("FAIL: Pattern " + pat[i] + " should transmute to " + newpat[i] +
+ "; " + newp + " seen instead");
+
+ String s = fmt.format(0);
+ if (!s.equals(num[i]))
+ {
+ errln("FAIL: Pattern " + pat[i] + " should format zero as " + num[i] +
+ "; " + s + " seen instead");
+ logln("Min integer digits = " + fmt.getMinimumIntegerDigits());
+ }
+ }
+ }
+
+ // Test exponential pattern
+ public void TestExponential() {
+ DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+ String pat[] = { "0.####E0", "00.000E00", "##0.####E000", "0.###E0;[0.###E0]" };
+ double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
+ long lval[] = { 0, -1, 1, 123456789 };
+ String valFormat[] = {
+ "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
+ "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
+ "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
+ "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
+ };
+ String lvalFormat[] = {
+ "0E0", "-1E0", "1E0", "1.2346E8",
+ "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
+ "0E000", "-1E000", "1E000", "123.4568E006",
+ "0E0", "[1E0]", "1E0", "1.235E8"
+ };
+ double valParse[] = {
+ 0.01234, 123460000, 1.23E300, -3.1416E-271,
+ 0.01234, 123460000, 1.23E300, -3.1416E-271,
+ 0.01234, 123456800, 1.23E300, -3.141593E-271,
+ 0.01234, 123500000, 1.23E300, -3.142E-271,
+ };
+ long lvalParse[] = {
+ 0, -1, 1, 123460000,
+ 0, -1, 1, 123460000,
+ 0, -1, 1, 123456800,
+ 0, -1, 1, 123500000,
+ };
+ int ival = 0, ilval = 0;
+ for (int p=0; p<pat.length; ++p) {
+ DecimalFormat fmt = new DecimalFormat(pat[p], sym);
+ logln("Pattern \"" + pat[p] + "\" -toPattern-> \"" +
+ fmt.toPattern() + '"');
+
+ for (int v=0; v<val.length; ++v) {
+ String s = fmt.format(val[v]);
+ logln(" Format " + val[v] + " -> " + escape(s));
+ if (!s.equals(valFormat[v+ival])) {
+ errln("FAIL: Expected " + valFormat[v+ival] +
+ ", got " + s +
+ ", pattern=" + fmt.toPattern());
+ }
+
+ ParsePosition pos = new ParsePosition(0);
+ Number a = fmt.parse(s, pos);
+ if (pos.getIndex() == s.length()) {
+ logln(" Parse -> " + a);
+ if (a.doubleValue() != valParse[v+ival]) {
+ errln("FAIL: Expected " + valParse[v+ival] +
+ ", got " + a.doubleValue() +
+ ", pattern=" + fmt.toPattern());
+ }
+ } else {
+ errln(" FAIL: Partial parse (" + pos.getIndex() +
+ " chars) -> " + a);
+ }
+ }
+ for (int v=0; v<lval.length; ++v) {
+ String s = fmt.format(lval[v]);
+ logln(" Format " + lval[v] + "L -> " + escape(s));
+ if (!s.equals(lvalFormat[v+ilval])) {
+ errln("ERROR: Expected " + lvalFormat[v+ilval] +
+ ", got " + s +
+ ", pattern=" + fmt.toPattern());
+ }
+
+ ParsePosition pos = new ParsePosition(0);
+ Number a = fmt.parse(s, pos);
+ if (pos.getIndex() == s.length()) {
+ logln(" Parse -> " + a);
+ if (a.longValue() != lvalParse[v+ilval]) {
+ errln("FAIL: Expected " + lvalParse[v+ilval] +
+ ", got " + a +
+ ", pattern=" + fmt.toPattern());
+ }
+ } else {
+ errln(" FAIL: Partial parse (" + pos.getIndex() +
+ " chars) -> " + a);
+ }
+ }
+ ival += val.length;
+ ilval += lval.length;
+ }
+ }
+
+ // Test the handling of quotes
+ public void TestQuotes()
+ {
+ String pat;
+ DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+ DecimalFormat fmt = new DecimalFormat(pat = "a'fo''o'b#", sym);
+ String s = fmt.format(123);
+ logln("Pattern \"" + pat + "\"");
+ logln(" Format 123 -> " + escape(s));
+ if (!s.equals("afo'ob123")) errln("FAIL: Expected afo'ob123");
+
+ fmt = new DecimalFormat(pat = "a''b#", sym);
+ s = fmt.format(123);
+ logln("Pattern \"" + pat + "\"");
+ logln(" Format 123 -> " + escape(s));
+ if (!s.equals("a'b123")) errln("FAIL: Expected a'b123");
+ }
+
+ // Test the use of the currency sign
+ public void TestCurrencySign()
+ {
+ DecimalFormatSymbols sym = DecimalFormatSymbols.getInstance(Locale.US);
+ DecimalFormat fmt = new DecimalFormat("\u00A4#,##0.00;-\u00A4#,##0.00", sym);
+ // Can't test this properly until currency API goes public
+ // DecimalFormatSymbols sym = fmt.getDecimalFormatSymbols();
+
+ String s = fmt.format(1234.56);
+ logln("Pattern \"" + fmt.toPattern() + "\"");
+ logln(" Format " + 1234.56 + " -> " + escape(s));
+ if (!s.equals("$1,234.56")) errln("FAIL: Expected $1,234.56");
+ s = fmt.format(-1234.56);
+ logln(" Format " + -1234.56 + " -> " + escape(s));
+ if (!s.equals("-$1,234.56")) errln("FAIL: Expected -$1,234.56");
+
+ fmt = new DecimalFormat("\u00A4\u00A4 #,##0.00;\u00A4\u00A4 -#,##0.00", sym);
+ s = fmt.format(1234.56);
+ logln("Pattern \"" + fmt.toPattern() + "\"");
+ logln(" Format " + 1234.56 + " -> " + escape(s));
+ if (!s.equals("USD 1,234.56")) errln("FAIL: Expected USD 1,234.56");
+ s = fmt.format(-1234.56);
+ logln(" Format " + -1234.56 + " -> " + escape(s));
+ if (!s.equals("USD -1,234.56")) errln("FAIL: Expected USD -1,234.56");
+ }
+ static String escape(String s)
+ {
+ StringBuffer buf = new StringBuffer();
+ char HEX[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
+ for (int i=0; i<s.length(); ++i)
+ {
+ char c = s.charAt(i);
+ if (c <= (char)0x7F) buf.append(c);
+ else
+ {
+ buf.append("\\U");
+ buf.append(HEX[(c & 0xF000) >> 12]);
+ buf.append(HEX[(c & 0x0F00) >> 8]);
+ buf.append(HEX[(c & 0x00F0) >> 4]);
+ buf.append(HEX[c & 0x000F]);
+ }
+ }
+ return buf.toString();
+ }
+
+ // Test simple currency format
+ // Bug 4024941; this code used to throw a NumberFormat exception
+ public void TestCurrency() {
+ NumberFormat currencyFmt =
+ NumberFormat.getCurrencyInstance(Locale.CANADA_FRENCH);
+ String s = currencyFmt.format(1.50);
+ logln("Un pauvre ici a..........." + s);
+ if (!s.equals("1,50 $")) {
+ errln("FAIL: Expected 1,50 $; got " + s + "; "+ dumpFmt(currencyFmt));
+ }
+ currencyFmt = NumberFormat.getCurrencyInstance(Locale.GERMANY);
+ s = currencyFmt.format(1.50);
+ logln("Un pauvre en Allemagne a.." + s);
+ if (!s.equals("1,50 \u20AC")) {
+ errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));
+ }
+ currencyFmt = NumberFormat.getCurrencyInstance(Locale.FRANCE);
+ s = currencyFmt.format(1.50);
+ logln("Un pauvre en France a....." + s);
+ if (!s.equals("1,50 \u20AC")) {
+ errln("FAIL: Expected 1,50 \u20AC; got " + s + "; " + dumpFmt(currencyFmt));
+ }
+ }
+
+ String dumpFmt(NumberFormat numfmt) {
+ DecimalFormat fmt = (DecimalFormat)numfmt;
+ StringBuffer buf = new StringBuffer();
+ buf.append("pattern \"");
+ buf.append(fmt.toPattern());
+ buf.append("\", currency \"");
+ buf.append(fmt.getDecimalFormatSymbols().getCurrencySymbol());
+ buf.append("\"");
+ return buf.toString();
+ }
+
+ // Test numeric parsing
+ // Bug 4059870
+ public void TestParse()
+ {
+ String arg = "0";
+ java.text.DecimalFormat format = new java.text.DecimalFormat("00");
+ try {
+ Number n = format.parse(arg);
+ logln("parse(" + arg + ") = " + n);
+ if (n.doubleValue() != 0.0) errln("FAIL: Expected 0");
+ } catch (Exception e) { errln("Exception caught: " + e); }
+ }
+
+ // Test rounding
+ public void TestRounding487() {
+ NumberFormat nf = NumberFormat.getInstance(Locale.US);
+ roundingTest(nf, 0.00159999, 4, "0.0016");
+ roundingTest(nf, 0.00995, 4, "0.01");
+ roundingTest(nf, 12.7995, 3, "12.8");
+ roundingTest(nf, 12.4999, 0, "12");
+ roundingTest(nf, -19.5, 0, "-20");
+ }
+
+ void roundingTest(NumberFormat nf, double x, int maxFractionDigits, String expected) {
+ nf.setMaximumFractionDigits(maxFractionDigits);
+ String out = nf.format(x);
+ logln("" + x + " formats with " + maxFractionDigits + " fractional digits to " + out);
+ if (!out.equals(expected)) {
+ errln("FAIL: Expected " + expected + ", got " + out);
+ }
+ }
+
+ /**
+ * Bug 4135202
+ * DecimalFormat should recognize not only Latin digits 0-9 (\u0030-\u0039)
+ * but also various other ranges of Unicode digits, such as Arabic
+ * digits \u0660-\u0669 and Devanagari digits \u0966-\u096F, to name
+ * a couple.
+ * @see java.lang.Character#isDigit(char)
+ */
+ public void TestUnicodeDigits() {
+ char[] zeros = {
+ 0x0030, // ISO-LATIN-1 digits ('0' through '9')
+ 0x0660, // Arabic-Indic digits
+ 0x06F0, // Extended Arabic-Indic digits
+ 0x0966, // Devanagari digits
+ 0x09E6, // Bengali digits
+ 0x0A66, // Gurmukhi digits
+ 0x0AE6, // Gujarati digits
+ 0x0B66, // Oriya digits
+ 0x0BE6, // Tamil digits
+ 0x0C66, // Telugu digits
+ 0x0CE6, // Kannada digits
+ 0x0D66, // Malayalam digits
+ 0x0E50, // Thai digits
+ 0x0ED0, // Lao digits
+ 0x0F20, // Tibetan digits
+ 0xFF10, // Fullwidth digits
+ };
+ NumberFormat format = NumberFormat.getInstance();
+ for (int i=0; i<zeros.length; ++i) {
+ char zero = zeros[i];
+ StringBuffer buf = new StringBuffer();
+ buf.append((char)(zero+3));
+ buf.append((char)(zero+1));
+ buf.append((char)(zero+4));
+ int n = -1;
+ try {
+ n = format.parse(buf.toString()).intValue();
+ }
+ catch (ParseException e) { n = -2; }
+ if (n != 314)
+ errln("Can't parse Unicode " + Integer.toHexString(zero) + " as digit (" + n + ")");
+ else
+ logln("Parse digit " + Integer.toHexString(zero) + " ok");
+ }
+ }
+
+ /**
+ * Bug 4122840
+ * Make sure that the currency symbol is not hard-coded in any locale.
+ */
+ public void TestCurrencySubstitution() {
+ final String SYM = "<currency>";
+ final String INTL_SYM = "<intl.currency>";
+ Locale[] locales = NumberFormat.getAvailableLocales();
+ for (int i=0; i<locales.length; ++i) {
+ NumberFormat nf = NumberFormat.getCurrencyInstance(locales[i]);
+ if (nf instanceof DecimalFormat) {
+ DecimalFormat df = (DecimalFormat)nf;
+ String genericPos = df.format(1234.5678);
+ String genericNeg = df.format(-1234.5678);
+ DecimalFormatSymbols sym = df.getDecimalFormatSymbols();
+ sym.setCurrencySymbol(SYM);
+ sym.setInternationalCurrencySymbol(INTL_SYM);
+ // We have to make a new DecimalFormat from scratch in order
+ // to make the new symbols 'take'. This may be a bug or
+ // design flaw in DecimalFormat.
+ String[] patterns = LocaleData.getBundle("sun.text.resources.FormatData", locales[i])
+ .getStringArray("NumberPatterns");
+ df = new DecimalFormat(patterns[1 /*CURRENCYSTYLE*/], sym);
+ String customPos = df.format(1234.5678);
+ String customNeg = df.format(-1234.5678);
+ if (genericPos.equals(customPos) || genericNeg.equals(customNeg)) {
+ errln("FAIL: " + locales[i] +
+ " not using currency symbol substitution: " + genericPos);
+ }
+ else {
+ if (customPos.indexOf(SYM) >= 0) {
+ if (customNeg.indexOf(INTL_SYM) >= 0)
+ errln("Fail: Positive and negative patterns use different symbols");
+ else
+ logln("Ok: " + locales[i] +
+ " uses currency symbol: " + genericPos +
+ ", " + customPos);
+ }
+ else if (customPos.indexOf(INTL_SYM) >= 0) {
+ if (customNeg.indexOf(SYM) >= 0)
+ errln("Fail: Positive and negative patterns use different symbols");
+ else
+ logln("Ok: " + locales[i] +
+ " uses intl. currency symbol: " + genericPos +
+ ", " + customPos);
+ }
+ else {
+ errln("FAIL: " + locales[i] +
+ " contains no currency symbol (impossible!)");
+ }
+ }
+ }
+ else logln("Skipping " + locales[i] + "; not a DecimalFormat");
+ }
+ }
+
+ public void TestIntegerFormat() throws ParseException {
+ NumberFormat format = NumberFormat.getIntegerInstance(Locale.GERMANY);
+
+ float[] formatInput = { 12345.67f, -12345.67f, -0, 0 };
+ String[] formatExpected = { "12.346", "-12.346", "0", "0" };
+
+ for (int i = 0; i < formatInput.length; i++) {
+ String result = format.format(formatInput[i]);
+ if (!result.equals(formatExpected[i])) {
+ errln("FAIL: Expected " + formatExpected[i] + ", got " + result);
+ }
+ }
+
+ String[] parseInput = { "0", "-0", "12.345,67", "-12.345,67" };
+ float[] parseExpected = { 0, 0, 12345, -12345 };
+
+ for (int i = 0; i < parseInput.length; i++) {
+ float result = ((Number) format.parse(parseInput[i])).floatValue();
+ if (result != parseExpected[i]) {
+ errln("FAIL: Expected " + parseExpected[i] + ", got " + result);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/PositionTest.java b/test/java/text/Format/NumberFormat/PositionTest.java
new file mode 100644
index 0000000000..31a5a3dbeb
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/PositionTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4109023 4153060 4153061
+ * @library /java/text/testlib
+ * @summary test ParsePosition and FieldPosition
+ */
+/*
+(C) Copyright Taligent, Inc. 1996 - All Rights Reserved
+(C) Copyright IBM Corp. 1996 - All Rights Reserved
+
+ The original version of this source code and documentation is copyrighted and
+owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
+provided under terms of a License Agreement between Taligent and Sun. This
+technology is protected by multiple US and International patents. This notice and
+attribution to Taligent may not be removed.
+ Taligent is a registered trademark of Taligent, Inc.
+*/
+
+import java.text.*;
+import java.io.*;
+
+public class PositionTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new PositionTest().run(args);
+ }
+
+ public void TestParsePosition() {
+ ParsePosition pp1 = new ParsePosition(0);
+ if (pp1.getIndex() == 0) {
+ logln("PP constructor() tested.");
+ }else{
+ errln("*** PP getIndex or constructor() result");
+ }
+
+ {
+ int to = 5;
+ ParsePosition pp2 = new ParsePosition ( to );
+ if (pp2.getIndex() == 5) {
+ logln("PP getIndex and constructor(TextOffset) tested.");
+ }else{
+ errln("*** PP getIndex or constructor(TextOffset) result");
+ }
+ pp2.setIndex( 3 );
+ if (pp2.getIndex() == 3) {
+ logln("PP setIndex tested.");
+ }else{
+ errln("*** PP getIndex or setIndex result");
+ }
+ }
+
+ ParsePosition pp2, pp3;
+ pp2 = new ParsePosition( 3 );
+ pp3 = new ParsePosition( 5 );
+ ParsePosition pp4 = new ParsePosition(5);
+ if (! pp2.equals(pp3)) {
+ logln("PP not equals tested.");
+ }else{
+ errln("*** PP not equals fails");
+ }
+ if (pp3.equals(pp4)) {
+ logln("PP equals tested.");
+ }else{
+ errln("*** PP equals fails (" + pp3.getIndex() + " != " + pp4.getIndex() + ")");
+ }
+
+ ParsePosition pp5;
+ pp5 = pp4;
+ if (pp4.equals(pp5)) {
+ logln("PP operator= tested.");
+ }else{
+ errln("*** PP operator= operator== or operator != result");
+ }
+
+ }
+
+ public void TestFieldPosition() {
+ FieldPosition fp = new FieldPosition( 7 );
+
+ if (fp.getField() == 7) {
+ logln("FP constructor(int) and getField tested.");
+ }else{
+ errln("*** FP constructor(int) or getField");
+ }
+
+ FieldPosition fph = new FieldPosition( 3 );
+ if ( fph.getField() != 3) errln("*** FP getField or heap constr.");
+
+ boolean err1 = false;
+ boolean err2 = false;
+ boolean err3 = false;
+// for (long i = -50; i < 50; i++ ) {
+// fp.setField( i+8 );
+// fp.setBeginIndex( i+6 );
+// fp.setEndIndex( i+7 );
+// if (fp.getField() != i+8) err1 = true;
+// if (fp.getBeginIndex() != i+6) err2 = true;
+// if (fp.getEndIndex() != i+7) err3 = true;
+// }
+ if (!err1) {
+ logln("FP setField and getField tested.");
+ }else{
+ errln("*** FP setField or getField");
+ }
+ if (!err2) {
+ logln("FP setBeginIndex and getBeginIndex tested.");
+ }else{
+ errln("*** FP setBeginIndex or getBeginIndex");
+ }
+ if (!err3) {
+ logln("FP setEndIndex and getEndIndex tested.");
+ }else{
+ errln("*** FP setEndIndex or getEndIndex");
+ }
+
+ logln("");
+ }
+
+ public void TestFieldPosition_example() {
+ //***** no error detection yet !!!!!!!
+ //***** this test is for compiler checks and visual verification only.
+ double doubleNum[] = { 123456789.0, -12345678.9, 1234567.89, -123456.789,
+ 12345.6789, -1234.56789, 123.456789, -12.3456789, 1.23456789};
+ int dNumSize = doubleNum.length;
+
+ DecimalFormat fmt = (DecimalFormat) NumberFormat.getInstance();
+ fmt.setDecimalSeparatorAlwaysShown(true);
+
+ final int tempLen = 20;
+ StringBuffer temp;
+
+ for (int i=0; i<dNumSize; i++) {
+ temp = new StringBuffer(); // Get new buffer
+
+ FieldPosition pos = new FieldPosition(NumberFormat.INTEGER_FIELD);
+ StringBuffer buf = new StringBuffer();
+ //char fmtText[tempLen];
+ //ToCharString(fmt->format(doubleNum[i], buf, pos), fmtText);
+ StringBuffer res = fmt.format(doubleNum[i], buf, pos);
+ int tempOffset = (tempLen <= (tempLen - pos.getEndIndex())) ?
+ tempLen : (tempLen - pos.getEndIndex());
+ for (int j=0; j<tempOffset; j++) temp.append('='); // initialize
+ //cout << temp << fmtText << endl;
+ logln("FP " + temp + res);
+ }
+
+ logln("");
+ }
+ /* @bug 4109023
+ * Need to override ParsePosition.equals and FieldPosition.equals.
+ */
+ public void Test4109023()
+ {
+
+ ParsePosition p = new ParsePosition(3);
+ ParsePosition p2 = new ParsePosition(3);
+ if (!p.equals(p2))
+ errln("Error : ParsePosition.equals() failed");
+ FieldPosition fp = new FieldPosition(2);
+ FieldPosition fp2 = new FieldPosition(2);
+ if (!fp.equals(fp2))
+ errln("Error : FieldPosition.equals() failed");
+ }
+
+ /**
+ * @bug 4153060
+ * ParsePosition.hashCode() returns different values on equal objects.
+ */
+ public void Test4153060() {
+ ParsePosition p = new ParsePosition(53);
+ ParsePosition q = new ParsePosition(53);
+ if (!p.equals(q)) {
+ errln("" + p + " and " + q + " are not equal and should be");
+ }
+ if (p.hashCode() != q.hashCode()) {
+ errln("ParsePosition.hashCode() different for equal objects");
+ } else {
+ logln("hashCode(" + p + ") = " + p.hashCode());
+ }
+ }
+
+ /**
+ * @bug 4153061
+ * FieldPosition.hashCode() returns different values on equal objects.
+ */
+ public void Test4153061() {
+ FieldPosition p = new FieldPosition(53);
+ FieldPosition q = new FieldPosition(53);
+ if (!p.equals(q)) {
+ errln("" + p + " and " + q + " are not equal and should be");
+ }
+ if (p.hashCode() != q.hashCode()) {
+ errln("FieldPosition.hashCode() different for equal objects");
+ } else {
+ logln("hashCode(" + p + ") = " + p.hashCode());
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/SerializationLoadTest.java b/test/java/text/Format/NumberFormat/SerializationLoadTest.java
new file mode 100644
index 0000000000..3499e1c553
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/SerializationLoadTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4101150
+ * @library /java/text/testlib
+ * @build SerializationLoadTest HexDumpReader
+ * @run main SerializationLoadTest
+ * @summary test serialization compatibility of DecimalFormat and DecimalFormatSymbols
+ * @key randomness
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class SerializationLoadTest {
+
+ public static void main(String[] args)
+ {
+ try {
+ InputStream istream1 = HexDumpReader.getStreamFromHexDump("DecimalFormat.114.txt");
+ ObjectInputStream p = new ObjectInputStream(istream1);
+ CheckDecimalFormat it = (CheckDecimalFormat)p.readObject();
+ System.out.println("1.1.4 DecimalFormat Loaded ok.");
+ System.out.println(it.Update());
+ System.out.println("Called Update successfully.");
+ istream1.close();
+
+ InputStream istream2 = HexDumpReader.getStreamFromHexDump("DecimalFormatSymbols.114.txt");
+ ObjectInputStream p2 = new ObjectInputStream(istream2);
+ CheckDecimalFormatSymbols it2 = (CheckDecimalFormatSymbols)p2.readObject();
+ System.out.println("1.1.4 DecimalFormatSymbols Loaded ok.");
+ System.out.println("getDigit : " + it2.Update());
+ System.out.println("Called Update successfully.");
+ istream2.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
+class CheckDecimalFormat implements Serializable
+{
+ DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
+
+ public String Update()
+ {
+ Random r = new Random();
+ return _decFormat.format(r.nextDouble());
+ }
+}
+
+class CheckDecimalFormatSymbols implements Serializable
+{
+ DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
+
+ public char Update()
+ {
+ return _decFormatSymbols.getDigit();
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/SerializationSaveTest.java b/test/java/text/Format/NumberFormat/SerializationSaveTest.java
new file mode 100644
index 0000000000..2f298adeb0
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/SerializationSaveTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1998, 2016, 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.
+ */
+
+/*
+ * No at-test for this test, because it needs to be run on JDK 1.1.4.
+ * Instead, the resulting serialized files DecimalFormat.114 and
+ * DecimalFormatSymbols.114 are archived.
+ */
+
+import java.awt.*;
+import java.text.*;
+import java.util.*;
+import java.io.*;
+
+public class SerializationSaveTest {
+
+ public static void main(String[] args)
+ {
+ try {
+ CheckDecimalFormat it = new CheckDecimalFormat();
+ System.out.println(it.Update());
+ FileOutputStream ostream = new FileOutputStream("DecimalFormat.114");
+ ObjectOutputStream p = new ObjectOutputStream(ostream);
+ p.writeObject(it);
+ ostream.close();
+ System.out.println("DecimalFormat saved ok.");
+ CheckDecimalFormatSymbols it2 = new CheckDecimalFormatSymbols();
+ System.out.println("getDigit : " + it2.Update());
+ FileOutputStream ostream2 = new FileOutputStream("DecimalFormatSymbols.114");
+ ObjectOutputStream p2 = new ObjectOutputStream(ostream2);
+ p2.writeObject(it2);
+ ostream2.close();
+ System.out.println("DecimalFormatSymbols saved ok.");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
+
+class CheckDecimalFormat implements Serializable
+{
+ DecimalFormat _decFormat = (DecimalFormat)NumberFormat.getInstance();
+
+ public String Update()
+ {
+ Random r = new Random();
+ return _decFormat.format(r.nextDouble());
+ }
+}
+
+class CheckDecimalFormatSymbols implements Serializable
+{
+ DecimalFormatSymbols _decFormatSymbols = new DecimalFormatSymbols();
+
+ public char Update()
+ {
+ return _decFormatSymbols.getDigit();
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/TestPeruCurrencyFormat.java b/test/java/text/Format/NumberFormat/TestPeruCurrencyFormat.java
new file mode 100644
index 0000000000..246208b7aa
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/TestPeruCurrencyFormat.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019, 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 8206879
+ * @summary Currency decimal marker incorrect for Peru.
+ * @modules jdk.localedata
+ * @run main/othervm -Djava.locale.providers=JRE TestPeruCurrencyFormat
+ */
+
+import java.text.NumberFormat;
+import java.util.Locale;
+
+public class TestPeruCurrencyFormat {
+
+ public static void main(String[] args) {
+ final String expected = "S/.1,234.56";
+ NumberFormat currencyFmt =
+ NumberFormat.getCurrencyInstance(new Locale("es", "PE"));
+ String s = currencyFmt.format(1234.56);
+
+ if (!s.equals(expected)) {
+ throw new RuntimeException("Currency format for Peru failed, expected " + expected + ", got " + s);
+ }
+ }
+}
diff --git a/test/java/text/Format/NumberFormat/TestgetPatternSeparator_ja.java b/test/java/text/Format/NumberFormat/TestgetPatternSeparator_ja.java
new file mode 100644
index 0000000000..2a73abf4ad
--- /dev/null
+++ b/test/java/text/Format/NumberFormat/TestgetPatternSeparator_ja.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1999, 2016, 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 4201262
+ * @summary Make sure that DecimalFormatSymbols.getPatternSeparator returns ';' in ja locale.
+ */
+
+import java.text.NumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
+
+public class TestgetPatternSeparator_ja {
+
+ public static void main(String[] argv) throws Exception {
+ DecimalFormat df = (DecimalFormat)NumberFormat.getInstance(Locale.JAPAN);
+ DecimalFormatSymbols dfs = df.getDecimalFormatSymbols();
+ if (dfs.getPatternSeparator() != ';') {
+ throw new Exception("DecimalFormatSymbols.getPatternSeparator doesn't return ';' in ja locale");
+ }
+ }
+}
diff --git a/test/java/text/Format/common/Bug4769840.java b/test/java/text/Format/common/Bug4769840.java
new file mode 100644
index 0000000000..0ac07ae230
--- /dev/null
+++ b/test/java/text/Format/common/Bug4769840.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003, 2016, 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 1.1 03/10/27
+ * @bug 4769840
+ * @library /java/text/testlib
+ * @build Bug4769840 HexDumpReader
+ * @run main Bug4769840
+ * @summary Confirm serialization compatibility
+ */
+
+import java.io.*;
+import java.text.*;
+
+public class Bug4769840 {
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1 && args[0].equals("-ser")) {
+ serialize();
+ } else {
+ deserialize();
+ }
+ }
+
+ /* Serialization */
+ private static void serialize() throws Exception {
+ /* Serialize with JDK 1.1 */
+ serialize("ChoiceFormat.ser", new ChoiceFormat("0# foo|1# bar"));
+
+ /*
+ * Serialize with JDK1.4.0 because the Field class was added in the
+ * version.
+ */
+ serialize("DateFormat.Field.ser", DateFormat.Field.TIME_ZONE);
+ serialize("MessageFormat.Field.ser", MessageFormat.Field.ARGUMENT);
+ serialize("NumberFormat.Field.ser", NumberFormat.Field.INTEGER);
+ }
+
+ private static void serialize(String filename, Object o) throws Exception {
+ FileOutputStream fos = new FileOutputStream(filename);
+ ObjectOutputStream out = new ObjectOutputStream(fos);
+ out.writeObject(o);
+ out.close();
+ }
+
+ /* Deserialization */
+ private static void deserialize() throws Exception {
+ deserialize("ChoiceFormat.ser");
+ deserialize("DateFormat.Field.ser");
+ deserialize("MessageFormat.Field.ser");
+ deserialize("NumberFormat.Field.ser");
+ }
+
+ private static void deserialize(String filename) throws Exception {
+ InputStream is = HexDumpReader.getStreamFromHexDump(filename + ".txt");
+ ObjectInputStream in = new ObjectInputStream(is);
+ Object obj = in.readObject();
+ in.close();
+ System.out.println("Deserialization of <" + filename + "> succeeded.");
+ }
+}
diff --git a/test/java/text/Format/common/Bug6215962.java b/test/java/text/Format/common/Bug6215962.java
new file mode 100644
index 0000000000..85dd5e2ceb
--- /dev/null
+++ b/test/java/text/Format/common/Bug6215962.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6215962
+ * @summary Confirm that replacing Utility.arayEquals methods have with
+ * Arrays.equals introduces no problem.
+ */
+import java.text.*;
+import java.util.*;
+
+public class Bug6215962 {
+
+ public static void main(String[] args) {
+ testMessageFormat();
+ testChoiceFormat();
+ testDateFormatSymbols();
+ }
+
+ /**
+ * Test cases for MessageFormat
+ */
+ static void testMessageFormat() {
+ MessageFormat mf1 = new MessageFormat("{0}", null);
+ MessageFormat mf2 = new MessageFormat("{0}", null);
+ check(mf1, mf2, true);
+
+ mf1.setLocale(null);
+ check(mf1, mf2, true);
+
+ mf1 = new MessageFormat("{0}", Locale.US);
+ check(mf1, mf2, false);
+
+ mf2 = new MessageFormat("{0}", Locale.JAPAN);
+ check(mf1, mf2, false);
+
+ mf1 = new MessageFormat("{0}", new Locale("ja", "JP"));
+ check(mf1, mf2, true);
+
+ mf1.setLocale(null);
+ check(mf1, mf2, false);
+
+ mf1 = new MessageFormat("{0}", new Locale("ja", "JP", "FOO"));
+ check(mf1, mf2, false);
+
+ mf2 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO"));
+ check(mf1, mf2, false);
+
+ mf1 = new MessageFormat("{1}", new Locale("ja", "JP", "FOO"));
+ check(mf1, mf2, true);
+
+ mf1 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO"));
+ check(mf1, mf2, false);
+
+ mf2 = new MessageFormat("{1, date}", new Locale("ja", "JP", "FOO"));
+ check(mf1, mf2, true);
+ }
+
+ static void check(MessageFormat f1, MessageFormat f2, boolean expected) {
+ boolean got = f1.equals(f2);
+ if (got != expected) {
+ throw new RuntimeException("Test failed for MessageFormat.equals(). Got: " + got + ", Expected: " + expected);
+ }
+ }
+
+ /**
+ * Test cases for MessageFormat
+ */
+ static void testChoiceFormat() {
+ double[] limits0 = {0,1,2,3,4,5,6};
+ double[] limits1 = {1,2,3,4,5,6,7};
+ String[] monthNames0 = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
+ String[] monthNames1 = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"};
+
+ ChoiceFormat cf1 = new ChoiceFormat(limits1, monthNames0);
+ ChoiceFormat cf2 = new ChoiceFormat(limits1, monthNames0);
+ check(cf1, cf2, true);
+
+ cf2 = new ChoiceFormat(limits0, monthNames0);
+ check(cf1, cf2, false);
+
+ cf2 = new ChoiceFormat(limits1, monthNames1);
+ check(cf1, cf2, false);
+ }
+
+ static void check(ChoiceFormat f1, ChoiceFormat f2, boolean expected) {
+ boolean got = f1.equals(f2);
+ if (got != expected) {
+ throw new RuntimeException("Test failed for ChoiceFormat.equals(). Got: " + got + ", Expected: " + expected);
+ }
+ }
+
+ /**
+ * Test cases for DateFormatSymbols
+ */
+ static void testDateFormatSymbols() {
+ DateFormatSymbols dfs1 = new DateFormatSymbols();
+ DateFormatSymbols dfs2 = new DateFormatSymbols();
+ check(dfs1, dfs2, true);
+
+ // Becase eras, months, shortmonths, weekdays, shortweekdays, ampms are
+ // the same data type (String[]) and are treated in the same way, here
+ // I test only Months.
+ String[] tmp = dfs1.getMonths();
+ String saved = tmp[0];
+ tmp[0] = "Foo";
+ dfs1.setMonths(tmp);
+ check(dfs1, dfs2, false);
+
+ tmp[0] = saved;
+ dfs1.setMonths(tmp);
+ check(dfs1, dfs2, true);
+
+ // Test LocalizedpatternChars (String)
+ String pattern = dfs2.getLocalPatternChars();
+ dfs2.setLocalPatternChars("Bar");
+ check(dfs1, dfs2, false);
+
+ dfs2.setLocalPatternChars(pattern);
+ check(dfs1, dfs2, true);
+
+ // Test TimeZone strings (String[][])
+ String[][] zones = dfs1.getZoneStrings();
+ saved = zones[0][1];
+ zones[0][1] = "Yokohama Summer Time";
+ dfs1.setZoneStrings(zones);
+ check(dfs1, dfs2, false);
+
+ zones[0][1] = saved;
+ dfs1.setZoneStrings(zones);
+ check(dfs1, dfs2, true);
+ }
+
+ static void check(DateFormatSymbols dfs1, DateFormatSymbols dfs2, boolean expected) {
+ boolean got = dfs1.equals(dfs2);
+ if (got != expected) {
+ throw new RuntimeException("Test failed for DateFormatSymbols.equals(). Got: " + got + ", Expected: " + expected);
+ }
+ }
+}
diff --git a/test/java/text/Format/common/ChoiceFormat.ser.txt b/test/java/text/Format/common/ChoiceFormat.ser.txt
new file mode 100644
index 0000000000..4947d1936e
--- /dev/null
+++ b/test/java/text/Format/common/ChoiceFormat.ser.txt
@@ -0,0 +1,37 @@
+#
+# Copyright (c) 2003, 2016, 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.
+#
+
+# Hex dump of a serialized ChoiceFormat for Bug4769840.
+
+aced0005737200166a6176612e746578742e43686f696365466f726d617418e9
+c6bee365b6040200025b000d63686f696365466f726d6174737400135b4c6a61
+76612f6c616e672f537472696e673b5b000c63686f6963654c696d6974737400
+025b44787200166a6176612e746578742e4e756d626572466f726d6174dff6b3
+bf137d07e80200065a000c67726f7570696e67557365644200116d6178467261
+6374696f6e4469676974734200106d6178496e74656765724469676974734200
+116d696e4672616374696f6e4469676974734200106d696e496e746567657244
+69676974735a00107061727365496e74656765724f6e6c79787200106a617661
+2e746578742e466f726d6174fbd8bc12e90f1843020000787001032800010075
+7200135b4c6a6176612e6c616e672e537472696e673badd256e7e91d7b470200
+0078700000000274000420666f6f74000420626172757200025b443ea68c14ab
+635a1e02000078700000000200000000000000003ff0000000000000
diff --git a/test/java/text/Format/common/DateFormat.Field.ser.txt b/test/java/text/Format/common/DateFormat.Field.ser.txt
new file mode 100644
index 0000000000..e78f24409e
--- /dev/null
+++ b/test/java/text/Format/common/DateFormat.Field.ser.txt
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2003, 2016, 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.
+#
+
+# Hex dump of a serialized DateFormat.Field for Bug4769840.
+
+aced00057372001a6a6176612e746578742e44617465466f726d617424466965
+6c646744fc81f123e71002000149000d63616c656e6461724669656c64787200
+166a6176612e746578742e466f726d6174244669656c6403d7fbbd383b0f9b02
+00007872002f6a6176612e746578742e41747472696275746564436861726163
+7465724974657261746f7224417474726962757465811e7426cd47175c020001
+4c00046e616d657400124c6a6176612f6c616e672f537472696e673b78707400
+0974696d65207a6f6e65ffffffff
diff --git a/test/java/text/Format/common/FormatIteratorTest.java b/test/java/text/Format/common/FormatIteratorTest.java
new file mode 100644
index 0000000000..7102f59dec
--- /dev/null
+++ b/test/java/text/Format/common/FormatIteratorTest.java
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2000, 2016, 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 4018937
+ * @library /java/text/testlib
+ * @build FormatIteratorTest PParser IntlTest
+ * @run main FormatIteratorTest
+ * @summary Tests the formatToCharacterIterator method of SimpleDateFormat,
+ * MessageFormat and DecimalFormat.
+ */
+
+import java.io.*;
+import java.lang.reflect.*;
+import java.text.*;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * FormatTester creates Formats, and tests the resulting FieldPositions
+ * and AttributedCharacterIterator based on a file. The file is a hierarchical
+ * set of key/value pairs, where each value can also be an array or map. The
+ * top map must contain a tests entry, which will be an array consisting
+ * of pairs of maps. The first map specifies the Format that
+ * should be created, and consists of:
+ * <pre>
+ * class = className
+ * args = (arg1 arg2 ...)
+ * valueClass = className
+ * valueArgs = (arg1 arg2 ...)
+ * </pre>
+ * The second map dictates what to test, and should consist of the following:
+ * <pre>
+ * length = lengthOfFormattedString
+ * text = Result of Formatting
+ * 0...lengthOfFormattedString = (arg1 arg2 ...)
+ * limits = ( range1 range2 ...)
+ * fieldPositions = ( fp1 fp2 ...)
+ * </pre>
+ * <code>lengthOfFormattedString</code> indicate the total length of formatted
+ * string. <code>text</code> indicates the resulting string.
+ * <code>0...x</code> where x == <code>lengthOfFormattedString - 1</code> is
+ * an array of the attributes that should exist at the particular
+ * location. <code>limits</code> is an array of maps, where each map
+ * can be used to test the bounds of a set of attributes. Each map will
+ * consist of:
+ * <pre>
+ * attributes = array of attributes
+ * begin = start location
+ * begin2 = second start location
+ * end = limit location
+ * end2 = second limit location
+ * </pre>
+ * These are tested by iterating from begin to end in the CharacterIterator
+ * and doing the following at each index:
+ * <pre>
+ * getRunStart() == begin
+ * getRunStart(attributes) == begin2
+ * getRunLimit() == end
+ * getRunLimit(attributes) == end2
+ * </pre>
+ * <code>fieldPositions</code> is used to test the results of invoking
+ * <code>format</code> with a <code>FieldPosition</code>.
+ * <code>fieldPositions</code> is an array of maps, where each map contains
+ * the following:
+ * <pre>
+ * field = Integer field reference (optional)
+ * fieldID = Object reference
+ * begin = begin index of FieldPosition after formatting
+ * end = end index of FieldPosition after formatting
+ * </pre>
+ * Any lines starting with {@code '#'} are comment lines and ignored.
+ */
+public class FormatIteratorTest extends IntlTest {
+ private static HashMap attrs;
+ private Format format;
+ private Object value;
+ private String text;
+
+ public static final Object ARG0_FIELD_ID = MessageFormat.
+ Field.ARGUMENT;
+ public static final Object ARG1_FIELD_ID = MessageFormat.
+ Field.ARGUMENT;
+ public static final Object ARG2_FIELD_ID = MessageFormat.
+ Field.ARGUMENT;
+ public static final Object ARG3_FIELD_ID = MessageFormat.
+ Field.ARGUMENT;
+
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ TimeZone reservedTimeZone = TimeZone.getDefault();
+ try {
+ // The current tests are only appropriate for US. If tests are
+ // added for other locales are added, then a property should be
+ // added to each file (test) to be able to specify the locale.
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+ new FormatIteratorTest().run(args);
+ } finally {
+ // restore the reserved locale and time zone
+ Locale.setDefault(reservedLocale);
+ TimeZone.setDefault(reservedTimeZone);
+ }
+ }
+
+ public FormatIteratorTest() {
+ }
+
+ public void testDecimalFormat() {
+ _test(new File(System.getProperty("test.src", "."),
+ "decimalFormat.props"));
+ }
+
+ public void testMessageFormat() {
+ _test(new File(System.getProperty("test.src", "."),
+ "messageFormat.props"));
+ }
+
+ public void testDateFormat() {
+ _test(new File(System.getProperty("test.src", "."),
+ "dateFormat.props"));
+ }
+
+ private void _test(File file) {
+ try {
+ attrs = new HashMap();
+ logln("testing: " + file);
+ PParser parser = new PParser();
+ Hashtable contents = parser.parse(new BufferedReader(
+ new FileReader(file)));
+ Vector test = (Vector)contents.get("tests");
+
+ for (int counter = 0; counter < test.size(); counter++) {
+ logln("creating: " + (counter / 2));
+
+ AttributedCharacterIterator iterator =
+ create((Hashtable)test.get(counter));
+
+ logln("verifying: " + (counter / 2));
+ verify(iterator, (Hashtable)test.get(++counter));
+ }
+ } catch (IOException ioe) {
+ errln("Error reading: " + ioe);
+ }
+ }
+
+ public void verify(AttributedCharacterIterator iterator,Hashtable table) {
+ int length = Integer.parseInt((String)table.get("length"));
+
+ // Verify the text
+ if (!getText(iterator).equals(
+ escapeIfNecessary((String)table.get("text")))) {
+ String text = getText(iterator);
+
+ errln("text doesn't match, got: " + getText(iterator));
+ }
+ if (iterator.getBeginIndex() != 0) {
+ errln("Bogus start: " + iterator.getBeginIndex());
+ }
+ if (iterator.getEndIndex() != length) {
+ errln("Bogus end: " + iterator.getEndIndex());
+ }
+ for (int counter = 0; counter < length; counter++) {
+ iterator.setIndex(counter);
+ if (!verifyAttributes(iterator.getAttributes().keySet(),
+ makeAttributes((Vector)table.get(Integer.
+ toString(counter))))) {
+ errln("Attributes don't match at " + counter + " expecting " +
+ makeAttributes((Vector)table.get(Integer.toString
+ (counter))) + " got " +
+ iterator.getAttributes().keySet());
+ }
+ }
+ for (int counter = length - 1; counter >= 0; counter--) {
+ iterator.setIndex(counter);
+ if (!verifyAttributes(iterator.getAttributes().keySet(),
+ makeAttributes((Vector)table.get(Integer.
+ toString(counter))))) {
+ errln("Attributes don't match at " + counter + " expecting " +
+ makeAttributes((Vector)table.get(Integer.toString
+ (counter))) + " got " +
+ iterator.getAttributes().keySet());
+ }
+ }
+ verifyLimits(iterator, table);
+
+ text = escapeIfNecessary((String)table.get("text"));
+ Vector fps = (Vector)table.get("fieldPositions");
+
+ if (fps != null) {
+ for (int counter = 0; counter < fps.size(); counter++) {
+ verifyFieldPosition(counter, (Hashtable)fps.get(counter));
+ }
+ }
+ }
+
+ private void verifyLimits(AttributedCharacterIterator iterator,
+ Hashtable table) {
+ Vector limits = (Vector)table.get("limits");
+
+ if (limits != null) {
+ for (int counter = 0; counter < limits.size(); counter++) {
+ verifyLimit(iterator, (Hashtable)limits.get(counter));
+ }
+ }
+ }
+
+ private void verifyLimit(AttributedCharacterIterator iterator,
+ Hashtable table) {
+ int begin = Integer.parseInt((String)table.get("begin"));
+ int end = Integer.parseInt((String)table.get("end"));
+ Set attrs = makeAttributes((Vector)table.get("attributes"));
+ String begin2S = (String)table.get("begin2");
+ int begin2 = (begin2S != null) ? Integer.parseInt(begin2S) : begin;
+ String end2S = (String)table.get("end2");
+ int end2 = (end2S != null) ? Integer.parseInt(end2S) : end;
+
+ for (int counter = begin; counter < end; counter++) {
+ iterator.setIndex(counter);
+ if (iterator.getRunStart() != begin) {
+ errln("Begin doesn't match want " + begin + " got " +
+ iterator.getRunStart() + " at " + counter + " attrs " +
+ attrs);
+ }
+ if (iterator.getRunStart(attrs) != begin2) {
+ errln("Begin2 doesn't match want " + begin2 + " got " +
+ iterator.getRunStart(attrs) + " at " + counter +
+ " attrs " + attrs);
+ }
+ if (iterator.getRunLimit() != end) {
+ errln("End doesn't match want " + end + " got " +
+ iterator.getRunLimit() + " at " + counter + " attrs " +
+ attrs);
+ }
+ if (iterator.getRunLimit(attrs) != end2) {
+ errln("End2 doesn't match want " + end2 + " got " +
+ iterator.getRunLimit(attrs) + " at " + counter +
+ " attrs " + attrs);
+ }
+ }
+ }
+
+ private boolean verifyAttributes(Set a, Set b) {
+ boolean aEmpty = (a.size() == 0);
+ boolean bEmpty = (b.size() == 0);
+
+ if (aEmpty && bEmpty) {
+ return true;
+ }
+ else if (aEmpty || bEmpty) {
+ return false;
+ }
+ return a.equals(b);
+ }
+
+ private String getText(AttributedCharacterIterator iterator) {
+ StringBuffer buffer = new StringBuffer();
+
+ for (int counter = 0; counter < iterator.getEndIndex(); counter++) {
+ buffer.append(iterator.setIndex(counter));
+ }
+ return buffer.toString();
+ }
+
+ private void verifyFieldPosition(int index, Hashtable table) {
+ Object o = table.get("field");
+ int begin = Integer.parseInt((String)table.get("begin"));
+ int end = Integer.parseInt((String)table.get("end"));
+
+ if (o != null) {
+ FieldPosition fp = new FieldPosition(((Integer)
+ lookupField((String)o)).intValue());
+
+ verifyFieldPosition(fp, begin, end, index);
+ }
+ o = table.get("fieldID");
+ if (o != null) {
+ FieldPosition fp = new FieldPosition((Format.Field)
+ lookupField((String)o));
+ verifyFieldPosition(fp, begin, end, index);
+ }
+ }
+
+ private void verifyFieldPosition(FieldPosition fp, int begin, int end,
+ int index) {
+ StringBuffer buffer = new StringBuffer();
+
+ format.format(value, buffer, fp);
+ if (fp.getBeginIndex() != begin) {
+ errln("bogus begin want " + begin + " got " + fp.getBeginIndex() +
+ " for " + fp + " at " + index);
+ }
+ if (fp.getEndIndex() != end) {
+ errln("bogus end want " + end + " got " + fp.getEndIndex() +
+ " for " + fp + " at " + index);
+ }
+ if (!buffer.toString().equals(text)) {
+ errln("Text does not match, want !" + buffer.toString() +
+ "! got !" + text + "!");
+ }
+ }
+
+ public AttributedCharacterIterator create(Hashtable table) {
+ format = (Format)createInstance((String)table.get("class"),
+ ((Vector)table.get("args")).toArray());
+ value = createInstance((String)table.get("valueClass"),
+ ((Vector)table.get("valueArgs")).toArray());
+
+ logln("Created format: " + format + " value " + value);
+ AttributedCharacterIterator aci = format.
+ formatToCharacterIterator(value);
+
+ logln("Obtained Iterator: " + aci);
+ return aci;
+ }
+
+ public Format.Field makeAttribute(String name) {
+ return (Format.Field)lookupField(name);
+ }
+
+ private Object createInstance(String className, Object[] args) {
+ if (className.equals("java.lang.reflect.Array")) {
+ for (int counter = 0; counter < args.length; counter++) {
+ if (args[counter] instanceof Vector) {
+ Vector v = (Vector)args[counter];
+
+ args[counter] = createInstance((String)v.get(0),
+ ((Vector)v.get(1)).toArray());
+ }
+ }
+ return args;
+ }
+ for (int counter = 0; counter < args.length; counter++) {
+ args[counter] = escapeIfNecessary((String)args[counter]);
+ }
+ try {
+ if (className.equals("java.util.concurrent.atomic.AtomicInteger")) {
+ return new AtomicInteger(Integer.valueOf((String)args[0]));
+ } else if (className.equals("java.util.concurrent.atomic.AtomicLong")) {
+ return new AtomicLong(Long.valueOf((String)args[0]));
+ } else {
+ Class klass = lookupClass(className);
+ Constructor cons = klass.getConstructor(
+ new Class[] { String.class });
+ Object value = cons.newInstance(args);
+
+ return value;
+ }
+ } catch (Throwable th) {
+ errln("Error creating instance " + th);
+ return null;
+ }
+ }
+
+ private Class lookupClass(String name) throws ClassNotFoundException {
+ try {
+ Class klass = Class.forName(name);
+
+ return klass;
+ } catch (ClassNotFoundException e1) {}
+
+ try {
+ Class klass = Class.forName("java.lang." + name);
+
+ return klass;
+ } catch (ClassNotFoundException e1) {}
+
+ Class klass = Class.forName("java.text." + name);
+
+ return klass;
+ }
+
+ private Object lookupField(String name) {
+ Throwable error = null;
+
+ try {
+ int dotIndex = name.indexOf('.');
+ Class klass = lookupClass(name.substring(0, dotIndex));
+ String fieldName = name.substring(dotIndex + 1);
+ Field[] fields = klass.getFields();
+
+ for (int counter = fields.length - 1; counter >= 0; counter--) {
+ if (fields[counter].getName().equals(fieldName)) {
+ return fields[counter].get(null);
+ }
+ }
+ } catch (Throwable th) {
+ error = th;
+ }
+ errln("Could not lookup field " + name + " " + error);
+ return null;
+ }
+
+ protected String escapeIfNecessary(String string) {
+ if (string != null) {
+ int index;
+
+ if ((index = string.indexOf("\\u")) != -1) {
+ StringBuffer sb = new StringBuffer(string.substring(0, index));
+
+ sb.append((char)Integer.parseInt(
+ string.substring(index + 2, index + 6), 16));
+ sb.append(string.substring(index + 6));
+ string = sb.toString();
+ }
+ }
+ return string;
+ }
+
+ public Set makeAttributes(Vector names) {
+ HashSet set = new HashSet(Math.max(1, names.size()));
+
+ for (int counter = 0; counter < names.size(); counter++) {
+ set.add(makeAttribute((String)names.get(counter)));
+ }
+ return set;
+ }
+}
diff --git a/test/java/text/Format/common/MessageFormat.Field.ser.txt b/test/java/text/Format/common/MessageFormat.Field.ser.txt
new file mode 100644
index 0000000000..5428b76680
--- /dev/null
+++ b/test/java/text/Format/common/MessageFormat.Field.ser.txt
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2003, 2016, 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.
+#
+
+# Hex dump of a serialized MessageFormat.Field for Bug4769840.
+
+aced00057372001d6a6176612e746578742e4d657373616765466f726d617424
+4669656c646da23d2c7b46bfaa020000787200166a6176612e746578742e466f
+726d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e7465
+78742e417474726962757465644368617261637465724974657261746f722441
+7474726962757465811e7426cd47175c0200014c00046e616d657400124c6a61
+76612f6c616e672f537472696e673b78707400166d6573736167652061726775
+6d656e74206669656c64
diff --git a/test/java/text/Format/common/NumberFormat.Field.ser.txt b/test/java/text/Format/common/NumberFormat.Field.ser.txt
new file mode 100644
index 0000000000..12851638ad
--- /dev/null
+++ b/test/java/text/Format/common/NumberFormat.Field.ser.txt
@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2003, 2016, 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.
+#
+
+# Hex dump of a serialized NumberFormat.Field for Bug4769840.
+
+aced00057372001c6a6176612e746578742e4e756d626572466f726d61742446
+69656c646802a038193ff37a020000787200166a6176612e746578742e466f72
+6d6174244669656c6403d7fbbd383b0f9b0200007872002f6a6176612e746578
+742e417474726962757465644368617261637465724974657261746f72244174
+74726962757465811e7426cd47175c0200014c00046e616d657400124c6a6176
+612f6c616e672f537472696e673b7870740007696e7465676572
diff --git a/test/java/text/Format/common/PParser.java b/test/java/text/Format/common/PParser.java
new file mode 100644
index 0000000000..6ada76b105
--- /dev/null
+++ b/test/java/text/Format/common/PParser.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2000, 2016, 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.io.*;
+import java.util.*;
+
+/*
+ * assignment : key = value;
+ * key : string
+ * value : string | array | dict
+ * nValue : , value
+ * array : ( value nValue )
+ * nAssignment: , assignment|value
+ * dict : { assignment* }
+ * string : "*" or anything but a ,(){}=
+ *
+ * special characters: ,(){}=
+ */
+
+public class PParser {
+ protected static final int OPEN_PAIR = 1;
+ protected static final int CLOSE_PAIR = 2;
+ protected static final int OPEN_ARRAY = 3;
+ protected static final int CLOSE_ARRAY = 4;
+ protected static final int MORE = 5;
+ protected static final int EQUAL = 6;
+ protected static final int STRING = 7;
+ protected static final int WS = 8;
+
+ protected Reader reader;
+ protected boolean bufferedToken;
+ protected StringBuffer stringBuffer = new StringBuffer();
+ protected int lastChar;
+ protected int lastToken;
+ protected int lineNumber;
+ protected int column;
+
+ public PParser() {
+ }
+
+ public Hashtable parse(Reader r) throws IOException {
+ this.reader = r;
+ bufferedToken = false;
+ lineNumber = 0;
+ column = 0;
+ if (getToken() != OPEN_PAIR) {
+ error("No initial open");
+ }
+ return parsePair();
+ }
+
+ protected Object parseValue(int lookAhead) throws IOException {
+ int token;
+
+ if (lookAhead == -1) {
+ token = getToken();
+ } else {
+ token = lookAhead;
+ }
+ switch (token) {
+ case STRING:
+ return stringBuffer.toString();
+ case OPEN_ARRAY:
+ return parseArray();
+ case OPEN_PAIR:
+ return parsePair();
+ default:
+ error("Expecting value");
+ }
+ return null;
+ }
+
+ protected Object parseArray() throws IOException {
+ Vector array = new Vector();
+ int token;
+
+ while ((token = getToken()) != CLOSE_ARRAY) {
+ if (token == MORE) {
+ token = getToken();
+ }
+ if (token != CLOSE_ARRAY) {
+ array.addElement(parseValue(token));
+ }
+ }
+ return array;
+ }
+
+ protected Hashtable parsePair() throws IOException {
+ Hashtable ht = new Hashtable(11);
+ int token;
+
+ while ((token = getToken()) != CLOSE_PAIR) {
+ if (token != STRING) {
+ error("Pair expecting string got");
+ }
+ String key = stringBuffer.toString();
+
+ if (getToken() != EQUAL) {
+ error("Expecting = ");
+ }
+
+ Object value = parseValue(-1);
+ ht.put(key, value);
+ }
+ return ht;
+ }
+
+ protected void ungetToken() {
+ if (bufferedToken) {
+ error("Can not buffer more than one token");
+ }
+ bufferedToken = true;
+ }
+
+ protected int getToken() throws IOException {
+ int token = getToken(false, false);
+
+ return token;
+ }
+
+ protected int getToken(boolean wantsWS, boolean inString)
+ throws IOException {
+ if (bufferedToken) {
+ bufferedToken = false;
+ if (lastToken != WS || wantsWS) {
+ return lastToken;
+ }
+ }
+ while ((lastChar = reader.read()) != -1) {
+ // If a line starts with '#', skip the line.
+ if (column == 0 && lastChar == '#') {
+ while ((lastChar = reader.read()) != -1
+ && lastChar != '\n') {
+ }
+ if (lastChar == -1) {
+ break;
+ }
+ }
+
+ column++;
+ switch(lastChar) {
+ case '\n':
+ lineNumber++;
+ column = 0;
+ case ' ':
+ case '\r':
+ case '\t':
+ if (wantsWS) {
+ lastToken = WS;
+ return WS;
+ }
+ break;
+ case ',':
+ lastToken = MORE;
+ return MORE;
+ case '(':
+ lastToken = OPEN_ARRAY;
+ return OPEN_ARRAY;
+ case ')':
+ lastToken = CLOSE_ARRAY;
+ return CLOSE_ARRAY;
+ case '{':
+ lastToken = OPEN_PAIR;
+ return OPEN_PAIR;
+ case '}':
+ lastToken = CLOSE_PAIR;
+ return CLOSE_PAIR;
+ case '=':
+ lastToken = EQUAL;
+ return EQUAL;
+ case '"':
+ lastToken = STRING;
+ if (!inString) {
+ stringBuffer.setLength(0);
+ while (true) {
+ getToken(true, true);
+ if (lastChar == '"') {
+ lastToken = STRING;
+ return STRING;
+ }
+ stringBuffer.append((char)lastChar);
+ }
+ }
+ return STRING;
+ default:
+ lastToken = STRING;
+ if (!inString) {
+ stringBuffer.setLength(0);
+ stringBuffer.append((char)lastChar);
+ while (getToken(true, true) == STRING) {
+ if (lastChar == '"') {
+ error("Unexpected quote");
+ }
+ stringBuffer.append((char)lastChar);
+ }
+ ungetToken();
+ }
+ return STRING;
+ }
+ }
+ return -1;
+ }
+
+ protected void error(String errorString) {
+ throw new RuntimeException(errorString + " at line " + lineNumber + " column " + column);
+ }
+
+ public static void dump(Object o) {
+ if (o instanceof String) {
+ System.out.print(o);
+ } else if(o instanceof Vector) {
+ Enumeration e = ((Vector)o).elements();
+
+ dump(" (");
+ while (e.hasMoreElements()) {
+ dump(e.nextElement());
+ dump(" -- ");
+ }
+ dump(" )");
+ } else {
+ Hashtable ht = (Hashtable)o;
+ Enumeration e = ht.keys();
+
+ dump(" {");
+ while (e.hasMoreElements()) {
+ Object key = e.nextElement();
+
+ dump(key);
+ dump(" = ");
+ dump(ht.get(key));
+ dump(";");
+ }
+ dump(" }");
+ }
+ }
+
+ public static void main(String[] args) {
+ if (args.length == 0) {
+ System.out.println("need filename");
+ } else {
+ try {
+ FileReader fr = new FileReader(args[0]);
+ PParser parser = new PParser();
+ Hashtable ht = parser.parse(fr);
+
+ dump(ht);
+ System.out.println();
+ }
+ catch (IOException ioe) {
+ System.out.println("Couldn't parse: " + ioe);
+ }
+ }
+ }
+}
diff --git a/test/java/text/Format/common/dateFormat.props b/test/java/text/Format/common/dateFormat.props
new file mode 100644
index 0000000000..22bb9a44d7
--- /dev/null
+++ b/test/java/text/Format/common/dateFormat.props
@@ -0,0 +1,333 @@
+#
+# Copyright (c) 2000, 2016, 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 data for FormatIteratorTest
+
+{
+ tests =
+ (
+ {
+ class = java.text.SimpleDateFormat
+ args = ("M/dd/yy")
+ valueClass = java.util.Date
+ valueArgs = ("7/10/71")
+ }
+ {
+ length = 7
+ text = "7/10/71"
+ 0 = (DateFormat$Field.MONTH)
+ 1 = ()
+ 2 = (DateFormat$Field.DAY_OF_MONTH)
+ 3 = (DateFormat$Field.DAY_OF_MONTH)
+ 4 = ()
+ 5 = (DateFormat$Field.YEAR)
+ 6 = (DateFormat$Field.YEAR)
+ limits = ( { attributes = (DateFormat$Field.MONTH)
+ begin = 0 end = 1}
+ { attributes = ()
+ begin = 1 begin2 = 0 end = 2 end2 = 7}
+ { attributes = (DateFormat$Field.DAY_OF_MONTH)
+ begin = 2 end = 4}
+ { attributes = ()
+ begin = 4 begin2 = 0 end = 5 end2 = 7}
+ { attributes = (DateFormat$Field.YEAR)
+ begin = 5 end = 7}
+ )
+ fieldPositions =
+ (
+ {
+ field = DateFormat.MONTH_FIELD
+ fieldID = DateFormat$Field.MONTH
+ begin = 0 end = 1
+ }
+ {
+ field = DateFormat.DATE_FIELD
+ fieldID = DateFormat$Field.DAY_OF_MONTH
+ begin = 2 end = 4
+ }
+ {
+ field = DateFormat.YEAR_FIELD
+ fieldID = DateFormat$Field.YEAR
+ begin = 5 end = 7
+ }
+ )
+ }
+
+ {
+ class = java.text.SimpleDateFormat
+ args = ("EEEEEEE MMMMMMMMMMMMM yyyy GG")
+ valueClass = java.util.Date
+ valueArgs = ("12/10/2020")
+ }
+ {
+ length = 25
+ text = "Thursday December 2020 AD"
+ 0 = (DateFormat$Field.DAY_OF_WEEK)
+ 1 = (DateFormat$Field.DAY_OF_WEEK)
+ 2 = (DateFormat$Field.DAY_OF_WEEK)
+ 3 = (DateFormat$Field.DAY_OF_WEEK)
+ 4 = (DateFormat$Field.DAY_OF_WEEK)
+ 5 = (DateFormat$Field.DAY_OF_WEEK)
+ 6 = (DateFormat$Field.DAY_OF_WEEK)
+ 7 = (DateFormat$Field.DAY_OF_WEEK)
+ 8 = ()
+ 9 = (DateFormat$Field.MONTH)
+ 10 = (DateFormat$Field.MONTH)
+ 11 = (DateFormat$Field.MONTH)
+ 12 = (DateFormat$Field.MONTH)
+ 13 = (DateFormat$Field.MONTH)
+ 14 = (DateFormat$Field.MONTH)
+ 15 = (DateFormat$Field.MONTH)
+ 16 = (DateFormat$Field.MONTH)
+ 17 = ()
+ 18 = (DateFormat$Field.YEAR)
+ 19 = (DateFormat$Field.YEAR)
+ 20 = (DateFormat$Field.YEAR)
+ 21 = (DateFormat$Field.YEAR)
+ 22 = ()
+ 23 = (DateFormat$Field.ERA)
+ 24 = (DateFormat$Field.ERA)
+ limits = ( { attributes = (DateFormat$Field.DAY_OF_WEEK)
+ begin = 0 end = 8}
+ { attributes = ()
+ begin = 8 begin2 = 0 end = 9 end2 = 25}
+ { attributes = (DateFormat$Field.MONTH)
+ begin = 9 end = 17}
+ { attributes = ()
+ begin = 17 begin2 = 0 end = 18 end2 = 25}
+ { attributes = (DateFormat$Field.YEAR)
+ begin = 18 end = 22}
+ { attributes = ()
+ begin = 22 begin2 = 0 end = 23 end2 = 25}
+ { attributes = (DateFormat$Field.ERA)
+ begin = 23 end = 25}
+ )
+ fieldPositions =
+ (
+ {
+ field = DateFormat.DAY_OF_WEEK_FIELD
+ fieldID = DateFormat$Field.DAY_OF_WEEK
+ begin = 0 end = 8
+ }
+ {
+ field = DateFormat.MONTH_FIELD
+ fieldID = DateFormat$Field.MONTH
+ begin = 9 end = 17
+ }
+ {
+ field = DateFormat.YEAR_FIELD
+ fieldID = DateFormat$Field.YEAR
+ begin = 18 end = 22
+ }
+ {
+ field = DateFormat.ERA_FIELD
+ fieldID = DateFormat$Field.ERA
+ begin = 23 end = 25
+ }
+ )
+ }
+
+ {
+ class = java.text.SimpleDateFormat
+ args = ("h HH:mm:ss:SSS aa")
+ valueClass = java.util.Date
+ valueArgs = ("1/1/2000 2:52:12 PM")
+ }
+ {
+ length = 17
+ text = "2 14:52:12:000 PM"
+ 0 = (DateFormat$Field.HOUR1)
+ 1 = ()
+ 2 = (DateFormat$Field.HOUR_OF_DAY0)
+ 3 = (DateFormat$Field.HOUR_OF_DAY0)
+ 4 = ()
+ 5 = (DateFormat$Field.MINUTE)
+ 6 = (DateFormat$Field.MINUTE)
+ 7 = ()
+ 8 = (DateFormat$Field.SECOND)
+ 9 = (DateFormat$Field.SECOND)
+ 10 = ()
+ 11 = (DateFormat$Field.MILLISECOND)
+ 12 = (DateFormat$Field.MILLISECOND)
+ 13 = (DateFormat$Field.MILLISECOND)
+ 14 = ()
+ 15 = (DateFormat$Field.AM_PM)
+ 16 = (DateFormat$Field.AM_PM)
+ limits = ( { attributes = (DateFormat$Field.HOUR1)
+ begin = 0 end = 1}
+ { attributes = ()
+ begin = 1 begin2 = 0 end = 2 end2 = 17}
+ { attributes = (DateFormat$Field.HOUR_OF_DAY0)
+ begin = 2 end = 4}
+ { attributes = ()
+ begin = 4 begin2 = 0 end = 5 end2 = 17}
+ { attributes = (DateFormat$Field.MINUTE)
+ begin = 5 end = 7}
+ { attributes = ()
+ begin = 7 begin2 = 0 end = 8 end2 = 17}
+ { attributes = (DateFormat$Field.SECOND)
+ begin = 8 end = 10}
+ { attributes = ()
+ begin = 10 begin2 = 0 end = 11 end2 = 17}
+ { attributes = (DateFormat$Field.MILLISECOND)
+ begin = 11 end = 14}
+ { attributes = ()
+ begin = 14 begin2 = 0 end = 15 end2 = 17}
+ { attributes = (DateFormat$Field.AM_PM)
+ begin = 15 end = 17}
+ )
+ fieldPositions =
+ (
+ {
+ field = DateFormat.HOUR1_FIELD
+ fieldID = DateFormat$Field.HOUR1
+ begin = 0 end = 1
+ }
+ {
+ field = DateFormat.HOUR_OF_DAY0_FIELD
+ fieldID = DateFormat$Field.HOUR_OF_DAY0
+ begin = 2 end = 4
+ }
+ {
+ field = DateFormat.MINUTE_FIELD
+ fieldID = DateFormat$Field.MINUTE
+ begin = 5 end = 7
+ }
+ {
+ field = DateFormat.SECOND_FIELD
+ fieldID = DateFormat$Field.SECOND
+ begin = 8 end = 10
+ }
+ {
+ field = DateFormat.MILLISECOND_FIELD
+ fieldID = DateFormat$Field.MILLISECOND
+ begin = 11 end = 14
+ }
+ {
+ field = DateFormat.AM_PM_FIELD
+ fieldID = DateFormat$Field.AM_PM
+ begin = 15 end = 17
+ }
+ )
+ }
+
+
+ {
+ class = java.text.SimpleDateFormat
+ args = ("kk KK DDD FF ww WW zz")
+ valueClass = java.util.Date
+ valueArgs = ("4/26/2031 2:02:52 AM")
+ }
+ {
+ length = 22
+ text = "02 02 116 04 17 04 PDT"
+ 0 = (DateFormat$Field.HOUR_OF_DAY1)
+ 1 = (DateFormat$Field.HOUR_OF_DAY1)
+ 2 = ()
+ 3 = (DateFormat$Field.HOUR0)
+ 4 = (DateFormat$Field.HOUR0)
+ 5 = ()
+ 6 = (DateFormat$Field.DAY_OF_YEAR)
+ 7 = (DateFormat$Field.DAY_OF_YEAR)
+ 8 = (DateFormat$Field.DAY_OF_YEAR)
+ 9 = ()
+ 10 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+ 11 = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+ 12 = ()
+ 13 = (DateFormat$Field.WEEK_OF_YEAR)
+ 14 = (DateFormat$Field.WEEK_OF_YEAR)
+ 15 = ()
+ 16 = (DateFormat$Field.WEEK_OF_MONTH)
+ 17 = (DateFormat$Field.WEEK_OF_MONTH)
+ 18 = ()
+ 19 = (DateFormat$Field.TIME_ZONE)
+ 20 = (DateFormat$Field.TIME_ZONE)
+ 21 = (DateFormat$Field.TIME_ZONE)
+ limits = ( { attributes = (DateFormat$Field.HOUR_OF_DAY1)
+ begin = 0 end = 2}
+ { attributes = ()
+ begin = 2 begin2 = 0 end = 3 end2 = 22}
+ { attributes = (DateFormat$Field.HOUR0)
+ begin = 3 end = 5}
+ { attributes = ()
+ begin = 5 begin2 = 0 end = 6 end2 = 22}
+ { attributes = (DateFormat$Field.DAY_OF_YEAR)
+ begin = 6 end = 9}
+ { attributes = ()
+ begin = 9 begin2 = 0 end = 10 end2 = 22}
+ { attributes = (DateFormat$Field.DAY_OF_WEEK_IN_MONTH)
+ begin = 10 end = 12}
+ { attributes = ()
+ begin = 12 begin2 = 0 end = 13 end2 = 22}
+ { attributes = (DateFormat$Field.WEEK_OF_YEAR)
+ begin = 13 end = 15}
+ { attributes = ()
+ begin = 15 begin2 = 0 end = 16 end2 = 22}
+ { attributes = (DateFormat$Field.WEEK_OF_MONTH)
+ begin = 16 end = 18}
+ { attributes = ()
+ begin = 18 begin2 = 0 end = 19 end2 = 22}
+ { attributes = (DateFormat$Field.TIME_ZONE)
+ begin = 19 end = 22}
+ )
+ fieldPositions =
+ (
+ {
+ field = DateFormat.HOUR_OF_DAY1_FIELD
+ fieldID = DateFormat$Field.HOUR_OF_DAY1
+ begin = 0 end = 2
+ }
+ {
+ field = DateFormat.HOUR0_FIELD
+ fieldID = DateFormat$Field.HOUR0
+ begin = 3 end = 5
+ }
+ {
+ field = DateFormat.DAY_OF_YEAR_FIELD
+ fieldID = DateFormat$Field.DAY_OF_YEAR
+ begin = 6 end = 9
+ }
+ {
+ field = DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD
+ fieldID = DateFormat$Field.DAY_OF_WEEK_IN_MONTH
+ begin = 10 end = 12
+ }
+ {
+ field = DateFormat.WEEK_OF_YEAR_FIELD
+ fieldID = DateFormat$Field.WEEK_OF_YEAR
+ begin = 13 end = 15
+ }
+ {
+ field = DateFormat.WEEK_OF_MONTH_FIELD
+ fieldID = DateFormat$Field.WEEK_OF_MONTH
+ begin = 16 end = 18
+ }
+ {
+ field = DateFormat.TIMEZONE_FIELD
+ fieldID = DateFormat$Field.TIME_ZONE
+ begin = 19 end = 22
+ }
+ )
+ }
+ )
+}
diff --git a/test/java/text/Format/common/decimalFormat.props b/test/java/text/Format/common/decimalFormat.props
new file mode 100644
index 0000000000..e6d9adc797
--- /dev/null
+++ b/test/java/text/Format/common/decimalFormat.props
@@ -0,0 +1,1280 @@
+#
+# Copyright (c) 2000, 2016, 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 data for FormatIteratorTest
+
+{
+ tests =
+ (
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.lang.Integer
+ valueArgs = ("1234567")
+ }
+ {
+ length = 9
+ text = "1,234,567"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ limits = ( { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 end2 = 9}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 9
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 1 end = 2
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###.##")
+ valueClass = java.lang.Float
+ valueArgs = ("567.78")
+ }
+ {
+ length = 6
+ text = "567.78"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 4 = (NumberFormat$Field.FRACTION)
+ 5 = (NumberFormat$Field.FRACTION)
+ limits = ( { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 3 }
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 3 end = 4}
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 4 end = 6}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 3
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 3 end = 4
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 4 end = 6
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("0.#E00")
+ valueClass = java.lang.Float
+ valueArgs = ("1200")
+ }
+ {
+ length = 6
+ text = "1.2E03"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 2 = (NumberFormat$Field.FRACTION)
+ 3 = (NumberFormat$Field.EXPONENT_SYMBOL)
+ 4 = (NumberFormat$Field.EXPONENT)
+ 5 = (NumberFormat$Field.EXPONENT)
+ limits = ( { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.EXPONENT_SYMBOL)
+ begin = 3 end = 4}
+ { attributes = (NumberFormat$Field.EXPONENT)
+ begin = 4 end = 6}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 1
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 1 end = 2
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 2 end = 3
+ }
+ {
+ fieldID = NumberFormat$Field.EXPONENT_SYMBOL
+ begin = 3 end = 4
+ }
+ {
+ fieldID = NumberFormat$Field.EXPONENT
+ begin = 4 end = 6
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("0.#E00")
+ valueClass = java.lang.Float
+ valueArgs = ("-.0012")
+ }
+ {
+ length = 8
+ text = "-1.2E-03"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 3 = (NumberFormat$Field.FRACTION)
+ 4 = (NumberFormat$Field.EXPONENT_SYMBOL)
+ 5 = (NumberFormat$Field.EXPONENT_SIGN)
+ 6 = (NumberFormat$Field.EXPONENT)
+ 7 = (NumberFormat$Field.EXPONENT)
+ limits = ( { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 3 end = 4}
+ { attributes = (NumberFormat$Field.EXPONENT_SYMBOL)
+ begin = 4 end = 5}
+ { attributes = (NumberFormat$Field.EXPONENT_SIGN)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.EXPONENT)
+ begin = 6 end = 8}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 2
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 2 end = 3
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 3 end = 4
+ }
+ {
+ fieldID = NumberFormat$Field.EXPONENT_SYMBOL
+ begin = 4 end = 5
+ }
+ {
+ fieldID = NumberFormat$Field.EXPONENT_SIGN
+ begin = 5 end = 6
+ }
+ {
+ fieldID = NumberFormat$Field.EXPONENT
+ begin = 6 end = 8
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###;(#,###)")
+ valueClass = java.lang.Integer
+ valueArgs = ("-1234")
+ }
+ {
+ length = 7
+ text = "(1,234)"
+ 0 = ()
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = ()
+ limits = ( { attributes = ()
+ begin = 0 end = 1 end2 = 7 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2 end2 = 6}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = ()
+ begin = 6 begin2 = 0 end = 7}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 6
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 2 end = 3
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###;-#,###")
+ valueClass = java.lang.Integer
+ valueArgs = ("-134")
+ }
+ {
+ length = 4
+ text = "-134"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ limits = ( { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 4 }
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 4
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("+#,###")
+ valueClass = java.lang.Integer
+ valueArgs = ("134")
+ }
+ {
+ length = 4
+ text = "+134"
+ 0 = ()
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ limits = ( { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end2 = 4 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 4 }
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 4
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("##.0#%")
+ valueClass = java.lang.Float
+ valueArgs = (".1234")
+ }
+ {
+ length = 6
+ text = "12.34%"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 3 = (NumberFormat$Field.FRACTION)
+ 4 = (NumberFormat$Field.FRACTION)
+ 5 = (NumberFormat$Field.PERCENT)
+ limits = ( { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 2 }
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 2 end = 3 }
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 3 end = 5 }
+ { attributes = (NumberFormat$Field.PERCENT)
+ begin = 5 end = 6 }
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 2
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 2 end = 3
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 3 end = 5
+ }
+ {
+ fieldID = NumberFormat$Field.PERCENT
+ begin = 5 end = 6
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,##.#\u2030")
+ valueClass = java.lang.Float
+ valueArgs = (".1234")
+ }
+ {
+ length = 7
+ text = "1,23.4\u2030"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.GROUPING_SEPARATOR
+ NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 5 = (NumberFormat$Field.FRACTION)
+ 6 = (NumberFormat$Field.PERMILLE)
+ limits = ( { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 end2 = 4 }
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2 }
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2 }
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 4 end = 5 }
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 5 end = 6 }
+ { attributes = (NumberFormat$Field.PERMILLE)
+ begin = 6 end = 7 }
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 4
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 1 end = 2
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 4 end = 5
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 5 end = 6
+ }
+ {
+ fieldID = NumberFormat$Field.PERMILLE
+ begin = 6 end = 7
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("\u00A40,000.00")
+ valueClass = java.lang.Float
+ valueArgs = ("12.51")
+ }
+ {
+ length = 9
+ text = "$0,012.51"
+ 0 = (NumberFormat$Field.CURRENCY)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.GROUPING_SEPARATOR
+ NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 7 = (NumberFormat$Field.FRACTION)
+ 8 = (NumberFormat$Field.FRACTION)
+ limits = ( { attributes = (NumberFormat$Field.CURRENCY)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2 end2 = 6 }
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 3 begin2 = 1 end = 6 }
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 6 end = 7 }
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 7 end = 9 }
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.CURRENCY
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 6
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 2 end = 3
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 6 end = 7
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 7 end = 9
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.math.BigInteger
+ valueArgs = ("-12345678901234567890123456789012345")
+ }
+ {
+ length = 47
+ text = "-12,345,678,901,234,567,890,123,456,789,012,345"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER)
+ 10 = (NumberFormat$Field.INTEGER)
+ 11 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER)
+ 14 = (NumberFormat$Field.INTEGER)
+ 15 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 16 = (NumberFormat$Field.INTEGER)
+ 17 = (NumberFormat$Field.INTEGER)
+ 18 = (NumberFormat$Field.INTEGER)
+ 19 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 20 = (NumberFormat$Field.INTEGER)
+ 21 = (NumberFormat$Field.INTEGER)
+ 22 = (NumberFormat$Field.INTEGER)
+ 23 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 24 = (NumberFormat$Field.INTEGER)
+ 25 = (NumberFormat$Field.INTEGER)
+ 26 = (NumberFormat$Field.INTEGER)
+ 27 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 28 = (NumberFormat$Field.INTEGER)
+ 29 = (NumberFormat$Field.INTEGER)
+ 30 = (NumberFormat$Field.INTEGER)
+ 31 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 32 = (NumberFormat$Field.INTEGER)
+ 33 = (NumberFormat$Field.INTEGER)
+ 34 = (NumberFormat$Field.INTEGER)
+ 35 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 36 = (NumberFormat$Field.INTEGER)
+ 37 = (NumberFormat$Field.INTEGER)
+ 38 = (NumberFormat$Field.INTEGER)
+ 39 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 40 = (NumberFormat$Field.INTEGER)
+ 41 = (NumberFormat$Field.INTEGER)
+ 42 = (NumberFormat$Field.INTEGER)
+ 43 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 44 = (NumberFormat$Field.INTEGER)
+ 45 = (NumberFormat$Field.INTEGER)
+ 46 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 3 end2 = 47 }
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 3 end = 4 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 4 begin2 = 1 end = 7 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 7 end = 8 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 8 begin2 = 1 end = 11 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 11 end = 12 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 12 begin2 = 1 end = 15 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 15 end = 16 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 16 begin2 = 1 end = 19 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 19 end = 20 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 20 begin2 = 1 end = 23 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 23 end = 24 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 24 begin2 = 1 end = 27 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 27 end = 28 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 28 begin2 = 1 end = 31 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 31 end = 32 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 32 begin2 = 1 end = 35 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 35 end = 36 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 36 begin2 = 1 end = 39 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 39 end = 40 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 40 begin2 = 1 end = 43 end2 = 47}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 43 begin2 = 43 end = 44 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 44 begin2 = 1 end = 47}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 47
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###.#####################")
+ valueClass = java.math.BigDecimal
+ valueArgs = ("-123456789012345678901234567890.12345678901234567890")
+ }
+ {
+ length = 60
+ text = "-123,456,789,012,345,678,901,234,567,890.1234567890123456789"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 9 = (NumberFormat$Field.INTEGER)
+ 10 = (NumberFormat$Field.INTEGER)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 13 = (NumberFormat$Field.INTEGER)
+ 14 = (NumberFormat$Field.INTEGER)
+ 15 = (NumberFormat$Field.INTEGER)
+ 16 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 17 = (NumberFormat$Field.INTEGER)
+ 18 = (NumberFormat$Field.INTEGER)
+ 19 = (NumberFormat$Field.INTEGER)
+ 20 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 21 = (NumberFormat$Field.INTEGER)
+ 22 = (NumberFormat$Field.INTEGER)
+ 23 = (NumberFormat$Field.INTEGER)
+ 24 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 25 = (NumberFormat$Field.INTEGER)
+ 26 = (NumberFormat$Field.INTEGER)
+ 27 = (NumberFormat$Field.INTEGER)
+ 28 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 29 = (NumberFormat$Field.INTEGER)
+ 30 = (NumberFormat$Field.INTEGER)
+ 31 = (NumberFormat$Field.INTEGER)
+ 32 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 33 = (NumberFormat$Field.INTEGER)
+ 34 = (NumberFormat$Field.INTEGER)
+ 35 = (NumberFormat$Field.INTEGER)
+ 36 = (NumberFormat$Field.INTEGER NumberFormat$Field.GROUPING_SEPARATOR)
+ 37 = (NumberFormat$Field.INTEGER)
+ 38 = (NumberFormat$Field.INTEGER)
+ 39 = (NumberFormat$Field.INTEGER)
+ 40 = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ 41 = (NumberFormat$Field.FRACTION)
+ 42 = (NumberFormat$Field.FRACTION)
+ 43 = (NumberFormat$Field.FRACTION)
+ 44 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 45 = (NumberFormat$Field.FRACTION)
+ 46 = (NumberFormat$Field.FRACTION)
+ 47 = (NumberFormat$Field.FRACTION)
+ 48 = (NumberFormat$Field.FRACTION)
+ 49 = (NumberFormat$Field.FRACTION)
+ 50 = (NumberFormat$Field.FRACTION)
+ 51 = (NumberFormat$Field.FRACTION)
+ 52 = (NumberFormat$Field.FRACTION)
+ 53 = (NumberFormat$Field.FRACTION)
+ 54 = (NumberFormat$Field.FRACTION)
+ 55 = (NumberFormat$Field.FRACTION)
+ 56 = (NumberFormat$Field.FRACTION)
+ 57 = (NumberFormat$Field.FRACTION)
+ 58 = (NumberFormat$Field.FRACTION)
+ 59 = (NumberFormat$Field.FRACTION)
+ limits = (
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 4 end2 = 40 }
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 4 end = 5 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 5 begin2 = 1 end = 8 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 8 end = 9 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 9 begin2 = 1 end = 12 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 12 end = 13 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 13 begin2 = 1 end = 16 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 16 end = 17 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 17 begin2 = 1 end = 20 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 20 end = 21 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 21 begin2 = 1 end = 24 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 24 end = 25 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 25 begin2 = 1 end = 28 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 28 end = 29 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 29 begin2 = 1 end = 32 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 32 end = 33 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 33 begin2 = 1 end = 36 end2 = 40}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 36 end = 37 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 37 begin2 = 1 end = 40 end2 = 40}
+ { attributes = (NumberFormat$Field.DECIMAL_SEPARATOR)
+ begin = 40 end = 41 }
+ { attributes = (NumberFormat$Field.FRACTION)
+ begin = 41 begin2 = 41 end = 60 }
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ fieldID = NumberFormat$Field.DECIMAL_SEPARATOR
+ begin = 40 end = 41
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 40
+ }
+ {
+ field = NumberFormat.FRACTION_FIELD
+ fieldID = NumberFormat$Field.FRACTION
+ begin = 41 end = 60
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.lang.Long
+ valueArgs = ("9223372036854775807")
+ }
+ {
+ length = 25
+ text = "9,223,372,036,854,775,807"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 10 = (NumberFormat$Field.INTEGER)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 14 = (NumberFormat$Field.INTEGER)
+ 15 = (NumberFormat$Field.INTEGER)
+ 16 = (NumberFormat$Field.INTEGER)
+ 17 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 18 = (NumberFormat$Field.INTEGER)
+ 19 = (NumberFormat$Field.INTEGER)
+ 20 = (NumberFormat$Field.INTEGER)
+ 21 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 22 = (NumberFormat$Field.INTEGER)
+ 23 = (NumberFormat$Field.INTEGER)
+ 24 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 end2 = 25}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 13 end = 14}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 13 end = 14}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 17 end = 18}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 17 end = 18}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 21 end = 22}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 21 end = 22}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 25
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 1 end = 2
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.util.concurrent.atomic.AtomicLong
+ valueArgs = ("9223372036854775807")
+ }
+ {
+ length = 25
+ text = "9,223,372,036,854,775,807"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 10 = (NumberFormat$Field.INTEGER)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 14 = (NumberFormat$Field.INTEGER)
+ 15 = (NumberFormat$Field.INTEGER)
+ 16 = (NumberFormat$Field.INTEGER)
+ 17 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 18 = (NumberFormat$Field.INTEGER)
+ 19 = (NumberFormat$Field.INTEGER)
+ 20 = (NumberFormat$Field.INTEGER)
+ 21 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 22 = (NumberFormat$Field.INTEGER)
+ 23 = (NumberFormat$Field.INTEGER)
+ 24 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 end2 = 25}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 13 end = 14}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 13 end = 14}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 17 end = 18}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 17 end = 18}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 21 end = 22}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 21 end = 22}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 25
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 1 end = 2
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.lang.Long
+ valueArgs = ("-9223372036854775808")
+ }
+ {
+ length = 26
+ text = "-9,223,372,036,854,775,808"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER)
+ 10 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER)
+ 14 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 15 = (NumberFormat$Field.INTEGER)
+ 16 = (NumberFormat$Field.INTEGER)
+ 17 = (NumberFormat$Field.INTEGER)
+ 18 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 19 = (NumberFormat$Field.INTEGER)
+ 20 = (NumberFormat$Field.INTEGER)
+ 21 = (NumberFormat$Field.INTEGER)
+ 22 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 23 = (NumberFormat$Field.INTEGER)
+ 24 = (NumberFormat$Field.INTEGER)
+ 25 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2 end2 = 26}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 14 end = 15}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 14 end = 15}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 18 end = 19}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 18 end = 19}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 22 end = 23}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 22 end = 23}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 26
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 2 end = 3
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.util.concurrent.atomic.AtomicLong
+ valueArgs = ("-9223372036854775808")
+ }
+ {
+ length = 26
+ text = "-9,223,372,036,854,775,808"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER)
+ 10 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER)
+ 14 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 15 = (NumberFormat$Field.INTEGER)
+ 16 = (NumberFormat$Field.INTEGER)
+ 17 = (NumberFormat$Field.INTEGER)
+ 18 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 19 = (NumberFormat$Field.INTEGER)
+ 20 = (NumberFormat$Field.INTEGER)
+ 21 = (NumberFormat$Field.INTEGER)
+ 22 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 23 = (NumberFormat$Field.INTEGER)
+ 24 = (NumberFormat$Field.INTEGER)
+ 25 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2 end2 = 26}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 14 end = 15}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 14 end = 15}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 18 end = 19}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 18 end = 19}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 22 end = 23}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 22 end = 23}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 26
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 2 end = 3
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.util.concurrent.atomic.AtomicInteger
+ valueArgs = ("2147483647")
+ }
+ {
+ length = 13
+ text = "2,147,483,647"
+ 0 = (NumberFormat$Field.INTEGER)
+ 1 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 2 = (NumberFormat$Field.INTEGER)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 6 = (NumberFormat$Field.INTEGER)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 10 = (NumberFormat$Field.INTEGER)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 0 end = 1 end2 = 13}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 1 end = 2}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 5 end = 6}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 9 end = 10}
+ )
+ fieldPositions =
+ (
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 0 end = 13
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 1 end = 2
+ }
+ )
+ }
+
+ {
+ class = java.text.DecimalFormat
+ args = ("#,###")
+ valueClass = java.util.concurrent.atomic.AtomicInteger
+ valueArgs = ("-2147483648")
+ }
+ {
+ length = 14
+ text = "-2,147,483,648"
+ 0 = (NumberFormat$Field.SIGN)
+ 1 = (NumberFormat$Field.INTEGER)
+ 2 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 3 = (NumberFormat$Field.INTEGER)
+ 4 = (NumberFormat$Field.INTEGER)
+ 5 = (NumberFormat$Field.INTEGER)
+ 6 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 7 = (NumberFormat$Field.INTEGER)
+ 8 = (NumberFormat$Field.INTEGER)
+ 9 = (NumberFormat$Field.INTEGER)
+ 10 = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 11 = (NumberFormat$Field.INTEGER)
+ 12 = (NumberFormat$Field.INTEGER)
+ 13 = (NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 0 end = 1 }
+ { attributes = (NumberFormat$Field.INTEGER)
+ begin = 1 end = 2 end2 = 14}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 2 end = 3}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 6 end = 7}
+ { attributes = (NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 10 end = 11}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = NumberFormat$Field.SIGN
+ begin = 0 end = 1
+ }
+ {
+ field = NumberFormat.INTEGER_FIELD
+ fieldID = NumberFormat$Field.INTEGER
+ begin = 1 end = 14
+ }
+ {
+ fieldID = NumberFormat$Field.GROUPING_SEPARATOR
+ begin = 2 end = 3
+ }
+ )
+ }
+ )
+}
diff --git a/test/java/text/Format/common/messageFormat.props b/test/java/text/Format/common/messageFormat.props
new file mode 100644
index 0000000000..c8aaeecfd3
--- /dev/null
+++ b/test/java/text/Format/common/messageFormat.props
@@ -0,0 +1,520 @@
+#
+# Copyright (c) 2000, 2016, 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 data for FormatIteratorTest
+
+{
+ tests =
+ (
+ {
+ class = java.text.MessageFormat
+ args = ("0={0} 1={1}")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ("zero" "one")
+ }
+ {
+ length = 12
+ text = "0=zero 1=one"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT)
+ 3 = (MessageFormat$Field.ARGUMENT)
+ 4 = (MessageFormat$Field.ARGUMENT)
+ 5 = (MessageFormat$Field.ARGUMENT)
+ 6 = ()
+ 7 = ()
+ 8 = ()
+ 9 = (MessageFormat$Field.ARGUMENT)
+ 10 = (MessageFormat$Field.ARGUMENT)
+ 11 = (MessageFormat$Field.ARGUMENT)
+ limits = ( { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 6}
+ { attributes = ()
+ begin = 0 begin2 = 0 end = 2 end2 = 12}
+ { attributes = ()
+ begin = 6 begin2 = 0 end = 9 end2 = 12}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 9 end = 12}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 6
+ }
+ )
+ }
+
+ {
+ class = java.text.MessageFormat
+ args = ("0={0} 1={1} 0={0}")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ("ze" "on")
+ }
+ {
+ length = 14
+ text = "0=ze 1=on 0=ze"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT)
+ 3 = (MessageFormat$Field.ARGUMENT)
+ 4 = ()
+ 5 = ()
+ 6 = ()
+ 7 = (MessageFormat$Field.ARGUMENT)
+ 8 = (MessageFormat$Field.ARGUMENT)
+ 9 = ()
+ 10 = ()
+ 11 = ()
+ 12 = (MessageFormat$Field.ARGUMENT)
+ 13 = (MessageFormat$Field.ARGUMENT)
+ limits = (
+ { attributes = ()
+ begin = 0 end = 2 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 4}
+ { attributes = ()
+ begin = 4 begin2 = 0 end = 7 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 7 end = 9}
+ { attributes = ()
+ begin = 9 begin2 = 0 end = 12 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 12 end = 14}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 4
+ }
+ )
+ }
+
+ {
+ class = java.text.MessageFormat
+ args = ("0={0,date} 1={1,number}")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ((java.util.Date ("5/23/2001")) (Integer ("20122")))
+ }
+ {
+ length = 23
+ text = "0=May 23, 2001 1=20,122"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 5 = (MessageFormat$Field.ARGUMENT)
+ 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 8 = (MessageFormat$Field.ARGUMENT)
+ 9 = (MessageFormat$Field.ARGUMENT)
+ 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 14 = ()
+ 15 = ()
+ 16 = ()
+ 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = ()
+ begin = 0 end = 2 end2 = 23}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 5 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT
+ DateFormat$Field.MONTH)
+ begin = 2 end = 5}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 5 begin2 = 2 end = 6 end2 = 14}
+ { attributes = (DateFormat$Field.DAY_OF_MONTH)
+ begin = 6 end = 8}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 8 begin2 = 2 end = 10 end2 = 14}
+ { attributes = ()
+ begin = 14 begin2 = 0 end = 17 end2 = 23}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 17 end = 19 end2 = 23}
+ { attributes = (MessageFormat$Field.ARGUMENT
+ NumberFormat$Field.INTEGER)
+ begin = 17 end = 19 end2 = 23}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 19 end = 20 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 20 begin2 = 17 end = 23}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 14
+ }
+ )
+ }
+
+ {
+ class = java.text.MessageFormat
+ args = ("0={0,date} 1={1,number}")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ((java.util.Date ("1/22/2003")) (java.math.BigInteger ("12345678901234567890123456789012345")))
+ }
+ {
+ length = 63
+ text = "0=Jan 22, 2003 1=12,345,678,901,234,567,890,123,456,789,012,345"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 5 = (MessageFormat$Field.ARGUMENT)
+ 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 8 = (MessageFormat$Field.ARGUMENT)
+ 9 = (MessageFormat$Field.ARGUMENT)
+ 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 14 = ()
+ 15 = ()
+ 16 = ()
+ 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 48 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 49 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 50 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 51 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 52 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 53 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 54 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 55 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 56 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 57 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 58 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 59 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 60 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 61 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 62 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ limits = (
+ { attributes = ()
+ begin = 0 end = 2 end2 = 63}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 5 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT
+ DateFormat$Field.MONTH)
+ begin = 2 end = 5}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 5 begin2 = 2 end = 6 end2 = 14}
+ { attributes = (DateFormat$Field.DAY_OF_MONTH)
+ begin = 6 end = 8}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 8 begin2 = 2 end = 10 end2 = 14}
+ { attributes = ()
+ begin = 14 begin2 = 0 end = 17 end2 = 63}
+ { attributes = (MessageFormat$Field.ARGUMENT
+ NumberFormat$Field.INTEGER)
+ begin = 17 end = 19 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 19 end = 20 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 20 begin2 = 17 end = 23 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 23 end = 24 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 24 begin2 = 17 end = 27 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 27 end = 28 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 28 begin2 = 17 end = 31 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 31 end = 32 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 32 begin2 = 17 end = 35 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 35 end = 36 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 36 begin2 = 17 end = 39 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 39 end = 40 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 40 begin2 = 17 end = 43 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 43 end = 44 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 44 begin2 = 17 end = 47 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 47 end = 48 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 48 begin2 = 17 end = 51 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 51 end = 52 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 52 begin2 = 17 end = 55 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 55 end = 56 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 56 begin2 = 17 end = 59 end2 = 63}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 59 end = 60 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 60 begin2 = 17 end = 63}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 14
+ }
+ )
+ }
+
+ {
+ class = java.text.MessageFormat
+ args = ("0={0,date} 1={1,number}")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ((java.util.Date ("1/26/2003")) (java.math.BigDecimal ("-12345678901234567890.1239")))
+ }
+ {
+ length = 48
+ text = "0=Jan 26, 2003 1=-12,345,678,901,234,567,890.124"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 3 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 4 = (MessageFormat$Field.ARGUMENT DateFormat$Field.MONTH)
+ 5 = (MessageFormat$Field.ARGUMENT)
+ 6 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 7 = (MessageFormat$Field.ARGUMENT DateFormat$Field.DAY_OF_MONTH)
+ 8 = (MessageFormat$Field.ARGUMENT)
+ 9 = (MessageFormat$Field.ARGUMENT)
+ 10 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 11 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 12 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 13 = (MessageFormat$Field.ARGUMENT DateFormat$Field.YEAR)
+ 14 = ()
+ 15 = ()
+ 16 = ()
+ 17 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.SIGN)
+ 18 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 19 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 20 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 21 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 22 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 23 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 24 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 25 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 26 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 27 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 28 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 29 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 30 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 31 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 32 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 33 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 34 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 35 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 36 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 37 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 38 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 39 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 40 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER
+ NumberFormat$Field.GROUPING_SEPARATOR)
+ 41 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 42 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 43 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.INTEGER)
+ 44 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.DECIMAL_SEPARATOR)
+ 45 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+ 46 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+ 47 = (MessageFormat$Field.ARGUMENT NumberFormat$Field.FRACTION)
+ limits = (
+ { attributes = ()
+ begin = 0 end = 2 end2 = 48}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 5 end2 = 14}
+ { attributes = (MessageFormat$Field.ARGUMENT
+ DateFormat$Field.MONTH)
+ begin = 2 end = 5}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 5 begin2 = 2 end = 6 end2 = 14}
+ { attributes = (DateFormat$Field.DAY_OF_MONTH)
+ begin = 6 end = 8}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 8 begin2 = 2 end = 10 end2 = 14}
+ { attributes = ()
+ begin = 14 begin2 = 0 end = 17 end2 = 48}
+
+ { attributes = (NumberFormat$Field.SIGN)
+ begin = 17 end = 18 }
+ { attributes = (MessageFormat$Field.ARGUMENT
+ NumberFormat$Field.INTEGER)
+ begin = 18 end = 20 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 20 end = 21 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 21 begin2 = 18 end = 24 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 24 end = 25 }
+
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 25 begin2 = 18 end = 28 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 28 end = 29 }
+
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 29 begin2 = 18 end = 32 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 32 end = 33 }
+
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 33 begin2 = 18 end = 36 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 36 end = 37 }
+
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 37 begin2 = 18 end = 40 end2 = 44}
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 40 end = 41 }
+ { attributes = (NumberFormat$Field.INTEGER
+ MessageFormat$Field.ARGUMENT)
+ begin = 41 begin2 = 18 end = 44 end2 = 44}
+
+ { attributes = (NumberFormat$Field.GROUPING_SEPARATOR)
+ begin = 44 begin2 = 41 end = 45 end2 = 48}
+
+ { attributes = (NumberFormat$Field.FRACTION
+ MessageFormat$Field.ARGUMENT)
+ begin = 45 end = 48}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 14
+ }
+ )
+ }
+
+ {
+ class = java.text.MessageFormat
+ args = ("0={0,choice,-1#neg| 0#zero | 1#more}xx")
+ valueClass = java.lang.reflect.Array
+ valueArgs = ((Integer ("-11")))
+ }
+ {
+ length = 7
+ text = "0=negxx"
+ 0 = ()
+ 1 = ()
+ 2 = (MessageFormat$Field.ARGUMENT)
+ 3 = (MessageFormat$Field.ARGUMENT)
+ 4 = (MessageFormat$Field.ARGUMENT)
+ 5 = ()
+ 6 = ()
+ limits = (
+ { attributes = ()
+ begin = 0 end = 2 end2 = 7}
+ { attributes = (MessageFormat$Field.ARGUMENT)
+ begin = 2 end = 5}
+ { attributes = ()
+ begin = 5 begin2 = 0 end = 7}
+ )
+ fieldPositions =
+ (
+ {
+ fieldID = MessageFormat$Field.ARGUMENT
+ begin = 2 end = 5
+ }
+ )
+ }
+ )
+}
+
diff --git a/test/java/text/testlib/HexDumpReader.java b/test/java/text/testlib/HexDumpReader.java
new file mode 100644
index 0000000000..7cb3ec00ae
--- /dev/null
+++ b/test/java/text/testlib/HexDumpReader.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2016, 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.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * HexDumpReader provides utility methods to read a hex dump text file
+ * and convert to an InputStream. The format supported by the methods
+ * can be generated by the following command.
+ *
+ * $ od -vw -t x1 foo | sed -r -e 's/^[0-9]+ ?//' -e 's/ //g' -e '/^$/d'
+ */
+public class HexDumpReader {
+ public static InputStream getStreamFromHexDump(String fileName) {
+ return getStreamFromHexDump(new File(System.getProperty("test.src", "."),
+ fileName));
+ }
+
+ public static InputStream getStreamFromHexDump(File hexFile) {
+ ByteArrayBuilder bab = new ByteArrayBuilder();
+ int lineNo = 0;
+ try (BufferedReader reader
+ = new BufferedReader(new InputStreamReader(new FileInputStream(hexFile),
+ "us-ascii"))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lineNo++;
+ line = line.trim();
+ // Skip blank and comment lines.
+ if (line.length() == 0) {
+ continue;
+ }
+ int x = line.indexOf('#');
+ if (x == 0) {
+ continue;
+ }
+ if (x > 0) {
+ line = line.substring(0, x).trim();
+ }
+ int len = line.length();
+ for (int i = 0; i < len; i += 2) {
+ bab.put((byte)Integer.parseInt(line.substring(i, i + 2), 16));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(hexFile.getName() + ":error:" + lineNo + ": " + e, e);
+ }
+ return new ByteArrayInputStream(bab.toArray());
+ }
+
+
+ private static class ByteArrayBuilder {
+ private static final int BUFFER_SIZE = 4096;
+
+ private int size;
+ private List<byte[]> bytes;
+ private byte[] current;
+ private int offset;
+
+ ByteArrayBuilder() {
+ bytes = new ArrayList<>();
+ current = new byte[BUFFER_SIZE];
+ }
+
+ void put(byte b) {
+ if (offset == BUFFER_SIZE) {
+ bytes.add(current);
+ current = new byte[BUFFER_SIZE];
+ offset = 0;
+ }
+ current[offset++] = b;
+ size++;
+ }
+
+ byte[] toArray() {
+ byte[] buf = new byte[size];
+ int ptr = 0;
+ for (byte[] ba : bytes) {
+ System.arraycopy(ba, 0, buf, ptr, ba.length);
+ ptr += ba.length;
+ }
+ System.arraycopy(current, 0, buf, ptr, offset);
+ assert ptr + offset == size;
+ return buf;
+ }
+ }
+
+}
diff --git a/test/java/text/testlib/IntlTest.java b/test/java/text/testlib/IntlTest.java
new file mode 100644
index 0000000000..d8ae8572f3
--- /dev/null
+++ b/test/java/text/testlib/IntlTest.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 1998, 2016, 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.io.IOException;
+import java.io.PrintWriter;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.LinkedHashMap;
+import java.util.List;
+
+/**
+ * IntlTest is a base class for tests that can be run conveniently from
+ * the command line as well as under the Java test harness.
+ * <p>
+ * Sub-classes implement a set of public void methods named "Test*" or
+ * "test*" with no arguments. Each of these methods performs some
+ * test. Test methods should indicate errors by calling either err() or
+ * errln(). This will increment the errorCount field and may optionally
+ * print a message to the log. Debugging information may also be added to
+ * the log via the log and logln methods. These methods will add their
+ * arguments to the log only if the test is being run in verbose mode.
+ */
+public abstract class IntlTest {
+
+ //------------------------------------------------------------------------
+ // Everything below here is boilerplate code that makes it possible
+ // to add a new test by simply adding a method to an existing class.
+ //------------------------------------------------------------------------
+
+ protected IntlTest() {
+ // Populate testMethods with all the test methods.
+ Method[] methods = getClass().getDeclaredMethods();
+ for (Method method : methods) {
+ if (Modifier.isPublic(method.getModifiers())
+ && method.getReturnType() == void.class
+ && method.getParameterCount() == 0) {
+ String name = method.getName();
+ if (name.length() > 4) {
+ if (name.startsWith("Test") || name.startsWith("test")) {
+ testMethods.put(name, method);
+ }
+ }
+ }
+ }
+ }
+
+ protected void run(String[] args) throws Exception
+ {
+ // Set up the log and reference streams. We use PrintWriters in order to
+ // take advantage of character conversion. The JavaEsc converter will
+ // convert Unicode outside the ASCII range to Java's \\uxxxx notation.
+ log = new PrintWriter(System.out, true);
+
+ // Parse the test arguments. They can be either the flag
+ // "-verbose" or names of test methods. Create a list of
+ // tests to be run.
+ List<Method> testsToRun = new ArrayList<>(args.length);
+ for (String arg : args) {
+ switch (arg) {
+ case "-verbose":
+ verbose = true;
+ break;
+ case "-prompt":
+ prompt = true;
+ break;
+ case "-nothrow":
+ nothrow = true;
+ break;
+ default:
+ Method m = testMethods.get(arg);
+ if (m == null) {
+ System.out.println("Method " + arg + ": not found");
+ usage();
+ return;
+ }
+ testsToRun.add(m);
+ break;
+ }
+ }
+
+ // If no test method names were given explicitly, run them all.
+ if (testsToRun.isEmpty()) {
+ testsToRun.addAll(testMethods.values());
+ }
+
+ System.out.println(getClass().getName() + " {");
+ indentLevel++;
+
+ // Run the list of tests given in the test arguments
+ for (Method testMethod : testsToRun) {
+ int oldCount = errorCount;
+
+ writeTestName(testMethod.getName());
+
+ try {
+ testMethod.invoke(this, new Object[0]);
+ } catch (IllegalAccessException e) {
+ errln("Can't acces test method " + testMethod.getName());
+ } catch (InvocationTargetException e) {
+ errln("Uncaught exception thrown in test method "
+ + testMethod.getName());
+ e.getTargetException().printStackTrace(this.log);
+ }
+ writeTestResult(errorCount - oldCount);
+ }
+ indentLevel--;
+ writeTestResult(errorCount);
+
+ if (prompt) {
+ System.out.println("Hit RETURN to exit...");
+ try {
+ System.in.read();
+ } catch (IOException e) {
+ System.out.println("Exception: " + e.toString() + e.getMessage());
+ }
+ }
+ if (nothrow) {
+ System.exit(errorCount);
+ }
+ }
+
+ /**
+ * Adds the given message to the log if we are in verbose mode.
+ */
+ protected void log(String message) {
+ logImpl(message, false);
+ }
+
+ protected void logln(String message) {
+ logImpl(message, true);
+ }
+
+ protected void logln() {
+ logImpl(null, true);
+ }
+
+ private void logImpl(String message, boolean newline) {
+ if (verbose) {
+ if (message != null) {
+ indent(indentLevel + 1);
+ log.print(message);
+ }
+ if (newline) {
+ log.println();
+ }
+ }
+ }
+
+ protected void err(String message) {
+ errImpl(message, false);
+ }
+
+ protected void errln(String message) {
+ errImpl(message, true);
+ }
+
+ private void errImpl(String message, boolean newline) {
+ errorCount++;
+ indent(indentLevel + 1);
+ log.print(message);
+ if (newline) {
+ log.println();
+ }
+ log.flush();
+
+ if (!nothrow) {
+ throw new RuntimeException(message);
+ }
+ }
+
+ protected int getErrorCount() {
+ return errorCount;
+ }
+
+ protected void writeTestName(String testName) {
+ indent(indentLevel);
+ log.print(testName);
+ log.flush();
+ needLineFeed = true;
+ }
+
+ protected void writeTestResult(int count) {
+ if (!needLineFeed) {
+ indent(indentLevel);
+ log.print("}");
+ }
+ needLineFeed = false;
+
+ if (count != 0) {
+ log.println(" FAILED");
+ } else {
+ log.println(" Passed");
+ }
+ }
+
+ /*
+ * Returns a spece-delimited hex String.
+ */
+ protected static String toHexString(String s) {
+ StringBuilder sb = new StringBuilder(" ");
+
+ for (int i = 0; i < s.length(); i++) {
+ sb.append(Integer.toHexString(s.charAt(i)));
+ sb.append(' ');
+ }
+
+ return sb.toString();
+ }
+
+ private void indent(int distance) {
+ if (needLineFeed) {
+ log.println(" {");
+ needLineFeed = false;
+ }
+ log.print(SPACES.substring(0, distance * 2));
+ }
+
+ /**
+ * Print a usage message for this test class.
+ */
+ void usage() {
+ System.out.println(getClass().getName() +
+ ": [-verbose] [-nothrow] [-prompt] [test names]");
+
+ System.out.println(" Available test names:");
+ for (String methodName : testMethods.keySet()) {
+ System.out.println("\t" + methodName);
+ }
+ }
+
+ private boolean prompt;
+ private boolean nothrow;
+ protected boolean verbose;
+
+ private PrintWriter log;
+ private int indentLevel;
+ private boolean needLineFeed;
+ private int errorCount;
+
+ private final Map<String, Method> testMethods = new LinkedHashMap<>();
+
+ private static final String SPACES = " ";
+}
diff --git a/test/java/time/test/java/time/format/TestNonIsoFormatter.java b/test/java/time/test/java/time/format/TestNonIsoFormatter.java
index 240443f8f3..4d033b2b4d 100644
--- a/test/java/time/test/java/time/format/TestNonIsoFormatter.java
+++ b/test/java/time/test/java/time/format/TestNonIsoFormatter.java
@@ -190,7 +190,7 @@ public class TestNonIsoFormatter {
String mdStr = "-01-01";
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("GGGG y-M-d")
- .toFormatter()
+ .toFormatter(Locale.ROOT)
.withChronology(chrono);
DateTimeFormatter dtfLenient = dtf.withResolverStyle(ResolverStyle.LENIENT);
assertEquals(LocalDate.parse(lenient+mdStr, dtfLenient), LocalDate.parse(strict+mdStr, dtf));
diff --git a/test/java/util/Calendar/BuddhistCalendarTest.java b/test/java/util/Calendar/BuddhistCalendarTest.java
new file mode 100644
index 0000000000..8d6a5fc346
--- /dev/null
+++ b/test/java/util/Calendar/BuddhistCalendarTest.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4817812 4847186 4956227 4956479
+ * @summary Confirm that BuddhistCalendar's add(), roll() and toString() work correctly with Buddhist Era years.
+ */
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import static java.util.Calendar.*;
+
+public class BuddhistCalendarTest {
+
+ private static final Locale THAI_LOCALE = new Locale("th", "TH");
+
+ public static void main(String[] args) {
+ testAddRoll();
+ testToString();
+ testException();
+ testLeastMax();
+ }
+
+ /**
+ * 4817812
+ */
+ static void testAddRoll() {
+ Calendar cal;
+ int base, year;
+
+ /*
+ * Test: BuddhistCalendar.add(YEAR)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.add(YEAR, 1);
+ year = cal.get(YEAR);
+ check(year, base+1, "add(+YEAR)");
+
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.add(YEAR, -3);
+ year = cal.get(YEAR);
+ check(year, base-3, "add(-YEAR)");
+
+ /*
+ * Test BuddhistCalendar.add(MONTH)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.set(MONTH, DECEMBER);
+ cal.add(MONTH, 2);
+ year = cal.get(YEAR);
+ check(year, base+1, "add(+MONTH)");
+
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.set(MONTH, FEBRUARY);
+ cal.add(MONTH, -4);
+ year = cal.get(YEAR);
+ check(year, base-1, "add(-MONTH)");
+
+ /*
+ * Test BuddhistCalendar.roll(YEAR)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.roll(YEAR, 2);
+ year = cal.get(YEAR);
+ check(year, base+2, "roll(+YEAR)");
+
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.roll(YEAR, -4);
+ year = cal.get(YEAR);
+ check(year, base-4, "roll(-YEAR)");
+
+ /*
+ * Test BuddhistCalendar.roll(WEEK_OF_YEAR)
+ */
+ cal = getBuddhistCalendar();
+ cal.set(YEAR, 2543); // A.D.2000
+ cal.set(MONTH, DECEMBER);
+ cal.set(DATE, 31);
+ base = cal.get(YEAR);
+ check(base, 2543, "roll(+WEEK_OF_YEAR)");
+ cal.roll(WEEK_OF_YEAR, 10);
+ year = cal.get(YEAR);
+ check(year, base, "roll(+WEEK_OF_YEAR)");
+
+ cal = getBuddhistCalendar();
+ cal.set(YEAR, 2543); // A.D.2000
+ cal.set(MONTH, JANUARY);
+ cal.set(DATE, 1);
+ base = cal.get(YEAR);
+ check(base, 2543, "roll(+WEEK_OF_YEAR)");
+ cal.roll(WEEK_OF_YEAR, -10);
+ year = cal.get(YEAR);
+ check(year, base, "roll(-WEEK_OF_YEAR)");
+
+ /*
+ * Test Calendar.set(year, month, date)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.set(3001, APRIL, 10);
+ year = cal.get(YEAR);
+ check(year, 3001, "set(year, month, date)");
+
+ /*
+ * Test Calendar.set(year, month, date, hour, minute)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.set(3020, MAY, 20, 9, 10);
+ year = cal.get(YEAR);
+ check(year, 3020, "set(year, month, date, hour, minute)");
+
+ /*
+ * Test Calendar.set(year, month, date, hour, minute, second)
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ cal.set(3120, MAY, 20, 9, 10, 52);
+ year = cal.get(YEAR);
+ check(year, 3120, "set(year, month, date, hour, minute, second)");
+
+ /*
+ * Test BuddhistCalendar.getActualMaximum(YEAR);
+ * set(YEAR)/get(YEAR) in this method doesn't affect the real
+ * YEAR value because a clone is used with set()&get().
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ int limit = cal.getActualMaximum(YEAR);
+ year = cal.get(YEAR);
+ check(year, base, "BuddhistCalendar.getActualMaximum(YEAR)");
+
+ /*
+ * Test BuddhistCalendar.getActualMinimum(YEAR);
+ * This doesn't call set(YEAR) nor get(YEAR), though.
+ */
+ cal = getBuddhistCalendar();
+ base = cal.get(YEAR);
+ limit = cal.getActualMinimum(YEAR);
+ year = cal.get(YEAR);
+ check(year, base, "BuddhistCalendar.getActualMinimum(YEAR)");
+ }
+
+ /**
+ * 4847186: BuddhistCalendar: toString() returns Gregorian year
+ */
+ static void testToString() {
+ Calendar cal = getBuddhistCalendar();
+ int year = cal.get(YEAR);
+ String s = cal.toString();
+ String y = s.replaceAll(".+,YEAR=(\\d+),.+", "$1");
+ if (Integer.parseInt(y) != year) {
+ throw new RuntimeException("toString(): wrong year value: got " + y
+ + ", expected " + year);
+ }
+ }
+
+ /**
+ * 4956479: BuddhistCalendar methods may return wrong values after exception
+ */
+ static void testException() {
+ Calendar cal = getBuddhistCalendar();
+ int year = cal.get(YEAR);
+ boolean exceptionOccurred = false;
+ try {
+ cal.add(100, +1); // cause exception
+ } catch (Exception e) {
+ exceptionOccurred = true;
+ }
+ if (!exceptionOccurred) {
+ throw new RuntimeException("testException: test case failed: no exception thrown");
+ }
+ int year2 = cal.get(YEAR);
+ if (year2 != year) {
+ throw new RuntimeException("wrong year value after exception: got " + year2
+ + ", expected " + year);
+ }
+ }
+
+ /**
+ * 4956227: getLeastMaximum(WEEK_OF_MONTH) return diff. val. for Greg. and Buddhist Calendar
+ */
+ static void testLeastMax() {
+ Calendar bc = getBuddhistCalendar();
+ // Specify THAI_LOCALE to get the same params for WEEK
+ // calculations (6904680).
+ Calendar gc = new GregorianCalendar(THAI_LOCALE);
+ for (int f = 0; f < Calendar.FIELD_COUNT; f++) {
+ if (f == ERA || f == YEAR) {
+ continue;
+ }
+ int bn = bc.getLeastMaximum(f);
+ int gn = gc.getLeastMaximum(f);
+ if (bn != gn) {
+ throw new RuntimeException("inconsistent Least Max value for " + Koyomi.getFieldName(f)
+ + ": Buddhist=" + bn
+ + ": Gregorian=" + gn);
+ }
+ }
+ }
+
+ /**
+ * @return a BuddhistCalendar
+ */
+ static Calendar getBuddhistCalendar() {
+ return Calendar.getInstance(THAI_LOCALE);
+ }
+
+ static void check(int got, int expected, String s) {
+ if (got != expected) {
+ throw new RuntimeException("Failed: " +
+ s + ": got:" + got + ", expected:" + expected);
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug4302966.java b/test/java/util/Calendar/Bug4302966.java
new file mode 100644
index 0000000000..6c3b9c3d60
--- /dev/null
+++ b/test/java/util/Calendar/Bug4302966.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4302966
+ * @summary In Czech Republic first day of week is Monday not Sunday
+ */
+
+import java.util.Calendar;
+import java.util.Locale;
+
+public class Bug4302966 {
+
+ public static void main(String[] args) {
+ Calendar czechCalendar = Calendar.getInstance(new Locale("cs"));
+ int firstDayOfWeek = czechCalendar.getFirstDayOfWeek();
+ if (firstDayOfWeek != Calendar.MONDAY) {
+ throw new RuntimeException();
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug4766302.java b/test/java/util/Calendar/Bug4766302.java
new file mode 100644
index 0000000000..42df92b7e1
--- /dev/null
+++ b/test/java/util/Calendar/Bug4766302.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4766302
+ * @summary Make sure that computeTime call doesn't reset the isTimeSet value.
+ */
+
+import java.util.GregorianCalendar;
+
+public class Bug4766302 {
+
+ static class MyCalendar extends GregorianCalendar {
+ boolean isTimeStillSet() {
+ return isTimeSet;
+ }
+
+ protected void computeTime() {
+ super.computeTime();
+ }
+ }
+
+ public static void main(String[] args) {
+ MyCalendar cal = new MyCalendar();
+ cal.computeTime();
+ if (!cal.isTimeStillSet()) {
+ throw new RuntimeException("computeTime() call reset isTimeSet.");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug4851640.java b/test/java/util/Calendar/Bug4851640.java
new file mode 100644
index 0000000000..4f5add3767
--- /dev/null
+++ b/test/java/util/Calendar/Bug4851640.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4851640
+ * @summary Make sure not to set UNSET fields to COMPUTED after time calculation.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.*;
+
+public class Bug4851640 {
+
+ public static void main(String args[]) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.clear();
+ cal.set(YEAR, 2003);
+ long t = cal.getTime().getTime();
+
+ // For the time calculation, the MONTH and DAY_OF_MONTH fields
+ // (with the default values) have been used for determining
+ // the date. However, both the MONTH and DAY_OF_MONTH fields
+ // should be kept UNSET after the time calculation.
+ if (cal.isSet(MONTH) || cal.isSet(DAY_OF_MONTH)) {
+ throw new RuntimeException("After getTime(): MONTH field=" + cal.isSet(MONTH)
+ + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH));
+ }
+
+ // After calling get() for any field, all field values are
+ // recalculated and their field states are set to
+ // COMPUTED. isSet() must return true.
+ int y = cal.get(YEAR);
+ if (!(cal.isSet(MONTH) && cal.isSet(DAY_OF_MONTH))) {
+ throw new RuntimeException("After get(): MONTH field=" + cal.isSet(MONTH)
+ + ", DAY_OF_MONTH field=" + cal.isSet(DAY_OF_MONTH));
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug4958050.java b/test/java/util/Calendar/Bug4958050.java
new file mode 100644
index 0000000000..dfd627cda6
--- /dev/null
+++ b/test/java/util/Calendar/Bug4958050.java
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4958050
+ * @summary Make sure that add() and roll() handle time zone offset changes (both raw and DST) correctly.
+ */
+
+import java.util.Locale;
+import java.util.TimeZone;
+import static java.util.Calendar.*;
+
+public class Bug4958050 {
+ static int errorCount = 0;
+
+ public static void main(String[] args) {
+ // All the test cases depend on historical GMT offset changes
+ // of Asia/Novosibirsk.
+ Koyomi cal = new Koyomi(TimeZone.getTimeZone("Asia/Novosibirsk"), Locale.US);
+ System.out.println("Time zone = " + cal.getTimeZone().getID());
+
+ // Test the week fields
+ int[] weekFields = { WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_WEEK_IN_MONTH };
+ for (int i = 0; i < weekFields.length; i++) {
+ int field = weekFields[i];
+ // add()
+ cal.clear();
+ cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
+ cal.add(weekFields[i], +1);
+ if (!cal.checkDate(1919, DECEMBER, 14)) {
+ error("1919/12/07: add("+cal.getFieldName(weekFields[i])+", +1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1930, JUNE, 21-7);
+ cal.add(weekFields[i], +1);
+ if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+ error("1930/6/14: add("+cal.getFieldName(weekFields[i])+", +1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+
+ // roll()
+ cal.clear();
+ cal.set(1919, DECEMBER, 14-7, 23, 50, 00);
+ cal.roll(weekFields[i], +1);
+ if (!cal.checkDate(1919, DECEMBER, 14)) {
+ error("1919/12/07: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1930, JUNE, 21-7);
+ cal.roll(weekFields[i], +1);
+ if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+ error("1930/6/14: roll("+cal.getFieldName(weekFields[i])+", +1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+ }
+
+ // Test the day fields
+ int[] dayFields = { DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK };
+ for (int i = 0; i < dayFields.length; i++) {
+ int field = dayFields[i];
+ // add()
+ cal.clear();
+ cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+ cal.add(field, +1);
+ if (!cal.checkDate(1919, DECEMBER, 14)) {
+ error("1919/12/13: add("+cal.getFieldName(field)+", +1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1919, DECEMBER, 14, 00, 00, 00);
+ cal.add(field, -1);
+ if (!cal.checkDate(1919, DECEMBER, 13)) {
+ error("1919/12/14: add("+cal.getFieldName(field)+", -1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1930, JUNE, 21-1);
+ cal.add(field, +1);
+ if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+ error("1930/6/20: add("+cal.getFieldName(field)+", +1)\n"
+ + cal.getMessage() + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1930, JUNE, 21, 01, 00, 00);
+ cal.add(field, -1);
+ if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
+ error("1930/6/21: add("+cal.getFieldName(field)+", -1)\n"
+ + cal.getMessage()+" " + cal.toDateTimeString());
+ }
+
+ // roll()
+ cal.clear();
+ cal.set(1930, JUNE, 21-1);
+ int amount = +1;
+ if (field == DAY_OF_WEEK) {
+ amount += 700;
+ }
+ cal.roll(field, amount);
+ if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+ error("1930/6/20: roll("+cal.getFieldName(field)+", +"+amount+")\n"
+ + cal.getMessage() + " " + cal.toDateTimeString());
+ }
+ cal.clear();
+ cal.set(1930, JUNE, 21, 01, 00, 00);
+ amount = -1;
+ if (field == DAY_OF_WEEK) {
+ amount -= 700;
+ }
+ cal.roll(field, amount);
+ if (!cal.checkDateTime(1930, JUNE, 20, 01, 00, 00, 000)) {
+ error("1930/6/21: roll("+cal.getFieldName(field)+", "+amount+")\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+ }
+
+ // Test the AM_PM field
+ // add()
+ cal.clear();
+ cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+ cal.add(AM_PM, +1);
+ if (!cal.checkDate(1919, DECEMBER, 14)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1919/12/13: add(AM_PM, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21-1, 12, 00, 00);
+ cal.add(AM_PM, +1);
+ if (!cal.checkDate(1930, JUNE, 21)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1930/6/20: add(AM_PM, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21-2, 12, 00, 00);
+ cal.add(AM_PM, +3);
+ if (!cal.checkDate(1930, JUNE, 21)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1930/6/10: add(AM_PM, +3)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1919, DECEMBER, 14, 11, 50, 00);
+ cal.add(AM_PM, -1);
+ if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23, 50, 00, 000)
+ || !cal.checkFieldValue(AM_PM, PM)) {
+ error("1919/12/14 11:50:00: add(AM_PM, -1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21, 01, 00, 00);
+ cal.add(AM_PM, -1);
+ if (!cal.checkDateTime(1930, JUNE, 21-1, 01+12, 00, 00, 000)
+ || !cal.checkFieldValue(AM_PM, PM)) {
+ error("1930/6/20: add(AM_PM, -1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21, 01, 00, 00);
+ cal.add(AM_PM, -3);
+ if (!cal.checkDateTime(1930, JUNE, 21-2, 01+12, 00, 00, 000)
+ || !cal.checkFieldValue(AM_PM, PM)) {
+ error("1930/6/10: add(AM_PM, -3)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ // roll() (should NOT change the date)
+ cal.clear();
+ cal.set(1919, DECEMBER, 14-1, 23, 50, 00);
+ cal.roll(AM_PM, +1);
+ if (!cal.checkDateTime(1919, DECEMBER, 14-1, 23-12, 50, 00, 000)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1919/12/13: roll(AM_PM, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21-1, 12, 00, 00);
+ cal.roll(AM_PM, +1);
+ if (!cal.checkDateTime(1930, JUNE, 21-1, 12-12, 00, 00, 000)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1930/6/20: roll(AM_PM, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ cal.clear();
+ cal.set(1930, JUNE, 21-2, 12, 00, 00);
+ cal.roll(AM_PM, +3);
+ if (!cal.checkDateTime(1930, JUNE, 21-2, 12-12, 00, 00, 000)
+ || !cal.checkFieldValue(AM_PM, AM)) {
+ error("1930/6/10: roll(AM_PM, +3)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ // Test the HOUR_OF_DAY field
+ // add()
+ cal.clear();
+ cal.set(1930, JUNE, 20, 23, 00, 00);
+ cal.add(HOUR_OF_DAY, +1);
+ if (!cal.checkDateTime(1930, JUNE, 21, 01, 00, 00, 000)) {
+ error("1930/6/20 23:00:00: add(HOUR_OF_DAY, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ // roll() (should NOT change the date)
+ cal.clear();
+ cal.set(1930, JUNE, 20, 23, 00, 00);
+ cal.roll(HOUR_OF_DAY, +1);
+ if (!cal.checkDateTime(1930, JUNE, 20, 00, 00, 00, 000)) {
+ error("1930/6/20 23:00:00: roll(HOUR_OF_DAY, +1)\n"
+ + cal.getMessage()+" "+cal.toDateTimeString());
+ }
+
+ checkErrors();
+ }
+
+ static void error(String s) {
+ System.out.println(s);
+ errorCount++;
+ }
+
+ static void checkErrors() {
+ if (errorCount > 0) {
+ throw new RuntimeException("Failed: " + errorCount + " error(s)");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug5078053.java b/test/java/util/Calendar/Bug5078053.java
new file mode 100644
index 0000000000..c6bb25bcf8
--- /dev/null
+++ b/test/java/util/Calendar/Bug5078053.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2004, 2016, 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 5078053
+ * @summary Make sure that Calendar.complete() normalizes stamp[] to
+ * COMPUTED. This can be observed through add() and roll().
+ */
+
+import java.util.TimeZone;
+import static java.util.Calendar.*;
+
+public class Bug5078053 {
+ static int errorCount = 0;
+
+ public static void main(String[] args) {
+ TimeZone defaultTz = TimeZone.getDefault();
+
+ try {
+ TimeZone tz = TimeZone.getTimeZone("Australia/Adelaide");
+ TimeZone.setDefault(tz);
+ Koyomi cal = new Koyomi();
+ cal.setFirstDayOfWeek(2);
+ cal.setMinimalDaysInFirstWeek(4);
+
+ // test roll()
+ cal.clear();
+ // 2002-01-01T00:00:00 in Australia/Adelaide
+ cal.setTimeInMillis(1009805400000L);
+ System.out.println(cal.getTime());
+ // The following set calls shouldn't affect roll() and add()
+ cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK));
+ cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR));
+ cal.getTime();
+ cal.roll(MONTH, +1);
+ System.out.println("roll: " + cal.getTime());
+ if (!cal.checkDate(2002, FEBRUARY, 1)) {
+ error("roll(MONTH, +1): " + cal.getMessage());
+ }
+ cal.roll(MONTH, -1);
+ if (!cal.checkDate(2002, JANUARY, 1)) {
+ error("roll(MONTH, -1): " + cal.getMessage());
+ }
+
+ // test add()
+ cal.clear();
+ // 2002-01-01T00:00:00+0930 in Australia/Adelaide
+ cal.setTimeInMillis(1009805400000L);
+ cal.set(DAY_OF_WEEK, cal.get(DAY_OF_WEEK));
+ cal.set(WEEK_OF_YEAR, cal.get(WEEK_OF_YEAR));
+ cal.getTime();
+ cal.add(MONTH, +1);
+ System.out.println(" add: " + cal.getTime());
+ if (!cal.checkDate(2002, FEBRUARY, 1)) {
+ error("add(MONTH, +1): " + cal.getMessage());
+ }
+ cal.add(MONTH, -1);
+ if (!cal.checkDate(2002, JANUARY, 1)) {
+ error("add(MONTH, -1): " + cal.getMessage());
+ }
+ }
+ finally {
+ TimeZone.setDefault(defaultTz);
+ }
+
+ checkErrors();
+ }
+
+ static void error(String s) {
+ System.out.println(s);
+ errorCount++;
+ }
+
+ static void checkErrors() {
+ if (errorCount > 0) {
+ throw new RuntimeException("Failed: " + errorCount + " error(s)");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Bug6178071.java b/test/java/util/Calendar/Bug6178071.java
new file mode 100644
index 0000000000..8d361c76bc
--- /dev/null
+++ b/test/java/util/Calendar/Bug6178071.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6178071 6440854
+ * @summary Make sure that setting HOUR right after a construction works
+ * as expected.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.*;
+
+public class Bug6178071 {
+ public static void main(String[] args) {
+ GregorianCalendar cal = new GregorianCalendar(2004, JANUARY, 1);
+ cal.set(HOUR, 1);
+ if (cal.get(HOUR_OF_DAY) != 1 ||
+ cal.get(HOUR) != 1 || cal.get(AM_PM) != AM) {
+ throw new RuntimeException("Unexpected hour of day: " + cal.getTime());
+ }
+
+ // Test case for 6440854
+ GregorianCalendar gc = new GregorianCalendar(2006,5,16);
+ gc.setLenient(false);
+ gc.set(HOUR_OF_DAY, 10);
+ // The following line shouldn't throw an IllegalArgumentException.
+ gc.get(YEAR);
+ }
+}
diff --git a/test/java/util/Calendar/Bug6234795.java b/test/java/util/Calendar/Bug6234795.java
new file mode 100644
index 0000000000..d1b2bc55c0
--- /dev/null
+++ b/test/java/util/Calendar/Bug6234795.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6234795
+ * @summary Rolling of HOUR or HOUR_OF_SET must set the other hour field.
+ */
+
+import java.util.GregorianCalendar;
+import static java.util.Calendar.AM;
+import static java.util.Calendar.AM_PM;
+import static java.util.Calendar.HOUR;
+import static java.util.Calendar.HOUR_OF_DAY;
+import static java.util.Calendar.SEPTEMBER;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class Bug6234795 {
+ public static void main(String[] args) {
+ testRoll(HOUR);
+ testRoll(HOUR_OF_DAY);
+ }
+
+ static void testRoll(int field) {
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"), Locale.US);
+ cal.clear();
+ cal.set(2005, SEPTEMBER, 12);
+
+ int otherField = (field == HOUR) ? HOUR_OF_DAY : HOUR;
+ int unit = (field == HOUR) ? 12 : 24;
+ int h;
+ for (h = 0; h <= 72; h++) {
+ int hour = cal.get(otherField);
+ int expected = h % 12;
+ if (hour != expected) {
+ throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+ + "+: h=" + h + ", got " + hour
+ + ", expected " + expected);
+ }
+ if (field == HOUR_OF_DAY) {
+ int ampm = cal.get(AM_PM);
+ expected = (h % unit) / 12;
+ if (ampm != expected) {
+ throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+ + "+: h=" + h + ", got "
+ + toString(ampm)
+ + ", expected " + toString(expected));
+ }
+ }
+ cal.roll(field, +1);
+ }
+ for (; h >= 0; h--) {
+ int hour = cal.get(otherField);
+ int expected = h % 12;
+ if (hour != expected) {
+ throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+ + "-: h=" + h + ", got " + hour
+ + ", expected " + expected);
+ }
+ if (field == HOUR_OF_DAY) {
+ int ampm = cal.get(AM_PM);
+ expected = (h % unit) / 12;
+ if (ampm != expected) {
+ throw new RuntimeException((field == HOUR ? "HOUR" : "HOUR_OF_DAY")
+ + "-: h=" + h + ", got " + toString(ampm)
+ + ", expected " + toString(expected));
+ }
+ }
+ cal.roll(field, -1);
+ }
+ }
+
+ static String toString(int ampm) {
+ return ampm == AM ? "AM" : "PM";
+ }
+}
diff --git a/test/java/util/Calendar/Bug6448234.java b/test/java/util/Calendar/Bug6448234.java
new file mode 100644
index 0000000000..16cf0fca1c
--- /dev/null
+++ b/test/java/util/Calendar/Bug6448234.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006, 2016, 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 6448234
+ * @summary Make sure indexing of DAY_OF_WEEK is correct in JapaneseImperialCalendar.getDisplayName.
+ */
+
+import java.util.Calendar;
+import java.util.Locale;
+import static java.util.Calendar.*;
+
+public class Bug6448234 {
+ public static void main(String[] args) {
+ Calendar jcal = Calendar.getInstance(new Locale("ja", "JP", "JP"));
+ Calendar gcal = Calendar.getInstance(Locale.US);
+
+ for (int i = SUNDAY; i <= SATURDAY; i++) {
+ jcal.set(DAY_OF_WEEK, i);
+ gcal.set(DAY_OF_WEEK, i);
+
+ // Test LONG
+ String j = jcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US);
+ String g = gcal.getDisplayName(DAY_OF_WEEK, LONG, Locale.US);
+ if (!j.equals(g)) {
+ throw new RuntimeException("Got " + j + ", expected " + g);
+ }
+
+ // Test SHORT
+ j = jcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US);
+ g = gcal.getDisplayName(DAY_OF_WEEK, SHORT, Locale.US);
+ if (!j.equals(g)) {
+ throw new RuntimeException("Got " + j + ", expected " + g);
+ }
+ }
+ }
+}
diff --git a/test/java/util/Calendar/CalendarLimitTest.java b/test/java/util/Calendar/CalendarLimitTest.java
new file mode 100644
index 0000000000..69dcbb5efc
--- /dev/null
+++ b/test/java/util/Calendar/CalendarLimitTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4033662
+ * @library /java/text/testlib
+ * @summary test for limit on Calendar
+ * @run main CalendarLimitTest -verbose
+ */
+
+import java.util.*;
+import java.text.*;
+
+/**
+ * This test verifies the behavior of Calendar around the very earliest limits
+ * which it can handle. It also verifies the behavior for large values of millis.
+ *
+ * Note: There used to be a limit, due to a bug, for early times. There is
+ * currently no limit.
+ *
+ * March 17, 1998: Added code to make sure big + dates are big + AD years, and
+ * big - dates are big + BC years.
+ */
+public class CalendarLimitTest extends IntlTest
+{
+ // This number determined empirically; this is the old limit,
+ // which we test for to make sure it isn't there anymore.
+ static final long EARLIEST_SUPPORTED_MILLIS = -210993120000000L;
+
+ static final int EPOCH_JULIAN_DAY = 2440588; // Jaunary 1, 1970 (Gregorian)
+ static final int JAN_1_1_JULIAN_DAY = 1721426; // January 1, year 1 (Gregorian)
+
+ // Useful millisecond constants
+ static final int ONE_SECOND = 1000;
+ static final int ONE_MINUTE = 60*ONE_SECOND;
+ static final int ONE_HOUR = 60*ONE_MINUTE;
+ static final int ONE_DAY = 24*ONE_HOUR;
+ static final int ONE_WEEK = 7*ONE_DAY;
+ static final long ONE_YEAR = (long)(365.2425 * ONE_DAY);
+
+ static long ORIGIN; // This is the *approximate* point at which BC switches to AD
+
+ public static void main(String argv[]) throws Exception {
+ new CalendarLimitTest().run(argv);
+ }
+
+ /**
+ * Converts Julian day to time as milliseconds.
+ * @param julian the given Julian day number.
+ * @return time as milliseconds.
+ */
+ private static final long julianDayToMillis(long julian) {
+ return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
+ }
+
+ /**
+ * Verify that the given time is processed without problem.
+ * @return the adjust year, with 0 = 1 BC, -1 = 2 BC, etc.
+ */
+ int test(long millis, Calendar cal, DateFormat fmt)
+ {
+ Exception exception = null;
+ String theDate = "";
+ try {
+ Date d= new Date(millis);
+ cal.setTime(d);
+ theDate = fmt.format(d);
+ }
+ catch (IllegalArgumentException e) {
+ exception = e;
+ }
+ String s = "0x" + Long.toHexString(millis) + " " + theDate;
+
+ int era=cal.get(Calendar.ERA), year=cal.get(Calendar.YEAR),
+ dom=cal.get(Calendar.DATE), mon=cal.get(Calendar.MONTH);
+
+ cal.clear();
+ cal.set(year, mon, dom);
+ cal.set(Calendar.ERA, era);
+ Date rt = cal.getTime();
+
+ boolean ok = true;
+ if (exception != null) {
+ errln("FAIL: Exception " + s);
+ ok = false;
+ }
+ if (((millis >= ORIGIN) && (era != GregorianCalendar.AD)) ||
+ ((millis < ORIGIN) && (era != GregorianCalendar.BC)) ||
+ (year < 1)) {
+ errln("FAIL: Bad year/era " + s);
+ ok = false;
+ }
+ if (dom<1 || dom>31) {
+ errln("FAIL: Bad DOM " + s);
+ ok = false;
+ }
+ if (Math.abs(millis - rt.getTime()) > ONE_DAY) {
+ errln("FAIL: RT fail " + s + " -> 0x" +
+ Long.toHexString(rt.getTime()) + " " +
+ fmt.format(rt));
+ ok = false;
+ }
+ if (ok) logln(s);
+ if (era==GregorianCalendar.BC) year = 1-year;
+ return year;
+ }
+
+ public void TestCalendarLimit()
+ {
+ ORIGIN = julianDayToMillis(JAN_1_1_JULIAN_DAY);
+
+ Calendar cal = Calendar.getInstance();
+ // You must set the time zone to GMT+0 or the edge cases like
+ // Long.MIN_VALUE, Long.MAX_VALUE, and right around the threshold
+ // won't work, since before converting to fields the calendar code
+ // will add the offset for the zone.
+ cal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
+
+ DateFormat dateFormat = DateFormat.getDateInstance();
+ dateFormat.setCalendar(cal); // Make sure you do this -- same reason as above
+ ((SimpleDateFormat)dateFormat).applyPattern("MMM d, yyyy G");
+
+ // Don't expect any failure for positive longs
+ int lastYear=0;
+ boolean first=true;
+ for (long m = Long.MAX_VALUE; m > 0; m >>= 1)
+ {
+ int y = test(m, cal, dateFormat);
+ if (!first && y > lastYear)
+ errln("FAIL: Years should be decreasing " + lastYear + " " + y);
+ first = false;
+ lastYear = y;
+ }
+
+ // Expect failures for negative millis below threshold
+ first = true;
+ for (long m = Long.MIN_VALUE; m < 0; m /= 2) // Don't use m >>= 1
+ {
+ int y = test(m, cal, dateFormat);
+ if (!first && y < lastYear)
+ errln("FAIL: Years should be increasing " + lastYear + " " + y);
+ first = false;
+ lastYear = y;
+ }
+
+ // Test right around the threshold
+ test(EARLIEST_SUPPORTED_MILLIS, cal, dateFormat);
+ test(EARLIEST_SUPPORTED_MILLIS-1, cal, dateFormat);
+
+ // Test a date that should work
+ test(Long.MIN_VALUE + ONE_DAY, cal, dateFormat);
+
+ // Try hours in the earliest day or two
+ // JUST FOR DEBUGGING:
+ if (false) {
+ ((SimpleDateFormat)dateFormat).applyPattern("H:mm MMM d, yyyy G");
+ for (int dom=2; dom<=3; ++dom) {
+ for (int h=0; h<24; ++h) {
+ cal.clear();
+ cal.set(Calendar.ERA, GregorianCalendar.BC);
+ cal.set(292269055, Calendar.DECEMBER, dom, h, 0);
+ Date d = cal.getTime();
+ cal.setTime(d);
+ logln("" + h + ":00 Dec "+dom+", 292269055 BC -> " +
+ Long.toHexString(d.getTime()) + " -> " +
+ dateFormat.format(cal.getTime()));
+ }
+ }
+ // Other way
+ long t = 0x80000000018c5c00L; // Dec 3, 292269055 BC
+ while (t<0) {
+ cal.setTime(new Date(t));
+ logln("0x" + Long.toHexString(t) + " -> " +
+ dateFormat.format(cal.getTime()));
+ t -= ONE_HOUR;
+ }
+ }
+ }
+}
+
+//eof
diff --git a/test/java/util/Calendar/CalendarRegression.java b/test/java/util/Calendar/CalendarRegression.java
new file mode 100644
index 0000000000..baae13f14f
--- /dev/null
+++ b/test/java/util/Calendar/CalendarRegression.java
@@ -0,0 +1,2496 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385
+ * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271
+ * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933
+ * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516
+ * 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 4623997
+ * 4685354 4655637 4683492 4080631 4080631 4167995 4340146 4639407
+ * 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 4960642
+ * 4973919 4980088 4965624 5013094 5006864 8152077
+ * @library /java/text/testlib
+ */
+
+import java.lang.reflect.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class CalendarRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new CalendarRegression().run(args);
+ }
+
+ /*
+ Synopsis: java.sql.Timestamp constructor works wrong on Windows 95
+
+ ==== Here is the test ====
+ public static void main (String args[]) {
+ java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700);
+ logln("expected=1901-04-05 05:08:13.1234567");
+ logln(" result="+t);
+ }
+
+ ==== Here is the output of the test on Solaris or NT ====
+ expected=1901-04-05 05:08:13.1234567
+ result=1901-04-05 05:08:13.1234567
+
+ ==== Here is the output of the test on Windows95 ====
+ expected=1901-04-05 05:08:13.1234567
+ result=1901-04-05 06:08:13.1234567
+ */
+
+ public void Test4031502() {
+ // This bug actually occurs on Windows NT as well, and doesn't
+ // require the host zone to be set; it can be set in Java.
+ String[] ids = TimeZone.getAvailableIDs();
+ boolean bad = false;
+ for (int i=0; i<ids.length; ++i) {
+ TimeZone zone = TimeZone.getTimeZone(ids[i]);
+ GregorianCalendar cal = new GregorianCalendar(zone);
+ cal.clear();
+ cal.set(1900, 15, 5, 5, 8, 13);
+ if (cal.get(Calendar.HOUR) != 5) {
+ logln(zone.getID() + " " +
+ //zone.useDaylightTime() + " " +
+ cal.get(Calendar.DST_OFFSET) / (60*60*1000) + " " +
+ zone.getRawOffset() / (60*60*1000) +
+ ": HOUR = " + cal.get(Calendar.HOUR));
+ bad = true;
+ }
+ }
+ if (bad) errln("TimeZone problems with GC");
+ }
+
+ public void Test4035301() {
+ GregorianCalendar c = new GregorianCalendar(98, 8, 7);
+ GregorianCalendar d = new GregorianCalendar(98, 8, 7);
+ if (c.after(d) ||
+ c.after(c) ||
+ c.before(d) ||
+ c.before(c) ||
+ !c.equals(c) ||
+ !c.equals(d))
+ errln("Fail");
+ }
+
+ public void Test4040996() {
+ String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
+ SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
+ pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+ pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
+ Calendar calendar = new GregorianCalendar(pdt);
+
+ calendar.set(Calendar.MONTH,3);
+ calendar.set(Calendar.DAY_OF_MONTH,18);
+ calendar.set(Calendar.SECOND, 30);
+
+ logln("MONTH: " + calendar.get(Calendar.MONTH));
+ logln("DAY_OF_MONTH: " +
+ calendar.get(Calendar.DAY_OF_MONTH));
+ logln("MINUTE: " + calendar.get(Calendar.MINUTE));
+ logln("SECOND: " + calendar.get(Calendar.SECOND));
+
+ calendar.add(Calendar.SECOND,6);
+ //This will print out todays date for MONTH and DAY_OF_MONTH
+ //instead of the date it was set to.
+ //This happens when adding MILLISECOND or MINUTE also
+ logln("MONTH: " + calendar.get(Calendar.MONTH));
+ logln("DAY_OF_MONTH: " +
+ calendar.get(Calendar.DAY_OF_MONTH));
+ logln("MINUTE: " + calendar.get(Calendar.MINUTE));
+ logln("SECOND: " + calendar.get(Calendar.SECOND));
+ if (calendar.get(Calendar.MONTH) != 3 ||
+ calendar.get(Calendar.DAY_OF_MONTH) != 18 ||
+ calendar.get(Calendar.SECOND) != 36)
+ errln("Fail: Calendar.add misbehaves");
+ }
+
+ public void Test4051765() {
+ Calendar cal = Calendar.getInstance();
+ cal.setLenient(false);
+ cal.set(Calendar.DAY_OF_WEEK, 0);
+ try {
+ cal.getTime();
+ errln("Fail: DAY_OF_WEEK 0 should be disallowed");
+ }
+ catch (IllegalArgumentException e) {
+ return;
+ }
+ }
+
+ /* User error - no bug here
+ public void Test4059524() {
+ // Create calendar for April 10, 1997
+ GregorianCalendar calendar = new GregorianCalendar();
+ // print out a bunch of interesting things
+ logln("ERA: " + calendar.get(calendar.ERA));
+ logln("YEAR: " + calendar.get(calendar.YEAR));
+ logln("MONTH: " + calendar.get(calendar.MONTH));
+ logln("WEEK_OF_YEAR: " +
+ calendar.get(calendar.WEEK_OF_YEAR));
+ logln("WEEK_OF_MONTH: " +
+ calendar.get(calendar.WEEK_OF_MONTH));
+ logln("DATE: " + calendar.get(calendar.DATE));
+ logln("DAY_OF_MONTH: " +
+ calendar.get(calendar.DAY_OF_MONTH));
+ logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
+ logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
+ logln("DAY_OF_WEEK_IN_MONTH: " +
+ calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
+ logln("AM_PM: " + calendar.get(calendar.AM_PM));
+ logln("HOUR: " + calendar.get(calendar.HOUR));
+ logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
+ logln("MINUTE: " + calendar.get(calendar.MINUTE));
+ logln("SECOND: " + calendar.get(calendar.SECOND));
+ logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
+ logln("ZONE_OFFSET: "
+ + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000)));
+ logln("DST_OFFSET: "
+ + (calendar.get(calendar.DST_OFFSET)/(60*60*1000)));
+ calendar = new GregorianCalendar(1997,3,10);
+ calendar.getTime();
+ logln("April 10, 1997");
+ logln("ERA: " + calendar.get(calendar.ERA));
+ logln("YEAR: " + calendar.get(calendar.YEAR));
+ logln("MONTH: " + calendar.get(calendar.MONTH));
+ logln("WEEK_OF_YEAR: " +
+ calendar.get(calendar.WEEK_OF_YEAR));
+ logln("WEEK_OF_MONTH: " +
+ calendar.get(calendar.WEEK_OF_MONTH));
+ logln("DATE: " + calendar.get(calendar.DATE));
+ logln("DAY_OF_MONTH: " +
+ calendar.get(calendar.DAY_OF_MONTH));
+ logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));
+ logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));
+ logln("DAY_OF_WEEK_IN_MONTH: " + calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));
+ logln("AM_PM: " + calendar.get(calendar.AM_PM));
+ logln("HOUR: " + calendar.get(calendar.HOUR));
+ logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));
+ logln("MINUTE: " + calendar.get(calendar.MINUTE));
+ logln("SECOND: " + calendar.get(calendar.SECOND));
+ logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));
+ logln("ZONE_OFFSET: "
+ + (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
+ logln("DST_OFFSET: "
+ + (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); // in hours
+ }
+ */
+
+ public void Test4059654() {
+ GregorianCalendar gc = new GregorianCalendar();
+
+ gc.set(1997, 3, 1, 15, 16, 17); // April 1, 1997
+
+ gc.set(Calendar.HOUR, 0);
+ gc.set(Calendar.AM_PM, Calendar.AM);
+ gc.set(Calendar.MINUTE, 0);
+ gc.set(Calendar.SECOND, 0);
+ gc.set(Calendar.MILLISECOND, 0);
+
+ Date cd = gc.getTime();
+ Date exp = new Date(97, 3, 1, 0, 0, 0);
+ if (!cd.equals(exp))
+ errln("Fail: Calendar.set broken. Got " + cd + " Want " + exp);
+ }
+
+ public void Test4061476() {
+ SimpleDateFormat fmt = new SimpleDateFormat("ddMMMyy", Locale.UK);
+ Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"),
+ Locale.UK);
+ fmt.setCalendar(cal);
+ try
+ {
+ Date date = fmt.parse("29MAY97");
+ cal.setTime(date);
+ }
+ catch (Exception e) {;}
+ cal.set(Calendar.HOUR_OF_DAY, 13);
+ logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
+ cal.add(Calendar.HOUR_OF_DAY, 6);
+ logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
+ if (cal.get(Calendar.HOUR_OF_DAY) != 19)
+ errln("Fail: Want 19 Got " + cal.get(Calendar.HOUR_OF_DAY));
+ }
+
+ public void Test4070502() {
+ Date d = getAssociatedDate(new Date(98, 0, 30));
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(d);
+ if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
+ cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
+ errln("Fail: Want weekday Got " + d);
+ }
+
+ /**
+ * Get the associated date starting from a specified date
+ * NOTE: the unnecessary "getTime()'s" below are a work-around for a
+ * bug in jdk 1.1.3 (and probably earlier versions also)
+ * <p>
+ * @param date The date to start from
+ */
+ public static Date getAssociatedDate(Date d) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTime(d);
+ //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
+ // cal.getTime(); // <--- REMOVE THIS TO SEE BUG
+ while (true) {
+ int wd = cal.get(Calendar.DAY_OF_WEEK);
+ if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) {
+ cal.add(Calendar.DATE, 1);
+ // cal.getTime();
+ }
+ else
+ break;
+ }
+ return cal.getTime();
+ }
+
+ public void Test4071197() {
+ dowTest(false);
+ dowTest(true);
+ }
+
+ void dowTest(boolean lenient) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.set(1997, Calendar.AUGUST, 12); // Wednesday
+ // cal.getTime(); // Force update
+ cal.setLenient(lenient);
+ cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
+ int dow = cal.get(Calendar.DAY_OF_WEEK);
+ int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
+ int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
+ logln(cal.getTime().toString());
+ if (min != Calendar.SUNDAY || max != Calendar.SATURDAY)
+ errln("FAIL: Min/max bad");
+ if (dow < min || dow > max)
+ errln("FAIL: Day of week " + dow + " out of range");
+ if (dow != Calendar.SUNDAY)
+ errln("FAIL: Day of week should be SUNDAY Got " + dow);
+ }
+
+ public void Test4071385() {
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new Date(98, Calendar.JUNE, 24));
+ cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24)))
+ errln("Fail");
+ }
+
+ public void Test4073929() {
+ GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27);
+ foo1.add(Calendar.DAY_OF_MONTH, +1);
+ int testyear = foo1.get(Calendar.YEAR);
+ int testmonth = foo1.get(Calendar.MONTH);
+ int testday = foo1.get(Calendar.DAY_OF_MONTH);
+ if (testyear != 1997 ||
+ testmonth != 8 ||
+ testday != 28)
+ errln("Fail: Calendar not initialized");
+ }
+
+ public void Test4083167() {
+ TimeZone saveZone = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ Date firstDate = new Date();
+ Calendar cal = new GregorianCalendar();
+ cal.setTime(firstDate);
+ long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
+ cal.get(Calendar.MINUTE) * 60000L +
+ cal.get(Calendar.SECOND) * 1000L +
+ cal.get(Calendar.MILLISECOND);
+
+ logln("Current time: " + firstDate.toString());
+
+ for (int validity=0; validity<30; validity++) {
+ Date lastDate = new Date(firstDate.getTime() +
+ (long)validity*1000*24*60*60);
+ cal.setTime(lastDate);
+ long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
+ cal.get(Calendar.MINUTE) * 60000L +
+ cal.get(Calendar.SECOND) * 1000L +
+ cal.get(Calendar.MILLISECOND);
+ if (firstMillisInDay != millisInDay) {
+ errln("Day has shifted " + lastDate);
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ public void Test4086724() {
+ SimpleDateFormat date;
+ TimeZone saveZone = TimeZone.getDefault();
+ Locale saveLocale = Locale.getDefault();
+
+ String summerTime = "British Summer Time";
+ String standardTime = "Greenwich Mean Time";
+ try {
+ Locale.setDefault(Locale.UK);
+ TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
+ date = new SimpleDateFormat("zzzz");
+
+ Calendar cal=Calendar.getInstance();
+ cal.set(1997,Calendar.SEPTEMBER,30);
+ Date now=cal.getTime();
+ String formattedDate = date.format(now);
+ if (!formattedDate.equals(summerTime)) {
+ errln("Wrong display name \"" + formattedDate
+ + "\" for <" + now + ">");
+ }
+ int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+ if (weekOfYear != 40) {
+ errln("Wrong week-of-year " + weekOfYear
+ + " for <" + now + ">");
+ }
+
+ cal.set(1996,Calendar.DECEMBER,31);
+ now=cal.getTime();
+ formattedDate = date.format(now);
+ if (!formattedDate.equals(standardTime)) {
+ errln("Wrong display name \"" + formattedDate
+ + "\" for <" + now + ">");
+ }
+ weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+ if (weekOfYear != 1) {
+ errln("Wrong week-of-year " + weekOfYear
+ + " for <" + now + ">");
+ }
+
+ cal.set(1997,Calendar.JANUARY,1);
+ now=cal.getTime();
+ formattedDate = date.format(now);
+ if (!formattedDate.equals(standardTime)) {
+ errln("Wrong display name \"" + formattedDate
+ + "\" for <" + now + ">");
+ }
+ weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+ if (weekOfYear != 1) {
+ errln("Wrong week-of-year " + weekOfYear
+ + " for <" + now + ">");
+ }
+
+ cal.set(1997,Calendar.JANUARY,8);
+ now=cal.getTime();
+ formattedDate = date.format(now);
+ if (!formattedDate.equals(standardTime)) {
+ errln("Wrong display name \"" + formattedDate
+ + "\" for <" + now + ">");
+ }
+ weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);
+ if (weekOfYear != 2) {
+ errln("Wrong week-of-year " + weekOfYear
+ + " for <" + now + ">");
+ }
+
+ }
+ finally {
+ Locale.setDefault(saveLocale);
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ public void Test4092362() {
+ GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
+ /*cal1.set( Calendar.YEAR, 1997 );
+ cal1.set( Calendar.MONTH, 10 );
+ cal1.set( Calendar.DATE, 11 );
+ cal1.set( Calendar.HOUR, 10 );
+ cal1.set( Calendar.MINUTE, 20 );
+ cal1.set( Calendar.SECOND, 40 ); */
+
+ logln( " Cal1 = " + cal1.getTime().getTime() );
+ logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) );
+ for( int k = 0; k < 100 ; k++ );
+
+ GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
+ /*cal2.set( Calendar.YEAR, 1997 );
+ cal2.set( Calendar.MONTH, 10 );
+ cal2.set( Calendar.DATE, 11 );
+ cal2.set( Calendar.HOUR, 10 );
+ cal2.set( Calendar.MINUTE, 20 );
+ cal2.set( Calendar.SECOND, 40 ); */
+
+ logln( " Cal2 = " + cal2.getTime().getTime() );
+ logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) );
+ if( !cal1.equals( cal2 ) )
+ errln("Fail: Milliseconds randomized");
+ }
+
+ public void Test4095407() {
+ GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13);
+ int dow = a.get(Calendar.DAY_OF_WEEK);
+ if (dow != Calendar.THURSDAY)
+ errln("Fail: Want THURSDAY Got " + dow);
+ }
+
+ public void Test4096231() {
+ TimeZone GMT = TimeZone.getTimeZone("GMT");
+ TimeZone PST = TimeZone.getTimeZone("PST");
+ int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
+
+ Calendar cal1 = new GregorianCalendar(PST);
+ cal1.setTime(new Date(880698639000L));
+ int p;
+ logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY)));
+ cal1.setTimeZone(GMT);
+ // Issue 1: Changing the timezone doesn't change the
+ // represented time.
+ int h1,h2;
+ logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY)));
+ cal1.setTime(new Date(880698639000L));
+ logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY)));
+ // Note: This test had a bug in it. It wanted h1!=h2, when
+ // what was meant was h1!=p. Fixed this concurrent with fix
+ // to 4177484.
+ if (p == h1 || h1 != h2)
+ errln("Fail: Hour same in different zones");
+
+ Calendar cal2 = new GregorianCalendar(GMT);
+ Calendar cal3 = new GregorianCalendar(PST);
+ cal2.set(Calendar.MILLISECOND, 0);
+ cal3.set(Calendar.MILLISECOND, 0);
+
+ cal2.set(cal1.get(cal1.YEAR),
+ cal1.get(cal1.MONTH),
+ cal1.get(cal1.DAY_OF_MONTH),
+ cal1.get(cal1.HOUR_OF_DAY),
+ cal1.get(cal1.MINUTE),
+ cal1.get(cal1.SECOND));
+
+ long t1,t2,t3,t4;
+ logln("RGMT 1 is: " + (t1=cal2.getTime().getTime()));
+ cal3.set(year, month, day, hr, min, sec);
+ logln("RPST 1 is: " + (t2=cal3.getTime().getTime()));
+ cal3.setTimeZone(GMT);
+ logln("RGMT 2 is: " + (t3=cal3.getTime().getTime()));
+ cal3.set(cal1.get(cal1.YEAR),
+ cal1.get(cal1.MONTH),
+ cal1.get(cal1.DAY_OF_MONTH),
+ cal1.get(cal1.HOUR_OF_DAY),
+ cal1.get(cal1.MINUTE),
+ cal1.get(cal1.SECOND));
+ // Issue 2: Calendar continues to use the timezone in its
+ // constructor for set() conversions, regardless
+ // of calls to setTimeZone()
+ logln("RGMT 3 is: " + (t4=cal3.getTime().getTime()));
+ if (t1 == t2 ||
+ t1 != t4 ||
+ t2 != t3)
+ errln("Fail: Calendar zone behavior faulty");
+ }
+
+ public void Test4096539() {
+ int[] y = {31,28,31,30,31,30,31,31,30,31,30,31};
+
+ for (int x=0;x<12;x++) {
+ GregorianCalendar gc = new
+ GregorianCalendar(1997,x,y[x]);
+ int m1,m2;
+ log((m1=gc.get(Calendar.MONTH)+1)+"/"+
+ gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+
+ " + 1mo = ");
+
+ gc.add(Calendar.MONTH, 1);
+ logln((m2=gc.get(Calendar.MONTH)+1)+"/"+
+ gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)
+ );
+ int m = (m1 % 12) + 1;
+ if (m2 != m)
+ errln("Fail: Want " + m + " Got " + m2);
+ }
+
+ }
+
+ public void Test4100311() {
+ GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
+ cal.set(Calendar.YEAR, 1997);
+ cal.set(Calendar.DAY_OF_YEAR, 1);
+ Date d = cal.getTime(); // Should be Jan 1
+ logln(d.toString());
+ if (cal.get(Calendar.DAY_OF_YEAR) != 1)
+ errln("Fail: DAY_OF_YEAR not set");
+ }
+
+ public void Test4103271() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ SimpleDateFormat sdf = new SimpleDateFormat();
+ int numYears=40, startYear=1997, numDays=15;
+ String output, testDesc;
+ GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
+ testCal.clear();
+ sdf.setCalendar(testCal);
+ sdf.applyPattern("d MMM yyyy");
+ boolean fail = false;
+ for (int firstDay=1; firstDay<=2; firstDay++) {
+ for (int minDays=1; minDays<=7; minDays++) {
+ testCal.setMinimalDaysInFirstWeek(minDays);
+ testCal.setFirstDayOfWeek(firstDay);
+ testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays));
+ logln(testDesc + " => 1st day of week=" +
+ String.valueOf(firstDay) +
+ ", minimum days in first week=" +
+ String.valueOf(minDays));
+ for (int j=startYear; j<=startYear+numYears; j++) {
+ testCal.set(j,11,25);
+ for(int i=0; i<numDays; i++) {
+ testCal.add(Calendar.DATE,1);
+ String calWOY;
+ int actWOY = testCal.get(Calendar.WEEK_OF_YEAR);
+ if (actWOY < 1 || actWOY > 53) {
+ Date d = testCal.getTime();
+ calWOY = String.valueOf(actWOY);
+ output = testDesc + " - " + sdf.format(d) + "\t";
+ output = output + "\t" + calWOY;
+ logln(output);
+ fail = true;
+ }
+ }
+ }
+ }
+ }
+
+ int[] DATA = {
+ 3, 52, 52, 52, 52, 52, 52, 52,
+ 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2,
+ 4, 52, 52, 52, 52, 52, 52, 52,
+ 53, 53, 53, 53, 53, 53, 53,
+ 1, 1, 1, 1, 1, 1, 1,
+ };
+ testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+ for (int j=0; j<DATA.length; j+=22) {
+ logln("Minimal days in first week = " + DATA[j] +
+ " Week starts on Sunday");
+ testCal.setMinimalDaysInFirstWeek(DATA[j]);
+ testCal.set(1997, Calendar.DECEMBER, 21);
+ for (int i=0; i<21; ++i) {
+ int woy = testCal.get(Calendar.WEEK_OF_YEAR);
+ log("\t" + testCal.getTime() + " " + woy);
+ if (woy != DATA[j + 1 + i]) {
+ log(" ERROR");
+ fail = true;
+ } else {
+ logln(" OK");
+ }
+
+ // Now compute the time from the fields, and make sure we
+ // get the same answer back. This is a round-trip test.
+ Date save = testCal.getTime();
+ testCal.clear();
+ testCal.set(Calendar.YEAR, DATA[j+1+i] < 25 ? 1998 : 1997);
+ testCal.set(Calendar.WEEK_OF_YEAR, DATA[j+1+i]);
+ testCal.set(Calendar.DAY_OF_WEEK, (i%7) + Calendar.SUNDAY);
+ if (!testCal.getTime().equals(save)) {
+ logln(" Parse failed: " + testCal.getTime());
+ fail= true;
+ } else {
+ logln(" Passed");
+ }
+
+ testCal.setTime(save);
+ testCal.add(Calendar.DAY_OF_MONTH, 1);
+ }
+ }
+
+ // Test field disambiguation with a few special hard-coded cases.
+ // This shouldn't fail if the above cases aren't failing.
+ Object[] DISAM = {
+ new Integer(1998), new Integer(1), new Integer(Calendar.SUNDAY),
+ new Date(97, Calendar.DECEMBER, 28),
+ new Integer(1998), new Integer(2), new Integer(Calendar.SATURDAY),
+ new Date(98, Calendar.JANUARY, 10),
+ new Integer(1998), new Integer(53), new Integer(Calendar.THURSDAY),
+ new Date(98, Calendar.DECEMBER, 31),
+ new Integer(1998), new Integer(53), new Integer(Calendar.FRIDAY),
+ new Date(99, Calendar.JANUARY, 1),
+ };
+ testCal.setMinimalDaysInFirstWeek(3);
+ testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+ for (int i=0; i<DISAM.length; i+=4) {
+ int y = ((Integer)DISAM[i]).intValue();
+ int woy = ((Integer)DISAM[i+1]).intValue();
+ int dow = ((Integer)DISAM[i+2]).intValue();
+ Date exp = (Date)DISAM[i+3];
+ testCal.clear();
+ testCal.set(Calendar.YEAR, y);
+ testCal.set(Calendar.WEEK_OF_YEAR, woy);
+ testCal.set(Calendar.DAY_OF_WEEK, dow);
+ log(y + "-W" + woy + "-DOW" + dow);
+ if (!testCal.getTime().equals(exp)) {
+ logln(" FAILED expect: " + exp + "\n got: " +testCal.getTime());
+ fail = true;
+ } else {
+ logln(" OK");
+ }
+ }
+
+ // Now try adding and rolling
+ Object ADD = new Object();
+ Object ROLL = new Object();
+ Object[] ADDROLL = {
+ ADD, new Integer(1), new Date(98, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 1),
+ ADD, new Integer(1), new Date(97, Calendar.DECEMBER, 28), new Date(98, Calendar.JANUARY, 4),
+ ROLL, new Integer(1), new Date(98, Calendar.DECEMBER, 27), new Date(98, Calendar.JANUARY, 4),
+ ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 24), new Date(99, Calendar.DECEMBER, 31),
+ ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 9),
+ };
+ testCal.setMinimalDaysInFirstWeek(3);
+ testCal.setFirstDayOfWeek(Calendar.SUNDAY);
+ for (int i=0; i<ADDROLL.length; i+=4) {
+ int amount = ((Integer)ADDROLL[i+1]).intValue();
+ Date before = (Date)ADDROLL[i+2];
+ Date after = (Date)ADDROLL[i+3];
+
+ testCal.setTime(before);
+ if (ADDROLL[i] == ADD)
+ testCal.add(Calendar.WEEK_OF_YEAR, amount);
+ else
+ testCal.roll(Calendar.WEEK_OF_YEAR, amount);
+ log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
+ amount + ")\t " + before +
+ "\n\t\t => " + testCal.getTime());
+ if (!after.equals(testCal.getTime())) {
+ logln("\tFAIL\n\t\texp: " + after);
+ fail = true;
+ } else
+ logln(" OK");
+
+ testCal.setTime(after);
+ if (ADDROLL[i] == ADD)
+ testCal.add(Calendar.WEEK_OF_YEAR, -amount);
+ else
+ testCal.roll(Calendar.WEEK_OF_YEAR, -amount);
+ log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +
+ (-amount) + ") " + after +
+ "\n\t\t => " + testCal.getTime());
+ if (!before.equals(testCal.getTime())) {
+ logln("\tFAIL\n\t\texp: " + before);
+ fail = true;
+ }
+ else logln("\tOK");
+ }
+
+ if (fail) {
+ errln("Fail: Week of year misbehaving");
+ }
+ }
+
+ public void Test4106136() {
+ Locale saveLocale = Locale.getDefault();
+ try {
+ Locale[] locales = { Locale.CHINESE, Locale.CHINA };
+ for (int i=0; i<locales.length; ++i) {
+ Locale.setDefault(locales[i]);
+ int[] n = {
+ Calendar.getAvailableLocales().length,
+ DateFormat.getAvailableLocales().length,
+ NumberFormat.getAvailableLocales().length
+ };
+ for (int j=0; j<n.length; ++j) {
+ if (n[j] == 0) {
+ errln("Fail: No locales for " + locales[i]);
+ }
+ }
+ }
+ }
+ finally {
+ Locale.setDefault(saveLocale);
+ }
+ }
+
+ public void Test4108764() {
+ Date d00 = new Date(97, Calendar.MARCH, 15, 12, 00, 00);
+ Date d01 = new Date(97, Calendar.MARCH, 15, 12, 00, 56);
+ Date d10 = new Date(97, Calendar.MARCH, 15, 12, 34, 00);
+ Date d11 = new Date(97, Calendar.MARCH, 15, 12, 34, 56);
+ Date epoch = new Date(70, Calendar.JANUARY, 1);
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(d11);
+
+ cal.clear( Calendar.MINUTE );
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(d01))
+ errln("Fail: clear(MINUTE) broken");
+
+ cal.set( Calendar.SECOND, 0 );
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(d00))
+ errln("Fail: set(SECOND, 0) broken");
+
+ cal.setTime(d11);
+ cal.set( Calendar.SECOND, 0 );
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(d10))
+ errln("Fail: set(SECOND, 0) broken #2");
+
+ cal.clear( Calendar.MINUTE );
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(d00))
+ errln("Fail: clear(MINUTE) broken #2");
+
+ cal.clear();
+ logln(cal.getTime().toString());
+ if (!cal.getTime().equals(epoch))
+ errln("Fail: clear() broken Want " + epoch);
+ }
+
+ public void Test4114578() {
+ int ONE_HOUR = 60*60*1000;
+ TimeZone saveZone = TimeZone.getDefault();
+ boolean fail = false;
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ Calendar cal = Calendar.getInstance();
+ long onset = new Date(98, Calendar.APRIL, 5, 1, 0).getTime() + ONE_HOUR;
+ long cease = new Date(98, Calendar.OCTOBER, 25, 0, 0).getTime() + 2*ONE_HOUR;
+
+ final int ADD = 1;
+ final int ROLL = 2;
+
+ long[] DATA = {
+ // Start Action Amt Expected_change
+ onset - ONE_HOUR, ADD, 1, ONE_HOUR,
+ onset, ADD, -1, -ONE_HOUR,
+ onset - ONE_HOUR, ROLL, 1, ONE_HOUR,
+ onset, ROLL, -1, -ONE_HOUR,
+ cease - ONE_HOUR, ADD, 1, ONE_HOUR,
+ cease, ADD, -1, -ONE_HOUR,
+ // roll() was changed to support wall-clock-based roll (JDK-8152077). The
+ // time value may jump 2 hours by skipping non-existent wall-clock time.
+ // Note that JDK-4114578 was a problem of add(), not roll().
+ cease - ONE_HOUR, ROLL, 1, ONE_HOUR * 2,
+ cease, ROLL, -1, -ONE_HOUR * 2,
+ };
+
+ for (int i=0; i<DATA.length; i+=4) {
+ Date date = new Date(DATA[i]);
+ int amt = (int) DATA[i+2];
+ long expectedChange = DATA[i+3];
+
+ log(date.toString());
+ cal.setTime(date);
+
+ switch ((int) DATA[i+1]) {
+ case ADD:
+ log(" add (HOUR," + (amt<0?"":"+")+amt + ")= ");
+ cal.add(Calendar.HOUR, amt);
+ break;
+ case ROLL:
+ log(" roll(HOUR," + (amt<0?"":"+")+amt + ")= ");
+ cal.roll(Calendar.HOUR, amt);
+ break;
+ }
+
+ log(cal.getTime().toString());
+
+ long change = cal.getTime().getTime() - date.getTime();
+ if (change != expectedChange) {
+ fail = true;
+ logln(" FAIL");
+ }
+ else logln(" OK");
+ }
+ } finally {
+ TimeZone.setDefault(saveZone);
+ }
+
+ if (fail) {
+ errln("Fail: roll/add misbehaves around DST onset/cease");
+ }
+ }
+
+ /**
+ * Make sure maximum for HOUR field is 11, not 12.
+ */
+ public void Test4118384() {
+ Calendar cal = Calendar.getInstance();
+ if (cal.getMaximum(Calendar.HOUR) != 11 ||
+ cal.getLeastMaximum(Calendar.HOUR) != 11 ||
+ cal.getActualMaximum(Calendar.HOUR) != 11)
+ errln("Fail: maximum of HOUR field should be 11");
+ }
+
+ /**
+ * Check isLeapYear for BC years.
+ */
+ public void Test4125881() {
+ GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
+ DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
+ cal.clear();
+ for (int y=-20; y<=10; ++y) {
+ cal.set(Calendar.ERA, y < 1 ? GregorianCalendar.BC : GregorianCalendar.AD);
+ cal.set(Calendar.YEAR, y < 1 ? 1 - y : y);
+ logln(y + " = " + fmt.format(cal.getTime()) + " " +
+ cal.isLeapYear(y));
+ if (cal.isLeapYear(y) != ((y+40)%4 == 0))
+ errln("Leap years broken");
+ }
+ }
+
+ /**
+ * Prove that GregorianCalendar is proleptic (it used to cut off
+ * at 45 BC, and not have leap years before then).
+ */
+ public void Test4125892() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
+ DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
+ cal.clear();
+ cal.set(Calendar.ERA, GregorianCalendar.BC);
+ cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically)
+ cal.set(Calendar.MONTH, Calendar.FEBRUARY);
+ cal.set(Calendar.DATE, 28);
+ cal.add(Calendar.DATE, 1);
+ if (cal.get(Calendar.DATE) != 29 ||
+ !cal.isLeapYear(-80)) // -80 == 81 BC
+ errln("Calendar not proleptic");
+ }
+
+ /**
+ * Calendar and GregorianCalendar hashCode() methods need improvement.
+ * Calendar needs a good implementation that subclasses can override,
+ * and GregorianCalendar should use that implementation.
+ */
+ public void Test4136399() {
+ /* Note: This test is actually more strict than it has to be.
+ * Technically, there is no requirement that unequal objects have
+ * unequal hashes. We only require equal objects to have equal hashes.
+ * It is desirable for unequal objects to have distributed hashes, but
+ * there is no hard requirement here.
+ *
+ * In this test we make assumptions about certain attributes of calendar
+ * objects getting represented in the hash, which need not always be the
+ * case (although it does work currently with the given test). */
+ Calendar a = Calendar.getInstance();
+ Calendar b = (Calendar)a.clone();
+ if (a.hashCode() != b.hashCode()) {
+ errln("Calendar hash code unequal for cloned objects");
+ }
+
+ b.setMinimalDaysInFirstWeek(7 - a.getMinimalDaysInFirstWeek());
+ if (a.hashCode() == b.hashCode()) {
+ errln("Calendar hash code ignores minimal days in first week");
+ }
+ b.setMinimalDaysInFirstWeek(a.getMinimalDaysInFirstWeek());
+
+ b.setFirstDayOfWeek((a.getFirstDayOfWeek() % 7) + 1); // Next day
+ if (a.hashCode() == b.hashCode()) {
+ errln("Calendar hash code ignores first day of week");
+ }
+ b.setFirstDayOfWeek(a.getFirstDayOfWeek());
+
+ b.setLenient(!a.isLenient());
+ if (a.hashCode() == b.hashCode()) {
+ errln("Calendar hash code ignores lenient setting");
+ }
+ b.setLenient(a.isLenient());
+
+ // Assume getTimeZone() returns a reference, not a clone
+ // of a reference -- this is true as of this writing
+ b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset() + 60*60*1000);
+ if (a.hashCode() == b.hashCode()) {
+ errln("Calendar hash code ignores zone");
+ }
+ b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset());
+
+ GregorianCalendar c = new GregorianCalendar();
+ GregorianCalendar d = (GregorianCalendar)c.clone();
+ if (c.hashCode() != d.hashCode()) {
+ errln("GregorianCalendar hash code unequal for clones objects");
+ }
+ Date cutover = c.getGregorianChange();
+ d.setGregorianChange(new Date(cutover.getTime() + 24*60*60*1000));
+ if (c.hashCode() == d.hashCode()) {
+ errln("GregorianCalendar hash code ignores cutover");
+ }
+ }
+
+ /**
+ * GregorianCalendar.equals() ignores cutover date
+ */
+ public void Test4141665() {
+ GregorianCalendar cal = new GregorianCalendar();
+ GregorianCalendar cal2 = (GregorianCalendar)cal.clone();
+ Date cut = cal.getGregorianChange();
+ Date cut2 = new Date(cut.getTime() + 100*24*60*60*1000L); // 100 days later
+ if (!cal.equals(cal2)) {
+ errln("Cloned GregorianCalendars not equal");
+ }
+ cal2.setGregorianChange(cut2);
+ if (cal.equals(cal2)) {
+ errln("GregorianCalendar.equals() ignores cutover");
+ }
+ }
+
+ /**
+ * Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar.roll()
+ * when IllegalArgumentException should be.
+ */
+ public void Test4142933() {
+ GregorianCalendar calendar = new GregorianCalendar();
+ try {
+ calendar.roll(-1, true);
+ errln("Test failed, no exception trown");
+ }
+ catch (IllegalArgumentException e) {
+ // OK: Do nothing
+ // logln("Test passed");
+ }
+ catch (Exception e) {
+ errln("Test failed. Unexpected exception is thrown: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
+ * confusing; unless the time zone has a raw offset of zero, one or the
+ * other of these will wrap. We've modified the test given in the bug
+ * report to therefore only check the behavior of a calendar with a zero raw
+ * offset zone.
+ */
+ public void Test4145158() {
+ GregorianCalendar calendar = new GregorianCalendar();
+
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+
+ calendar.setTime(new Date(Long.MIN_VALUE));
+ int year1 = calendar.get(Calendar.YEAR);
+ int era1 = calendar.get(Calendar.ERA);
+
+ calendar.setTime(new Date(Long.MAX_VALUE));
+ int year2 = calendar.get(Calendar.YEAR);
+ int era2 = calendar.get(Calendar.ERA);
+
+ if (year1 == year2 && era1 == era2) {
+ errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
+ }
+ }
+
+ /**
+ * Maximum value for YEAR field wrong.
+ */
+ public void Test4145983() {
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
+ Date[] DATES = { new Date(Long.MAX_VALUE), new Date(Long.MIN_VALUE) };
+ for (int i=0; i<DATES.length; ++i) {
+ calendar.setTime(DATES[i]);
+ int year = calendar.get(Calendar.YEAR);
+ int maxYear = calendar.getMaximum(Calendar.YEAR);
+ if (year > maxYear) {
+ errln("Failed for "+DATES[i].getTime()+" ms: year=" +
+ year + ", maxYear=" + maxYear);
+ }
+ }
+ }
+
+ /**
+ * This is a bug in the validation code of GregorianCalendar. As reported,
+ * the bug seems worse than it really is, due to a bug in the way the bug
+ * report test was written. In reality the bug is restricted to the DAY_OF_YEAR
+ * field. - liu 6/29/98
+ */
+ public void Test4147269() {
+ final String[] fieldName = {
+ "ERA",
+ "YEAR",
+ "MONTH",
+ "WEEK_OF_YEAR",
+ "WEEK_OF_MONTH",
+ "DAY_OF_MONTH",
+ "DAY_OF_YEAR",
+ "DAY_OF_WEEK",
+ "DAY_OF_WEEK_IN_MONTH",
+ "AM_PM",
+ "HOUR",
+ "HOUR_OF_DAY",
+ "MINUTE",
+ "SECOND",
+ "MILLISECOND",
+ "ZONE_OFFSET",
+ "DST_OFFSET"
+ };
+ GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setLenient(false);
+ Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date
+ for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+ calendar.setTime(date);
+ // Note: In the bug report, getActualMaximum() was called instead
+ // of getMaximum() -- this was an error. The validation code doesn't
+ // use getActualMaximum(), since that's too costly.
+ int max = calendar.getMaximum(field);
+ int value = max+1;
+ calendar.set(field, value);
+ try {
+ calendar.getTime(); // Force time computation
+ // We expect an exception to be thrown. If we fall through
+ // to the next line, then we have a bug.
+ errln("Test failed with field " + fieldName[field] +
+ ", date before: " + date +
+ ", date after: " + calendar.getTime() +
+ ", value: " + value + " (max = " + max +")");
+ } catch (IllegalArgumentException e) {}
+ }
+ }
+
+ /**
+ * Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)
+ * doesn't behave as a pure Julian calendar.
+ * CANNOT REPRODUCE THIS BUG
+ */
+ public void Test4149677() {
+ TimeZone[] zones = { TimeZone.getTimeZone("GMT"),
+ TimeZone.getTimeZone("PST"),
+ TimeZone.getTimeZone("EAT") };
+ for (int i=0; i<zones.length; ++i) {
+ GregorianCalendar calendar = new GregorianCalendar(zones[i]);
+
+ // Make sure extreme values don't wrap around
+ calendar.setTime(new Date(Long.MIN_VALUE));
+ if (calendar.get(Calendar.ERA) != GregorianCalendar.BC) {
+ errln("Fail: Date(Long.MIN_VALUE) has an AD year in " + zones[i]);
+ }
+ calendar.setTime(new Date(Long.MAX_VALUE));
+ if (calendar.get(Calendar.ERA) != GregorianCalendar.AD) {
+ errln("Fail: Date(Long.MAX_VALUE) has a BC year in " + zones[i]);
+ }
+
+ calendar.setGregorianChange(new Date(Long.MAX_VALUE));
+ // to obtain a pure Julian calendar
+
+ boolean is100Leap = calendar.isLeapYear(100);
+ if (!is100Leap) {
+ errln("test failed with zone " + zones[i].getID());
+ errln(" cutover date is Date(Long.MAX_VALUE)");
+ errln(" isLeapYear(100) returns: " + is100Leap);
+ }
+ }
+ }
+
+ /**
+ * Calendar and Date HOUR broken. If HOUR is out-of-range, Calendar
+ * and Date classes will misbehave.
+ */
+ public void Test4162587() {
+ TimeZone savedTz = TimeZone.getDefault();
+ TimeZone tz = TimeZone.getTimeZone("PST");
+ TimeZone.setDefault(tz);
+ GregorianCalendar cal = new GregorianCalendar(tz);
+ Date d;
+
+ try {
+ for (int i=0; i<5; ++i) {
+ if (i>0) logln("---");
+
+ cal.clear();
+ cal.set(1998, Calendar.APRIL, 5, i, 0);
+ d = cal.getTime();
+ String s0 = d.toString();
+ logln("0 " + i + ": " + s0);
+
+ cal.clear();
+ cal.set(1998, Calendar.APRIL, 4, i+24, 0);
+ d = cal.getTime();
+ String sPlus = d.toString();
+ logln("+ " + i + ": " + sPlus);
+
+ cal.clear();
+ cal.set(1998, Calendar.APRIL, 6, i-24, 0);
+ d = cal.getTime();
+ String sMinus = d.toString();
+ logln("- " + i + ": " + sMinus);
+
+ if (!s0.equals(sPlus) || !s0.equals(sMinus)) {
+ errln("Fail: All three lines must match");
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(savedTz);
+ }
+ }
+
+ /**
+ * Adding 12 months behaves differently from adding 1 year
+ */
+ public void Test4165343() {
+ GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29);
+ Date start = calendar.getTime();
+ logln("init date: " + start);
+ calendar.add(Calendar.MONTH, 12);
+ Date date1 = calendar.getTime();
+ logln("after adding 12 months: " + date1);
+ calendar.setTime(start);
+ calendar.add(Calendar.YEAR, 1);
+ Date date2 = calendar.getTime();
+ logln("after adding one year : " + date2);
+ if (date1.equals(date2)) {
+ logln("Test passed");
+ } else {
+ errln("Test failed");
+ }
+ }
+
+ /**
+ * GregorianCalendar.getActualMaximum() does not account for first day of week.
+ */
+ public void Test4166109() {
+ /* Test month:
+ *
+ * March 1998
+ * Su Mo Tu We Th Fr Sa
+ * 1 2 3 4 5 6 7
+ * 8 9 10 11 12 13 14
+ * 15 16 17 18 19 20 21
+ * 22 23 24 25 26 27 28
+ * 29 30 31
+ */
+ boolean passed = true;
+ int field = Calendar.WEEK_OF_MONTH;
+
+ GregorianCalendar calendar = new GregorianCalendar(Locale.US);
+ calendar.set(1998, Calendar.MARCH, 1);
+ calendar.setMinimalDaysInFirstWeek(1);
+ logln("Date: " + calendar.getTime());
+
+ int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH);
+
+ for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) {
+ calendar.setFirstDayOfWeek(firstInWeek);
+ int returned = calendar.getActualMaximum(field);
+ int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
+
+ logln("First day of week = " + firstInWeek +
+ " getActualMaximum(WEEK_OF_MONTH) = " + returned +
+ " expected = " + expected +
+ ((returned == expected) ? " ok" : " FAIL"));
+
+ if (returned != expected) {
+ passed = false;
+ }
+ }
+ if (!passed) {
+ errln("Test failed");
+ }
+ }
+
+ /**
+ * Calendar.getActualMaximum(YEAR) works wrong.
+ *
+ * Note: Before 1.5, this test case assumed that
+ * setGregorianChange didn't change object's date. But it was
+ * changed. See 4928615.
+ */
+ public void Test4167060() {
+ int field = Calendar.YEAR;
+ DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G",
+ Locale.US);
+
+ int[][] dates = {
+ // year, month, day of month
+ { 100, Calendar.NOVEMBER, 1 },
+ { -99 /*100BC*/, Calendar.JANUARY, 1 },
+ { 1996, Calendar.FEBRUARY, 29 }};
+
+ String[] id = { "Hybrid", "Gregorian", "Julian" };
+
+ for (int k=0; k<3; ++k) {
+ logln("--- " + id[k] + " ---");
+
+ for (int j = 0; j < dates.length; ++j) {
+ GregorianCalendar calendar = new GregorianCalendar();
+ if (k == 1) {
+ calendar.setGregorianChange(new Date(Long.MIN_VALUE));
+ } else if (k == 2) {
+ calendar.setGregorianChange(new Date(Long.MAX_VALUE));
+ }
+ calendar.set(dates[j][0], dates[j][1], dates[j][2]);
+ format.setCalendar((Calendar)calendar.clone());
+
+ Date dateBefore = calendar.getTime();
+
+ int maxYear = calendar.getActualMaximum(field);
+ logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime()));
+ logln("date before: " + format.format(dateBefore));
+
+ int years[] = {2000, maxYear-1, maxYear, maxYear+1};
+
+ for (int i = 0; i < years.length; i++) {
+ boolean valid = years[i] <= maxYear;
+ calendar.set(field, years[i]);
+ Date dateAfter = calendar.getTime();
+ int newYear = calendar.get(field);
+ calendar.setTime(dateBefore); // restore calendar for next use
+
+ logln(" Year " + years[i] + (valid? " ok " : " bad") +
+ " => " + format.format(dateAfter));
+ if (valid && newYear != years[i]) {
+ errln(" FAIL: " + newYear + " should be valid; date, month and time shouldn't change");
+ } else if (!valid && newYear == years[i]) {
+ errln(" FAIL: " + newYear + " should be invalid");
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Calendar.roll broken
+ * This bug relies on the TimeZone bug 4173604 to also be fixed.
+ */
+ public void Test4173516() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ int fieldsList[][] = {
+ { 1997, Calendar.FEBRUARY, 1, 10, 45, 15, 900 },
+ { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 },
+ // test case for 4960642 with default cutover
+ { 1582, Calendar.OCTOBER, 4, 23, 59, 59, 999 },
+ };
+ String[] fieldNames = {
+ "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
+ "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH",
+ "AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND",
+ "ZONE_OFFSET", "DST_OFFSET"
+ };
+
+ Locale savedLocale = Locale.getDefault();
+ Locale.setDefault(Locale.US);
+ int limit = 40;
+
+ try {
+ GregorianCalendar cal = new GregorianCalendar();
+
+ cal.setTime(new Date(0));
+ cal.roll(Calendar.HOUR, 0x7F000000);
+ cal.roll(Calendar.HOUR, -0x7F000000);
+ if (cal.getTime().getTime() != 0) {
+ errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime());
+ }
+
+ for (int op=0; op<2; ++op) {
+ logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll"));
+
+ for (int field=0; field < Calendar.FIELD_COUNT; ++field) {
+ if (field != Calendar.ZONE_OFFSET &&
+ field != Calendar.DST_OFFSET) {
+ for (int j=0; j<fieldsList.length; ++j) {
+ int fields[] = fieldsList[j];
+ cal.clear();
+ cal.set(fields[0], fields[1], fields[2],
+ fields[3], fields[4], fields[5]);
+ cal.set(Calendar.MILLISECOND, fields[6]);
+ for (int i = 0; i < 2*limit; i++) {
+ if (op == 0) {
+ cal.add(field, i < limit ? 1 : -1);
+ } else {
+ cal.roll(field, i < limit ? 1 : -1);
+ }
+ }
+
+ if (cal.get(Calendar.YEAR) != fields[0] ||
+ cal.get(Calendar.MONTH) != fields[1] ||
+ cal.get(Calendar.DATE) != fields[2] ||
+ cal.get(Calendar.HOUR_OF_DAY) != fields[3] ||
+ cal.get(Calendar.MINUTE) != fields[4] ||
+ cal.get(Calendar.SECOND) != fields[5] ||
+ cal.get(Calendar.MILLISECOND) != fields[6]) {
+ errln("Field " + field +
+ " (" + fieldNames[field] +
+ ") FAIL, expected " +
+ fields[0] +
+ "/" + (fields[1] + 1) +
+ "/" + fields[2] +
+ " " + fields[3] +
+ ":" + fields[4] +
+ ":" + fields[5] +
+ "." + fields[6] +
+ ", got " + cal.get(Calendar.YEAR) +
+ "/" + (cal.get(Calendar.MONTH) + 1) +
+ "/" + cal.get(Calendar.DATE) +
+ " " + cal.get(Calendar.HOUR_OF_DAY) +
+ ":" + cal.get(Calendar.MINUTE) +
+ ":" + cal.get(Calendar.SECOND) +
+ "." + cal.get(Calendar.MILLISECOND));
+
+ cal.clear();
+ cal.set(fields[0], fields[1], fields[2],
+ fields[3], fields[4], fields[5]);
+ cal.set(Calendar.MILLISECOND, fields[6]);
+ errln(cal.get(Calendar.YEAR) +
+ "/" + (cal.get(Calendar.MONTH) + 1) +
+ "/" + cal.get(Calendar.DATE) +
+ " " + cal.get(Calendar.HOUR_OF_DAY) +
+ ":" + cal.get(Calendar.MINUTE) +
+ ":" + cal.get(Calendar.SECOND) +
+ "." + cal.get(Calendar.MILLISECOND));
+
+ long prev = cal.getTime().getTime();
+ for (int i = 0; i < 2*limit; i++) {
+ if (op == 0) {
+ cal.add(field, i < limit ? 1 : -1);
+ } else {
+ cal.roll(field, i < limit ? 1 : -1);
+ }
+ long t = cal.getTime().getTime();
+ long delta = t - prev;
+ prev = t;
+ errln((op == 0 ? "add(" : "roll(") +
+ fieldNames[field] + ", " +
+ (i < limit ? "+" : "-") + "1) => " +
+ cal.get(Calendar.YEAR) +
+ "/" + (cal.get(Calendar.MONTH) + 1) +
+ "/" + cal.get(Calendar.DATE) +
+ " " + cal.get(Calendar.HOUR_OF_DAY) +
+ ":" + cal.get(Calendar.MINUTE) +
+ ":" + cal.get(Calendar.SECOND) +
+ "." + cal.get(Calendar.MILLISECOND) +
+ " d=" + delta);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ public void Test4174361() {
+ GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29);
+
+ calendar.add(Calendar.MONTH, 10);
+ Date date1 = calendar.getTime();
+ int d1 = calendar.get(Calendar.DAY_OF_MONTH);
+
+ calendar = new GregorianCalendar(1996, 1, 29);
+ calendar.add(Calendar.MONTH, 11);
+ Date date2 = calendar.getTime();
+ int d2 = calendar.get(Calendar.DAY_OF_MONTH);
+
+ if (d1 != d2) {
+ errln("adding months to Feb 29 broken");
+ }
+ }
+
+ /**
+ * Calendar does not update field values when setTimeZone is called.
+ */
+ public void Test4177484() {
+ TimeZone PST = TimeZone.getTimeZone("PST");
+ TimeZone EST = TimeZone.getTimeZone("EST");
+
+ Calendar cal = Calendar.getInstance(PST, Locale.US);
+ cal.clear();
+ cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary
+ int h1 = cal.get(Calendar.HOUR_OF_DAY);
+ cal.setTimeZone(EST);
+ int h2 = cal.get(Calendar.HOUR_OF_DAY);
+ if (h1 == h2) {
+ errln("FAIL: Fields not updated after setTimeZone");
+ }
+
+ // getTime() must NOT change when time zone is changed.
+ // getTime() returns zone-independent time in ms.
+ cal.clear();
+ cal.setTimeZone(PST);
+ cal.set(Calendar.HOUR_OF_DAY, 10);
+ Date pst10 = cal.getTime();
+ cal.setTimeZone(EST);
+ Date est10 = cal.getTime();
+ if (!pst10.equals(est10)) {
+ errln("FAIL: setTimeZone changed time");
+ }
+ }
+
+ /**
+ * Week of year is wrong at the start and end of the year.
+ */
+ public void Test4197699() {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setFirstDayOfWeek(Calendar.MONDAY);
+ cal.setMinimalDaysInFirstWeek(4);
+ DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy 'DOY='D 'WOY='w");
+ fmt.setCalendar(cal);
+
+ int[] DATA = {
+ 2000, Calendar.JANUARY, 1, 52,
+ 2001, Calendar.DECEMBER, 31, 1,
+ };
+
+ for (int i=0; i<DATA.length; ) {
+ cal.set(DATA[i++], DATA[i++], DATA[i++]);
+ int expWOY = DATA[i++];
+ int actWOY = cal.get(Calendar.WEEK_OF_YEAR);
+ if (expWOY == actWOY) {
+ logln("Ok: " + fmt.format(cal.getTime()));
+ } else {
+ errln("FAIL: " + fmt.format(cal.getTime())
+ + ", expected WOY=" + expWOY);
+ cal.add(Calendar.DATE, -8);
+ for (int j=0; j<14; ++j) {
+ cal.add(Calendar.DATE, 1);
+ logln(fmt.format(cal.getTime()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Calendar DAY_OF_WEEK_IN_MONTH fields->time broken. The problem
+ * is in the field disambiguation code in GregorianCalendar. This
+ * code is supposed to choose the most recent set of fields
+ * among the following:
+ *
+ * MONTH + DAY_OF_MONTH
+ * MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ * MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ * DAY_OF_YEAR
+ * WEEK_OF_YEAR + DAY_OF_WEEK
+ */
+ public void Test4209071() {
+ Calendar cal = Calendar.getInstance(Locale.US);
+
+ // General field setting test
+ int Y = 1995 - 1900;
+
+ Object[] FIELD_DATA = {
+ // Add new test cases as needed.
+
+ // 0
+ new int[] {}, new Date(Y, Calendar.JANUARY, 1),
+ // 1
+ new int[] { Calendar.MONTH, Calendar.MARCH },
+ new Date(Y, Calendar.MARCH, 1),
+ // 2
+ new int[] { Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY },
+ new Date(Y, Calendar.JANUARY, 4),
+ // 3
+ new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
+ Calendar.DAY_OF_MONTH, 18, },
+ new Date(Y, Calendar.JANUARY, 18),
+ // 4
+ new int[] { Calendar.DAY_OF_MONTH, 18,
+ Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+ new Date(Y, Calendar.JANUARY, 18),
+ // 5 (WOM -1 is in previous month)
+ new int[] { Calendar.DAY_OF_MONTH, 18,
+ Calendar.WEEK_OF_MONTH, -1,
+ Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+ new Date(Y-1, Calendar.DECEMBER, 22),
+ // 6
+ new int[] { Calendar.DAY_OF_MONTH, 18,
+ Calendar.WEEK_OF_MONTH, 4,
+ Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+ new Date(Y, Calendar.JANUARY, 26),
+ // 7 (DIM -1 is in same month)
+ new int[] { Calendar.DAY_OF_MONTH, 18,
+ Calendar.DAY_OF_WEEK_IN_MONTH, -1,
+ Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },
+ new Date(Y, Calendar.JANUARY, 26),
+ // 8
+ new int[] { Calendar.WEEK_OF_YEAR, 9,
+ Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, },
+ new Date(Y, Calendar.MARCH, 1),
+ // 9
+ new int[] { Calendar.MONTH, Calendar.OCTOBER,
+ Calendar.DAY_OF_WEEK_IN_MONTH, 1,
+ Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
+ new Date(Y, Calendar.OCTOBER, 6),
+ // 10
+ new int[] { Calendar.MONTH, Calendar.OCTOBER,
+ Calendar.WEEK_OF_MONTH, 2,
+ Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },
+ new Date(Y, Calendar.OCTOBER, 13),
+ // 11
+ new int[] { Calendar.MONTH, Calendar.OCTOBER,
+ Calendar.DAY_OF_MONTH, 15,
+ Calendar.DAY_OF_YEAR, 222, },
+ new Date(Y, Calendar.AUGUST, 10),
+ // 12
+ new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
+ Calendar.MONTH, Calendar.DECEMBER, },
+ new Date(Y, Calendar.DECEMBER, 7),
+ };
+
+ for (int i=0; i<FIELD_DATA.length; i+=2) {
+ int[] fields = (int[]) FIELD_DATA[i];
+ Date exp = (Date) FIELD_DATA[i+1];
+
+ cal.clear();
+ cal.set(Calendar.YEAR, Y + 1900);
+ for (int j=0; j<fields.length; j+=2) {
+ cal.set(fields[j], fields[j+1]);
+ }
+
+ Date act = cal.getTime();
+ if (!act.equals(exp)) {
+ errln("FAIL: Test " + (i/2) + " got " + act +
+ ", want " + exp +
+ " (see test/java/util/Calendar/CalendarRegression.java");
+ }
+ }
+
+ // Test specific failure reported in bug
+ Object[] DATA = {
+ new Integer(1), new Date(1997-1900, Calendar.JANUARY, 5),
+ new Integer(4), new Date(1997-1900, Calendar.JANUARY, 26),
+ new Integer(8), new Date(1997-1900, Calendar.FEBRUARY, 23),
+ new Integer(-1), new Date(1997-1900, Calendar.JANUARY, 26),
+ new Integer(-4), new Date(1997-1900, Calendar.JANUARY, 5),
+ new Integer(-8), new Date(1996-1900, Calendar.DECEMBER, 8),
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ cal.clear();
+ cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,
+ ((Number) DATA[i]).intValue());
+ cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
+ cal.set(Calendar.MONTH, Calendar.JANUARY);
+ cal.set(Calendar.YEAR, 1997);
+ Date actual = cal.getTime();
+ if (!actual.equals(DATA[i+1])) {
+ errln("FAIL: Sunday " + DATA[i] +
+ " of Jan 1997 -> " + actual +
+ ", want " + DATA[i+1]);
+ }
+ }
+ }
+
+ public void Test4288792() throws Exception
+ {
+ TimeZone savedTZ = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ GregorianCalendar cal = new GregorianCalendar();
+ try {
+ for (int i = 1900; i < 2100; i++) {
+ for (int j1 = 1; j1 <= 7; j1++) {
+ // Loop for MinimalDaysInFirstWeek: 1..7
+ for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) {
+ // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+ cal.clear();
+ cal.setMinimalDaysInFirstWeek(j1);
+ cal.setFirstDayOfWeek(j);
+ cal.set(Calendar.YEAR, i);
+ int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR);
+ cal.set(Calendar.WEEK_OF_YEAR, maxWeek);
+ cal.set(Calendar.DAY_OF_WEEK, j);
+
+ for (int k = 1; k < 7; k++) {
+ cal.add(Calendar.DATE, 1);
+ int WOY = cal.get(Calendar.WEEK_OF_YEAR);
+ if (WOY != maxWeek) {
+ errln(cal.getTime() + ",got=" + WOY
+ + ",expected=" + maxWeek
+ + ",min=" + j1 + ",first=" + j);
+ }
+ }
+
+ cal.add(Calendar.DATE, 1);
+ int WOY = cal.get(Calendar.WEEK_OF_YEAR);
+ if (WOY != 1) {
+ errln(cal.getTime() + ",got=" + WOY
+ + ",expected=1,min=" + j1 + ",first" + j);
+ }
+ }
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(savedTZ);
+ }
+ }
+
+ public void Test4328747() throws Exception {
+ Calendar c = (Calendar)Calendar.getInstance(Locale.US);
+ c.clear();
+ c.set(1966,0,1); // 1 jan 1966
+
+ // serialize
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream s = new ObjectOutputStream(out);
+ s.writeObject(c);
+ s.flush();
+
+ // deserialize
+ ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+ Calendar result = (Calendar)t.readObject();
+
+ // let recalculate fields with the same UTC time
+ result.setTime(result.getTime());
+ // Bug gives 1965 11 19
+ if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0)
+ || (result.get(c.DATE) != 1)) {
+ errln("deserialized Calendar returned wrong date field(s): "
+ + result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE)
+ + ", expected 1966/0/1");
+ }
+ }
+
+ /**
+ * Test whether Calendar can be serialized/deserialized correctly
+ * even if invalid/customized TimeZone is used.
+ */
+ public void Test4413980() {
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ try {
+ boolean pass = true;
+ String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",
+ "GMT+3:00", "GMT-01:30"};
+ for (int i = 0; i < IDs.length; i++) {
+ TimeZone tz = TimeZone.getTimeZone(IDs[i]);
+ TimeZone.setDefault(tz);
+
+ Calendar c = (Calendar)Calendar.getInstance();
+
+ // serialize
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream s = new ObjectOutputStream(out);
+ s.writeObject(c);
+ s.flush();
+
+ // deserialize
+ ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
+
+ if (!c.equals(t.readObject())) {
+ pass = false;
+ logln("Calendar instance which uses TimeZone <" +
+ IDs[i] + "> is incorrectly serialized/deserialized.");
+ } else {
+ logln("Calendar instance which uses TimeZone <" +
+ IDs[i] + "> is correctly serialized/deserialized.");
+ }
+ }
+ if (!pass) {
+ errln("Fail: Calendar serialization/equality bug");
+ }
+ }
+ catch (IOException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ catch (ClassNotFoundException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ finally {
+ TimeZone.setDefault(savedTimeZone);
+ }
+ }
+
+ /**
+ * 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week
+ */
+ public void Test4546637() {
+ GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04);
+ day.setMinimalDaysInFirstWeek(1);
+ int wom = day.get(Calendar.WEEK_OF_MONTH);
+
+ day.setFirstDayOfWeek(Calendar.MONDAY);
+ if (day.get(Calendar.WEEK_OF_MONTH) != 1) {
+ errln("Fail: 2001/11/4 must be the first week of the month.");
+ }
+ }
+
+ /**
+ * 4623997: GregorianCalendar returns bad WEEK_OF_YEAR
+ */
+ public void Test4623997() {
+ GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1);
+
+ int dow = cal.get(GregorianCalendar.DAY_OF_WEEK);
+
+ cal.setFirstDayOfWeek(GregorianCalendar.MONDAY);
+ cal.setMinimalDaysInFirstWeek(4);
+
+ if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) {
+ errln("Fail: 2000/1/1 must be the 52nd week of the year.");
+ }
+ }
+
+ /**
+ * 4685354: Handling of Calendar fields setting state is broken
+ *
+ * <p>Need to use SimpleDateFormat to test because a call to
+ * get(int) changes internal states of a Calendar.
+ */
+ public void Test4685354() {
+ if (Locale.getDefault().equals(new Locale("hi", "IN"))) {
+ return;
+ }
+
+ Calendar calendar = Calendar.getInstance(Locale.US);
+ DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+ String expected = "1999/12/31";
+ Date t;
+ String s;
+
+ try {
+ calendar.setTime(df.parse(expected));
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected parse exception", e);
+ }
+
+ t = calendar.getTime();
+ calendar.set(Calendar.DAY_OF_MONTH, 33);
+ t = calendar.getTime();
+ calendar.set(Calendar.DAY_OF_MONTH, 0);
+ s = df.format(calendar.getTime());
+ if (!expected.equals(s)) {
+ errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s);
+ }
+
+ // The same thing must work with ZONE_OFFSET set
+ try {
+ calendar.setTime(df.parse(expected));
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected parse exception", e);
+ }
+ t = calendar.getTime();
+ calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+ calendar.set(Calendar.DAY_OF_MONTH, 33);
+ t = calendar.getTime();
+ calendar.set(Calendar.DAY_OF_MONTH, 0);
+ s = df.format(calendar.getTime());
+ if (!expected.equals(s)) {
+ errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s);
+ }
+
+ expected = "1999/12/24"; // 0th week of 2000
+ calendar.clear();
+ Date initialDate = null;
+ try {
+ initialDate = df.parse(expected);
+ calendar.setTime(initialDate);
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected parse exception", e);
+ }
+ t = calendar.getTime();
+ calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+ // jump to the next year
+ calendar.set(Calendar.WEEK_OF_YEAR, 100);
+ t = calendar.getTime();
+ calendar.set(Calendar.WEEK_OF_YEAR, 0);
+ s = df.format(calendar.getTime());
+ if (!expected.equals(s)) {
+ errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s);
+ }
+ // change the state back
+ calendar.clear();
+ calendar.setTime(initialDate);
+ calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));
+ // jump to next month
+ calendar.set(Calendar.WEEK_OF_MONTH, 7);
+ t = calendar.getTime();
+ calendar.set(Calendar.WEEK_OF_MONTH, 0);
+ s = df.format(calendar.getTime());
+ if (!expected.equals(s)) {
+ errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s);
+ }
+
+ // Make sure the time fields work correctly.
+ calendar.clear();
+ df = new SimpleDateFormat("HH:mm:ss");
+ TimeZone tz = TimeZone.getTimeZone("GMT");
+ df.setTimeZone(tz);
+ calendar.setTimeZone(tz);
+ expected = "22:59:59";
+ try {
+ calendar.setTime(df.parse(expected));
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected parse exception", e);
+ }
+ t = calendar.getTime();
+ // time should be 22:59:59.
+ calendar.set(Calendar.MINUTE, 61);
+ // time should be 23:01:59.
+ t = calendar.getTime();
+ calendar.set(Calendar.MINUTE, -1);
+ // time should be back to 22:59:59.
+ s = df.format(calendar.getTime());
+ if (!expected.equals(s)) {
+ errln("MINUTE: expected: " + expected + ", got: " + s);
+ }
+ }
+
+ /**
+ * 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value
+ *
+ * <p>Need to use SimpleDateFormat to test because a call to
+ * get(int) changes internal states of a Calendar.
+ */
+ public void Test4655637() {
+ // Skip this test case if it's Thai locale
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTime(new Date(1029814211523L));
+ cal.set(Calendar.YEAR, 2001);
+ Date t = cal.getTime();
+ cal.set(Calendar.MONTH, Calendar.JANUARY);
+ t = cal.getTime();
+
+ cal.set(Calendar.DAY_OF_MONTH, 8);
+ t = cal.getTime();
+
+ cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
+ DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+ String expected = "2001/01/08";
+ String s = df.format(cal.getTime());
+ if (!expected.equals(s)) {
+ errln("expected: " + expected + ", got: " + s);
+ }
+ }
+
+ /**
+ * 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime().
+ *
+ * <p>Need to use SimpleDateFormat to test because a call to
+ * get(int) changes internal states of a Calendar.
+ *
+ * <p>This test case throws ArrayIndexOutOfBoundsException without the fix.
+ */
+ public void Test4683492() {
+ Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0);
+ cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
+ cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
+ cal.set(Calendar.MONTH, 12);
+ DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);
+ String expected = "2003/01/31";
+ String s = df.format(cal.getTime());
+ if (!expected.equals(s)) {
+ errln("expected: " + expected + ", got: " + s);
+ }
+ }
+
+ /**
+ * 4080631: Calendar.hashCode is amazingly bad
+ */
+ public void Test4080631() {
+ Calendar cal = Calendar.getInstance();
+ int h1 = cal.hashCode();
+ cal.add(cal.SECOND, +1);
+ int h2 = cal.hashCode();
+ Calendar cal2 = (Calendar) cal.clone();
+ cal.add(cal.MILLISECOND, +1);
+ int h3 = cal.hashCode();
+ logln("hash code: h1="+h1+", h2="+h2+", h3="+h3);
+ if (h1 == h2 || h1 == h3 || h2 == h3) {
+ errln("hash code is poor: hashCode="+h1);
+ }
+ h2 = cal2.hashCode();
+ cal.add(cal.MILLISECOND, -1);
+ int h4 = cal.hashCode();
+ logln("hash code: h2="+h2+", h4="+h4);
+ if (cal.equals(cal2) && h2 != h4) {
+ errln("broken hash code: h2="+h2+", h4="+h4);
+ }
+ int x = cal.getFirstDayOfWeek() + 3;
+ if (x > cal.SATURDAY) {
+ x -= 7;
+ }
+ cal.setFirstDayOfWeek(x);
+ int h5 = cal.hashCode();
+ logln("hash code: h4="+h4+", h5="+h5);
+ if (h4 == h5) {
+ errln("has code is poor with first day of week param: hashCode="+h4);
+ }
+ }
+
+ /**
+ * 4125161: RFE: GregorianCalendar needs more era names (BCE and CE)
+ */
+ /*
+ public void Test4125161() throws Exception {
+ Class gc = GregorianCalendar.class;
+ Field f;
+ int mod;
+ f = gc.getDeclaredField("BCE");
+ mod = f.getModifiers();
+ if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
+ errln("BCE: wrong modifiers: " + mod);
+ }
+ f = gc.getDeclaredField("CE");
+ mod = f.getModifiers();
+ if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {
+ errln("CE: wrong modifiers: " + mod);
+ }
+ if (GregorianCalendar.BCE != GregorianCalendar.BC
+ || GregorianCalendar.CE != GregorianCalendar.AD) {
+ errln("Wrong BCE and/or CE values");
+ }
+ }
+ */
+
+ /**
+ * 4167995: GregorianCalendar.setGregorianChange() not to spec
+ */
+ public void Test4167995() {
+ Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT"));
+ logln("Hybrid: min date");
+ gc.setTime(new Date(Long.MIN_VALUE));
+ if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+ errln(gc.getMessage());
+ }
+ logln("Hybrid: max date");
+ gc.setTime(new Date(Long.MAX_VALUE));
+ if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+ errln(gc.getMessage());
+ }
+
+ gc.setGregorianChange(new Date(Long.MIN_VALUE));
+ logln("Gregorian: min date");
+ gc.setTime(new Date(Long.MIN_VALUE));
+ if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+ errln(gc.getMessage());
+ }
+ logln("Gregorian: max date");
+ gc.setTime(new Date(Long.MAX_VALUE));
+ if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+ errln(gc.getMessage());
+ }
+
+ gc.setGregorianChange(new Date(Long.MAX_VALUE));
+ logln("Julian: min date");
+ gc.setTime(new Date(Long.MIN_VALUE));
+ if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.BC)) {
+ errln(gc.getMessage());
+ }
+ logln("Julian: max date");
+ gc.setTime(new Date(Long.MAX_VALUE));
+ if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY)
+ || !gc.checkFieldValue(gc.ERA, gc.AD)) {
+ errln(gc.getMessage());
+ }
+ }
+
+ /**
+ * 4340146: Calendar.equals modifies state
+ */
+ public void Test4340146() {
+ Koyomi cal = new Koyomi();
+ cal.clear();
+ cal.set(2003, cal.OCTOBER, 32);
+ cal.equals(new Koyomi());
+ if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
+ errln(cal.getMessage());
+ }
+ new Koyomi().equals(cal);
+ if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ /**
+ * 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking
+ */
+ public void Test4639407() {
+ // The following operations in non-lenient mode shouldn't
+ // throw IllegalArgumentException.
+ Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati"));
+ cal.setLenient(false);
+ cal.set(2003, cal.OCTOBER, 10);
+ cal.getTime();
+ cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu"));
+ cal.set(2003, cal.OCTOBER, 10);
+ cal.getTime();
+ }
+
+ /**
+ * 4652815: rolling week-of-year back hundreds of weeks changes year
+ */
+ public void Test4652815() {
+ Koyomi cal = new Koyomi(Locale.US);
+ testRoll(cal, 2003, cal.SEPTEMBER, 29);
+ testRoll(cal, 2003, cal.DECEMBER, 24);
+ testRoll(cal, 1582, cal.DECEMBER, 19);
+ testRoll(cal, 1582, cal.DECEMBER, 20);
+ }
+
+ private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) {
+ cal.clear();
+ cal.set(year, month, dayOfMonth);
+ cal.getTime(); // normalize fields
+ logln("Roll backwards from " + cal.toDateString());
+ for (int i = 0; i < 1000; i++) {
+ cal.roll(cal.WEEK_OF_YEAR, -i);
+ if (!cal.checkFieldValue(cal.YEAR, year)) {
+ errln(cal.getMessage());
+ }
+ }
+ logln("Roll forewards from " + cal.toDateString());
+ for (int i = 0; i < 1000; i++) {
+ cal.roll(cal.WEEK_OF_YEAR, +i);
+ if (!cal.checkFieldValue(cal.YEAR, year)) {
+ errln(cal.getMessage());
+ }
+ }
+ }
+
+ /**
+ * 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era
+ */
+ public void Test4652830() {
+ Koyomi cal = new Koyomi(Locale.US);
+ cal.clear();
+ logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice");
+ cal.set(cal.ERA, cal.BC);
+ cal.set(9, cal.FEBRUARY, 28);
+ if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) {
+ errln(" wrong actual max of DAY_OF_YEAR: got "
+ + cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366);
+ }
+ cal.roll(cal.DAY_OF_MONTH, +1);
+ if (!cal.checkFieldValue(cal.ERA, cal.BC)
+ || !cal.checkDate(9, cal.FEBRUARY, 29)) {
+ errln(cal.getMessage());
+ }
+ cal.roll(cal.DAY_OF_MONTH, +1);
+ if (!cal.checkFieldValue(cal.ERA, cal.BC)
+ || !cal.checkDate(9, cal.FEBRUARY, 1)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ /**
+ * 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization
+ */
+ public void Test4740554() {
+ logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum");
+ Koyomi cal = new Koyomi(Locale.US);
+ cal.clear();
+ cal.set(1999, cal.FEBRUARY + 12, 1);
+ if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ /**
+ * 4936355: GregorianCalendar causes overflow/underflow with time of day calculation
+ */
+ public void Test4936355() {
+ Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT"));
+ cal.clear();
+ cal.set(1970, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE,
+ (long)Integer.MAX_VALUE * 60 * 60 * 1000);
+
+ cal.clear();
+ cal.set(1970, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE,
+ (long)Integer.MAX_VALUE * 60 * 60 * 1000);
+
+ cal.clear();
+ cal.set(1970, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE,
+ (long)Integer.MAX_VALUE * 60 * 1000);
+
+ cal.clear();
+ // Make sure to use Gregorian dates (before and after the
+ // set() call) for testing
+ cal.set(250000, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE,
+ (long)Integer.MIN_VALUE * 60 * 60 * 1000);
+
+ cal.clear();
+ cal.set(250000, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE,
+ (long)Integer.MIN_VALUE * 60 * 60 * 1000);
+
+ cal.clear();
+ cal.set(250000, cal.JANUARY, 1);
+ checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE,
+ (long)Integer.MIN_VALUE * 60 * 1000);
+ }
+
+ private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) {
+ long time = cal.getTimeInMillis();
+ cal.set(field, value);
+ long time2 = cal.getTimeInMillis();
+ if ((time + expectedDelta) != time2) {
+ String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE";
+ errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time2
+ + ", expected " + (time+expectedDelta));
+ }
+ }
+
+ /**
+ * 4722650: Calendar.equals can throw an exception in non-lenient
+ * (piggy-back tests for compareTo() which is new in 1.5)
+ */
+ public void Test4722650() {
+ Calendar cal1 = new GregorianCalendar();
+ cal1.clear();
+ Calendar cal2 = new GregorianCalendar();
+ cal2.clear();
+ cal2.setLenient(false);
+
+ cal1.set(2003, Calendar.OCTOBER, 31);
+ cal2.set(2003, Calendar.OCTOBER, 31);
+ try {
+ if (cal1.equals(cal2)) {
+ errln("lenient and non-lenient shouldn't be equal. (2003/10/31)");
+ }
+ if (cal1.compareTo(cal2) != 0) {
+ errln("cal1 and cal2 should represent the same time. (2003/10/31)");
+ }
+ } catch (IllegalArgumentException e) {
+ errln("equals threw IllegalArugumentException with non-lenient");
+ }
+
+ cal1.set(2003, Calendar.OCTOBER, 32);
+ cal2.set(2003, Calendar.OCTOBER, 32);
+ try {
+ if (cal1.equals(cal2)) {
+ errln("lenient and non-lenient shouldn't be equal. (2003/10/32)");
+ }
+ if (cal1.compareTo(cal2) != 0) {
+ errln("cal1 and cal2 should represent the same time. (2003/10/32)");
+ }
+ } catch (IllegalArgumentException e) {
+ errln("equals threw IllegalArugumentException with non-lenient");
+ }
+
+ cal1 = Calendar.getInstance(new Locale("th", "TH"));
+ cal1.setTimeInMillis(0L);
+ cal2 = Calendar.getInstance(Locale.US);
+ cal2.setTimeInMillis(0L);
+ if (cal1.equals(cal2)) {
+ errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)");
+ }
+ if (cal1.compareTo(cal2) != 0) {
+ errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)");
+ }
+ }
+
+ /**
+ * 4738710: API: Calendar comparison methods should be improved
+ */
+ public void Test4738710() {
+ Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30);
+ Comparable<Calendar> cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1);
+ Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2);
+ if (!(cal1.compareTo(cal0) > 0)) {
+ errln("!(cal1 > cal0)");
+ }
+ if (!(cal1.compareTo(cal2) < 0)) {
+ errln("!(cal1 < cal2)");
+ }
+ if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) {
+ errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)");
+ }
+
+ if (cal0.after(cal2)) {
+ errln("cal0 shouldn't be after cal2");
+ }
+ if (cal2.before(cal0)) {
+ errln("cal2 shouldn't be before cal0");
+ }
+
+ if (cal0.after(new Integer(0))) {
+ errln("cal0.after() returned true with an Integer.");
+ }
+ if (cal0.before(new Integer(0))) {
+ errln("cal0.before() returned true with an Integer.");
+ }
+ if (cal0.after(null)) {
+ errln("cal0.after() returned true with null.");
+ }
+ if (cal0.before(null)) {
+ errln("cal0.before() returned true with null.");
+ }
+ }
+
+ /**
+ * 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date
+ */
+ public void Test4633646() {
+ Koyomi cal = new Koyomi(Locale.US);
+ cal.setTime(new Date(2002-1900, 1-1, 28));
+ sub4633646(cal);
+
+ cal.setLenient(false);
+ cal.setTime(new Date(2002-1900, 1-1, 28));
+ sub4633646(cal);
+
+ cal = new Koyomi(Locale.US);
+ cal.clear();
+ cal.set(2002, cal.JANUARY, 28);
+ sub4633646(cal);
+
+ cal.clear();
+ cal.setLenient(false);
+ cal.set(2002, cal.JANUARY, 28);
+ sub4633646(cal);
+ }
+
+ void sub4633646(Koyomi cal) {
+ cal.getTime();
+ cal.set(cal.WEEK_OF_MONTH, 1);
+ if (cal.isLenient()) {
+ if (!cal.checkDate(2001, cal.DECEMBER, 31)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) {
+ errln(cal.getMessage());
+ }
+ } else {
+ try {
+ Date d = cal.getTime();
+ errln("didn't throw IllegalArgumentException in non-lenient");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ /**
+ * 4846659: Calendar: Both set() and roll() don't work for AM_PM time field
+ * (Partially fixed only roll as of 1.5)
+ */
+ public void Test4846659() {
+ Koyomi cal = new Koyomi();
+ cal.clear();
+ cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+ cal.getTime();
+ // Test roll()
+ cal.roll(cal.AM_PM, +1); // should turn to PM
+ if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
+ errln("roll: AM_PM didn't change to PM");
+ }
+
+ cal.clear();
+ cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+ cal.getTime();
+ // Test set()
+ cal.set(cal.AM_PM, cal.PM); // should turn to PM
+ if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {
+ errln("set: AM_PM didn't change to PM");
+ }
+
+ cal.clear();
+ cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);
+ cal.getTime();
+ cal.set(cal.AM_PM, cal.PM);
+ cal.set(cal.HOUR, 9);
+ if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) {
+ errln("set: both AM_PM and HOUT didn't change to PM");
+ }
+ }
+
+ /**
+ * 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek()
+ */
+ public void Test4822110() {
+ Koyomi cal = new Koyomi(Locale.US);
+ // June 2003
+ // S M Tu W Th F S
+ // 1 2 3 4 5 6 7
+ // 8 9 10 11 12 13 14
+ // 15 16 17 18 19 20 21
+ // 22 23 24 25 26 27 28
+ // 29 30
+ cal.clear();
+ // 6/1 to 6/7 should be the 1st week of June.
+ cal.set(2003, cal.JUNE, 2);
+ cal.getTime(); // Let cal calculate time.
+ cal.setFirstDayOfWeek(cal.MONDAY);
+ // Now 6/2 to 6/8 should be the 2nd week of June. Sunday of
+ // that week is 6/8.
+ logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH));
+ cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
+ logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY");
+ if (!cal.checkDate(2003, cal.JUNE, 8)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ /**
+ * 4973919: Inconsistent GregorianCalendar hashCode before and after serialization
+ */
+ public void Test4966499() throws Exception {
+ GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7);
+
+ // Serialize date1
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(date1);
+
+ byte[] buffer = baos.toByteArray();
+
+ // Deserialize it
+ ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ GregorianCalendar date2 = (GregorianCalendar)ois.readObject();
+
+ if (!date1.equals(date2)) {
+ errln("date1.equals(date2) != true");
+ }
+ if (date1.hashCode() != date2.hashCode()) {
+ errln("inconsistent hashCode() value (before=0x"
+ +Integer.toHexString(date1.hashCode())+
+ ", after=0x"+Integer.toHexString(date2.hashCode())+")");
+ }
+ }
+
+ /**
+ * 4980088: GregorianCalendar.getActualMaximum doesn't throw exception
+ */
+ public void Test4980088() {
+ GregorianCalendar cal = new GregorianCalendar();
+ try {
+ int x = cal.getMaximum(100);
+ errln("getMaximum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+
+ try {
+ int x = cal.getLeastMaximum(100);
+ errln("getLeastMaximum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+
+ try {
+ int x = cal.getActualMaximum(100);
+ errln("getActualMaximum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+
+ try {
+ int x = cal.getMinimum(100);
+ errln("getMinimum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+
+ try {
+ int x = cal.getGreatestMinimum(100);
+ errln("getGreatestMinimum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+
+ try {
+ int x = cal.getActualMinimum(100);
+ errln("getActualMinimum(100) didn't throw an exception.");
+ } catch (IndexOutOfBoundsException e) {
+ logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage());
+ }
+ }
+
+ /**
+ * 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value
+ */
+ public void Test4965624() {
+ // 5013094: This test case needs to use "GMT" to specify
+ // Gregorian cutover dates.
+ TimeZone savedZone = TimeZone.getDefault();
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ try {
+ Map<Date, Boolean> data = new HashMap<Date, Boolean>();
+ data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE);
+ data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE);
+ data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE);
+ data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE);
+ data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE);
+ data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE);
+ data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE);
+ data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE);
+
+ Iterator<Date> itr = data.keySet().iterator();
+ while (itr.hasNext()) {
+ Date d = itr.next();
+ boolean expected = data.get(d).booleanValue();
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setGregorianChange(d);
+ if (cal.isLeapYear(1000) != expected) {
+ errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) +
+ " with cutover date (Julian) " + d);
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(savedZone);
+ }
+ }
+
+ // Note that we can't use Date to produce Gregorian calendar dates
+ // before the default cutover date.
+ static Date getGregorianDate(int year, int month, int dayOfMonth) {
+ GregorianCalendar g = new GregorianCalendar();
+ // Make g a pure Gregorian calendar
+ g.setGregorianChange(new Date(Long.MIN_VALUE));
+ g.clear();
+ g.set(year, month, dayOfMonth);
+ return g.getTime();
+ }
+
+ /**
+ * 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 1
+ */
+ public void Test5006864() {
+ GregorianCalendar cal = new GregorianCalendar();
+ int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH);
+ if (min != 1) {
+ errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned "
+ + min + ", expected 1.");
+ }
+ min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH);
+ if (min != 1) {
+ errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned "
+ + min + ", expected 1.");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/CalendarTest.java b/test/java/util/Calendar/CalendarTest.java
new file mode 100644
index 0000000000..d8320295a6
--- /dev/null
+++ b/test/java/util/Calendar/CalendarTest.java
@@ -0,0 +1,1102 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4064654 4374886 4984320 4984574 4944795
+ * @library /java/text/testlib
+ * @summary test for Calendar
+ * @key randomness
+ */
+
+import java.util.*;
+import java.text.*;
+import java.io.*;
+
+public class CalendarTest extends IntlTest {
+ static final int ONE_DAY = 24*60*60*1000;
+ static final int EPOCH_JULIAN = 2440588;
+
+ public static void main(String argv[]) throws Exception {
+ new CalendarTest().run(argv);
+ }
+
+ /**
+ * Test the behavior of the GregorianCalendar around the changeover.
+ */
+ public void TestGregorianChangeover() {
+ TimeZone savedZone = TimeZone.getDefault();
+ /*
+ Changeover -7 days: 1582/9/28 dow=6
+ Changeover -6 days: 1582/9/29 dow=7
+ Changeover -5 days: 1582/9/30 dow=1
+ Changeover -4 days: 1582/10/1 dow=2
+ Changeover -3 days: 1582/10/2 dow=3
+ Changeover -2 days: 1582/10/3 dow=4
+ Changeover -1 days: 1582/10/4 dow=5
+ Changeover +0 days: 1582/10/15 dow=6
+ Changeover +1 days: 1582/10/16 dow=7
+ Changeover +2 days: 1582/10/17 dow=1
+ Changeover +3 days: 1582/10/18 dow=2
+ Changeover +4 days: 1582/10/19 dow=3
+ Changeover +5 days: 1582/10/20 dow=4
+ Changeover +6 days: 1582/10/21 dow=5
+ Changeover +7 days: 1582/10/22 dow=6
+ */
+ int MON[] = { 9, 9, 9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 };
+ int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 };
+ int DOW[] = { 6, 7, 1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6 };
+ // ^ <-Changeover Fri Oct 15 1582
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Date co = new Date(1582-1900, Calendar.OCTOBER, 15);
+ GregorianCalendar cal = new GregorianCalendar();
+ int j = 0;
+ for (int i = -7; i <= 7; ++i, ++j) {
+ Date d = new Date(co.getTime() + i*ONE_DAY);
+ cal.setTime(d);
+ int y = cal.get(Calendar.YEAR);
+ int mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY;
+ int dom = cal.get(Calendar.DATE);
+ int dow = cal.get(Calendar.DAY_OF_WEEK);
+
+ logln("Changeover " + (i>=0?"+":"") + i +
+ " days: " + y + "/" + mon + "/" + dom + " dow=" + dow);
+ if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j]) {
+ errln(" Fail: Above line is wrong");
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(savedZone);
+ }
+ }
+
+ /**
+ * Test the mapping between millis and fields. For the purposes
+ * of this test, we don't care about timezones and week data
+ * (first day of week, minimal days in first week).
+ */
+ public void TestMapping() {
+ TimeZone saveZone = TimeZone.getDefault();
+ int[] DATA = {
+ // Julian# Year Month DOM JULIAN:Year, Month, DOM
+ 2440588, 1970, Calendar.JANUARY, 1, 1969, Calendar.DECEMBER, 19,
+ 2415080, 1900, Calendar.MARCH, 1, 1900, Calendar.FEBRUARY, 17,
+ 2451604, 2000, Calendar.FEBRUARY, 29, 2000, Calendar.FEBRUARY, 16,
+ 2452269, 2001, Calendar.DECEMBER, 25, 2001, Calendar.DECEMBER, 12,
+ 2416526, 1904, Calendar.FEBRUARY, 15, 1904, Calendar.FEBRUARY, 2,
+ 2416656, 1904, Calendar.JUNE, 24, 1904, Calendar.JUNE, 11,
+ 1721426, 1, Calendar.JANUARY, 1, 1, Calendar.JANUARY, 3,
+ 2000000, 763, Calendar.SEPTEMBER, 18, 763, Calendar.SEPTEMBER, 14,
+ 4000000, 6239, Calendar.JULY, 12, 6239, Calendar.MAY, 28,
+ 8000000, 17191, Calendar.FEBRUARY, 26, 17190, Calendar.OCTOBER, 22,
+ 10000000, 22666, Calendar.DECEMBER, 20, 22666, Calendar.JULY, 5,
+ };
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+ Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
+ Date PURE_JULIAN = new Date(Long.MAX_VALUE);
+ GregorianCalendar cal = new GregorianCalendar();
+ for (int i = 0; i < DATA.length; i += 7) {
+ int julian = DATA[i];
+ int year = DATA[i+1];
+ int month = DATA[i+2];
+ int dom = DATA[i+3];
+ int year2, month2, dom2;
+ long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY;
+ String s;
+
+ // Test Gregorian computation
+ cal.setGregorianChange(PURE_GREGORIAN);
+ cal.clear();
+ cal.set(year, month, dom);
+ long calMillis = cal.getTime().getTime();
+ long delta = calMillis - millis;
+ cal.setTime(new Date(millis));
+ year2 = cal.get(Calendar.YEAR);
+ month2 = cal.get(Calendar.MONTH);
+ dom2 = cal.get(Calendar.DAY_OF_MONTH);
+ s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
+ " => " + calMillis +
+ " (" + ((float)delta/ONE_DAY) + " day delta) => " +
+ year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
+ if (delta != 0 || year != year2 || month != month2 ||
+ dom != dom2) {
+ errln(s + " FAIL");
+ } else {
+ logln(s);
+ }
+
+ // Test Julian computation
+ year = DATA[i+4];
+ month = DATA[i+5];
+ dom = DATA[i+6];
+ cal.setGregorianChange(PURE_JULIAN);
+ cal.clear();
+ cal.set(year, month, dom);
+ calMillis = cal.getTime().getTime();
+ delta = calMillis - millis;
+ cal.setTime(new Date(millis));
+ year2 = cal.get(Calendar.YEAR);
+ month2 = cal.get(Calendar.MONTH);
+ dom2 = cal.get(Calendar.DAY_OF_MONTH);
+ s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
+ " => " + calMillis +
+ " (" + ((float)delta/ONE_DAY) + " day delta) => " +
+ year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
+ if (delta != 0 || year != year2 || month != month2 ||
+ dom != dom2) {
+ errln(s + " FAIL");
+ } else {
+ logln(s);
+ }
+ }
+
+ cal.setGregorianChange(new Date(1582-1900, Calendar.OCTOBER, 15));
+ auxMapping(cal, 1582, Calendar.OCTOBER, 4);
+ auxMapping(cal, 1582, Calendar.OCTOBER, 15);
+ auxMapping(cal, 1582, Calendar.OCTOBER, 16);
+ for (int y = 800; y < 3000; y += 1+(int)100*Math.random()) {
+ for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; ++m) {
+ auxMapping(cal, y, m, 15);
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+ private void auxMapping(Calendar cal, int y, int m, int d) {
+ cal.clear();
+ cal.set(y, m, d);
+ long millis = cal.getTime().getTime();
+ cal.setTime(new Date(millis));
+ int year2 = cal.get(Calendar.YEAR);
+ int month2 = cal.get(Calendar.MONTH);
+ int dom2 = cal.get(Calendar.DAY_OF_MONTH);
+ if (y != year2 || m != month2 || dom2 != d)
+ errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " +
+ year2 + "-" + (month2+1) + "-" + dom2);
+ }
+
+ public void TestGenericAPI() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ String str;
+
+ Date when = new Date(90, Calendar.APRIL, 15);
+
+ String tzid = "TestZone";
+ int tzoffset = 123400;
+
+ SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid);
+ Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone());
+
+ if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed");
+
+ Calendar cal2 = Calendar.getInstance(cal.getTimeZone());
+
+ cal.setTime(when);
+ cal2.setTime(when);
+
+ if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed");
+ // if ((*cal != *cal2)) errln("FAIL: Calendar.operator!= failed");
+ if (!cal.equals(cal2) ||
+ cal.before(cal2) ||
+ cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+ cal2.setTime(new Date(when.getTime() + 1000));
+ if (cal.equals(cal2) ||
+ cal2.before(cal) ||
+ cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+ cal.roll(Calendar.SECOND, true);
+ if (!cal.equals(cal2) ||
+ cal.before(cal2) ||
+ cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+ // Roll back to January
+ cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH)));
+ if (cal.equals(cal2) ||
+ cal2.before(cal) ||
+ cal.after(cal2)) errln("FAIL: equals/before/after failed");
+
+ // C++ only
+ /* TimeZone z = cal.orphanTimeZone();
+ if (z.getID(str) != tzid ||
+ z.getRawOffset() != tzoffset)
+ errln("FAIL: orphanTimeZone failed");
+ */
+
+ for (int i = 0; i < 2; ++i) {
+ boolean lenient = ( i > 0 );
+ cal.setLenient(lenient);
+ if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed");
+ // Later: Check for lenient behavior
+ }
+
+ int i;
+ for (i = Calendar.SUNDAY; i <= Calendar.SATURDAY; ++i) {
+ cal.setFirstDayOfWeek(i);
+ if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
+ }
+
+ for (i = 0; i <= 7; ++i) {
+ cal.setMinimalDaysInFirstWeek(i);
+ if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
+ }
+
+ for (i = 0; i < Calendar.FIELD_COUNT; ++i) {
+ if (cal.getMinimum(i) != cal.getGreatestMinimum(i))
+ errln("FAIL: getMinimum doesn't match getGreatestMinimum for field " + i);
+ if (cal.getLeastMaximum(i) > cal.getMaximum(i))
+ errln("FAIL: getLeastMaximum larger than getMaximum for field " + i);
+ if (cal.getMinimum(i) >= cal.getMaximum(i))
+ errln("FAIL: getMinimum not less than getMaximum for field " + i);
+ }
+
+ cal.setTimeZone(TimeZone.getDefault());
+ cal.clear();
+ cal.set(1984, 5, 24);
+ if (cal.getTime().getTime() != new Date(84, 5, 24).getTime()) {
+ errln("FAIL: Calendar.set(3 args) failed");
+ logln(" Got: " + cal.getTime() + " Expected: " + new Date(84, 5, 24));
+ }
+
+ cal.clear();
+ cal.set(1985, 3, 2, 11, 49);
+ if (cal.getTime().getTime() != new Date(85, 3, 2, 11, 49).getTime()) {
+ errln("FAIL: Calendar.set(5 args) failed");
+ logln(" Got: " + cal.getTime() + " Expected: " + new Date(85, 3, 2, 11, 49));
+ }
+
+ cal.clear();
+ cal.set(1995, 9, 12, 1, 39, 55);
+ if (cal.getTime().getTime() != new Date(95, 9, 12, 1, 39, 55).getTime()) {
+ errln("FAIL: Calendar.set(6 args) failed");
+ logln(" Got: " + cal.getTime() + " Expected: " + new Date(95, 9, 12, 1, 39, 55));
+ }
+
+ cal.getTime();
+ for (i = 0; i < Calendar.FIELD_COUNT; ++i) {
+ switch(i) {
+ case Calendar.YEAR: case Calendar.MONTH: case Calendar.DATE:
+ case Calendar.HOUR_OF_DAY: case Calendar.MINUTE: case Calendar.SECOND:
+ if (!cal.isSet(i))
+ errln("FAIL: !Calendar.isSet test failed: " + calendarFieldNames[i]);
+ break;
+ default:
+ if (cal.isSet(i))
+ errln("FAIL: Calendar.isSet test failed: " + calendarFieldNames[i]);
+ }
+ cal.clear(i);
+ if (cal.isSet(i)) errln("FAIL: Calendar.clear/isSet failed");
+ }
+
+ // delete cal;
+ // delete cal2;
+
+ Locale[] loc = Calendar.getAvailableLocales();
+ long count = loc.length;
+ if (count < 1 || loc == null) {
+ errln("FAIL: getAvailableLocales failed");
+ }
+ else {
+ for (i = 0; i < count; ++i) {
+ cal = Calendar.getInstance(loc[i]);
+ // delete cal;
+ }
+ }
+
+ cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH);
+ // delete cal;
+
+ cal = Calendar.getInstance(zone, Locale.ENGLISH);
+ // delete cal;
+
+ GregorianCalendar gc = new GregorianCalendar(zone);
+ // delete gc;
+
+ gc = new GregorianCalendar(Locale.ENGLISH);
+ // delete gc;
+
+ gc = new GregorianCalendar(Locale.ENGLISH);
+ // delete gc;
+
+ gc = new GregorianCalendar(zone, Locale.ENGLISH);
+ // delete gc;
+
+ gc = new GregorianCalendar(zone);
+ // delete gc;
+
+ gc = new GregorianCalendar(1998, 10, 14, 21, 43);
+ if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43).getTime())
+ errln("FAIL: new GregorianCalendar(ymdhm) failed");
+ // delete gc;
+
+ gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55);
+ if (gc.getTime().getTime() != new Date(98, 10, 14, 21, 43, 55).getTime())
+ errln("FAIL: new GregorianCalendar(ymdhms) failed");
+
+ // C++ only:
+ // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH);
+ // gc2 = gc;
+ // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
+ // delete gc;
+ // delete z;
+ }
+
+ // Verify Roger Webster's bug
+ public void TestRog() {
+ GregorianCalendar gc = new GregorianCalendar();
+
+ int year = 1997, month = Calendar.APRIL, date = 1;
+ gc.set(year, month, date); // April 1, 1997
+
+ gc.set(Calendar.HOUR_OF_DAY, 23);
+ gc.set(Calendar.MINUTE, 0);
+ gc.set(Calendar.SECOND, 0);
+ gc.set(Calendar.MILLISECOND, 0);
+
+ for (int i = 0; i < 9; i++, gc.add(Calendar.DATE, 1)) {
+ if (gc.get(Calendar.YEAR) != year ||
+ gc.get(Calendar.MONTH) != month ||
+ gc.get(Calendar.DATE) != (date + i))
+ errln("FAIL: Date " + gc.getTime() + " wrong");
+ }
+ }
+
+ // Verify DAY_OF_WEEK
+ public void TestDOW943() {
+ dowTest(false);
+ dowTest(true);
+ }
+
+ void dowTest(boolean lenient) {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.set(1997, Calendar.AUGUST, 12); // Wednesday
+ cal.getTime(); // Force update
+ cal.setLenient(lenient);
+ cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
+ int dow = cal.get(Calendar.DAY_OF_WEEK);
+ int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
+ int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
+ if (dow < min || dow > max) errln("FAIL: Day of week " + dow + " out of range");
+ if (dow != Calendar.SUNDAY) {
+ errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime());
+ }
+ if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) errln("FAIL: Min/max bad");
+ }
+
+ // Verify that the clone method produces distinct objects with no
+ // unintentionally shared fields.
+ public void TestClonesUnique908() {
+ Calendar c = Calendar.getInstance();
+ Calendar d = (Calendar)c.clone();
+ c.set(Calendar.MILLISECOND, 123);
+ d.set(Calendar.MILLISECOND, 456);
+ if (c.get(Calendar.MILLISECOND) != 123 ||
+ d.get(Calendar.MILLISECOND) != 456) {
+ errln("FAIL: Clones share fields");
+ }
+ }
+
+ // Verify effect of Gregorian cutoff value
+ public void TestGregorianChange768() {
+ boolean b;
+ GregorianCalendar c = new GregorianCalendar();
+ logln("With cutoff " + c.getGregorianChange());
+ logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
+ logln(" (should be FALSE)");
+ if (b != false) errln("FAIL");
+ c.setGregorianChange(new Date(0, 0, 1)); // Jan 1 1900
+ logln("With cutoff " + c.getGregorianChange());
+ logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
+ logln(" (should be TRUE)");
+ if (b != true) errln("FAIL");
+ }
+
+ // Test the correct behavior of the disambiguation algorithm.
+ public void TestDisambiguation765() throws Exception {
+ Locale savedLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ Calendar c = Calendar.getInstance();
+ c.setLenient(false);
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.DATE, 3);
+
+ verify765("1997 third day of June = ", c, 1997, Calendar.JUNE, 3);
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
+ verify765("1997 first Tuesday in June = ", c, 1997, Calendar.JUNE, 3);
+
+ c.setLenient(true); // for 4944795
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
+ verify765("1997 last Tuesday in June = ", c, 1997, Calendar.JUNE, 24);
+
+ c.setLenient(false);
+ IllegalArgumentException e = null;
+ try {
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 0);
+ c.getTime();
+ }
+ catch (IllegalArgumentException ex) {
+ e = ex;
+ }
+ verify765("1997 zero-th Tuesday in June = ", e);
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.WEEK_OF_MONTH, 1);
+ verify765("1997 Tuesday in week 1 of June = ", c, 1997, Calendar.JUNE, 3);
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.WEEK_OF_MONTH, 4);
+ verify765("1997 Tuesday in week 4 of June = ", c, 1997, Calendar.JUNE, 24);
+
+ try {
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.MONTH, Calendar.JUNE);
+ c.set(Calendar.WEEK_OF_MONTH, 1);
+ verify765("1997 Tuesday in week 0 of June = ", c, 1997, Calendar.JUNE, 3);
+ }
+ catch (IllegalArgumentException ex) {
+ errln("FAIL: Exception seen: " + ex.getMessage());
+ // ex.printStackTrace(log);
+ }
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.WEEK_OF_YEAR, 2);
+ verify765("1997 Tuesday in week 2 of year = ", c, 1997, Calendar.JANUARY, 7);
+
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.WEEK_OF_YEAR, 10);
+ verify765("1997 Tuesday in week 10 of year = ", c, 1997, Calendar.MARCH, 4);
+
+ try {
+ c.clear();
+ c.set(Calendar.YEAR, 1997);
+ c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
+ c.set(Calendar.WEEK_OF_YEAR, 0);
+ verify765("1997 Tuesday in week 0 of year = ", c, 1996, Calendar.DECEMBER, 24);
+ throw new Exception("Fail: WEEK_OF_YEAR 0 should be illegal");
+ }
+ catch (IllegalArgumentException ex) {}
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ }
+ }
+ void verify765(String msg, Calendar c, int year, int month, int day) {
+ if (c.get(Calendar.YEAR) == year &&
+ c.get(Calendar.MONTH) == month &&
+ c.get(Calendar.DATE) == day) {
+ logln("PASS: " + msg + c.getTime());
+ }
+ else {
+ errln("FAIL: " + msg + c.getTime() +
+ "; expected " +
+ year + "/" + (month+1) + "/" + day);
+ }
+ }
+ // Called when e expected to be non-null
+ void verify765(String msg, IllegalArgumentException e) {
+ if (e == null) errln("FAIL: No IllegalArgumentException for " + msg);
+ else logln("PASS: " + msg + "IllegalArgument as expected");
+ }
+
+ // Test the behavior of GMT vs. local time
+ public void TestGMTvsLocal4064654() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ // Sample output 1:
+ // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0
+ // date = Wed Jan 01 04:00:00 PST 1997
+ // offset for Wed Jan 01 04:00:00 PST 1997= -8hr
+ test4064654(1997, 1, 1, 12, 0, 0);
+
+ // Sample output 2:
+ // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0
+ // date = Wed Apr 16 10:30:00 PDT 1997
+ // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr
+
+ // Note that in sample output 2 according to the offset, the gmt time
+ // of the result would be 1997 4 16 17 30 0 which is different from the
+ // input of 1997 4 16 18 30 0.
+ test4064654(1997, 4, 16, 18, 30, 0);
+ }
+ void test4064654(int yr, int mo, int dt, int hr, int mn, int sc) {
+ Date date;
+ Calendar gmtcal = Calendar.getInstance();
+ gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
+ gmtcal.set(yr, mo-1, dt, hr, mn, sc);
+ gmtcal.set(Calendar.MILLISECOND, 0);
+
+ date = gmtcal.getTime();
+ logln("date = "+date);
+
+ Calendar cal = Calendar.getInstance();
+ cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
+ cal.setTime(date);
+
+ int offset = cal.getTimeZone().getOffset(cal.get(Calendar.ERA),
+ cal.get(Calendar.YEAR),
+ cal.get(Calendar.MONTH),
+ cal.get(Calendar.DATE),
+ cal.get(Calendar.DAY_OF_WEEK),
+ cal.get(Calendar.MILLISECOND));
+
+ logln("offset for "+date+"= "+(offset/1000/60/60.0) + "hr");
+
+ int utc = ((cal.get(Calendar.HOUR_OF_DAY) * 60 +
+ cal.get(Calendar.MINUTE)) * 60 +
+ cal.get(Calendar.SECOND)) * 1000 +
+ cal.get(Calendar.MILLISECOND) - offset;
+
+ int expected = ((hr * 60 + mn) * 60 + sc) * 1000;
+
+ if (utc != expected)
+ errln("FAIL: Discrepancy of " +
+ (utc - expected) + " millis = " +
+ ((utc-expected)/1000/60/60.0) + " hr");
+ }
+
+ // Verify that add and set work regardless of the order in which
+ // they are called.
+ public void TestAddSetOrder621() {
+ Date d = new Date(97, 4, 14, 13, 23, 45);
+
+ Calendar cal = Calendar.getInstance ();
+ cal.setTime (d);
+ cal.add (Calendar.DATE, -5);
+ cal.set (Calendar.HOUR_OF_DAY, 0);
+ cal.set (Calendar.MINUTE, 0);
+ cal.set (Calendar.SECOND, 0);
+ // ma feb 03 00:00:00 GMT+00:00 1997
+ String s = cal.getTime ().toString ();
+
+ cal = Calendar.getInstance ();
+ cal.setTime (d);
+ cal.set (Calendar.HOUR_OF_DAY, 0);
+ cal.set (Calendar.MINUTE, 0);
+ cal.set (Calendar.SECOND, 0);
+ cal.add (Calendar.DATE, -5);
+ // ma feb 03 13:11:06 GMT+00:00 1997
+ String s2 = cal.getTime ().toString ();
+
+ if (s.equals(s2))
+ logln("Pass: " + s + " == " + s2);
+ else
+ errln("FAIL: " + s + " != " + s2);
+ }
+
+ // Verify that add works.
+ public void TestAdd520() {
+ int y = 1997, m = Calendar.FEBRUARY, d = 1;
+ GregorianCalendar temp = new GregorianCalendar( y, m, d );
+ check520(temp, y, m, d);
+
+ temp.add( temp.YEAR, 1 );
+ y++;
+ check520(temp, y, m, d);
+
+ temp.add( temp.MONTH, 1 );
+ m++;
+ check520(temp, y, m, d);
+
+ temp.add( temp.DATE, 1 );
+ d++;
+ check520(temp, y, m, d);
+
+ temp.add( temp.DATE, 2 );
+ d += 2;
+ check520(temp, y, m, d);
+
+ temp.add( temp.DATE, 28 );
+ d = 1; ++m;
+ check520(temp, y, m, d);
+ }
+ void check520(Calendar c, int y, int m, int d) {
+ if (c.get(Calendar.YEAR) != y ||
+ c.get(Calendar.MONTH) != m ||
+ c.get(Calendar.DATE) != d) {
+ errln("FAILURE: Expected YEAR/MONTH/DATE of " +
+ y + "/" + (m+1) + "/" + d +
+ "; got " +
+ c.get(Calendar.YEAR) + "/" +
+ (c.get(Calendar.MONTH)+1) + "/" +
+ c.get(Calendar.DATE));
+ }
+ else logln("Confirmed: " +
+ y + "/" + (m+1) + "/" + d);
+ }
+
+ // Verify that setting fields works. This test fails when an exception is thrown.
+ public void TestFieldSet4781() {
+ try {
+ GregorianCalendar g = new GregorianCalendar();
+ GregorianCalendar g2 = new GregorianCalendar();
+ // At this point UTC value is set, various fields are not.
+ // Now set to noon.
+ g2.set(Calendar.HOUR, 12);
+ g2.set(Calendar.MINUTE, 0);
+ g2.set(Calendar.SECOND, 0);
+ // At this point the object thinks UTC is NOT set, but fields are set.
+ // The following line will result in IllegalArgumentException because
+ // it thinks the YEAR is set and it is NOT.
+ if (g2.equals(g))
+ logln("Same");
+ else
+ logln("Different");
+ }
+ catch (IllegalArgumentException e) {
+ errln("Unexpected exception seen: " + e);
+ }
+ }
+
+ // Test serialization of a Calendar object
+ public void TestSerialize337() {
+ Calendar cal = Calendar.getInstance();
+
+ boolean ok = false;
+
+ try {
+ FileOutputStream f = new FileOutputStream(FILENAME);
+ ObjectOutput s = new ObjectOutputStream(f);
+ s.writeObject(PREFIX);
+ s.writeObject(cal);
+ s.writeObject(POSTFIX);
+ f.close();
+
+ FileInputStream in = new FileInputStream(FILENAME);
+ ObjectInputStream t = new ObjectInputStream(in);
+ String pre = (String)t.readObject();
+ Calendar c = (Calendar)t.readObject();
+ String post = (String)t.readObject();
+ in.close();
+
+ ok = pre.equals(PREFIX) &&
+ post.equals(POSTFIX) &&
+ cal.equals(c);
+
+ File fl = new File(FILENAME);
+ fl.delete();
+ }
+ catch (IOException e) {
+ errln("FAIL: Exception received:");
+ // e.printStackTrace(log);
+ }
+ catch (ClassNotFoundException e) {
+ errln("FAIL: Exception received:");
+ // e.printStackTrace(log);
+ }
+
+ if (!ok) errln("Serialization of Calendar object failed.");
+ }
+ static final String PREFIX = "abc";
+ static final String POSTFIX = "def";
+ static final String FILENAME = "tmp337.bin";
+
+ // Try to zero out the seconds field
+ public void TestSecondsZero121() {
+ Calendar cal = new GregorianCalendar();
+ // Initialize with current date/time
+ cal.setTime(new Date());
+ // Round down to minute
+ cal.set(Calendar.SECOND, 0);
+ Date d = cal.getTime();
+ String s = d.toString();
+ if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s);
+ }
+
+ // Try various sequences of add, set, and get method calls.
+ public void TestAddSetGet0610() {
+ //
+ // Error case 1:
+ // - Upon initialization calendar fields, millis = System.currentTime
+ // - After set is called fields are initialized, time is not
+ // - Addition uses millis which are still *now*
+ //
+ {
+ Calendar calendar = new GregorianCalendar( ) ;
+ calendar.set( 1993, Calendar.JANUARY, 4 ) ;
+ logln( "1A) " + value( calendar ) ) ;
+ calendar.add( Calendar.DATE, 1 ) ;
+ String v = value(calendar);
+ logln( "1B) " + v );
+ logln( "--) 1993/0/5" ) ;
+ if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+ "; saw " + v);
+ }
+
+ //
+ // Error case 2:
+ // - Upon initialization calendar fields set, millis = 0
+ // - Addition uses millis which are still 1970, 0, 1
+ //
+
+ {
+ Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
+ logln( "2A) " + value( calendar ) ) ;
+ calendar.add( Calendar.DATE, 1 ) ;
+ String v = value(calendar);
+ logln( "2B) " + v );
+ logln( "--) 1993/0/5" ) ;
+ if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+ "; saw " + v);
+ }
+
+ //
+ // Error case 3:
+ // - Upon initialization calendar fields, millis = 0
+ // - getTime( ) is called which forces the millis to be set
+ // - Addition uses millis which are correct
+ //
+
+ {
+ Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
+ logln( "3A) " + value( calendar ) ) ;
+ calendar.getTime( ) ;
+ calendar.add( Calendar.DATE, 1 ) ;
+ String v = value(calendar);
+ logln( "3B) " + v ) ;
+ logln( "--) 1993/0/5" ) ;
+ if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
+ "; saw " + v);
+ }
+ }
+ static String value( Calendar calendar ) {
+ return( calendar.get( Calendar.YEAR ) + "/" +
+ calendar.get( Calendar.MONTH ) + "/" +
+ calendar.get( Calendar.DATE ) ) ;
+ }
+ static String EXPECTED_0610 = "1993/0/5";
+
+ // Test that certain fields on a certain date are as expected.
+ public void TestFields060() {
+ int year = 1997;
+ int month = java.util.Calendar.OCTOBER; //october
+ int dDate = 22; //DAYOFWEEK should return 3 for Wednesday
+ GregorianCalendar calendar = null;
+
+ calendar = new GregorianCalendar( year, month, dDate);
+ for (int i = 0; i < EXPECTED_FIELDS.length; ) {
+ int field = EXPECTED_FIELDS[i++];
+ int expected = EXPECTED_FIELDS[i++];
+ if (calendar.get(field) != expected) {
+ errln("Expected field " + field + " to have value " + expected +
+ "; received " + calendar.get(field) + " instead");
+ }
+ }
+ }
+ static int EXPECTED_FIELDS[] = {
+ Calendar.YEAR, 1997,
+ Calendar.MONTH, Calendar.OCTOBER,
+ Calendar.DAY_OF_MONTH, 22,
+ Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY,
+ Calendar.DAY_OF_WEEK_IN_MONTH, 4,
+ Calendar.DAY_OF_YEAR, 295
+ };
+
+ static final String[] calendarFieldNames = {
+ /* 0 */ "ERA",
+ /* 1 */ "YEAR",
+ /* 2 */ "MONTH",
+ /* 3 */ "WEEK_OF_YEAR",
+ /* 4 */ "WEEK_OF_MONTH",
+ /* 5 */ "DAY_OF_MONTH",
+ /* 6 */ "DAY_OF_YEAR",
+ /* 7 */ "DAY_OF_WEEK",
+ /* 8 */ "DAY_OF_WEEK_IN_MONTH",
+ /* 9 */ "AM_PM",
+ /* 10 */ "HOUR",
+ /* 11 */ "HOUR_OF_DAY",
+ /* 12 */ "MINUTE",
+ /* 13 */ "SECOND",
+ /* 14 */ "MILLISECOND",
+ /* 15 */ "ZONE_OFFSET",
+ /* 16 */ "DST_OFFSET"
+ };
+
+ // Verify that the fields are as expected (mostly zero) at the epoch start.
+ // Note that we adjust for the default timezone to get most things to zero.
+ public void TestEpochStartFields() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ String[][] lt = {
+ {"en", "US", "US/Pacific"}, /* First day = 1, Minimum day = 1 */
+ {"en", "US", "America/Anchorage"}, /* First day = 1, Minimum day = 1 */
+ {"en", "TO", "Pacific/Tongatapu"}, /* First day = 1, Minimum day = 1 */
+ {"en", "MH", "Pacific/Majuro"}, /* First day = 1, Minimum day = 1 */
+ {"ja", "JP", "Asia/Tokyo"}, /* First day = 1, Minimum day = 1 */
+ {"iw", "IL", "Asia/Jerusalem"}, /* First day = 1, Minimum day = 1 */
+ {"hi", "IN", "Asia/Jakarta"}, /* First day = 1, Minimum day = 1 */
+ {"en", "GB", "Europe/London"}, /* First day = 2, Minimum day = 1 */
+ {"en", "GB", "GMT"}, /* First day = 2, Minimum day = 1 */
+ {"de", "DE", "Europe/Berlin"}, /* First day = 2, Minimum day = 4 */
+ {"ar", "EG", "Africa/Cairo"}, /* First day = 7, Minimum day = 1 */
+ };
+
+ int[][] goldenData = {
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0},
+ {1, 1969, 11, 1, 5, 31, 365, 4, 5, 1, 11, 23, 0, 0, 0, -36000000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 46800000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 43200000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 32400000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 25200000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 1, 1, 0, 0, 0, 3600000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 0, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 3600000, 0},
+ {1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, 7200000, 0},
+ };
+
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+
+ try {
+ for (int j = 0; j < lt.length; j++) {
+ Locale l = new Locale(lt[j][0], lt[j][1]);
+ TimeZone z = TimeZone.getTimeZone(lt[j][2]);
+ Locale.setDefault(l);
+ TimeZone.setDefault(z);
+ Calendar c = Calendar.getInstance();
+ Date d = new Date(-z.getRawOffset());
+
+ int val;
+ int[] EPOCH_FIELDS = goldenData[j];
+ c.setTime(d);
+
+ boolean err = false;
+ for (int i = 0; i < calendarFieldNames.length; ++i) {
+ if ((val = c.get(i)) != EPOCH_FIELDS[i]) {
+ errln("Wrong value: " + val +
+ " for field(" + calendarFieldNames[i] +
+ "), expected: " + EPOCH_FIELDS[i]);
+ err = true;
+ }
+ }
+ if (err) {
+ errln("Failed: \n\tDate=" + d + "\n\tTimeZone=" + z +
+ "\n\tLocale=" + l + "\n\tCalendar=" + c);
+ }
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+ }
+
+ // Verify that as you add days to the calendar (e.g., 24 day periods),
+ // the day of the week shifts in the expected pattern.
+ public void TestDOWProgression() {
+ Calendar cal =
+ new GregorianCalendar(1972, Calendar.OCTOBER, 26);
+ marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7
+ }
+
+ // Supply a delta which is not a multiple of 7.
+ void marchByDelta(Calendar cal, int delta) {
+ Calendar cur = (Calendar)cal.clone();
+ int initialDOW = cur.get(Calendar.DAY_OF_WEEK);
+ int DOW, newDOW = initialDOW;
+ do {
+ DOW = newDOW;
+ logln("DOW = " + DOW + " " + cur.getTime());
+
+ cur.add(Calendar.DAY_OF_WEEK, delta);
+ newDOW = cur.get(Calendar.DAY_OF_WEEK);
+ int expectedDOW = 1 + (DOW + delta - 1) % 7;
+ if (newDOW != expectedDOW) {
+ errln("Day of week should be " + expectedDOW +
+ " instead of " + newDOW + " on " + cur.getTime());
+ return;
+ }
+ }
+ while (newDOW != initialDOW);
+ }
+
+ public void TestActualMinMax() {
+ Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10);
+ cal.setFirstDayOfWeek(Calendar.SUNDAY);
+ cal.setMinimalDaysInFirstWeek(3);
+
+ if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) != 1)
+ errln("Actual minimum date for 3/10/1967 should have been 1; got " +
+ cal.getActualMinimum(Calendar.DAY_OF_MONTH));
+ if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 31)
+ errln("Actual maximum date for 3/10/1967 should have been 31; got " +
+ cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+
+ cal.set(Calendar.MONTH, Calendar.FEBRUARY);
+ if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 28)
+ errln("Actual maximum date for 2/10/1967 should have been 28; got " +
+ cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+ if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 365)
+ errln("Number of days in 1967 should have been 365; got " +
+ cal.getActualMaximum(Calendar.DAY_OF_YEAR));
+
+ cal.set(Calendar.YEAR, 1968);
+ if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 29)
+ errln("Actual maximum date for 2/10/1968 should have been 29; got " +
+ cal.getActualMaximum(Calendar.DAY_OF_MONTH));
+ if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 366)
+ errln("Number of days in 1968 should have been 366; got " +
+ cal.getActualMaximum(Calendar.DAY_OF_YEAR));
+ // Using week settings of SUNDAY/3 (see above)
+ if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 52)
+ errln("Number of weeks in 1968 should have been 52; got " +
+ cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
+
+ cal.set(Calendar.YEAR, 1976);
+ // Using week settings of SUNDAY/3 (see above)
+ if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 53)
+ errln("Number of weeks in 1976 should have been 53; got " +
+ cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
+ }
+
+ public void TestRoll() {
+ Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 31);
+
+ int[] dayValues = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
+
+ for (int i = 0; i < dayValues.length; i++) {
+ Calendar cal2 = (Calendar)cal.clone();
+ cal2.roll(Calendar.MONTH, i);
+ if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues[i])
+ errln("Rolling the month in 1/31/1997 up by " + i + " should have yielded "
+ + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded "
+ + ((i + 1) % 12) + "/" + cal2.get(Calendar.DAY_OF_MONTH) + "/1997.");
+ }
+
+ cal.set(1996, Calendar.FEBRUARY, 29);
+
+ int[] monthValues = { 1, 2, 2, 2, 1, 2, 2, 2, 1, 2 };
+ int[] dayValues2 = { 29, 1, 1, 1, 29, 1, 1, 1, 29, 1 };
+
+ for (int i = 0; i < dayValues2.length; i++) {
+ Calendar cal2 = (Calendar)cal.clone();
+ cal2.roll(Calendar.YEAR, i);
+ if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues2[i] || cal2.get(Calendar.MONTH)
+ != monthValues[i])
+ errln("Rolling the year in 2/29/1996 up by " + i + " should have yielded "
+ + (monthValues[i] + 1) + "/" + dayValues2[i] + "/"
+ + (1996 + i) + ", but actually yielded "
+ + (cal2.get(Calendar.MONTH) + 1) + "/" +
+ cal2.get(Calendar.DAY_OF_MONTH) + "/" + (1996 + i) + ".");
+ }
+
+ // Test rolling hour of day
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.roll(Calendar.HOUR_OF_DAY, -2);
+ int f = cal.get(Calendar.HOUR_OF_DAY);
+ if (f != 22) errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22");
+ cal.roll(Calendar.HOUR_OF_DAY, 5);
+ f = cal.get(Calendar.HOUR_OF_DAY);
+ if (f != 3) errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3");
+ cal.roll(Calendar.HOUR_OF_DAY, 21);
+ f = cal.get(Calendar.HOUR_OF_DAY);
+ if (f != 0) errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0");
+
+ // Test rolling hour
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.roll(Calendar.HOUR, -2);
+ f = cal.get(Calendar.HOUR);
+ if (f != 10) errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10");
+ cal.roll(Calendar.HOUR, 5);
+ f = cal.get(Calendar.HOUR);
+ if (f != 3) errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3");
+ cal.roll(Calendar.HOUR, 9);
+ f = cal.get(Calendar.HOUR);
+ if (f != 0) errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0");
+ }
+
+ /*
+ * Confirm that multiple calls to Calendar.set() works correctly.
+ */
+ public void Test4374886() {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+ Calendar cal = Calendar.getInstance();
+ cal.set(Calendar.YEAR, 2001);
+ cal.set(Calendar.MONTH, Calendar.OCTOBER);
+ cal.set(Calendar.WEEK_OF_YEAR, 4);
+ cal.set(Calendar.DAY_OF_WEEK, 2);
+
+ if (cal.get(Calendar.YEAR) != 2001 ||
+ cal.get(Calendar.MONTH) != Calendar.JANUARY ||
+ cal.get(Calendar.DATE) != 22 ||
+ cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
+ errln("Failed : got " + cal.getTime() + ", expected Mon Jan 22, 2001");
+ }
+ }
+ finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+ }
+}
+
+//eof
diff --git a/test/java/util/Calendar/FieldStateTest.java b/test/java/util/Calendar/FieldStateTest.java
new file mode 100644
index 0000000000..caa6f219a2
--- /dev/null
+++ b/test/java/util/Calendar/FieldStateTest.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4860664 4916815 4867075
+ * @library /java/text/testlib
+ * @build Koyomi
+ * @run main FieldStateTest
+ * @summary Unit tests for internal fields states.
+ */
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static java.util.Calendar.*;
+
+public class FieldStateTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ TimeZone reservedTimeZone = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Locale.setDefault(Locale.US);
+
+ new FieldStateTest().run(args);
+ } finally {
+ // restore the reserved locale and time zone
+ Locale.setDefault(reservedLocale);
+ TimeZone.setDefault(reservedTimeZone);
+ }
+ }
+
+ public void TestFieldState() {
+ Koyomi cal = new Koyomi();
+ logln("Right after instantialtion:");
+ if (!cal.checkAllSet()) {
+ errln(cal.getMessage());
+ }
+
+ logln("Set date to 2003/10/31 after the instantiation:");
+ cal.set(2003, OCTOBER, 31);
+ // let cal calculate the time
+ cal.getTime();
+ // At this point, all fields have to be recalculated and
+ // happen to have the set-state from the instantiation. The
+ // three fields should have "externally set" and the rest of
+ // the fields have "computed". But we can't distinguish them
+ // outside the package.
+ if (!cal.checkAllSet()) {
+ errln(cal.getMessage());
+ }
+ // Make sure that the correct date was produced.
+ if (!cal.checkInternalDate(2003, OCTOBER, 31, FRIDAY)) {
+ errln(cal.getMessage());
+ }
+
+ logln("Change to Monday of the week, which is 2003/10/27:");
+ cal.set(DAY_OF_WEEK, MONDAY);
+ cal.getTime();
+ if (!cal.checkDate(2003, OCTOBER, 27)) {
+ errln(cal.getMessage());
+ }
+
+ // The same operation didn't work after calling clear() before
+ // 1.5 because the set-state was just depends on its previous
+ // operations. After the instantiation, all the fields are set
+ // to "computed". But after calling clear(), the state becomes
+ // "unset".
+ logln("Set to 2003/10/31 after clear():");
+ cal.clear();
+ cal.set(2003, OCTOBER, 31);
+ cal.getTime();
+ cal.set(DAY_OF_WEEK, MONDAY);
+ if (!cal.checkDate(2003, OCTOBER, 27, MONDAY)) {
+ errln(cal.getMessage());
+ }
+
+ logln("Set to 2003/10/31 after clear(), then to the 51st week of year (12/19):");
+ cal.clear();
+ cal.set(2003, OCTOBER, 31);
+ cal.getTime();
+ cal.set(WEEK_OF_YEAR, 51);
+ if (!cal.checkFieldValue(WEEK_OF_YEAR, 51)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkDate(2003, DECEMBER, 19, FRIDAY)) {
+ errln(cal.getMessage());
+ }
+
+ logln("Set to 2003/10 Mon of 4th week (10/20: 43rd week of year, 293rd day):");
+ cal.clear();
+ cal.set(YEAR, 2003);
+ cal.set(MONTH, OCTOBER);
+ cal.set(DAY_OF_WEEK, MONDAY);
+ cal.set(WEEK_OF_MONTH, 4);
+ cal.getTime();
+ if (!cal.checkFieldValue(DAY_OF_MONTH, 20)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(WEEK_OF_YEAR, 43)) {
+ errln(cal.getMessage());
+ }
+
+ logln("Set to 2003/10 Mon of 43rd week of year (10/20: 4th week of month, 293rd day):");
+ cal.clear();
+ cal.set(YEAR, 2003);
+ cal.set(DAY_OF_WEEK, MONDAY);
+ cal.set(WEEK_OF_YEAR, 43);
+ cal.getTime();
+ if (!cal.checkDate(2003, OCTOBER, 20, MONDAY)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(WEEK_OF_MONTH, 4)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(DAY_OF_YEAR, 293)) {
+ errln(cal.getMessage());
+ }
+
+ logln("Set day of week to SUNDAY and date to 2003/10/31. "
+ + "Then, getTime and set week of year to 43.");
+ cal.setTime(new Date(2003-1990, OCTOBER, 31));
+ cal.set(DAY_OF_WEEK, SUNDAY);
+ cal.set(2003, OCTOBER, 31); // 2003/10/31 is Friday.
+ cal.set(ZONE_OFFSET, 0);
+ cal.set(DST_OFFSET, 0);
+
+ // This call should change the day of week to FRIDAY since the
+ // selected field combination should be YEAR, MONTH and
+ // DAY_OF_MONTH. The other calendar fields must be normalized
+ // with the selected date.
+ cal.getTime();
+ cal.set(WEEK_OF_YEAR, 43);
+ if (!cal.checkDate(2003, OCTOBER, 24, FRIDAY)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ /*
+ * 4916815: REGRESSION: Problem with java.util.Calendar VM 1.4.2-b28
+ */
+ public void Test4916815() {
+ logln("Set date to 2003/9/26 (Fri). Roll to Aug and back to Sep. "+
+ "Set dayofweek to Sunday which should be 2003/9/21.");
+ Koyomi cal = new Koyomi();
+ cal.clear();
+ // 2003/9/26 (Fri)
+ cal.set(2003, SEPTEMBER, 26);
+ // Go to August then back to September
+ cal.roll(MONTH, -1);
+ cal.roll(MONTH, +1);
+ Koyomi cal2 = (Koyomi) cal.clone();
+ cal2.getTime();
+ // Sunday of the week should be 2003/9/21.
+ cal2.set(DAY_OF_WEEK, SUNDAY);
+ if (!cal2.checkDate(2003, SEPTEMBER, 21, SUNDAY)) {
+ errln(cal2.getMessage());
+ }
+ }
+
+ /*
+ * 4867075: GregorianCalendar get() calls complete() internally, should getTime() too?
+ */
+ public void Test4867075() {
+ Koyomi cal = new Koyomi(Locale.US);
+ cal.clear();
+ cal.set(YEAR, 2004);
+ cal.set(WEEK_OF_YEAR, 1);
+ checkDate(cal, SUNDAY, 2003, DECEMBER, 28);
+ checkDate(cal, MONDAY, 2003, DECEMBER, 29);
+ checkDate(cal, TUESDAY, 2003, DECEMBER, 30);
+ checkDate(cal, WEDNESDAY, 2003, DECEMBER, 31);
+ checkDate(cal, THURSDAY, 2004, JANUARY, 1);
+ checkDate(cal, FRIDAY, 2004, JANUARY, 2);
+ checkDate(cal, SATURDAY, 2004, JANUARY, 3);
+ }
+
+ private void checkDate(Koyomi cal, int dayOfWeek,
+ int expectedYear, int expectedMonth, int expectedDayOfMonth) {
+ cal.set(DAY_OF_WEEK, dayOfWeek);
+ cal.getTime();
+ if (!cal.checkInternalDate(expectedYear, expectedMonth, expectedDayOfMonth, dayOfWeek)) {
+ errln(cal.getMessage());
+ }
+ }
+
+ static String toHexString(int x) {
+ return Integer.toHexString(x);
+ }
+}
diff --git a/test/java/util/Calendar/GregorianCutoverTest.java b/test/java/util/Calendar/GregorianCutoverTest.java
new file mode 100644
index 0000000000..bd743ae19f
--- /dev/null
+++ b/test/java/util/Calendar/GregorianCutoverTest.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4359204 4928615 4743587 4956232 6459836 6549953
+ * @library /java/text/testlib
+ * @build Koyomi
+ * @run main GregorianCutoverTest
+ * @summary Unit tests related to the Gregorian cutover support.
+ */
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static java.util.GregorianCalendar.*;
+
+public class GregorianCutoverTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ TimeZone tz = TimeZone.getDefault();
+ Locale lc = Locale.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Locale.setDefault(Locale.US);
+
+ new GregorianCutoverTest().run(args);
+ } finally {
+ TimeZone.setDefault(tz);
+ Locale.setDefault(lc);
+ }
+ }
+
+ /**
+ * 4359204: GregorianCalendar.get(cal.DAY_OF_YEAR) is inconsistent for year 1582
+ */
+ public void Test4359204() {
+ Koyomi cal = new Koyomi();
+
+ cal.set(1582, JANUARY, 1);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+ cal.set(1582, OCTOBER, 1);
+ checkContinuity(cal, WEEK_OF_MONTH);
+
+ // JCK tests the cutover date 1970-1-1 (Epoch)
+ cal.setGregorianChange(new Date(0));
+ cal.set(1969, JANUARY, 1);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+ cal.set(1969, DECEMBER, 1);
+ checkContinuity(cal, WEEK_OF_MONTH);
+ cal.set(1970, JANUARY, 1);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+
+ // Use large date (year >= 50000)
+ cal.setGregorianChange(new Date(50000-1900, JANUARY, 20));
+ cal.set(49998, JANUARY, 1);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+ cal.set(49999, JANUARY, 1);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+ cal.set(50000, JANUARY, 20);
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+
+ // Handling of "overlapping" dates may still be incorrect as
+ // of 1.5. Also, there's no way to disambiguate "overlapping"
+ // dates.
+ // millis=-112033929600000: date=-1581-10-15T00:00:00.000Z
+ cal.setGregorianChange(new Date(-112033929600000L));
+ cal.set(ERA, AD);
+ cal.set(-1581, JANUARY, 1);
+ // The year should have 379 days.
+ checkContinuity(cal, DAY_OF_YEAR);
+ checkContinuity(cal, WEEK_OF_YEAR);
+
+ logln("Default cutover");
+ cal = new Koyomi();
+ cal.set(1582, OCTOBER, 1);
+ logln(" roll --DAY_OF_MONTH from 1582/10/01");
+ cal.roll(DAY_OF_MONTH, -1);
+ if (!cal.checkDate(1582, OCTOBER, 31)) {
+ errln(cal.getMessage());
+ }
+ logln(" roll DAY_OF_MONTH+10 from 1582/10/31");
+ cal.roll(DAY_OF_MONTH, +10);
+ if (!cal.checkDate(1582, OCTOBER, 20)) {
+ errln(cal.getMessage());
+ }
+ logln(" roll DAY_OF_MONTH-10 from 1582/10/20");
+ cal.roll(DAY_OF_MONTH, -10);
+ if (!cal.checkDate(1582, OCTOBER, 31)) {
+ errln(cal.getMessage());
+ }
+ logln(" roll back one day further");
+ cal.roll(DAY_OF_MONTH, +1);
+ if (!cal.checkDate(1582, OCTOBER, 1)) {
+ errln(cal.getMessage());
+ }
+
+ // should handle the gap between 1969/12/22 (Julian) to 1970/1/5 (Gregorian)
+ logln("Cutover date is 1970/1/5");
+ cal.setGregorianChange(new Date(1970-1900, JANUARY, 5));
+ cal.set(ERA, AD);
+ cal.set(YEAR, 1970);
+ logln(" Set DAY_OF_YEAR to the 28th day of 1970");
+ cal.set(DAY_OF_YEAR, 28);
+ if (!cal.checkDate(1970, FEBRUARY, 1)) {
+ errln(cal.getMessage());
+ }
+ if (!cal.checkFieldValue(WEEK_OF_YEAR, 5)) {
+ errln(cal.getMessage());
+ }
+ logln(" 1969/12/22 should be the 356th day of the year.");
+ cal.set(1969, DECEMBER, 22);
+ if (!cal.checkFieldValue(DAY_OF_YEAR, 356)) {
+ errln(cal.getMessage());
+ }
+ logln(" Set DAY_OF_YEAR to autual maximum.");
+ int actualMaxDayOfYear = cal.getActualMaximum(DAY_OF_YEAR);
+ if (actualMaxDayOfYear != 356) {
+ errln("actual maximum of DAY_OF_YEAR: got " + actualMaxDayOfYear + ", expected 356");
+ }
+ cal.set(DAY_OF_YEAR, actualMaxDayOfYear);
+ if (!cal.checkDate(1969, DECEMBER, 22)) {
+ errln(cal.getMessage());
+ }
+ cal.set(1969, DECEMBER, 22);
+ cal.roll(DAY_OF_YEAR, +1);
+ logln(" Set to 1969/12/22 and roll DAY_OF_YEAR++");
+ if (!cal.checkDate(1969, JANUARY, 1)) {
+ errln(cal.getMessage());
+ }
+ logln(" 1970/1/5 should be the first day of the year.");
+ cal.set(1970, JANUARY, 5);
+ if (!cal.checkFieldValue(DAY_OF_YEAR, 1)) {
+ errln(cal.getMessage());
+ }
+ logln(" roll --DAY_OF_MONTH from 1970/1/5");
+ cal.roll(DAY_OF_MONTH, -1);
+ if (!cal.checkDate(1970, JANUARY, 31)) {
+ errln(cal.getMessage());
+ }
+ logln(" roll back one day of month");
+ cal.roll(DAY_OF_MONTH, +1);
+ if (!cal.checkDate(1970, JANUARY, 5)) {
+ errln(cal.getMessage());
+ }
+
+ // Test "missing" dates in non-lenient.
+ cal = new Koyomi(); // new instance for the default cutover
+ cal.setLenient(false);
+ try {
+ // the next day of 1582/10/4 (Julian) is 1582/10/15 (Gregorian)
+ logln("1582/10/10 doesn't exit with the default cutover.");
+ cal.set(1582, OCTOBER, 10);
+ cal.getTime();
+ errln(" Didn't throw IllegalArgumentException in non-lenient.");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ private void checkContinuity(Koyomi cal, int field) {
+ cal.getTime();
+ logln(Koyomi.getFieldName(field) + " starting on " + cal.toDateString());
+ int max = cal.getActualMaximum(field);
+ for (int i = 1; i <= max; i++) {
+ logln(i + " " + cal.toDateString());
+ if (!cal.checkFieldValue(field, i)) {
+ errln(" " + cal.toDateString() + ":\t" + cal.getMessage());
+ }
+ cal.add(field, +1);
+ }
+ }
+
+ /**
+ * 4928615: GregorianCalendar returns wrong dates after setGregorianChange
+ */
+ public void Test4928615() {
+ Koyomi cal = new Koyomi();
+ logln("Today is 2003/10/1 Gregorian.");
+ Date x = new Date(2003-1900, 10-1, 1);
+ cal.setTime(x);
+
+ logln(" Changing the cutover date to yesterday...");
+ cal.setGregorianChange(new Date(x.getTime() - (24*3600*1000)));
+ if (!cal.checkDate(2003, OCTOBER, 1)) {
+ errln(" " + cal.getMessage());
+ }
+ logln(" Changing the cutover date to tomorrow...");
+ cal.setGregorianChange(new Date(x.getTime() + (24*3600*1000)));
+ if (!cal.checkDate(2003, SEPTEMBER, 18)) {
+ errln(" " + cal.getMessage());
+ }
+ }
+
+ /**
+ * 4743587: GregorianCalendar.getLeastMaximum() returns wrong values
+ */
+ public void Test4743587() {
+ Koyomi cal = new Koyomi();
+ Koyomi cal2 = (Koyomi) cal.clone();
+ logln("getLeastMaximum should handle cutover year.\n"
+ +" default cutover date");
+ if (!cal.checkLeastMaximum(DAY_OF_YEAR, 365-10)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkLeastMaximum(WEEK_OF_YEAR, 52-((10+6)/7))) {
+ errln(" " + cal.getMessage());
+ }
+ // Corrected for 4956232
+ if (!cal.checkLeastMaximum(DAY_OF_MONTH, 28)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkLeastMaximum(WEEK_OF_MONTH, 3)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkLeastMaximum(DAY_OF_WEEK_IN_MONTH, 3)) {
+ errln(" " + cal.getMessage());
+ }
+ // make sure that getLeastMaximum calls didn't affect the date
+ if (!cal.equals(cal2)) {
+ errln(" getLeastMaximum calls modified the object.");
+ }
+ if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 1)) {
+ errln(" " + cal.getMessage());
+ }
+
+ logln(" changing the date to 1582/10/20 for actual min/max tests");
+ cal.set(1582, OCTOBER, 20);
+ if (!cal.checkActualMinimum(DAY_OF_MONTH, 1)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) {
+ errln(" " + cal.getMessage());
+ }
+
+ cal = new Koyomi();
+ logln("Change the cutover date to 1970/1/5.");
+ cal.setGregorianChange(new Date(1970-1900, 0, 5));
+ if (!cal.checkLeastMaximum(DAY_OF_YEAR, 356)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkLeastMaximum(DAY_OF_MONTH, 22)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkGreatestMinimum(DAY_OF_MONTH, 5)) {
+ errln(" " + cal.getMessage());
+ }
+ cal.set(1970, JANUARY, 10);
+ if (!cal.checkActualMinimum(DAY_OF_MONTH, 5)) {
+ errln(" " + cal.getMessage());
+ }
+ if (!cal.checkActualMaximum(DAY_OF_MONTH, 31)) {
+ errln(" " + cal.getMessage());
+ }
+ }
+
+ /**
+ * 6459836: (cal) GregorianCalendar set method provides wrong result
+ */
+ public void Test6459836() {
+ int hour = 13865672;
+ Koyomi gc1 = new Koyomi();
+ gc1.clear();
+ gc1.set(1, gc1.JANUARY, 1, 0, 0, 0);
+ gc1.set(gc1.HOUR_OF_DAY, hour);
+ if (!gc1.checkDate(1582, gc1.OCTOBER, 4)) {
+ errln("test case 1: " + gc1.getMessage());
+ }
+ gc1.clear();
+ gc1.set(1, gc1.JANUARY, 1, 0, 0, 0);
+ gc1.set(gc1.HOUR_OF_DAY, hour + 24);
+ if (!gc1.checkDate(1582, gc1.OCTOBER, 15)) {
+ errln("test case 2: " + gc1.getMessage());
+ }
+ }
+
+ /**
+ * 6549953 (cal) WEEK_OF_YEAR and DAY_OF_YEAR calculation problems around Gregorian cutover
+ */
+ public void Test6549953() {
+ Koyomi cal = new Koyomi();
+
+ cal.set(YEAR, 1582);
+ cal.set(WEEK_OF_YEAR, 42);
+ cal.set(DAY_OF_WEEK, FRIDAY);
+ cal.checkFieldValue(WEEK_OF_YEAR, 42);
+ cal.checkFieldValue(DAY_OF_WEEK, FRIDAY);
+ if (!cal.checkDate(1582, OCTOBER, 29)) {
+ errln(cal.getMessage());
+ }
+ cal.clear();
+ cal.set(1582, OCTOBER, 1);
+ cal.set(DAY_OF_YEAR, 292);
+ if (!cal.checkDate(1582, OCTOBER, 29)) {
+ errln(cal.getMessage());
+ }
+ }
+}
diff --git a/test/java/util/Calendar/JapanEraNameCompatTest.java b/test/java/util/Calendar/JapanEraNameCompatTest.java
new file mode 100644
index 0000000000..8efed7d224
--- /dev/null
+++ b/test/java/util/Calendar/JapanEraNameCompatTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2019, 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 8218781
+ * @summary Test the localized names of Japanese era Reiwa from COMPAT provider.
+ * @modules jdk.localedata
+ * @run testng/othervm -Djava.locale.providers=COMPAT JapanEraNameCompatTest
+ */
+
+import static java.util.Calendar.*;
+import static java.util.Locale.*;
+
+import java.time.LocalDate;
+import java.time.chrono.JapaneseChronology;
+import java.time.chrono.JapaneseEra;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.format.TextStyle;
+import java.util.Calendar;
+import java.util.Locale;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+@Test
+public class JapanEraNameCompatTest {
+ static final Calendar c = new Calendar.Builder()
+ .setCalendarType("japanese")
+ .setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1)
+ .build();
+ static final String EngName = "Reiwa";
+ static final String CJName = "\u4ee4\u548c";
+ static final String KoreanName = "\ub808\uc774\uc640";
+ static final String ArabicName = "\u0631\u064a\u0648\u0627";
+ static final String ThaiName = "\u0e40\u0e23\u0e27\u0e30";
+ static final String HindiName = "\u0930\u0947\u0907\u0935\u093e";
+ static final String RussianName = "\u0420\u044d\u0439\u0432\u0430";
+ static final String SerbianName = "\u0420\u0435\u0438\u0432\u0430";
+ static final String SerbLatinName = "Reiva";
+
+ @DataProvider(name="UtilCalendar")
+ Object[][] dataUtilCalendar() {
+ return new Object[][] {
+ //locale, long, short
+ { JAPAN, CJName, "R" },
+ { KOREAN, KoreanName, "R" },
+ { CHINA, CJName, "R" },
+ { TAIWAN, CJName, "R" }, // fallback to zh
+ { new Locale("ar"), ArabicName, ArabicName },
+ { new Locale("th"), ThaiName, "R" },
+ // hi_IN fallback to root
+ { new Locale("hi", "IN"), EngName, "R" }
+ };
+ }
+
+ @Test(dataProvider="UtilCalendar")
+ public void testCalendarEraDisplayName(Locale locale,
+ String longName, String shortName) {
+ assertEquals(c.getDisplayName(ERA, LONG, locale), longName);
+ assertEquals(c.getDisplayName(ERA, SHORT, locale), shortName);
+ }
+
+ @DataProvider(name="JavaTime")
+ Object[][] dataJavaTime() {
+ return new Object[][] {
+ // locale, full, short
+ { JAPAN, CJName, CJName },
+ { KOREAN, KoreanName, KoreanName },
+ { CHINA, CJName, CJName },
+ { TAIWAN, CJName, CJName },
+ { new Locale("ar"), ArabicName, ArabicName },
+ { new Locale("th"), ThaiName, ThaiName },
+ { new Locale("hi", "IN"), HindiName, HindiName },
+ { new Locale("ru"), RussianName, RussianName },
+ { new Locale("sr"), SerbianName, SerbianName },
+ { Locale.forLanguageTag("sr-Latn"), SerbLatinName, SerbLatinName },
+ { new Locale("hr"), EngName, EngName },
+ { new Locale("in"), EngName, EngName },
+ { new Locale("lt"), EngName, EngName },
+ { new Locale("nl"), EngName, EngName },
+ { new Locale("no"), EngName, "R" },
+ { new Locale("sv"), EngName, EngName },
+ // el fallback to root
+ { new Locale("el"), EngName, EngName }
+ };
+ }
+
+ @Test(dataProvider="JavaTime")
+ public void testChronoJapanEraDisplayName(Locale locale,
+ String fullName, String shortName) {
+
+ JapaneseEra era = JapaneseEra.valueOf("Reiwa");
+ assertEquals(era.getDisplayName(TextStyle.FULL, locale), fullName);
+ assertEquals(era.getDisplayName(TextStyle.SHORT, locale), shortName);
+ assertEquals(era.getDisplayName(TextStyle.NARROW, locale), "R");
+ }
+
+ @Test
+ public void testFormatParseEraName() {
+ LocalDate date = LocalDate.of(2019, 5, 1);
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd GGGG");
+ formatter = formatter.withChronology(JapaneseChronology.INSTANCE);
+
+ int num = 0;
+ for (Locale locale : Calendar.getAvailableLocales()) {
+ formatter = formatter.withLocale(locale);
+ try {
+ LocalDate.parse(date.format(formatter), formatter);
+ } catch (DateTimeParseException e) {
+ // If an array is defined for Japanese eras in java.time resource,
+ // but an era entry is missing, format fallback to English name
+ // while parse throw DateTimeParseException.
+ num++;
+ System.out.println("Missing java.time resource data for locale: " + locale);
+ }
+ }
+ if (num > 0) {
+ throw new RuntimeException("Missing java.time data for " + num + " locales");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/JulianTest.java b/test/java/util/Calendar/JulianTest.java
new file mode 100644
index 0000000000..bd7105bce8
--- /dev/null
+++ b/test/java/util/Calendar/JulianTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004, 2016, 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 5029449
+ * @summary Tests for the Julian calendar system (before the Gregorian cutover)
+ * @library /java/text/testlib
+ */
+
+import static java.util.GregorianCalendar.*;
+
+public class JulianTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new JulianTest().run(args);
+ }
+
+ /*
+ * 5029449: Regression: GregorianCalendar produces wrong Julian calendar dates in BC 1
+ */
+ public void Test5029449() {
+ Koyomi cal = new Koyomi();
+ cal.clear();
+ cal.set(1, JANUARY, 0);
+ // Date should be BC 1/12/31
+ if (!cal.checkFieldValue(ERA, BC)
+ || !cal.checkDate(1, DECEMBER, 31)) {
+ errln(cal.getMessage());
+ }
+ }
+}
diff --git a/test/java/util/Calendar/Koyomi.java b/test/java/util/Calendar/Koyomi.java
new file mode 100644
index 0000000000..8eec03b5de
--- /dev/null
+++ b/test/java/util/Calendar/Koyomi.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2003, 2016, 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 static java.util.Calendar.*;
+
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * GregorianCalendar subclass for testing.
+ */
+public class Koyomi extends GregorianCalendar {
+ static final String[] FIELD_NAMES = {
+ "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH", "DAY_OF_MONTH",
+ "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR",
+ "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
+ "DST_OFFSET"
+ };
+
+ static final int ALL_FIELDS = (1 << FIELD_COUNT) - 1;
+
+ public Koyomi() {
+ }
+
+ public Koyomi(TimeZone tz) {
+ super(tz);
+ }
+
+ public Koyomi(Locale loc) {
+ super(loc);
+ }
+
+ public Koyomi(TimeZone tz, Locale loc) {
+ super(tz, loc);
+ }
+
+ @Override
+ public void computeTime() {
+ super.computeTime();
+ }
+
+ @Override
+ public void computeFields() {
+ super.computeFields();
+ }
+
+ @Override
+ public void complete() {
+ super.complete();
+ }
+
+ static String getFieldName(int field) {
+ return FIELD_NAMES[field];
+ }
+
+ String toDateString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(internalGet(ERA) == 0 ? "BCE " : "");
+ sb.append(internalGet(YEAR)).append('-');
+ sb.append(internalGet(MONTH)+1).append('-');
+ sb.append(internalGet(DAY_OF_MONTH));
+ return sb.toString();
+ }
+
+ String toTimeString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(internalGet(HOUR_OF_DAY)).append(':');
+ sb.append(internalGet(MINUTE)).append(':');
+ sb.append(internalGet(SECOND)).append('.');
+ int ms = internalGet(MILLISECOND);
+ if (ms < 100) {
+ sb.append('0');
+ if (ms < 10) {
+ sb.append('0');
+ }
+ }
+ sb.append(ms);
+ int offset = internalGet(ZONE_OFFSET) + internalGet(DST_OFFSET);
+ offset /= 60000;
+ offset = (offset/60) * 100 + (offset%60);
+ if (offset >= 0) {
+ sb.append('+');
+ } else {
+ sb.append('-');
+ offset = -offset;
+ }
+ if (offset < 1000) {
+ sb.append('0');
+ if (offset < 100) {
+ sb.append('0');
+ }
+ }
+ sb.append(offset);
+ return sb.toString();
+ }
+
+ String toDateTimeString() {
+ return toDateString() + "T" + toTimeString();
+ }
+
+ StringBuilder msg = new StringBuilder();
+
+ void initTest() {
+ msg = new StringBuilder();
+ }
+
+ String getMessage() {
+ String s = msg.toString();
+ msg = new StringBuilder();
+ return " " + s;
+ }
+
+ void setMessage(String msg) {
+ this.msg = new StringBuilder(msg);
+ }
+
+ void appendMessage(String msg) {
+ this.msg.append(msg);
+ }
+
+ boolean getStatus() {
+ return msg.length() == 0;
+ }
+
+ int getSetStateFields() {
+ int mask = 0;
+ for (int i = 0; i < FIELD_COUNT; i++) {
+ if (isSet(i)) {
+ mask |= 1 << i;
+ }
+ }
+ return mask;
+ }
+
+ int[] getFields() {
+ int[] fds = new int[fields.length];
+ System.arraycopy(fields, 0, fds, 0, fds.length);
+ return fds;
+ }
+
+ boolean checkAllSet() {
+ initTest();
+ for (int i = 0; i < FIELD_COUNT; i++) {
+ checkFieldState(i, true);
+ }
+ return getStatus();
+ }
+
+ boolean checkInternalDate(int year, int month, int dayOfMonth) {
+ initTest();
+ checkInternalFieldValue(YEAR, year);
+ checkInternalFieldValue(MONTH, month);
+ checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth);
+ return getStatus();
+ }
+
+ boolean checkInternalDate(int year, int month, int dayOfMonth, int dayOfWeek) {
+ initTest();
+ checkInternalFieldValue(YEAR, year);
+ checkInternalFieldValue(MONTH, month);
+ checkInternalFieldValue(DAY_OF_MONTH, dayOfMonth);
+ checkInternalFieldValue(DAY_OF_WEEK, dayOfWeek);
+ return getStatus();
+ }
+
+ boolean checkActualMaximum(int field, int expectedValue) {
+ int val;
+ if ((val = getActualMaximum(field)) != expectedValue) {
+ appendMessage("getActualMaximum("+FIELD_NAMES[field]+"): got " + val
+ + " expected " + expectedValue);
+ }
+ return getStatus();
+ }
+
+ boolean checkLeastMaximum(int field, int expectedValue) {
+ int val;
+ if ((val = getLeastMaximum(field)) != expectedValue) {
+ appendMessage("getLeastMaximum("+FIELD_NAMES[field]+"): got " + val
+ + " expected " + expectedValue);
+ }
+ return getStatus();
+ }
+
+ boolean checkActualMinimum(int field, int expectedValue) {
+ int val;
+ if ((val = getActualMinimum(field)) != expectedValue) {
+ appendMessage("getActualMinimum("+FIELD_NAMES[field]+"): got " + val
+ + " expected " + expectedValue);
+ }
+ return getStatus();
+ }
+
+ boolean checkGreatestMinimum(int field, int expectedValue) {
+ int val;
+ if ((val = getGreatestMinimum(field)) != expectedValue) {
+ appendMessage("getGreatestMinimum("+FIELD_NAMES[field]+"): got " + val
+ + " expected " + expectedValue);
+ }
+ return getStatus();
+ }
+
+ boolean checkDate(int year, int month, int dayOfMonth) {
+ initTest();
+ checkFieldValue(YEAR, year);
+ checkFieldValue(MONTH, month);
+ checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+ return getStatus();
+ }
+
+ boolean checkDate(int year, int month, int dayOfMonth, int dayOfWeek) {
+ initTest();
+ checkFieldValue(YEAR, year);
+ checkFieldValue(MONTH, month);
+ checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+ checkFieldValue(DAY_OF_WEEK, dayOfWeek);
+ return getStatus();
+ }
+
+ boolean checkDateTime(int year, int month, int dayOfMonth,
+ int hourOfDay, int minute, int second, int ms) {
+ initTest();
+ checkFieldValue(YEAR, year);
+ checkFieldValue(MONTH, month);
+ checkFieldValue(DAY_OF_MONTH, dayOfMonth);
+ checkFieldValue(HOUR_OF_DAY, hourOfDay);
+ checkFieldValue(MINUTE, minute);
+ checkFieldValue(SECOND, second);
+ checkFieldValue(MILLISECOND, ms);
+ return getStatus();
+ }
+
+ boolean checkTime(int hourOfDay, int minute, int second, int ms) {
+ initTest();
+ checkFieldValue(HOUR_OF_DAY, hourOfDay);
+ checkFieldValue(MINUTE, minute);
+ checkFieldValue(SECOND, second);
+ checkFieldValue(MILLISECOND, ms);
+ return getStatus();
+ }
+
+ boolean checkFieldState(int field, boolean expectedState) {
+ if (isSet(field) != expectedState) {
+ appendMessage(FIELD_NAMES[field] + " state is not " + expectedState + "; ");
+ return false;
+ }
+ return true;
+ }
+
+ boolean checkFieldValue(int field, int expectedValue) {
+ int val;
+ if ((val = get(field)) != expectedValue) {
+ appendMessage("get(" + FIELD_NAMES[field] + "): got " + val +
+ ", expected " + expectedValue + "; ");
+ return false;
+ }
+ return true;
+ }
+
+ boolean checkInternalFieldValue(int field, int expectedValue) {
+ int val;
+ if ((val = internalGet(field)) != expectedValue) {
+ appendMessage("internalGet(" + FIELD_NAMES[field] + "): got " + val +
+ ", expected " + expectedValue + "; ");
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/test/java/util/Calendar/Limit.java b/test/java/util/Calendar/Limit.java
new file mode 100644
index 0000000000..1ab0e172dc
--- /dev/null
+++ b/test/java/util/Calendar/Limit.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.*;
+import java.text.*;
+
+/**
+ * Test GregorianCalendar limits, which should not exist.
+ * @test
+ * @bug 4056585
+ * @summary Make sure that GregorianCalendar works far in the past and future.
+ * @author Alan Liu
+ */
+public class Limit {
+ static final long ONE_DAY = 24*60*60*1000L;
+
+ public static void main(String args[]) throws Exception {
+ GregorianCalendar c = new GregorianCalendar();
+ DateFormat fmt = new SimpleDateFormat("EEEE, MMMM dd, yyyy G", Locale.US);
+ long bigMillis = 300000000000000L;
+
+ try {
+ // We check two things:
+ // 1. That handling millis in the range of +/- bigMillis works.
+ // bigMillis is a value that used to blow up.
+ // 2. The round-trip format/parse works in these extreme areas.
+ c.setTime(new Date(-bigMillis));
+ String s = fmt.format(c.getTime());
+ Date d = fmt.parse(s);
+ if (Math.abs(d.getTime() + bigMillis) >= ONE_DAY) {
+ throw new Exception(s + " != " + fmt.format(d));
+ }
+
+ c.setTime(new Date(+bigMillis));
+ s = fmt.format(c.getTime());
+ d = fmt.parse(s);
+ if (Math.abs(d.getTime() - bigMillis) >= ONE_DAY) {
+ throw new Exception(s + " != " + fmt.format(d));
+ }
+ } catch (IllegalArgumentException | ParseException e) {
+ throw e;
+ }
+ }
+}
diff --git a/test/java/util/Calendar/NonLenientTest.java b/test/java/util/Calendar/NonLenientTest.java
new file mode 100644
index 0000000000..6c42c59493
--- /dev/null
+++ b/test/java/util/Calendar/NonLenientTest.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4147269 4266783 4726030
+ * @summary Make sure that validation is adequate in non-lenient mode.
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+import static java.util.Calendar.*;
+
+public class NonLenientTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ Locale reservedLocale = Locale.getDefault();
+ TimeZone reservedTimeZone = TimeZone.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+ new NonLenientTest().run(args);
+ } finally {
+ // restore the reserved locale and time zone
+ Locale.setDefault(reservedLocale);
+ TimeZone.setDefault(reservedTimeZone);
+ }
+ }
+
+ public void TestValidationInNonLenient() {
+ Koyomi cal = getNonLenient();
+
+ // 2003 isn't a leap year.
+ cal.set(2003, FEBRUARY, 29);
+ validate(cal, "2003/2/29");
+
+ // October has only 31 days.
+ cal.set(2003, OCTOBER, 32);
+ validate(cal, "2003/10/32");
+
+ // 2003/10/31 is Friday.
+ cal.set(2003, OCTOBER, 31);
+ cal.set(DAY_OF_WEEK, SUNDAY);
+ validate(cal, "2003/10/31 SUNDAY");
+
+ // 2003/10/31 is the 304th day of the year.
+ cal.clear();
+ cal.set(DAY_OF_YEAR, 1);
+ cal.set(2003, OCTOBER, 31);
+ validate(cal, "2003/10/31 DAY_OF_YEAR=1");
+
+ // 2003/10 isn't the 1st week of the year.
+ cal.clear();
+ cal.set(YEAR, 2003);
+ cal.set(WEEK_OF_YEAR, 1);
+ cal.set(MONTH, OCTOBER);
+ validate(cal, "2003/10 WEEK_OF_YEAR=1");
+
+ // The 1st week of 2003 doesn't have Monday.
+ cal.clear();
+ cal.set(YEAR, 2003);
+ cal.set(WEEK_OF_YEAR, 1);
+ cal.set(DAY_OF_WEEK, MONDAY);
+ validate(cal, "2003 WEEK_OF_YEAR=1 MONDAY.");
+
+ // 2003 has 52 weeks.
+ cal.clear();
+ cal.set(YEAR, 2003);
+ cal.set(WEEK_OF_YEAR, 53);
+ cal.set(DAY_OF_WEEK, WEDNESDAY);
+ validate(cal, "2003 WEEK_OF_YEAR=53");
+
+ /*
+ * These test cases assume incompatible behavior in Tiger as
+ * the result of the validation bug fixes. However, it looks
+ * like we have to allow applications to set ZONE_OFFSET and
+ * DST_OFFSET values to modify the time zone offsets given by
+ * a TimeZone. The definition of non-leniency for time zone
+ * offsets is somewhat vague. (See 6231602)
+ *
+ * The following test cases are now disabled.
+
+ // America/Los_Angeles is GMT-08:00
+ cal.clear();
+ cal.set(2003, OCTOBER, 31);
+ cal.set(ZONE_OFFSET, 0);
+ validate(cal, "ZONE_OFFSET=0:00 in America/Los_Angeles");
+
+ // 2003/10/31 shouldn't be in DST.
+ cal.clear();
+ cal.set(2003, OCTOBER, 31);
+ cal.set(DST_OFFSET, 60*60*1000);
+ validate(cal, "2003/10/31 DST_OFFSET=1:00 in America/Los_Angeles");
+
+ */
+ }
+
+ /**
+ * 4266783: java.util.GregorianCalendar: incorrect validation in non-lenient
+ */
+ public void Test4266783() {
+ Koyomi cal = getNonLenient();
+ // 2003/1 has up to 5 weeks.
+ cal.set(YEAR, 2003);
+ cal.set(MONTH, JANUARY);
+ cal.set(WEEK_OF_MONTH, 6);
+ cal.set(DAY_OF_WEEK, SUNDAY);
+ validate(cal, "6th Sunday in Jan 2003");
+ }
+
+
+ /**
+ * 4726030: GregorianCalendar doesn't check invalid dates in non-lenient
+ */
+ public void Test4726030() {
+ Koyomi cal = getNonLenient();
+ // Default year is 1970 in GregorianCalendar which isn't a leap year.
+ cal.set(MONTH, FEBRUARY);
+ cal.set(DAY_OF_MONTH, 29);
+ validate(cal, "2/29 in the default year 1970");
+ }
+
+ /**
+ * 4147269: java.util.GregorianCalendar.computeTime() works wrong when lenient is false
+ */
+ public void Test4147269() {
+ Koyomi calendar = getNonLenient();
+ Date date = (new GregorianCalendar(1996,0,3)).getTime();
+
+ for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+ calendar.setTime(date);
+ int max = calendar.getActualMaximum(field);
+ int value = max+1;
+ calendar.set(field, value);
+ try {
+ calendar.computeTime(); // call method under test
+ errln("Test failed with field " + calendar.getFieldName(field)
+ + "\n\tdate before: " + date
+ + "\n\tdate after: " + calendar.getTime()
+ + "\n\tvalue: " + value + " (max = " + max +")");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ for (int field = 0; field < Calendar.FIELD_COUNT; field++) {
+ calendar.setTime(date);
+ int min = calendar.getActualMinimum(field);
+ int value = min-1;
+ calendar.set(field, value);
+ try {
+ calendar.computeTime(); // call method under test
+ errln("Test failed with field " + calendar.getFieldName(field)
+ + "\n\tdate before: " + date
+ + "\n\tdate after: " + calendar.getTime()
+ + "\n\tvalue: " + value + " (min = " + min +")");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+ }
+
+ void validate(Koyomi cal, String desc) {
+ int[] originalFields = cal.getFields();
+ int setFields = cal.getSetStateFields();
+
+ try {
+ cal.complete();
+ errln(desc + " should throw IllegalArgumentException in non-lenient.");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // The code below will be executed with the -nothrow option
+
+ // In non-lenient, calendar field values that have beeb set by
+ // user shouldn't be modified.
+ int[] afterFields = cal.getFields();
+ for (int i = 0; i < Calendar.FIELD_COUNT; i++) {
+ if (cal.isSet(i) && originalFields[i] != afterFields[i]) {
+ errln(" complete() modified fields[" + cal.getFieldName(i) + "] got "
+ + afterFields[i] + ", expected " + originalFields[i]);
+ }
+ }
+ // In non-lenient, set state of fields shouldn't be modified.
+ int afterSetFields = cal.getSetStateFields();
+ if (setFields != afterSetFields) {
+ errln(" complate() modified set states: before 0x" + toHex(setFields)
+ + ", after 0x"+ toHex(afterSetFields));
+ }
+ }
+
+ static Koyomi getNonLenient() {
+ Koyomi cal = new Koyomi();
+ cal.clear();
+ cal.setLenient(false);
+ return cal;
+ }
+
+ static String toHex(int x) {
+ return Integer.toHexString(x);
+ }
+}
diff --git a/test/java/util/Calendar/ResolutionTest.java b/test/java/util/Calendar/ResolutionTest.java
new file mode 100644
index 0000000000..98356131b0
--- /dev/null
+++ b/test/java/util/Calendar/ResolutionTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007, 2016, 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 6452848
+ * @summary Make sure that the resolution of (WEKK_OF_MONTH +
+ * DAY_OF_WEEK) and (DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK) works as
+ * specified in the API.
+ * @key randomness
+ */
+
+import java.util.*;
+import static java.util.Calendar.*;
+
+public class ResolutionTest {
+ static Random rand = new Random();
+
+ public static void main(String[] args) {
+ for (int year = 1995; year < 2011; year++) {
+ for (int month = JANUARY; month <= DECEMBER; month++) {
+ for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+ test(year, month, dow);
+ }
+ }
+ }
+ }
+
+ static void test(int year, int month, int dow) {
+ Calendar cal = new GregorianCalendar(year, month, 1);
+ int max = cal.getActualMaximum(DAY_OF_MONTH);
+ ArrayList<Integer> list = new ArrayList<Integer>();
+ for (int d = 1; d <= max; d++) {
+ cal.clear();
+ cal.set(year, month, d);
+ if (cal.get(DAY_OF_WEEK) == dow) {
+ list.add(d);
+ }
+ }
+ for (int i = 0; i < 100; i++) {
+ int nth = rand.nextInt(list.size()); // 0-based
+ int day = list.get(nth);
+ nth++; // 1-based
+ testDayOfWeekInMonth(year, month, nth, dow, day);
+ }
+
+ // Put WEEK_OF_MONTH-DAY_OF_MONTH pairs
+ list = new ArrayList<Integer>();
+ for (int d = 1; d <= max; d++) {
+ cal.clear();
+ cal.set(year, month, d);
+ if (cal.get(DAY_OF_WEEK) == dow) {
+ list.add(cal.get(WEEK_OF_MONTH));
+ list.add(d);
+ }
+ }
+ for (int i = 0; i < list.size(); i++) {
+ int nth = list.get(i++);
+ int day = list.get(i);
+ testWeekOfMonth(year, month, nth, dow, day);
+ }
+ }
+
+ static Koyomi cal = new Koyomi();
+
+ static void testDayOfWeekInMonth(int year, int month, int nth, int dow, int expected) {
+ // don't call clear() here
+ cal.set(YEAR, year);
+ cal.set(MONTH, month);
+ // Set DAY_OF_WEEK_IN_MONTH before DAY_OF_WEEK
+ cal.set(DAY_OF_WEEK_IN_MONTH, nth);
+ cal.set(DAY_OF_WEEK, dow);
+ if (!cal.checkDate(year, month, expected)) {
+ throw new RuntimeException(String.format("DOWIM: year=%d, month=%d, nth=%d, dow=%d:%s%n",
+ year, month+1, nth, dow, cal.getMessage()));
+ }
+ }
+
+ static void testWeekOfMonth(int year, int month, int nth, int dow, int expected) {
+ // don't call clear() here
+ cal.set(YEAR, year);
+ cal.set(MONTH, month);
+ // Set WEEK_OF_MONTH before DAY_OF_WEEK
+ cal.set(WEEK_OF_MONTH, nth);
+ cal.set(DAY_OF_WEEK, dow);
+ if (!cal.checkDate(year, month, expected)) {
+ throw new RuntimeException(String.format("WOM: year=%d, month=%d, nth=%d, dow=%d:%s%n",
+ year, month+1, nth, dow, cal.getMessage()));
+ }
+ }
+}
diff --git a/test/java/util/Calendar/RollDayOfWeekTest.java b/test/java/util/Calendar/RollDayOfWeekTest.java
new file mode 100644
index 0000000000..5b85016c31
--- /dev/null
+++ b/test/java/util/Calendar/RollDayOfWeekTest.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2004, 2016, 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 5090555 5091805
+ * @summary Make sure that rolling DAY_OF_WEEK stays in the same week
+ * around year boundaries.
+ * @run main/othervm RollDayOfWeekTest 5 5
+ */
+
+import java.util.*;
+
+import static java.util.Calendar.*;
+
+// Usage: java RollDayOfWeekTest [pastYears futureYears]
+public class RollDayOfWeekTest {
+ public static void main(String[] args) {
+ int pastYears = 5, futureYears = 23;
+ if (args.length == 2) {
+ pastYears = Integer.parseInt(args[0]);
+ pastYears = Math.max(1, Math.min(pastYears, 5));
+ futureYears = Integer.parseInt(args[1]);
+ futureYears = Math.max(1, Math.min(futureYears, 28));
+ }
+
+ System.out.printf("Test [%d .. %+d] year range.%n", -pastYears, futureYears);
+ Calendar cal = new GregorianCalendar();
+ int year = cal.get(YEAR) - pastYears;
+
+ // Use the all combinations of firstDayOfWeek and
+ // minimalDaysInFirstWeek values in the year range current
+ // year - pastYears to current year + futureYears.
+ for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) {
+ for (int mdifw = 1; mdifw <= 7; mdifw++) {
+ cal.clear();
+ cal.setFirstDayOfWeek(fdw);
+ cal.setMinimalDaysInFirstWeek(mdifw);
+ cal.set(year, JANUARY, 1);
+ checkRoll(cal, futureYears);
+ }
+ }
+
+ // testing roll from BCE to CE
+ year = -1;
+ for (int fdw = SUNDAY; fdw <= SATURDAY; fdw++) {
+ for (int mdifw = 1; mdifw <= 7; mdifw++) {
+ cal.clear();
+ cal.setFirstDayOfWeek(fdw);
+ cal.setMinimalDaysInFirstWeek(mdifw);
+ cal.set(year, JANUARY, 1);
+ checkRoll(cal, 4);
+ }
+ }
+ }
+
+
+ static void checkRoll(Calendar cal, int years) {
+ Calendar cal2 = null, cal3 = null, prev = null;
+ // Check 28 years
+ for (int x = 0; x < (int)(365.2425*years); x++) {
+ cal2 = (Calendar) cal.clone();
+ cal3 = (Calendar) cal.clone();
+
+ // roll foreword
+ for (int i = 0; i < 10; i++) {
+ prev = (Calendar) cal2.clone();
+ cal2.roll(Calendar.DAY_OF_WEEK, +1);
+ roll(cal3, +1);
+ long t2 = cal2.getTimeInMillis();
+ long t3 = cal3.getTimeInMillis();
+ if (t2 != t3) {
+ System.err.println("prev: " + prev.getTime() + "\n" + prev);
+ System.err.println("cal2: " + cal2.getTime() + "\n" + cal2);
+ System.err.println("cal3: " + cal3.getTime() + "\n" + cal3);
+ throw new RuntimeException("+1: t2=" + t2 + ", t3=" + t3);
+ }
+ }
+
+ // roll backward
+ for (int i = 0; i < 10; i++) {
+ prev = (Calendar) cal2.clone();
+ cal2.roll(Calendar.DAY_OF_WEEK, -1);
+ roll(cal3, -1);
+ long t2 = cal2.getTimeInMillis();
+ long t3 = cal3.getTimeInMillis();
+ if (t2 != t3) {
+ System.err.println("prev: " + prev.getTime() + "\n" + prev);
+ System.err.println("cal2: " + cal2.getTime() + "\n" + cal2);
+ System.err.println("cal3: " + cal3.getTime() + "\n" + cal3);
+ throw new RuntimeException("-1: t2=" + t2 + ", t3=" + t3);
+ }
+ }
+ cal.add(DAY_OF_YEAR, +1);
+ }
+ }
+
+ // Another way to roll within the same week.
+ static void roll(Calendar cal, int n) {
+ int doy = cal.get(DAY_OF_YEAR);
+ int diff = cal.get(DAY_OF_WEEK) - cal.getFirstDayOfWeek();
+ if (diff < 0) {
+ diff += 7;
+ }
+
+ // dow1: first day of the week
+ int dow1 = doy - diff;
+ n %= 7;
+ doy += n;
+ if (doy < dow1) {
+ doy += 7;
+ } else if (doy >= dow1 + 7) {
+ doy -= 7;
+ }
+ cal.set(DAY_OF_YEAR, doy);
+ }
+}
diff --git a/test/java/util/Calendar/StampOverflow.java b/test/java/util/Calendar/StampOverflow.java
new file mode 100644
index 0000000000..fc10595c87
--- /dev/null
+++ b/test/java/util/Calendar/StampOverflow.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4404619 6348819
+ * @summary Make sure that Calendar doesn't cause nextStamp overflow.
+ */
+
+import java.lang.reflect.*;
+import java.util.*;
+import static java.util.Calendar.*;
+
+// Calendar fails when turning negative to positive (zero), not
+// positive to negative with nextStamp. If a negative value was set to
+// nextStamp, it would fail even with the fix. So, there's no way to
+// reproduce the symptom in a short time -- at leaset it would take a
+// couple of hours even if we started with Integer.MAX_VALUE. So, this
+// test case just checks that set() calls don't cause any nextStamp
+// overflow.
+
+public class StampOverflow {
+ public static void main(String[] args) throws IllegalAccessException {
+ // Get a Field for "nextStamp".
+ Field nextstamp = null;
+ try {
+ nextstamp = Calendar.class.getDeclaredField("nextStamp");
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException("implementation changed?", e);
+ }
+
+ nextstamp.setAccessible(true);
+
+ Calendar cal = new GregorianCalendar();
+ int initialValue = nextstamp.getInt(cal);
+ // Set nextStamp to a very large number
+ nextstamp.setInt(cal, Integer.MAX_VALUE - 100);
+
+ for (int i = 0; i < 1000; i++) {
+ invoke(cal);
+ int stampValue = nextstamp.getInt(cal);
+ // nextStamp must not be less than initialValue.
+ if (stampValue < initialValue) {
+ throw new RuntimeException("invalid nextStamp: " + stampValue);
+ }
+ }
+ }
+
+ static void invoke(Calendar cal) {
+ cal.clear();
+ cal.set(2000, NOVEMBER, 2, 0, 0, 0);
+ int y = cal.get(YEAR);
+ int m = cal.get(MONTH);
+ int d = cal.get(DAY_OF_MONTH);
+ if (y != 2000 || m != NOVEMBER || d != 2) {
+ throw new RuntimeException("wrong date produced ("
+ + y + "/" + (m+1) + "/" + d + ")");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/ZoneOffsets.java b/test/java/util/Calendar/ZoneOffsets.java
new file mode 100644
index 0000000000..147df33749
--- /dev/null
+++ b/test/java/util/Calendar/ZoneOffsets.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6231602
+ * @summary Make sure that ZONE_OFFSET and/or DST_OFFSET setting is
+ * taken into account for time calculations.
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+public class ZoneOffsets {
+ // This TimeZone always returns the dstOffset value.
+ private static class TestTimeZone extends TimeZone {
+ private int gmtOffset;
+ private int dstOffset;
+
+ TestTimeZone(int gmtOffset, String id, int dstOffset) {
+ this.gmtOffset = gmtOffset;
+ setID(id);
+ this.dstOffset = dstOffset;
+ }
+
+ public int getOffset(int era, int year, int month, int day,
+ int dayOfWeek, int milliseconds) {
+ return gmtOffset + dstOffset;
+ }
+
+ public int getOffset(long date) {
+ return gmtOffset + dstOffset;
+ }
+
+ public void setRawOffset(int offsetMillis) {
+ gmtOffset = offsetMillis;
+ }
+
+ public int getRawOffset() {
+ return gmtOffset;
+ }
+
+ public int getDSTSavings() {
+ return dstOffset;
+ }
+
+ public boolean useDaylightTime() {
+ return dstOffset != 0;
+ }
+
+ public boolean inDaylightTime(Date date) {
+ return dstOffset != 0;
+ }
+
+ public String toString() {
+ return "TestTimeZone[" + getID() + ", " + gmtOffset + ", " + dstOffset + "]";
+ }
+ }
+
+ private static Locale[] locales = {
+ Locale.getDefault(),
+ new Locale("th", "TH"),
+ new Locale("ja", "JP", "JP"),
+ };
+
+ private static final int HOUR = 60 * 60 * 1000;
+
+ private static int[][] offsets = {
+ { 0, 0 },
+ { 0, HOUR },
+ { 0, 2 * HOUR },
+ { -8 * HOUR, 0 },
+ { -8 * HOUR, HOUR },
+ { -8 * HOUR, 2 * HOUR },
+ { 9 * HOUR, 0 },
+ { 9 * HOUR, HOUR },
+ { 9 * HOUR, 2 * HOUR },
+ };
+
+ public static void main(String[] args) {
+ for (int l = 0; l < locales.length; l++) {
+ Locale loc = locales[l];
+ for (int i = 0; i < offsets.length; i++) {
+ test(loc, offsets[i][0], offsets[i][1]);
+ }
+ }
+
+ // The test case in the bug report.
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setLenient(false);
+ cal.setGregorianChange(new Date(Long.MIN_VALUE));
+ cal.clear();
+ cal.set(ZONE_OFFSET, 0);
+ cal.set(DST_OFFSET, 0);
+ cal.set(ERA, AD);
+ cal.set(2004, FEBRUARY, 3, 0, 0, 0);
+ cal.set(MILLISECOND, 0);
+ // The following line should not throw an IllegalArgumentException.
+ cal.getTime();
+ }
+
+ private static void test(Locale loc, int gmtOffset, int dstOffset) {
+ TimeZone tz1 = new TestTimeZone(gmtOffset,
+ "GMT" + (gmtOffset/HOUR) + "." + (dstOffset/HOUR),
+ dstOffset);
+ int someDifferentOffset = gmtOffset + 2 * HOUR;
+ TimeZone tz2 = new TestTimeZone(someDifferentOffset,
+ "GMT"+ (someDifferentOffset/HOUR) + "." + (dstOffset/HOUR),
+ dstOffset);
+
+ int someDifferentDSTOffset = dstOffset == 2 * HOUR ? HOUR : dstOffset + HOUR;
+ TimeZone tz3 = new TestTimeZone(gmtOffset,
+ "GMT"+ (gmtOffset/HOUR) + "." + (someDifferentDSTOffset/HOUR),
+ someDifferentDSTOffset);
+
+ // cal1 is the base line.
+ Calendar cal1 = Calendar.getInstance(tz1, loc);
+ cal1.clear();
+ cal1.set(2005, MARCH, 11);
+ long t1 = cal1.getTime().getTime();
+ int gmt = cal1.get(ZONE_OFFSET);
+ int dst = cal1.get(DST_OFFSET);
+
+ // Test 8 cases with cal2.
+ Calendar cal2 = Calendar.getInstance(tz2, loc);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test1: set only ZONE_OFFSET
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) {
+ error("Test1", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz3);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test2: set only DST_OFFSET
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) {
+ error("Test2", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz2);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test3: set both ZONE_OFFSET and DST_OFFSET
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime()) {
+ error("Test3", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz3);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test4: set both ZONE_OFFSET and DST_OFFSET
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime()) {
+ error("Test4", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ // Test the same thing in non-lenient
+ cal2.setLenient(false);
+
+ cal2.setTimeZone(tz2);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test5: set only ZONE_OFFSET in non-lenient
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ if (t1 != cal2.getTime().getTime() || dst != cal2.get(DST_OFFSET)) {
+ error("Test5", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz3);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test6: set only DST_OFFSET in non-lenient
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime() || gmt != cal2.get(ZONE_OFFSET)) {
+ error("Test6", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz2);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test7: set both ZONE_OFFSET and DST_OFFSET in non-lenient
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime()) {
+ error("Test7", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+
+ cal2.setTimeZone(tz3);
+ cal2.clear();
+ cal2.set(2005, MARCH, 11);
+ // test8: set both ZONE_OFFSET and DST_OFFSET in non-lenient
+ cal2.set(ZONE_OFFSET, gmtOffset);
+ cal2.set(DST_OFFSET, dstOffset);
+ if (t1 != cal2.getTime().getTime()) {
+ error("Test8", loc, cal2, gmtOffset, dstOffset, t1);
+ }
+ }
+
+ private static void error(String msg, Locale loc, Calendar cal2, int gmtOffset, int dstOffset, long t1) {
+ System.err.println(cal2);
+ throw new RuntimeException(msg + ": Locale=" + loc
+ + ", gmtOffset=" + gmtOffset + ", dstOffset=" + dstOffset
+ + ", cal1 time=" + t1 + ", cal2 time=" + cal2.getTime().getTime());
+ }
+}
diff --git a/test/java/util/Calendar/bug4028518.java b/test/java/util/Calendar/bug4028518.java
new file mode 100644
index 0000000000..982b93adc8
--- /dev/null
+++ b/test/java/util/Calendar/bug4028518.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4028518
+ * @summary Make sure cloned GregorianCalendar is unchanged by modifying its original.
+ */
+
+import java.util.GregorianCalendar ;
+import static java.util.Calendar.*;
+
+public class bug4028518 {
+
+ public static void main(String[] args)
+ {
+ GregorianCalendar cal1 = new GregorianCalendar() ;
+ GregorianCalendar cal2 = (GregorianCalendar) cal1.clone() ;
+
+ printdate(cal1, "cal1: ") ;
+ printdate(cal2, "cal2 - cloned(): ") ;
+ cal1.add(DAY_OF_MONTH, 1) ;
+ printdate(cal1, "cal1 after adding 1 day: ") ;
+ printdate(cal2, "cal2 should be unmodified: ") ;
+ if (cal1.get(DAY_OF_MONTH) == cal2.get(DAY_OF_MONTH)) {
+ throw new RuntimeException("cloned GregorianCalendar modified");
+ }
+ }
+
+ private static void printdate(GregorianCalendar cal, String string)
+ {
+ System.out.println(string + (cal.get(MONTH) + 1)
+ + "/" + cal.get(DAY_OF_MONTH)
+ + "/" + cal.get(YEAR)) ;
+ }
+}
diff --git a/test/java/util/Calendar/bug4100311.java b/test/java/util/Calendar/bug4100311.java
new file mode 100644
index 0000000000..ef0f36ecbd
--- /dev/null
+++ b/test/java/util/Calendar/bug4100311.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4100311
+ * @summary Make sure set(DAY_OF_YEAR, 1) works.
+ */
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Date;
+
+public class bug4100311
+{
+ @SuppressWarnings("deprecation")
+ public static void main(String args[])
+ {
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.set(Calendar.YEAR, 1997);
+ cal.set(Calendar.DAY_OF_YEAR, 1);
+ Date d = cal.getTime(); // Should be Jan 1
+ if (d.getMonth() != 0 || d.getDate() != 1) {
+ throw new RuntimeException("Date isn't Jan 1");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/bug4243802.java b/test/java/util/Calendar/bug4243802.java
new file mode 100644
index 0000000000..1f3b910c1b
--- /dev/null
+++ b/test/java/util/Calendar/bug4243802.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4243802
+ * @summary confirm that Calendar.setTimeInMillis() and
+ * getTimeInMillis() can be called from a user program. (They used to
+ * be protected methods.)
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+public class bug4243802 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new bug4243802().run(args);
+ }
+
+ /**
+ * 4243802: RFE: need way to set the date of a calendar without a Date object
+ */
+ public void Test4243802() {
+ TimeZone saveZone = TimeZone.getDefault();
+ Locale saveLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+
+ Calendar cal1 = Calendar.getInstance();
+ Calendar cal2 = Calendar.getInstance();
+
+ cal1.clear();
+ cal2.clear();
+ cal1.set(2001, Calendar.JANUARY, 25, 1, 23, 45);
+ cal2.setTimeInMillis(cal1.getTimeInMillis());
+ if ((cal2.get(Calendar.YEAR) != 2001) ||
+ (cal2.get(Calendar.MONTH) != Calendar.JANUARY) ||
+ (cal2.get(Calendar.DAY_OF_MONTH) != 25) ||
+ (cal2.get(Calendar.HOUR_OF_DAY) != 1) ||
+ (cal2.get(Calendar.MINUTE) != 23) ||
+ (cal2.get(Calendar.SECOND) != 45) ||
+ (cal2.get(Calendar.MILLISECOND) != 0)) {
+ errln("Failed: expected 1/25/2001 1:23:45.000" +
+ ", got " + (cal2.get(Calendar.MONTH)+1) + "/" +
+ cal2.get(Calendar.DAY_OF_MONTH) +"/" +
+ cal2.get(Calendar.YEAR) + " " +
+ cal2.get(Calendar.HOUR_OF_DAY) + ":" +
+ cal2.get(Calendar.MINUTE) + ":" +
+ cal2.get(Calendar.SECOND) + "." +
+ toMillis(cal2.get(Calendar.MILLISECOND)));
+ }
+ logln("Passed.");
+ }
+ finally {
+ Locale.setDefault(saveLocale);
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ private String toMillis(int m) {
+ StringBuffer sb = new StringBuffer();
+ if (m < 100) {
+ sb.append('0');
+ }
+ if (m < 10) {
+ sb.append('0');
+ }
+ sb.append(m);
+ return sb.toString();
+ }
+}
diff --git a/test/java/util/Calendar/bug4316678.java b/test/java/util/Calendar/bug4316678.java
new file mode 100644
index 0000000000..8ae6bbc294
--- /dev/null
+++ b/test/java/util/Calendar/bug4316678.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2016, 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.io.*;
+import java.util.*;
+import java.text.*;
+
+/**
+ * @test
+ * @bug 4316678
+ * @summary test that Calendar's Serializasion works correctly.
+ * @library /java/text/testlib
+ */
+public class bug4316678 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new bug4316678().run(args);
+ }
+
+ public void Test4316678() throws Exception {
+ GregorianCalendar gc1;
+ GregorianCalendar gc2;
+ TimeZone saveZone = TimeZone.getDefault();
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+ gc1 = new GregorianCalendar(2000, Calendar.OCTOBER, 10);
+ try (ObjectOutputStream out
+ = new ObjectOutputStream(new FileOutputStream("bug4316678.ser"))) {
+ out.writeObject(gc1);
+ }
+
+ try (ObjectInputStream in
+ = new ObjectInputStream(new FileInputStream("bug4316678.ser"))) {
+ gc2 = (GregorianCalendar)in.readObject();
+ }
+
+ gc1.set(Calendar.DATE, 16);
+ gc2.set(Calendar.DATE, 16);
+ if (!gc1.getTime().equals(gc2.getTime())) {
+ errln("Invalid Time :" + gc2.getTime() +
+ ", expected :" + gc1.getTime());
+ }
+ } finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+}
diff --git a/test/java/util/Calendar/bug4372743.java b/test/java/util/Calendar/bug4372743.java
new file mode 100644
index 0000000000..1800ebc002
--- /dev/null
+++ b/test/java/util/Calendar/bug4372743.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2000, 2016, 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 4372743
+ * @summary test that checks transitions of ERA and YEAR which are caused by add(MONTH).
+ * @library /java/text/testlib
+ */
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+import static java.util.GregorianCalendar.*;
+
+public class bug4372743 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new bug4372743().run(args);
+ }
+
+ private int[][] data = {
+ {AD, 2, MARCH},
+ {AD, 2, FEBRUARY},
+ {AD, 2, JANUARY},
+ {AD, 1, DECEMBER},
+ {AD, 1, NOVEMBER},
+ {AD, 1, OCTOBER},
+ {AD, 1, SEPTEMBER},
+ {AD, 1, AUGUST},
+ {AD, 1, JULY},
+ {AD, 1, JUNE},
+ {AD, 1, MAY},
+ {AD, 1, APRIL},
+ {AD, 1, MARCH},
+ {AD, 1, FEBRUARY},
+ {AD, 1, JANUARY},
+ {BC, 1, DECEMBER},
+ {BC, 1, NOVEMBER},
+ {BC, 1, OCTOBER},
+ {BC, 1, SEPTEMBER},
+ {BC, 1, AUGUST},
+ {BC, 1, JULY},
+ {BC, 1, JUNE},
+ {BC, 1, MAY},
+ {BC, 1, APRIL},
+ {BC, 1, MARCH},
+ {BC, 1, FEBRUARY},
+ {BC, 1, JANUARY},
+ {BC, 2, DECEMBER},
+ {BC, 2, NOVEMBER},
+ {BC, 2, OCTOBER},
+ };
+ private int tablesize = data.length;
+
+ private void check(GregorianCalendar gc, int index) {
+ if (gc.get(ERA) != data[index][ERA]) {
+ errln("Invalid era :" + gc.get(ERA) +
+ ", expected :" + data[index][ERA]);
+ }
+ if (gc.get(YEAR) != data[index][YEAR]) {
+ errln("Invalid year :" + gc.get(YEAR) +
+ ", expected :" + data[index][YEAR]);
+ }
+ if (gc.get(MONTH) != data[index][MONTH]) {
+ errln("Invalid month :" + gc.get(MONTH) +
+ ", expected :" + data[index][MONTH]);
+ }
+ }
+
+ public void Test4372743() {
+ GregorianCalendar gc;
+ TimeZone saveZone = TimeZone.getDefault();
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+
+ /* Set March 3, A.D. 2 */
+ gc = new GregorianCalendar(2, MARCH, 3);
+ for (int i = 0; i < tablesize; i++) {
+ check(gc, i);
+ gc.add(gc.MONTH, -1);
+ }
+
+ /* Again, Set March 3, A.D. 2 */
+ gc = new GregorianCalendar(2, MARCH, 3);
+ for (int i = 0; i < tablesize; i+=7) {
+ check(gc, i);
+ gc.add(gc.MONTH, -7);
+ }
+
+ /* Set March 10, 2 B.C. */
+ gc = new GregorianCalendar(2, OCTOBER, 10);
+ gc.add(gc.YEAR, -3);
+ for (int i = tablesize -1; i >= 0; i--) {
+ check(gc, i);
+ gc.add(gc.MONTH, 1);
+ }
+
+ /* Again, Set March 10, 2 B.C. */
+ gc = new GregorianCalendar(2, OCTOBER, 10);
+ gc.add(gc.YEAR, -3);
+ for (int i = tablesize -1; i >= 0; i-=8) {
+ check(gc, i);
+ gc.add(gc.MONTH, 8);
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+}
diff --git a/test/java/util/Calendar/bug4401223.java b/test/java/util/Calendar/bug4401223.java
new file mode 100644
index 0000000000..fbd9e29a8f
--- /dev/null
+++ b/test/java/util/Calendar/bug4401223.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4401223
+ * @summary Make sure that GregorianCalendar doesn't cause IllegalArgumentException at some special situations which are related to the Leap Year.
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+public class bug4401223 extends IntlTest {
+
+ public void Test4401223a() {
+ int status = 0;
+ String s = null;
+
+ try {
+ Date date = new Date(2000-1900, Calendar.FEBRUARY, 29);
+ GregorianCalendar gc = new GregorianCalendar();
+ gc.setTime(date);
+ gc.setLenient(false);
+ gc.set(Calendar.YEAR, 2001);
+ s = "02/29/00 & set(YEAR,2001) = " + gc.getTime().toString();
+ } catch (Exception ex) {
+ status++;
+ s = "Exception occurred for 2/29/00 & set(YEAR,2001): " + ex;
+ }
+ if (status > 0) {
+ errln(s);
+ } else {
+ logln(s);
+ }
+ }
+
+ public void Test4401223b() {
+ int status = 0;
+ String s = null;
+
+ try {
+ Date date = new Date(2000-1900, Calendar.DECEMBER, 31);
+ GregorianCalendar gc = new GregorianCalendar();
+ gc.setTime(date);
+ gc.setLenient(false);
+ gc.set(Calendar.YEAR, 2001);
+
+ if (gc.get(Calendar.YEAR) != 2001 ||
+ gc.get(Calendar.MONTH) != Calendar.DECEMBER ||
+ gc.get(Calendar.DATE) != 31 ||
+ gc.get(Calendar.DAY_OF_YEAR) != 365) {
+ status++;
+ s = "Wrong Date : 12/31/00 & set(YEAR,2001) ---> " + gc.getTime().toString();
+ } else {
+ s = "12/31/00 & set(YEAR,2001) = " + gc.getTime().toString();
+ }
+ } catch (Exception ex) {
+ status++;
+ s = "Exception occurred for 12/31/00 & set(YEAR,2001) : " + ex;
+ }
+ if (status > 0) {
+ errln(s);
+ } else {
+ logln(s);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ new bug4401223().run(args);
+ }
+}
diff --git a/test/java/util/Calendar/bug4409072.java b/test/java/util/Calendar/bug4409072.java
new file mode 100644
index 0000000000..d8e56a4554
--- /dev/null
+++ b/test/java/util/Calendar/bug4409072.java
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4409072
+ * @summary tests for set(), add(), and roll() with various week parameters.
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+import static java.util.Calendar.*;
+
+public class bug4409072 extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new bug4409072().run(args);
+ }
+
+ /* Confirm some public methods' behavior in Calendar.
+ * (e.g. add(), roll(), set())
+ */
+ public void Test4409072() {
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTZ = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ testSet();
+ testAdd();
+ testRoll();
+ } finally {
+ TimeZone.setDefault(savedTZ);
+ Locale.setDefault(savedLocale);
+ }
+ }
+
+ /*
+ * Golden data for set() test
+ */
+ static final int[][][] resultWOMForSetTest = {
+ { /* For year1998 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11},
+ /* Mon */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11},
+ /* Tue */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ /* Wed */ {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ /* Thu */ {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ /* Fri */ {10,27}, {10,27}, {10,27}, {11, 4}, {11, 4}, {11, 4}, {11, 4},
+ /* Sat */ {11, 4}, {11, 4}, {11, 4}, {11, 4}, {11,11}, {11,11}, {11,11},
+ },
+ { /* For year1999 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10},
+ /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10},
+ /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10},
+ /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10},
+ },
+ { /* For year2000 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8},
+ /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8},
+ /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8},
+ /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1},
+ /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ },
+ { /* For year2001 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+ /* Mon */ {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+ /* Tue */ {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+ /* Wed */ {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7}, {11, 7},
+ /* Thu */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7}, {11, 7},
+ /* Fri */ {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {10,30}, {11, 7},
+ /* Sat */ {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7}, {11, 7},
+ },
+ { /* For year2002 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+ /* Mon */ {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+ /* Tue */ {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+ /* Wed */ {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6}, {11, 6},
+ /* Thu */ {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6}, {11, 6},
+ /* Fri */ {10,29}, {10,29}, {10,29}, {10,29}, {10,29}, {11, 6}, {11, 6},
+ /* Sat */ {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11, 6}, {11,13},
+ },
+ { /* For year2003 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12},
+ /* Mon */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+ /* Tue */ {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+ /* Wed */ {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+ /* Thu */ {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5}, {11, 5},
+ /* Fri */ {10,28}, {10,28}, {10,28}, {10,28}, {11, 5}, {11, 5}, {11, 5},
+ /* Sat */ {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11, 5}, {11,12}, {11,12},
+ },
+ { /* For year2004 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10},
+ /* Mon */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10},
+ /* Tue */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11,10},
+ /* Wed */ {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Thu */ {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Fri */ {10,26}, {10,26}, {11, 3}, {11, 3}, {11, 3}, {11, 3}, {11, 3},
+ /* Sat */ {11, 3}, {11, 3}, {11, 3}, {11,10}, {11,10}, {11,10}, {11,10},
+ },
+ { /* For year2005 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9},
+ /* Mon */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9},
+ /* Tue */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9}, {11, 9},
+ /* Wed */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 9},
+ /* Thu */ {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2},
+ /* Fri */ {10,25}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2}, {11, 2},
+ /* Sat */ {11, 2}, {11, 2}, {11, 9}, {11, 9}, {11, 9}, {11, 9}, {11, 9},
+ },
+ { /* For year2006 */
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ /* Mon */ {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ /* Tue */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8}, {11, 8},
+ /* Wed */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8}, {11, 8},
+ /* Thu */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 8},
+ /* Fri */ {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1}, {11, 1},
+ /* Sat */ {11, 1}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8}, {11, 8},
+ },
+ };
+
+ static final int[][][] resultWOYForSetTest1 = {
+ { /* For year1998 */
+ /* FirstDayOfWeek = Sunday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9},
+ {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+ /* FirstDayOfWeek = Monday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+ /* FirstDayOfWeek = Tuesday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9},
+ /* FirstDayOfWeek = Wednesday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9},
+ /* FirstDayOfWeek = Thursday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ /* FirstDayOfWeek = Friday */
+ {1997,11,26}, {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 2},
+ /* FirstDayOfWeek = Saturday */
+ {1998, 0, 2}, {1998, 0, 2}, {1998, 0, 9}, {1998, 0, 9},
+ {1998, 0, 9}, {1998, 0, 9}, {1998, 0, 9},
+ },
+ { /* For year1999 */
+ /* FirstDayOfWeek = Sunday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8},
+ {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+ /* FirstDayOfWeek = Monday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8},
+ {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+ /* FirstDayOfWeek = Tuesday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+ {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+ /* FirstDayOfWeek = Wednesday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+ {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8},
+ /* FirstDayOfWeek = Thursday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 8},
+ /* FirstDayOfWeek = Friday */
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+ {1999, 0, 1}, {1999, 0, 1}, {1999, 0, 1},
+ /* FirstDayOfWeek = Saturday */
+ {1999, 0, 1}, {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+ {1999, 0, 8}, {1999, 0, 8}, {1999, 0, 8},
+ },
+ { /* For year2000 */
+ /* FirstDayOfWeek = Sunday */
+ {1999,11,31}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ /* FirstDayOfWeek = Monday */
+ {1999,11,31}, {1999,11,31}, {2000, 0, 7}, {2000, 0, 7},
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ /* FirstDayOfWeek = Tuesday */
+ {1999,11,31}, {1999,11,31}, {1999,11,31}, {2000, 0, 7},
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ /* FirstDayOfWeek = Wednesday */
+ {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ /* FirstDayOfWeek = Thursday */
+ {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+ {1999,11,31}, {2000, 0, 7}, {2000, 0, 7},
+ /* FirstDayOfWeek = Friday */
+ {1999,11,31}, {1999,11,31}, {1999,11,31}, {1999,11,31},
+ {1999,11,31}, {1999,11,31}, {2000, 0, 7},
+ /* FirstDayOfWeek = Saturday */
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ {2000, 0, 7}, {2000, 0, 7}, {2000, 0, 7},
+ },
+ { /* For year2001 */
+ /* FirstDayOfWeek = Sunday */
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0,12},
+ /* FirstDayOfWeek = Monday */
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ /* FirstDayOfWeek = Tuesday */
+ {2000,11,29}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ /* FirstDayOfWeek = Wednesday */
+ {2000,11,29}, {2000,11,29}, {2001, 0, 5}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ /* FirstDayOfWeek = Thursday */
+ {2000,11,29}, {2000,11,29}, {2000,11,29}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ /* FirstDayOfWeek = Friday */
+ {2000,11,29}, {2000,11,29}, {2000,11,29}, {2000,11,29},
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ /* FirstDayOfWeek = Saturday */
+ {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5}, {2001, 0, 5},
+ {2001, 0, 5}, {2001, 0,12}, {2001, 0,12},
+ },
+ { /* For year2002 */
+ /* FirstDayOfWeek = Sunday */
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0,11}, {2002, 0,11},
+ /* FirstDayOfWeek = Monday */
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0,11},
+ /* FirstDayOfWeek = Tuesday */
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ /* FirstDayOfWeek = Wednesday */
+ {2001,11,28}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ /* FirstDayOfWeek = Thursday */
+ {2001,11,28}, {2001,11,28}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ /* FirstDayOfWeek = Friday */
+ {2001,11,28}, {2001,11,28}, {2001,11,28}, {2002, 0, 4},
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ /* FirstDayOfWeek = Saturday */
+ {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4}, {2002, 0, 4},
+ {2002, 0,11}, {2002, 0,11}, {2002, 0,11},
+ },
+ { /* For year2003 */
+ /* FirstDayOfWeek = Sunday */
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0,10}, {2003, 0,10}, {2003, 0,10},
+ /* FirstDayOfWeek = Monday */
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0, 3}, {2003, 0,10}, {2003, 0,10},
+ /* FirstDayOfWeek = Tuesday */
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10},
+ /* FirstDayOfWeek = Wednesday */
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ /* FirstDayOfWeek = Thursday */
+ {2002,11,27}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ /* FirstDayOfWeek = Friday */
+ {2002,11,27}, {2002,11,27}, {2003, 0, 3}, {2003, 0, 3},
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3},
+ /* FirstDayOfWeek = Saturday */
+ {2003, 0, 3}, {2003, 0, 3}, {2003, 0, 3}, {2003, 0,10},
+ {2003, 0,10}, {2003, 0,10}, {2003, 0,10},
+ },
+ { /* For year2004 */
+ /* FirstDayOfWeek = Sunday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9},
+ {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+ /* FirstDayOfWeek = Monday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+ /* FirstDayOfWeek = Tuesday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9},
+ /* FirstDayOfWeek = Wednesday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9},
+ /* FirstDayOfWeek = Thursday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ /* FirstDayOfWeek = Friday */
+ {2003,11,26}, {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 2},
+ /* FirstDayOfWeek = Saturday */
+ {2004, 0, 2}, {2004, 0, 2}, {2004, 0, 9}, {2004, 0, 9},
+ {2004, 0, 9}, {2004, 0, 9}, {2004, 0, 9},
+ },
+ { /* For year2005 */
+ /* FirstDayOfWeek = Sunday */
+ {2004,11,31}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ /* FirstDayOfWeek = Monday */
+ {2004,11,31}, {2004,11,31}, {2005, 0, 7}, {2005, 0, 7},
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ /* FirstDayOfWeek = Tuesday */
+ {2004,11,31}, {2004,11,31}, {2004,11,31}, {2005, 0, 7},
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ /* FirstDayOfWeek = Wednesday */
+ {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ /* FirstDayOfWeek = Thursday */
+ {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+ {2004,11,31}, {2005, 0, 7}, {2005, 0, 7},
+ /* FirstDayOfWeek = Friday */
+ {2004,11,31}, {2004,11,31}, {2004,11,31}, {2004,11,31},
+ {2004,11,31}, {2004,11,31}, {2005, 0, 7},
+ /* FirstDayOfWeek = Saturday */
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ {2005, 0, 7}, {2005, 0, 7}, {2005, 0, 7},
+ },
+ { /* For year2006 */
+ /* FirstDayOfWeek = Sunday */
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Monday */
+ {2005,11,30}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Tuesday */
+ {2005,11,30}, {2005,11,30}, {2006, 0, 6}, {2006, 0, 6},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Wednesday */
+ {2005,11,30}, {2005,11,30}, {2005,11,30}, {2006, 0, 6},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Thursday */
+ {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Friday */
+ {2005,11,30}, {2005,11,30}, {2005,11,30}, {2005,11,30},
+ {2005,11,30}, {2006, 0, 6}, {2006, 0, 6},
+ /* FirstDayOfWeek = Saturday */
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6}, {2006, 0, 6},
+ {2006, 0, 6}, {2006, 0, 6}, {2006, 0,13},
+ }
+ };
+
+ static final int[][] resultWOYForSetTest2 = {
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+ /* Mon */ {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+ /* Tue */ {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+ /* Wed */ {4,25}, {4,25}, {4,25}, {4,25}, {5, 1}, {5, 1}, {5, 1},
+ /* Thu */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8}, {5, 8},
+ /* Fri */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 8},
+ /* Sat */ {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1}, {5, 1},
+ };
+
+ /**
+ * Test for set()
+ */
+ void testSet() {
+ boolean noerror = true;
+ Calendar cal = Calendar.getInstance();
+ int sYear=1998;
+ int eYear=2006;
+
+ // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+ for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+ // Loop for MinimalDaysInFirstWeek: 1..7
+ for (int minDow = 1; minDow <= 7; minDow++) {
+ int index = (dow-1)*7 + (minDow-1);
+
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(YEAR, 2005);
+ cal.set(DAY_OF_WEEK, WEDNESDAY);
+ cal.set(WEEK_OF_YEAR, 22);
+
+ int y = 2005;
+ int m = resultWOYForSetTest2[index][0];
+ int d = resultWOYForSetTest2[index][1];
+ int year = cal.get(YEAR);
+ int month = cal.get(MONTH);
+ int date = cal.get(DATE);
+
+ if (cal.get(WEEK_OF_YEAR) != 22) {
+ noerror = false;
+ errln("Failed : set(WEEK_OF_YEAR=22)" +
+ " *** get(WEEK_OF_YEAR=" +
+ cal.get(WEEK_OF_YEAR) + ")" +
+ ", got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+2005 +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ } else if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : set(WEEK_OF_YEAR=22)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+
+ for (int targetYear = sYear; targetYear<= eYear; targetYear++) {
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(YEAR, targetYear);
+ cal.set(DAY_OF_WEEK, FRIDAY);
+ cal.set(MONTH, DECEMBER);
+ cal.set(WEEK_OF_MONTH, 1);
+
+ y = targetYear;
+ m = resultWOMForSetTest[targetYear-sYear][index][0];
+ d = resultWOMForSetTest[targetYear-sYear][index][1];
+ year = cal.get(YEAR);
+ month = cal.get(MONTH);
+ date = cal.get(DATE);
+
+ if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : set(WEEK_OF_MONTH=1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(YEAR, targetYear);
+ cal.set(DAY_OF_WEEK, FRIDAY);
+ cal.set(WEEK_OF_YEAR, 1);
+
+ y = resultWOYForSetTest1[targetYear-sYear][index][0];
+ m = resultWOYForSetTest1[targetYear-sYear][index][1];
+ d = resultWOYForSetTest1[targetYear-sYear][index][2];
+ year = cal.get(YEAR);
+ month = cal.get(MONTH);
+ date = cal.get(DATE);
+
+ if (cal.get(WEEK_OF_YEAR) != 1) {
+ noerror = false;
+ errln("Failed : set(WEEK_OF_YEAR=1)" +
+ " *** get(WEEK_OF_YEAR=" +
+ cal.get(WEEK_OF_YEAR) + ")" +
+ ", got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ } else if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : set(WEEK_OF_YEAR=1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+ }
+ }
+ }
+
+ if (noerror) {
+ logln("Passed : set() test");
+ }
+ }
+
+ /**
+ * Test for add()
+ */
+ void testAdd() {
+ boolean noerror = true;
+ Calendar cal = Calendar.getInstance();
+
+ // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+ for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+ // Loop for MinimalDaysInFirstWeek: 1..7
+ for (int minDow = 1; minDow <= 7; minDow++) {
+ int oldWOY, newWOY;
+
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(2005, DECEMBER, 7);
+ oldWOY = cal.get(WEEK_OF_YEAR);
+
+ for (int cnt = 0; cnt < 7; cnt++) {
+ cal.add(WEEK_OF_YEAR, 1);
+ }
+
+ int year = cal.get(YEAR);
+ int month = cal.get(MONTH);
+ int date = cal.get(DATE);
+
+ if ((year != 2006) || (month != 0) || (date != 25)) {
+ noerror = false;
+ errln("Failed : add(WEEK_OF_YEAR+1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected 1/25/2006" +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+
+ for (int cnt = 0; cnt < 10; cnt++) {
+ cal.add(WEEK_OF_YEAR, -1);
+ }
+ newWOY = cal.get(WEEK_OF_YEAR);
+
+ year = cal.get(YEAR);
+ month = cal.get(MONTH);
+ date = cal.get(DATE);
+
+ if ((oldWOY - newWOY) != 3) {
+ errln("Failed : add(WEEK_OF_YEAR-1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected 11/16/2005" +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow +
+ ", WEEK_OF_YEAR=" + newWOY +
+ " should be " + (oldWOY-3));
+ } else if ((year != 2005) || (month != 10) || (date != 16)) {
+ errln("Failed : add(-1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected 11/16/2005" +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+ }
+ }
+
+ if (noerror) {
+ logln("Passed : add() test");
+ }
+ }
+
+ /*
+ * Golden data for roll() test
+ */
+ static final int[] resultWOMForRollTest = {
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ 1, 1, 1, 26, 26, 26, 26,
+ /* Mon */ 1, 1, 1, 1, 26, 26, 26,
+ /* Tue */ 31, 31, 31, 31, 31, 24, 24,
+ /* Wed */ 31, 31, 31, 31, 31, 31, 24,
+ /* Thu */ 31, 31, 31, 31, 31, 31, 31,
+ /* Fri */ 1, 31, 31, 31, 31, 31, 31,
+ /* Sat */ 1, 1, 31, 31, 31, 31, 31,
+ };
+
+ static final int[][] resultWOYForRollTest = {
+ /* Min = 1 2 3 4 5 6 7 */
+ /* Sun */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+ /* Mon */ {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+ /* Tue */ {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+ /* Wed */ {1, 2}, {1, 2}, {1, 2}, {0,26}, {0,26}, {0,26}, {0,26},
+ /* Thu */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2}, {1, 2},
+ /* Fri */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {1, 2},
+ /* Sat */ {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26}, {0,26},
+ };
+
+ /**
+ * Test for roll()
+ */
+ void testRoll() {
+ boolean noerror = true;
+ Calendar cal = Calendar.getInstance();
+
+ // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
+ for (int dow = SUNDAY; dow <= SATURDAY; dow++) {
+
+ // Loop for MinimalDaysInFirstWeek: 1..7
+ for (int minDow = 1; minDow <= 7; minDow++) {
+ int oldWOY, newWOY;
+ int index = (dow-1)*7 + (minDow-1);
+
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(2005, DECEMBER, 12);
+ oldWOY = cal.get(WEEK_OF_YEAR);
+ for (int cnt = 0; cnt < 2; cnt++) {
+ cal.roll(WEEK_OF_MONTH, -1);
+ }
+ int y = 2005;
+ int m = DECEMBER;
+ int d = resultWOMForRollTest[index];
+ int year = cal.get(YEAR);
+ int month = cal.get(MONTH);
+ int date = cal.get(DATE);
+
+ if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : roll(WEEK_OF_MONTH-1)" +
+ " got " + (month+1) + "/" + date + "/" + year +
+ ", expected " + (m+1) + "/" + d + "/" + y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+
+ cal.clear();
+ cal.setLenient(true);
+ cal.setMinimalDaysInFirstWeek(minDow);
+ cal.setFirstDayOfWeek(dow);
+ cal.set(2005, DECEMBER, 7);
+ oldWOY = cal.get(WEEK_OF_YEAR);
+
+ for (int cnt = 0; cnt < 7; cnt++) {
+ cal.roll(WEEK_OF_YEAR, 1);
+ }
+
+ y = 2005;
+ m = resultWOYForRollTest[index][0];
+ d = resultWOYForRollTest[index][1];
+ year = cal.get(YEAR);
+ month = cal.get(MONTH);
+ date = cal.get(DATE);
+
+ if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : roll(WEEK_OF_YEAR+1)" +
+ " got " + (month+1) + "/" + date + "/" + year +
+ ", expected " + (m+1) + "/" + d + "/" + y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+
+ for (int cnt = 0; cnt < 10; cnt++) {
+ cal.roll(WEEK_OF_YEAR, -1);
+ }
+ newWOY = cal.get(WEEK_OF_YEAR);
+
+ y = 2005;
+ m = NOVEMBER;
+ d = 16;
+ year = cal.get(YEAR);
+ month = cal.get(MONTH);
+ date = cal.get(DATE);
+
+ if ((year != y) || (month != m) || (date != d)) {
+ noerror = false;
+ errln("Failed : roll(WEEK_OF_YEAR-1)" +
+ " got " + (month+1)+"/"+date+"/"+year +
+ ", expected " + (m+1)+"/"+d+"/"+y +
+ ", MinFirstDOW=" + minDow +
+ ", FirstDOW=" + dow);
+ }
+ }
+ }
+
+ if (noerror) {
+ logln("Passed : roll() test");
+ }
+ }
+}
diff --git a/test/java/util/Calendar/bug4514831.java b/test/java/util/Calendar/bug4514831.java
new file mode 100644
index 0000000000..9d635e2616
--- /dev/null
+++ b/test/java/util/Calendar/bug4514831.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4514831
+ * @summary Confirm that GregorianCalendar.roll() works properly during transition from Daylight Saving Time to Standard Time.
+ */
+
+import java.util.*;
+
+public class bug4514831 {
+
+ public static void main(String[] args) {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ boolean err = false;
+
+ String golden_data1 ="27-28 28-29 29-30 30-31 31-1 1-2 2-3 ";
+ String golden_data2 ="27-28 28-29 29-30 30-31 31-25 25-26 26-27 ";
+ String golden_data3 ="1-8 8-15 15-22 22-29 29-1 1-8 8-15 ";
+
+ try {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Pacific"));
+
+ String test_roll = "";
+ GregorianCalendar c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27);
+ for (int i=0; i < 7; i++) {
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+ c_roll.roll(c_roll.DAY_OF_YEAR, true);
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+ }
+ if (!test_roll.equals(golden_data1)) {
+ err = true;
+ System.err.println("Wrong roll(DAY_OF_YEAR) transition: got "+
+ test_roll + "expected " + golden_data1);
+ }
+
+ test_roll = "";
+ c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 27);
+ c_roll.setFirstDayOfWeek(Calendar.THURSDAY);
+ for (int i=0; i < 7; i++) {
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+ c_roll.roll(c_roll.DAY_OF_WEEK, true);
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+ }
+ if (!test_roll.equals(golden_data2)) {
+ err = true;
+ System.err.println("Wrong roll(DAY_OF_WEEK) transition: got "+
+ test_roll + "expected " + golden_data2);
+ }
+
+ test_roll = "";
+ c_roll = new GregorianCalendar(2001, Calendar.OCTOBER, 1);
+ for (int i=0; i < 7; i++) {
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + "-";
+ c_roll.roll(c_roll.DAY_OF_WEEK_IN_MONTH, true);
+ test_roll += c_roll.get(c_roll.DAY_OF_MONTH) + " ";
+ }
+ if (!test_roll.equals(golden_data3)) {
+ err = true;
+ System.err.println("Wrong roll(DAY_OF_WEEK_IN_MONTH) transition: got "+
+ test_roll + "expected " + golden_data3);
+ }
+ } finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+
+ if (err) {
+ throw new RuntimeException("Wrong roll() transition");
+ }
+ }
+}
diff --git a/test/java/util/Collections/NCopies.java b/test/java/util/Collections/NCopies.java
index db1a61b0dc..2458386fb6 100644
--- a/test/java/util/Collections/NCopies.java
+++ b/test/java/util/Collections/NCopies.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -82,6 +82,56 @@ public class NCopies {
checkEmpty(x.subList(x.size()/2, x.size()/2));
}
+ private static <T> List<T> referenceNCopies(int n, T o) {
+ // A simplest correct implementation of nCopies to compare with the actual optimized implementation
+ return new AbstractList<T>() {
+ public int size() { return n; }
+
+ public T get(int index) {
+ check(0 <= index && index < n, "Index is incorrect");
+ return o;
+ }
+ };
+ }
+
+ private static void checkHashCode() {
+ int[] sizes = {0, 1, 2, 3, 5, 10, 31, 32, 100, 1000};
+ String[] elements = {null, "non-null"};
+ for (int size : sizes) {
+ for (String element : elements) {
+ int expectedHashCode = referenceNCopies(size, element).hashCode();
+ int actualHashCode = Collections.nCopies(size, element).hashCode();
+ check(expectedHashCode == actualHashCode,
+ "Collections.nCopies(" + size + ", " + element + ").hashCode()");
+ }
+ }
+ }
+
+ private static void checkEquals() {
+ int[][] sizePairs = {{0, 0}, {0, 1}, {1, 0}, {1, 1}, {1, 2}, {2, 1}};
+ String[] elements = {null, "non-null"};
+ for (int[] pair : sizePairs) {
+ for (String element : elements) {
+ boolean equal = pair[0] == pair[1];
+ String msg = "[" + pair[0] + ", " + element + "] <=> [" + pair[1] + ", " + element + "]";
+ check(equal == Collections.nCopies(pair[0], element).equals(Collections.nCopies(pair[1], element)), msg);
+ check(equal == Collections.nCopies(pair[0], element).equals(referenceNCopies(pair[1], element)), msg);
+ check(equal == referenceNCopies(pair[0], element).equals(Collections.nCopies(pair[1], element)), msg);
+ }
+ }
+ List<String> nulls = Collections.nCopies(10, null);
+ List<String> nonNulls = Collections.nCopies(10, "non-null");
+ List<String> nullsButOne = new ArrayList<>(nulls);
+ nullsButOne.set(9, "non-null");
+ List<String> nonNullsButOne = new ArrayList<>(nonNulls);
+ nonNullsButOne.set(9, null);
+ check(!nulls.equals(nonNulls));
+ check(!nulls.equals(nullsButOne));
+ check(!nulls.equals(nonNullsButOne));
+ check(!nonNulls.equals(nonNullsButOne));
+ check(Collections.nCopies(0, null).equals(Collections.nCopies(0, "non-null")));
+ }
+
public static void main(String[] args) {
try {
List<String> empty = Collections.nCopies(0, "foo");
@@ -92,6 +142,10 @@ public class NCopies {
check(foos.size() == 42);
checkFoos(foos.subList(foos.size()/2, foos.size()-1));
+ checkHashCode();
+
+ checkEquals();
+
} catch (Throwable t) { unexpected(t); }
System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
diff --git a/test/java/util/Currency/ValidateISO4217.java b/test/java/util/Currency/ValidateISO4217.java
index 568de12d4b..2d3eab1f04 100644
--- a/test/java/util/Currency/ValidateISO4217.java
+++ b/test/java/util/Currency/ValidateISO4217.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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,8 @@
/*
* @test
* @bug 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759
- * 8074350 8074351 8145952
+ * 8074350 8074351 8145952 8187946 8193552 8202026 8204269
+ * 8208746 8209775
* @summary Validate ISO 4217 data for Currency class.
*/
@@ -93,7 +94,11 @@ public class ValidateISO4217 {
/* Codes that are obsolete, do not have related country */
static final String otherCodes =
- "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LUF-MGF-MTL-MXV-MZM-NLG-PTE-ROL-RUR-SDD-SIT-SKK-SRG-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-YUM-ZMK-ZWD-ZWN-ZWR";
+ "ADP-AFA-ATS-AYM-AZM-BEF-BGL-BOV-BYB-BYR-CHE-CHW-CLF-COU-CUC-CYP-"
+ + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-"
+ + "PTE-ROL-RUR-SDD-SIT-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-"
+ + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-"
+ + "YUM-ZMK-ZWD-ZWN-ZWR";
static boolean err = false;
diff --git a/test/java/util/Currency/tablea1.txt b/test/java/util/Currency/tablea1.txt
index 10501b0d2e..706c94623b 100644
--- a/test/java/util/Currency/tablea1.txt
+++ b/test/java/util/Currency/tablea1.txt
@@ -1,12 +1,12 @@
#
#
-# Amendments up until ISO 4217 AMENDMENT NUMBER 162
-# (As of 30 Auguest 2016)
+# Amendments up until ISO 4217 AMENDMENT NUMBER 169
+# (As of 27 Aug 2018)
#
# Version
FILEVERSION=2
-DATAVERSION=162
+DATAVERSION=169
# ISO 4217 currency data
AF AFN 971 2
@@ -135,14 +135,14 @@ KR KRW 410 0
KW KWD 414 3
KG KGS 417 2
LA LAK 418 2
-LV LVL 428 2 2013-12-31-22-00-00 EUR 978 2
+LV EUR 978 2
LB LBP 422 2
#LS ZAR 710 2
LS LSL 426 2
LR LRD 430 2
LY LYD 434 3
LI CHF 756 2
-LT LTL 440 2 2014-12-31-22-00-00 EUR 978 2
+LT EUR 978 2
LU EUR 978 2
MO MOP 446 2
MK MKD 807 2
@@ -154,7 +154,7 @@ ML XOF 952 0
MT EUR 978 2
MH USD 840 2
MQ EUR 978 2
-MR MRO 478 2
+MR MRU 929 2
MU MUR 480 2
YT EUR 978 2
MX MXN 484 2
@@ -210,7 +210,7 @@ PM EUR 978 2
VC XCD 951 2
WS WST 882 2
SM EUR 978 2
-ST STD 678 2
+ST STN 930 2
SA SAR 682 2
SN XOF 952 0
# MA 134
@@ -268,7 +268,7 @@ UY UYU 858 2
#UY UYI 940 0
UZ UZS 860 2
VU VUV 548 0
-VE VEF 937 2
+VE VES 928 2
VN VND 704 0
VG USD 840 2
VI USD 840 2
diff --git a/test/java/util/Date/Bug4955000.java b/test/java/util/Date/Bug4955000.java
new file mode 100644
index 0000000000..c94b23868c
--- /dev/null
+++ b/test/java/util/Date/Bug4955000.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4955000
+ * @summary Make sure that a Date and a GregorianCalendar produce the
+ * same date/time. Both are new implementations in 1.5.
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+@SuppressWarnings("deprecation")
+public class Bug4955000 {
+ // Tests for Date.UTC(), derived from JCK
+ // Date.miscTests.Date1025 and Date2015
+ public static void main(String[] args) {
+ TimeZone defaultTZ = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("NST"));
+ GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ // Date1025
+ int[] years1 = {
+ Integer.MIN_VALUE,
+ Integer.MIN_VALUE + 1,
+ gc.getMinimum(YEAR) - 1,
+ gc.getMaximum(YEAR) + 1,
+ Integer.MAX_VALUE - 1,
+ Integer.MAX_VALUE
+ };
+ for (int i = 0; i < years1.length; i++) {
+ gc.clear();
+ gc.set(years1[i], gc.JANUARY, 1);
+ long t = gc.getTimeInMillis();
+ long utc = Date.UTC(years1[i] - 1900, 1-1, 1,
+ 0, 0, 0); // Jan 1 00:00:00
+ if (t != utc) {
+ throw new RuntimeException("t (" + t + ") != utc (" + utc +")");
+ }
+ }
+
+ // Date2015
+ int years[] = {
+ gc.getGreatestMinimum(YEAR),
+ gc.getGreatestMinimum(YEAR) + 1,
+ -1,
+ 0,
+ 1,
+ gc.getLeastMaximum(YEAR) - 1,
+ gc.getLeastMaximum(YEAR)
+ };
+
+ int months[] = {
+ gc.getMinimum(MONTH),
+ gc.getMinimum(MONTH) + 1,
+ gc.getMaximum(MONTH) - 1,
+ gc.getMaximum(MONTH)
+ };
+
+ int dates[] = {
+ gc.getMinimum(DAY_OF_MONTH),
+ gc.getMinimum(DAY_OF_MONTH) + 1,
+ gc.getMaximum(DAY_OF_MONTH) - 1,
+ gc.getMaximum(DAY_OF_MONTH)
+ };
+
+ int hs[] = {
+ gc.getMinimum(HOUR),
+ gc.getMinimum(HOUR) + 1,
+ gc.getMaximum(HOUR) - 1,
+ gc.getMaximum(HOUR)
+ };
+
+ int ms[] = {
+ gc.getMinimum(MINUTE),
+ gc.getMinimum(MINUTE) + 1,
+ gc.getMaximum(MINUTE) - 1,
+ gc.getMaximum(MINUTE)
+ };
+
+ int ss[] = {
+ gc.getMinimum(SECOND),
+ gc.getMinimum(SECOND) + 1,
+ gc.getMaximum(SECOND) - 1,
+ gc.getMaximum(SECOND)
+ };
+
+ for(int i = 0; i < years.length; i++) {
+ for(int j = 0; j < months.length; j++) {
+ for(int k = 0; k < dates.length; k++) {
+ for(int m = 0; m < hs.length; m++) {
+ for(int n = 0; n < ms.length; n++) {
+ for(int p = 0; p < ss.length; p++) {
+ int year = years[i] - 1900;
+ int month = months[j];
+ int date = dates[k];
+ int hours = hs[m];
+ int minutes = ms[n];
+ int seconds = ss[p];
+
+ long result = Date.UTC(year, month, date,
+ hours, minutes, seconds);
+
+ gc.clear();
+ gc.set(year + 1900, month, date, hours, minutes, seconds);
+
+ long expected = gc.getTime().getTime();
+
+ if (expected != result) {
+ throw new RuntimeException("expected (" + expected
+ + ") != result (" + result +")");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } finally {
+ TimeZone.setDefault(defaultTZ);
+ }
+ }
+}
diff --git a/test/java/util/Date/DateGregorianCalendarTest.java b/test/java/util/Date/DateGregorianCalendarTest.java
new file mode 100644
index 0000000000..49dbc8bc41
--- /dev/null
+++ b/test/java/util/Date/DateGregorianCalendarTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2003, 2016, 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 4614842
+ * @summary Make sure that a Date and a GregorianCalendar produce the same date/time. Both are new implementations in 1.5.
+ * @run main DateGregorianCalendarTest 15
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+// Usage: java DateGregorianCalendarTest [duration]
+
+@SuppressWarnings("deprecation")
+public class DateGregorianCalendarTest {
+ static volatile boolean runrun = true;
+ static int nThreads;
+
+ public static void main(String[] args) {
+ int duration = 600;
+ if (args.length == 1) {
+ duration = Math.max(10, Integer.parseInt(args[0]));
+ }
+
+ TimeZone savedTZ = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Thread[] t = new Thread[10]; // for future bugs...
+ int index = 0;
+ t[index++] = new Thread(new Runnable() {
+ public void run() {
+ GregorianCalendar gc = new GregorianCalendar();
+
+ long delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+ long count = 0;
+ try {
+ for (long t = Long.MIN_VALUE; runrun && t < Long.MAX_VALUE-delta; t += delta) {
+ gc.setTimeInMillis(t);
+ Date date = new Date(t);
+ int y;
+ if (!((y = gc.get(YEAR)) == (date.getYear()+1900) &&
+ gc.get(MONTH) == date.getMonth() &&
+ gc.get(DAY_OF_MONTH) == date.getDate() &&
+ gc.get(HOUR_OF_DAY) == date.getHours() &&
+ gc.get(MINUTE) == date.getMinutes() &&
+ gc.get(SECOND) == date.getSeconds())) {
+ throw new RuntimeException("GregorinCalendar and Date returned different dates."
+ +" (millis=" + t + ")\n"
+ +"GC=" + gc + "\nDate=" + date);
+ }
+ ++count;
+ if (y >= 1) {
+ delta = (long)(365.2422 * 24 * 60 * 60 * 1000);
+ }
+ if (y >= 1970) {
+ delta = (24 * 60 * 60 * 1000);
+ }
+ if (y >= 2039) {
+ delta = (long)(279 * 365.2422 * 24 * 60 * 60 * 1000);
+ }
+ }
+ if (runrun) {
+ System.out.println("Part I (count="+count+"): Passed");
+ } else {
+ System.out.println("Part I (count="+count+"): Incomplete");
+ }
+ } catch (RuntimeException e) {
+ System.out.println("Part I (count="+count+"): FAILED");
+ runrun = false;
+ throw e;
+ } finally {
+ decrementCounter();
+ }
+ }
+ });
+
+ t[index++] = new Thread(new Runnable() {
+ public void run() {
+ GregorianCalendar gc = new GregorianCalendar();
+
+ long count = 0;
+ int delta;
+ try {
+ for (long year = Integer.MIN_VALUE+1900;
+ runrun && year <= Integer.MAX_VALUE; year += delta) {
+ checkTimes(gc, year, JANUARY, 1, 0, 0, 0);
+ ++count;
+ delta = getDelta((int)year);
+ }
+
+ for (long month = Integer.MIN_VALUE;
+ runrun && month <= Integer.MAX_VALUE; month += delta) {
+ checkTimes(gc, 1900, month, 1, 0, 0, 0);
+ ++count;
+ delta = getDelta(gc.get(YEAR));
+ }
+
+ for (long dayOfMonth = Integer.MIN_VALUE;
+ runrun && dayOfMonth <= Integer.MAX_VALUE; dayOfMonth += delta) {
+ checkTimes(gc, 1900, JANUARY, dayOfMonth, 0, 0, 0);
+ ++count;
+ delta = getDelta(gc.get(YEAR));
+ }
+ if (runrun) {
+ System.out.println("Part II (count="+count+"): Passed");
+ } else {
+ System.out.println("Part II (count="+count+"): Incomplete");
+ }
+ } catch (RuntimeException e) {
+ System.out.println("Part II (count="+count+"): FAILED");
+ runrun = false;
+ throw e;
+ } finally {
+ decrementCounter();
+ }
+ }
+ });
+
+ // t3 takes more than 10 minutes (on Ultra-60 450MHz) without
+ // the 4936355 fix due to getting the small delta.
+ t[index++] = new Thread(new Runnable() {
+ public void run() {
+ GregorianCalendar gc = new GregorianCalendar();
+
+ long count = 0;
+ int delta;
+ try {
+ for (long hourOfDay = Integer.MIN_VALUE;
+ runrun && hourOfDay <= Integer.MAX_VALUE; hourOfDay += delta) {
+ checkTimes(gc, 1970, JANUARY, 1, hourOfDay, 0, 0);
+ ++count;
+ delta = getDelta(gc.get(YEAR));
+ }
+ for (long minutes = Integer.MIN_VALUE;
+ runrun && minutes <= Integer.MAX_VALUE; minutes += delta) {
+ checkTimes(gc, 1970, JANUARY, 1, 0, minutes, 0);
+ ++count;
+ delta = getDelta(gc.get(YEAR)) * 60;
+ }
+ for (long seconds = Integer.MIN_VALUE;
+ runrun && seconds <= Integer.MAX_VALUE; seconds += delta) {
+ checkTimes(gc, 1970, JANUARY, 1, 0, 0, seconds);
+ ++count;
+ delta = getDelta(gc.get(YEAR)) * 60 * 60;
+ }
+ if (runrun) {
+ System.out.println("Part III (count="+count+"): Passed");
+ } else {
+ System.out.println("Part III (count="+count+"): Incomplete");
+ }
+ } catch (RuntimeException e) {
+ System.out.println("Part III (count="+count+"): FAILED");
+ runrun = false;
+ throw e;
+ } finally {
+ decrementCounter();
+ }
+ }
+ });
+
+ for (int i = 0; i < index; i++) {
+ incrementCounter();
+ t[i].start();
+ }
+
+ try {
+ for (int i = 0; getCounter() > 0 && i < duration; i++) {
+ Thread.sleep(1000);
+ }
+ runrun = false;
+ for (int i = 0; i < index; i++) {
+ t[i].join();
+ }
+ } catch (InterruptedException e) {
+ }
+ } finally {
+ TimeZone.setDefault(savedTZ);
+ }
+ }
+
+ static void checkTimes(GregorianCalendar gc, long year, long month, long dayOfMonth,
+ long hourOfDay, long minutes, long seconds) {
+ gc.clear();
+ gc.set((int)year, (int)month, (int)dayOfMonth, (int)hourOfDay, (int)minutes, (int)seconds);
+ long time = gc.getTimeInMillis();
+ Date date = new Date((int)year - 1900, (int)month, (int)dayOfMonth,
+ (int)hourOfDay, (int)minutes, (int)seconds);
+ long time2 = date.getTime();
+ if (time != time2) {
+ throw new RuntimeException("GregorinCalendar and Date returned different values.\n"
+ +"year="+year+", month="+month+", dayOfMonth="+dayOfMonth
+ +"\nhourOfDay="+hourOfDay+", minutes="+minutes+", seconds="+seconds
+ +"\ntime=" + time + ", time2=" + time2
+ +"\nGC=" + gc + "\nDate=" + date);
+ }
+ }
+
+ static final int getDelta(int year) {
+ return (year >= 1970 && year <= 2039) ? 1 : 1<<13;
+ }
+
+ synchronized static void incrementCounter() {
+ nThreads++;
+ }
+
+ synchronized static void decrementCounter() {
+ nThreads--;
+ }
+
+ synchronized static int getCounter() {
+ return nThreads;
+ }
+}
diff --git a/test/java/util/Date/DateRegression.java b/test/java/util/Date/DateRegression.java
new file mode 100644
index 0000000000..70d8a5bf70
--- /dev/null
+++ b/test/java/util/Date/DateRegression.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4023247 4027685 4032037 4072029 4073003 4118010 4120606 4133833 4136916 6274757 6314387
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+
+@SuppressWarnings("deprecation")
+public class DateRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new DateRegression().run(args);
+ }
+
+ /**
+ * @bug 4023247
+ */
+ public void Test4023247() {
+ Date d1 = new Date(0);
+ Date d2 = new Date(0);
+
+ d1.setYear(96);
+ d1.setMonth(11);
+ d1.setDate(22);
+ d1.setHours(0);
+ d1.setMinutes(0);
+ d1.setSeconds(0);
+
+ d2.setYear(96);
+ d2.setMonth(11);
+ d2.setDate(22);
+ d2.setHours(0);
+ d2.setMinutes(0);
+ d2.setSeconds(0);
+
+ if (d1.hashCode() != d2.hashCode())
+ errln("Fail: Date hashCode misbehaves");
+ }
+
+ /**
+ * @bug 4027685
+ */
+ public void Test4027685() {
+ // Should be 01/16/97 00:00:00
+ Date nite = new Date("16-JAN-97 12:00 AM");
+ // Should be 01/16/97 12:00:00
+ Date noon = new Date("16-JAN-97 12:00 PM");
+
+ logln("Midnight = " + nite + ", Noon = " + noon);
+ if (!nite.equals(new Date(97, Calendar.JANUARY, 16, 0, 0)) ||
+ !noon.equals(new Date(97, Calendar.JANUARY, 16, 12, 0)))
+ errln("Fail: Nite/Noon confused");
+ }
+
+ /**
+ * @bug 4032037
+ */
+ public void Test4032037() {
+ Date ref = new Date(97, 1, 10);
+ Date d = new Date(Date.parse("2/10/97"));
+ logln("Date.parse(2/10/97) => " + d);
+ if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+ d = new Date(Date.parse("10 feb 1997"));
+ logln("Date.parse(10 feb 1997) => " + d);
+ if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+ d = new Date("2/10/97");
+ logln("Date(2/10/97) => " + d);
+ if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+ d = new Date("10 feb 1997");
+ logln("Date(10 feb 1997) => " + d);
+ if (!d.equals(ref)) errln("Fail: Want " + ref + " Got " + d);
+ }
+
+ /**
+ * @bug 4072029
+ */
+ public void Test4072029() {
+ TimeZone saveZone = TimeZone.getDefault();
+
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ Date now = new Date();
+ String s = now.toString();
+ Date now2 = new Date(now.toString());
+ String s2 = now2.toString(); // An hour's difference
+
+ if (!s.equals(s2) ||
+ Math.abs(now.getTime() - now2.getTime()) > 60000 /*one min*/) {
+ errln("Fail: Roundtrip toString/parse");
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ /**
+ * @bug 4073003
+ */
+ public void Test4073003() {
+ Date d = new Date(Date.parse("01/02/1984"));
+ if (!d.equals(new Date(84, 0, 2)))
+ errln("Fail: Want 1/2/1984 Got " + d);
+ d = new Date(Date.parse("02/03/2012"));
+ if (!d.equals(new Date(112, 1, 3)))
+ errln("Fail: Want 2/3/2012 Got " + d);
+ d = new Date(Date.parse("03/04/15"));
+ if (!d.equals(new Date(115, 2, 4)))
+ errln("Fail: Want 3/4/2015 Got " + d);
+ }
+
+ /**
+ * @bug 4118010
+ * Regress bug:
+ * Feb. 2000 has 29 days, but Date(2000, 1, 29) returns March 01, 2000
+ * NOTE: This turned out to be a user error (passing in 2000 instead
+ * of 2000-1900 to the Date constructor).
+ */
+ public void Test4118010() {
+ Date d=new java.util.Date(2000-1900, Calendar.FEBRUARY, 29);
+ int m=d.getMonth();
+ int date=d.getDate();
+ if (m != Calendar.FEBRUARY ||
+ date != 29)
+ errln("Fail: Want Feb 29, got " + d);
+ }
+
+ /**
+ * @bug 4120606
+ * Date objects share state after cloning.
+ */
+ public void Test4120606() {
+ Date d = new Date(98, Calendar.JUNE, 24);
+ d.setMonth(Calendar.MAY);
+ Date e = (Date)d.clone();
+ d.setMonth(Calendar.FEBRUARY);
+ if (e.getMonth() != Calendar.MAY) {
+ errln("Cloned Date objects share state");
+ }
+ }
+
+ /**
+ * @bug 4133833
+ * Date constructor crashes with parameters out of range, when it should
+ * normalize.
+ */
+ public void Test4133833() {
+ Date date = new java.util.Date(12,15,19);
+ Date exp = new Date(1913-1900, Calendar.APRIL, 19);
+ if (!date.equals(exp))
+ errln("Fail: Want " + exp +
+ "; got " + date);
+ }
+
+ /**
+ * @bug 4136916
+ * Date.toString() throws exception in 1.2b4-E
+ * CANNOT REPRODUCE this bug
+ */
+ public void Test4136916() {
+ Date time = new Date();
+ logln(time.toString());
+ }
+
+ /**
+ * @bug 6274757
+ * Date getTime and toString interaction for some time values
+ */
+ public void Test6274757() {
+ TimeZone savedTz = TimeZone.getDefault();
+ try {
+ // Use a time zone west of GMT.
+ TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
+ TimeZone jdkGMT = TimeZone.getTimeZone("GMT");
+ Calendar jdkCal = Calendar.getInstance(jdkGMT);
+ jdkCal.clear();
+ jdkCal.set(1582, Calendar.OCTOBER, 15);
+ logln("JDK time: " + jdkCal.getTime().getTime() );
+ logln("JDK time (str): " + jdkCal.getTime() );
+ logln("Day of month: " + jdkCal.get(Calendar.DAY_OF_MONTH));
+ Date co = jdkCal.getTime();
+ logln("Change over (Oct 15 1582) = " + co + " (" +
+ co.getTime() + ")");
+ long a = jdkCal.getTime().getTime();
+ Date c = jdkCal.getTime();
+ c.toString();
+ long b = c.getTime();
+
+ if (a != b) {
+ errln("ERROR: " + a + " != " + b);
+ } else {
+ logln(a + " = " + b);
+ }
+ } finally {
+ TimeZone.setDefault(savedTz);
+ }
+ }
+
+ /**
+ * @bug 6314387
+ * JCK6.0: api/java_util/Date/index.html#misc fails, mustang
+ */
+ public void Test6314387() {
+ Date d = new Date(Long.MAX_VALUE);
+ int y = d.getYear();
+ if (y != 292277094) {
+ errln("yesr: got " + y + ", expected 292277094");
+ }
+ d = new Date(Long.MIN_VALUE);
+ y = d.getYear();
+ if (y != 292267155) {
+ errln("yesr: got " + y + ", expected 292267155");
+ }
+ }
+}
+
+//eof
diff --git a/test/java/util/Date/DateTest.java b/test/java/util/Date/DateTest.java
new file mode 100644
index 0000000000..98392760ba
--- /dev/null
+++ b/test/java/util/Date/DateTest.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1997, 2016, 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 4143459
+ * @summary test Date
+ * @library /java/text/testlib
+ */
+
+import java.text.*;
+import java.util.*;
+
+@SuppressWarnings("deprecation")
+public class DateTest extends IntlTest
+{
+ public static void main(String[] args) throws Exception {
+ new DateTest().run(args);
+ }
+
+ /**
+ * @bug 4143459
+ * Warning: Use TestDefaultZone() for complete testing of this bug.
+ */
+ public void TestDefaultZoneLite() {
+ // Note: This test is redundant with TestDefaultZone(). It was added by
+ // request to provide a short&sweet test for this bug. It does not test
+ // all cases though, so IF THIS TEST PASSES, THE BUG MAY STILL BE
+ // PRESENT. Use TestDefaultZone() to be sure.
+ TimeZone save = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Date d = new Date();
+ d.setYear(98);
+ d.setMonth(Calendar.JANUARY);
+ d.setDate(1);
+ d.setHours(6);
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ if (d.getHours() != 22) {
+ errln("Fail: Date.setHours()/getHours() ignoring default zone");
+ }
+ }
+ finally { TimeZone.setDefault(save); }
+ }
+
+ /**
+ * @bug 4143459
+ */
+ public void TestDefaultZone() {
+ // Various problems can creep up, with the current implementation of Date,
+ // when the default zone is changed.
+
+ TimeZone saveZone = TimeZone.getDefault();
+ try {
+
+ Date d = new Date(); // Trigger static init
+ Date ref = new Date(883634400000L); // This is Thu Jan 1 1998 6:00 am GMT
+ String refstr = "Jan 1 1998 6:00";
+ TimeZone GMT = TimeZone.getTimeZone("GMT");
+ TimeZone PST = TimeZone.getTimeZone("PST");
+
+ String[] names = { "year", "month", "date", "day of week", "hour", "offset" };
+ int[] GMT_EXP = { 98, Calendar.JANUARY, 1, Calendar.THURSDAY - Calendar.SUNDAY, 6, 0 };
+ int[] PST_EXP = { 97, Calendar.DECEMBER, 31, Calendar.WEDNESDAY - Calendar.SUNDAY, 22, 480 };
+
+ // There are two cases to consider: a Date object with no Calendar
+ // sub-object (most Date objects), and a Date object with a Calendar
+ // sub-object. We make two passes to cover the two cases.
+ for (int pass=0; pass<2; ++pass) {
+ logln(pass == 0 ? "Normal Date object" : "Date with Calendar sub-object");
+
+ TimeZone.setDefault(GMT);
+ d = new Date(refstr);
+ if (pass == 1) {
+ // Force creation of Calendar sub-object
+ d.setYear(d.getYear());
+ }
+ if (d.getTime() != ref.getTime()) {
+ errln("FAIL: new Date(\"" + refstr + "\") x GMT -> " + d +
+ " " + d.getTime() + " ms");
+ }
+
+ int[] fields = { d.getYear(), d.getMonth(), d.getDate(),
+ d.getDay(), d.getHours(), d.getTimezoneOffset() };
+ for (int i=0; i<fields.length; ++i) {
+ if (fields[i] != GMT_EXP[i]) {
+ errln("FAIL: GMT Expected " + names[i] + " of " + GMT_EXP[i] +
+ ", got " + fields[i]);
+ }
+ }
+
+ TimeZone.setDefault(PST);
+ int[] fields2 = { d.getYear(), d.getMonth(), d.getDate(),
+ d.getDay(), d.getHours(), d.getTimezoneOffset() };
+ for (int i=0; i<fields2.length; ++i) {
+ if (fields2[i] != PST_EXP[i]) {
+ errln("FAIL: PST Expected " + names[i] + " of " + PST_EXP[i] +
+ ", got " + fields2[i]);
+ }
+ }
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveZone);
+ }
+ }
+
+ // Test the performance of Date
+ public void TestPerformance592()
+ {
+ int REPS = 500;
+
+ // Do timing test with Date
+ long start = new Date().getTime();
+ for (int i=0; i<REPS; ++i)
+ {
+ Date d = new Date();
+ int y = d.getYear();
+ }
+ long ms = new Date().getTime() - start;
+
+ double perLoop = ((double)ms) / REPS;
+ logln(REPS + " iterations at " + perLoop + " ms/loop");
+ if (perLoop > PER_LOOP_LIMIT)
+ logln("WARNING: Date constructor/getYear slower than " +
+ PER_LOOP_LIMIT + " ms");
+ }
+ static double PER_LOOP_LIMIT = 3.0;
+
+ /**
+ * Verify that the Date(String) constructor works.
+ */
+ public void TestParseOfGMT()
+ {
+ Date OUT = null;
+
+ /* Input values */
+ String stringVal = "Jan 01 00:00:00 GMT 1900";
+ long expectedVal = -2208988800000L;
+
+ OUT = new Date( stringVal );
+
+ if( OUT.getTime( ) == expectedVal ) {
+ // logln("PASS");
+ }
+ else {
+ errln( "Expected: " +
+ new Date( expectedVal ) +
+ ": " +
+ expectedVal +
+ " Received: " +
+ OUT.toString() +
+ ": " +
+ OUT.getTime() );
+ }
+ }
+
+ // Check out Date's behavior with large negative year values; bug 664
+ // As of the fix to bug 4056585, Date should work correctly with
+ // large negative years.
+ public void TestDateNegativeYears()
+ {
+ Date d1= new Date(80,-1,2);
+ logln(d1.toString());
+ d1= new Date(-80,-1,2);
+ logln(d1.toString());
+ boolean e = false;
+ try {
+ d1= new Date(-800000,-1,2);
+ logln(d1.toString());
+ }
+ catch (IllegalArgumentException ex) {
+ e = true;
+ }
+ if (e) errln("FAIL: Saw exception for year -800000");
+ else logln("Pass: No exception for year -800000");
+ }
+
+ // Verify the behavior of Date
+ public void TestDate480()
+ {
+ TimeZone save = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ Date d1=new java.util.Date(97,8,13,10,8,13);
+ logln("d = "+d1);
+ Date d2=new java.util.Date(97,8,13,30,8,13); // 20 hours later
+ logln("d+20h = "+d2);
+
+ double delta = (d2.getTime() - d1.getTime()) / 3600000;
+
+ logln("delta = " + delta + "h");
+
+ if (delta != 20.0) errln("Expected delta of 20; got " + delta);
+
+ Calendar cal = Calendar.getInstance();
+ cal.clear();
+ cal.set(1997,8,13,10,8,13);
+ Date t1 = cal.getTime();
+ logln("d = "+t1);
+ cal.clear();
+ cal.set(1997,8,13,30,8,13); // 20 hours later
+ Date t2 = cal.getTime();
+ logln("d+20h = "+t2);
+
+ double delta2 = (t2.getTime() - t1.getTime()) / 3600000;
+
+ logln("delta = " + delta2 + "h");
+
+ if (delta != 20.0) errln("Expected delta of 20; got " + delta2);
+ }
+ finally {
+ TimeZone.setDefault(save);
+ }
+ }
+}
diff --git a/test/java/util/Date/TZ.java b/test/java/util/Date/TZ.java
new file mode 100644
index 0000000000..56722a1cdb
--- /dev/null
+++ b/test/java/util/Date/TZ.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4108737
+ * @summary java.util.Date doesn't fail if current TimeZone is changed
+ */
+
+import java.util.TimeZone;
+import java.util.Date;
+
+public class TZ {
+
+ public static void main(String args[]) {
+ TimeZone tz = TimeZone.getDefault();
+ try {
+ testMain();
+ } finally {
+ TimeZone.setDefault(tz);
+ }
+ }
+
+ static void testMain() {
+ String expectedResult = "Sat Feb 01 00:00:00 PST 1997";
+
+ // load the java.util.Date class in the GMT timezone
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ new Date(); // load the class (to run static initializers)
+
+ // use the class in different timezone
+ TimeZone.setDefault(TimeZone.getTimeZone("PST"));
+ @SuppressWarnings("deprecation")
+ Date date = new Date(97, 1, 1);
+ if (!date.toString().equals(expectedResult)) {
+ throw new RuntimeException("Regression bug id #4108737 - Date fails if default time zone changed");
+ }
+ }
+}
diff --git a/test/java/util/Date/TimestampTest.java b/test/java/util/Date/TimestampTest.java
new file mode 100644
index 0000000000..950f0a5fb9
--- /dev/null
+++ b/test/java/util/Date/TimestampTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2004, 2016, 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 5008227
+ * @summary Make sure that changes to the Date class don't break java.sql.Timestamp.
+ * @modules java.sql
+ * @library /java/text/testlib
+ */
+
+import java.util.*;
+import java.sql.Timestamp;
+
+public class TimestampTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new TimestampTest().run(args);
+ }
+
+ /**
+ * 5008227: java.sql.Timestamp.after() is not returning correct result
+ *
+ * Test before(), after(), equals(), compareTo() and getTime().
+ */
+ public void Test5008227() {
+ long t = System.currentTimeMillis();
+ Timestamp ts1 = new Timestamp(t), ts2 = new Timestamp(t);
+ ts1.setNanos(999999999);
+ ts2.setNanos( 1000000);
+ compareTimestamps(ts1, ts2, 1);
+
+ ts1.setTime(t + 1000);
+ ts2.setTime(t);
+ ts1.setNanos( 999999);
+ ts2.setNanos(999999999);
+ compareTimestamps(ts1, ts2, 1);
+
+ ts1.setTime(t);
+ ts2.setTime(t);
+ ts1.setNanos(123456789);
+ ts2.setNanos(123456789);
+ compareTimestamps(ts1, ts2, 0);
+
+ ts1.setTime(t);
+ ts2.setTime(t);
+ ts1.setNanos(1);
+ ts2.setNanos(2);
+ compareTimestamps(ts1, ts2, -1);
+
+ ts1.setTime(t);
+ ts2.setTime(t+1000);
+ ts1.setNanos(999999);
+ ts2.setNanos( 0);
+ compareTimestamps(ts1, ts2, -1);
+ }
+
+ /**
+ * Compares two Timestamps with the expected result.
+ *
+ * @param ts1 the first Timestamp
+ * @param ts2 the second Timestamp
+ * @param expect the expected relation between ts1 and ts2; 0 if
+ * ts1 equals to ts2, or 1 if ts1 is after ts2, or -1 if ts1 is
+ * before ts2.
+ */
+ private void compareTimestamps(Timestamp ts1, Timestamp ts2, int expected) {
+ boolean expectedResult = expected > 0;
+ boolean result = ts1.after(ts2);
+ if (result != expectedResult) {
+ errln("ts1.after(ts2) returned " + result
+ + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+ }
+
+ expectedResult = expected < 0;
+ result = ts1.before(ts2);
+ if (result != expectedResult) {
+ errln("ts1.before(ts2) returned " + result
+ + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+ }
+
+ expectedResult = expected == 0;
+ result = ts1.equals(ts2);
+ if (result != expectedResult) {
+ errln("ts1.equals(ts2) returned " + result
+ + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+ }
+
+ int x = ts1.compareTo(ts2);
+ int y = (x > 0) ? 1 : (x < 0) ? -1 : 0;
+ if (y != expected) {
+ errln("ts1.compareTo(ts2) returned " + x + ", expected "
+ + relation(expected, "") + "0"
+ + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+ }
+ long t1 = ts1.getTime();
+ long t2 = ts2.getTime();
+ int z = (t1 > t2) ? 1 : (t1 < t2) ? -1 : 0;
+ if (z == 0) {
+ int n1 = ts1.getNanos();
+ int n2 = ts2.getNanos();
+ z = (n1 > n2) ? 1 : (n1 < n2) ? -1 : 0;
+ }
+ if (z != expected) {
+ errln("ts1.getTime() " + relation(z, "==") + " ts2.getTime(), expected "
+ + relation(expected, "==")
+ + ". (ts1=" + ts1 + ", ts2=" + ts2 + ")");
+ }
+ }
+
+ private static String relation(int x, String whenEqual) {
+ return (x > 0) ? ">" : (x < 0) ? "<" : whenEqual;
+ }
+}
diff --git a/test/java/util/Locale/Bug8040211.java b/test/java/util/Locale/Bug8040211.java
new file mode 100644
index 0000000000..4a7a099b2d
--- /dev/null
+++ b/test/java/util/Locale/Bug8040211.java
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2016, 2019, 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 8040211 8191404 8203872 8222980
+ * @summary Checks the IANA language subtag registry data update
+ * (LSR Revision: 2019-04-03) with Locale and Locale.LanguageRange
+ * class methods.
+ * @run main Bug8040211
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.List;
+import java.util.Locale.LanguageRange;
+import java.util.Locale.FilteringMode;
+import static java.util.Locale.FilteringMode.EXTENDED_FILTERING;
+
+public class Bug8040211 {
+
+ static boolean err = false;
+
+ public static void main(String[] args) {
+ testLanguageRange();
+ testLocale();
+
+ if (err) {
+ throw new RuntimeException("Failed.");
+ }
+ }
+
+ private static void testLanguageRange() {
+ System.out.println("Test LanguageRange class parse method...");
+ test_parse();
+ }
+
+ private static void testLocale() {
+ System.out.println("Test Locale class methods...");
+ test_filter();
+ test_filterTags();
+ test_lookup();
+ test_lookupTag();
+ }
+
+ private static void test_parse() {
+ boolean error = false;
+ String str = "Accept-Language: aam, adp, aue, bcg, cqu, ema,"
+ + " en-gb-oed, gti, kdz, koj, kwq, kxe, lii, lmm, mtm, ngv,"
+ + " oyb, phr, pub, suj, taj;q=0.9, ar-hyw;q=0.8, yug;q=0.5, gfx;q=0.4";
+ ArrayList<LanguageRange> expected = new ArrayList<>();
+ expected.add(new LanguageRange("aam", 1.0));
+ expected.add(new LanguageRange("aas", 1.0));
+ expected.add(new LanguageRange("adp", 1.0));
+ expected.add(new LanguageRange("dz", 1.0));
+ expected.add(new LanguageRange("aue", 1.0));
+ expected.add(new LanguageRange("ktz", 1.0));
+ expected.add(new LanguageRange("bcg", 1.0));
+ expected.add(new LanguageRange("bgm", 1.0));
+ expected.add(new LanguageRange("cqu", 1.0));
+ expected.add(new LanguageRange("quh", 1.0));
+ expected.add(new LanguageRange("ema", 1.0));
+ expected.add(new LanguageRange("uok", 1.0));
+ expected.add(new LanguageRange("en-gb-oed", 1.0));
+ expected.add(new LanguageRange("en-gb-oxendict", 1.0));
+ expected.add(new LanguageRange("gti", 1.0));
+ expected.add(new LanguageRange("nyc", 1.0));
+ expected.add(new LanguageRange("kdz", 1.0));
+ expected.add(new LanguageRange("ncp", 1.0));
+ expected.add(new LanguageRange("koj", 1.0));
+ expected.add(new LanguageRange("kwv", 1.0));
+ expected.add(new LanguageRange("kwq", 1.0));
+ expected.add(new LanguageRange("yam", 1.0));
+ expected.add(new LanguageRange("kxe", 1.0));
+ expected.add(new LanguageRange("tvd", 1.0));
+ expected.add(new LanguageRange("lii", 1.0));
+ expected.add(new LanguageRange("raq", 1.0));
+ expected.add(new LanguageRange("lmm", 1.0));
+ expected.add(new LanguageRange("rmx", 1.0));
+ expected.add(new LanguageRange("mtm", 1.0));
+ expected.add(new LanguageRange("ymt", 1.0));
+ expected.add(new LanguageRange("ngv", 1.0));
+ expected.add(new LanguageRange("nnx", 1.0));
+ expected.add(new LanguageRange("oyb", 1.0));
+ expected.add(new LanguageRange("thx", 1.0));
+ expected.add(new LanguageRange("skk", 1.0));
+ expected.add(new LanguageRange("jeg", 1.0));
+ expected.add(new LanguageRange("phr", 1.0));
+ expected.add(new LanguageRange("pmu", 1.0));
+ expected.add(new LanguageRange("pub", 1.0));
+ expected.add(new LanguageRange("puz", 1.0));
+ expected.add(new LanguageRange("suj", 1.0));
+ expected.add(new LanguageRange("xsj", 1.0));
+ expected.add(new LanguageRange("taj", 0.9));
+ expected.add(new LanguageRange("tsf", 0.9));
+ expected.add(new LanguageRange("ar-hyw", 0.8));
+ expected.add(new LanguageRange("yug", 0.5));
+ expected.add(new LanguageRange("yuu", 0.5));
+ expected.add(new LanguageRange("gfx", 0.4));
+ expected.add(new LanguageRange("oun", 0.4));
+ expected.add(new LanguageRange("mwj", 0.4));
+ expected.add(new LanguageRange("vaj", 0.4));
+ List<LanguageRange> got = LanguageRange.parse(str);
+ if (!areEqual(expected, got)) {
+ error = true;
+ System.err.println(" language parse() test failed.");
+ }
+
+ if (error) {
+ err = true;
+ System.err.println(" test_parse() failed.");
+ } else {
+ System.out.println(" test_parse() passed.");
+ }
+
+ }
+
+ private static boolean areEqual(List<LanguageRange> expected,
+ List<LanguageRange> got) {
+ boolean error = false;
+
+ int expectedSize = expected.size();
+ int actualSize = got.size();
+
+ if (expectedSize != actualSize) {
+ error = true;
+
+ System.err.println(" Expected size=" + expectedSize);
+ for (LanguageRange lr : expected) {
+ System.err.println(" range=" + lr.getRange()
+ + ", weight=" + lr.getWeight());
+ }
+
+ System.out.println(" Actual size=" + actualSize);
+ for (LanguageRange lr : got) {
+ System.err.println(" range=" + lr.getRange()
+ + ", weight=" + lr.getWeight());
+ }
+ } else {
+ for (int i = 0; i < expectedSize; i++) {
+ LanguageRange lr1 = expected.get(i);
+ LanguageRange lr2 = got.get(i);
+
+ if (!lr1.getRange().equals(lr2.getRange())
+ || lr1.getWeight() != lr2.getWeight()) {
+ error = true;
+ System.err.println(" " + i + ": Expected: range=" + lr1.getRange()
+ + ", weight=" + lr1.getWeight());
+ System.err.println(" " + i + ": Actual: range=" + lr2.getRange()
+ + ", weight=" + lr2.getWeight());
+ }
+ }
+ }
+
+ return !error;
+ }
+
+ private static void test_filter() {
+ boolean error = false;
+
+ String ranges = "mtm-RU, en-gb-oed, coy, ar-HY";
+ String tags = "de-DE, en, mtm-RU, ymt-RU, en-gb-oxendict, ja-JP, pij, nts, ar-arevela";
+ FilteringMode mode = EXTENDED_FILTERING;
+
+ List<LanguageRange> priorityList = LanguageRange.parse(ranges);
+ List<Locale> tagList = generateLocales(tags);
+ String actualLocales
+ = showLocales(Locale.filter(priorityList, tagList, mode));
+ String expectedLocales = "mtm-RU, ymt-RU, en-GB-oxendict, nts, pij";
+
+ if (!expectedLocales.equals(actualLocales)) {
+ error = true;
+ showErrorMessage("#1 filter(" + mode + ")",
+ ranges, tags, expectedLocales, actualLocales);
+ }
+
+ ranges = "phr-*-IN, ja-JP";
+ tags = "en, pmu-Guru-IN, ja-Latn-JP, iw";
+ mode = EXTENDED_FILTERING;
+
+ priorityList = LanguageRange.parse(ranges);
+ tagList = generateLocales(tags);
+ actualLocales = showLocales(Locale.filter(priorityList, tagList, mode));
+ expectedLocales = "pmu-Guru-IN, ja-Latn-JP";
+
+ if (!expectedLocales.equals(actualLocales)) {
+ error = true;
+ showErrorMessage("#2 filter(" + mode + ")",
+ ranges, tags, expectedLocales, actualLocales);
+ }
+
+ if (error) {
+ err = true;
+ System.out.println(" test_filter() failed.");
+ } else {
+ System.out.println(" test_filter() passed.");
+ }
+ }
+
+ private static void test_filterTags() {
+ boolean error = false;
+
+ String ranges = "gti;q=0.2, gfx, kzj";
+ String tags = "de-DE, gti, he, nyc, mwj, vaj, ktr, dtp";
+
+ List<LanguageRange> priorityList = LanguageRange.parse(ranges);
+ List<String> tagList = generateLanguageTags(tags);
+ String actualTags
+ = showLanguageTags(Locale.filterTags(priorityList, tagList));
+ String expectedTags = "mwj, vaj, ktr, dtp, gti, nyc";
+
+ if (!expectedTags.equals(actualTags)) {
+ error = true;
+ showErrorMessage("filterTags()",
+ ranges, tags, expectedTags, actualTags);
+ }
+
+ if (error) {
+ err = true;
+ System.out.println(" test_filterTags() failed.");
+ } else {
+ System.out.println(" test_filterTags() passed.");
+ }
+ }
+
+ private static void test_lookup() {
+ boolean error = false;
+
+ String ranges = "en;q=0.2, yam, rmx;q=0.9";
+ String tags = "de-DE, en, kwq, lmm";
+ List<LanguageRange> priorityList = LanguageRange.parse(ranges);
+ List<Locale> localeList = generateLocales(tags);
+ String actualLocale
+ = Locale.lookup(priorityList, localeList).toLanguageTag();
+ String expectedLocale = "kwq";
+
+ if (!expectedLocale.equals(actualLocale)) {
+ error = true;
+ showErrorMessage("lookup()", ranges, tags, expectedLocale, actualLocale);
+ }
+
+ if (error) {
+ err = true;
+ System.out.println(" test_lookup() failed.");
+ } else {
+ System.out.println(" test_lookup() passed.");
+ }
+ }
+
+ private static void test_lookupTag() {
+ boolean error = false;
+
+ String ranges = "en, tsf;q=0.2";
+ String tags = "es, ja-JP, taj";
+ List<LanguageRange> priorityList = LanguageRange.parse(ranges);
+ List<String> tagList = generateLanguageTags(tags);
+ String actualTag = Locale.lookupTag(priorityList, tagList);
+ String expectedTag = "taj";
+
+ if (!expectedTag.equals(actualTag)) {
+ error = true;
+ showErrorMessage("lookupTag()", ranges, tags, expectedTag, actualTag);
+ }
+
+ if (error) {
+ err = true;
+ System.out.println(" test_lookupTag() failed.");
+ } else {
+ System.out.println(" test_lookupTag() passed.");
+ }
+ }
+
+ private static List<Locale> generateLocales(String tags) {
+ if (tags == null) {
+ return null;
+ }
+
+ List<Locale> localeList = new ArrayList<>();
+ if (tags.equals("")) {
+ return localeList;
+ }
+ String[] t = tags.split(", ");
+ for (String tag : t) {
+ localeList.add(Locale.forLanguageTag(tag));
+ }
+ return localeList;
+ }
+
+ private static List<String> generateLanguageTags(String tags) {
+ List<String> tagList = new ArrayList<>();
+ String[] t = tags.split(", ");
+ for (String tag : t) {
+ tagList.add(tag);
+ }
+ return tagList;
+ }
+
+ private static String showLanguageTags(List<String> tags) {
+ StringBuilder sb = new StringBuilder();
+
+ Iterator<String> itr = tags.iterator();
+ if (itr.hasNext()) {
+ sb.append(itr.next());
+ }
+ while (itr.hasNext()) {
+ sb.append(", ");
+ sb.append(itr.next());
+ }
+
+ return sb.toString().trim();
+ }
+
+ private static String showLocales(List<Locale> locales) {
+ StringBuilder sb = new StringBuilder();
+
+ java.util.Iterator<Locale> itr = locales.iterator();
+ if (itr.hasNext()) {
+ sb.append(itr.next().toLanguageTag());
+ }
+ while (itr.hasNext()) {
+ sb.append(", ");
+ sb.append(itr.next().toLanguageTag());
+ }
+
+ return sb.toString().trim();
+ }
+
+ private static void showErrorMessage(String methodName,
+ String priorityList,
+ String tags,
+ String expectedTags,
+ String actualTags) {
+ System.out.println("\nIncorrect " + methodName + " result.");
+ System.out.println(" Priority list : " + priorityList);
+ System.out.println(" Language tags : " + tags);
+ System.out.println(" Expected value : " + expectedTags);
+ System.out.println(" Actual value : " + actualTags);
+ }
+
+}
+
diff --git a/test/java/util/Locale/tools/EquivMapsGenerator.java b/test/java/util/Locale/tools/EquivMapsGenerator.java
deleted file mode 100644
index 15e5fa9248..0000000000
--- a/test/java/util/Locale/tools/EquivMapsGenerator.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.io.*;
-import java.nio.charset.*;
-import java.nio.file.*;
-import java.util.*;
-
-public class EquivMapsGenerator {
-
- /*
- * IANA Language Subtag Registry file downloaded from
- * http://www.iana.org/assignments/language-subtag-registry
- */
- private static final String DEFAULT_LSR_FILE =
- "language-subtag-registry.txt";
-
- private static boolean verbose = false;
-
- public static void main(String[] args) throws Exception {
- String fileLSR = DEFAULT_LSR_FILE;
-
- for (int i = 0; i < args.length; i++) {
- String s = args[i];
- if (s.equals("-lsr")) {
- fileLSR = args[++i];
- } else if (s.equals("-verbose")) {
- verbose = true;
- }
- }
-
- readLSRfile(fileLSR);
- generateEquivalentMap();
- generateSourceCode();
- }
-
- private static String LSRrevisionDate;
- private static Map<String, StringBuilder> initialLanguageMap =
- new TreeMap<>();
- private static Map<String, StringBuilder> initialRegionVariantMap =
- new TreeMap<>();
-
- private static Map<String, String> sortedLanguageMap1 = new TreeMap<>();
- private static Map<String, String[]> sortedLanguageMap2 = new TreeMap<>();
- private static Map<String, String> sortedRegionVariantMap =
- new TreeMap<>();
-
- private static void readLSRfile(String filename) throws Exception {
- String type = null;
- String tag = null;
- String preferred = null;
- int mappingNum = 0;
-
- for (String line : Files.readAllLines(Paths.get(filename),
- Charset.forName("UTF-8"))) {
- line = line.toLowerCase();
- int index = line.indexOf(' ')+1;
- if (line.startsWith("file-date:")) {
- LSRrevisionDate = line.substring(index);
- if (verbose) {
- System.out.println("LSR revision date=" + LSRrevisionDate);
- }
- } else if (line.startsWith("type:")) {
- type = line.substring(index);
- } else if (line.startsWith("tag:") || line.startsWith("subtag:")) {
- tag = line.substring(index);
- } else if (line.startsWith("preferred-value:")
- && !type.equals("extlang")) {
- preferred = line.substring(index);
- mappingNum++;
- processDeprecatedData(type, tag, preferred);
- } else if (line.equals("%%")) {
- type = null;
- tag = null;
- preferred = null;
- }
- }
-
- if (verbose) {
- System.out.println("readLSRfile(" + filename + ")");
- System.out.println(" Total number of mapping=" + mappingNum);
- System.out.println("\n Map for language. Size="
- + initialLanguageMap.size());
-
- for (String key : initialLanguageMap.keySet()) {
- System.out.println(" " + key + ": \""
- + initialLanguageMap.get(key) + "\"");
- }
-
- System.out.println("\n Map for region and variant. Size="
- + initialRegionVariantMap.size());
-
- for (String key : initialRegionVariantMap.keySet()) {
- System.out.println(" " + key + ": \""
- + initialRegionVariantMap.get(key) + "\"");
- }
- }
- }
-
- private static void processDeprecatedData(String type,
- String tag,
- String preferred) {
- StringBuilder sb;
- if (type.equals("region") || type.equals("variant")) {
- if (!initialRegionVariantMap.containsKey(preferred)) {
- sb = new StringBuilder("-");
- sb.append(preferred);
- sb.append(",-");
- sb.append(tag);
- initialRegionVariantMap.put("-"+preferred, sb);
- } else {
- throw new RuntimeException("New case, need implementation."
- + " A region/variant subtag \"" + preferred
- + "\" is registered for more than one subtags.");
- }
- } else { // language, grandfahered, and redundant
- if (!initialLanguageMap.containsKey(preferred)) {
- sb = new StringBuilder(preferred);
- sb.append(',');
- sb.append(tag);
- initialLanguageMap.put(preferred, sb);
- } else {
- sb = initialLanguageMap.get(preferred);
- sb.append(',');
- sb.append(tag);
- initialLanguageMap.put(preferred, sb);
- }
- }
- }
-
- private static void generateEquivalentMap() {
- String[] subtags;
- for (String preferred : initialLanguageMap.keySet()) {
- subtags = initialLanguageMap.get(preferred).toString().split(",");
-
- if (subtags.length == 2) {
- sortedLanguageMap1.put(subtags[0], subtags[1]);
- sortedLanguageMap1.put(subtags[1], subtags[0]);
- } else if (subtags.length == 3) {
- sortedLanguageMap2.put(subtags[0],
- new String[]{subtags[1], subtags[2]});
- sortedLanguageMap2.put(subtags[1],
- new String[]{subtags[0], subtags[2]});
- sortedLanguageMap2.put(subtags[2],
- new String[]{subtags[0], subtags[1]});
- } else {
- throw new RuntimeException("New case, need implementation."
- + " A language subtag \"" + preferred
- + "\" is registered for more than two subtags. ");
- }
- }
-
- for (String preferred : initialRegionVariantMap.keySet()) {
- subtags =
- initialRegionVariantMap.get(preferred).toString().split(",");
-
- sortedRegionVariantMap.put(subtags[0], subtags[1]);
- sortedRegionVariantMap.put(subtags[1], subtags[0]);
- }
-
- if (verbose) {
- System.out.println("generateEquivalentMap()");
- System.out.println(" \nSorted map for language subtags which have only one equivalent. Size="
- + sortedLanguageMap1.size());
- for (String key : sortedLanguageMap1.keySet()) {
- System.out.println(" " + key + ": \""
- + sortedLanguageMap1.get(key) + "\"");
- }
-
- System.out.println("\n Sorted map for language subtags which have multiple equivalents. Size="
- + sortedLanguageMap2.size());
- for (String key : sortedLanguageMap2.keySet()) {
- String[] s = sortedLanguageMap2.get(key);
- System.out.println(" " + key + ": \""
- + s[0] + "\", \"" + s[1] + "\"");
- }
-
- System.out.println("\n Sorted map for region and variant subtags. Size="
- + sortedRegionVariantMap.size());
- for (String key : sortedRegionVariantMap.keySet()) {
- System.out.println(" " + key + ": \""
- + sortedRegionVariantMap.get(key) + "\"");
- }
- }
- System.out.println();
- }
-
- private final static String headerText =
- "final class LocaleEquivalentMaps {\n\n"
- + " static final Map<String, String> singleEquivMap;\n"
- + " static final Map<String, String[]> multiEquivsMap;\n"
- + " static final Map<String, String> regionVariantEquivMap;\n\n"
- + " static {\n"
- + " singleEquivMap = new HashMap<>();\n"
- + " multiEquivsMap = new HashMap<>();\n"
- + " regionVariantEquivMap = new HashMap<>();\n\n"
- + " // This is an auto-generated file and should not be manually edited.\n";
-
- private final static String footerText =
- " }\n\n"
- + "}";
-
- private static void generateSourceCode() {
- System.out.println(headerText
- + " // LSR Revision: " + LSRrevisionDate);
-
- for (String key : sortedLanguageMap1.keySet()) {
- String value = sortedLanguageMap1.get(key);
- System.out.println(" singleEquivMap.put(\""
- + key + "\", \"" + value + "\");");
- }
- System.out.println();
- for (String key : sortedLanguageMap2.keySet()) {
- String[] values = sortedLanguageMap2.get(key);
- System.out.println(" multiEquivsMap.put(\""
- + key + "\", new String[] {\"" + values[0] + "\", \""
- + values[1] + "\"});");
- }
- System.out.println();
- for (String key : sortedRegionVariantMap.keySet()) {
- String value = sortedRegionVariantMap.get(key);
- System.out.println(" regionVariantEquivMap.put(\""
- + key + "\", \"" + value + "\");");
- }
-
- System.out.println(footerText);
- }
-
-}
diff --git a/test/java/util/Objects/CheckIndex.java b/test/java/util/Objects/CheckIndex.java
new file mode 100644
index 0000000000..bb11386139
--- /dev/null
+++ b/test/java/util/Objects/CheckIndex.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2015, 2016 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
+ * @summary com.sun.crypto.provider.Preconditions.checkIndex tests
+ * @run testng CheckIndex
+ * @bug 8135248 8142493 8155794
+ */
+
+import com.sun.crypto.provider.Preconditions;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.IntSupplier;
+
+import static org.testng.Assert.*;
+
+public class CheckIndex {
+
+ static class AssertingOutOfBoundsException extends RuntimeException {
+ public AssertingOutOfBoundsException(String message) {
+ super(message);
+ }
+ }
+
+ static BiFunction<String, List<Integer>, AssertingOutOfBoundsException> assertingOutOfBounds(
+ String message, String expCheckKind, Integer... expArgs) {
+ return (checkKind, args) -> {
+ assertEquals(checkKind, expCheckKind);
+ assertEquals(args, Collections.unmodifiableList(Arrays.asList(expArgs)));
+ try {
+ args.clear();
+ fail("Out of bounds List<Integer> argument should be unmodifiable");
+ } catch (Exception e) {
+ }
+ return new AssertingOutOfBoundsException(message);
+ };
+ }
+
+ static BiFunction<String, List<Integer>, AssertingOutOfBoundsException> assertingOutOfBoundsReturnNull(
+ String expCheckKind, Integer... expArgs) {
+ return (checkKind, args) -> {
+ assertEquals(checkKind, expCheckKind);
+ assertEquals(args, Collections.unmodifiableList(Arrays.asList(expArgs)));
+ return null;
+ };
+ }
+
+ static final int[] VALUES = {0, 1, Integer.MAX_VALUE - 1, Integer.MAX_VALUE, -1, Integer.MIN_VALUE + 1, Integer.MIN_VALUE};
+
+ @DataProvider
+ static Object[][] checkIndexProvider() {
+ List<Object[]> l = new ArrayList<>();
+ for (int index : VALUES) {
+ for (int length : VALUES) {
+ boolean withinBounds = index >= 0 &&
+ length >= 0 &&
+ index < length;
+ l.add(new Object[]{index, length, withinBounds});
+ }
+ }
+ return l.toArray(new Object[0][0]);
+ }
+
+ interface X {
+ int apply(int a, int b, int c);
+ }
+
+ @Test(dataProvider = "checkIndexProvider")
+ public void testCheckIndex(int index, int length, boolean withinBounds) {
+ List<Integer> list = Collections.unmodifiableList(Arrays.asList(new Integer[] { index, length }));
+ String expectedMessage = withinBounds
+ ? null
+ : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+ apply("checkIndex", list).getMessage();
+
+ BiConsumer<Class<? extends RuntimeException>, IntSupplier> checker = (ec, s) -> {
+ try {
+ int rIndex = s.getAsInt();
+ if (!withinBounds)
+ fail(String.format(
+ "Index %d is out of bounds of [0, %d), but was reported to be within bounds", index, length));
+ assertEquals(rIndex, index);
+ }
+ catch (RuntimeException e) {
+ assertTrue(ec.isInstance(e));
+ if (withinBounds)
+ fail(String.format(
+ "Index %d is within bounds of [0, %d), but was reported to be out of bounds", index, length));
+ else
+ assertEquals(e.getMessage(), expectedMessage);
+ }
+ };
+
+ checker.accept(AssertingOutOfBoundsException.class,
+ () -> Preconditions.checkIndex(index, length,
+ assertingOutOfBounds(expectedMessage, "checkIndex", index, length)));
+ checker.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkIndex(index, length,
+ assertingOutOfBoundsReturnNull("checkIndex", index, length)));
+ checker.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkIndex(index, length, null));
+ checker.accept(ArrayIndexOutOfBoundsException.class,
+ () -> Preconditions.checkIndex(index, length,
+ Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+ checker.accept(StringIndexOutOfBoundsException.class,
+ () -> Preconditions.checkIndex(index, length,
+ Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+ }
+
+
+ @DataProvider
+ static Object[][] checkFromToIndexProvider() {
+ List<Object[]> l = new ArrayList<>();
+ for (int fromIndex : VALUES) {
+ for (int toIndex : VALUES) {
+ for (int length : VALUES) {
+ boolean withinBounds = fromIndex >= 0 &&
+ toIndex >= 0 &&
+ length >= 0 &&
+ fromIndex <= toIndex &&
+ toIndex <= length;
+ l.add(new Object[]{fromIndex, toIndex, length, withinBounds});
+ }
+ }
+ }
+ return l.toArray(new Object[0][0]);
+ }
+
+ @Test(dataProvider = "checkFromToIndexProvider")
+ public void testCheckFromToIndex(int fromIndex, int toIndex, int length, boolean withinBounds) {
+ List<Integer> list = Collections.unmodifiableList(Arrays.asList(new Integer[] { fromIndex, toIndex, length }));
+ String expectedMessage = withinBounds
+ ? null
+ : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+ apply("checkFromToIndex", list).getMessage();
+
+ BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
+ try {
+ int rIndex = s.getAsInt();
+ if (!withinBounds)
+ fail(String.format(
+ "Range [%d, %d) is out of bounds of [0, %d), but was reported to be withing bounds", fromIndex, toIndex, length));
+ assertEquals(rIndex, fromIndex);
+ }
+ catch (RuntimeException e) {
+ assertTrue(ec.isInstance(e));
+ if (withinBounds)
+ fail(String.format(
+ "Range [%d, %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, toIndex, length));
+ else
+ assertEquals(e.getMessage(), expectedMessage);
+ }
+ };
+
+ check.accept(AssertingOutOfBoundsException.class,
+ () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+ assertingOutOfBounds(expectedMessage, "checkFromToIndex", fromIndex, toIndex, length)));
+ check.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+ assertingOutOfBoundsReturnNull("checkFromToIndex", fromIndex, toIndex, length)));
+ check.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length, null));
+ check.accept(ArrayIndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+ Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+ check.accept(StringIndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromToIndex(fromIndex, toIndex, length,
+ Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+ }
+
+
+ @DataProvider
+ static Object[][] checkFromIndexSizeProvider() {
+ List<Object[]> l = new ArrayList<>();
+ for (int fromIndex : VALUES) {
+ for (int size : VALUES) {
+ for (int length : VALUES) {
+ // Explicitly convert to long
+ long lFromIndex = fromIndex;
+ long lSize = size;
+ long lLength = length;
+ // Avoid overflow
+ long lToIndex = lFromIndex + lSize;
+
+ boolean withinBounds = lFromIndex >= 0L &&
+ lSize >= 0L &&
+ lLength >= 0L &&
+ lFromIndex <= lToIndex &&
+ lToIndex <= lLength;
+ l.add(new Object[]{fromIndex, size, length, withinBounds});
+ }
+ }
+ }
+ return l.toArray(new Object[0][0]);
+ }
+
+ @Test(dataProvider = "checkFromIndexSizeProvider")
+ public void testCheckFromIndexSize(int fromIndex, int size, int length, boolean withinBounds) {
+ List<Integer> list = Collections.unmodifiableList(Arrays.asList(new Integer[] { fromIndex, size, length }));
+ String expectedMessage = withinBounds
+ ? null
+ : Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new).
+ apply("checkFromIndexSize", list).getMessage();
+
+ BiConsumer<Class<? extends RuntimeException>, IntSupplier> check = (ec, s) -> {
+ try {
+ int rIndex = s.getAsInt();
+ if (!withinBounds)
+ fail(String.format(
+ "Range [%d, %d + %d) is out of bounds of [0, %d), but was reported to be withing bounds", fromIndex, fromIndex, size, length));
+ assertEquals(rIndex, fromIndex);
+ }
+ catch (RuntimeException e) {
+ assertTrue(ec.isInstance(e));
+ if (withinBounds)
+ fail(String.format(
+ "Range [%d, %d + %d) is within bounds of [0, %d), but was reported to be out of bounds", fromIndex, fromIndex, size, length));
+ else
+ assertEquals(e.getMessage(), expectedMessage);
+ }
+ };
+
+ check.accept(AssertingOutOfBoundsException.class,
+ () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+ assertingOutOfBounds(expectedMessage, "checkFromIndexSize", fromIndex, size, length)));
+ check.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+ assertingOutOfBoundsReturnNull("checkFromIndexSize", fromIndex, size, length)));
+ check.accept(IndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromIndexSize(fromIndex, size, length, null));
+ check.accept(ArrayIndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+ Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new)));
+ check.accept(StringIndexOutOfBoundsException.class,
+ () -> Preconditions.checkFromIndexSize(fromIndex, size, length,
+ Preconditions.outOfBoundsExceptionFormatter(StringIndexOutOfBoundsException::new)));
+ }
+
+ @Test
+ public void uniqueMessagesForCheckKinds() {
+ BiFunction<String, List<Integer>, IndexOutOfBoundsException> f =
+ Preconditions.outOfBoundsExceptionFormatter(IndexOutOfBoundsException::new);
+
+ List<String> messages = new ArrayList<>();
+ List<Integer> arg1 = Collections.unmodifiableList(Arrays.asList(new Integer[] { -1 }));
+ List<Integer> arg2 = Collections.unmodifiableList(Arrays.asList(new Integer[] { -1, 0 }));
+ List<Integer> arg3 = Collections.unmodifiableList(Arrays.asList(new Integer[] { -1, 0, 0 }));
+ List<Integer> arg4 = Collections.unmodifiableList(Arrays.asList(new Integer[] { -1, 0, 0, 0 }));
+ // Exact arguments
+ messages.add(f.apply("checkIndex", arg2).getMessage());
+ messages.add(f.apply("checkFromToIndex", arg3).getMessage());
+ messages.add(f.apply("checkFromIndexSize", arg3).getMessage());
+ // Unknown check kind
+ messages.add(f.apply("checkUnknown", arg3).getMessage());
+ // Known check kind with more arguments
+ messages.add(f.apply("checkIndex", arg3).getMessage());
+ messages.add(f.apply("checkFromToIndex", arg4).getMessage());
+ messages.add(f.apply("checkFromIndexSize", arg4).getMessage());
+ // Known check kind with fewer arguments
+ messages.add(f.apply("checkIndex", arg1).getMessage());
+ messages.add(f.apply("checkFromToIndex", arg2).getMessage());
+ messages.add(f.apply("checkFromIndexSize", arg2).getMessage());
+ // Null arguments
+ messages.add(f.apply(null, null).getMessage());
+ messages.add(f.apply("checkNullArguments", null).getMessage());
+ messages.add(f.apply(null, arg1).getMessage());
+
+ assertEquals(messages.size(), messages.stream().distinct().count());
+ }
+}
diff --git a/test/java/util/TimeZone/Bug4322313.java b/test/java/util/TimeZone/Bug4322313.java
new file mode 100644
index 0000000000..fdd1f7c92c
--- /dev/null
+++ b/test/java/util/TimeZone/Bug4322313.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4322313
+ * @summary Make sure that new implementation of custom time zone
+ * support for TimeZone.getTimeZone() works correctly and the
+ * getDisplayName() methods are locale independent.
+ * @library /java/text/testlib
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+
+public class Bug4322313 extends IntlTest {
+ private static final int MPM = 60 * 1000; /* Milliseconds per minute */
+ private static final Object[][] VALIDS = {
+ /* given ID rawOffset normalized ID */
+ {"GMT+00:00", 0, "GMT+00:00"},
+ {"GMT+3:04", 184 * MPM, "GMT+03:04"},
+ {"GMT+03:04", 184 * MPM, "GMT+03:04"},
+ {"GMT+13:42", 822 * MPM, "GMT+13:42"},
+ /* ISO-LATIN-1 digits */
+ {"GMT+\u0030\u0031:\u0032\u0033", 83 * MPM, "GMT+01:23"},
+
+ {"GMT+0", 0, "GMT+00:00"},
+ {"GMT+3", 180 * MPM, "GMT+03:00"},
+ {"GMT+13", 780 * MPM, "GMT+13:00"},
+ {"GMT+034", 34 * MPM, "GMT+00:34"},
+ {"GMT+1034", 634 * MPM, "GMT+10:34"},
+
+ {"GMT-00:00", 0, "GMT-00:00"},
+ {"GMT-3:04", -184 * MPM, "GMT-03:04"},
+ {"GMT-03:04", -184 * MPM, "GMT-03:04"},
+ {"GMT-13:42", -822 * MPM, "GMT-13:42"},
+ /* ISO-LATIN-1 digits */
+ {"GMT-\u0030\u0031:\u0032\u0033", -83 * MPM, "GMT-01:23"},
+
+ {"GMT-0", 0, "GMT-00:00"},
+ {"GMT-3", -180 * MPM, "GMT-03:00"},
+ {"GMT-13", -780 * MPM, "GMT-13:00"},
+ {"GMT-034", -34 * MPM, "GMT-00:34"},
+ {"GMT-1034", -634 * MPM, "GMT-10:34"},
+ };
+
+ private static final String[] INVALIDS = {
+ "GMT+5:8", "GMT+11:1", "GMT+23:60", "GMT+24:13",
+ "GMT+0a:0A", "GMT +13:42", "GMT+ 13:42", "GMT+13 :42",
+ "GMT+13: 42", "GMT+421:950", "GMT+-13:42", "GMT+!13:42",
+ "GMT+a", "GMT+24", "GMT+060", "GMT+3003",
+ "GMT+42195", "GMT+-1", "GMT+-15", " GMT",
+
+ "GMT-5:8", "GMT-11:1", "GMT-23:60", "GMT-24:13",
+ "GMT-0a:0A", "GMT -13:42", "GMT- 13:42", "GMT-13 :42",
+ "GMT-13: 42", "GMT-421:950", "GMT-+13:42", "GMT-#13:42",
+ "GMT-a", "GMT-24", "GMT-060", "GMT-2403",
+ "GMT-42195", "GMT-+1", "GMT-+15", "G M T",
+ "GMT+09:00 ",
+ };
+
+ void Test4322313() {
+ Locale savedLocale = Locale.getDefault();
+ TimeZone savedTimeZone = TimeZone.getDefault();
+ boolean err = false;
+
+ Locale[] locs = Locale.getAvailableLocales();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+ for (int i = 0; i < locs.length; i++) {
+ Locale.setDefault(locs[i]);
+
+ /* Okay case */
+ for (int k = 0; k < VALIDS.length; k++) {
+ TimeZone tz = TimeZone.getTimeZone((String)VALIDS[k][0]);
+ int offset;
+
+ if (!tz.getID().equals(VALIDS[k][2])) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] Invalid TimeZone ID, expected:" +
+ VALIDS[k][2] + ", got:" + tz.getID() + ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] Valid TimeZone ID, got:" + VALIDS[k][2]);
+ }
+
+ offset = tz.getRawOffset();
+ if (offset != (int)VALIDS[k][1]) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] Invalid RawOffset, expected:" + VALIDS[k][1] +
+ ", got:" + offset + ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] Vaild RawOffset, got:" + offset);
+ }
+
+ offset = tz.getDSTSavings();
+ if (offset != 0) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] DSTSavings should be zero, got:" + offset +
+ ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + VALIDS[k][0] +
+ "\"] DSTSavings is zero.");
+ }
+ }
+
+ /* Error case */
+ for (int k=0; k < INVALIDS.length; k++) {
+ TimeZone tz = TimeZone.getTimeZone(INVALIDS[k]);
+ int offset;
+
+ if (!tz.getID().equals("GMT")) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] Invalid TimeZone ID, expected:GMT, got:" +
+ tz.getID() + ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] Valid TimeZone ID, got:" + tz.getID());
+ }
+
+ offset = tz.getRawOffset();
+ if (offset != 0) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] RawOffset should be zero, got:" + offset +
+ ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] RawOffset is zero.");
+ }
+
+ offset = tz.getDSTSavings();
+ if (offset != 0) {
+ err = true;
+ System.err.println("\tFailed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] DSTSavings should be zero, got:" + offset +
+ ", " + tz);
+ } else {
+ logln("\tPassed [Locale=" +
+ Locale.getDefault() + ", \"" + INVALIDS[k] +
+ "\"] DSTSavings is zero.");
+ }
+ }
+
+ // getDisplayName() tests
+ {
+ String normalizedID = "GMT-08:00";
+ TimeZone tz = TimeZone.getTimeZone("GMT-8");
+ String s;
+ s = tz.getDisplayName(true, tz.LONG);
+ if (!normalizedID.equals(s)) {
+ err = true;
+ System.err.println("getDisplayName returned unexpected name: " + s +
+ " in " + Locale.getDefault());
+ }
+ s = tz.getDisplayName(true, tz.SHORT);
+ if (!normalizedID.equals(s)) {
+ err = true;
+ System.err.println("getDisplayName returned unexpected name: " + s +
+ " in " + Locale.getDefault());
+ }
+ s = tz.getDisplayName(false, tz.LONG);
+ if (!normalizedID.equals(s)) {
+ err = true;
+ System.err.println("getDisplayName returned unexpected name: " + s +
+ " in " + Locale.getDefault());
+ }
+ s = tz.getDisplayName(false, tz.SHORT);
+ if (!normalizedID.equals(s)) {
+ err = true;
+ System.err.println("getDisplayName returned unexpected name: " + s +
+ " in " + Locale.getDefault());
+ }
+ }
+ }
+ } finally {
+ Locale.setDefault(savedLocale);
+ TimeZone.setDefault(savedTimeZone);
+ }
+ if (err) {
+ errln("TimeZone.getTimeZone() test failed");
+ } else {
+ logln("TimeZone.getTimeZone() test passed");
+ }
+ }
+
+ public static void main (String[] args) throws Exception {
+ new Bug4322313().run(args);
+ }
+}
diff --git a/test/java/util/TimeZone/Bug5097350.java b/test/java/util/TimeZone/Bug5097350.java
new file mode 100644
index 0000000000..ff0894bf3d
--- /dev/null
+++ b/test/java/util/TimeZone/Bug5097350.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2004, 2016, 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 5097350
+ * @summary Make sure that TimeZone.getTimeZone returns a clone of a cached TimeZone instance.
+ */
+
+import java.util.*;
+import java.text.*;
+
+public class Bug5097350 {
+ public static void main(String[] args) {
+ String[] tzids = TimeZone.getAvailableIDs();
+ List<String> ids = new ArrayList<>(tzids.length + 10);
+ ids.addAll(Arrays.asList(tzids));
+ // add some custom ids
+ ids.add("GMT+1");
+ ids.add("GMT-7:00");
+ ids.add("GMT+10:20");
+ ids.add("GMT-00:00");
+ ids.add("GMT+00:00");
+
+ for (String id : ids) {
+ test(id);
+ }
+ }
+
+ private static void test(String id) {
+ TimeZone tz1 = TimeZone.getTimeZone(id);
+ int offset1 = tz1.getRawOffset();
+ tz1.setRawOffset(offset1 + 13 * 60 * 60 * 1000);
+
+ TimeZone tz2 = TimeZone.getTimeZone(id);
+ if (tz1 == tz2) {
+ throw new RuntimeException("TimeZones are identical: " + id);
+ }
+ if (offset1 != tz2.getRawOffset()) {
+ throw new RuntimeException("Offset changed through aliasing: " + id);
+ }
+ }
+}
diff --git a/test/java/util/TimeZone/DefaultTimeZoneTest.html b/test/java/util/TimeZone/DefaultTimeZoneTest.html
new file mode 100644
index 0000000000..1fa0659ed6
--- /dev/null
+++ b/test/java/util/TimeZone/DefaultTimeZoneTest.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!--
+ Copyright (c) 2005, 2016, 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.
+-->
+<!---->
+<html>
+ <head>
+ <title>Disable Auto-adjust Daylight Saving Time Test</title>
+ </head>
+
+ <body>
+This applet tests the platform time zone detection on all platforms (Part I)
+and on/off of DST adjustment on Windows (Part II).
+
+Part I:
+
+Observe the displayed Time zone ID and the local time. If you can change
+the platform time zone setting, try several time zones. If both the ID and
+the local time, including the time zone name and its time zone offset, are
+always correct, Part I passes. Note that some time zone IDs have their
+aliases that may be displayed. For example, "US/Pacific" is an alias of
+"America/Los_Angeles".
+
+If you are running this applet in non-English locale, the time zone names
+can be displayed in the local language and English by pushing the
+English/Local button.
+
+If platform time zones are NOT detected correctly, press the Fail button
+to finish this applet.
+
+If this platform is Windows, proceed to Part II. Otherwise, press the Pass
+button to finish this applet.
+
+Part II:
+
+Note that Part II may require the Administrator privilege to change
+Windows setting.
+
+ 1. Open the Date and Time control panel.
+ 2. Select any time zone where daylight saving time is *currently* in effect,
+ such as "(GMT-08:00) Pacific Time (US & Canada); Tijuana",
+ "(GMT+10:00) Canberra, Melbourne, Sydney", and Apply.
+ 3. Observe the local time on the control panel (Date&Time pane) and
+ the applet local time should be the same (daylight time).
+ 4. Clear "Automatically adjust clock for daylight saving changes" and Apply.
+ 5. Observe the two local times should be the same (standard time).
+ 6. Select "Automatically adjust clock for daylight saving changes" and Apply.
+
+If the local time in the control panel and applet are always the same,
+then this test passes. Press the Pass or Fail button based on the Part II
+result and finish this applet.
+
+<applet code="DefaultTimeZoneTest.class" width=500 height=90></applet>
+ </body>
+</html>
diff --git a/test/java/util/TimeZone/DefaultTimeZoneTest.java b/test/java/util/TimeZone/DefaultTimeZoneTest.java
new file mode 100644
index 0000000000..a6d3ac5086
--- /dev/null
+++ b/test/java/util/TimeZone/DefaultTimeZoneTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2005, 2016, 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 4296930 5033603 7092679
+ * @summary Make sure that Java runtime detects the platform time zone
+ * correctly. Also make sure that the system time zone detection code
+ * detects the "Automatically adjust clock for daylight saving
+ * changes" setting correctly on Windows.
+ * @run applet/manual=yesno DefaultTimeZoneTest.html
+ */
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.text.*;
+import java.util.*;
+
+public class DefaultTimeZoneTest extends JApplet implements Runnable {
+ static final String FORMAT = "yyyy-MM-dd HH:mm:ss zzzz (XXX)";
+ JLabel tzid;
+ JLabel label;
+ SimpleDateFormat sdf = new SimpleDateFormat(FORMAT);
+ JButton button = new JButton("English");
+ Thread clock;
+ boolean english = false;
+
+ @Override
+ public void init() {
+ tzid = new JLabel("Time zone ID: " + sdf.getTimeZone().getID(), SwingConstants.CENTER);
+ tzid.setAlignmentX(Component.CENTER_ALIGNMENT);
+ label = new JLabel(sdf.format(new Date()), SwingConstants.CENTER);
+ label.setAlignmentX(Component.CENTER_ALIGNMENT);
+ button.addActionListener(new ActionListener() {
+ @Override
+ @SuppressWarnings("deprecation")
+ public void actionPerformed(ActionEvent e) {
+ english = (english == false);
+ Locale loc = english ? Locale.US : Locale.getDefault();
+ sdf = new SimpleDateFormat(FORMAT, loc);
+ button.setLabel(!english ? "English" : "Local");
+ }
+ });
+ button.setAlignmentX(Component.CENTER_ALIGNMENT);
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
+ panel.add(Box.createRigidArea(new Dimension(0, 10)));
+ panel.add(tzid);
+ panel.add(Box.createRigidArea(new Dimension(0, 5)));
+ panel.add(label);
+ panel.add(Box.createRigidArea(new Dimension(0, 10)));
+ panel.add(button);
+ getContentPane().add(panel);
+ }
+
+ @Override
+ public void start() {
+ clock = new Thread(this);
+ clock.start();
+ }
+
+ @Override
+ public void stop() {
+ clock = null;
+ }
+
+ @Override
+ public void run() {
+ Thread me = Thread.currentThread();
+
+ while (clock == me) {
+ // Reset the default time zone so that
+ // TimeZone.getDefault will detect the platform time zone
+ TimeZone.setDefault(null);
+ System.setProperty("user.timezone", "");
+ TimeZone tz = TimeZone.getDefault();
+ sdf.setTimeZone(tz);
+ tzid.setText("Time zone ID: " + tz.getID());
+ label.setText(sdf.format(new Date()));
+ repaint();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+}
diff --git a/test/java/util/TimeZone/HongKong.java b/test/java/util/TimeZone/HongKong.java
new file mode 100644
index 0000000000..ef9c3f923f
--- /dev/null
+++ b/test/java/util/TimeZone/HongKong.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001, 2016, 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 4487276 8008577
+ * @summary Verify that Hong Kong locale uses traditional Chinese names.
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI HongKong
+ */
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class HongKong {
+ public static void main(String[] args) {
+ Locale reservedLocale = Locale.getDefault();
+ try {
+ Locale.setDefault(new Locale("zh", "HK"));
+ checkCountry(Locale.GERMANY, "\u5fb7\u570b");
+ checkCountry(Locale.FRANCE, "\u6cd5\u570b");
+ checkCountry(Locale.ITALY, "\u7fa9\u5927\u5229");
+ checkTimeZone("Asia/Shanghai",
+ "\u4e2d\u570b\u6a19\u6e96\u6642\u9593");
+ } finally {
+ // restore the reserved locale
+ Locale.setDefault(reservedLocale);
+ }
+ }
+
+ private static void checkCountry(Locale country, String expected) {
+ String actual = country.getDisplayCountry();
+ if (!expected.equals(actual)) {
+ throw new RuntimeException();
+ }
+ }
+
+ private static void checkTimeZone(String timeZoneID, String expected) {
+ TimeZone timeZone = TimeZone.getTimeZone(timeZoneID);
+ String actual = timeZone.getDisplayName();
+ if (!expected.equals(actual)) {
+ throw new RuntimeException();
+ }
+ }
+}
diff --git a/test/java/util/TimeZone/IDTest.java b/test/java/util/TimeZone/IDTest.java
new file mode 100644
index 0000000000..d5396b619b
--- /dev/null
+++ b/test/java/util/TimeZone/IDTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4509255 5055567 6176318 7090844
+ * @summary Tests consistencies of time zone IDs.
+ */
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.TreeMap;
+
+public class IDTest {
+ public static void main(String[] args) {
+ Set<String> ids = new HashSet<>();
+ Map<Integer, Set<String>> tree = new TreeMap<>();
+
+ String[] tzs = TimeZone.getAvailableIDs();
+ String[] tzs2 = TimeZone.getAvailableIDs();
+ if (tzs.length != tzs2.length) {
+ throw new RuntimeException("tzs.length(" + tzs.length
+ + ") != tzs2.length(" + tzs2.length + ")");
+ }
+ for (int i = 0; i < tzs.length; i++) {
+ if (tzs[i] != tzs2[i]) {
+ throw new RuntimeException(i + ": " + tzs[i] + " != " + tzs2[i]);
+ }
+ }
+
+ System.out.println("Total: " + tzs.length + " time zone IDs");
+ for (String id : tzs) {
+ ids.add(id);
+ TimeZone tz = TimeZone.getTimeZone(id);
+ Integer offset = tz.getRawOffset();
+ Set<String> s = tree.get(offset);
+ if (s == null) {
+ s = new HashSet<>();
+ tree.put(offset, s);
+ }
+ s.add(id);
+ }
+
+ for (Integer key : tree.keySet()) {
+ Set<String> s1 = tree.get(key);
+
+ // Make sure no duplicates in the other sets
+ for (Integer k : tree.keySet()) {
+ if (k.equals(key)) {
+ continue;
+ }
+ Set<String> s2 = new HashSet<>(tree.get(k));
+ s2.retainAll(s1);
+ if (!s2.isEmpty()) {
+ throw new RuntimeException("s1 included in the subset for " + (k.intValue()/60000) +
+ " (" + s2 + " shouldn't be in s1)");
+ }
+ }
+
+ // Check the getAvailableIDs(int) call to return the same
+ // set of IDs
+ int offset = key.intValue();
+ tzs = TimeZone.getAvailableIDs(offset);
+ tzs2 = TimeZone.getAvailableIDs(offset);
+ if (!Arrays.equals(tzs, tzs2)) {
+ throw new RuntimeException("inconsistent tzs from getAvailableIDs("+offset+")");
+ }
+ Set<String> s2 = new HashSet<>();
+ s2.addAll(Arrays.asList(tzs));
+ if (!s1.equals(s2)) {
+ throw new RuntimeException("s1 != s2 for " + offset/60000 +
+ " (diff=" + getDiff(s1, s2) + ")");
+ }
+ if (!ids.containsAll(s2)) {
+ throw new RuntimeException("s2 isn't a subset of ids (" + getDiff(s2, ids) +
+ " not in ids)");
+ }
+ }
+
+ for (Integer key : tree.keySet()) {
+ Set<String> s1 = tree.get(key);
+ ids.removeAll(s1);
+ }
+ if (!ids.isEmpty()) {
+ throw new RuntimeException("ids didn't become empty. (" + ids + ")");
+ }
+ }
+
+ private static String getDiff(Set<String> set1, Set<String> set2) {
+ Set<String> s1 = new HashSet<>(set1);
+ s1.removeAll(set2);
+
+ Set<String> s2 = new HashSet<>(set2);
+ s2.removeAll(set1);
+ s2.addAll(s1);
+ return s2.toString();
+ }
+}
diff --git a/test/java/util/TimeZone/TimeZoneBoundaryTest.java b/test/java/util/TimeZone/TimeZoneBoundaryTest.java
new file mode 100644
index 0000000000..a1d44ea080
--- /dev/null
+++ b/test/java/util/TimeZone/TimeZoneBoundaryTest.java
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1997, 2016, 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
+ * @library /java/text/testlib
+ * @summary test Time Zone Boundary
+ */
+
+import java.text.*;
+import java.util.*;
+
+/**
+ * A test which discovers the boundaries of DST programmatically and verifies
+ * that they are correct.
+ */
+public class TimeZoneBoundaryTest extends IntlTest
+{
+ static final int ONE_SECOND = 1000;
+ static final int ONE_MINUTE = 60*ONE_SECOND;
+ static final int ONE_HOUR = 60*ONE_MINUTE;
+ static final long ONE_DAY = 24*ONE_HOUR;
+ static final long ONE_YEAR = (long)(365.25 * ONE_DAY);
+ static final long SIX_MONTHS = ONE_YEAR / 2;
+
+ static final int MONTH_LENGTH[] = {31,29,31,30,31,30,31,31,30,31,30,31};
+
+ // These values are empirically determined to be correct
+ static final long PST_1997_BEG = 860320800000L;
+ static final long PST_1997_END = 877856400000L;
+
+ // Minimum interval for binary searches in ms; should be no larger
+ // than 1000.
+ static final long INTERVAL = 10; // Milliseconds
+
+ static final String AUSTRALIA = "Australia/Adelaide";
+ static final long AUSTRALIA_1997_BEG = 877797000000L;
+ static final long AUSTRALIA_1997_END = 859653000000L;
+
+ public static void main(String[] args) throws Exception {
+ new TimeZoneBoundaryTest().run(args);
+ }
+
+ /**
+ * Date.toString().substring() Boundary Test
+ * Look for a DST changeover to occur within 6 months of the given Date.
+ * The initial Date.toString() should yield a string containing the
+ * startMode as a SUBSTRING. The boundary will be tested to be
+ * at the expectedBoundary value.
+ */
+ void findDaylightBoundaryUsingDate(Date d, String startMode, long expectedBoundary)
+ {
+ // Given a date with a year start, find the Daylight onset
+ // and end. The given date should be 1/1/xx in some year.
+
+ if (d.toString().indexOf(startMode) == -1)
+ {
+ logln("Error: " + startMode + " not present in " + d);
+ }
+
+ // Use a binary search, assuming that we have a Standard
+ // time at the midpoint.
+ long min = d.getTime();
+ long max = min + SIX_MONTHS;
+
+ while ((max - min) > INTERVAL)
+ {
+ long mid = (min + max) >> 1;
+ String s = new Date(mid).toString();
+ // logln(s);
+ if (s.indexOf(startMode) != -1)
+ {
+ min = mid;
+ }
+ else
+ {
+ max = mid;
+ }
+ }
+
+ logln("Date Before: " + showDate(min));
+ logln("Date After: " + showDate(max));
+ long mindelta = expectedBoundary - min;
+ long maxdelta = max - expectedBoundary;
+ if (mindelta >= 0 && mindelta <= INTERVAL &&
+ mindelta >= 0 && mindelta <= INTERVAL)
+ logln("PASS: Expected boundary at " + expectedBoundary);
+ else
+ errln("FAIL: Expected boundary at " + expectedBoundary);
+ }
+
+ void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST, long expectedBoundary)
+ {
+ findDaylightBoundaryUsingTimeZone(d, startsInDST, expectedBoundary,
+ TimeZone.getDefault());
+ }
+
+ void findDaylightBoundaryUsingTimeZone(Date d, boolean startsInDST,
+ long expectedBoundary, TimeZone tz)
+ {
+ // Given a date with a year start, find the Daylight onset
+ // and end. The given date should be 1/1/xx in some year.
+
+ // Use a binary search, assuming that we have a Standard
+ // time at the midpoint.
+ long min = d.getTime();
+ long max = min + SIX_MONTHS;
+
+ if (tz.inDaylightTime(d) != startsInDST)
+ {
+ errln("FAIL: " + tz.getID() + " inDaylightTime(" +
+ d + ") != " + startsInDST);
+ startsInDST = !startsInDST; // Flip over; find the apparent value
+ }
+
+ if (tz.inDaylightTime(new Date(max)) == startsInDST)
+ {
+ errln("FAIL: " + tz.getID() + " inDaylightTime(" +
+ (new Date(max)) + ") != " + (!startsInDST));
+ return;
+ }
+
+ while ((max - min) > INTERVAL)
+ {
+ long mid = (min + max) >> 1;
+ boolean isIn = tz.inDaylightTime(new Date(mid));
+ if (isIn == startsInDST)
+ {
+ min = mid;
+ }
+ else
+ {
+ max = mid;
+ }
+ }
+
+ logln(tz.getID() + " Before: " + showDate(min, tz));
+ logln(tz.getID() + " After: " + showDate(max, tz));
+
+ long mindelta = expectedBoundary - min;
+ long maxdelta = max - expectedBoundary;
+ if (mindelta >= 0 && mindelta <= INTERVAL &&
+ mindelta >= 0 && mindelta <= INTERVAL)
+ logln("PASS: Expected boundary at " + expectedBoundary);
+ else
+ errln("FAIL: Expected boundary at " + expectedBoundary);
+ }
+
+ private static String showDate(long l)
+ {
+ return showDate(new Date(l));
+ }
+
+ @SuppressWarnings("deprecation")
+ private static String showDate(Date d)
+ {
+ return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) +
+ " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) +
+ " \"" + d + "\" = " +
+ d.getTime();
+ }
+
+ private static String showDate(long l, TimeZone z)
+ {
+ return showDate(new Date(l), z);
+ }
+
+ @SuppressWarnings("deprecation")
+ private static String showDate(Date d, TimeZone zone)
+ {
+ DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
+ fmt.setTimeZone(zone);
+ return "" + d.getYear() + "/" + showNN(d.getMonth()+1) + "/" + showNN(d.getDate()) +
+ " " + showNN(d.getHours()) + ":" + showNN(d.getMinutes()) +
+ " \"" + d + "\" = " +
+ fmt.format(d);
+ }
+
+ private static String showNN(int n)
+ {
+ return ((n < 10) ? "0" : "") + n;
+ }
+
+ /**
+ * Given a date, a TimeZone, and expected values for inDaylightTime,
+ * useDaylightTime, zone and DST offset, verify that this is the case.
+ */
+ void verifyDST(Date d, TimeZone time_zone,
+ boolean expUseDaylightTime, boolean expInDaylightTime,
+ int expZoneOffset, int expDSTOffset)
+ {
+ logln("-- Verifying time " + d +
+ " in zone " + time_zone.getID());
+
+ if (time_zone.inDaylightTime(d) == expInDaylightTime)
+ logln("PASS: inDaylightTime = " + time_zone.inDaylightTime(d));
+ else
+ errln("FAIL: inDaylightTime = " + time_zone.inDaylightTime(d));
+
+ if (time_zone.useDaylightTime() == expUseDaylightTime)
+ logln("PASS: useDaylightTime = " + time_zone.useDaylightTime());
+ else
+ errln("FAIL: useDaylightTime = " + time_zone.useDaylightTime());
+
+ if (time_zone.getRawOffset() == expZoneOffset)
+ logln("PASS: getRawOffset() = " + expZoneOffset/(double)ONE_HOUR);
+ else
+ errln("FAIL: getRawOffset() = " + time_zone.getRawOffset()/(double)ONE_HOUR +
+ "; expected " + expZoneOffset/(double)ONE_HOUR);
+
+ GregorianCalendar gc = new GregorianCalendar(time_zone);
+ gc.setTime(d);
+ int offset = time_zone.getOffset(gc.get(gc.ERA), gc.get(gc.YEAR), gc.get(gc.MONTH),
+ gc.get(gc.DAY_OF_MONTH), gc.get(gc.DAY_OF_WEEK),
+ ((gc.get(gc.HOUR_OF_DAY) * 60 +
+ gc.get(gc.MINUTE)) * 60 +
+ gc.get(gc.SECOND)) * 1000 +
+ gc.get(gc.MILLISECOND));
+ if (offset == expDSTOffset)
+ logln("PASS: getOffset() = " + offset/(double)ONE_HOUR);
+ else
+ errln("FAIL: getOffset() = " + offset/(double)ONE_HOUR +
+ "; expected " + expDSTOffset/(double)ONE_HOUR);
+ }
+
+ @SuppressWarnings("deprecation")
+ public void TestBoundaries()
+ {
+ TimeZone pst = TimeZone.getTimeZone("PST");
+ TimeZone save = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(pst);
+
+ // DST changeover for PST is 4/6/1997 at 2 hours past midnight
+ Date d = new Date(97,Calendar.APRIL,6);
+
+ // i is minutes past midnight standard time
+ for (int i=60; i<=180; i+=15)
+ {
+ boolean inDST = (i >= 120);
+ Date e = new Date(d.getTime() + i*60*1000);
+ verifyDST(e, pst, true, inDST, -8*ONE_HOUR,
+ inDST ? -7*ONE_HOUR : -8*ONE_HOUR);
+ }
+
+ logln("========================================");
+ findDaylightBoundaryUsingDate(new Date(97,0,1), "PST", PST_1997_BEG);
+ logln("========================================");
+ findDaylightBoundaryUsingDate(new Date(97,6,1), "PDT", PST_1997_END);
+
+ // Southern hemisphere test
+ logln("========================================");
+ TimeZone z = TimeZone.getTimeZone(AUSTRALIA);
+ findDaylightBoundaryUsingTimeZone(new Date(97,0,1), true, AUSTRALIA_1997_END, z);
+
+ logln("========================================");
+ findDaylightBoundaryUsingTimeZone(new Date(97,0,1), false, PST_1997_BEG);
+ logln("========================================");
+ findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true, PST_1997_END);
+ } finally {
+ TimeZone.setDefault(save);
+ }
+ }
+
+ void testUsingBinarySearch(SimpleTimeZone tz, Date d, long expectedBoundary)
+ {
+ // Given a date with a year start, find the Daylight onset
+ // and end. The given date should be 1/1/xx in some year.
+
+ // Use a binary search, assuming that we have a Standard
+ // time at the midpoint.
+ long min = d.getTime();
+ long max = min + (long)(365.25 / 2 * ONE_DAY);
+
+ // First check the boundaries
+ boolean startsInDST = tz.inDaylightTime(d);
+
+ if (tz.inDaylightTime(new Date(max)) == startsInDST)
+ {
+ logln("Error: inDaylightTime(" + (new Date(max)) + ") != " + (!startsInDST));
+ }
+
+ while ((max - min) > INTERVAL)
+ {
+ long mid = (min + max) >> 1;
+ if (tz.inDaylightTime(new Date(mid)) == startsInDST)
+ {
+ min = mid;
+ }
+ else
+ {
+ max = mid;
+ }
+ }
+
+ logln("Binary Search Before: " + showDate(min));
+ logln("Binary Search After: " + showDate(max));
+
+ long mindelta = expectedBoundary - min;
+ long maxdelta = max - expectedBoundary;
+ if (mindelta >= 0 && mindelta <= INTERVAL &&
+ mindelta >= 0 && mindelta <= INTERVAL)
+ logln("PASS: Expected boundary at " + expectedBoundary);
+ else
+ errln("FAIL: Expected boundary at " + expectedBoundary);
+ }
+
+ /*
+ static void testUsingMillis(Date d, boolean startsInDST)
+ {
+ long millis = d.getTime();
+ long max = millis + (long)(370 * ONE_DAY); // A year plus extra
+
+ boolean lastDST = startsInDST;
+ while (millis < max)
+ {
+ cal.setTime(new Date(millis));
+ boolean inDaylight = cal.inDaylightTime();
+
+ if (inDaylight != lastDST)
+ {
+ logln("Switch " + (inDaylight ? "into" : "out of")
+ + " DST at " + (new Date(millis)));
+ lastDST = inDaylight;
+ }
+
+ millis += 15*ONE_MINUTE;
+ }
+ }
+ */
+
+ /**
+ * Test new rule formats.
+ */
+ @SuppressWarnings("deprecation")
+ public void TestNewRules()
+ {
+ //logln(Locale.getDefault().getDisplayName());
+ //logln(TimeZone.getDefault().getID());
+ //logln(new Date(0));
+
+ if (true)
+ {
+ // Doesn't matter what the default TimeZone is here, since we
+ // are creating our own TimeZone objects.
+
+ SimpleTimeZone tz;
+
+ logln("-----------------------------------------------------------------");
+ logln("Aug 2ndTues .. Mar 15");
+ tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_1",
+ Calendar.AUGUST, 2, Calendar.TUESDAY, 2*ONE_HOUR,
+ Calendar.MARCH, 15, 0, 2*ONE_HOUR);
+ //logln(tz.toString());
+ logln("========================================");
+ testUsingBinarySearch(tz, new Date(97,0,1), 858416400000L);
+ logln("========================================");
+ testUsingBinarySearch(tz, new Date(97,6,1), 871380000000L);
+
+ logln("-----------------------------------------------------------------");
+ logln("Apr Wed>=14 .. Sep Sun<=20");
+ tz = new SimpleTimeZone(-8*ONE_HOUR, "Test_2",
+ Calendar.APRIL, 14, -Calendar.WEDNESDAY, 2*ONE_HOUR,
+ Calendar.SEPTEMBER, -20, -Calendar.SUNDAY, 2*ONE_HOUR);
+ //logln(tz.toString());
+ logln("========================================");
+ testUsingBinarySearch(tz, new Date(97,0,1), 861184800000L);
+ logln("========================================");
+ testUsingBinarySearch(tz, new Date(97,6,1), 874227600000L);
+ }
+
+ /*
+ if (true)
+ {
+ logln("========================================");
+ logln("Stepping using millis");
+ testUsingMillis(new Date(97,0,1), false);
+ }
+
+ if (true)
+ {
+ logln("========================================");
+ logln("Stepping using fields");
+ testUsingFields(1997, false);
+ }
+
+ if (false)
+ {
+ cal.clear();
+ cal.set(1997, 3, 5, 10, 0);
+ // cal.inDaylightTime();
+ logln("Date = " + cal.getTime());
+ logln("Millis = " + cal.getTime().getTime()/3600000);
+ }
+ */
+ }
+
+ //----------------------------------------------------------------------
+ //----------------------------------------------------------------------
+ //----------------------------------------------------------------------
+ // Long Bug
+ //----------------------------------------------------------------------
+ //----------------------------------------------------------------------
+ //----------------------------------------------------------------------
+
+ //public void Test3()
+ //{
+ // findDaylightBoundaryUsingTimeZone(new Date(97,6,1), true);
+ //}
+
+ /**
+ * Find boundaries by stepping.
+ */
+ @SuppressWarnings("deprecation")
+ void findBoundariesStepwise(int year, long interval, TimeZone z, int expectedChanges)
+ {
+ Date d = new Date(year - 1900, Calendar.JANUARY, 1);
+ long time = d.getTime(); // ms
+ long limit = time + ONE_YEAR + ONE_DAY;
+ boolean lastState = z.inDaylightTime(d);
+ int changes = 0;
+ logln("-- Zone " + z.getID() + " starts in " + year + " with DST = " + lastState);
+ logln("useDaylightTime = " + z.useDaylightTime());
+ while (time < limit)
+ {
+ d.setTime(time);
+ boolean state = z.inDaylightTime(d);
+ if (state != lastState)
+ {
+ logln((state ? "Entry " : "Exit ") +
+ "at " + d);
+ lastState = state;
+ ++changes;
+ }
+ time += interval;
+ }
+ if (changes == 0)
+ {
+ if (!lastState && !z.useDaylightTime()) logln("No DST");
+ else errln("FAIL: Timezone<" + z.getID() + "> DST all year, or no DST with true useDaylightTime");
+ }
+ else if (changes != 2)
+ {
+ errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; should see 0 or 2");
+ }
+ else if (!z.useDaylightTime())
+ {
+ errln("FAIL: Timezone<" + z.getID() + "> useDaylightTime false but 2 changes seen");
+ }
+ if (changes != expectedChanges)
+ {
+ errln("FAIL: Timezone<" + z.getID() + "> " + changes + " changes seen; expected " + expectedChanges);
+ }
+ }
+
+ public void TestStepwise()
+ {
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("ACT"), 0);
+ // "EST" is disabled because its behavior depends on the mapping property. (6466476).
+ //findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("EST"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("HST"), 0);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("PST8PDT"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST"), 0);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("SystemV/PST8PDT"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Japan"), 0);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("Europe/Paris"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone("America/Los_Angeles"), 2);
+ findBoundariesStepwise(1997, ONE_DAY, TimeZone.getTimeZone(AUSTRALIA), 2);
+ }
+}
diff --git a/test/java/util/TimeZone/TimeZoneRegression.java b/test/java/util/TimeZone/TimeZoneRegression.java
new file mode 100644
index 0000000000..8b9e2f4a22
--- /dev/null
+++ b/test/java/util/TimeZone/TimeZoneRegression.java
@@ -0,0 +1,995 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429
+ * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960
+ * 4966229 6433179 6851214 8007520 8008577
+ * @library /java/text/testlib
+ * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression
+ */
+
+import java.util.*;
+import java.io.*;
+import java.text.*;
+
+public class TimeZoneRegression extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new TimeZoneRegression().run(args);
+ }
+
+ public void Test4052967() {
+ logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");
+ String id = TimeZone.getDefault().getID();
+ logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));
+ logln("TimeZone.getDefault().getID(): " + id);
+ logln(new Date().toString());
+ logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
+ }
+
+ public void Test4073209() {
+ TimeZone z1 = TimeZone.getTimeZone("PST");
+ TimeZone z2 = TimeZone.getTimeZone("PST");
+ if (z1 == z2) {
+ errln("Fail: TimeZone should return clones");
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void Test4073215() {
+ SimpleTimeZone z = new SimpleTimeZone(0, "GMT");
+ if (z.useDaylightTime()) {
+ errln("Fail: Fix test to start with non-DST zone");
+ }
+ z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);
+ z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);
+ if (!z.useDaylightTime()) {
+ errln("Fail: DST not active");
+ }
+ if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) ||
+ !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) ||
+ z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) {
+ errln("Fail: DST not working as expected");
+ }
+ }
+
+ /**
+ * The expected behavior of TimeZone around the boundaries is:
+ * (Assume transition time of 2:00 AM)
+ * day of onset 1:59 AM STD = display name 1:59 AM ST
+ * 2:00 AM STD = display name 3:00 AM DT
+ * day of end 0:59 AM STD = display name 1:59 AM DT
+ * 1:00 AM STD = display name 1:00 AM ST
+ */
+ public void Test4084933() {
+ // test both SimpleTimeZone and ZoneInfo objects.
+ // @since 1.4
+ sub4084933(getPST());
+ sub4084933(TimeZone.getTimeZone("PST"));
+ }
+
+ private void sub4084933(TimeZone tz) {
+ long offset1 = tz.getOffset(1,
+ 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));
+ long offset2 = tz.getOffset(1,
+ 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);
+
+ long offset3 = tz.getOffset(1,
+ 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));
+ long offset4 = tz.getOffset(1,
+ 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);
+
+ /*
+ * The following was added just for consistency. It shows that going *to* Daylight
+ * Savings Time (PDT) does work at 2am.
+ */
+
+ long offset5 = tz.getOffset(1,
+ 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));
+ long offset6 = tz.getOffset(1,
+ 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);
+
+ long offset7 = tz.getOffset(1,
+ 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));
+ long offset8 = tz.getOffset(1,
+ 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);
+
+ long SToffset = -8 * 60*60*1000L;
+ long DToffset = -7 * 60*60*1000L;
+ if (offset1 != SToffset || offset2 != SToffset ||
+ offset3 != SToffset || offset4 != DToffset ||
+ offset5 != DToffset || offset6 != SToffset ||
+ offset7 != SToffset || offset8 != SToffset)
+ errln("Fail: TimeZone misbehaving"); {
+ }
+ }
+
+ public void Test4096952() {
+ String[] ZONES = { "GMT", "MET", "IST" };
+ boolean pass = true;
+ try {
+ for (int i=0; i<ZONES.length; ++i) {
+ TimeZone zone = TimeZone.getTimeZone(ZONES[i]);
+ if (!zone.getID().equals(ZONES[i]))
+ errln("Fail: Test broken; zones not instantiating");
+
+ ByteArrayOutputStream baos;
+ ObjectOutputStream ostream =
+ new ObjectOutputStream(baos = new
+ ByteArrayOutputStream());
+ ostream.writeObject(zone);
+ ostream.close();
+ baos.close();
+ ObjectInputStream istream =
+ new ObjectInputStream(new
+ ByteArrayInputStream(baos.toByteArray()));
+ TimeZone frankenZone = (TimeZone) istream.readObject();
+ //logln("Zone: " + zone);
+ //logln("FrankenZone: " + frankenZone);
+ if (!zone.equals(frankenZone)) {
+ logln("TimeZone " + zone.getID() +
+ " not equal to serialized/deserialized one");
+ pass = false;
+ }
+ }
+ if (!pass) errln("Fail: TimeZone serialization/equality bug");
+ }
+ catch (IOException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ catch (ClassNotFoundException e) {
+ errln("Fail: " + e);
+ e.printStackTrace();
+ }
+ }
+
+ public void Test4109314() {
+ // test both SimpleTimeZone and ZoneInfo objects.
+ // @since 1.4
+ if (Locale.getDefault().equals(new Locale("th", "TH"))) {
+ return;
+ }
+ sub4109314(getPST());
+ sub4109314(TimeZone.getTimeZone("PST"));
+ }
+
+
+ @SuppressWarnings("deprecation")
+ private void sub4109314(TimeZone PST) {
+ GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
+ Object[] testData = {
+ PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),
+ PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),
+ };
+ boolean pass=true;
+ for (int i=0; i<testData.length; i+=3) {
+ testCal.setTimeZone((TimeZone) testData[i]);
+ long t = ((Date)testData[i+1]).getTime();
+ Date end = (Date) testData[i+2];
+ while (t < end.getTime()) {
+ testCal.setTime(new Date(t));
+ if (!checkCalendar314(testCal, (TimeZone) testData[i]))
+ pass = false;
+ t += 60*60*1000L;
+ }
+ }
+ if (!pass) errln("Fail: TZ API inconsistent");
+ }
+
+ boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {
+ // GregorianCalendar testCal = (GregorianCalendar)aCal.clone();
+
+ final int ONE_DAY = 24*60*60*1000;
+
+ int tzOffset, tzRawOffset;
+ Float tzOffsetFloat,tzRawOffsetFloat;
+ // Here is where the user made an error. They were passing in the value of
+ // the MILLSECOND field; you need to pass in the millis in the day in STANDARD
+ // time.
+ int millis = testCal.get(Calendar.MILLISECOND) +
+ 1000 * (testCal.get(Calendar.SECOND) +
+ 60 * (testCal.get(Calendar.MINUTE) +
+ 60 * (testCal.get(Calendar.HOUR_OF_DAY)))) -
+ testCal.get(Calendar.DST_OFFSET);
+
+ /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE
+ * BEGINNING OR END OF A MONTH. We must add this code because
+ * getOffset() has been changed to be more strict about the parameters
+ * it receives -- it turns out that this test was passing in illegal
+ * values. */
+ int date = testCal.get(Calendar.DATE);
+ int dow = testCal.get(Calendar.DAY_OF_WEEK);
+ while (millis < 0) {
+ millis += ONE_DAY;
+ --date;
+ dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7);
+ }
+ while (millis >= ONE_DAY) {
+ millis -= ONE_DAY;
+ ++date;
+ dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7);
+ }
+
+ tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA),
+ testCal.get(Calendar.YEAR),
+ testCal.get(Calendar.MONTH),
+ date,
+ dow,
+ millis);
+ tzRawOffset = testTZ.getRawOffset();
+ tzOffsetFloat = new Float((float)tzOffset/(float)3600000);
+ tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000);
+
+ Date testDate = testCal.getTime();
+
+ boolean inDaylightTime = testTZ.inDaylightTime(testDate);
+ SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");
+ sdf.setCalendar(testCal);
+ String inDaylightTimeString;
+
+ boolean passed;
+
+ if (inDaylightTime)
+ {
+ inDaylightTimeString = " DST ";
+ passed = (tzOffset == (tzRawOffset + 3600000));
+ }
+ else
+ {
+ inDaylightTimeString = " ";
+ passed = (tzOffset == tzRawOffset);
+ }
+
+ String output = testTZ.getID() + " " + sdf.format(testDate) +
+ " Offset(" + tzOffsetFloat + ")" +
+ " RawOffset(" + tzRawOffsetFloat + ")" +
+ " " + millis/(float)3600000 + " " +
+ inDaylightTimeString;
+
+ if (passed)
+ output += " ";
+ else
+ output += "ERROR";
+
+ if (passed) logln(output); else errln(output);
+ return passed;
+ }
+
+ /**
+ * CANNOT REPRODUDE
+ *
+ * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never
+ * should have been made public. It's simply too hard to use correctly.
+ *
+ * The original test code failed to do the following:
+ * (1) Call Calendar.setTime() before getting the fields!
+ * (2) Use the right millis (as usual) for getOffset(); they were passing
+ * in the MILLIS field, instead of the STANDARD MILLIS IN DAY.
+ * When you fix these two problems, the test passes, as expected.
+ */
+ public void Test4126678() {
+ // Note: this test depends on the PST time zone.
+ TimeZone initialZone = TimeZone.getDefault();
+
+ // test both SimpleTimeZone and ZoneInfo objects.
+ // @since 1.4
+ sub4126678(getPST());
+ sub4126678(TimeZone.getTimeZone("PST"));
+
+ // restore the initial time zone so that this test case
+ // doesn't affect the others.
+ TimeZone.setDefault(initialZone);
+ }
+
+ @SuppressWarnings("deprecation")
+ private void sub4126678(TimeZone tz) {
+ Calendar cal = Calendar.getInstance();
+ TimeZone.setDefault(tz);
+ cal.setTimeZone(tz);
+
+ Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0);
+ // the dt value is local time in PST.
+ if (!tz.inDaylightTime(dt))
+ errln("We're not in Daylight Savings Time and we should be.\n");
+
+ cal.setTime(dt);
+ int era = cal.get(Calendar.ERA);
+ int year = cal.get(Calendar.YEAR);
+ int month = cal.get(Calendar.MONTH);
+ int day = cal.get(Calendar.DATE);
+ int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
+ int millis = cal.get(Calendar.MILLISECOND) +
+ (cal.get(Calendar.SECOND) +
+ (cal.get(Calendar.MINUTE) +
+ (cal.get(Calendar.HOUR) * 60) * 60) * 1000) -
+ cal.get(Calendar.DST_OFFSET);
+
+ long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);
+ long raw_offset = tz.getRawOffset();
+ if (offset == raw_offset) {
+ errln("Offsets should not match when in DST");
+ }
+ }
+
+ /**
+ * TimeZone.getAvailableIDs(int) throws exception for certain values,
+ * due to a faulty constant in TimeZone.java.
+ */
+ public void Test4151406() {
+ int max = 0;
+ for (int h=-28; h<=30; ++h) {
+ // h is in half-hours from GMT; rawoffset is in millis
+ int rawoffset = h * 1800000;
+ int hh = (h<0) ? -h : h;
+ String hname = ((h<0) ? "GMT-" : "GMT+") +
+ ((hh/2 < 10) ? "0" : "") +
+ (hh/2) + ':' +
+ ((hh%2==0) ? "00" : "30");
+ try {
+ String[] ids = TimeZone.getAvailableIDs(rawoffset);
+ if (ids.length > max) max = ids.length;
+ logln(hname + ' ' + ids.length +
+ ((ids.length > 0) ? (" e.g. " + ids[0]) : ""));
+ } catch (Exception e) {
+ errln(hname + ' ' + "Fail: " + e);
+ }
+ }
+ logln("Maximum zones per offset = " + max);
+ }
+
+ public void Test4151429() {
+ try {
+ TimeZone tz = TimeZone.getTimeZone("GMT");
+ String name = tz.getDisplayName(true, Integer.MAX_VALUE,
+ Locale.getDefault());
+ errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");
+ } catch(IllegalArgumentException e) {}
+ }
+
+ /**
+ * SimpleTimeZone accepts illegal DST savings values. These values
+ * must be non-zero. There is no upper limit at this time.
+ */
+ public void Test4154525() {
+ final int GOOD = 1, BAD = 0;
+ int[] DATA = {
+ 1, GOOD,
+ 0, BAD,
+ -1, BAD,
+ 60*60*1000, GOOD,
+ Integer.MIN_VALUE, BAD,
+ // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ int savings = DATA[i];
+ boolean valid = DATA[i+1] == GOOD;
+ String method = null;
+ for (int j=0; j<2; ++j) {
+ try {
+ switch (j) {
+ case 0:
+ method = "constructor";
+ SimpleTimeZone z = new SimpleTimeZone(0, "id",
+ Calendar.JANUARY, 1, 0, 0,
+ Calendar.MARCH, 1, 0, 0,
+ savings); // <- what we're interested in
+ break;
+ case 1:
+ method = "setDSTSavings()";
+ z = new SimpleTimeZone(0, "GMT");
+ z.setDSTSavings(savings);
+ break;
+ }
+ if (valid) {
+ logln("Pass: DST savings of " + savings + " accepted by " + method);
+ } else {
+ errln("Fail: DST savings of " + savings + " accepted by " + method);
+ }
+ } catch (IllegalArgumentException e) {
+ if (valid) {
+ errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);
+ } else {
+ logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST
+ * and different DST parameters.
+ */
+ public void Test4154537() {
+ // tz1 and tz2 have no DST and different rule parameters
+ SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);
+ SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);
+ // tza and tzA have the same rule params
+ SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);
+ SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);
+ // tzb differs from tza
+ SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);
+ if (tz1.useDaylightTime() || tz2.useDaylightTime() ||
+ !tza.useDaylightTime() || !tzA.useDaylightTime() ||
+ !tzb.useDaylightTime()) {
+ errln("Test is broken -- rewrite it");
+ }
+ if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {
+ errln("Fail: hasSameRules() broken for zones with rules");
+ }
+ if (!tz1.hasSameRules(tz2)) {
+ errln("Fail: hasSameRules() returns false for zones without rules");
+ errln("zone 1 = " + tz1);
+ errln("zone 2 = " + tz2);
+ }
+ }
+
+ /**
+ * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't
+ * check for out-of-range arguments.
+ */
+ public void Test4154542() {
+ final int GOOD = 1;
+ final int BAD = 0;
+
+ final int GOOD_MONTH = Calendar.JANUARY;
+ final int GOOD_DAY = 1;
+ final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;
+ final int GOOD_TIME = 0;
+
+ int[] DATA = {
+ GOOD, Integer.MIN_VALUE, 0, Integer.MAX_VALUE, Integer.MIN_VALUE,
+ GOOD, Calendar.JANUARY, -5, Calendar.SUNDAY, 0,
+ GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000-1,
+ GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000,
+ BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000+1,
+ BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, -1,
+ BAD, Calendar.JANUARY, -6, Calendar.SUNDAY, 0,
+ BAD, Calendar.DECEMBER, 6, Calendar.SATURDAY, 24*60*60*1000,
+ GOOD, Calendar.DECEMBER, 1, 0, 0,
+ GOOD, Calendar.DECEMBER, 31, 0, 0,
+ BAD, Calendar.APRIL, 31, 0, 0,
+ BAD, Calendar.DECEMBER, 32, 0, 0,
+ BAD, Calendar.JANUARY-1, 1, Calendar.SUNDAY, 0,
+ BAD, Calendar.DECEMBER+1, 1, Calendar.SUNDAY, 0,
+ GOOD, Calendar.DECEMBER, 31, -Calendar.SUNDAY, 0,
+ GOOD, Calendar.DECEMBER, 31, -Calendar.SATURDAY, 0,
+ BAD, Calendar.DECEMBER, 32, -Calendar.SATURDAY, 0,
+ BAD, Calendar.DECEMBER, -32, -Calendar.SATURDAY, 0,
+ BAD, Calendar.DECEMBER, 31, -Calendar.SATURDAY-1, 0,
+ };
+ SimpleTimeZone zone = new SimpleTimeZone(0, "Z");
+ for (int i=0; i<DATA.length; i+=5) {
+ boolean shouldBeGood = (DATA[i] == GOOD);
+ int month = DATA[i+1];
+ int day = DATA[i+2];
+ int dayOfWeek = DATA[i+3];
+ int time = DATA[i+4];
+
+ Exception ex = null;
+ try {
+ zone.setStartRule(month, day, dayOfWeek, time);
+ } catch (IllegalArgumentException e) {
+ ex = e;
+ }
+ if ((ex == null) != shouldBeGood) {
+ errln("setStartRule(month=" + month + ", day=" + day +
+ ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+ (shouldBeGood ? (") should work but throws " + ex)
+ : ") should fail but doesn't"));
+ }
+
+ ex = null;
+ try {
+ zone.setEndRule(month, day, dayOfWeek, time);
+ } catch (IllegalArgumentException e) {
+ ex = e;
+ }
+ if ((ex == null) != shouldBeGood) {
+ errln("setEndRule(month=" + month + ", day=" + day +
+ ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+ (shouldBeGood ? (") should work but throws " + ex)
+ : ") should fail but doesn't"));
+ }
+
+ ex = null;
+ try {
+ SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
+ month, day, dayOfWeek, time,
+ GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);
+ } catch (IllegalArgumentException e) {
+ ex = e;
+ }
+ if ((ex == null) != shouldBeGood) {
+ errln("SimpleTimeZone(month=" + month + ", day=" + day +
+ ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+ (shouldBeGood ? (", <end>) should work but throws " + ex)
+ : ", <end>) should fail but doesn't"));
+ }
+
+ ex = null;
+ try {
+ SimpleTimeZone temp = new SimpleTimeZone(0, "Z",
+ GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,
+ month, day, dayOfWeek, time);
+ } catch (IllegalArgumentException e) {
+ ex = e;
+ }
+ if ((ex == null) != shouldBeGood) {
+ errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +
+ ", dayOfWeek=" + dayOfWeek + ", time=" + time +
+ (shouldBeGood ? (") should work but throws " + ex)
+ : ") should fail but doesn't"));
+ }
+ }
+ }
+
+ /**
+ * SimpleTimeZone.getOffset accepts illegal arguments.
+ */
+ public void Test4154650() {
+ final int GOOD=1, BAD=0;
+ final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;
+ final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;
+ int[] DATA = {
+ GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+ GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+ GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,
+
+ GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,
+ GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME,
+
+ GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME,
+ GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,
+ BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,
+
+ GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,
+ GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,
+ BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,
+ BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,
+ };
+
+ TimeZone tz = TimeZone.getDefault();
+ for (int i=0; i<DATA.length; i+=7) {
+ boolean good = DATA[i] == GOOD;
+ IllegalArgumentException e = null;
+ try {
+ int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],
+ DATA[i+4], DATA[i+5], DATA[i+6]);
+ } catch (IllegalArgumentException ex) {
+ e = ex;
+ }
+ if (good != (e == null)) {
+ errln("Fail: getOffset(" +
+ DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +
+ DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +
+ (good ? (") threw " + e) : ") accepts invalid args"));
+ }
+ }
+ }
+
+ /**
+ * TimeZone constructors allow null IDs.
+ */
+ public void Test4159922() {
+ TimeZone z = null;
+
+ // TimeZone API. Only hasSameRules() and setDefault() should
+ // allow null.
+ try {
+ z = TimeZone.getTimeZone((String)null);
+ errln("FAIL: Null allowed in getTimeZone");
+ } catch (NullPointerException e) {}
+ z = TimeZone.getTimeZone("GMT");
+ try {
+ z.getDisplayName(false, TimeZone.SHORT, null);
+ errln("FAIL: Null allowed in getDisplayName(3)");
+ } catch (NullPointerException e) {}
+ try {
+ z.getDisplayName(null);
+ errln("FAIL: Null allowed in getDisplayName(1)");
+ } catch (NullPointerException e) {}
+ try {
+ if (z.hasSameRules(null)) {
+ errln("FAIL: hasSameRules returned true");
+ }
+ } catch (NullPointerException e) {
+ errln("FAIL: Null NOT allowed in hasSameRules");
+ }
+ try {
+ z.inDaylightTime(null);
+ errln("FAIL: Null allowed in inDaylightTime");
+ } catch (NullPointerException e) {}
+ try {
+ z.setID(null);
+ errln("FAIL: Null allowed in setID");
+ } catch (NullPointerException e) {}
+
+ TimeZone save = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(null);
+ } catch (NullPointerException e) {
+ errln("FAIL: Null NOT allowed in setDefault");
+ } finally {
+ TimeZone.setDefault(save);
+ }
+
+ // SimpleTimeZone API
+ SimpleTimeZone s = null;
+ try {
+ s = new SimpleTimeZone(0, null);
+ errln("FAIL: Null allowed in SimpleTimeZone(2)");
+ } catch (NullPointerException e) {}
+ try {
+ s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);
+ errln("FAIL: Null allowed in SimpleTimeZone(10)");
+ } catch (NullPointerException e) {}
+ try {
+ s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);
+ errln("FAIL: Null allowed in SimpleTimeZone(11)");
+ } catch (NullPointerException e) {}
+ }
+
+ /**
+ * TimeZone broken at midnight. The TimeZone code fails to handle
+ * transitions at midnight correctly.
+ */
+ @SuppressWarnings("deprecation")
+ public void Test4162593() {
+ SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);
+ final int ONE_HOUR = 60*60*1000;
+ TimeZone initialZone = TimeZone.getDefault();
+
+ SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,
+ Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,
+ Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);
+
+ /* Zone
+ * Starting time
+ * Transition expected between start+1H and start+2H
+ */
+ Object[] DATA = {
+ new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,
+ Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,
+ Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),
+ new int[] {98, Calendar.SEPTEMBER, 30, 22, 0},
+ Boolean.TRUE,
+
+ asuncion,
+ new int[] {100, Calendar.FEBRUARY, 28, 22, 0},
+ Boolean.FALSE,
+
+ asuncion,
+ new int[] {100, Calendar.FEBRUARY, 29, 22, 0},
+ Boolean.TRUE,
+ };
+
+ String[] zone = new String[4];
+
+ try {
+ for (int j=0; j<DATA.length; j+=3) {
+ TimeZone tz = (TimeZone)DATA[j];
+ TimeZone.setDefault(tz);
+ fmt.setTimeZone(tz);
+
+ // Must construct the Date object AFTER setting the default zone
+ int[] p = (int[])DATA[j+1];
+ Date d = new Date(p[0], p[1], p[2], p[3], p[4]);
+ boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();
+
+ logln(tz.getID() + ":");
+ for (int i=0; i<4; ++i) {
+ zone[i] = fmt.format(d);
+ logln("" + i + ": " + d);
+ d = new Date(d.getTime() + ONE_HOUR);
+ }
+ if (zone[0].equals(zone[1]) &&
+ (zone[1].equals(zone[2]) != transitionExpected) &&
+ zone[2].equals(zone[3])) {
+ logln("Ok: transition " + transitionExpected);
+ } else {
+ errln("Fail: boundary transition incorrect");
+ }
+ }
+ }
+ finally {
+ // restore the initial time zone so that this test case
+ // doesn't affect the others.
+ TimeZone.setDefault(initialZone);
+ }
+ }
+
+ /**
+ * TimeZone broken in last hour of year
+ */
+ public void Test4173604() {
+ // test both SimpleTimeZone and ZoneInfo objects.
+ // @since 1.4
+ sub4173604(getPST());
+ sub4173604(TimeZone.getTimeZone("PST"));
+ }
+
+ private void sub4173604(TimeZone pst) {
+ int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);
+ int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);
+ int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);
+ if (o22 != o23 || o22 != o00) {
+ errln("Offsets should be the same (for PST), but got: " +
+ "12/31 22:00 " + o22 +
+ ", 12/31 23:00 " + o23 +
+ ", 01/01 00:00 " + o00);
+ }
+
+ GregorianCalendar cal = new GregorianCalendar();
+ cal.setTimeZone(pst);
+ cal.clear();
+ cal.set(1998, Calendar.JANUARY, 1);
+ int lastDST = cal.get(Calendar.DST_OFFSET);
+ int transitions = 0;
+ int delta = 5;
+ while (cal.get(Calendar.YEAR) < 2000) {
+ cal.add(Calendar.MINUTE, delta);
+ if (cal.get(Calendar.DST_OFFSET) != lastDST) {
+ ++transitions;
+ Calendar t = (Calendar)cal.clone();
+ t.add(Calendar.MINUTE, -delta);
+ logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET));
+ logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET)));
+ }
+ }
+ if (transitions != 4) {
+ errln("Saw " + transitions + " transitions; should have seen 4");
+ }
+ }
+
+ /**
+ * getDisplayName doesn't work with unusual savings/offsets.
+ */
+ @SuppressWarnings("deprecation")
+ public void Test4176686() {
+ // Construct a zone that does not observe DST but
+ // that does have a DST savings (which should be ignored).
+ int offset = 90 * 60000; // 1:30
+ SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");
+ z1.setDSTSavings(45 * 60000); // 0:45
+
+ // Construct a zone that observes DST for the first 6 months.
+ SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");
+ z2.setDSTSavings(45 * 60000); // 0:45
+ z2.setStartRule(Calendar.JANUARY, 1, 0);
+ z2.setEndRule(Calendar.JULY, 1, 0);
+
+ // Also check DateFormat
+ DateFormat fmt1 = new SimpleDateFormat("z");
+ fmt1.setTimeZone(z1); // Format uses standard zone
+ DateFormat fmt2 = new SimpleDateFormat("z");
+ fmt2.setTimeZone(z2); // Format uses DST zone
+ Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST
+ Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard
+
+ // Description, Result, Expected Result
+ String[] DATA = {
+ "getDisplayName(false, SHORT)/std zone",
+ z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+ "getDisplayName(false, LONG)/std zone",
+ z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
+ "getDisplayName(true, SHORT)/std zone",
+ z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",
+ "getDisplayName(true, LONG)/std zone",
+ z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",
+ "getDisplayName(false, SHORT)/dst zone",
+ z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",
+ "getDisplayName(false, LONG)/dst zone",
+ z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",
+ "getDisplayName(true, SHORT)/dst zone",
+ z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",
+ "getDisplayName(true, LONG)/dst zone",
+ z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",
+ "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",
+ "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",
+ "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",
+ "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",
+ };
+
+ for (int i=0; i<DATA.length; i+=3) {
+ if (!DATA[i+1].equals(DATA[i+2])) {
+ errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);
+ }
+ }
+ }
+
+ /**
+ * SimpleTimeZone allows invalid DOM values.
+ */
+ public void Test4184229() {
+ SimpleTimeZone zone = null;
+ try {
+ zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);
+ errln("Failed. No exception has been thrown for DOM -1 startDay");
+ } catch(IllegalArgumentException e) {
+ logln("(a) " + e.getMessage());
+ }
+ try {
+ zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);
+ errln("Failed. No exception has been thrown for DOM -1 endDay");
+ } catch(IllegalArgumentException e) {
+ logln("(b) " + e.getMessage());
+ }
+ try {
+ zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);
+ errln("Failed. No exception has been thrown for DOM -1 startDay +savings");
+ } catch(IllegalArgumentException e) {
+ logln("(c) " + e.getMessage());
+ }
+ try {
+ zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);
+ errln("Failed. No exception has been thrown for DOM -1 endDay +savings");
+ } catch(IllegalArgumentException e) {
+ logln("(d) " + e.getMessage());
+ }
+ // Make a valid constructor call for subsequent tests.
+ zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);
+ try {
+ zone.setStartRule(0, -1, 0, 0);
+ errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");
+ } catch(IllegalArgumentException e) {
+ logln("(e) " + e.getMessage());
+ }
+ try {
+ zone.setStartRule(0, -1, 0);
+ errln("Failed. No exception has been thrown for DOM -1 setStartRule");
+ } catch(IllegalArgumentException e) {
+ logln("(f) " + e.getMessage());
+ }
+ try {
+ zone.setEndRule(0, -1, 0, 0);
+ errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");
+ } catch(IllegalArgumentException e) {
+ logln("(g) " + e.getMessage());
+ }
+ try {
+ zone.setEndRule(0, -1, 0);
+ errln("Failed. No exception has been thrown for DOM -1 setEndRule");
+ } catch(IllegalArgumentException e) {
+ logln("(h) " + e.getMessage());
+ }
+ }
+
+ /**
+ * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get
+ * of 2/29/1996 (leap day).
+ */
+ public void Test4208960 () {
+ // test both SimpleTimeZone and ZoneInfo objects.
+ // @since 1.4
+ sub4208960(getPST());
+ sub4208960(TimeZone.getTimeZone("PST"));
+ }
+
+ private void sub4208960(TimeZone tz) {
+ try {
+ int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,
+ Calendar.THURSDAY, 0);
+ } catch (IllegalArgumentException e) {
+ errln("FAILED: to get TimeZone.getOffset(2/29/96)");
+ }
+ try {
+ int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,
+ Calendar.THURSDAY, 0);
+ errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");
+ } catch (IllegalArgumentException e) {
+ logln("got IllegalArgumentException");
+ }
+ }
+
+ /**
+ * 4966229: java.util.Date methods may works incorrect.
+ * sun.util.calendar.ZoneInfo doesn't clone properly.
+ */
+ @SuppressWarnings("deprecation")
+ public void Test4966229() {
+ TimeZone savedTZ = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+ Date d = new Date(2100-1900, 5, 1); // specify year >2037
+ TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
+
+ Calendar cal = new GregorianCalendar(tz);
+ cal.setTime(d);
+
+ // Change the raw offset in tz
+ int offset = tz.getRawOffset();
+ tz.setRawOffset(0);
+
+ TimeZone tz2 = (TimeZone) tz.clone();
+ Calendar cal2 = new GregorianCalendar(tz2);
+ cal2.setTime(d);
+ int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY);
+
+ // Restore the GMT offset in tz which shouldn't affect tz2
+ tz.setRawOffset(offset);
+ cal2.setTime(d);
+ int hourOfDay = cal2.get(cal.HOUR_OF_DAY);
+ if (hourOfDay != expectedHourOfDay) {
+ errln("wrong hour of day: got: " + hourOfDay
+ + ", expected: " + expectedHourOfDay);
+ }
+ } finally {
+ TimeZone.setDefault(savedTZ);
+ }
+ }
+
+ /**
+ * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+
+ */
+ public void Test6433179() {
+ // Use the old America/Winnipeg rule for testing. Note that
+ // startMode is WALL_TIME for testing. It's actually
+ // STANDARD_TIME, though.
+ //Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S
+ //Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D
+ TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg",
+ Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME,
+ 1*ONE_HOUR);
+ Calendar cal = Calendar.getInstance(tz, Locale.US);
+ cal.clear();
+ cal.set(2039, Calendar.OCTOBER, 1);
+ cal.getTime();
+ cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);
+ cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1);
+ cal.add(Calendar.HOUR_OF_DAY, 2);
+ if (cal.get(cal.DST_OFFSET) == 0) {
+ errln("Should still be in DST.");
+ }
+ }
+
+ private static final int ONE_HOUR = 60 * 60 * 1000;
+ /**
+ * Returns an instance of SimpleTimeZone for
+ * "PST". (TimeZone.getTimeZone() no longer returns a
+ * SimpleTimeZone object.)
+ * @since 1.4
+ */
+ private SimpleTimeZone getPST() {
+ return new SimpleTimeZone(-8*ONE_HOUR, "PST",
+ Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR,
+ Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR,
+ 1*ONE_HOUR);
+ }
+}
+//eof
diff --git a/test/java/util/TimeZone/TimeZoneTest.java b/test/java/util/TimeZone/TimeZoneTest.java
new file mode 100644
index 0000000000..27391375a7
--- /dev/null
+++ b/test/java/util/TimeZone/TimeZoneTest.java
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 1997, 2019, 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 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483
+ * 8008577 8077685 8098547 8133321 8138716 8148446 8151876 8228469
+ * @library /java/text/testlib
+ * @summary test TimeZone
+ */
+
+import java.io.*;
+import java.text.*;
+import java.util.*;
+import sun.util.resources.LocaleData;
+
+public class TimeZoneTest extends IntlTest
+{
+ static final int millisPerHour = 3600000;
+
+ public static void main(String[] args) throws Exception {
+ new TimeZoneTest().run(args);
+ }
+
+ /**
+ * Bug 4130885
+ * Certain short zone IDs, used since 1.1.x, are incorrect.
+ *
+ * The worst of these is:
+ *
+ * "CAT" (Central African Time) should be GMT+2:00, but instead returns a
+ * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST,
+ * or AZOST, depending on which zone is meant, but in no case is it CAT.
+ *
+ * Other wrong zone IDs:
+ *
+ * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time,
+ * GMT-5:00. European Central time is abbreviated CEST.
+ *
+ * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time,
+ * GMT-11:00. Solomon Island time is SBT.
+ *
+ * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for
+ * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST.
+ *
+ * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in
+ * another bug.] It should be "AKST". AST is Atlantic Standard Time,
+ * GMT-4:00.
+ *
+ * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time,
+ * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct
+ * from MST with daylight savings.
+ *
+ * In addition to these problems, a number of zones are FAKE. That is, they
+ * don't match what people use in the real world.
+ *
+ * FAKE zones:
+ *
+ * EET (should be EEST)
+ * ART (should be EET)
+ * MET (should be IRST)
+ * NET (should be AMST)
+ * PLT (should be PKT)
+ * BST (should be BDT)
+ * VST (should be ICT)
+ * CTT (should be CST) +
+ * ACT (should be CST) +
+ * AET (should be EST) +
+ * MIT (should be WST) +
+ * IET (should be EST) +
+ * PRT (should be AST) +
+ * CNT (should be NST)
+ * AGT (should be ARST)
+ * BET (should be EST) +
+ *
+ * + A zone with the correct name already exists and means something
+ * else. E.g., EST usually indicates the US Eastern zone, so it cannot be
+ * used for Brazil (BET).
+ */
+ public void TestShortZoneIDs() throws Exception {
+
+ ZoneDescriptor[] JDK_116_REFERENCE_LIST = {
+ new ZoneDescriptor("MIT", 780, true),
+ new ZoneDescriptor("HST", -600, false),
+ new ZoneDescriptor("AST", -540, true),
+ new ZoneDescriptor("PST", -480, true),
+ new ZoneDescriptor("PNT", -420, false),
+ new ZoneDescriptor("MST", -420, false),
+ new ZoneDescriptor("CST", -360, true),
+ new ZoneDescriptor("IET", -300, true),
+ new ZoneDescriptor("EST", -300, false),
+ new ZoneDescriptor("PRT", -240, false),
+ new ZoneDescriptor("CNT", -210, true),
+ new ZoneDescriptor("AGT", -180, false),
+ new ZoneDescriptor("BET", -180, false),
+ // new ZoneDescriptor("CAT", -60, false), // Wrong:
+ // As of bug 4130885, fix CAT (Central Africa)
+ new ZoneDescriptor("CAT", 120, false), // Africa/Harare
+ new ZoneDescriptor("GMT", 0, false),
+ new ZoneDescriptor("UTC", 0, false),
+ new ZoneDescriptor("ECT", 60, true),
+ new ZoneDescriptor("ART", 120, false),
+ new ZoneDescriptor("EET", 120, true),
+ new ZoneDescriptor("EAT", 180, false),
+ new ZoneDescriptor("MET", 60, true),
+ new ZoneDescriptor("NET", 240, false),
+ new ZoneDescriptor("PLT", 300, false),
+ new ZoneDescriptor("IST", 330, false),
+ new ZoneDescriptor("BST", 360, false),
+ new ZoneDescriptor("VST", 420, false),
+ new ZoneDescriptor("CTT", 480, false),
+ new ZoneDescriptor("JST", 540, false),
+ new ZoneDescriptor("ACT", 570, false),
+ new ZoneDescriptor("AET", 600, true),
+ new ZoneDescriptor("SST", 660, false),
+ // new ZoneDescriptor("NST", 720, false),
+ // As of bug 4130885, fix NST (New Zealand)
+ new ZoneDescriptor("NST", 720, true), // Pacific/Auckland
+ };
+
+ Map<String, ZoneDescriptor> hash = new HashMap<>();
+
+ String[] ids = TimeZone.getAvailableIDs();
+ for (String id : ids) {
+ if (id.length() == 3) {
+ hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id)));
+ }
+ }
+
+ for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) {
+ ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i];
+ ZoneDescriptor currentZone = hash.get(referenceZone.getID());
+ if (referenceZone.equals(currentZone)) {
+ logln("ok " + referenceZone);
+ }
+ else {
+ errln("Fail: Expected " + referenceZone +
+ "; got " + currentZone);
+ }
+ }
+ }
+
+ /**
+ * A descriptor for a zone; used to regress the short zone IDs.
+ */
+ static class ZoneDescriptor {
+ String id;
+ int offset; // In minutes
+ boolean daylight;
+
+ ZoneDescriptor(TimeZone zone) {
+ this.id = zone.getID();
+ this.offset = zone.getRawOffset() / 60000;
+ this.daylight = zone.useDaylightTime();
+ }
+
+ ZoneDescriptor(String id, int offset, boolean daylight) {
+ this.id = id;
+ this.offset = offset;
+ this.daylight = daylight;
+ }
+
+ public String getID() { return id; }
+
+ @Override
+ public boolean equals(Object o) {
+ ZoneDescriptor that = (ZoneDescriptor)o;
+ return that != null &&
+ id.equals(that.id) &&
+ offset == that.offset &&
+ daylight == that.daylight;
+ }
+
+ @Override
+ public int hashCode() {
+ return id.hashCode() ^ offset | (daylight ? 1 : 0);
+ }
+
+ @Override
+ public String toString() {
+ int min = offset;
+ char sign = '+';
+ if (min < 0) { sign = '-'; min = -min; }
+
+ return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' +
+ (min%60<10?"0":"") + (min%60) + ", " +
+ (daylight ? "Daylight" : "Standard") + "]";
+ }
+
+ public static int compare(Object o1, Object o2) {
+ ZoneDescriptor i1 = (ZoneDescriptor)o1;
+ ZoneDescriptor i2 = (ZoneDescriptor)o2;
+ if (i1.offset > i2.offset) return 1;
+ if (i1.offset < i2.offset) return -1;
+ if (i1.daylight && !i2.daylight) return 1;
+ if (!i1.daylight && i2.daylight) return -1;
+ return i1.id.compareTo(i2.id);
+ }
+ }
+
+ static final String formatMinutes(int min) {
+ char sign = '+';
+ if (min < 0) { sign = '-'; min = -min; }
+ int h = min/60;
+ min = min%60;
+ return "" + sign + h + ":" + ((min<10) ? "0" : "") + min;
+ }
+ /**
+ * As part of the VM fix (see CCC approved RFE 4028006, bug
+ * 4044013), TimeZone.getTimeZone() has been modified to recognize
+ * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and
+ * GMT[+-]hh. Test this behavior here.
+ *
+ * Bug 4044013
+ *
+ * ID "Custom" is no longer used for TimeZone objects created with
+ * a custom time zone ID, such as "GMT-8". See 4322313.
+ */
+ public void TestCustomParse() throws Exception {
+ Object[] DATA = {
+ // ID Expected offset in minutes
+ "GMT", null,
+ "GMT+0", new Integer(0),
+ "GMT+1", new Integer(60),
+ "GMT-0030", new Integer(-30),
+ "GMT+15:99", null,
+ "GMT+", null,
+ "GMT-", null,
+ "GMT+0:", null,
+ "GMT-:", null,
+ "GMT+0010", new Integer(10), // Interpret this as 00:10
+ "GMT-10", new Integer(-10*60),
+ "GMT+30", null,
+ "GMT-3:30", new Integer(-(3*60+30)),
+ "GMT-230", new Integer(-(2*60+30)),
+ };
+ for (int i=0; i<DATA.length; i+=2) {
+ String id = (String)DATA[i];
+ Integer exp = (Integer)DATA[i+1];
+ TimeZone zone = TimeZone.getTimeZone(id);
+ if (zone.getID().equals("GMT")) {
+ logln(id + " -> generic GMT");
+ // When TimeZone.getTimeZone() can't parse the id, it
+ // returns GMT -- a dubious practice, but required for
+ // backward compatibility.
+ if (exp != null) {
+ throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) +
+ " for " + id + ", got parse failure");
+ }
+ }
+ else {
+ int ioffset = zone.getRawOffset()/60000;
+ String offset = formatMinutes(ioffset);
+ logln(id + " -> " + zone.getID() + " GMT" + offset);
+ if (exp == null) {
+ throw new Exception("Expected parse failure for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ }
+ else if (ioffset != exp.intValue()) {
+ throw new Exception("Expected offset of " + formatMinutes(exp.intValue()) +
+ ", id Custom, for " + id +
+ ", got offset of " + offset +
+ ", id " + zone.getID());
+ }
+ }
+ }
+ }
+
+ /**
+ * Test the basic functionality of the getDisplayName() API.
+ *
+ * Bug 4112869
+ * Bug 4028006
+ *
+ * See also API change request A41.
+ *
+ * 4/21/98 - make smarter, so the test works if the ext resources
+ * are present or not.
+ */
+ public void TestDisplayName() {
+ TimeZone zone = TimeZone.getTimeZone("PST");
+ String name = zone.getDisplayName(Locale.ENGLISH);
+ logln("PST->" + name);
+ if (!name.equals("Pacific Standard Time"))
+ errln("Fail: Expected \"Pacific Standard Time\"");
+
+ //*****************************************************************
+ // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ //*****************************************************************
+ Object[] DATA = {
+ new Boolean(false), new Integer(TimeZone.SHORT), "PST",
+ new Boolean(true), new Integer(TimeZone.SHORT), "PDT",
+ new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time",
+ new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time",
+ };
+
+ for (int i=0; i<DATA.length; i+=3) {
+ name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(),
+ ((Integer)DATA[i+1]).intValue(),
+ Locale.ENGLISH);
+ if (!name.equals(DATA[i+2]))
+ errln("Fail: Expected " + DATA[i+2] + "; got " + name);
+ }
+
+ // Make sure that we don't display the DST name by constructing a fake
+ // PST zone that has DST all year long.
+ SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST");
+ zone2.setStartRule(Calendar.JANUARY, 1, 0);
+ zone2.setEndRule(Calendar.DECEMBER, 31, 0);
+ logln("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date()));
+ name = zone2.getDisplayName(Locale.ENGLISH);
+ logln("Modified PST->" + name);
+ if (!name.equals("Pacific Standard Time"))
+ errln("Fail: Expected \"Pacific Standard Time\"");
+
+ // Make sure we get the default display format for Locales
+ // with no display name data.
+ Locale zh_CN = Locale.SIMPLIFIED_CHINESE;
+ name = zone.getDisplayName(zh_CN);
+ //*****************************************************************
+ // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES
+ //*****************************************************************
+ logln("PST(zh_CN)->" + name);
+
+ // Now be smart -- check to see if zh resource is even present.
+ // If not, we expect the en fallback behavior.
+ ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
+ Locale.ENGLISH);
+ ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.TimeZoneNames",
+ zh_CN);
+
+ boolean noZH = enRB == zhRB;
+
+ if (noZH) {
+ logln("Warning: Not testing the zh_CN behavior because resource is absent");
+ if (!name.equals("Pacific Standard Time"))
+ errln("Fail: Expected Pacific Standard Time");
+ }
+ else if (!name.equals("Pacific Standard Time") &&
+ !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") &&
+ !name.equals("GMT-08:00") &&
+ !name.equals("GMT-8:00") &&
+ !name.equals("GMT-0800") &&
+ !name.equals("GMT-800")) {
+ errln("Fail: Expected GMT-08:00 or something similar");
+ errln("************************************************************");
+ errln("THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED");
+ errln("************************************************************");
+ }
+
+ // Now try a non-existent zone
+ zone2 = new SimpleTimeZone(90*60*1000, "xyzzy");
+ name = zone2.getDisplayName(Locale.ENGLISH);
+ logln("GMT+90min->" + name);
+ if (!name.equals("GMT+01:30") &&
+ !name.equals("GMT+1:30") &&
+ !name.equals("GMT+0130") &&
+ !name.equals("GMT+130"))
+ errln("Fail: Expected GMT+01:30 or something similar");
+ }
+
+ public void TestGenericAPI() {
+ String id = "NewGMT";
+ int offset = 12345;
+
+ SimpleTimeZone zone = new SimpleTimeZone(offset, id);
+ if (zone.useDaylightTime()) {
+ errln("FAIL: useDaylightTime should return false");
+ }
+
+ TimeZone zoneclone = (TimeZone)zone.clone();
+ if (!zoneclone.equals(zone)) {
+ errln("FAIL: clone or operator== failed");
+ }
+ zoneclone.setID("abc");
+ if (zoneclone.equals(zone)) {
+ errln("FAIL: clone or operator!= failed");
+ }
+
+ zoneclone = (TimeZone)zone.clone();
+ if (!zoneclone.equals(zone)) {
+ errln("FAIL: clone or operator== failed");
+ }
+ zoneclone.setRawOffset(45678);
+ if (zoneclone.equals(zone)) {
+ errln("FAIL: clone or operator!= failed");
+ }
+
+ TimeZone saveDefault = TimeZone.getDefault();
+ try {
+ TimeZone.setDefault(zone);
+ TimeZone defaultzone = TimeZone.getDefault();
+ if (defaultzone == zone) {
+ errln("FAIL: Default object is identical, not clone");
+ }
+ if (!defaultzone.equals(zone)) {
+ errln("FAIL: Default object is not equal");
+ }
+ }
+ finally {
+ TimeZone.setDefault(saveDefault);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public void TestRuleAPI()
+ {
+ // ErrorCode status = ZERO_ERROR;
+
+ int offset = (int)(60*60*1000*1.75); // Pick a weird offset
+ SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone");
+ if (zone.useDaylightTime()) errln("FAIL: useDaylightTime should return false");
+
+ // Establish our expected transition times. Do this with a non-DST
+ // calendar with the (above) declared local offset.
+ GregorianCalendar gc = new GregorianCalendar(zone);
+ gc.clear();
+ gc.set(1990, Calendar.MARCH, 1);
+ long marchOneStd = gc.getTime().getTime(); // Local Std time midnight
+ gc.clear();
+ gc.set(1990, Calendar.JULY, 1);
+ long julyOneStd = gc.getTime().getTime(); // Local Std time midnight
+
+ // Starting and ending hours, WALL TIME
+ int startHour = (int)(2.25 * 3600000);
+ int endHour = (int)(3.5 * 3600000);
+
+ zone.setStartRule(Calendar.MARCH, 1, 0, startHour);
+ zone.setEndRule (Calendar.JULY, 1, 0, endHour);
+
+ gc = new GregorianCalendar(zone);
+ // if (failure(status, "new GregorianCalendar")) return;
+
+ long marchOne = marchOneStd + startHour;
+ long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time
+
+ long expMarchOne = 636251400000L;
+ if (marchOne != expMarchOne)
+ {
+ errln("FAIL: Expected start computed as " + marchOne +
+ " = " + new Date(marchOne));
+ logln(" Should be " + expMarchOne +
+ " = " + new Date(expMarchOne));
+ }
+
+ long expJulyOne = 646793100000L;
+ if (julyOne != expJulyOne)
+ {
+ errln("FAIL: Expected start computed as " + julyOne +
+ " = " + new Date(julyOne));
+ logln(" Should be " + expJulyOne +
+ " = " + new Date(expJulyOne));
+ }
+
+ testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(),
+ new Date(90, Calendar.JUNE, 15).getTime(), marchOne);
+ testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(),
+ new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne);
+
+ if (zone.inDaylightTime(new Date(marchOne - 1000)) ||
+ !zone.inDaylightTime(new Date(marchOne)))
+ errln("FAIL: Start rule broken");
+ if (!zone.inDaylightTime(new Date(julyOne - 1000)) ||
+ zone.inDaylightTime(new Date(julyOne)))
+ errln("FAIL: End rule broken");
+
+ zone.setStartYear(1991);
+ if (zone.inDaylightTime(new Date(marchOne)) ||
+ zone.inDaylightTime(new Date(julyOne - 1000)))
+ errln("FAIL: Start year broken");
+
+ // failure(status, "TestRuleAPI");
+ // delete gc;
+ // delete zone;
+ }
+
+ void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary)
+ {
+ // ErrorCode status = ZERO_ERROR;
+ boolean startsInDST = tz.inDaylightTime(new Date(min));
+ // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+ if (tz.inDaylightTime(new Date(max)) == startsInDST) {
+ logln("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST));
+ return;
+ }
+ // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+ while ((max - min) > INTERVAL) {
+ long mid = (min + max) / 2;
+ if (tz.inDaylightTime(new Date(mid)) == startsInDST) {
+ min = mid;
+ }
+ else {
+ max = mid;
+ }
+ // if (failure(status, "SimpleTimeZone::inDaylightTime")) return;
+ }
+ logln("Binary Search Before: " + min + " = " + new Date(min));
+ logln("Binary Search After: " + max + " = " + new Date(max));
+ long mindelta = expectedBoundary - min;
+ long maxdelta = max - expectedBoundary;
+ if (mindelta >= 0 &&
+ mindelta <= INTERVAL &&
+ mindelta >= 0 &&
+ mindelta <= INTERVAL)
+ logln("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary));
+ else
+ errln("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary));
+ }
+
+ static final int INTERVAL = 100;
+
+ // Bug 006; verify the offset for a specific zone.
+ public void TestPRTOffset()
+ {
+ TimeZone tz = TimeZone.getTimeZone( "PRT" );
+ if( tz == null ) {
+ errln( "FAIL: TimeZone(PRT) is null" );
+ }
+ else{
+ if (tz.getRawOffset() != (-4*millisPerHour))
+ errln("FAIL: Offset for PRT should be -4");
+ }
+
+ }
+
+ // Test various calls
+ @SuppressWarnings("deprecation")
+ public void TestVariousAPI518()
+ {
+ TimeZone time_zone = TimeZone.getTimeZone("PST");
+ Date d = new Date(97, Calendar.APRIL, 30);
+
+ logln("The timezone is " + time_zone.getID());
+
+ if (time_zone.inDaylightTime(d) != true)
+ errln("FAIL: inDaylightTime returned false");
+
+ if (time_zone.useDaylightTime() != true)
+ errln("FAIL: useDaylightTime returned false");
+
+ if (time_zone.getRawOffset() != -8*millisPerHour)
+ errln( "FAIL: getRawOffset returned wrong value");
+
+ GregorianCalendar gc = new GregorianCalendar();
+ gc.setTime(d);
+ if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH),
+ gc.get(gc.DAY_OF_MONTH),
+ gc.get(gc.DAY_OF_WEEK), 0)
+ != -7*millisPerHour)
+ errln("FAIL: getOffset returned wrong value");
+ }
+
+ // Test getAvailableID API
+ public void TestGetAvailableIDs913()
+ {
+ StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { ");
+ String[] s = TimeZone.getAvailableIDs();
+ for (int i=0; i<s.length; ++i)
+ {
+ if (i > 0) buf.append(", ");
+ buf.append(s[i]);
+ }
+ buf.append(" };");
+ logln(buf.toString());
+
+ buf.setLength(0);
+ buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { ");
+ s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000);
+ for (int i=0; i<s.length; ++i)
+ {
+ if (i > 0) buf.append(", ");
+ buf.append(s[i]);
+ }
+ buf.append(" };");
+ logln(buf.toString());
+
+ TimeZone tz = TimeZone.getTimeZone("PST");
+ if (tz != null)
+ logln("getTimeZone(PST) = " + tz.getID());
+ else
+ errln("FAIL: getTimeZone(PST) = null");
+
+ tz = TimeZone.getTimeZone("America/Los_Angeles");
+ if (tz != null)
+ logln("getTimeZone(America/Los_Angeles) = " + tz.getID());
+ else
+ errln("FAIL: getTimeZone(PST) = null");
+
+ // Bug 4096694
+ tz = TimeZone.getTimeZone("NON_EXISTENT");
+ if (tz == null)
+ errln("FAIL: getTimeZone(NON_EXISTENT) = null");
+ else if (!tz.getID().equals("GMT"))
+ errln("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID());
+ }
+
+ /**
+ * Bug 4107276
+ */
+ public void TestDSTSavings() {
+ // It might be better to find a way to integrate this test into the main TimeZone
+ // tests above, but I don't have time to figure out how to do this (or if it's
+ // even really a good idea). Let's consider that a future. --rtg 1/27/98
+ SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest",
+ Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0,
+ (int)(0.5 * millisPerHour));
+
+ if (tz.getRawOffset() != -5 * millisPerHour)
+ errln("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) +
+ " hours instead of -5 hours.");
+ if (!tz.useDaylightTime())
+ errln("Test time zone should use DST but claims it doesn't.");
+ if (tz.getDSTSavings() != 0.5 * millisPerHour)
+ errln("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() /
+ millisPerHour) + " hours instead.");
+
+ int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
+ Calendar.THURSDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
+ 10 * millisPerHour);
+ if (offset != -4.5 * millisPerHour)
+ errln("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ tz.setDSTSavings(millisPerHour);
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1,
+ Calendar.THURSDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY,
+ 10 * millisPerHour);
+ if (offset != -4 * millisPerHour)
+ errln("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+ }
+
+ /**
+ * Bug 4107570
+ */
+ public void TestAlternateRules() {
+ // Like TestDSTSavings, this test should probably be integrated somehow with the main
+ // test at the top of this class, but I didn't have time to figure out how to do that.
+ // --rtg 1/28/98
+
+ SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest");
+
+ // test the day-of-month API
+ tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour);
+ tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour);
+
+ int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5,
+ Calendar.THURSDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10AM, 3/5/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15,
+ Calendar.SUNDAY, 10 * millisPerHour);
+ if (offset != -4 * millisPerHour)
+ errln("The offset for 10AM, 3/15/98 should have been -4 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
+ Calendar.THURSDAY, 10 * millisPerHour);
+ if (offset != -4 * millisPerHour)
+ errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25,
+ Calendar.SUNDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10AM, 10/25/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ // test the day-of-week-after-day-in-month API
+ tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true);
+ tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false);
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11,
+ Calendar.WEDNESDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10AM, 3/11/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14,
+ Calendar.SATURDAY, 10 * millisPerHour);
+ if (offset != -4 * millisPerHour)
+ errln("The offset for 10AM, 3/14/98 should have been -4 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15,
+ Calendar.THURSDAY, 10 * millisPerHour);
+ if (offset != -4 * millisPerHour)
+ errln("The offset for 10AM, 10/15/98 should have been -4 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+
+ offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17,
+ Calendar.SATURDAY, 10 * millisPerHour);
+ if (offset != -5 * millisPerHour)
+ errln("The offset for 10AM, 10/17/98 should have been -5 hours, but we got "
+ + (offset / millisPerHour) + " hours.");
+ }
+}
+
+//eof
diff --git a/test/java/util/TimeZone/TransitionTest.java b/test/java/util/TimeZone/TransitionTest.java
new file mode 100644
index 0000000000..5f012d09d7
--- /dev/null
+++ b/test/java/util/TimeZone/TransitionTest.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4278609 4761696
+ * @library /java/text/testlib
+ * @summary Make sure to handle DST transition ending at 0:00 January 1.
+ */
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.SimpleTimeZone;
+import java.util.TimeZone;
+
+public class TransitionTest extends IntlTest {
+
+ public static void main(String[] args) throws Exception {
+ new TransitionTest().run(args);
+ }
+
+ public void Test4278609() {
+ SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone",
+ /* DST start day: August, 1, 0:00 */
+ Calendar.AUGUST, 1, 0, 0,
+ /* DST end day: January, 1, 0:00 (wall-clock)*/
+ Calendar.JANUARY, 1, 0, 0,
+ 60 * 60 * 1000);
+
+ Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+
+ // setting a date using GMT zone just after the end rule of tz zone
+ cal.clear();
+ cal.set(Calendar.ERA, GregorianCalendar.AD);
+ cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00);
+
+ Date date = cal.getTime();
+
+ int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000
+ + cal.get(Calendar.MINUTE) * 60000
+ + cal.get(Calendar.SECOND) * 1000
+ + cal.get(Calendar.MILLISECOND);
+ /* we must use standard local time */
+ millis += tz.getRawOffset();
+
+ int offset = tz.getOffset(cal.get(Calendar.ERA),
+ cal.get(Calendar.YEAR),
+ cal.get(Calendar.MONTH),
+ cal.get(Calendar.DATE),
+ cal.get(Calendar.DAY_OF_WEEK),
+ millis);
+
+ if (offset != 0) {
+ SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz",
+ Locale.US);
+ format.setTimeZone(tz);
+ errln("Wrong DST transition: " + tz
+ + "\na date just after DST = " + format.format(date)
+ + "\ngetOffset = " + offset);
+ }
+ }
+
+ /*
+ * 4761696: Rewrite SimpleTimeZone to support correct DST transitions
+ *
+ * Derived from JCK test cases some of which specify wrong day of week values.
+ */
+ public void Test4761696() {
+ GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+
+ // test#1
+ int rawOffset = -43200000;
+ int saving = 1800000;
+ int timeOfDay = 84600001;
+ SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.JULY, 1, 0, 0,
+ Calendar.JANUARY, 1, 0, 0,
+ saving);
+ int year = Integer.MIN_VALUE;
+ tz.setStartYear(year);
+ int offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.DECEMBER,
+ 31,
+ 1, // should be SATURDAY
+ timeOfDay);
+ int y = (int) mod((long)year, 28L); // 28-year cycle
+ cal.clear();
+ cal.set(cal.ERA, cal.AD);
+ cal.set(y, Calendar.DECEMBER, 31);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ long localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(cal.ERA, cal.AD);
+ cal.set(y + 1, Calendar.JANUARY, 1);
+ cal.set(cal.MILLISECOND, -saving);
+ long endTime = cal.getTimeInMillis() + rawOffset;
+ long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("test#1: wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+
+ // test#2
+ saving = 1;
+ timeOfDay = 0;
+ tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.JULY, 1, 0, 0,
+ Calendar.JANUARY, 1, 0, 0,
+ saving);
+ tz.setStartYear(year);
+ offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.AUGUST,
+ 15,
+ 1, // should be MONDAY
+ timeOfDay);
+ y = (int) mod((long)year, 28L); // 28-year cycle
+ cal.clear();
+ cal.set(y, Calendar.AUGUST, 15);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(y + 1, Calendar.JANUARY, 1);
+ cal.set(cal.MILLISECOND, -saving);
+ endTime = cal.getTimeInMillis() + rawOffset;
+ expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("Wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+
+ rawOffset = 43200000;
+ saving = 1;
+ timeOfDay = 3599998;
+ tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.JULY, 1, 0, 3600000,
+ Calendar.JANUARY, 1, 0, 3600000,
+ saving);
+ tz.setStartYear(year);
+ offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.JANUARY,
+ 1,
+ 1,
+ timeOfDay);
+ y = (int) mod((long)year, 28L); // 28-year cycle
+ cal.clear();
+ cal.set(y, Calendar.JANUARY, 1);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(y + 1, Calendar.JANUARY, 1);
+ cal.set(cal.MILLISECOND, 3600000-saving);
+ endTime = cal.getTimeInMillis() + rawOffset;
+ expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("test#2: wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+
+ // test#3
+ rawOffset = -43200000;
+ saving = 1800000;
+ timeOfDay = 84600001;
+ tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.SEPTEMBER, 1, 0, 0,
+ Calendar.MARCH, 1, 0, 0,
+ saving);
+ tz.setStartYear(year);
+ offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.FEBRUARY,
+ 28,
+ 1,
+ timeOfDay);
+ y = (int) mod((long)year, 28L); // 28-year cycle
+ cal.clear();
+ cal.set(y, Calendar.FEBRUARY, 28);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(y, Calendar.MARCH, 1);
+ cal.set(cal.MILLISECOND, -saving);
+ endTime = cal.getTimeInMillis() + rawOffset;
+ expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("test#3: wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+
+ // test#4
+ rawOffset = -43200000;
+ saving = 1;
+ timeOfDay = 0;
+ tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.JANUARY, -4, 1, 3600000,
+ Calendar.JULY, -4, 1, 3600000,
+ saving);
+ tz.setStartYear(year);
+ offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.JANUARY,
+ 10,
+ 2, // should be 1 (SUNDAY)
+ timeOfDay);
+ y = (int) mod((long)year, 28L); // 28-year cycle
+ cal.clear();
+ cal.set(y, Calendar.JANUARY, 10);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(cal.YEAR, y);
+ cal.set(cal.MONTH, Calendar.JANUARY);
+ cal.set(cal.DAY_OF_MONTH, 8);
+ cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1);
+ cal.set(cal.DAY_OF_WEEK, 1);
+ cal.set(cal.MILLISECOND, 3600000-saving);
+ long startTime = cal.getTimeInMillis() + rawOffset;
+ expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("test#4: wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+
+ // test#5
+ rawOffset = 0;
+ saving = 3600000;
+ timeOfDay = 7200000;
+ year = 1982;
+ tz = new SimpleTimeZone(rawOffset, "stz",
+ Calendar.APRIL, 1, 0, 7200000,
+ Calendar.OCTOBER, 10, 0, 7200000,
+ saving);
+ offset = tz.getOffset(GregorianCalendar.AD,
+ year,
+ Calendar.OCTOBER,
+ 10,
+ 1,
+ timeOfDay);
+ cal.clear();
+ cal.set(year, Calendar.OCTOBER, 10);
+ cal.set(cal.MILLISECOND, timeOfDay);
+ localtime = cal.getTimeInMillis() + rawOffset; // local standard time
+
+ cal.clear();
+ cal.set(year, Calendar.OCTOBER, 10);
+ cal.set(cal.MILLISECOND, 7200000-saving);
+ endTime = cal.getTimeInMillis() + rawOffset;
+ expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
+ if (offset != expectedOffset) {
+ errln("test#5: wrong offset: got "+offset+", expected="+expectedOffset);
+ }
+ }
+
+ public static final long floorDivide(long n, long d) {
+ return ((n >= 0) ?
+ (n / d) : (((n + 1L) / d) - 1L));
+ }
+
+ public static final long mod(long x, long y) {
+ return (x - y * floorDivide(x, y));
+ }
+}
diff --git a/test/java/util/TimeZone/UTCAliasTest.java b/test/java/util/TimeZone/UTCAliasTest.java
new file mode 100644
index 0000000000..aa7079326c
--- /dev/null
+++ b/test/java/util/TimeZone/UTCAliasTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2005, 2016, 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 6282072
+ * @summary Make sure that "UTC" is an alias of "Etc/UTC" as defined in the tzdata backward.
+ * @modules java.base/sun.util.calendar
+ * @compile -XDignore.symbol.file UTCAliasTest.java
+ */
+
+import java.util.*;
+import sun.util.calendar.ZoneInfo;
+
+public class UTCAliasTest {
+ public static void main(String[] args) {
+ Map<String,String> map = ZoneInfo.getAliasTable();
+ String alias = map.get("UTC");
+ if (!alias.equals("Etc/UTC")) {
+ throw new RuntimeException("got " + alias + ", expected Etc/UTC");
+ }
+ TimeZone GMT = TimeZone.getTimeZone("GMT");
+ TimeZone UTC = TimeZone.getTimeZone("UTC");
+ if (!GMT.hasSameRules(UTC)) {
+ throw new RuntimeException("GMT and UTC have different rules");
+ }
+ TimeZone EtcUTC = TimeZone.getTimeZone("Etc/UTC");
+ if (!UTC.hasSameRules(EtcUTC)) {
+ throw new RuntimeException("UTC and Etc/UTC have different rules");
+ }
+ }
+}
diff --git a/test/java/util/TimeZone/bug4096952.java b/test/java/util/TimeZone/bug4096952.java
new file mode 100644
index 0000000000..20ccc685ac
--- /dev/null
+++ b/test/java/util/TimeZone/bug4096952.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1998, 2016, 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 4096952
+ * @summary simple serialization/deserialization test
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.TimeZone;
+
+public class bug4096952 {
+
+ public static void main(String[] args) {
+ int errors = 0;
+ String[] ZONES = { "GMT", "MET", "IST" };
+ for (String id : ZONES) {
+ TimeZone zone = TimeZone.getTimeZone(id);
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try (ObjectOutputStream ostream = new ObjectOutputStream(baos)) {
+ ostream.writeObject(zone);
+ }
+ try (ObjectInputStream istream
+ = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()))) {
+ if (!zone.equals(istream.readObject())) {
+ errors++;
+ System.out.println("Time zone " + id + " are not equal to serialized/deserialized one.");
+ } else {
+ System.out.println("Time zone " + id + " ok.");
+ }
+ }
+ } catch (IOException | ClassNotFoundException e) {
+ errors++;
+ System.out.println(e);
+ }
+ }
+ if (errors > 0) {
+ throw new RuntimeException("test failed");
+ }
+ }
+}
diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CustomFJPoolTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CustomFJPoolTest.java
new file mode 100644
index 0000000000..e2846bf883
--- /dev/null
+++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CustomFJPoolTest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2017, 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 org.openjdk.tests.java.util.stream;
+
+import org.testng.annotations.Test;
+
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Tests stream execution in a custom ForkJoinPool. See JDK-8190974.
+ */
+@Test
+public class CustomFJPoolTest {
+
+ // A Spliterator that counts the number of spliterators created
+ // including itself, thus the count starts at 1
+ static class SplitCountingSpliterator<T> implements Spliterator<T> {
+ final Spliterator<T> s;
+ final AtomicInteger nsplits;
+
+ // Top-level constructor
+ public SplitCountingSpliterator(Spliterator<T> s) {
+ this.s = s;
+ nsplits = new AtomicInteger(1);
+ }
+
+ // Splitting constructor
+ SplitCountingSpliterator(Spliterator<T> s, AtomicInteger nsplits) {
+ this.s = s;
+ this.nsplits = nsplits;
+ }
+
+ int splits() {
+ return nsplits.get();
+ }
+
+ @Override
+
+ public boolean tryAdvance(Consumer<? super T> action) {
+ return s.tryAdvance(action);
+ }
+
+ @Override
+ public void forEachRemaining(Consumer<? super T> action) {
+ s.forEachRemaining(action);
+ }
+
+ @Override
+ public Spliterator<T> trySplit() {
+ Spliterator<T> split = s.trySplit();
+ if (split != null) {
+ nsplits.incrementAndGet();
+ return new SplitCountingSpliterator<>(split, nsplits);
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public long estimateSize() {
+ return s.estimateSize();
+ }
+
+ @Override
+ public long getExactSizeIfKnown() {
+ return s.getExactSizeIfKnown();
+ }
+
+ @Override
+ public int characteristics() {
+ return s.characteristics();
+ }
+
+ @Override
+ public boolean hasCharacteristics(int characteristics) {
+ return s.hasCharacteristics(characteristics);
+ }
+
+ @Override
+ public Comparator<? super T> getComparator() {
+ return s.getComparator();
+ }
+ }
+
+ public void testCustomPools() throws Exception {
+ int splitsForP1 = countSplits(new ForkJoinPool(1));
+ int splitsForP2 = countSplits(new ForkJoinPool(2));
+ assertEquals(splitsForP2, splitsForP1 * 2);
+
+ int commonParallelism = ForkJoinPool.getCommonPoolParallelism();
+ if (commonParallelism > 1 && commonParallelism < 128) {
+ int splitsForPHalfC = countSplits(new ForkJoinPool(commonParallelism / 2));
+ int splitsForPC = countSplits(ForkJoinPool.commonPool());
+
+ assertTrue(splitsForPHalfC < splitsForPC);
+ assertEquals(splitsForPC / splitsForPHalfC,
+ nearestPowerOfTwo(commonParallelism) / nearestPowerOfTwo(commonParallelism / 2));
+ }
+ }
+
+ static int countSplits(ForkJoinPool fjp) throws Exception {
+ // The number of splits will be equivalent to the number of leaf nodes
+ // and will be a power of 2
+ ForkJoinTask<Integer> fInteger = fjp.submit(() -> {
+ Spliterator<Integer> s = IntStream.range(0, 1024).boxed().parallel().spliterator();
+ SplitCountingSpliterator<Integer> cs = new SplitCountingSpliterator<>(s);
+ StreamSupport.stream(cs, true).forEach(e -> {});
+ return cs.splits();
+ });
+ return fInteger.get();
+ }
+
+ static int nearestPowerOfTwo(int i) {
+ return (i & (i - 1)) == 0
+ ? i
+ : 1 << (32 - Integer.numberOfLeadingZeros(i));
+ }
+}
diff --git a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java
index 0abe67e4d4..3074e07229 100644
--- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java
+++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, 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
@@ -24,7 +24,7 @@
/*
* @test
* @summary flat-map operations
- * @bug 8044047 8076458
+ * @bug 8044047 8076458 8075939
*/
package org.openjdk.tests.java.util.stream;
@@ -36,6 +36,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.function.Function;
import java.util.stream.*;
+import java.util.concurrent.atomic.AtomicInteger;
import static java.util.stream.LambdaTestHelpers.*;
import static java.util.stream.ThowableHelper.checkNPE;
@@ -43,6 +44,7 @@ import static java.util.stream.ThowableHelper.checkNPE;
@Test
public class FlatMapOpTest extends OpTestCase {
+ @Test
public void testNullMapper() {
checkNPE(() -> Stream.of(1).flatMap(null));
checkNPE(() -> IntStream.of(1).flatMap(null));
@@ -53,6 +55,7 @@ public class FlatMapOpTest extends OpTestCase {
static final Function<Integer, Stream<Integer>> integerRangeMapper
= e -> IntStream.range(0, e).boxed();
+ @Test
public void testFlatMap() {
String[] stringsArray = {"hello", "there", "", "yada"};
Stream<String> strings = Arrays.asList(stringsArray).stream();
@@ -85,11 +88,24 @@ public class FlatMapOpTest extends OpTestCase {
exerciseOps(data, s -> s.flatMap((Integer e) -> IntStream.range(0, e).boxed().limit(10)));
}
+ @Test
+ public void testOpsShortCircuit() {
+ AtomicInteger count = new AtomicInteger();
+ Stream.of(0).flatMap(i -> IntStream.range(0, 100).boxed()).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+ }
+
//
@Test(dataProvider = "IntStreamTestData", dataProviderClass = IntStreamTestDataProvider.class)
public void testIntOps(String name, TestData.OfInt data) {
- Collection<Integer> result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToInt(j -> j)));
+ Collection<Integer> result = exerciseOps(data, s -> s.flatMap(IntStream::of));
+ assertEquals(data.size(), result.size());
+ assertContents(data, result);
+
+ result = exerciseOps(data, s -> s.boxed().flatMapToInt(IntStream::of));
assertEquals(data.size(), result.size());
assertContents(data, result);
@@ -101,13 +117,35 @@ public class FlatMapOpTest extends OpTestCase {
public void testIntOpsX(String name, TestData.OfInt data) {
exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e)));
exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, e).limit(10)));
+
+ exerciseOps(data, s -> s.boxed().flatMapToInt(e -> IntStream.range(0, e)));
+ exerciseOps(data, s -> s.boxed().flatMapToInt(e -> IntStream.range(0, e).limit(10)));
+ }
+
+ @Test
+ public void testIntOpsShortCircuit() {
+ AtomicInteger count = new AtomicInteger();
+ IntStream.of(0).flatMap(i -> IntStream.range(0, 100)).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+
+ count.set(0);
+ Stream.of(0).flatMapToInt(i -> IntStream.range(0, 100)).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
}
//
@Test(dataProvider = "LongStreamTestData", dataProviderClass = LongStreamTestDataProvider.class)
public void testLongOps(String name, TestData.OfLong data) {
- Collection<Long> result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToLong(j -> j)));
+ Collection<Long> result = exerciseOps(data, s -> s.flatMap(LongStream::of));
+ assertEquals(data.size(), result.size());
+ assertContents(data, result);
+
+ result = exerciseOps(data, s -> s.boxed().flatMapToLong(LongStream::of));
assertEquals(data.size(), result.size());
assertContents(data, result);
@@ -121,11 +159,30 @@ public class FlatMapOpTest extends OpTestCase {
exerciseOps(data, s -> s.flatMap(e -> LongStream.range(0, e).limit(10)));
}
+ @Test
+ public void testLongOpsShortCircuit() {
+ AtomicInteger count = new AtomicInteger();
+ LongStream.of(0).flatMap(i -> LongStream.range(0, 100)).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+
+ count.set(0);
+ Stream.of(0).flatMapToLong(i -> LongStream.range(0, 100)).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+ }
+
//
@Test(dataProvider = "DoubleStreamTestData", dataProviderClass = DoubleStreamTestDataProvider.class)
public void testDoubleOps(String name, TestData.OfDouble data) {
- Collection<Double> result = exerciseOps(data, s -> s.flatMap(i -> Collections.singleton(i).stream().mapToDouble(j -> j)));
+ Collection<Double> result = exerciseOps(data, s -> s.flatMap(DoubleStream::of));
+ assertEquals(data.size(), result.size());
+ assertContents(data, result);
+
+ result = exerciseOps(data, s -> s.boxed().flatMapToDouble(DoubleStream::of));
assertEquals(data.size(), result.size());
assertContents(data, result);
@@ -138,4 +195,19 @@ public class FlatMapOpTest extends OpTestCase {
exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).asDoubleStream()));
exerciseOps(data, s -> s.flatMap(e -> IntStream.range(0, (int) e).limit(10).asDoubleStream()));
}
+
+ @Test
+ public void testDoubleOpsShortCircuit() {
+ AtomicInteger count = new AtomicInteger();
+ DoubleStream.of(0).flatMap(i -> IntStream.range(0, 100).asDoubleStream()).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+
+ count.set(0);
+ Stream.of(0).flatMapToDouble(i -> IntStream.range(0, 100).asDoubleStream()).
+ peek(i -> count.incrementAndGet()).
+ limit(10).toArray();
+ assertEquals(count.get(), 10);
+ }
}
diff --git a/test/java/util/zip/ZipFile/MultiThreadedReadTest.java b/test/java/util/zip/ZipFile/MultiThreadedReadTest.java
index d4cbd5384d..c68cfe3864 100644
--- a/test/java/util/zip/ZipFile/MultiThreadedReadTest.java
+++ b/test/java/util/zip/ZipFile/MultiThreadedReadTest.java
@@ -29,11 +29,13 @@
* @run main MultiThreadedReadTest
*/
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.Random;
+import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
@@ -42,7 +44,8 @@ import jdk.testlibrary.FileUtils;
public class MultiThreadedReadTest extends Thread {
private static final int NUM_THREADS = 10;
- private static final String ZIPFILE_NAME = "large.zip";
+ private static final String ZIPFILE_NAME =
+ System.currentTimeMillis() + "-bug8038491-tmp.large.zip";
private static final String ZIPENTRY_NAME = "random.txt";
private static InputStream is = null;
@@ -61,23 +64,34 @@ public class MultiThreadedReadTest extends Thread {
threadArray[i].join();
}
} finally {
+ long t = System.currentTimeMillis();
FileUtils.deleteFileIfExistsWithRetry(Paths.get(ZIPFILE_NAME));
+ System.out.println("Deleting zip file took:" +
+ (System.currentTimeMillis() - t) + "ms");
}
}
private static void createZipFile() throws Exception {
- try (ZipOutputStream zos =
- new ZipOutputStream(new FileOutputStream(ZIPFILE_NAME))) {
-
- zos.putNextEntry(new ZipEntry(ZIPENTRY_NAME));
- StringBuilder sb = new StringBuilder();
- Random rnd = new Random();
- for(int i = 0; i < 1000; i++) {
- // append some random string for ZipEntry
- sb.append(Long.toString(rnd.nextLong()));
+ CRC32 crc32 = new CRC32();
+ long t = System.currentTimeMillis();
+ File zipFile = new File(ZIPFILE_NAME);
+ try (FileOutputStream fos = new FileOutputStream(zipFile);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ ZipOutputStream zos = new ZipOutputStream(bos)) {
+ ZipEntry e = new ZipEntry(ZIPENTRY_NAME);
+ e.setMethod(ZipEntry.STORED);
+ StringBuilder blahBuilder = new StringBuilder();
+ for (int i = 0; i < 10_000; i++) {
+ blahBuilder.append("BLAH");
}
- byte[] b = sb.toString().getBytes();
- zos.write(b, 0, b.length);
+ byte[] toWrite = blahBuilder.toString().getBytes();
+ e.setTime(t);
+ e.setSize(toWrite.length);
+ crc32.reset();
+ crc32.update(toWrite);
+ e.setCrc(crc32.getValue());
+ zos.putNextEntry(e);
+ zos.write(toWrite);
}
}
@@ -86,6 +100,7 @@ public class MultiThreadedReadTest extends Thread {
try {
while (is.read() != -1) { }
} catch (Exception e) {
+ System.out.println("read exception:" + e);
// Swallow any Exceptions (which are expected) - we're only interested in the crash
}
}
diff --git a/test/javax/accessibility/SlowPanelIteration/SlowPanelIteration.java b/test/javax/accessibility/SlowPanelIteration/SlowPanelIteration.java
index 2e42f8fa14..daf2f1c0cb 100644
--- a/test/javax/accessibility/SlowPanelIteration/SlowPanelIteration.java
+++ b/test/javax/accessibility/SlowPanelIteration/SlowPanelIteration.java
@@ -104,4 +104,4 @@ public final class SlowPanelIteration {
frame.dispose();
}
}
-} \ No newline at end of file
+}
diff --git a/test/javax/crypto/Cipher/EmptyFinalBuffer.java b/test/javax/crypto/Cipher/EmptyFinalBuffer.java
new file mode 100644
index 0000000000..6479a44a8d
--- /dev/null
+++ b/test/javax/crypto/Cipher/EmptyFinalBuffer.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, 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 6946830
+ * @summary Test the Cipher.doFinal() with 0-length buffer
+ * @key randomness
+ */
+
+import java.util.*;
+import java.nio.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class EmptyFinalBuffer {
+
+ private static final String[] ALGOS = {
+ "AES/ECB/PKCS5Padding", "AES/CBC/PKCS5Padding"
+ };
+
+ public static void main(String[] args) throws Exception {
+
+ Provider[] provs = Security.getProviders();
+
+ SecretKey key = new SecretKeySpec(new byte[16], "AES");
+
+ boolean testFailed = false;
+ for (Provider p : provs) {
+ System.out.println("Testing: " + p.getName());
+ for (String algo : ALGOS) {
+ System.out.print("Algo: " + algo);
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algo, p);
+ } catch (NoSuchAlgorithmException nsae) {
+ // skip
+ System.out.println("=> No Support");
+ continue;
+ }
+ c.init(Cipher.ENCRYPT_MODE, key);
+ AlgorithmParameters params = c.getParameters();
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ try {
+ byte[] out = c.doFinal(new byte[0]);
+ System.out.println("=> Accepted w/ " +
+ (out == null? "null" : (out.length + "-byte")) +
+ " output");
+ } catch (Exception e) {
+ testFailed = true;
+ System.out.println("=> Rejected w/ Exception");
+ e.printStackTrace();
+ }
+ }
+ }
+ if (testFailed) {
+ throw new Exception("One or more tests failed");
+ } else {
+ System.out.println("All tests passed");
+ }
+ }
+}
diff --git a/test/javax/imageio/plugins/jpeg/JpegTablesOnlyReadTest.java b/test/javax/imageio/plugins/jpeg/JpegTablesOnlyReadTest.java
new file mode 100644
index 0000000000..2393da3c25
--- /dev/null
+++ b/test/javax/imageio/plugins/jpeg/JpegTablesOnlyReadTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, 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 8191073
+ * @summary Test verifies that when user tries to read image data from a
+ * tables-only image input stream it should through IIOException
+ * instead of throwing any other exception as per specification.
+ * @run main JpegTablesOnlyReadTest
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Base64;
+import javax.imageio.IIOException;
+import javax.imageio.ImageIO;
+
+public class JpegTablesOnlyReadTest {
+ // JPEG input stream containing tables-only image
+ private static String inputImageBase64 = "/9j/4IAQSkZJRgABAQEASABIAAD"
+ + "/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI//////////////////////"
+ + "//////////////////////////////2wBDAVVaWnhpeOuCguv//////////////"
+ + "///////////////////////////////////////////////////////////wAAR"
+ + "CAAgACADASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECA//EACUQAQA"
+ + "CAAUDBAMAAAAAAAAAAAEAAhESITGxQXKSA2Fi0SIyUf/EABYBAQEBAAAAAAAAAA"
+ + "AAAAAAAAABA//EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAMAwEAAhEDEQA/A"
+ + "Nf2VW2OKaWTqnRhl97eb9wrs91uWPEBUX+EtmrssvvbzfuJWjVG2tg1svLLtgJ0"
+ + "Uxwmd96d5zE7tVdnutyxm5JVoo0u6rpXHdWLP8PU8WIjtRuvVZN96d5zDP8AD1P"
+ + "Fhre1Apc/Ida4RAdv/9k=";
+
+ public static void main(String[] args) throws IOException {
+ byte[] inputBytes = Base64.getDecoder().decode(inputImageBase64);
+ InputStream in = new ByteArrayInputStream(inputBytes);
+
+ // Read tables-only JPEG image
+ try {
+ ImageIO.read(in);
+ } catch (IIOException e) {
+ // do nothing we expect it to throw IIOException if it throws
+ // any other exception test will fail.
+ }
+ }
+}
+
diff --git a/test/javax/imageio/stream/NullStreamCheckTest.java b/test/javax/imageio/stream/NullStreamCheckTest.java
new file mode 100644
index 0000000000..f763b9de1e
--- /dev/null
+++ b/test/javax/imageio/stream/NullStreamCheckTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, 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 8044289
+ * @summary Test verifies that when some of the read() and write() methods
+ * are not able to get stream from createImageInputStream() and
+ * createImageOutputStream() are we doing null check for stream
+ * and throwing IOException as per specification.
+ * @run main NullStreamCheckTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import javax.imageio.ImageIO;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageInputStreamSpi;
+import javax.imageio.spi.ImageOutputStreamSpi;
+
+public class NullStreamCheckTest {
+
+ // get ImageIORegistry default instance.
+ private static final IIORegistry localRegistry = IIORegistry.
+ getDefaultInstance();
+ // stream variables needed for input and output.
+ static LocalOutputStream outputStream = new LocalOutputStream();
+ static LocalInputStream inputStream = new LocalInputStream();
+
+ static final int width = 50, height = 50;
+
+ // input and output BufferedImage needed while read and write.
+ static BufferedImage inputImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_ARGB);
+
+ // creates test file needed for read and write in local directory.
+ private static File createTestFile(String name) throws IOException {
+ String sep = System.getProperty("file.separator");
+ String dir = System.getProperty("test.src", ".");
+ String filePath = dir+sep;
+ File directory = new File(filePath);
+ File tmpTestFile = File.createTempFile(name, ".png", directory);
+ directory.delete();
+ return tmpTestFile;
+ }
+
+ /* if we catch expected IOException message return
+ * false otherwise return true.
+ */
+ private static boolean verifyOutputExceptionMessage(IOException ex) {
+ String message = ex.getMessage();
+ return (!message.equals("Can't create an ImageOutputStream!"));
+ }
+
+ /* if we catch expected IOException message return
+ * false otherwise return true.
+ */
+ private static boolean verifyInputExceptionMessage(IOException ex) {
+ String message = ex.getMessage();
+ return (!message.equals("Can't create an ImageInputStream!"));
+ }
+
+ private static void verifyFileWrite() throws IOException {
+ File outputTestFile = createTestFile("outputTestFile");
+ try {
+ ImageIO.write(inputImage, "png", outputTestFile);
+ } catch (IOException ex) {
+ if (verifyOutputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ outputTestFile.delete();
+ }
+ }
+
+ private static void verifyStreamWrite() throws IOException {
+ try {
+ ImageIO.write(inputImage, "png", outputStream);
+ } catch (IOException ex) {
+ if (verifyOutputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ try {
+ outputStream.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+ }
+
+ private static void verifyFileRead() throws IOException {
+ File inputTestFile = createTestFile("inputTestFile");
+ try {
+ ImageIO.read(inputTestFile);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ inputTestFile.delete();
+ }
+ }
+
+ private static void verifyStreamRead() throws IOException {
+ try {
+ ImageIO.read(inputStream);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException ex) {
+ throw ex;
+ }
+ }
+ }
+
+ private static void verifyUrlRead() throws IOException {
+ URL url;
+ File inputTestUrlFile = createTestFile("inputTestFile");
+ try {
+ try {
+ url = inputTestUrlFile.toURI().toURL();
+ } catch (MalformedURLException ex) {
+ throw ex;
+ }
+
+ try {
+ ImageIO.read(url);
+ } catch (IOException ex) {
+ if (verifyInputExceptionMessage(ex))
+ throw ex;
+ }
+ } finally {
+ inputTestUrlFile.delete();
+ }
+ }
+
+ public static void main(String[] args) throws IOException,
+ MalformedURLException {
+
+ /* deregister ImageOutputStreamSpi so that we creatImageOutputStream
+ * returns null while writing.
+ */
+ localRegistry.deregisterAll(ImageOutputStreamSpi.class);
+ /* verify possible ImageIO.write() scenario's for null stream output
+ * from createImageOutputStream() API in ImageIO class.
+ */
+ verifyFileWrite();
+ verifyStreamWrite();
+
+ /* deregister ImageInputStreamSpi so that we creatImageInputStream
+ * returns null while reading.
+ */
+ localRegistry.deregisterAll(ImageInputStreamSpi.class);
+ /* verify possible ImageIO.read() scenario's for null stream output
+ * from createImageInputStream API in ImageIO class.
+ */
+ verifyFileRead();
+ verifyStreamRead();
+ verifyUrlRead();
+ }
+
+ static class LocalOutputStream extends OutputStream {
+
+ @Override
+ public void write(int i) throws IOException {
+ }
+ }
+
+ static class LocalInputStream extends InputStream {
+
+ @Override
+ public int read() throws IOException {
+ return 0;
+ }
+ }
+}
diff --git a/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java b/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java
index 9850aa2ba5..dfe87ba8a6 100644
--- a/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java
+++ b/test/javax/swing/JComboBox/8033069/bug8033069NoScrollBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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 javax.swing.UnsupportedLookAndFeelException;
public class bug8033069NoScrollBar implements Runnable {
private static final String[] NO_SCROLL_ITEMS = new String[] {
- "A", "B", "C", "D", "E", "F"
+ "AA", "B", "C", "D", "E", "F"
};
private final Robot robot;
@@ -110,6 +110,7 @@ public class bug8033069NoScrollBar implements Runnable {
// Move mouse pointer to the center of the fist combo box
Point p = cb1.getLocationOnScreen();
Dimension d = cb1.getSize();
+ System.out.println(d.width + "," + d.height);
robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
// Click it to open popup
robot.mousePress(InputEvent.BUTTON1_MASK);
diff --git a/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java b/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java
index fed71e654b..7644c80ab2 100644
--- a/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java
+++ b/test/javax/swing/JComboBox/8033069/bug8033069ScrollBar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@ import java.awt.AWTException;
public class bug8033069ScrollBar extends bug8033069NoScrollBar {
private static final String[] SCROLL_ITEMS = new String[] {
- "A", "B", "C", "D", "E", "F",
+ "AA", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "L",
"M", "N", "O", "P", "Q", "R"
};
diff --git a/test/javax/swing/SwingUtilities/TestTextPosInPrint.java b/test/javax/swing/SwingUtilities/TestTextPosInPrint.java
new file mode 100644
index 0000000000..8a41dc2dfa
--- /dev/null
+++ b/test/javax/swing/SwingUtilities/TestTextPosInPrint.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2019, 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 8214702
+ @summary Verifies text position for whitespaced string in printing Swing text
+ @run main/manual TestTextPosInPrint
+ */
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Font;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.print.Printable;
+import java.awt.print.PageFormat;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JFrame;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.WindowConstants;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+
+public class TestTextPosInPrint implements Printable {
+ private static final CountDownLatch testEndedSignal = new CountDownLatch(1);
+ private static final int testTimeout = 300000;
+ private static volatile String testFailureMsg;
+ private static volatile boolean testPassed;
+ private static volatile boolean testFinished;
+ private static PrinterJob job;
+ private static JPanel panel;
+ private static JFrame f;
+
+ public static void main(String[] args) throws Exception {
+ job = PrinterJob.getPrinterJob();
+ if (job.getPrintService() == null) {
+ System.out.println("This test requires printers to be installed. Exiting.");
+ return;
+ }
+ SwingUtilities.invokeLater(() -> createAndShowTestDialog());
+
+ try {
+ if (!testEndedSignal.await(testTimeout, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException(String.format(
+ "Test timeout '%d ms' elapsed.", testTimeout));
+ }
+ if (!testPassed) {
+ String failureMsg = testFailureMsg;
+ if ((failureMsg != null) && (!failureMsg.trim().isEmpty())) {
+ throw new RuntimeException(failureMsg);
+ } else {
+ throw new RuntimeException("Test failed.");
+ }
+ }
+ } catch (InterruptedException ie) {
+ throw new RuntimeException(ie);
+ } finally {
+ testFinished = true;
+ SwingUtilities.invokeAndWait(() -> f.dispose());
+ }
+ }
+
+ private static void doTest() throws Exception {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ f = new JFrame();
+ f.setLocationRelativeTo(null);
+ panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ Font font = new Font("Serif", Font.PLAIN, 12);
+ JLabel l1 = new JLabel(" 1. ABCDE");
+ l1.setHorizontalAlignment(SwingConstants.LEFT);
+ JLabel l2 = new JLabel(" 2. ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ l2.setHorizontalAlignment(SwingConstants.LEFT);
+ //JLabel l3 = new JLabel(" 3. ABCDE ");
+ JLabel l3 = new JLabel(" 3. ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ l3.setHorizontalAlignment(SwingConstants.LEFT);
+ panel.add(BorderLayout.NORTH, l1);
+ panel.add(BorderLayout.CENTER, l2);
+ panel.add(BorderLayout.SOUTH, l3);
+ f.getContentPane().add(BorderLayout.NORTH, panel);
+ f.setSize(400, 300);
+ f.setVisible(true);
+
+ job.setPrintable(new TestTextPosInPrint());
+ if (job.printDialog()) {
+ try {
+ job.print();
+ } catch (PrinterException pe) {
+ throw new RuntimeException(pe);
+ }
+ }
+ }
+
+ private static void pass() {
+ testPassed = true;
+ testEndedSignal.countDown();
+ }
+
+ private static void fail(String failureMsg) {
+ testFailureMsg = failureMsg;
+ testPassed = false;
+ testEndedSignal.countDown();
+ }
+
+ private static String convertMillisToTimeStr(int millis) {
+ if (millis < 0) {
+ return "00:00:00";
+ }
+ int hours = millis / 3600000;
+ int minutes = (millis - hours * 3600000) / 60000;
+ int seconds = (millis - hours * 3600000 - minutes * 60000) / 1000;
+ return String.format("%02d:%02d:%02d", hours, minutes, seconds);
+ }
+
+ private static void createAndShowTestDialog() {
+ String description =
+ " 1. Click on \"Start Test\" button.\r\n" +
+ " 2. Multiple strings will be displayed on console.\r\n" +
+ " 3. A print dialog will be shown. Select any printer to print. " +
+ "\r\n" +
+ " If the printed output of the strings are same without any alignment issue, click on \"PASS\"\r\n" +
+ " button, otherwise click on \"FAIL\" button.";
+
+ final JDialog dialog = new JDialog();
+ dialog.setTitle("SaveFileWithoutPrinter");
+ dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ dialog.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ dialog.dispose();
+ fail("Main dialog was closed.");
+ }
+ });
+
+ final JLabel testTimeoutLabel = new JLabel(String.format(
+ "Test timeout: %s", convertMillisToTimeStr(testTimeout)));
+ final long startTime = System.currentTimeMillis();
+ final Timer timer = new Timer(0, null);
+ timer.setDelay(1000);
+ timer.addActionListener((e) -> {
+ int leftTime = testTimeout - (int) (System.currentTimeMillis() - startTime);
+ if ((leftTime < 0) || testFinished) {
+ timer.stop();
+ dialog.dispose();
+ }
+ testTimeoutLabel.setText(String.format(
+ "Test timeout: %s", convertMillisToTimeStr(leftTime)));
+ });
+ timer.start();
+
+ JTextArea textArea = new JTextArea(description);
+ textArea.setEditable(false);
+
+ final JButton testButton = new JButton("Start Test");
+ final JButton passButton = new JButton("PASS");
+ final JButton failButton = new JButton("FAIL");
+ testButton.addActionListener((e) -> {
+ testButton.setEnabled(false);
+ new Thread(() -> {
+ try {
+ doTest();
+
+ SwingUtilities.invokeLater(() -> {
+ passButton.setEnabled(true);
+ failButton.setEnabled(true);
+ });
+ } catch (Throwable t) {
+ t.printStackTrace();
+ dialog.dispose();
+ fail("Exception occurred in a thread executing the test.");
+ }
+ }).start();
+ });
+ passButton.setEnabled(false);
+ passButton.addActionListener((e) -> {
+ dialog.dispose();
+ pass();
+ });
+ failButton.setEnabled(false);
+ failButton.addActionListener((e) -> {
+ dialog.dispose();
+ fail("Printed texts are not aligned as shown in console");
+ });
+
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ JPanel labelPanel = new JPanel(new FlowLayout());
+ labelPanel.add(testTimeoutLabel);
+ mainPanel.add(labelPanel, BorderLayout.NORTH);
+ mainPanel.add(textArea, BorderLayout.CENTER);
+ JPanel buttonPanel = new JPanel(new FlowLayout());
+ buttonPanel.add(testButton);
+ buttonPanel.add(passButton);
+ buttonPanel.add(failButton);
+ mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+ dialog.add(mainPanel);
+
+ dialog.pack();
+ dialog.setVisible(true);
+ }
+
+ @Override
+ public int print(Graphics pg, PageFormat pf, int pageNum)
+ throws PrinterException {
+ if (pageNum > 0){
+ return Printable.NO_SUCH_PAGE;
+ }
+
+ Graphics2D g2 = (Graphics2D) pg;
+ g2.translate(pf.getImageableX(), pf.getImageableY());
+ panel.paint(g2);
+ return Printable.PAGE_EXISTS;
+ }
+}
diff --git a/test/javax/swing/text/html/8218674/TooltipImageTest.java b/test/javax/swing/text/html/8218674/TooltipImageTest.java
new file mode 100644
index 0000000000..1a1b768380
--- /dev/null
+++ b/test/javax/swing/text/html/8218674/TooltipImageTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019, 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
+ * @key headful
+ * @bug 8218674
+ * @summary Tests if Images are rendered and scaled correctly in JToolTip.
+ * @run main TooltipImageTest
+ */
+import java.awt.Dimension;
+import java.awt.Insets;
+import javax.swing.JToolTip;
+import javax.swing.SwingUtilities;
+
+public class TooltipImageTest {
+
+ private static void checkSize(JToolTip tip, int width, int height) {
+ Dimension d = tip.getPreferredSize();
+ Insets insets = tip.getInsets();
+ //6 seems to be the extra width being allocated for some reason
+ //for a tooltip window.
+ if (!((d.width - insets.right - insets.left - 6) == width) &&
+ !((d.height - insets.top - insets.bottom) == height)) {
+ throw new RuntimeException("Test case fails: Expected width, height is " + width + ", " + height +
+ " whereas actual width, height are " + (d.width - insets.right - insets.left - 6) + " " +
+ (d.height - insets.top - insets.bottom));
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ String PATH = TooltipImageTest.class.getResource("circle.png").getPath();
+ SwingUtilities.invokeAndWait(() -> {
+ JToolTip tip = new JToolTip();
+ tip.setTipText("<html><img width=\"100\" src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 100, 100);
+
+ tip.setTipText("<html><img height=\"100\" src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 100, 100);
+
+ tip.setTipText("<html><img src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 200, 200);
+
+ tip.setTipText("<html><img width=\"50\" src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 50, 50);
+
+ tip.setTipText("<html><img height=\"50\" src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 50, 50);
+
+ tip.setTipText("<html><img width=\"100\" height=\"50\" src=\"file:///" + PATH + "\"></html>");
+ checkSize(tip, 100, 50);
+ });
+
+ System.out.println("Test case passed.");
+ }
+}
diff --git a/test/javax/swing/text/html/8218674/circle.png b/test/javax/swing/text/html/8218674/circle.png
new file mode 100644
index 0000000000..614f942dc5
--- /dev/null
+++ b/test/javax/swing/text/html/8218674/circle.png
Binary files differ
diff --git a/test/javax/xml/jaxp/transform/8207760/JDK8207760.java b/test/javax/xml/jaxp/transform/8207760/JDK8207760.java
new file mode 100644
index 0000000000..5ad5f56822
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/8207760/JDK8207760.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2018, 2019, 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.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.testng.Assert;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import java.util.Random;
+import javax.xml.transform.OutputKeys;
+import org.testng.annotations.DataProvider;
+
+/*
+ * @test
+ * @run testng/othervm JDK8207760
+ * @summary Verifies that a surrogate pair at the edge of a buffer is properly handled
+ * @bug 8207760
+ */
+public class JDK8207760 {
+ final String xsl8207760 =
+ "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n" +
+ " <xsl:output omit-xml-declaration=\"yes\" indent=\"no\" />\n" +
+ "\n" +
+ " <xsl:template match=\"node()|@*\">\n" +
+ " <xsl:copy>\n" +
+ " <xsl:apply-templates select=\"node()|@*\" />\n" +
+ " </xsl:copy>\n" +
+ " </xsl:template>\n" +
+ "</xsl:stylesheet>\n";
+
+ final String xsl8207760_2 = "<xsl:stylesheet \n" +
+ " version=\"1.0\" \n" +
+ " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n" +
+ "\n" +
+ " <xsl:output method=\"xml\" indent=\"no\" cdata-section-elements=\"source\"/>\n" +
+ "\n" +
+ " <xsl:template match=\"source\">\n" +
+ " <xsl:copy>\n" +
+ " <xsl:apply-templates select=\"node()\" />\n" +
+ " </xsl:copy>\n" +
+ " </xsl:template>\n" +
+ "\n" +
+ "</xsl:stylesheet>";
+
+ final String xsl8207760_3 = "<xsl:stylesheet \n" +
+ " version=\"1.0\" \n" +
+ " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n" +
+ "\n" +
+ " <xsl:output method=\"xml\" indent=\"no\" cdata-section-elements=\"source\"/>\n" +
+ "\n" +
+ " <xsl:template match=\"source\">\n" +
+ " <xsl:copy>\n" +
+ " <!-- Copy the attributes -->\n" +
+ " <xsl:apply-templates select=\"@*\"/>\n" +
+ " <!-- Convert the contained nodes (elements and text) into text -->\n" +
+ " <xsl:variable name=\"subElementsText\">\n" +
+ " <xsl:apply-templates select=\"node()\"/>\n" +
+ " </xsl:variable>\n" +
+ " <!-- Output the XML directive and the converted nodes -->\n" +
+ " <xsl:value-of select=\"$subElementsText\"/>\n" +
+ " </xsl:copy>\n" +
+ " </xsl:template>\n" +
+ "\n" +
+ "</xsl:stylesheet>";
+
+ @DataProvider(name = "xsls")
+ public Object[][] getDataBug8207760_cdata() {
+ return new Object[][]{
+ {xsl8207760_2},
+ {xsl8207760_3},
+ };
+ }
+
+ /*
+ * @bug 8207760
+ * Verifies that a surrogate pair at the edge of a buffer is properly handled
+ * when serializing into a Character section.
+ */
+ @Test
+ public final void testBug8207760() throws Exception {
+ String[] xmls = prepareXML(false);
+ Transformer t = createTransformerFromInputstream(
+ new ByteArrayInputStream(xsl8207760.getBytes(StandardCharsets.UTF_8)));
+ t.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
+ StringWriter sw = new StringWriter();
+ t.transform(new StreamSource(new StringReader(xmls[0])), new StreamResult(sw));
+ Assert.assertEquals(sw.toString().replaceAll(System.lineSeparator(), "\n"), xmls[1]);
+ }
+
+ /*
+ * @bug 8207760
+ * Verifies that a surrogate pair at the edge of a buffer is properly handled
+ * when serializing into a CDATA section.
+ */
+ @Test(dataProvider = "xsls")
+ public final void testBug8207760_cdata(String xsl) throws Exception {
+ String[] xmls = prepareXML(true);
+ Transformer t = createTransformerFromInputstream(
+ new ByteArrayInputStream(xsl.getBytes(StandardCharsets.UTF_8)));
+ t.setOutputProperty(OutputKeys.ENCODING, StandardCharsets.UTF_8.name());
+ StringWriter sw = new StringWriter();
+ t.transform(new StreamSource(new StringReader(xmls[0])), new StreamResult(sw));
+ Assert.assertEquals(sw.toString().replaceAll(System.lineSeparator(), "\n"), xmls[1]);
+ }
+
+ private String[] prepareXML(boolean cdata) {
+ String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><source>";
+ if (cdata) {
+ xml += "<![CDATA[";
+ }
+ String tail = "abc 123 </source>";
+ if (cdata) {
+ tail = "abc 123 ]]></source>";
+ }
+ String temp = generateString(1023);
+ xml = xml + temp + '\uD83C' + '\uDF42' + tail;
+ //xml = xml + temp + tail;
+ String expected = (!cdata) ? "<source>" + temp + "&#127810;" + tail
+ : xml;
+
+ return new String[]{xml, expected};
+ }
+
+ static final char[] CHARS = "abcdefghijklmnopqrstuvwxyz \n".toCharArray();
+ StringBuilder sb = new StringBuilder(1024 << 4);
+ Random random = new Random();
+
+ private String generateString(int size) {
+ sb.setLength(0);
+ for (int i = 0; i < size; i++) {
+ char c = CHARS[random.nextInt(CHARS.length)];
+ sb.append(c);
+ }
+
+ return sb.toString();
+ }
+
+ private Transformer createTransformerFromInputstream(InputStream xslStream)
+ throws TransformerException {
+ return TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream));
+ }
+}
diff --git a/test/javax/xml/jaxp/transform/sort/SortTest.java b/test/javax/xml/jaxp/transform/sort/SortTest.java
new file mode 100644
index 0000000000..e8622e8fce
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/SortTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2018, 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.io.StringWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Templates;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8193830
+ * @run testng/othervm -DrunSecMngr=true SortTest
+ * @run testng/othervm SortTest
+ * @summary verify xsl:sort lang attribute
+ */
+public class SortTest {
+
+ static final String LAND_EN = "en";
+ static final String LAND_PL = "pl";
+ static final String LAND_RU = "ru";
+
+ String filepath;
+ String slash = "";
+
+ @BeforeClass
+ public void setUpClass() throws Exception {
+ String file1 = getClass().getResource("/sort-alphabet-english.xml").getFile();
+ if (System.getProperty("os.name").contains("Windows")) {
+ filepath = file1.substring(1, file1.lastIndexOf("/") + 1);
+ slash = "/";
+ } else {
+ filepath = file1.substring(0, file1.lastIndexOf("/") + 1);
+ }
+ }
+
+ /*
+ * DataProvider fields:
+ * lang, xml, xsl, gold file
+ */
+ @DataProvider(name = "parameters")
+ public Object[][] getParameters() {
+
+ return new Object[][]{
+ {LAND_EN, "sort-alphabet-english.xml", "sort-alphabet-english.xsl", "sort-alphabet-english.out"},
+ {LAND_PL, "sort-alphabet-polish.xml", "sort-alphabet-polish.xsl", "sort-alphabet-polish.out"},
+ {LAND_RU, "sort-alphabet-russian.xml", "sort-alphabet-russian.xsl", "sort-alphabet-russian.out"},};
+ }
+
+ @Test(dataProvider = "parameters")
+ public final void testTransform(String lang, String xml, String xsl, String gold)
+ throws Exception {
+
+ StringWriter sw = new StringWriter();
+ // Create transformer factory
+ TransformerFactory factory = TransformerFactory.newInstance();
+
+ // Use the factory to create a template containing the xsl file
+ Templates template = factory.newTemplates(new StreamSource(getClass().getResourceAsStream(xsl)));
+ // Use the template to create a transformer
+ Transformer xformer = template.newTransformer();
+ xformer.setParameter("lang", lang);
+ // Prepare the input and output files
+ Source source = new StreamSource(getClass().getResourceAsStream(xml));
+
+ /*
+ * The following may be used to produce gold files.
+ * Using however the original gold files, and compare without considering
+ * the format
+ */
+ //String output = getClass().getResource(gold).getPath();
+ //Result result = new StreamResult(new FileOutputStream(output));
+ // use the following to verify the output against the pre-generated one
+ Result result = new StreamResult(sw);
+
+ // Apply the xsl file to the source file and write the result to the
+ // output file
+ xformer.transform(source, result);
+
+ String out = sw.toString();
+
+ List<String> lines = Files.readAllLines(Paths.get(filepath + gold));
+ String[] resultLines = out.split("\n");
+ int i = 0;
+
+ // the purpose is to test sort, so ignore the format of the output
+
+ for (String line : lines) {
+ Assert.assertEquals(resultLines[i++].trim(), line.trim());
+ }
+ }
+}
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.out b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.out
new file mode 100644
index 0000000000..a34c49ab47
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.out
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?><root>
+<p>lang: en</p>
+<ul>
+<li>A</li>
+<li>C</li>
+<li>D</li>
+<li>E</li>
+<li>F</li>
+<li>G</li>
+<li>H</li>
+<li>I</li>
+<li>J</li>
+<li>K</li>
+<li>L</li>
+<li>M</li>
+<li>N</li>
+<li>O</li>
+<li>P</li>
+<li>Q</li>
+<li>R</li>
+<li>S</li>
+<li>T</li>
+<li>U</li>
+<li>V</li>
+<li>W</li>
+<li>X</li>
+<li>Y</li>
+<li>Z</li>
+</ul>
+</root> \ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xml b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xml
new file mode 100644
index 0000000000..7093d67c53
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alphabet language="en">
+ <character>A</character>
+ <character>E</character>
+ <character>C</character>
+ <character>D</character>
+ <character>F</character>
+ <character>G</character>
+ <character>H</character>
+ <character>I</character>
+ <character>J</character>
+ <character>K</character>
+ <character>L</character>
+ <character>M</character>
+ <character>N</character>
+ <character>Y</character>
+ <character>O</character>
+ <character>P</character>
+ <character>Q</character>
+ <character>U</character>
+ <character>R</character>
+ <character>S</character>
+ <character>V</character>
+ <character>W</character>
+ <character>T</character>
+ <character>X</character>
+ <character>Z</character>
+</alphabet>
+
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xsl b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xsl
new file mode 100644
index 0000000000..ef57a3d543
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-english.xsl
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" version="1.0" omit-xml-declaration="no" encoding="UTF-8" indent="yes" xml:space="preserve" />
+ <!-- <xsl:output method="html" doctype-system="http://www.w3.org/TR/html4/strict.dtd" doctype-public="-//W3C//DTD HTML
+ 4.01//EN" version="4.0" encoding="UTF-8" indent="yes" xml:lang="$lang" omit-xml-declaration="no"/> -->
+ <xsl:param name="lang" />
+ <xsl:template match="alphabet">
+ <root>
+ <p>lang: <xsl:value-of select="$lang" /></p>
+ <ul>
+ <xsl:apply-templates select="character">
+ <xsl:sort select="." lang="{$lang}" order="ascending" />
+ </xsl:apply-templates>
+ </ul>
+ </root>
+ </xsl:template>
+ <xsl:template match="character">
+ <li>
+ <xsl:value-of select="text()" />
+ </li>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.out b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.out
new file mode 100644
index 0000000000..5219d79d9d
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.out
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?><root>
+<p>lang: pl</p>
+<ul>
+<li>A</li>
+<li>Ą</li>
+<li>B</li>
+<li>C</li>
+<li>Ć</li>
+<li>D</li>
+<li>E</li>
+<li>Ę</li>
+<li>F</li>
+<li>G</li>
+<li>H</li>
+<li>I</li>
+<li>J</li>
+<li>K</li>
+<li>L</li>
+<li>Ł</li>
+<li>M</li>
+<li>N</li>
+<li>Ń</li>
+<li>O</li>
+<li>Ó</li>
+<li>P</li>
+<li>R</li>
+<li>S</li>
+<li>Ś</li>
+<li>T</li>
+<li>U</li>
+<li>W</li>
+<li>Y</li>
+<li>Z</li>
+<li>Ź</li>
+<li>Ż</li>
+</ul>
+</root> \ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xml b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xml
new file mode 100644
index 0000000000..cf08ac1bfc
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alphabet language="pl">
+ <character>A</character>
+ <character>Ż</character>
+ <character>B</character>
+ <character>C</character>
+ <character>Ć</character>
+ <character>D</character>
+ <character>Ł</character>
+ <character>E</character>
+ <character>Ę</character>
+ <character>F</character>
+ <character>G</character>
+ <character>H</character>
+ <character>I</character>
+ <character>J</character>
+ <character>K</character>
+ <character>L</character>
+ <character>Z</character>
+ <character>Ź</character>
+ <character>M</character>
+ <character>N</character>
+ <character>Ń</character>
+ <character>O</character>
+ <character>Ó</character>
+ <character>P</character>
+ <character>R</character>
+ <character>S</character>
+ <character>Ś</character>
+ <character>T</character>
+ <character>U</character>
+ <character>W</character>
+ <character>Ą</character>
+ <character>Y</character>
+</alphabet> \ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xsl b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xsl
new file mode 100644
index 0000000000..e91e53c619
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-polish.xsl
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" version="1.0" omit-xml-declaration="no" encoding="UTF-8" indent="yes" xml:space="preserve" />
+ <!-- <xsl:output method="html" doctype-system="http://www.w3.org/TR/html4/strict.dtd" doctype-public="-//W3C//DTD HTML
+ 4.01//EN" version="4.0" encoding="UTF-8" indent="yes" xml:lang="$lang" omit-xml-declaration="no"/> -->
+ <xsl:param name="lang" />
+ <xsl:template match="alphabet">
+ <root>
+ <p>lang: <xsl:value-of select="$lang" /></p>
+ <ul>
+ <xsl:apply-templates select="character">
+ <xsl:sort select="." lang="{$lang}" order="ascending" />
+ </xsl:apply-templates>
+ </ul>
+ </root>
+ </xsl:template>
+ <xsl:template match="character">
+ <li>
+ <xsl:value-of select="text()" />
+ </li>
+ </xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.out b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.out
new file mode 100644
index 0000000000..724d22d6e8
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.out
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?><root>
+<p>lang: ru</p>
+<ul>
+<li>А</li>
+<li>Б</li>
+<li>В</li>
+<li>Г</li>
+<li>Д</li>
+<li>Е</li>
+<li>Ё</li>
+<li>Ж</li>
+<li>З</li>
+<li>И</li>
+<li>Й</li>
+<li>К</li>
+<li>Л</li>
+<li>М</li>
+<li>Н</li>
+<li>О</li>
+<li>П</li>
+<li>Р</li>
+<li>С</li>
+<li>Т</li>
+<li>У</li>
+<li>Ф</li>
+<li>Х</li>
+<li>Ц</li>
+<li>Ч</li>
+<li>Ш</li>
+<li>Щ</li>
+<li>Ъ</li>
+<li>Ы</li>
+<li>Ь</li>
+<li>Э</li>
+<li>Ю</li>
+<li>Я</li>
+</ul>
+</root> \ No newline at end of file
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xml b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xml
new file mode 100644
index 0000000000..6811b16c93
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<alphabet language="ru">
+ <character>А</character>
+ <character>Б</character>
+ <character>В</character>
+ <character>Г</character>
+ <character>Д</character>
+ <character>Е</character>
+ <character>Ё</character>
+ <character>Ж</character>
+ <character>З</character>
+ <character>Й</character>
+ <character>П</character>
+ <character>Я</character>
+ <character>К</character>
+ <character>Л</character>
+ <character>С</character>
+ <character>М</character>
+ <character>Н</character>
+ <character>О</character>
+ <character>Р</character>
+ <character>И</character>
+ <character>Т</character>
+ <character>Ф</character>
+ <character>Х</character>
+ <character>Ц</character>
+ <character>У</character>
+ <character>Ш</character>
+ <character>Щ</character>
+ <character>Ъ</character>
+ <character>Ы</character>
+ <character>Ч</character>
+ <character>Ь</character>
+ <character>Э</character>
+ <character>Ю</character>
+</alphabet>
diff --git a/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xsl b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xsl
new file mode 100644
index 0000000000..e91e53c619
--- /dev/null
+++ b/test/javax/xml/jaxp/transform/sort/sort-alphabet-russian.xsl
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+ <!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ -->
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:output method="xml" version="1.0" omit-xml-declaration="no" encoding="UTF-8" indent="yes" xml:space="preserve" />
+ <!-- <xsl:output method="html" doctype-system="http://www.w3.org/TR/html4/strict.dtd" doctype-public="-//W3C//DTD HTML
+ 4.01//EN" version="4.0" encoding="UTF-8" indent="yes" xml:lang="$lang" omit-xml-declaration="no"/> -->
+ <xsl:param name="lang" />
+ <xsl:template match="alphabet">
+ <root>
+ <p>lang: <xsl:value-of select="$lang" /></p>
+ <ul>
+ <xsl:apply-templates select="character">
+ <xsl:sort select="." lang="{$lang}" order="ascending" />
+ </xsl:apply-templates>
+ </ul>
+ </root>
+ </xsl:template>
+ <xsl:template match="character">
+ <li>
+ <xsl:value-of select="text()" />
+ </li>
+ </xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/test/jb/java/awt/Font/font430.sh b/test/jb/java/awt/Font/font430.sh
index 50ccb3e305..3806e87543 100644
--- a/test/jb/java/awt/Font/font430.sh
+++ b/test/jb/java/awt/Font/font430.sh
@@ -40,7 +40,7 @@ cd ${TESTSRC}
${TESTJAVA}/bin/javac -d ${TESTCLASSES} Font430.java
${TESTJAVA}/bin/java -cp ${TESTCLASSES} Font430 t1.bmp true
-${TESTJAVA}/bin/java -cp ${TESTCLASSES} Font430 t2.bmp true
+${TESTJAVA}/bin/java -cp ${TESTCLASSES} Font430 t2.bmp false
cmp t1.bmp t2.bmp
exit_code=$?
@@ -49,6 +49,7 @@ case $exit_code in
0) echo "PASSED"
;;
*) echo "FAILED: $exit_code"
+ mv t[1..2].bmp ${TESTCLASSES}
exit 1
;;
esac
diff --git a/test/jbProblemsList.txt b/test/jbProblemsList.txt
index 6135053af6..f548ea100f 100644
--- a/test/jbProblemsList.txt
+++ b/test/jbProblemsList.txt
@@ -187,6 +187,7 @@ java/awt/Modal/LWModalTest/LWModalTest.java
java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java 8066259 generic-all
java/awt/Modal/ModalInternalFrameTest/ModalInternalFrameTest.java 8159599 generic-all
java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8052166 generic-all
+java/awt/Mouse/MouseComboBoxTest/MouseComboBoxTest.java 8052166 generic-all
java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8023562 macosx-all,windows-all,linux-all
java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8023562 macosx-all,windows-all,linux-all
java/awt/Mouse/EnterExitEvents/ModalDialogEnterExitEventsTest.java 8165619 generic-all
@@ -267,7 +268,7 @@ java/awt/event/KeyEvent/AltCharAcceleratorTest/AltCharAcceleratorTest.java
java/awt/event/KeyEvent/DeadKey/DeadKeySystemAssertionDialog.java 8145652 generic-all
java/awt/event/KeyEvent/CorrectTime/CorrectTime.java 6626492 generic-all
java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java 8169476 windows-all,macosx-all,linux-all
-java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474 windows-all,linux-all
+java/awt/event/KeyEvent/KeyChar/KeyCharTest.java 8169474 windows-all,linux-all,macosx-all
java/awt/event/KeyEvent/KeyTyped/CtrlASCII.html 7156316,8160623 generic-all
java/awt/event/KeyEvent/SwallowKeyEvents/SwallowKeyEvents.java JRE-1018 macosx-all,linux-all
java/awt/event/MouseEvent/EventTimeInFuture/EventTimeInFuture.java 8032254 linux-all
@@ -353,7 +354,7 @@ javax/sound/sampled/DirectAudio/bug6400879.java
# jdk_beans
java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all
-java/beans/Introspector/Test8027648.java 8030123 linux-all
+java/beans/Introspector/Test8027648.java 8030123 linux-all,windows-all
############################################################################
@@ -609,7 +610,8 @@ javax/swing/JFrame/4962534/bug4962534.html
javax/swing/JFrame/8016356/bug8016356.java 8169955 windows-all
javax/swing/JInternalFrame/5066752/bug5066752.java 8007719 generic-all
javax/swing/JInternalFrame/8020708/bug8020708.java 8032568 generic-all
-javax/swing/JInternalFrame/8069348/bug8069348.java 8208570 linux-all
+javax/swing/JInternalFrame/8069348/bug8069348.java 8208570 linux-all,macosx-all
+javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java 8186513 generic-all
javax/swing/JInternalFrame/Test6325652.java 8196467,8160880 linux-all,macosx-all,windows-all
javax/swing/JInternalFrame/Test6505027.java 8172535 generic-all
javax/swing/JLabel/6596966/bug6596966.java 8040914 linux-all,macosx-all,windows-all
@@ -843,6 +845,8 @@ com/sun/java/swing/plaf/windows/Test8173145.java
com/sun/jdi/FieldWatchpoints.java 8206438 generic-all
# ignored
+com/sun/crypto/provider/Cipher/AES/TestAESCiphers/TestAESWithProviderChange.java 8228440 generic-all
+com/sun/crypto/provider/Cipher/AES/TestAESCiphers/TestAESWithRemoveAddProvider.java 8228440 generic-all
com/sun/crypto/provider/Cipher/DES/PerformanceTest.java generic-all
com/sun/jdi/PopAndInvokeTest.java generic-all
com/sun/security/auth/callback/DialogCallbackHandler/Default.java generic-all
@@ -930,4 +934,22 @@ sun/security/mscapi/CastError.java
sun/security/mscapi/SignatureOffsets.java JRE-720 windows-all
sun/security/mscapi/SmallPrimeExponentP.java JRE-720 windows-all
-sun/tools/native2ascii/Native2AsciiTests.sh JRE-738 windows-all \ No newline at end of file
+sun/tools/native2ascii/Native2AsciiTests.sh JRE-738 windows-all
+
+java/text/BreakIterator/BreakIteratorTest.java 8229922 generic-all
+java/text/Format/DateFormat/DateFormatTest.java 8229922 generic-all
+java/text/Format/DateFormat/NonGregorianFormatTest.java 8229922 generic-all
+java/text/Format/MessageFormat/LargeMessageFormat.java 8229922 generic-all
+java/text/Format/NumberFormat/NumberRegression.java 8229922 generic-all
+java/text/Format/NumberFormat/NumberTest.java 8229922 generic-all
+java/util/Calendar/CalendarRegression.java 8229922 generic-all
+java/util/Calendar/JapanEraNameCompatTest.java 8229922 generic-all
+java/util/TimeZone/HongKong.java 8229922 generic-all
+sun/text/IntHashtable/Bug4170614Test.sh 8229922 generic-all
+
+security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java 8224768 generic-all
+
+com/sun/crypto/provider/Cipher/AES/TestAESCiphers/TestAESWithProviderChange.java 8228440 generic-all
+com/sun/crypto/provider/Cipher/AES/TestAESCiphers/TestAESWithRemoveAddProvider.java 8228440 generic-all
+
+java/awt/FontMetrics/MaxAdvanceIsMax.java 8221305 solaris-all,macosx-all
diff --git a/test/jbcommitProblemList.txt b/test/jbcommitProblemList.txt
index af868c7a6b..7f2f97e65a 100644
--- a/test/jbcommitProblemList.txt
+++ b/test/jbcommitProblemList.txt
@@ -13,6 +13,7 @@ java/awt/Graphics/LineClipTest.java
java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.html nobug macosx-all
java/awt/List/ActionAfterRemove/ActionAfterRemove.java nobug windows-all,macosx-all
java/awt/Menu/NullMenuLabelTest/NullMenuLabelTest.java nobug linux-all
+java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java.MenuBarSetFont nobug windows-all
java/awt/Robot/HiDPIScreenCapture/HiDPIRobotScreenCaptureTest.java nobug windows-all
java/awt/ScrollPane/ScrollPanePreferredSize/ScrollPanePreferredSize.java nobug macosx-all
java/awt/Toolkit/SunDisplayChangerLeakTest/SunDisplayChangerLeakTest.java nobug linux-all,windows-all
@@ -26,10 +27,10 @@ java/awt/hidpi/ClientAreaOriginWindowsTest.java
java/awt/hidpi/DrawOnFrameGraphicsTest.java nobug windows-all
java/awt/hidpi/DrawOnFrameGraphicsTest.java nobug windows-all
java/awt/hidpi/properties/HiDPIPropertiesUnixTest.java nobug linux-all,macosx-all
+java/awt/image/DrawImage/UnmanagedDrawImagePerformance.java nobug windows-all
javax/swing/JFrame/NSTexturedJFrame/NSTexturedJFrame.java nobug macosx-all
javax/swing/JInternalFrame/8069348/bug8069348.java nobug macosx-all,windows-all
-javax/swing/JInternalFrame/8160248/JInternalFrameDraggingTest.java nobug macosx-all,windows-all
javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java nobug linux-all
javax/swing/JPopupMenu/7154841/bug7154841.java nobug macosx-all
javax/swing/JTable/8133919/DrawGridLInesTest.java nobug linux-all
diff --git a/test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java b/test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java
new file mode 100644
index 0000000000..2b18226623
--- /dev/null
+++ b/test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2018, 2019, 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 8153732 8212202 8221263 8221412 8222108
+ * @requires (os.family == "Windows")
+ * @summary Windows remote printer changes do not reflect in lookupPrintServices()
+ * @run main/manual/othervm -Dsun.java2d.print.minRefreshTime=120 RemotePrinterStatusRefresh
+ */
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.swing.AbstractListModel;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+
+import static javax.swing.BorderFactory.createTitledBorder;
+
+public class RemotePrinterStatusRefresh extends WindowAdapter {
+
+ private static final long DEFAULT_REFRESH_TIME = 240L;
+ private static final long MINIMAL_REFRESH_TIME = 120L;
+
+ private static final long refreshTime = getRefreshTime();
+
+ private static final long TIMEOUT = refreshTime * 4 + 60;
+
+
+ private static final CountDownLatch latch = new CountDownLatch(1);
+ private static volatile RemotePrinterStatusRefresh test;
+
+ private volatile boolean testResult;
+ private volatile boolean testTimedOut;
+
+ private final JFrame frame;
+
+ private JButton refreshButton;
+ private JButton passButton;
+ private JButton failButton;
+
+ private final ServiceItemListModel beforeList;
+ private final ServiceItemListModel afterList;
+
+ private JTextField nextRefresh;
+ private JTextField timeLeft;
+
+ private final Timer timer;
+ private final long startTime;
+
+
+ private static class ServiceItem {
+ private enum State {
+ REMOVED, UNCHANGED, ADDED
+ }
+
+ final String name;
+ State state;
+
+ private ServiceItem(final String name) {
+ this.name = name;
+ state = State.UNCHANGED;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return (obj instanceof ServiceItem)
+ && ((ServiceItem) obj).name.equals(name);
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+ }
+
+ private static class ServiceItemListModel extends AbstractListModel<ServiceItem> {
+ private final List<ServiceItem> list;
+
+ private ServiceItemListModel(List<ServiceItem> list) {
+ this.list = list;
+ }
+
+ @Override
+ public int getSize() {
+ return list.size();
+ }
+
+ @Override
+ public ServiceItem getElementAt(int index) {
+ return list.get(index);
+ }
+
+ private void refreshList(List<ServiceItem> newList) {
+ list.clear();
+ list.addAll(newList);
+ fireChanged();
+ }
+
+ private void fireChanged() {
+ fireContentsChanged(this, 0, list.size() - 1);
+ }
+ }
+
+ private static class ServiceItemListRenderer extends DefaultListCellRenderer {
+ @Override
+ public Component getListCellRendererComponent(JList<?> list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus) {
+ Component component =
+ super.getListCellRendererComponent(list, value, index,
+ isSelected, cellHasFocus);
+ switch (((ServiceItem) value).state) {
+ case REMOVED:
+ component.setBackground(Color.RED);
+ component.setForeground(Color.WHITE);
+ break;
+ case ADDED:
+ component.setBackground(Color.GREEN);
+ component.setForeground(Color.BLACK);
+ break;
+ case UNCHANGED:
+ default:
+ break;
+ }
+ return component;
+ }
+ }
+
+ private static final String INSTRUCTIONS_TEXT =
+ "Please follow the steps for this manual test:\n"
+ + "Step 0: \"Before\" list is populated with currently "
+ + "configured printers.\n"
+ + "Step 1: Add or Remove a network printer using "
+ + "Windows Control Panel.\n"
+ + "Step 2: Wait for 2\u20134 minutes after adding or removing.\n"
+ + " \"Next printer refresh in\" gives you a "
+ + "rough estimation on when update will happen.\n"
+ + "Step 3: Click Refresh."
+ + "\"After\" list is populated with updated list "
+ + "of printers.\n"
+ + "Step 4: Compare the list of printers in \"Before\" and "
+ + "\"After\" lists.\n"
+ + " Added printers are highlighted with "
+ + "green color, removed ones \u2014 with "
+ + "red color.\n"
+ + "Step 5: Click Pass if the list of printers is correctly "
+ + "updated.\n"
+ + "Step 6: If the list is not updated, wait for another "
+ + "2\u20134 minutes, and then click Refresh again.\n"
+ + "Step 7: If the list does not update, click Fail.\n"
+ + "\n"
+ + "You have to click Refresh to enable Pass and Fail buttons. "
+ + "If no button is pressed,\n"
+ + "the test will time out. "
+ + "Closing the window also fails the test.";
+
+ public static void main(String[] args) throws Exception {
+ SwingUtilities.invokeAndWait(RemotePrinterStatusRefresh::createUI);
+
+ latch.await();
+ if (!test.testResult) {
+ throw new RuntimeException("Test failed"
+ + (test.testTimedOut ? " because of time out" : ""));
+ }
+ }
+
+ private static long getRefreshTime() {
+ String refreshTime =
+ System.getProperty("sun.java2d.print.minRefreshTime",
+ Long.toString(DEFAULT_REFRESH_TIME));
+ try {
+ long value = Long.parseLong(refreshTime);
+ return value < MINIMAL_REFRESH_TIME ? MINIMAL_REFRESH_TIME : value;
+ } catch (NumberFormatException e) {
+ return DEFAULT_REFRESH_TIME;
+ }
+ }
+
+ private static void createUI() {
+ test = new RemotePrinterStatusRefresh();
+ }
+
+ private RemotePrinterStatusRefresh() {
+ frame = new JFrame("RemotePrinterStatusRefresh");
+ frame.addWindowListener(this);
+
+
+ JPanel northPanel = new JPanel(new BorderLayout());
+ northPanel.add(createInfoPanel(), BorderLayout.NORTH);
+ northPanel.add(createInstructionsPanel(), BorderLayout.SOUTH);
+
+
+ beforeList = new ServiceItemListModel(
+ Collections.unmodifiableList(collectPrinterList()));
+ afterList = new ServiceItemListModel(new ArrayList<>());
+ logList("Before:", beforeList.list);
+
+ JPanel listPanel = new JPanel(new GridLayout(1, 2));
+ listPanel.setBorder(createTitledBorder("Print Services"));
+ listPanel.add(createListPanel(beforeList, "Before:", 'b'));
+ listPanel.add(createListPanel(afterList, "After:", 'a'));
+
+
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(northPanel, BorderLayout.NORTH);
+ mainPanel.add(listPanel, BorderLayout.CENTER);
+ mainPanel.add(createButtonPanel(), BorderLayout.SOUTH);
+
+
+ frame.add(mainPanel);
+ frame.pack();
+ refreshButton.requestFocusInWindow();
+ frame.setVisible(true);
+
+
+ timer = new Timer(1000, this::updateTimeLeft);
+ timer.start();
+ startTime = System.currentTimeMillis();
+ updateTimeLeft(null);
+ }
+
+ private JPanel createInfoPanel() {
+ JLabel javaLabel = new JLabel("Java version:");
+ JTextField javaVersion =
+ new JTextField(System.getProperty("java.runtime.version"));
+ javaVersion.setEditable(false);
+ javaLabel.setLabelFor(javaVersion);
+
+ JLabel refreshTimeLabel = new JLabel("Refresh interval:");
+ long minutes = refreshTime / 60;
+ long seconds = refreshTime % 60;
+ String interval = String.format("%1$d seconds%2$s",
+ refreshTime,
+ minutes > 0
+ ? String.format(" (%1$d %2$s%3$s)",
+ minutes,
+ minutes > 1 ? "minutes" : "minute",
+ seconds > 0
+ ? String.format(" %1$d %2$s",
+ seconds,
+ seconds > 1 ? "seconds" : "second")
+ : "")
+ : ""
+ );
+ JTextField refreshInterval = new JTextField(interval);
+ refreshInterval.setEditable(false);
+ refreshTimeLabel.setLabelFor(refreshInterval);
+
+ JLabel nextRefreshLabel = new JLabel("Next printer refresh in:");
+ nextRefresh = new JTextField();
+ nextRefresh.setEditable(false);
+ nextRefreshLabel.setLabelFor(nextRefresh);
+
+ JLabel timeoutLabel = new JLabel("Time left:");
+ timeLeft = new JTextField();
+ timeLeft.setEditable(false);
+ timeoutLabel.setLabelFor(timeLeft);
+
+ JPanel infoPanel = new JPanel();
+ GroupLayout layout = new GroupLayout(infoPanel);
+ infoPanel.setLayout(layout);
+ infoPanel.setBorder(BorderFactory.createTitledBorder("Info"));
+ layout.setAutoCreateGaps(true);
+ layout.setHorizontalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(javaLabel)
+ .addComponent(refreshTimeLabel)
+ .addComponent(nextRefreshLabel)
+ .addComponent(timeoutLabel)
+ )
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING, true)
+ .addComponent(javaVersion)
+ .addComponent(refreshInterval)
+ .addComponent(nextRefresh)
+ .addComponent(timeLeft)
+ )
+ );
+ layout.setVerticalGroup(
+ layout.createSequentialGroup()
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(javaLabel)
+ .addComponent(javaVersion)
+ )
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(refreshTimeLabel)
+ .addComponent(refreshInterval))
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(nextRefreshLabel)
+ .addComponent(nextRefresh))
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(timeoutLabel)
+ .addComponent(timeLeft))
+ );
+ return infoPanel;
+ }
+
+ private JPanel createInstructionsPanel() {
+ JPanel instructionsPanel = new JPanel(new BorderLayout());
+ JTextArea instructionText = new JTextArea(INSTRUCTIONS_TEXT);
+ instructionText.setEditable(false);
+ instructionsPanel.setBorder(createTitledBorder("Test Instructions"));
+ instructionsPanel.add(new JScrollPane(instructionText));
+ return instructionsPanel;
+ }
+
+ private JPanel createListPanel(final ServiceItemListModel model,
+ final String title,
+ final char mnemonic) {
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ JList<ServiceItem> list = new JList<>(model);
+ list.setCellRenderer(new ServiceItemListRenderer());
+
+ JLabel label = new JLabel(title);
+ label.setLabelFor(list);
+ label.setDisplayedMnemonic(mnemonic);
+ JPanel labelPanel = new JPanel();
+ labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.X_AXIS));
+ labelPanel.add(label, BorderLayout.EAST);
+ labelPanel.add(Box.createHorizontalGlue());
+
+ panel.add(labelPanel);
+ panel.add(new JScrollPane(list));
+ return panel;
+ }
+
+ private JPanel createButtonPanel() {
+ refreshButton = new JButton("Refresh");
+ refreshButton.addActionListener(this::refresh);
+
+ passButton = new JButton("Pass");
+ passButton.addActionListener(this::pass);
+ passButton.setEnabled(false);
+
+ failButton = new JButton("Fail");
+ failButton.addActionListener(this::fail);
+ failButton.setEnabled(false);
+
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
+ buttonPanel.add(Box.createHorizontalGlue());
+ buttonPanel.add(refreshButton);
+ buttonPanel.add(passButton);
+ buttonPanel.add(failButton);
+ buttonPanel.add(Box.createHorizontalGlue());
+ return buttonPanel;
+ }
+
+ private static List<ServiceItem> collectPrinterList() {
+ PrintService[] printServices = PrintServiceLookup.lookupPrintServices(null, null);
+ List<ServiceItem> list = new ArrayList<>(printServices.length);
+ for (PrintService service : printServices) {
+ list.add(new ServiceItem(service.getName()));
+ }
+ return list;
+ }
+
+ private static void logList(final String title, final List<ServiceItem> list) {
+ System.out.println(title);
+ for (ServiceItem item : list) {
+ System.out.println(item.name);
+ }
+ System.out.println();
+ }
+
+ private static void compareLists(final ServiceItemListModel before, final ServiceItemListModel after) {
+ boolean beforeUpdated = false;
+ boolean afterUpdated = false;
+
+ for (ServiceItem item : before.list) {
+ if (!after.list.contains(item)) {
+ item.state = ServiceItem.State.REMOVED;
+ beforeUpdated = true;
+ } else if (item.state != ServiceItem.State.UNCHANGED) {
+ item.state = ServiceItem.State.UNCHANGED;
+ beforeUpdated = true;
+ }
+ }
+
+ for (ServiceItem item : after.list) {
+ if (!before.list.contains(item)) {
+ item.state = ServiceItem.State.ADDED;
+ afterUpdated = true;
+ } else if (item.state != ServiceItem.State.UNCHANGED) {
+ item.state = ServiceItem.State.UNCHANGED;
+ afterUpdated = true;
+ }
+ }
+
+ if (beforeUpdated) {
+ before.fireChanged();
+ }
+ if (afterUpdated) {
+ after.fireChanged();
+ }
+ }
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ System.out.println("The window closed");
+ disposeUI();
+ }
+
+ private void disposeUI() {
+ timer.stop();
+ latch.countDown();
+ frame.dispose();
+ }
+
+ @SuppressWarnings("unused")
+ private void refresh(ActionEvent e) {
+ System.out.println("Refresh button pressed");
+ afterList.refreshList(collectPrinterList());
+ compareLists(beforeList, afterList);
+ passButton.setEnabled(true);
+ failButton.setEnabled(true);
+ logList("After:", afterList.list);
+ }
+
+ @SuppressWarnings("unused")
+ private void pass(ActionEvent e) {
+ System.out.println("Pass button pressed");
+ testResult = true;
+ disposeUI();
+ }
+
+ @SuppressWarnings("unused")
+ private void fail(ActionEvent e) {
+ System.out.println("Fail button pressed");
+ testResult = false;
+ disposeUI();
+ }
+
+ @SuppressWarnings("unused")
+ private void updateTimeLeft(ActionEvent e) {
+ long elapsed = (System.currentTimeMillis() - startTime) / 1000;
+ long left = TIMEOUT - elapsed;
+ if (left < 0) {
+ testTimedOut = true;
+ disposeUI();
+ }
+ timeLeft.setText(formatTime(left));
+ nextRefresh.setText(formatTime(refreshTime - (elapsed % refreshTime)));
+ }
+
+ private static String formatTime(final long seconds) {
+ long minutes = seconds / 60;
+ return String.format("%d:%02d", minutes, seconds - minutes * 60);
+ }
+
+}
diff --git a/test/lib/testlibrary/jdk/testlibrary/Convert.java b/test/lib/testlibrary/jdk/testlibrary/Convert.java
new file mode 100644
index 0000000000..33afbf0d11
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/Convert.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+package jdk.testlibrary;
+
+import java.math.BigInteger;
+
+/**
+ * Utility class containing conversions between strings, arrays, and numeric
+ * values.
+ */
+
+public class Convert {
+
+ // Convert from a byte array to a hexadecimal representation as a string.
+ public static String byteArrayToHexString(byte[] arr) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < arr.length; ++i) {
+ byte curVal = arr[i];
+ result.append(Character.forDigit(curVal >> 4 & 0xF, 16));
+ result.append(Character.forDigit(curVal & 0xF, 16));
+ }
+ return result.toString();
+ }
+
+ // Expand a single byte to a byte array
+ public static byte[] byteToByteArray(byte v, int length) {
+ byte[] result = new byte[length];
+ result[0] = v;
+ return result;
+ }
+
+ // Convert a hexadecimal string to a byte array
+ public static byte[] hexStringToByteArray(String str) {
+ byte[] result = new byte[str.length() / 2];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (byte) Character.digit(str.charAt(2 * i), 16);
+ result[i] <<= 4;
+ result[i] += Character.digit(str.charAt(2 * i + 1), 16);
+ }
+ return result;
+ }
+
+ /*
+ * Convert a hexadecimal string to the corresponding little-ending number
+ * as a BigInteger. The clearHighBit argument determines whether the most
+ * significant bit of the highest byte should be set to 0 in the result.
+ */
+ public static
+ BigInteger hexStringToBigInteger(boolean clearHighBit, String str) {
+ BigInteger result = BigInteger.ZERO;
+ for (int i = 0; i < str.length() / 2; i++) {
+ int curVal = Character.digit(str.charAt(2 * i), 16);
+ curVal <<= 4;
+ curVal += Character.digit(str.charAt(2 * i + 1), 16);
+ if (clearHighBit && i == str.length() / 2 - 1) {
+ curVal &= 0x7F;
+ }
+ result = result.add(BigInteger.valueOf(curVal).shiftLeft(8 * i));
+ }
+ return result;
+ }
+}
+
diff --git a/test/lib/testlibrary/jdk/testlibrary/FileUtils.java b/test/lib/testlibrary/jdk/testlibrary/FileUtils.java
index 7882262274..b9f3088040 100644
--- a/test/lib/testlibrary/jdk/testlibrary/FileUtils.java
+++ b/test/lib/testlibrary/jdk/testlibrary/FileUtils.java
@@ -33,6 +33,7 @@ import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
@@ -190,5 +191,41 @@ public final class FileUtils {
}
return excs;
}
+
+ /**
+ * Checks whether all file systems are accessible. This is performed
+ * by checking free disk space on all mounted file systems via a
+ * separate, spawned process. File systems are considered to be
+ * accessible if this process completes successfully before a given
+ * fixed duration has elapsed.
+ *
+ * @implNote On Unix this executes the {@code df} command in a separate
+ * process and on Windows always returns {@code true}.
+ */
+ public static boolean areFileSystemsAccessible() throws IOException {
+ boolean areFileSystemsAccessible = true;
+ if (!isWindows) {
+ // try to check whether 'df' hangs
+ System.out.println("\n--- df output ---");
+ System.out.flush();
+ Process proc = new ProcessBuilder("df").inheritIO().start();
+ try {
+ proc.waitFor(90, TimeUnit.SECONDS);
+ } catch (InterruptedException ignored) {
+ }
+ try {
+ int exitValue = proc.exitValue();
+ if (exitValue != 0) {
+ System.err.printf("df process exited with %d != 0%n",
+ exitValue);
+ areFileSystemsAccessible = false;
+ }
+ } catch (IllegalThreadStateException ignored) {
+ System.err.println("df command apparently hung");
+ areFileSystemsAccessible = false;
+ }
+ }
+ return areFileSystemsAccessible;
+ }
}
diff --git a/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java
new file mode 100644
index 0000000000..78844678e5
--- /dev/null
+++ b/test/lib/testlibrary/jdk/testlibrary/net/URIBuilder.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Google 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.
+ */
+
+package jdk.testlibrary.net;
+
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+public class URIBuilder {
+
+ public static URIBuilder newBuilder() {
+ return new URIBuilder();
+ }
+
+ private String scheme;
+ private String userInfo;
+ private String host;
+ private int port;
+ private String path;
+ private String query;
+ private String fragment;
+
+ private URIBuilder() {}
+
+ public URIBuilder scheme(String scheme) {
+ this.scheme = scheme;
+ return this;
+ }
+
+ public URIBuilder userInfo(String userInfo) {
+ this.userInfo = userInfo;
+ return this;
+ }
+
+ public URIBuilder host(String host) {
+ this.host = host;
+ return this;
+ }
+
+ public URIBuilder loopback() {
+ return host(InetAddress.getLoopbackAddress().getHostAddress());
+ }
+
+ public URIBuilder port(int port) {
+ this.port = port;
+ return this;
+ }
+
+ public URIBuilder path(String path) {
+ this.path = path;
+ return this;
+ }
+
+ public URIBuilder query(String query) {
+ this.query = query;
+ return this;
+ }
+
+ public URIBuilder fragment(String fragment) {
+ this.fragment = fragment;
+ return this;
+ }
+
+ public URI build() throws URISyntaxException {
+ return new URI(scheme, userInfo, host, port, path, query, fragment);
+ }
+
+ public URI buildUnchecked() {
+ try {
+ return build();
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public URL toURL() throws URISyntaxException, MalformedURLException {
+ return build().toURL();
+ }
+
+ public URL toURLUnchecked() {
+ try {
+ return toURL();
+ } catch (URISyntaxException | MalformedURLException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java
new file mode 100644
index 0000000000..e76210b16d
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/ActalisCA.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2017, 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 8189131
+ * @summary Interoperability tests with Actalis CA
+ * @build ValidatePathWithParams
+ * @run main/othervm/timeout=180 -Djava.security.debug=certpath ActalisCA OCSP
+ * @run main/othervm/timeout=180 -Djava.security.debug=certpath ActalisCA CRL
+ */
+
+ /*
+ * Obtain test artifacts for Actalis CA from:
+ *
+ * Test web site with *active *TLS Server certificate:
+ * https://ssltest-a.actalis.it:8443
+ * If doesn't work then use certificate of https://www.actalis.it
+ *
+ * Test web site with *revoked *TLS Server certificate:
+ * https://ssltest-r.actalis.it:8444
+ *
+ * Test web site with *expired *TLS Server certificate:
+ * https://ssltest-e.actalis.it:8445
+ */
+public class ActalisCA {
+
+ // Owner: CN=Actalis Extended Validation Server CA G1,
+ // O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT
+ // Issuer: CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967,
+ // L=Milan, C=IT
+ private static final String INT_VALID = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIGTDCCBDSgAwIBAgIIMtYr/GdQGsswDQYJKoZIhvcNAQELBQAwazELMAkGA1UE\n"
+ + "BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w\n"
+ + "MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290\n"
+ + "IENBMB4XDTE1MDUxNDA3MDAzOFoXDTMwMDUxNDA3MDAzOFowgYcxCzAJBgNVBAYT\n"
+ + "AklUMQ8wDQYDVQQIDAZNaWxhbm8xDzANBgNVBAcMBk1pbGFubzEjMCEGA1UECgwa\n"
+ + "QWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxMTAvBgNVBAMMKEFjdGFsaXMgRXh0\n"
+ + "ZW5kZWQgVmFsaWRhdGlvbiBTZXJ2ZXIgQ0EgRzEwggEiMA0GCSqGSIb3DQEBAQUA\n"
+ + "A4IBDwAwggEKAoIBAQD1Ygc1CwmqXqjd3dTEKMLUwGdb/3+00ytg0uBb4RB+89/O\n"
+ + "4K/STFZcGUjcCq6Job5cmxZBGyRRBYfCEn4vg8onedFztkO0NvD04z4wLFyxjSRT\n"
+ + "bcMm2d+/Xci5XLA3Q9wG8TGzHTVQKmdvFpQ7b7EsmOc0uXA7w3UGhLjb2EYpu/Id\n"
+ + "uZ1LUTyEOHc3XHXI3a3udkRBDs/bObTcbte80DPbNetRFB+jHbIw5sH171IeBFGN\n"
+ + "PB92Iebp01yE8g3X9RqPXrrV7ririEtwFMYp+KgA8BRHxsoNV3xZmhdzJm0AMzC2\n"
+ + "waLM3H562xPM0UntAYh2pRrAUUtgURRizCT1kr6tAgMBAAGjggHVMIIB0TBBBggr\n"
+ + "BgEFBQcBAQQ1MDMwMQYIKwYBBQUHMAGGJWh0dHA6Ly9vY3NwMDUuYWN0YWxpcy5p\n"
+ + "dC9WQS9BVVRILVJPT1QwHQYDVR0OBBYEFGHB5IYeTW10dLzZlzsxcXjLP5/cMA8G\n"
+ + "A1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbtifN7OHCUyQICNtAw\n"
+ + "RQYDVR0gBD4wPDA6BgRVHSAAMDIwMAYIKwYBBQUHAgEWJGh0dHBzOi8vd3d3LmFj\n"
+ + "dGFsaXMuaXQvYXJlYS1kb3dubG9hZDCB4wYDVR0fBIHbMIHYMIGWoIGToIGQhoGN\n"
+ + "bGRhcDovL2xkYXAwNS5hY3RhbGlzLml0L2NuJTNkQWN0YWxpcyUyMEF1dGhlbnRp\n"
+ + "Y2F0aW9uJTIwUm9vdCUyMENBLG8lM2RBY3RhbGlzJTIwUy5wLkEuJTJmMDMzNTg1\n"
+ + "MjA5NjcsYyUzZElUP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q7YmluYXJ5MD2g\n"
+ + "O6A5hjdodHRwOi8vY3JsMDUuYWN0YWxpcy5pdC9SZXBvc2l0b3J5L0FVVEgtUk9P\n"
+ + "VC9nZXRMYXN0Q1JMMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEA\n"
+ + "OD8D2Z2fw76+GIu+mDEgygH/y7F9K4I6rZOc3LqGBecO3C0fGcIuuG7APtxGGk7Y\n"
+ + "nk97Qt+3pDoek9EP65/1u128pRncZcjEAeMgKb7UuJxwoR6Sj5zhOadotKcCQqmF\n"
+ + "Si99ExNo6dTq5Eyp1KrqepLmezbO9owx4Q44mtNpfKLMgzDqOn/dwNMo/pGYbMfP\n"
+ + "DjhxEnta1HXgcEcgCk1Au16xkdzapwY4sXpKuwB24phfWF+cveKAQ0Rncmvrm34i\n"
+ + "9B6leZUkSHDe4mRkbO5nObhKHYRmVSr0Q/wvGCmTgGTKuw/Gj8+RFb5MEkOKEcJn\n"
+ + "I32CPohpiW/jlpeLaFBIgJnXuZTxmfTX55sqtXDlKxRxFwq1W3kML4UfGZsgjx1l\n"
+ + "hX5fQ1QlEZeO9CyPpgGO5Py2KXXKhUxCtF7tawAYimWwslxvPCjHDND/WhM1Fz9e\n"
+ + "2yqwHcSQAOUVv5mk9uYc6/NSLwLb5in3R728GNEpHHhbx5QZhtdqR8mb56uJUDKI\n"
+ + "AwnnZckcR+SLGL2Agx7hY7YCMOQhSsO6PA81M/mGW2hGCiZw3GULJe9ejL/vdS0I\n"
+ + "PWrp7YLnXUa6mtXVSBKGrVrlbpJaN10+fB4Yrlk4O2sF4WNUAHMBn9T+zOXaBAhj\n"
+ + "vNlMU7+elLkTcKIB7qJJuSZChxzoevM2ciO3BpGuRxg=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: OID.1.3.6.1.4.1.311.60.2.1.3=IT, STREET=Via S. Clemente 53,
+ // OID.2.5.4.15=Private Organization, CN=www.actalis.it,
+ // SERIALNUMBER=03358520967, O=Actalis S.p.A., L=Ponte San Pietro, ST=Bergamo, C=IT
+ // Issuer: CN=Actalis Extended Validation Server CA G1,
+ // O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT
+ // Serial number: eeeee6d6463bde2
+ // Valid from: Sat Jun 17 05:59:17 PDT 2017 until: Mon Jun 17 05:59:17 PDT 2019
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIHwTCCBqmgAwIBAgIIDu7ubWRjveIwDQYJKoZIhvcNAQELBQAwgYcxCzAJBgNV\n"
+ + "BAYTAklUMQ8wDQYDVQQIDAZNaWxhbm8xDzANBgNVBAcMBk1pbGFubzEjMCEGA1UE\n"
+ + "CgwaQWN0YWxpcyBTLnAuQS4vMDMzNTg1MjA5NjcxMTAvBgNVBAMMKEFjdGFsaXMg\n"
+ + "RXh0ZW5kZWQgVmFsaWRhdGlvbiBTZXJ2ZXIgQ0EgRzEwHhcNMTcwNjE3MTI1OTE3\n"
+ + "WhcNMTkwNjE3MTI1OTE3WjCB0zELMAkGA1UEBhMCSVQxEDAOBgNVBAgMB0Jlcmdh\n"
+ + "bW8xGTAXBgNVBAcMEFBvbnRlIFNhbiBQaWV0cm8xFzAVBgNVBAoMDkFjdGFsaXMg\n"
+ + "Uy5wLkEuMRQwEgYDVQQFEwswMzM1ODUyMDk2NzEXMBUGA1UEAwwOd3d3LmFjdGFs\n"
+ + "aXMuaXQxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRswGQYDVQQJDBJW\n"
+ + "aWEgUy4gQ2xlbWVudGUgNTMxEzARBgsrBgEEAYI3PAIBAxMCSVQwggEiMA0GCSqG\n"
+ + "SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwZ3++4pQYGfhXSqin1CKRJ6SOqkTcX3O0\n"
+ + "6b4jZbSNomyqyn6aHOz6ztOlj++fPzxmIzErEySOTd3G0pr+iwpYQVdeg1Y27KL8\n"
+ + "OiwwUrlV4ZMa8KKXr4BnWlDbFIo+eIcSew5V7CiodDyxpj9zjqJK497LF1jxgXtr\n"
+ + "IoMRwrh2Y0NbJCZGUCL30sQr/W4xBnO1+pi2DbCieGe/XoK8yEtx9FdnEFvyT9qn\n"
+ + "zYyrXvnTvfVSwzwtEIn+akjomI4WfCFLBF0M7v4dAHypfnPAAoW1c0BBqNB32zf0\n"
+ + "rYwNnD7UwZlcDihEYlgC70Dfy7bPsdq2spmOMk/VUqb3U0LHRVM3AgMBAAGjggPh\n"
+ + "MIID3TB9BggrBgEFBQcBAQRxMG8wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jYWNlcnQu\n"
+ + "YWN0YWxpcy5pdC9jZXJ0cy9hY3RhbGlzLWF1dGV2ZzEwMQYIKwYBBQUHMAGGJWh0\n"
+ + "dHA6Ly9vY3NwMDUuYWN0YWxpcy5pdC9WQS9BVVRIRVYtRzEwHQYDVR0OBBYEFK9y\n"
+ + "954QoY/5XV6TayD1gWVy0gQOMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAUYcHk\n"
+ + "hh5NbXR0vNmXOzFxeMs/n9wwUAYDVR0gBEkwRzA8BgYrgR8BEQEwMjAwBggrBgEF\n"
+ + "BQcCARYkaHR0cHM6Ly93d3cuYWN0YWxpcy5pdC9hcmVhLWRvd25sb2FkMAcGBWeB\n"
+ + "DAEBMIHvBgNVHR8EgecwgeQwgaKggZ+ggZyGgZlsZGFwOi8vbGRhcDA1LmFjdGFs\n"
+ + "aXMuaXQvY24lM2RBY3RhbGlzJTIwRXh0ZW5kZWQlMjBWYWxpZGF0aW9uJTIwU2Vy\n"
+ + "dmVyJTIwQ0ElMjBHMSxvJTNkQWN0YWxpcyUyMFMucC5BLi8wMzM1ODUyMDk2Nyxj\n"
+ + "JTNkSVQ/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5hcnkwPaA7oDmGN2h0\n"
+ + "dHA6Ly9jcmwwNS5hY3RhbGlzLml0L1JlcG9zaXRvcnkvQVVUSEVWLUcxL2dldExh\n"
+ + "c3RDUkwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\n"
+ + "BQcDAjAZBgNVHREEEjAQgg53d3cuYWN0YWxpcy5pdDCCAX4GCisGAQQB1nkCBAIE\n"
+ + "ggFuBIIBagFoAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFc\n"
+ + "tiwHywAABAMARzBFAiEA7GC5/kja3l8cBw1/wBpHl/AKH6eL1MKpmICtf5G09c4C\n"
+ + "IBM887DQEwD2E4Xx/IP+33NMvUOhSwZ4XODgqFVXsz0wAHYA7ku9t3XOYLrhQmkf\n"
+ + "q+GeZqMPfl+wctiDAMR7iXqo/csAAAFctiwIqwAABAMARzBFAiEAwwiR95ozXdKs\n"
+ + "+uULfrzgENbHc2rLgGIac6ZMv0xHDLACIFLQVpvQBRQfys2KVRGHQKGxqAeghQZw\n"
+ + "9nJL+U5huzfaAHYA3esdK3oNT6Ygi4GtgWhwfi6OnQHVXIiNPRHEzbbsvswAAAFc\n"
+ + "tiwMqwAABAMARzBFAiEAifV9ocxbO6b3I22jb2zxBvG2e83hXHitOhYXkHdSmZkC\n"
+ + "IDJLuPvGOczF9axgphImlUbT9dX3wRpjEi5IeV+pxMiYMA0GCSqGSIb3DQEBCwUA\n"
+ + "A4IBAQB5U6k1Onv9Y7POHGnUOI0ATHevbpbS/7r68DZQ6cRmDIpsZyjW6PxYs9nc\n"
+ + "3ob3Pjomm+S7StDl9ehI7rYLlZC52QlXlsq1fzEQ9xSkf+VSD70A91dPIFAdI/jQ\n"
+ + "aWvIUvQEbhfUZc0ihIple0VyWGH5bza0DLW+C8ttF8KqICUfL8S8mZgjbXvVg2fY\n"
+ + "HLW9lWR/Pkco2yRc8gZyr9FGkXOcmJ8aFaCuJnGm/IVRCieYp60If4DoAKz49xpF\n"
+ + "CF6RjOAJ//UGSp/ySjHMmT8PLO7NvhsT4XDDGTSeIYYpO++tbEIcLcjW9m2k5Gnh\n"
+ + "kmEenr0hdcpeLgsP3Fsy7JxyQNpL\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=Actalis Authentication CA G3, O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT
+ // Issuer: CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, L=Milan, C=IT
+ // SN: 741d584a 72fc06bc
+ // Valid from: Wed Feb 12 22:32:23 PST 2014
+ // Valid till: Mon Feb 12 22:32:23 PST 2024
+ private static final String INT_REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIGTTCCBDWgAwIBAgIIdB1YSnL8BrwwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE\n"
+ + "BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w\n"
+ + "MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290\n"
+ + "IENBMB4XDTE0MDIxMzE1MDIyM1oXDTI0MDIxMzE1MDIyM1owezELMAkGA1UEBhMC\n"
+ + "SVQxDzANBgNVBAgMBk1pbGFubzEPMA0GA1UEBwwGTWlsYW5vMSMwIQYDVQQKDBpB\n"
+ + "Y3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzElMCMGA1UEAwwcQWN0YWxpcyBBdXRo\n"
+ + "ZW50aWNhdGlvbiBDQSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n"
+ + "AMzhDjmhNDym6ze3PegbIKmiavXpAjgVCZ344k1DOtdSCV6k3h3rqfHqFn3mrayA\n"
+ + "btmJ0NeC886WxUUsJwHJ3bOnNBQZIHxLV+1RVD/6TQqb6/bPJu4rDwEfhbJSmErc\n"
+ + "29wUJWqxXMhSAWTHi3Pq0vrkx59e5KTEyfB2kHo6InlR72sCCRdtCL9aDuDm8nYK\n"
+ + "pTSAJr36ultwME5NyCNSyN2JIK0wYbEi7MVNbp5KN9MusTp3cOMDoVBreYulmnEu\n"
+ + "TNazmoAv0K8oLS7iX7c9x+zGjUUAucFEuSlRn3sL6hFAiKjy4PDClvnyqQHBBdZr\n"
+ + "/3JOxAcgXv7aZ4/STeXeDXsCAwEAAaOCAeMwggHfMEEGCCsGAQUFBwEBBDUwMzAx\n"
+ + "BggrBgEFBQcwAYYlaHR0cDovL3BvcnRhbC5hY3RhbGlzLml0L1ZBL0FVVEgtUk9P\n"
+ + "VDAdBgNVHQ4EFgQUqqr9yowdTfEug+EG/PqO6g4jrj0wDwYDVR0TAQH/BAUwAwEB\n"
+ + "/zAfBgNVHSMEGDAWgBRS2Ig6yJ94Zu2J83s4cJTJAgI20DBUBgNVHSAETTBLMEkG\n"
+ + "BFUdIAAwQTA/BggrBgEFBQcCARYzaHR0cHM6Ly9wb3J0YWwuYWN0YWxpcy5pdC9S\n"
+ + "ZXBvc2l0b3J5L1BvbGljeS9TU0wvQ1BTMIHiBgNVHR8EgdowgdcwgZSggZGggY6G\n"
+ + "gYtsZGFwOi8vbGRhcC5hY3RhbGlzLml0L2NuJTNkQWN0YWxpcyUyMEF1dGhlbnRp\n"
+ + "Y2F0aW9uJTIwUm9vdCUyMENBLG8lM2RBY3RhbGlzJTIwUy5wLkEuJTJmMDMzNTg1\n"
+ + "MjA5NjcsYyUzZElUP2NlcnRpZmljYXRlUmV2b2NhdGlvbkxpc3Q7YmluYXJ5MD6g\n"
+ + "PKA6hjhodHRwOi8vcG9ydGFsLmFjdGFsaXMuaXQvUmVwb3NpdG9yeS9BVVRILVJP\n"
+ + "T1QvZ2V0TGFzdENSTDAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB\n"
+ + "ABP93l+9QBgzHF0Clf3gMAelGqwXT25DwZVFIkBw6YyqOPcaqzw1XKHJJEMQ8xOp\n"
+ + "8uuiPLP/ObxEXBBvH7ofNW7nRUIzGsuLPhzdfJhdzilCVAvz4WRsX44nWOQS4Qu0\n"
+ + "npo7dbq/KxFUCUO9yNEJp6YxNloy8XFIlazkHFTKGJqoUpsGoc7B9YmPchhE2FPb\n"
+ + "OZiOCg4Y2Qp43UJfnENgZ3gJFh16juQE1uS8Q/JJI7ZzJfJ/W0uQoDnCprOPUpLF\n"
+ + "G03e0asFxwQqhL84Jvf7rJZaWvwydHP4hH47nzpHWEGXwfJLXXoO7LHgqVB7K9Ar\n"
+ + "Zf3pY0S/3Fs+AN/PrEY3Z3rb7ypQLRiot1oJLl8matiGEF4aFL5DDkr9wfRAZ8S8\n"
+ + "WT69vN68ENGgEwyeZSlQxn+4g6quHRav0fmF2fGnLaq7tteSPVocT7XaMEpkHqNs\n"
+ + "x1q/PJbr39s/1QVZtS9CrdoCr0QAnBaX//PPB6ansSLFcvEqM9QcV9xQZex88ToX\n"
+ + "nk3TcHtA0ezWJlCkg626MhdQZrhHbkauHfIGSOmCkn3zHp0BZQ6Vo7UOdRMT7QS7\n"
+ + "y7AkET9Qmapwh2CFUdCJSXklVRd+06XhhOB37NQU0pGJQJ3xjEPrILZ8kLhW3Tyq\n"
+ + "Iv30LW7MXZ4yQn/JHEZbuiOOb4R45hsPZxe6gOq/e+sf\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=ssltest-r.actalis.it, O=Actalis S.p.A., L=Ponte San Pietro, ST=Bergamo, C=IT
+ // Issuer: CN=Actalis Authentication CA G3, O=Actalis S.p.A./03358520967, L=Milano, ST=Milano, C=IT
+ // SN: 0455de97 5c71c96f
+ // Valid from: Thu Jan 28 16:23:52 PST 2016
+ // Valid till: Mon Jan 28 16:23:52 PST 2019
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFmDCCBICgAwIBAgIIBFXel1xxyW8wDQYJKoZIhvcNAQELBQAwezELMAkGA1UE\n"
+ + "BhMCSVQxDzANBgNVBAgMBk1pbGFubzEPMA0GA1UEBwwGTWlsYW5vMSMwIQYDVQQK\n"
+ + "DBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzElMCMGA1UEAwwcQWN0YWxpcyBB\n"
+ + "dXRoZW50aWNhdGlvbiBDQSBHMzAeFw0xNjAxMjkwODUzNTJaFw0xOTAxMjkwODUz\n"
+ + "NTJaMHIxCzAJBgNVBAYTAklUMRAwDgYDVQQIDAdCZXJnYW1vMRkwFwYDVQQHDBBQ\n"
+ + "b250ZSBTYW4gUGlldHJvMRcwFQYDVQQKDA5BY3RhbGlzIFMucC5BLjEdMBsGA1UE\n"
+ + "AwwUc3NsdGVzdC1yLmFjdGFsaXMuaXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw\n"
+ + "ggEKAoIBAQClbzoXCvD21FD7Oy/TKZu4fmDFJrISrNfasLlC3krLHkgb1vg23Z1P\n"
+ + "+7rIymDgrJSzjvYmisl+VM7xXxTsyI2pp9Qp/uzTMAMML9ISd/s0LaMBiNN5iPyj\n"
+ + "W91gGzGe30Jc319afKwFBaveSv7NO3DWsmHw9koezWkKUug2dnQCVXk1uTSdobnq\n"
+ + "wOgwxdd86LpZnFLxBIYdU68S4vogAQZjdja/S1+tF6JnfvY6o/xRJmQckVtNmUs6\n"
+ + "Dj3KoN2o/8BEgSCYcJz8tfoZcVazVkWOp/u6moUnm1/IKSYNgtHnB1ub0fB2AttW\n"
+ + "Vi7cs3SG/tDMMP8yc1kWScWf8CYj/AI1AgMBAAGjggInMIICIzA/BggrBgEFBQcB\n"
+ + "AQQzMDEwLwYIKwYBBQUHMAGGI2h0dHA6Ly9vY3NwMDMuYWN0YWxpcy5pdC9WQS9B\n"
+ + "VVRILUczMB0GA1UdDgQWBBRIKN5WmrjivlnT1rDzsH1WZ+PuvTAMBgNVHRMBAf8E\n"
+ + "AjAAMB8GA1UdIwQYMBaAFKqq/cqMHU3xLoPhBvz6juoOI649MGAGA1UdIARZMFcw\n"
+ + "SwYGK4EfARQBMEEwPwYIKwYBBQUHAgEWM2h0dHBzOi8vcG9ydGFsLmFjdGFsaXMu\n"
+ + "aXQvUmVwb3NpdG9yeS9Qb2xpY3kvU1NML0NQUzAIBgZngQwBAgIwgd8GA1UdHwSB\n"
+ + "1zCB1DCBlKCBkaCBjoaBi2xkYXA6Ly9sZGFwMDMuYWN0YWxpcy5pdC9jbiUzZEFj\n"
+ + "dGFsaXMlMjBBdXRoZW50aWNhdGlvbiUyMENBJTIwRzMsbyUzZEFjdGFsaXMlMjBT\n"
+ + "LnAuQS4lMmYwMzM1ODUyMDk2NyxjJTNkSVQ/Y2VydGlmaWNhdGVSZXZvY2F0aW9u\n"
+ + "TGlzdDtiaW5hcnkwO6A5oDeGNWh0dHA6Ly9jcmwwMy5hY3RhbGlzLml0L1JlcG9z\n"
+ + "aXRvcnkvQVVUSC1HMy9nZXRMYXN0Q1JMMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE\n"
+ + "FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0RBBgwFoIUc3NsdGVzdC1yLmFj\n"
+ + "dGFsaXMuaXQwDQYJKoZIhvcNAQELBQADggEBAHZLND53/CZoMlDtfln0ZByCEhoF\n"
+ + "/XtA9cYy2azRGgS/VY4WUccvg99MM50cwn5GPRsJpoaFXeDrjV3DkOUK1jERzjx4\n"
+ + "5y83K/AkCGe7uU17aS+tweETizBAfHNj78oHmZDmkDSEY2STaeuHNDJ9ft0v3QTb\n"
+ + "VW54R5W3OBU7L/sJoEUdRxzGN7vO82PboGvyApMCWDRLKE7bPP4genQtF3XPcaFl\n"
+ + "ekuSiEVYS+KnM2v9tCWHqw6x7raWHFB9w1kAKNwv0hbEJkeC+a2bCdPwv8hs//sa\n"
+ + "gUF4p61mIpf+5qmQ6gcZOClPWyrbYdQdfCvKgbEdKhwB0v5KS0NIRRn41SE=\n"
+ + "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+ boolean ocspEnabled = false;
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ ocspEnabled = true;
+ }
+
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT_VALID},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Revoked certificate is using SHA1 signature
+ if (ocspEnabled) {
+ // Revoked test certificate is expired
+ // and backdated revocation check is only possible with OCSP
+ pathValidator.setValidationDate("July 01, 2016");
+ }
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT_REVOKED},
+ ValidatePathWithParams.Status.REVOKED,
+ "Fri Jan 29 01:06:42 PST 2016", System.out);
+
+ // reset validation date back to current date
+ pathValidator.resetValidationDate();
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java
new file mode 100644
index 0000000000..2a1a846161
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/BuypassCA.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2017, 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 8189131
+ * @summary Interoperability tests with Buypass Class 2 and Class 3 CA
+ * @build ValidatePathWithParams
+ * @run main/othervm/timeout=180 -Djava.security.debug=certpath BuypassCA OCSP
+ * @run main/othervm/timeout=180 -Djava.security.debug=certpath BuypassCA CRL
+ */
+
+ /*
+ * Obtain test artifacts for Buypass Class 2 and Class 3 CAs from:
+ * Class 2:
+ * https://valid.domainplus.ca22.ssl.buypass.no/CA2Class2 (valid)
+ * https://revoked.domainplus.ca22.ssl.buypass.no (revoked)
+ *
+ * Class3:
+ * https://valid.business.ca23.ssl.buypass.no (valid)
+ * https://revoked.business.ca23.ssl.buypass.no (revoked)
+ */
+public class BuypassCA {
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ boolean ocspEnabled = true;
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ ocspEnabled = false;
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ new BuypassClass2().runTest(pathValidator);
+ new BuypassClass3().runTest(pathValidator, ocspEnabled);
+ }
+}
+
+class BuypassClass2 {
+
+ // Owner: CN=Buypass Class 2 CA 2, O=Buypass AS-983163327, C=NO
+ // Issuer: CN=Buypass Class 2 Root CA, O=Buypass AS-983163327, C=NO
+ private static final String INT_CLASS_2 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFCzCCAvOgAwIBAgIBGDANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd\n"
+ + "MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg\n"
+ + "Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjEwMTYxN1oXDTMwMTAyNjEwMTYxN1ow\n"
+ + "SzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0w\n"
+ + "GwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMjCCASIwDQYJKoZIhvcNAQEBBQAD\n"
+ + "ggEPADCCAQoCggEBAJyrZ8aWSw0PkdLsyswzK/Ny/A5/uU6EqQ99c6omDMpI+yNo\n"
+ + "HjUO42ryrATs4YHla+xj+MieWyvz9HYaCnrGL0CE4oX8M7WzD+g8h6tUCS0AakJx\n"
+ + "dC5PBocUkjQGZ5ZAoF92ms6C99qfQXhHx7lBP/AZT8sCWP0chOf9/cNxCplspYVJ\n"
+ + "HkQjKN3VGa+JISavCcBqf33ihbPZ+RaLjOTxoaRaWTvlkFxHqsaZ3AsW71qSJwaE\n"
+ + "55l9/qH45vn5mPrHQJ8h5LjgQcN5KBmxUMoA2iT/VSLThgcgl+Iklbcv9rs6aaMC\n"
+ + "JH+zKbub+RyRijmyzD9YBr+ZTaowHvJs9G59uZMCAwEAAaOB9jCB8zAPBgNVHRMB\n"
+ + "Af8EBTADAQH/MB8GA1UdIwQYMBaAFMmAd+BikoL1RpzzuvdMw964o605MB0GA1Ud\n"
+ + "DgQWBBSSrWWJsgAPy1ENwSPslE6PwQQ/dzAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0g\n"
+ + "BAowCDAGBgRVHSAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwuYnV5cGFz\n"
+ + "cy5uby9jcmwvQlBDbGFzczJSb290Q0EuY3JsMD4GCCsGAQUFBwEBBDIwMDAuBggr\n"
+ + "BgEFBQcwAYYiaHR0cDovL29jc3AuYnV5cGFzcy5uby9vY3NwL0JQT2NzcDANBgkq\n"
+ + "hkiG9w0BAQsFAAOCAgEAq8IVUouNdeHQljyp8xpa9GC7rpSRXGRRTolSXNa9TUfU\n"
+ + "48Z0Vj3x9jT58I+I8P7fKp+p4Wdu0kcwxOXsooP8hdGLqXY4nV9amkNRiTs99xa3\n"
+ + "Qu/KdLeAPEeeKztxDCLXGmsC4+1G6DuDrOkwSm9Tm+HxSZRGR4Qo3mU3CCSz37us\n"
+ + "q7I0mnY4cCeBPQ3zW5J7k7KmMpUlxOPnLpaASY2JhoeiWIWddH6LUsMkZk1jDv+M\n"
+ + "Hyw2JWZUEUMCZoxLZ7F+4xP7v8wcEtICFo6tZIaawq9p/S6+mJLcoQ7wdQBM0+NA\n"
+ + "cc1MnSbPz75WP4cFhVf1SFq5gBBMCgzYaw+A9bJxDgqV3IMG6TtWfOWz7KhMV+EL\n"
+ + "iVp0fXua2GITRwr+htWnID3ShbHOtCMUm9qrqC6aWNPvJqqKLdhgU9bQ/s5o05a0\n"
+ + "D8NFT07l8yY6+ge+PPHOidnZrTNFIF9dtEdtyXGNrcqhZF0QvqeV1yZ/Kf2+W4pa\n"
+ + "Wor82CuDZNfcf0lje3guk+oZexxpIO57eGJQh9iGLM5dBeEMF7+f5j/1/rGsf6vA\n"
+ + "KkudpjiTl1v/GoO2zMDTTQVcjEsLSYSV0+s2p5QTXuAXrL0/ER3KQRvewIAtmzFg\n"
+ + "IaPy7t2TV0olHISRMvaEz4Guh2biuO/N6SP3pkk3dsMxiEVw7Xc+ouCb03Rz3aA=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=valid.domainplus.ca22.ssl.buypass.no
+ // Issuer: CN=Buypass Class 2 CA 2, O=Buypass AS-983163327, C=NO
+ // Serial number: f0673c7183c95b38c93
+ // Valid from: Mon Jan 25 00:20:55 PST 2016 until: Fri Jan 25 14:59:00 PST 2019
+ private static final String VALID_CLASS_2 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIEgzCCA2ugAwIBAgIKDwZzxxg8lbOMkzANBgkqhkiG9w0BAQsFADBLMQswCQYD\n"
+ + "VQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMM\n"
+ + "FEJ1eXBhc3MgQ2xhc3MgMiBDQSAyMB4XDTE2MDEyNTA4MjA1NVoXDTE5MDEyNTIy\n"
+ + "NTkwMFowLzEtMCsGA1UEAwwkdmFsaWQuZG9tYWlucGx1cy5jYTIyLnNzbC5idXlw\n"
+ + "YXNzLm5vMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwhA0eVz8ADqx\n"
+ + "dcrIZUzCf1n+kaBFyEF4WteUMtM4ta7szTm19f1/O4LRwr+pI5qQDgWHnHMX9sit\n"
+ + "rKOJPfMRgWrViaQ5y9QCZ4h2BIuDe61XVGkEcUiOoNojLRvDrbjpknI69nb1wbjn\n"
+ + "fpmCQVjYXoandr7RsexdWG4e+s6rk5Jk/zAUzU3Vbi0lmDJ62Dd+Dk3/IVrSebOp\n"
+ + "eIDniRX4vjIeucnDDTQ1VqSIN+gYNR/bMxXKFbScGAG+BpgZMwetJBJhTi7zlOgR\n"
+ + "4zAtdvvpJNN1pmNCsmJaM25WQgH6a05cTQtgYN//MKqTDww7z+LfK37mOxh3vBTu\n"
+ + "TR5S6VxzQQIDAQABo4IBgzCCAX8wCQYDVR0TBAIwADAfBgNVHSMEGDAWgBSSrWWJ\n"
+ + "sgAPy1ENwSPslE6PwQQ/dzAdBgNVHQ4EFgQUIs9OWkfc6S1c8mbYgi6Ns1kzh0Mw\n"
+ + "DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAf\n"
+ + "BgNVHSAEGDAWMAoGCGCEQgEaAQIEMAgGBmeBDAECATA6BgNVHR8EMzAxMC+gLaAr\n"
+ + "hilodHRwOi8vY3JsLmJ1eXBhc3Mubm8vY3JsL0JQQ2xhc3MyQ0EyLmNybDAvBgNV\n"
+ + "HREEKDAmgiR2YWxpZC5kb21haW5wbHVzLmNhMjIuc3NsLmJ1eXBhc3Mubm8wdQYI\n"
+ + "KwYBBQUHAQEEaTBnMC4GCCsGAQUFBzABhiJodHRwOi8vb2NzcC5idXlwYXNzLm5v\n"
+ + "L29jc3AvQlBPY3NwMDUGCCsGAQUFBzAChilodHRwOi8vY3J0LmJ1eXBhc3Mubm8v\n"
+ + "Y3J0L0JQQ2xhc3MyQ0EyLmNlcjANBgkqhkiG9w0BAQsFAAOCAQEAjDPxDQnnzH+v\n"
+ + "Mnj8dRM6NPBVXl4JNofWlwqzYdu+HauFeF3AOZVVyr/YbOR9/ewDrScOvrGohndV\n"
+ + "7Si0l5hz3fo51Ra81TyR8kWR7nJC2joidT1X4a0hF9zu8CNQNVmkOhoACgeuv42R\n"
+ + "NDwmj9TfpNRyC4RA7/NzXMeRJYfOrh18S9VHhCzsWScd9td3u7hrhBOPPOql9f2K\n"
+ + "t9Hcevo+cceE6bGYwbW6xNr3iPOh31shMxgRUMojVamtH70tYMi+0e0lrzXdxgGO\n"
+ + "ISnXBS2HptakUIxF3feTOjBhhh5vb9RJxfdJA///ggkR3L51MfjrusucpNoz3k3P\n"
+ + "f5e7ZlSJ6g==\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=revoked.domainplus.ca22.ssl.buypass.no
+ // Issuer: CN=Buypass Class 2 CA 2, O=Buypass AS-983163327, C=NO
+ // Serial number: f07a517dfc19ea8bf8f
+ // Valid from: Mon Jan 25 00:22:09 PST 2016 until: Fri Jan 25 14:59:00 PST 2019
+ private static final String REVOKED_CLASS_2 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIEhzCCA2+gAwIBAgIKDwelF9/Bnqi/jzANBgkqhkiG9w0BAQsFADBLMQswCQYD\n"
+ + "VQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMM\n"
+ + "FEJ1eXBhc3MgQ2xhc3MgMiBDQSAyMB4XDTE2MDEyNTA4MjIwOVoXDTE5MDEyNTIy\n"
+ + "NTkwMFowMTEvMC0GA1UEAwwmcmV2b2tlZC5kb21haW5wbHVzLmNhMjIuc3NsLmJ1\n"
+ + "eXBhc3Mubm8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjp/5BLRjH\n"
+ + "03XNNT2YXqg+txclRaUu88Rjbj4oEudFbkGTl+oBhmXX4QjM4WGvgw1AHW7nePWF\n"
+ + "/j3aR1kWJCl/ZOe097mb0V0dIwK6u6RVx9ERd4ITa/cmUJjy1+D+vCsT0elJY1vf\n"
+ + "vbwCdaloS7MZDG3wmJGxrUz7fo7t/JdsW481Ymau3xVTQ+45MusPmOE8RZ6nggIQ\n"
+ + "dZIA00XPhlQwg5ivuPwtcNNZIkk1fkU+5J+RUOI5qHA9zH2s1Hly6PzTATCxSDSi\n"
+ + "zqAmBH0ehrWqCWiKH5P3J8dCRA6qa2n5pD71CweLrUsbmztkBHUlYKlZ0fP6bGiI\n"
+ + "ZDMBLL/aFQybAgMBAAGjggGFMIIBgTAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFJKt\n"
+ + "ZYmyAA/LUQ3BI+yUTo/BBD93MB0GA1UdDgQWBBQZICByGObE/pJISOcMavbKRl2L\n"
+ + "+zAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\n"
+ + "MB8GA1UdIAQYMBYwCgYIYIRCARoBAgQwCAYGZ4EMAQIBMDoGA1UdHwQzMDEwL6At\n"
+ + "oCuGKWh0dHA6Ly9jcmwuYnV5cGFzcy5uby9jcmwvQlBDbGFzczJDQTIuY3JsMDEG\n"
+ + "A1UdEQQqMCiCJnJldm9rZWQuZG9tYWlucGx1cy5jYTIyLnNzbC5idXlwYXNzLm5v\n"
+ + "MHUGCCsGAQUFBwEBBGkwZzAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuYnV5cGFz\n"
+ + "cy5uby9vY3NwL0JQT2NzcDA1BggrBgEFBQcwAoYpaHR0cDovL2NydC5idXlwYXNz\n"
+ + "Lm5vL2NydC9CUENsYXNzMkNBMi5jZXIwDQYJKoZIhvcNAQELBQADggEBAAdjMdlP\n"
+ + "qYNK+YkrqTgQV0dblIazL/cIhMPByjnEkfxew9tDxpcMWafIFKcgM/QxYJG/mzoL\n"
+ + "sSQ9pzzuGLQX7eAPA3rlWoQBusOeOaC3HQqy73kGStd7H8HPa3m+q47Z6JG0w+Fb\n"
+ + "rk8odrml+8rAEPLBlldB39xJuNVHjmlyTEDSC4azEXjfV4+kj8uE86sm+AoTt4Ba\n"
+ + "tEZSbKp70oH63QKBAEHORMM4gXeP+WG276p3kTcL1VUfgQw7vVmGN0C8DjhK4BAC\n"
+ + "0PUChr8agu0F5YcqpGxjLemMnDrqW+Bi/JYmGhEjWTiLSyYSlvJb1dAFUyPlc958\n"
+ + "pmOu5xTMEatiPFI=\n"
+ + "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID_CLASS_2, INT_CLASS_2},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED_CLASS_2, INT_CLASS_2},
+ ValidatePathWithParams.Status.REVOKED,
+ "Mon Jan 25 00:24:47 PST 2016", System.out);
+ }
+}
+
+class BuypassClass3 {
+
+ // Owner: CN=Buypass Class 3 CA 2, O=Buypass AS-983163327, C=NO
+ // Issuer: CN=Buypass Class 3 Root CA, O=Buypass AS-983163327, C=NO
+ private static final String INT_CLASS_3 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFCzCCAvOgAwIBAgIBGDANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd\n"
+ + "MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg\n"
+ + "Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA5MTYxN1oXDTMwMTAyNjA5MTYxN1ow\n"
+ + "SzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0w\n"
+ + "GwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMjCCASIwDQYJKoZIhvcNAQEBBQAD\n"
+ + "ggEPADCCAQoCggEBAL1OFdoURRXuCuwTBJpuCKDE8Euzcg0AeCRGq3VdagbChyCE\n"
+ + "CQ5vYWwmpHCyFl1b+r2KyWdQBBdG+msAcIYZal5cjZzrTWvbkfiAD/OneMjhqYB0\n"
+ + "pTQIXbTjpPUMOjFM8waNZcqGJqC9H+Z9NkjK5THAK0oOOfKNPHg1MeImbOHVw0fR\n"
+ + "48WnNrPpnQDt+SbPFSvw+dACDAybx1XgjMPq7pmZDWbkajOz4yCvrgZm6jvAPeT3\n"
+ + "qkBFh7zOZ3IZVdfmRjVahx0iXp5TJ1SsrRr/uCiae1O+NR//XDG3dl9j17HsFlhY\n"
+ + "Rl6EvEfVV0OcW94Ret9uBUF73ANZl0b+gwCXnV0CAwEAAaOB9jCB8zAPBgNVHRMB\n"
+ + "Af8EBTADAQH/MB8GA1UdIwQYMBaAFEe4zf/lb+74suwvTg75JbCOPGvDMB0GA1Ud\n"
+ + "DgQWBBQiMC7S+/ZLysC4O9IExOly5pebDDAOBgNVHQ8BAf8EBAMCAQYwEQYDVR0g\n"
+ + "BAowCDAGBgRVHSAAMD0GA1UdHwQ2MDQwMqAwoC6GLGh0dHA6Ly9jcmwuYnV5cGFz\n"
+ + "cy5uby9jcmwvQlBDbGFzczNSb290Q0EuY3JsMD4GCCsGAQUFBwEBBDIwMDAuBggr\n"
+ + "BgEFBQcwAYYiaHR0cDovL29jc3AuYnV5cGFzcy5uby9vY3NwL0JQT2NzcDANBgkq\n"
+ + "hkiG9w0BAQsFAAOCAgEAaOLyxpj2t9k9Rzkxkcj/teTNOWxBLPZDi+eFx3u7laf2\n"
+ + "mX/ZUSSE4g7OiKnD7ozWk9Qgocn3rBWGDKsp676RwWV97Elofz73Oebei6P3Gg/9\n"
+ + "CD8y6rf8xHRxru5d1ZQ1NkWdPwYI38jlt3LaDjJKZjJW7pOPIMRvw1Y1AY3mYgCJ\n"
+ + "Qqpw8jgukHIP0454DPzkUXzg/ZVJG0swmFmjYfARleSPidcs5BJx5ngpcUS4745g\n"
+ + "mN9PQ578+ROIbML4Jx83myivlyTQSPdYSwzSswb1RVBJmiF9qC0B1hivCrs4BATu\n"
+ + "YeaPV6CiNDr0jGnbxAskz7QDNR6uJSUKX3L9iY2TB/4/5hJ9TZ/YDI6OEG/wVtBz\n"
+ + "5FkU0ucztyQa4UG1mXR8Zbs/zt9Fj0Xn8f5IM3dB/s/r8c1AFDIcLRUqP/LkI9Wj\n"
+ + "XovWr79PEJcIfIln0AfzYfBBxCRE+4QHcVhci6p/mbyl2a+Rf8ZGNTiDLaWSZp5x\n"
+ + "jqdaq5UQaoZK8XQ+JVR0etep/KPgVMXq5Zv16YEb2vjs//RfxT8psDZLe/37+Bs4\n"
+ + "AG9sdT/bsH7HDQwodTon/HvMmxt4EiU/1Sjco4Fok9VmSE2UVjIghajbbTSKR3LV\n"
+ + "UuU19x12fKp+htO8L+wVlGgxXb9WvDBNHCe6RmR4jqavmvrAyCPtrx3cXwqGmXA=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: SERIALNUMBER=983163327, CN=valid.business.ca23.ssl.buypass.no,
+ // O=BUYPASS AS, L=OSLO, OID.2.5.4.17=0484, C=NO
+ // Issuer: CN=Buypass Class 3 CA 2, O=Buypass AS-983163327, C=NO
+ // Serial number: 97631b91e98293b35c8
+ // Valid from: Fri Feb 06 00:57:04 PST 2015 until: Fri Feb 09 14:59:00 PST 2018
+ private static final String VALID_CLASS_3 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIE1DCCA7ygAwIBAgIKCXYxuR6YKTs1yDANBgkqhkiG9w0BAQsFADBLMQswCQYD\n"
+ + "VQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMM\n"
+ + "FEJ1eXBhc3MgQ2xhc3MgMyBDQSAyMB4XDTE1MDIwNjA4NTcwNFoXDTE4MDIwOTIy\n"
+ + "NTkwMFowgYExCzAJBgNVBAYTAk5PMQ0wCwYDVQQRDAQwNDg0MQ0wCwYDVQQHDARP\n"
+ + "U0xPMRMwEQYDVQQKDApCVVlQQVNTIEFTMSswKQYDVQQDDCJ2YWxpZC5idXNpbmVz\n"
+ + "cy5jYTIzLnNzbC5idXlwYXNzLm5vMRIwEAYDVQQFEwk5ODMxNjMzMjcwggEiMA0G\n"
+ + "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbahUoF2A7upqIxDQKraZ+aEOzNkHF\n"
+ + "1fIQEtUMQS1OTB8la7pWsBnv1gk9Ja2ifIrwdSxAjefL3SXR47h4vxUMnufMnkTk\n"
+ + "PERXft/XR8/jZQZRpznnN/V89ctb8qcVhHCooTIELOBzF9QAmDnawZQogwhDNLNy\n"
+ + "kLtWsl75X547DS/Z5hsqCqXPyOiFzkHY59uamYu48TF9d7HwQ741H0YhehoxTl/O\n"
+ + "YqzW2wqYxqhQuCX5IuYER7G/P3G6UAm+VB9aujtWW+TBT9+iWh0aT+C7ezDtREse\n"
+ + "lwb44svf8S3iW18KlSF8EMT0qwqNpA8njOCQiSgluYD+Uk9E5f8505UzAgMBAAGj\n"
+ + "ggGBMIIBfTAJBgNVHRMEAjAAMB8GA1UdIwQYMBaAFCIwLtL79kvKwLg70gTE6XLm\n"
+ + "l5sMMB0GA1UdDgQWBBQncKIaP6HdQV8RIBO+dddWDSKvJjAOBgNVHQ8BAf8EBAMC\n"
+ + "BaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB8GA1UdIAQYMBYwCgYI\n"
+ + "YIRCARoBAwQwCAYGZ4EMAQICMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly9jcmwu\n"
+ + "YnV5cGFzcy5uby9jcmwvQlBDbGFzczNDQTIuY3JsMC0GA1UdEQQmMCSCInZhbGlk\n"
+ + "LmJ1c2luZXNzLmNhMjMuc3NsLmJ1eXBhc3Mubm8wdQYIKwYBBQUHAQEEaTBnMC4G\n"
+ + "CCsGAQUFBzABhiJodHRwOi8vb2NzcC5idXlwYXNzLm5vL29jc3AvQlBPY3NwMDUG\n"
+ + "CCsGAQUFBzAChilodHRwOi8vY3J0LmJ1eXBhc3Mubm8vY3J0L0JQQ2xhc3MzQ0Ey\n"
+ + "LmNlcjANBgkqhkiG9w0BAQsFAAOCAQEAqeA3IqMPn/az52twbNnimXIhIb7tWj7U\n"
+ + "NSBqr+httoQvNo7NbtVCgO/fM3/t0YN7rgZfP07QTn7L7CwoddrgHbnuCuFr9UhD\n"
+ + "df7cfY3cwDhWx+YKgXTkRZpXXrOPqeY2+9gaJlcQCnw66t5EBa4lSBnN0ZtkB4lT\n"
+ + "ujFP6BAyzZAjRdXWUidtErDWZri1uLmWAP0kQNez2toOcQ0XpbrbL8+nQtvOVOJv\n"
+ + "b/c8WoaoC14C32mAeC5bx4dQ3mpf3hQv9man1SPjY/rsDsWWjsaJAijl3YPtP2bU\n"
+ + "JRCCM7qfZWrY8/uBLG2llfjviKV9I6sT76w7TnawPsz+SkDXFm/nwg==\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: SERIALNUMBER=983163327, CN=revoked.business.ca23.ssl.buypass.no,
+ // O=BUYPASS AS, L=OSLO, OID.2.5.4.17=0402, C=NO
+ // Issuer: CN=Buypass Class 3 CA 2, O=Buypass AS-983163327, C=NO
+ private static final String REVOKED_CLASS_3 = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIE2DCCA8CgAwIBAgIKARno/wYhPtNtmjANBgkqhkiG9w0BAQsFADBLMQswCQYD\n"
+ + "VQQGEwJOTzEdMBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMM\n"
+ + "FEJ1eXBhc3MgQ2xhc3MgMyBDQSAyMB4XDTEzMDIwMTA5MTE0NFoXDTE2MDIwMTA5\n"
+ + "MTE0NFowgYMxCzAJBgNVBAYTAk5PMQ0wCwYDVQQRDAQwNDAyMQ0wCwYDVQQHDARP\n"
+ + "U0xPMRMwEQYDVQQKDApCVVlQQVNTIEFTMS0wKwYDVQQDDCRyZXZva2VkLmJ1c2lu\n"
+ + "ZXNzLmNhMjMuc3NsLmJ1eXBhc3Mubm8xEjAQBgNVBAUTCTk4MzE2MzMyNzCCASIw\n"
+ + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMmBUI0wNCz4kLikR5wog4QTUEmO\n"
+ + "XoGgjnQv0cKfDogbewK+0ngdyyR8dZOqSauQTGLlPTpo6DEWpD3Jqrr444MV6Vc1\n"
+ + "AGWnjk3T+KT5tKl6qJOQq17Y+HEnsTEzCo1kieVygpSu7FBa2OnhHNmLWThhGUEi\n"
+ + "mLqrEyfjMSb9zacvo06Zr7S8BauLRB3aM5BeMVF7Bj/9f/FvnB/y1cRDLG32WRCx\n"
+ + "K9IAFwCaJkfWsXx+bnaO4uEQwLFZ96p7L5mr+QNvI6QuweIY1hDM3RDM6HQkGTK9\n"
+ + "8iHSzGBSCGwOM24Ym3XM5vTbiV5uLno+QEYlJL/+qbYvarbO2gPF+6A6M10CAwEA\n"
+ + "AaOCAYMwggF/MAkGA1UdEwQCMAAwHwYDVR0jBBgwFoAUIjAu0vv2S8rAuDvSBMTp\n"
+ + "cuaXmwwwHQYDVR0OBBYEFNI2C2XKZkNRHZrHLkBhCMeDRN0KMA4GA1UdDwEB/wQE\n"
+ + "AwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwHwYDVR0gBBgwFjAK\n"
+ + "BghghEIBGgEDBDAIBgZngQwBAgIwOgYDVR0fBDMwMTAvoC2gK4YpaHR0cDovL2Ny\n"
+ + "bC5idXlwYXNzLm5vL2NybC9CUENsYXNzM0NBMi5jcmwwLwYDVR0RBCgwJoIkcmV2\n"
+ + "b2tlZC5idXNpbmVzcy5jYTIzLnNzbC5idXlwYXNzLm5vMHUGCCsGAQUFBwEBBGkw\n"
+ + "ZzAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuYnV5cGFzcy5uby9vY3NwL0JQT2Nz\n"
+ + "cDA1BggrBgEFBQcwAoYpaHR0cDovL2NydC5idXlwYXNzLm5vL2NydC9CUENsYXNz\n"
+ + "M0NBMi5jZXIwDQYJKoZIhvcNAQELBQADggEBAGNQe9cgrw/mN7bChof205NRS+TH\n"
+ + "A8f0JcKk1KrPYYW+ilyp6j3My26Sm9a4ZyKRhAS8fCxYUXWzfNvJNFYv2ttLuegl\n"
+ + "SFfeXjSJJZW9+wC5oRLta++62UTTxXp0Zf5UkMsHZCIjvnk0yGWZa0phyRCH89ca\n"
+ + "4vfRTOGNTNfX3d0jm/+fm70UNYHKZ/VcxVj0vH2Ij/kDUy7r2cw1gQ65RDUotnTu\n"
+ + "Yt59y3COyMZeYNMcuoss2XWnedFoD7fwCSkNqVbwjCxGVkL1+ivbWhqlCefaniZX\n"
+ + "Wy35oP1635RSxHbCMU9msmUO7FS8n1VH2edEC797gduK5pn2aBhy/MW0unU=\n"
+ + "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled)
+ throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID_CLASS_3, INT_CLASS_3},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ if (ocspEnabled) {
+ // Revoked test certificate is expired
+ // and backdated revocation check is only possible with OCSP
+ pathValidator.setValidationDate("July 01, 2013");
+ }
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED_CLASS_3, INT_CLASS_3},
+ ValidatePathWithParams.Status.REVOKED,
+ "Wed Feb 06 02:56:32 PST 2013", System.out);
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java
new file mode 100644
index 0000000000..e3edae4126
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/ComodoCA.java
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2017, 2019, 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 8189131
+ * @summary Interoperability tests with Comodo RSA, ECC, userTrust RSA, and
+ * userTrust ECC CAs
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath ComodoCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath ComodoCA CRL
+ */
+
+ /*
+ * Obtain TLS test artifacts for Comodo CAs from:
+ *
+ * Valid TLS Certificates:
+ * https://comodorsacertificationauthority-ev.comodoca.com
+ * https://comodoecccertificationauthority-ev.comodoca.com
+ * https://usertrustrsacertificationauthority-ev.comodoca.com
+ * https://usertrustecccertificationauthority-ev.comodoca.com
+ *
+ * Revoked TLS Certificates:
+ * https://comodorsacertificationauthority-ev.comodoca.com:444
+ * https://comodoecccertificationauthority-ev.comodoca.com:444
+ * https://usertrustrsacertificationauthority-ev.comodoca.com:444
+ * https://usertrustecccertificationauthority-ev.comodoca.com:444
+ */
+public class ComodoCA {
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ new ComodoRSA().runTest(pathValidator);
+ new ComodoECC().runTest(pathValidator);
+ new ComodoUserTrustRSA().runTest(pathValidator);
+ new ComodoUserTrustECC().runTest(pathValidator);
+ }
+}
+
+class ComodoRSA {
+
+ // Owner: CN=COMODO RSA Extended Validation Secure Server CA,
+ // O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
+ // Issuer: CN=COMODO RSA Certification Authority, O=COMODO CA Limited,
+ // L=Salford, ST=Greater Manchester, C=GB
+ // Serial number: 6a74380d4ebfed435b5a3f7e16abdd8
+ // Valid from: Sat Feb 11 16:00:00 PST 2012 until: Thu Feb 11 15:59:59 PST 2027
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIGDjCCA/agAwIBAgIQBqdDgNTr/tQ1taP34Wq92DANBgkqhkiG9w0BAQwFADCB\n"
+ + "hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n"
+ + "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n"
+ + "BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIwMjEy\n"
+ + "MDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n"
+ + "EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n"
+ + "Q09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQg\n"
+ + "VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC\n"
+ + "AQ8AMIIBCgKCAQEAlVbeVLTf1QJJe9FbXKKyHo+cK2JMK40SKPMalaPGEP0p3uGf\n"
+ + "CzhAk9HvbpUQ/OGQF3cs7nU+e2PsYZJuTzurgElr3wDqAwB/L3XVKC/sVmePgIOj\n"
+ + "vdwDmZOLlJFWW6G4ajo/Br0OksxgnP214J9mMF/b5pTwlWqvyIqvgNnmiDkBfBzA\n"
+ + "xSr3e5Wg8narbZtyOTDr0VdVAZ1YEZ18bYSPSeidCfw8/QpKdhQhXBZzQCMZdMO6\n"
+ + "WAqmli7eNuWf0MLw4eDBYuPCGEUZUaoXHugjddTI0JYT/8ck0YwLJ66eetw6YWNg\n"
+ + "iJctXQUL5Tvrrs46R3N2qPos3cCHF+msMJn4HwIDAQABo4IBaTCCAWUwHwYDVR0j\n"
+ + "BBgwFoAUu69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFDna/8ooFIqodBMI\n"
+ + "ueQOqdL6fp1pMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/AgEAMD4G\n"
+ + "A1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5j\n"
+ + "b21vZG8uY29tL0NQUzBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9k\n"
+ + "b2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggr\n"
+ + "BgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29t\n"
+ + "L0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz\n"
+ + "cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAERCnUFRK0iIXZebeV4R\n"
+ + "AUpSGXtBLMeJPNBy3IX6WK/VJeQT+FhlZ58N/1eLqYVeyqZLsKeyLeCMIs37/3mk\n"
+ + "jCuN/gI9JN6pXV/kD0fQ22YlPodHDK4ixVAihNftSlka9pOlk7DgG4HyVsTIEFPk\n"
+ + "1Hax0VtpS3ey4E/EhOfUoFDuPPpE/NBXueEoU/1Tzdy5H3pAvTA/2GzS8+cHnx8i\n"
+ + "teoiccsq8FZ8/qyo0QYPFBRSTP5kKwxpKrgNUG4+BAe/eiCL+O5lCeHHSQgyPQ0o\n"
+ + "fkkdt0rvAucNgBfIXOBhYsvss2B5JdoaZXOcOBCgJjqwyBZ9kzEi7nQLiMBciUEA\n"
+ + "KKlHMd99SUWa9eanRRrSjhMQ34Ovmw2tfn6dNVA0BM7pINae253UqNpktNEvWS5e\n"
+ + "ojZh1CSggjMziqHRbO9haKPl0latxf1eYusVqHQSTC8xjOnB3xBLAer2VBvNfzu9\n"
+ + "XJ/B288ByvK6YBIhMe2pZLiySVgXbVrXzYxtvp5/4gJYp9vDLVj2dAZqmvZh+fYA\n"
+ + "tmnYOosxWd2R5nwnI4fdAw+PKowegwFOAWEMUnNt/AiiuSpm5HZNMaBWm9lTjaK2\n"
+ + "jwLI5jqmBNFI+8NKAnb9L9K8E7bobTQk+p0pisehKxTxlgBzuRPpwLk6R1YCcYAn\n"
+ + "pLwltum95OmYdBbxN4SBB7SC\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: d3df2597cbed1ab6e02ee82021771614
+ // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH7jCCBtagAwIBAgIRANPfJZfL7Rq24C7oICF3FhQwDQYJKoZIhvcNAQELBQAw\n" +
+ "gZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO\n" +
+ "BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYD\n" +
+ "VQQDEy9DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" +
+ "ciBDQTAeFw0xODExMjkwMDAwMDBaFw0yMTAyMjYyMzU5NTlaMIIBWzERMA8GA1UE\n" +
+ "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" +
+ "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRsw\n" +
+ "GQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAU\n" +
+ "BgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAj\n" +
+ "BgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGDAWBgNVBAoTD1Nl\n" +
+ "Y3RpZ28gTGltaXRlZDEaMBgGA1UECxMRQ09NT0RPIEVWIFNHQyBTU0wxODA2BgNV\n" +
+ "BAMTL2NvbW9kb3JzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2Eu\n" +
+ "Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0P95lAFOOkEOy614\n" +
+ "rCX7OlOK0Xy0nPAcCFxAcLYBosX8YmXWuePHg596UyEqE3U530pTqiccY53bDiYP\n" +
+ "gSJgr1OlfC7BPLN+QKaeSrFmNgrcoAk3TXejgv7zLXOwZVS6Wk38Z8xrFNvhd2Z5\n" +
+ "J6RM/3U+HDfF7OKMGrexr77Ws7lEFpPUgd4eEe+IL1Y2sbwIiD+PkzIL2LjctkeJ\n" +
+ "FcsRHUvNP8wIhGyIbkARuJhdXkE13lKKIe0EnWrRkkf4DEvYRFpPjVUKmluhnBOG\n" +
+ "YkYaiTL0VaOnrPxToSfHR8Awkhk0TNbosAkUo8TKcRTTTiMUUIS6Y9SqoILiiDG6\n" +
+ "WmFjzQIDAQABo4IDcTCCA20wHwYDVR0jBBgwFoAUOdr/yigUiqh0Ewi55A6p0vp+\n" +
+ "nWkwHQYDVR0OBBYEFD5LhmEivA6h4az0EFPi5erz1TH+MA4GA1UdDwEB/wQEAwIF\n" +
+ "oDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBP\n" +
+ "BgNVHSAESDBGMDsGDCsGAQQBsjEBAgEFATArMCkGCCsGAQUFBwIBFh1odHRwczov\n" +
+ "L3NlY3VyZS5jb21vZG8uY29tL0NQUzAHBgVngQwBATBWBgNVHR8ETzBNMEugSaBH\n" +
+ "hkVodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FFeHRlbmRlZFZhbGlk\n" +
+ "YXRpb25TZWN1cmVTZXJ2ZXJDQS5jcmwwgYcGCCsGAQUFBwEBBHsweTBRBggrBgEF\n" +
+ "BQcwAoZFaHR0cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRW\n" +
+ "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8v\n" +
+ "b2NzcC5jb21vZG9jYS5jb20wOgYDVR0RBDMwMYIvY29tb2RvcnNhY2VydGlmaWNh\n" +
+ "dGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggF9BgorBgEEAdZ5AgQCBIIB\n" +
+ "bQSCAWkBZwB1AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABZ2Bx\n" +
+ "+EAAAAQDAEYwRAIgXot8xi2N4oV6A8n2aXJ/TI6oI5t30ZgiyR3jF8nY8tYCIGBB\n" +
+ "e7sTFniA3vzfxhMbYsyAEy50PNFCaqLjNoyOaGNqAHYAb1N2rDHwMRnYmQCkURX/\n" +
+ "dxUcEdkCwQApBo2yCJo32RMAAAFnYHH4LQAABAMARzBFAiBq8utPzn0fL5zPPQNB\n" +
+ "gueIXEFDXPw8s5D+pzD6+ySwegIhAJUCgsW++nO2JwYNwJTxPsHOWs7WpXqXCsVC\n" +
+ "/FlJ1HHbAHYAu9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e0YUAAAFnYHH4\n" +
+ "OAAABAMARzBFAiA7rSUo9XVQDb3CBLo85qFMzYzsylF223s0u4WXQTUGqQIhAKJq\n" +
+ "j602nEd4imaE9Wr7OWdIbbhLcNm5dhVZerk4MD6GMA0GCSqGSIb3DQEBCwUAA4IB\n" +
+ "AQBPeidaCGBGyFDK60+Eh8GyKQSMowcRA74B6C+JlQYTBtl024xAV7d3fnbULtzY\n" +
+ "rs5EGxlEPIR/ZLAETTdEi1mAalXAi2l1QDrmTeOGW+FZXlcXQuNeg56D9gkApftR\n" +
+ "yFFRLNScchNDsMwR3UOlJnD05DJk1J+SeNvOlefwfDHIlZBiQIrSxdWS8GIIkKLp\n" +
+ "4PIy+N4lgNEudi2LuRheEjmrkN9+NcKlU+v7lzlwCfWCDna2hacGRPRo5fAao5O0\n" +
+ "mlUzAYm76dn5dGGBVVqA0cfWnUeVfSTrlVb/QN+uYno4vIrpR5VBYPuJYU47vgzL\n" +
+ "YrTYerPngjPbZB0bfLOja0vb\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodorsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=COMODO RSA Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: 720aa2cfa40094521224f901a984b167
+ // Valid from: Thu Jun 29 17:00:00 PDT 2017 until: Sun Sep 29 16:59:59 PDT 2019
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH8jCCBtqgAwIBAgIQcgqiz6QAlFISJPkBqYSxZzANBgkqhkiG9w0BAQsFADCB\n" +
+ "kjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n" +
+ "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNV\n" +
+ "BAMTL0NPTU9ETyBSU0EgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVy\n" +
+ "IENBMB4XDTE3MDYzMDAwMDAwMFoXDTE5MDkyOTIzNTk1OVowggFdMREwDwYDVQQF\n" +
+ "EwgwNDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0\n" +
+ "ZSBPcmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZ\n" +
+ "BgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQG\n" +
+ "A1UECRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMG\n" +
+ "A1UECRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09N\n" +
+ "T0RPIENBIExpbWl0ZWQxGjAYBgNVBAsTEUNPTU9ETyBFViBTR0MgU1NMMTgwNgYD\n" +
+ "VQQDEy9jb21vZG9yc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2Nh\n" +
+ "LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAND/eZQBTjpBDsut\n" +
+ "eKwl+zpTitF8tJzwHAhcQHC2AaLF/GJl1rnjx4OfelMhKhN1Od9KU6onHGOd2w4m\n" +
+ "D4EiYK9TpXwuwTyzfkCmnkqxZjYK3KAJN013o4L+8y1zsGVUulpN/GfMaxTb4Xdm\n" +
+ "eSekTP91Phw3xezijBq3sa++1rO5RBaT1IHeHhHviC9WNrG8CIg/j5MyC9i43LZH\n" +
+ "iRXLER1LzT/MCIRsiG5AEbiYXV5BNd5SiiHtBJ1q0ZJH+AxL2ERaT41VCppboZwT\n" +
+ "hmJGGoky9FWjp6z8U6Enx0fAMJIZNEzW6LAJFKPEynEU004jFFCEumPUqqCC4ogx\n" +
+ "ulphY80CAwEAAaOCA3QwggNwMB8GA1UdIwQYMBaAFDna/8ooFIqodBMIueQOqdL6\n" +
+ "fp1pMB0GA1UdDgQWBBQ+S4ZhIrwOoeGs9BBT4uXq89Ux/jAOBgNVHQ8BAf8EBAMC\n" +
+ "BaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n" +
+ "TwYDVR0gBEgwRjA7BgwrBgEEAbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6\n" +
+ "Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmg\n" +
+ "R4ZFaHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRXh0ZW5kZWRWYWxp\n" +
+ "ZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYB\n" +
+ "BQUHMAKGRWh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4dGVuZGVk\n" +
+ "VmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDov\n" +
+ "L29jc3AuY29tb2RvY2EuY29tMDoGA1UdEQQzMDGCL2NvbW9kb3JzYWNlcnRpZmlj\n" +
+ "YXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMIIBgAYKKwYBBAHWeQIEAgSC\n" +
+ "AXAEggFsAWoAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAVz5\n" +
+ "cV7GAAAEAwBHMEUCIQCpgc0Eqw3g4pr+oX88h5xgL1VEAiDpqAhbRtilgYwBbgIg\n" +
+ "UaIm+n8AHi55nB//Sb4Nz18GYVcfELfpIzRh1vW9HbYAdwBWFAaaL9fC7NP14b1E\n" +
+ "sj7HRna5vJkRXMDvlJhV1onQ3QAAAVz5cVybAAAEAwBIMEYCIQDdsgC4KZ++OP44\n" +
+ "X7LbUcNaxe0kFzbctF2L3bnmhp9nXQIhAM0/g+PrZBIBpYlOtzidePi8bBHrLWn2\n" +
+ "uBiP3pYIntl4AHcA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFc\n" +
+ "+XFeoQAABAMASDBGAiEAoySTb/QKw7JwtZtPHnECEMzgENQSFy58Kl+Mvcd3SmcC\n" +
+ "IQD8cU66Ih3ejvt0OTX+lfxQPKyggQfm4Uk/lwn5LEJXbDANBgkqhkiG9w0BAQsF\n" +
+ "AAOCAQEAKEaSYWn3Hi8rfJS4cMTJoMkVp2vpPH2dGXySBEy67TEGRw9+f75w3q95\n" +
+ "r1m3P+xsR6dBoidTq/6wqUYI51lB4Fq9ylh1Stp5Gj54CuyT+S31l7lD7sl0KMsn\n" +
+ "HDUDQHId7hKeORYpiIZOcrKOglKdi1uiGwDgoiLKh98lUrZA6durrhH+sl69wqp2\n" +
+ "0XAu+3hurXzCoZFJfyngTO1kt9qcFUAxc5LofIa9QvC6VR7dI4aAh7dUpIRlnjG3\n" +
+ "jJ1mUMTqWO6TFTtddb+uQjDqNgkYYYNuSax1WMEIZWbIi13EjXK1GPQUXJe6gQin\n" +
+ "NUq9JH9NPK6m8A1YKT+wgzfTDeaV2Q==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Nov 29 08:41:09 PST 2018", System.out);
+ }
+}
+
+class ComodoECC {
+
+ // Owner: CN=COMODO ECC Extended Validation Secure Server CA,
+ // O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
+ // Issuer: CN=COMODO ECC Certification Authority, O=COMODO CA Limited,
+ // L=Salford, ST=Greater Manchester, C=GB
+ // Serial number: 61d4643b412b5d8d715499d8553aa03
+ // Valid from: Sun Apr 14 17:00:00 PDT 2013 until: Fri Apr 14 16:59:59 PDT 2028
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIDojCCAyigAwIBAgIQBh1GQ7QStdjXFUmdhVOqAzAKBggqhkjOPQQDAzCBhTEL\n"
+ + "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n"
+ + "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT\n"
+ + "IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTMwNDE1MDAw\n"
+ + "MDAwWhcNMjgwNDE0MjM1OTU5WjCBkjELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy\n"
+ + "ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N\n"
+ + "T0RPIENBIExpbWl0ZWQxODA2BgNVBAMTL0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFs\n"
+ + "aWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\n"
+ + "QgAEV3AaPyeTQy0aWXXkBJMR42DsJ5pnbliJe7ndaHzCDslVlY8ofpxeFiqluZrK\n"
+ + "KNcJeBU/Jl1YI9jLMyMZKsfSoaOCAWkwggFlMB8GA1UdIwQYMBaAFHVxpxlIGbyd\n"
+ + "nepBR9+UxEh3mdN5MB0GA1UdDgQWBBTTTsMZulhZ0Rxgt2FTRzund4/4ijAOBgNV\n"
+ + "HQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADA+BgNVHSAENzA1MDMGBFUd\n"
+ + "IAAwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNvbS9DUFMw\n"
+ + "TAYDVR0fBEUwQzBBoD+gPYY7aHR0cDovL2NybC5jb21vZG9jYS5jb20vQ09NT0RP\n"
+ + "RUNDQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwcQYIKwYBBQUHAQEEZTBjMDsG\n"
+ + "CCsGAQUFBzAChi9odHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9FQ0NBZGRU\n"
+ + "cnVzdENBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29t\n"
+ + "MAoGCCqGSM49BAMDA2gAMGUCMQDmPWS98nREWdt4xB83r9MVvgG5INpKHi6V1dUY\n"
+ + "lCqvSvXXjK0QvZSrOB7cj9RavGgCMG2xJNG+SvlTWEYpmK7eXSgmRUgoBDeQ0yDK\n"
+ + "lnxmeeOBnnCaDIxAcA3aCj2Gtdt3sA==\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: 603a5c2f85b63e00ba46ce8c3f6000b0
+ // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGXzCCBgWgAwIBAgIQYDpcL4W2PgC6Rs6MP2AAsDAKBggqhkjOPQQDAjCBkjEL\n" +
+ "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" +
+ "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" +
+ "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" +
+ "MB4XDTE4MTEyOTAwMDAwMFoXDTIxMDIyNjIzNTk1OVowggFXMREwDwYDVQQFEwgw\n" +
+ "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" +
+ "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZBgNV\n" +
+ "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQGA1UE\n" +
+ "CRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMGA1UE\n" +
+ "CRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEYMBYGA1UEChMPU2VjdGln\n" +
+ "byBMaW1pdGVkMRYwFAYDVQQLEw1DT01PRE8gRVYgU1NMMTgwNgYDVQQDEy9jb21v\n" +
+ "ZG9lY2NjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTBZMBMG\n" +
+ "ByqGSM49AgEGCCqGSM49AwEHA0IABLduqgUu00bv8n0fkYqiwM1tgvlLKRWZTkXO\n" +
+ "BIS3zWDIBZKGSoxJ8Cc7nR+mvrkT6jzoT4FHejxX0UBTnC45oYGjggNzMIIDbzAf\n" +
+ "BgNVHSMEGDAWgBTTTsMZulhZ0Rxgt2FTRzund4/4ijAdBgNVHQ4EFgQU6WdLcyrH\n" +
+ "BcOmd7whAxcxkeVUpFcwDgYDVR0PAQH/BAQDAgWAMAwGA1UdEwEB/wQCMAAwHQYD\n" +
+ "VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOwYMKwYBBAGy\n" +
+ "MQECAQUBMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20v\n" +
+ "Q1BTMAcGBWeBDAEBMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29tb2Rv\n" +
+ "Y2EuY29tL0NPTU9ET0VDQ0V4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNB\n" +
+ "LmNybDCBhwYIKwYBBQUHAQEEezB5MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0LmNv\n" +
+ "bW9kb2NhLmNvbS9DT01PRE9FQ0NFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2\n" +
+ "ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTA6\n" +
+ "BgNVHREEMzAxgi9jb21vZG9lY2NjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNv\n" +
+ "bW9kb2NhLmNvbTCCAX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYA7ku9t3XOYLrh\n" +
+ "Qmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFnYHQLpwAABAMARzBFAiB0pm9GZG/W\n" +
+ "REFW/umEd07eSzGsPZpRkOXahkiAmXiuxgIhAOiYZKB4Gr4JlAuQsajqbrS715L9\n" +
+ "03E7walRViBHMA3XAHcAb1N2rDHwMRnYmQCkURX/dxUcEdkCwQApBo2yCJo32RMA\n" +
+ "AAFnYHQLmwAABAMASDBGAiEAqUN6xU8mcNaYExuxUSZQR1WP5SZrgrDnAl+DN4t3\n" +
+ "R1MCIQCJseJMXtpzP2jB1d1sz/WS6pDERjutjYc0ko//m+WjlAB2ALvZ37wfinG1\n" +
+ "k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABZ2B0C6cAAAQDAEcwRQIgI42QfFzd\n" +
+ "f9W0a383BnL3nGgLQinrd7usIbA81LwOvlECIQD+fmSDEs6lwsS5EGtIvygWMs2F\n" +
+ "7FWI1I8ucE0ikP+wCjAKBggqhkjOPQQDAgNIADBFAiB3P9kNVyLpA8tovSGeRvdx\n" +
+ "VfA0Slz//EIeeHhbHz7D/AIhAN+WFuDimGKE1XcKrmucSBLSrYGWlY8XJcF6en3v\n" +
+ "KOC7\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=comodoecccertificationauthority-ev.comodoca.com, OU=COMODO EV SSL, O=COMODO CA Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=COMODO ECC Extended Validation Secure Server CA, O=COMODO CA Limited, L=Salford,
+ // ST=Greater Manchester, C=GB
+ // Serial number: 414e5d66ec7d15ca504213f2811d57af
+ // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGYDCCBgWgAwIBAgIQQU5dZux9FcpQQhPygR1XrzAKBggqhkjOPQQDAjCBkjEL\n" +
+ "MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE\n" +
+ "BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxODA2BgNVBAMT\n" +
+ "L0NPTU9ETyBFQ0MgRXh0ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB\n" +
+ "MB4XDTE3MDcwNDAwMDAwMFoXDTE5MTAwMzIzNTk1OVowggFZMREwDwYDVQQFEwgw\n" +
+ "NDA1ODY5MDETMBEGCysGAQQBgjc8AgEDEwJHQjEdMBsGA1UEDxMUUHJpdmF0ZSBP\n" +
+ "cmdhbml6YXRpb24xCzAJBgNVBAYTAkdCMQ8wDQYDVQQREwZNNSAzRVExGzAZBgNV\n" +
+ "BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEWMBQGA1UE\n" +
+ "CRMNVHJhZmZvcmQgUm9hZDEWMBQGA1UECRMNRXhjaGFuZ2UgUXVheTElMCMGA1UE\n" +
+ "CRMcM3JkIEZsb29yLCAyNiBPZmZpY2UgVmlsbGFnZTEaMBgGA1UEChMRQ09NT0RP\n" +
+ "IENBIExpbWl0ZWQxFjAUBgNVBAsTDUNPTU9ETyBFViBTU0wxODA2BgNVBAMTL2Nv\n" +
+ "bW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2EuY29tMFkw\n" +
+ "EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEt26qBS7TRu/yfR+RiqLAzW2C+UspFZlO\n" +
+ "Rc4EhLfNYMgFkoZKjEnwJzudH6a+uRPqPOhPgUd6PFfRQFOcLjmhgaOCA3EwggNt\n" +
+ "MB8GA1UdIwQYMBaAFNNOwxm6WFnRHGC3YVNHO6d3j/iKMB0GA1UdDgQWBBTpZ0tz\n" +
+ "KscFw6Z3vCEDFzGR5VSkVzAOBgNVHQ8BAf8EBAMCBYAwDAYDVR0TAQH/BAIwADAd\n" +
+ "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTwYDVR0gBEgwRjA7BgwrBgEE\n" +
+ "AbIxAQIBBQEwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv\n" +
+ "bS9DUFMwBwYFZ4EMAQEwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDovL2NybC5jb21v\n" +
+ "ZG9jYS5jb20vQ09NT0RPRUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVy\n" +
+ "Q0EuY3JsMIGHBggrBgEFBQcBAQR7MHkwUQYIKwYBBQUHMAKGRWh0dHA6Ly9jcnQu\n" +
+ "Y29tb2RvY2EuY29tL0NPTU9ET0VDQ0V4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNl\n" +
+ "cnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29t\n" +
+ "MDoGA1UdEQQzMDGCL2NvbW9kb2VjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYu\n" +
+ "Y29tb2RvY2EuY29tMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgCkuQmQtBhY\n" +
+ "FIe7E6LMZ3AKPDWYBPkb37jjd80OyA3cEAAAAV0NLqsqAAAEAwBHMEUCIAz9Jjq3\n" +
+ "qLUd/a2PYZnLGsEG/MrL7vab5rmGBg8RGAJxAiEA7JJnar07NIjCLLO77xJ3UFcu\n" +
+ "UMM3M8JgGC8wbuRwxbUAdgBWFAaaL9fC7NP14b1Esj7HRna5vJkRXMDvlJhV1onQ\n" +
+ "3QAAAV0NLqjmAAAEAwBHMEUCIHRvPWKr7vPMBWx1gLPkt8inPINWPNSoax178e5A\n" +
+ "D0cPAiEAvRL/VP4DLiyHvcU9AOqTzQXGuWCzswWKG59hSm7gS4kAdQDuS723dc5g\n" +
+ "uuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAV0NLqsDAAAEAwBGMEQCIFALT043\n" +
+ "X5IffLsxIAGXTrWgkZHf12QKgrYKXVB629eOAiAIeci2xi3fUW6mU8tT4LwyjowV\n" +
+ "DkrSCw1ZMo0JApsfzTAKBggqhkjOPQQDAgNJADBGAiEA7HUxjwx0MBC+4PuPx4Z1\n" +
+ "WpKz7jdHOMTh1sdaoVV5hNoCIQDrnjBFUopXHTvm/rj+aMFIeYejggPqv14KJOqT\n" +
+ "gym+uA==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Nov 29 08:12:02 PST 2018", System.out);
+ }
+}
+
+class ComodoUserTrustRSA {
+
+ // Owner: CN=USERTrust RSA Extended Validation Secure Server CA,
+ // O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US
+ // Issuer: CN=USERTrust RSA Certification Authority, O=The USERTRUST Network,
+ // L=Jersey City, ST=New Jersey, C=US
+ // Serial number: f6bb751efa7d2e8368e606407334f83
+ // Valid from: Sat Feb 11 16:00:00 PST 2012 until: Thu Feb 11 15:59:59 PST 2027
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIGGTCCBAGgAwIBAgIQD2u3Ue+n0ug2jmBkBzNPgzANBgkqhkiG9w0BAQwFADCB\n"
+ + "iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl\n"
+ + "cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV\n"
+ + "BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTIw\n"
+ + "MjEyMDAwMDAwWhcNMjcwMjExMjM1OTU5WjCBlTELMAkGA1UEBhMCVVMxEzARBgNV\n"
+ + "BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU\n"
+ + "aGUgVVNFUlRSVVNUIE5ldHdvcmsxOzA5BgNVBAMTMlVTRVJUcnVzdCBSU0EgRXh0\n"
+ + "ZW5kZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0B\n"
+ + "AQEFAAOCAQ8AMIIBCgKCAQEAlJwjjGNzAgMFwLu05RnhYFJS1PpbcyPH6VZOij+z\n"
+ + "PyvCILGvwXC8A+EgBthY080+kIlSxrNyOdnrUfNj8IsBtBlmtOF9nMWgD0Cb4HB1\n"
+ + "Y/tCNas8IHMtKr6eI4nJa4NjPhTcST+GtC8r+bVGHk0QpX4LbT+Z8WeE7pXIOUGs\n"
+ + "9j66/hsMwgnBxkQ9xXN0jhTFITUZfnCuM0vOo5hRYlCNtwD8iaHJPaKxYe6qHSKH\n"
+ + "WCBK7GUQiQRngry+YKLx3YtC3k/NQIyhaTLY/gUFi57kPcpZoa0h3RGfS9MpPFoe\n"
+ + "mk3rGH3jwjVFxR1ep1FtP/kprzLaR1UL81gxENhWvZEWXQIDAQABo4IBbjCCAWow\n"
+ + "HwYDVR0jBBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFC+BT+Jm\n"
+ + "+rxov5lDhFKJIDqC86SlMA4GA1UdDwEB/wQEAwIBBjASBgNVHRMBAf8ECDAGAQH/\n"
+ + "AgEAMDoGA1UdIAQzMDEwLwYEVR0gADAnMCUGCCsGAQUFBwIBFhlodHRwczovL2Nw\n"
+ + "cy51c2VydHJ1c3QuY29tMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNl\n"
+ + "cnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNy\n"
+ + "bDB2BggrBgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRy\n"
+ + "dXN0LmNvbS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZ\n"
+ + "aHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAa2bX\n"
+ + "Xf22zjY/QLzzdZwJ9JO86qH/czwCFPK4o9Cb7rixQL9S7zHw1dm3n/+Lx5kT9lqx\n"
+ + "wB0dqoZ8o0XwFgVcksGz7QRhEBjrB0nSUNYG8kuFaMxRWa9ze6Ovov44WDrq1uyF\n"
+ + "npi3eeQiwMr3xHmY76b1NX0WqvlTTFw4L5DrcIohBz1zKVkRp7LH/s5vxjDECM+/\n"
+ + "erdy1WTILNFv09gwz4iFyfu/WmYYNUKlQJaSoUqja/KHcqY8zYKKjq5o982Ji3Ti\n"
+ + "/Odkx1NJA1Yf5ivDxxRFQmij6knL1pi1wgQxGjd67V3/+HfHF7MCRWk8mXnT32B9\n"
+ + "1Hk3jm10GL0R6y/XFsLhv0mGkmKD1vTP7vz1hdMLlVgxEs1k5dLMybtjUJ3LuENz\n"
+ + "avmZ/G/vOi284ZRo/gA/YjT5CeeWgI11IHbpRDAqKy4BWhmtIi11u12i9ftPxxrD\n"
+ + "/VwHtC0hTTOBnYgbJAK9ZLvaJUBU22EimU4Jv3ELkeV7SWedbAdfjXolI1mCcAbq\n"
+ + "RgzRC+RaTloSmO2dWicDBW7KlRHmKZXrkDUAExSBY/1j9HmNcYzWv4NCTtK7t0en\n"
+ + "gsE/OP2b7zHrHWtC/F1JwOCrH1JkbPA7c/6nNJVY2AscGM16pIU89OL0Ez1PyZYG\n"
+ + "4fokbdNREXoShKClNIPbB5iY+WdSzb9CKLyb96g=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL,
+ // O=Sectigo Limited, STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road,
+ // L=Salford, ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
+ // ST=New Jersey, C=US
+ // Serial number: d3c204e8df6a1539568cf15e97e57b1d
+ // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIIADCCBuigAwIBAgIRANPCBOjfahU5VozxXpflex0wDQYJKoZIhvcNAQELBQAw\n" +
+ "gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" +
+ "ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" +
+ "VQQDEzJVU0VSVHJ1c3QgUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNl\n" +
+ "cnZlciBDQTAeFw0xODExMjkwMDAwMDBaFw0yMTAyMjYyMzU5NTlaMIIBXjERMA8G\n" +
+ "A1UEBRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFBy\n" +
+ "aXZhdGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VR\n" +
+ "MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx\n" +
+ "FjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkx\n" +
+ "JTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGDAWBgNVBAoT\n" +
+ "D1NlY3RpZ28gTGltaXRlZDEaMBgGA1UECxMRQ09NT0RPIEVWIFNHQyBTU0wxOzA5\n" +
+ "BgNVBAMTMnVzZXJ0cnVzdHJzYWNlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29t\n" +
+ "b2RvY2EuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnh/rxeiY\n" +
+ "wpLa651eLvGnR+RErhDWkTZtqZcHw9Oy7JL2uELyEPbM+v0az40cBHS0bQZJZbWm\n" +
+ "XNukMUMSwIb4z7t8OXlxz9uvxEufvlqBl4qeC/z3LpFBRRHEero3yGKVwkoe1aP2\n" +
+ "Pq7Udi+7i7eVZZdA1ticxZWo/UBU9mwbIOYqf/4xzZ6G891hKb+NAuuEfxG52vXZ\n" +
+ "l8odMThfHuDlkfS7nZMQBaO40KJeSEBhr+5TIS7d7tWWye/F6oEQ0+dHBiF9PyZ1\n" +
+ "dXoO8aue/80mP+0FMYTmRFsKHge6ZjojfH9cLlR5kTqtP5Tqh5GBQ4zp3uyIBBU6\n" +
+ "ylKp9PNHkewGUQIDAQABo4IDfTCCA3kwHwYDVR0jBBgwFoAUL4FP4mb6vGi/mUOE\n" +
+ "UokgOoLzpKUwHQYDVR0OBBYEFHz7cvDn1LYe2M+z4plwQn7rt938MA4GA1UdDwEB\n" +
+ "/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\n" +
+ "BQcDAjBLBgNVHSAERDBCMDcGDCsGAQQBsjEBAgEFATAnMCUGCCsGAQUFBwIBFhlo\n" +
+ "dHRwczovL2Nwcy51c2VydHJ1c3QuY29tMAcGBWeBDAEBMFoGA1UdHwRTMFEwT6BN\n" +
+ "oEuGSWh0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FFeHRlbmRl\n" +
+ "ZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcmwwgY0GCCsGAQUFBwEBBIGAMH4w\n" +
+ "VQYIKwYBBQUHMAKGSWh0dHA6Ly9jcnQudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RS\n" +
+ "U0FFeHRlbmRlZFZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwJQYIKwYBBQUH\n" +
+ "MAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wPQYDVR0RBDYwNIIydXNlcnRy\n" +
+ "dXN0cnNhY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9jYS5jb20wggGA\n" +
+ "BgorBgEEAdZ5AgQCBIIBcASCAWwBagB3AO5Lvbd1zmC64UJpH6vhnmajD35fsHLY\n" +
+ "gwDEe4l6qP3LAAABZ2ElLBIAAAQDAEgwRgIhAM33ah4mcEfxzv4a8+BLysZKJygV\n" +
+ "jeARvesL/mH6y51bAiEA4hzW9aDRmEnuCcagONmIexMl0s3gMWfaU8/0s4ESJecA\n" +
+ "dgBvU3asMfAxGdiZAKRRFf93FRwR2QLBACkGjbIImjfZEwAAAWdhJSwQAAAEAwBH\n" +
+ "MEUCIQDCZ7GZayfWD3blSOWgk8PrAs/GVVpc5gJG3V+wq8LHMwIgH6n8DkoA46v1\n" +
+ "0UrmkVo7ND18ykuWyNH83QafsolTYSIAdwC72d+8H4pxtZOUI5eqkntHOFeVCqtS\n" +
+ "6BqQlmQ2jh7RhQAAAWdhJSwSAAAEAwBIMEYCIQC/XcbvfZzEqDpUthm3gYzndaiB\n" +
+ "8djqlQ89Mo29WDMS8AIhAKcWwmE5F2SuoTojiO0pPC5w5T38uW0vTXzb+fkj+6d5\n" +
+ "MA0GCSqGSIb3DQEBCwUAA4IBAQAmq2kRR74802+YMB2AaqklGcFRCuBVxU/ExbvE\n" +
+ "loNpNk64KH2eHwMK13ad0Lbc8/LaVgIJPtPz87LNqu00kQh0DL/kCnoO94+Z+usU\n" +
+ "ulQNYr8y3sg8+NZd9ui/VQTOcXrlovL+mnJnTgsCUzNYcoBIPq7lHxtZv5MG99AR\n" +
+ "6NyGTG28Aw8ZByCzhaasDOyT4YwlfveVUtsx1jKUC+0e6IhsGhxADnYOnrDD0cNd\n" +
+ "4bgX6SkpM0MCg6Nc3X/C4fo3WaSRM6FO4S98NY4g2DhNskT/7TmX2DsPwS005t0r\n" +
+ "3Ld31zbQaywKdpCsT74/hEBMfcDiP02mmtyrlqHD4R3tdYne\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustrsacertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=USERTrust RSA Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
+ // ST=New Jersey, C=US
+ // Serial number: ffcada019c9fb1155a32300083cb99c9
+ // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIIATCCBumgAwIBAgIRAP/K2gGcn7EVWjIwAIPLmckwDQYJKoZIhvcNAQELBQAw\n" +
+ "gZUxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtK\n" +
+ "ZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYD\n" +
+ "VQQDEzJVU0VSVHJ1c3QgUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNl\n" +
+ "cnZlciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8G\n" +
+ "A1UEBRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFBy\n" +
+ "aXZhdGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VR\n" +
+ "MRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQx\n" +
+ "FjAUBgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkx\n" +
+ "JTAjBgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoT\n" +
+ "EUNPTU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7\n" +
+ "MDkGA1UEAxMydXNlcnRydXN0cnNhY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5j\n" +
+ "b21vZG9jYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCeH+vF\n" +
+ "6JjCktrrnV4u8adH5ESuENaRNm2plwfD07Lskva4QvIQ9sz6/RrPjRwEdLRtBkll\n" +
+ "taZc26QxQxLAhvjPu3w5eXHP26/ES5++WoGXip4L/PcukUFFEcR6ujfIYpXCSh7V\n" +
+ "o/Y+rtR2L7uLt5Vll0DW2JzFlaj9QFT2bBsg5ip//jHNnobz3WEpv40C64R/Ebna\n" +
+ "9dmXyh0xOF8e4OWR9LudkxAFo7jQol5IQGGv7lMhLt3u1ZbJ78XqgRDT50cGIX0/\n" +
+ "JnV1eg7xq57/zSY/7QUxhOZEWwoeB7pmOiN8f1wuVHmROq0/lOqHkYFDjOne7IgE\n" +
+ "FTrKUqn080eR7AZRAgMBAAGjggN8MIIDeDAfBgNVHSMEGDAWgBQvgU/iZvq8aL+Z\n" +
+ "Q4RSiSA6gvOkpTAdBgNVHQ4EFgQUfPty8OfUth7Yz7PimXBCfuu33fwwDgYDVR0P\n" +
+ "AQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" +
+ "AQUFBwMCMEsGA1UdIAREMEIwNwYMKwYBBAGyMQECAQUBMCcwJQYIKwYBBQUHAgEW\n" +
+ "GWh0dHBzOi8vY3BzLnVzZXJ0cnVzdC5jb20wBwYFZ4EMAQEwWgYDVR0fBFMwUTBP\n" +
+ "oE2gS4ZJaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VTRVJUcnVzdFJTQUV4dGVu\n" +
+ "ZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBjQYIKwYBBQUHAQEEgYAw\n" +
+ "fjBVBggrBgEFBQcwAoZJaHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VTRVJUcnVz\n" +
+ "dFJTQUV4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAlBggrBgEF\n" +
+ "BQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTA9BgNVHREENjA0gjJ1c2Vy\n" +
+ "dHJ1c3Ryc2FjZXJ0aWZpY2F0aW9uYXV0aG9yaXR5LWV2LmNvbW9kb2NhLmNvbTCC\n" +
+ "AX8GCisGAQQB1nkCBAIEggFvBIIBawFpAHYApLkJkLQYWBSHuxOizGdwCjw1mAT5\n" +
+ "G9+443fNDsgN3BAAAAFdDU2iYQAABAMARzBFAiB0o4GnVHD8MeVQ32D0XYu+EQQW\n" +
+ "jvN78rmCfk0OEBxyFAIhAKgyctIn0IaDJiZzsrtAiqEnkcMtuh8o+R0Rqw1ygAjk\n" +
+ "AHcAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDU2gFgAABAMA\n" +
+ "SDBGAiEA7mcmZ8H5uHuNCdI0CVxsqDZQcZX/gVk94KckePkzQoACIQCHwm5hcvNC\n" +
+ "M8vNmFkboQN79DglRctHrlh143A6mUTk8QB2AO5Lvbd1zmC64UJpH6vhnmajD35f\n" +
+ "sHLYgwDEe4l6qP3LAAABXQ1NojoAAAQDAEcwRQIhAPqwijgE0Fr6uJ+yF+TvyXco\n" +
+ "Hduv9h7R5WWwJfghXiMyAiBB4+fJm4rIcOnJBZmOqFnRpIjPN0jwDqJT0nDHxaXA\n" +
+ "nDANBgkqhkiG9w0BAQsFAAOCAQEACXitF1bTEvV1HX11WrT/XuoMhsoPK4TS16rs\n" +
+ "FqztV4iXKlA1/h5qbsjYY1gVrM+/6kQkmEs5qrxsek2WNxY80NO3WAzroRJ3H9Sd\n" +
+ "mPn0No2P8LZ5Fs5hvaD/PfWO5xxey80c3kGyvWOej90P3IrL/1RiULyh95TrXBjI\n" +
+ "ddCBsZ28904wsQUrPBPMpiu0DKl1HR/em9WkcipMi+onJxxFWjucssz5PW/BzGYF\n" +
+ "jfWLDEI0tN5L4CWV3iVXFXOURY1Mwhtsey9jvlEyxSsys55QdKF40yGgtV9VC+os\n" +
+ "7hJP33+qA0cvCTaRytiPP6z/l2G/KSIXTyv6SxzGhsTFfzLAOg==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Nov 29 10:58:13 PST 2018", System.out);
+ }
+}
+
+class ComodoUserTrustECC {
+
+ // Owner: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network,
+ // L=Jersey City, ST=New Jersey, C=US
+ // Issuer: CN=USERTrust ECC Certification Authority, O=The USERTRUST Network,
+ // L=Jersey City, ST=New Jersey, C=US
+ // Serial number: 3d09b24f5c08a7ce8eb85a51d3c1aa52
+ // Valid from: Sun Apr 14 17:00:00 PDT 2013 until: Fri Apr 14 16:59:59 PDT 2028
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIDwTCCA0igAwIBAgIQPQmyT1wIp86OuFpR08GqUjAKBggqhkjOPQQDAzCBiDEL\n"
+ + "MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl\n"
+ + "eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT\n"
+ + "JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTMwNDE1\n"
+ + "MDAwMDAwWhcNMjgwNDE0MjM1OTU5WjCBlTELMAkGA1UEBhMCVVMxEzARBgNVBAgT\n"
+ + "Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg\n"
+ + "VVNFUlRSVVNUIE5ldHdvcmsxOzA5BgNVBAMTMlVTRVJUcnVzdCBFQ0MgRXh0ZW5k\n"
+ + "ZWQgVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMFkwEwYHKoZIzj0CAQYIKoZI\n"
+ + "zj0DAQcDQgAEkSRGk0F0N82ZCZ+kVZ/StqVUiWRirw1ebViS06+j+HgS9xZKRGh7\n"
+ + "bqSas/gNMyg1LZusGu5IvEmXmNC5hzOT06OCAYMwggF/MB8GA1UdIwQYMBaAFDrh\n"
+ + "CYbUzxnClnZ0SXbc4DXGY2OaMB0GA1UdDgQWBBQqnFr5TqEw2kBLK+lL8fWc3AL5\n"
+ + "LjAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADA/BgNVHSAEODA2\n"
+ + "MDQGBFUdIAAwLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9jcHMudHJ1c3QtcHJvdmlk\n"
+ + "ZXIuY29tMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwudHJ1c3QtcHJvdmlk\n"
+ + "ZXIuY29tL1VTRVJUcnVzdEVDQ0NlcnRpZmljYXRpb25BdXRob3JpdHkuY3JsMIGA\n"
+ + "BggrBgEFBQcBAQR0MHIwRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQudHJ1c3QtcHJv\n"
+ + "dmlkZXIuY29tL1VTRVJUcnVzdEVDQ0FkZFRydXN0Q0EuY3J0MCoGCCsGAQUFBzAB\n"
+ + "hh5odHRwOi8vb2NzcC50cnVzdC1wcm92aWRlci5jb20wCgYIKoZIzj0EAwMDZwAw\n"
+ + "ZAIwSzIqrW8TN9/aCfkhUtz0t8IIK+Z46z3wm+crwjThpQ/VoPgTNbvP/lGTi1xR\n"
+ + "qJvLAjBFa27l4uqeAQZHNJnIx1Mu9OXzoJelx1cYP7ToQUms/g+PK77yImJcXUU3\n"
+ + "s1rWGRU=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=Sectigo Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
+ // ST=New Jersey, C=US
+ // Serial number: ab1455f9833ae7783f95de8744181f6a
+ // Valid from: Wed Nov 28 16:00:00 PST 2018 until: Fri Feb 26 15:59:59 PST 2021
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGhjCCBiygAwIBAgIRAKsUVfmDOud4P5Xeh0QYH2owCgYIKoZIzj0EAwIwgZUx\n" +
+ "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" +
+ "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" +
+ "EzJVU0VSVHJ1c3QgRUNDIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" +
+ "ciBDQTAeFw0xODExMjkwMDAwMDBaFw0yMTAyMjYyMzU5NTlaMIIBXjERMA8GA1UE\n" +
+ "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" +
+ "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRsw\n" +
+ "GQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAU\n" +
+ "BgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAj\n" +
+ "BgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGDAWBgNVBAoTD1Nl\n" +
+ "Y3RpZ28gTGltaXRlZDEaMBgGA1UECxMRQ09NT0RPIEVWIFNHQyBTU0wxOzA5BgNV\n" +
+ "BAMTMnVzZXJ0cnVzdGVjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2Rv\n" +
+ "Y2EuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAELTJfEd92Wlg+h/AVtPsM\n" +
+ "mwX9Puvi+WGCv3sgFRpur8Iy2kGVpXHRQTCn2j9aky4tFQGm7OG2klJA/MEeevKV\n" +
+ "aaOCA48wggOLMB8GA1UdIwQYMBaAFCqcWvlOoTDaQEsr6Uvx9ZzcAvkuMB0GA1Ud\n" +
+ "DgQWBBSzrWHzmiHwx2Rrm7SjRC0UegNrKzAOBgNVHQ8BAf8EBAMCBYAwDAYDVR0T\n" +
+ "AQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwUAYDVR0gBEkw\n" +
+ "RzA8BgwrBgEEAbIxAQIBBQEwLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9jcHMudHJ1\n" +
+ "c3QtcHJvdmlkZXIuY29tMAcGBWeBDAEBMF8GA1UdHwRYMFYwVKBSoFCGTmh0dHA6\n" +
+ "Ly9jcmwudHJ1c3QtcHJvdmlkZXIuY29tL1VTRVJUcnVzdEVDQ0V4dGVuZGVkVmFs\n" +
+ "aWRhdGlvblNlY3VyZVNlcnZlckNBLmNybDCBmAYIKwYBBQUHAQEEgYswgYgwWgYI\n" +
+ "KwYBBQUHMAKGTmh0dHA6Ly9jcnQudHJ1c3QtcHJvdmlkZXIuY29tL1VTRVJUcnVz\n" +
+ "dEVDQ0V4dGVuZGVkVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBLmNydDAqBggrBgEF\n" +
+ "BQcwAYYeaHR0cDovL29jc3AudHJ1c3QtcHJvdmlkZXIuY29tMD0GA1UdEQQ2MDSC\n" +
+ "MnVzZXJ0cnVzdGVjY2NlcnRpZmljYXRpb25hdXRob3JpdHktZXYuY29tb2RvY2Eu\n" +
+ "Y29tMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgDuS723dc5guuFCaR+r4Z5m\n" +
+ "ow9+X7By2IMAxHuJeqj9ywAAAWdhJc3KAAAEAwBHMEUCIQCPBqO6bw8GSm3HxUf5\n" +
+ "vRcv74BOEAwZxEr0+PyszJHDbQIgCDXHPzlznU2jbaPdbZ65OQ78mRL5aDDMt1vf\n" +
+ "/foQr/wAdQBvU3asMfAxGdiZAKRRFf93FRwR2QLBACkGjbIImjfZEwAAAWdhJc3B\n" +
+ "AAAEAwBGMEQCICIvBLk08NTaEWtKdH8xl2VjjYUo+yQmtdqwMiVMjEB8AiAc50at\n" +
+ "gCogvZhdlIlGAqg5oND0K74+iglilBVvuTcIoQB2ALvZ37wfinG1k5Qjl6qSe0c4\n" +
+ "V5UKq1LoGpCWZDaOHtGFAAABZ2ElzcsAAAQDAEcwRQIhALDnAxdhUQvt2HkslYbG\n" +
+ "J8mYzWbDSSoidZzF4EF4bredAiB3xrSKOKFdTF3KUFHJANqT0c6Xxmo5dVUtovwM\n" +
+ "QMb1vTAKBggqhkjOPQQDAgNIADBFAiEA2ZwNj/BD8n2yR5BMBQvw7utv9XWrJvKQ\n" +
+ "11EPtBSCEhUCIBcyI0yl5dRff6+4x8IeCrLiAOYsfzM7Y/a5uRKFnbYz\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=usertrustecccertificationauthority-ev.comodoca.com, OU=COMODO EV SGC SSL, O=COMODO CA Limited,
+ // STREET="3rd Floor, 26 Office Village", STREET=Exchange Quay, STREET=Trafford Road, L=Salford,
+ // ST=Greater Manchester, OID.2.5.4.17=M5 3EQ, C=GB, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=GB, SERIALNUMBER=04058690
+ // Issuer: CN=USERTrust ECC Extended Validation Secure Server CA, O=The USERTRUST Network, L=Jersey City,
+ // ST=New Jersey, C=US
+ // Serial number: 9bd0c93cac9ca2edc1a7dd923316b3c6
+ // Valid from: Mon Jul 03 17:00:00 PDT 2017 until: Thu Oct 03 16:59:59 PDT 2019
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGhzCCBi2gAwIBAgIRAJvQyTysnKLtwafdkjMWs8YwCgYIKoZIzj0EAwIwgZUx\n" +
+ "CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJz\n" +
+ "ZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMTswOQYDVQQD\n" +
+ "EzJVU0VSVHJ1c3QgRUNDIEV4dGVuZGVkIFZhbGlkYXRpb24gU2VjdXJlIFNlcnZl\n" +
+ "ciBDQTAeFw0xNzA3MDQwMDAwMDBaFw0xOTEwMDMyMzU5NTlaMIIBYDERMA8GA1UE\n" +
+ "BRMIMDQwNTg2OTAxEzARBgsrBgEEAYI3PAIBAxMCR0IxHTAbBgNVBA8TFFByaXZh\n" +
+ "dGUgT3JnYW5pemF0aW9uMQswCQYDVQQGEwJHQjEPMA0GA1UEERMGTTUgM0VRMRsw\n" +
+ "GQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxFjAU\n" +
+ "BgNVBAkTDVRyYWZmb3JkIFJvYWQxFjAUBgNVBAkTDUV4Y2hhbmdlIFF1YXkxJTAj\n" +
+ "BgNVBAkTHDNyZCBGbG9vciwgMjYgT2ZmaWNlIFZpbGxhZ2UxGjAYBgNVBAoTEUNP\n" +
+ "TU9ETyBDQSBMaW1pdGVkMRowGAYDVQQLExFDT01PRE8gRVYgU0dDIFNTTDE7MDkG\n" +
+ "A1UEAxMydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21v\n" +
+ "ZG9jYS5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtMl8R33ZaWD6H8BW0\n" +
+ "+wybBf0+6+L5YYK/eyAVGm6vwjLaQZWlcdFBMKfaP1qTLi0VAabs4baSUkD8wR56\n" +
+ "8pVpo4IDjjCCA4owHwYDVR0jBBgwFoAUKpxa+U6hMNpASyvpS/H1nNwC+S4wHQYD\n" +
+ "VR0OBBYEFLOtYfOaIfDHZGubtKNELRR6A2srMA4GA1UdDwEB/wQEAwIFgDAMBgNV\n" +
+ "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBQBgNVHSAE\n" +
+ "STBHMDwGDCsGAQQBsjEBAgEFATAsMCoGCCsGAQUFBwIBFh5odHRwczovL2Nwcy50\n" +
+ "cnVzdC1wcm92aWRlci5jb20wBwYFZ4EMAQEwXwYDVR0fBFgwVjBUoFKgUIZOaHR0\n" +
+ "cDovL2NybC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRydXN0RUNDRXh0ZW5kZWRW\n" +
+ "YWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3JsMIGYBggrBgEFBQcBAQSBizCBiDBa\n" +
+ "BggrBgEFBQcwAoZOaHR0cDovL2NydC50cnVzdC1wcm92aWRlci5jb20vVVNFUlRy\n" +
+ "dXN0RUNDRXh0ZW5kZWRWYWxpZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCoGCCsG\n" +
+ "AQUFBzABhh5odHRwOi8vb2NzcC50cnVzdC1wcm92aWRlci5jb20wPQYDVR0RBDYw\n" +
+ "NIIydXNlcnRydXN0ZWNjY2VydGlmaWNhdGlvbmF1dGhvcml0eS1ldi5jb21vZG9j\n" +
+ "YS5jb20wggF8BgorBgEEAdZ5AgQCBIIBbASCAWgBZgB1AKS5CZC0GFgUh7sTosxn\n" +
+ "cAo8NZgE+RvfuON3zQ7IDdwQAAABXQ0/jQ0AAAQDAEYwRAIgPbaNWgoi6OfyNwL2\n" +
+ "+jiySsoLrkx+0d4NJE1WnZQcfzwCICW4yvsXaMxoOXpQp3EPgrYk5Ajfvy/dY3Ui\n" +
+ "0/dbQtHxAHYAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFdDT+K\n" +
+ "xwAABAMARzBFAiB3GQasrX+akoHX02ZvXCcvhWCqv6qQOhLCUqflPoRbuAIhALwe\n" +
+ "hrQo8S1Tm5vbMcxGiViq5ZcawxENWhxZ9hS0BZweAHUA7ku9t3XOYLrhQmkfq+Ge\n" +
+ "ZqMPfl+wctiDAMR7iXqo/csAAAFdDT+M4AAABAMARjBEAiAjvp8w/fdTVW1VGE0T\n" +
+ "I0YcCIXTYFDgzUMsEUiKHANAgwIgETQUcac7Hiis2fgQ+GdGF9yuh+xMo2Z8QXNu\n" +
+ "1Cknf+8wCgYIKoZIzj0EAwIDSAAwRQIgQ5UiUI7xodmmMYNs3CmqlZHw/04BQRAR\n" +
+ "4gRm7blZSIMCIQDHvIWTaPzSO6vwVzs6wSD6FqebLiFxoddC6aZG8Nm0wQ==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Nov 29 10:06:00 PST 2018", System.out);
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java
new file mode 100644
index 0000000000..152e77907b
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/DTrustCA.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2017, 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 8189131
+ * @summary Interoperability tests with "D-Trust Root Class 3 CA 2 2009" and
+ * "D-Trust Root Class 3 CA 2 EV 2009" CAs
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath DTrustCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath DTrustCA CRL
+ */
+public class DTrustCA {
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ boolean ocspEnabled = true;
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ ocspEnabled = false;
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ new RootClass3CA2().runTest(pathValidator, ocspEnabled);
+ new RootClass3CA2EV().runTest(pathValidator, ocspEnabled);
+ }
+}
+
+class RootClass3CA2 {
+
+ // Owner: CN=D-TRUST SSL Class 3 CA 1 2009, O=D-Trust GmbH, C=DE
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFMjCCBBqgAwIBAgIDCZBjMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF\n"
+ + "MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD\n"
+ + "bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMTIxMjQ2NTVaFw0yOTExMDUwODM1NTha\n"
+ + "MEwxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJjAkBgNVBAMM\n"
+ + "HUQtVFJVU1QgU1NMIENsYXNzIDMgQ0EgMSAyMDA5MIIBIjANBgkqhkiG9w0BAQEF\n"
+ + "AAOCAQ8AMIIBCgKCAQEAoal0SyLSijE0JkuhHJmOCbmQznyxuSY7DaEwhUsdUpI+\n"
+ + "2llkDLz6s9BWQe1zCVXDhrt3qz5U5H4h6jxm5Ec+ZbFiU3Gv2yxpI5cRPrqj9mJU\n"
+ + "1CGgy1+29khuUnoopzSq66HPuGZGh06I7bJkXTQ7AQ92z1MdL2wATj1UWdNid3sQ\n"
+ + "NiWIm+69nURHY6tmCNenNcG6aV4qjHMUPsjpCRabNY9nUO12rsmiDW2mbAC3gcxQ\n"
+ + "lqLgLYur9HvB8cW0xu2JZ/B3PXmNphVuWskp3Y1u0SvIYzuEsE7lWDbBmtWZtabB\n"
+ + "hzThkDQvd+3keQ1sU/beq1NeXfgKzQ5G+4Ql2PUY/wIDAQABo4ICGjCCAhYwHwYD\n"
+ + "VR0jBBgwFoAU/doUxJ8w3iG9HkI5/KtjI0ng8YQwRAYIKwYBBQUHAQEEODA2MDQG\n"
+ + "CCsGAQUFBzABhihodHRwOi8vcm9vdC1jMy1jYTItMjAwOS5vY3NwLmQtdHJ1c3Qu\n"
+ + "bmV0MF8GA1UdIARYMFYwVAYEVR0gADBMMEoGCCsGAQUFBwIBFj5odHRwOi8vd3d3\n"
+ + "LmQtdHJ1c3QubmV0L2ludGVybmV0L2ZpbGVzL0QtVFJVU1RfUm9vdF9QS0lfQ1BT\n"
+ + "LnBkZjAzBgNVHREELDAqgRBpbmZvQGQtdHJ1c3QubmV0hhZodHRwOi8vd3d3LmQt\n"
+ + "dHJ1c3QubmV0MIHTBgNVHR8EgcswgcgwgYCgfqB8hnpsZGFwOi8vZGlyZWN0b3J5\n"
+ + "LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El\n"
+ + "MjAyJTIwMjAwOSxPPUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZv\n"
+ + "Y2F0aW9ubGlzdDBDoEGgP4Y9aHR0cDovL3d3dy5kLXRydXN0Lm5ldC9jcmwvZC10\n"
+ + "cnVzdF9yb290X2NsYXNzXzNfY2FfMl8yMDA5LmNybDAdBgNVHQ4EFgQUUBkylJrE\n"
+ + "tQRNVtDAgyHVNVWwsXowDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8C\n"
+ + "AQAwDQYJKoZIhvcNAQELBQADggEBABM5QRHX/yInsmZLWVlvmWmKb3c4IB3hAIVR\n"
+ + "sAGhkvQJ/RD1GZjZUBBYMWkD1P37fTQxlqTOe3NecVvElkYZuCq7HSM6o7awzb3m\n"
+ + "yLn1kN+hDCsxX0EYbVSNjEjkW3QEkqJH9owH4qeMDxf7tfXB7BVKO+rarYPa2PR8\n"
+ + "Wz2KhjFDmAeFg2J89YcpeJJEEJXoweAkgJEEwwEIfJ2yLjYo78RD0Rvij/+zkfj9\n"
+ + "+dSvTiZTuqicyo37qNoYHgchuqXnKodhWkW89oo2NKhfeNHHbqvXEJmx0PbI6YyQ\n"
+ + "50GnYECZRHNKhgbPEtNy/QetU53aWlTlvu4NIwLW5XVsrxlQ2Zw=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=certdemo-ov-valid.ssl.d-trust.net, O=D-Trust GmbH, OU=IT,
+ // L=Berlin, ST=Berlin, C=DE, SERIALNUMBER=DTRWS354803406304201, DNQ=7223150018
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIF1jCCBL6gAwIBAgIDD07RMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNVBAYTAkRF\n"
+ + "MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJjAkBgNVBAMMHUQtVFJVU1QgU1NMIENs\n"
+ + "YXNzIDMgQ0EgMSAyMDA5MB4XDTEyMTIxMTEwMTgzN1oXDTE1MTIyMTExMTgwOVow\n"
+ + "gbMxEzARBgNVBC4TCjcyMjMxNTAwMTgxHTAbBgNVBAUTFERUUldTMzU0ODAzNDA2\n"
+ + "MzA0MjAxMQswCQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZC\n"
+ + "ZXJsaW4xCzAJBgNVBAsMAklUMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV\n"
+ + "BAMMIWNlcnRkZW1vLW92LXZhbGlkLnNzbC5kLXRydXN0Lm5ldDCCASIwDQYJKoZI\n"
+ + "hvcNAQEBBQADggEPADCCAQoCggEBAMbo9ih0Bo4zKaKwl+mClCxhedC3YOpBzrun\n"
+ + "zbqYJuy6vbHuZdMtU3nO7ziTPbnoVFboKmyEtAMwJ+qudHdWaa/nA4Hlhmg5+CWZ\n"
+ + "OolX3VmMlrZ+LpaeajduOgDa7DQDcixZ+ndd24Xc/u9L83CH7ziQDs4XNJxx63Wf\n"
+ + "lSMKBKkmvry7CfCXcsR4dYW8tTBm1PESJZVNqOKkOiwHwMA69knpXwghmDbKgZro\n"
+ + "01chjeyYb39ZhwHNWlxh5rgd2HZpgrl8kUY3yV9PrQcjFPbKT6ZgHfRiHlax4vbX\n"
+ + "qiHHcHRr7iVPruyCf0DU3BqhDVUhnrJ+vqTyg+m/OJduznF2nXcCAwEAAaOCAlcw\n"
+ + "ggJTMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBRQ\n"
+ + "GTKUmsS1BE1W0MCDIdU1VbCxejBDBggrBgEFBQcBAQQ3MDUwMwYIKwYBBQUHMAGG\n"
+ + "J2h0dHA6Ly9zc2wtYzMtY2ExLTIwMDkub2NzcC5kLXRydXN0Lm5ldDBmBgNVHSAE\n"
+ + "XzBdMFsGCysGAQQBpTQCgUgBMEwwSgYIKwYBBQUHAgEWPmh0dHA6Ly93d3cuZC10\n"
+ + "cnVzdC5uZXQvaW50ZXJuZXQvZmlsZXMvRC1UUlVTVF9Sb290X1BLSV9DUFMucGRm\n"
+ + "MIHRBgNVHR8EgckwgcYwgcOggcCggb2GeWxkYXA6Ly9kaXJlY3RvcnkuZC10cnVz\n"
+ + "dC5uZXQvQ049RC1UUlVTVCUyMFNTTCUyMENsYXNzJTIwMyUyMENBJTIwMSUyMDIw\n"
+ + "MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxp\n"
+ + "c3SGQGh0dHA6Ly9jcmwuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfc3NsX2NsYXNz\n"
+ + "XzNfY2FfMV8yMDA5LmRlci5jcmwwMwYDVR0SBCwwKoEQaW5mb0BkLXRydXN0Lm5l\n"
+ + "dIYWaHR0cDovL3d3dy5kLXRydXN0Lm5ldDAdBgNVHQ4EFgQUHjGMR/EdDBRf+Ejf\n"
+ + "WW5a8beoBrwwDgYDVR0PAQH/BAQDAgSwMCwGA1UdEQQlMCOCIWNlcnRkZW1vLW92\n"
+ + "LXZhbGlkLnNzbC5kLXRydXN0Lm5ldDANBgkqhkiG9w0BAQsFAAOCAQEAGN4yxyF3\n"
+ + "sszODgDSkCNX1s4R874jmBmMYy4Af9/kwKNp2GtqPPhnDu8VFtq0bqs1e06XZ4/W\n"
+ + "6pUPRZIlynjPASkQl+aJGzyZlaH+K0Al80M/7FRRmLCW9Do/RszRihdhcjeyG+Bi\n"
+ + "2k+A35aVqKMAWzoH4M7TCPg4+ECltaFgJ+25loXl3j0yiP/DmBwATO80Nx78ILl5\n"
+ + "D6cDyftMKUwdKKlUsB2RMOJsVBcotBMGTB1i/YoSKIu6t7QnoVFMHEia2wZegPCj\n"
+ + "hBKhLf/Zde/VrSN3IIft93XRabqXWqjpDCvpb/b06/0o5aZIycrj+Kya54dsdXMO\n"
+ + "FRy9N0HZYzvt9g==\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=certdemo-ov-revoked.ssl.d-trust.net, O=D-Trust GmbH, OU=IT,
+ // L=Berlin, ST=Berlin, C=DE, DNQ=5562882417
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFuzCCBKOgAwIBAgIDExFnMA0GCSqGSIb3DQEBCwUAMEwxCzAJBgNVBAYTAkRF\n"
+ + "MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJjAkBgNVBAMMHUQtVFJVU1QgU1NMIENs\n"
+ + "YXNzIDMgQ0EgMSAyMDA5MB4XDTE0MDYyNjE2MTg1NloXDTE1MDYyOTE2MTg1Nlow\n"
+ + "gZYxEzARBgNVBC4TCjU1NjI4ODI0MTcxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZC\n"
+ + "ZXJsaW4xDzANBgNVBAcTBkJlcmxpbjELMAkGA1UECxMCSVQxFTATBgNVBAoTDEQt\n"
+ + "VHJ1c3QgR21iSDEsMCoGA1UEAxMjY2VydGRlbW8tb3YtcmV2b2tlZC5zc2wuZC10\n"
+ + "cnVzdC5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtdH2wqHgG\n"
+ + "tqlekrfRQzJuhMzRllfYcmmsxr7jsnwgPe0+zib+GeTDm9U5+XKjT1uYETL501ov\n"
+ + "HfKsZ/aK+k58iFF5evEtdHic/2v868uwxcm/Kcn+zt2uX9QvfSUzJPQkW/Ynu3w2\n"
+ + "IhuBNBlFAJgxjYr2xMUmDrVDx1/ZfBc0ddyo87MccLZOdmqLhef8bJQ+3q6DA+Z1\n"
+ + "bGk1wHl9KgFNtOjlKws5nKzCzyugy+MhLo+4wPxi0UhUA7QA7fk7lWBwJ9fZRTT/\n"
+ + "cKfP4lUucXdQBS2ZhvpEZggjjBDhTHtZLwdfEUlf1GZ+GwD8IB9whlwqT2cS9WUR\n"
+ + "XI9b14TJM2zfAgMBAAGjggJZMIICVTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYB\n"
+ + "BQUHAwIwHwYDVR0jBBgwFoAUUBkylJrEtQRNVtDAgyHVNVWwsXowQwYIKwYBBQUH\n"
+ + "AQEENzA1MDMGCCsGAQUFBzABhidodHRwOi8vc3NsLWMzLWNhMS0yMDA5Lm9jc3Au\n"
+ + "ZC10cnVzdC5uZXQwZgYDVR0gBF8wXTBbBgsrBgEEAaU0AoFIATBMMEoGCCsGAQUF\n"
+ + "BwIBFj5odHRwOi8vd3d3LmQtdHJ1c3QubmV0L2ludGVybmV0L2ZpbGVzL0QtVFJV\n"
+ + "U1RfUm9vdF9QS0lfQ1BTLnBkZjCB0QYDVR0fBIHJMIHGMIHDoIHAoIG9hnlsZGFw\n"
+ + "Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBTU0wlMjBDbGFz\n"
+ + "cyUyMDMlMjBDQSUyMDElMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0\n"
+ + "aWZpY2F0ZXJldm9jYXRpb25saXN0hkBodHRwOi8vY3JsLmQtdHJ1c3QubmV0L2Ny\n"
+ + "bC9kLXRydXN0X3NzbF9jbGFzc18zX2NhXzFfMjAwOS5kZXIuY3JsMDMGA1UdEgQs\n"
+ + "MCqBEGluZm9AZC10cnVzdC5uZXSGFmh0dHA6Ly93d3cuZC10cnVzdC5uZXQwHQYD\n"
+ + "VR0OBBYEFC4+5qwI2S+t/TaZ/kMADTR7FjdOMA4GA1UdDwEB/wQEAwIEsDAuBgNV\n"
+ + "HREEJzAlgiNjZXJ0ZGVtby1vdi1yZXZva2VkLnNzbC5kLXRydXN0Lm5ldDANBgkq\n"
+ + "hkiG9w0BAQsFAAOCAQEAO3sbXee7GbEyXSRZOgwk2LloPNIFriFGP8WAWnsaf056\n"
+ + "jxHRnjjPQRyqhBmGQAGwrEp3a3uF+6gbM2XuoKPjNFqjqnQNR2+lVRs8pVTTjJ+r\n"
+ + "SekcOUbCx6nIe98OBheAljAxfeal3e8bBrP3VA+QvOscaLJiC1ZsGfqvrGYJDt6b\n"
+ + "UFMKbNuwDcfpKkrB0AyW0NvYALwgTPr+SgbxB0Xrp0W+dg6XfHmpuRSSPUkZqzEY\n"
+ + "uPTmIgs7qCtVEIpV91gDFBDNfr4QbFVCNvDmMIZNMnXUEmTW81N1KUVTNdz8k5TY\n"
+ + "HO/7TeeAi2u0m3ERrLXE9SKtNwUMJujEOQ/UmQkIQw==\n"
+ + "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled)
+ throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ if (ocspEnabled) {
+ // Test certificates are expired in 2015
+ // and backdated revocation check is only possible with OCSP
+ pathValidator.setValidationDate("Jan 01, 2015");
+ }
+
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Jun 26 09:28:39 PDT 2014", System.out);
+
+ // reset validation date back to current date
+ pathValidator.resetValidationDate();
+ }
+}
+
+class RootClass3CA2EV {
+
+ // Owner: CN=D-TRUST SSL Class 3 CA 1 EV 2009, O=D-Trust GmbH, C=DE
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFRTCCBC2gAwIBAgIDCZBkMA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF\n"
+ + "MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD\n"
+ + "bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMTIxMjUyNDNaFw0yOTExMDUwODUw\n"
+ + "NDZaME8xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKTAnBgNV\n"
+ + "BAMMIEQtVFJVU1QgU1NMIENsYXNzIDMgQ0EgMSBFViAyMDA5MIIBIjANBgkqhkiG\n"
+ + "9w0BAQEFAAOCAQ8AMIIBCgKCAQEAygp+ZziakFyPq80fk1QIT9UCcPy0R3UIyq56\n"
+ + "hXA6lhgfs1l9R9wRM9/DIVX2olb0gHCXdpnHRm+jwzeL3dHJO8Im5Om/c24ZfSVE\n"
+ + "zBcgKxS5X7X5e7oCYb9tozd9xs04WqYd5kWrvCJsSQf5gtv5gAeJt+QiU7dtXs3A\n"
+ + "YDflWv4g9eEaDExxM0VQmceEAo5qc7I7dk5ry356G14zQmr29cxie6YS0kH+7qn5\n"
+ + "g+c21M01sENle0tBPxIfkv+nV95Ih3JkpHSPm/wgFKfCtwRtG+5VehUoMEpgfi0X\n"
+ + "fmVkag558aQpaaeQCtYZnXuq6g1D1LAcjIqMpOP4wNRp1ldLzQIDAQABo4ICJzCC\n"
+ + "AiMwHwYDVR0jBBgwFoAU05SKTGITKhkuzK9yin0215oc3GcwRwYIKwYBBQUHAQEE\n"
+ + "OzA5MDcGCCsGAQUFBzABhitodHRwOi8vcm9vdC1jMy1jYTItZXYtMjAwOS5vY3Nw\n"
+ + "LmQtdHJ1c3QubmV0MF8GA1UdIARYMFYwVAYEVR0gADBMMEoGCCsGAQUFBwIBFj5o\n"
+ + "dHRwOi8vd3d3LmQtdHJ1c3QubmV0L2ludGVybmV0L2ZpbGVzL0QtVFJVU1RfUm9v\n"
+ + "dF9QS0lfQ1BTLnBkZjAzBgNVHREELDAqgRBpbmZvQGQtdHJ1c3QubmV0hhZodHRw\n"
+ + "Oi8vd3d3LmQtdHJ1c3QubmV0MIHdBgNVHR8EgdUwgdIwgYeggYSggYGGf2xkYXA6\n"
+ + "Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQvQ049RC1UUlVTVCUyMFJvb3QlMjBDbGFz\n"
+ + "cyUyMDMlMjBDQSUyMDIlMjBFViUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURF\n"
+ + "P2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwRqBEoEKGQGh0dHA6Ly93d3cuZC10\n"
+ + "cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfZXZfMjAwOS5j\n"
+ + "cmwwHQYDVR0OBBYEFKztpZ16orZD8RiKJWpsscyo8lrUMA4GA1UdDwEB/wQEAwIB\n"
+ + "BjASBgNVHRMBAf8ECDAGAQH/AgEAMA0GCSqGSIb3DQEBCwUAA4IBAQA6I3sGyvb4\n"
+ + "MdTyEZFBBWBN/5Kx1SVkkPsll8DvgosJiuuK4I7mD6FFKDjKgogr407EoDSS2t1+\n"
+ + "pSmQCb0rNXoJT3YIlpZGqPYU2rcwrelabJQZWAfoRnbkDx2aqofhp5u45dyQpM2t\n"
+ + "R93/oA36iuHYc9Ewq8CaLGolrpT138RD7i4nN7sZFuFH0IseNz0+EZm88NHi9WeJ\n"
+ + "UyshWFKBKARi+589Y4P/G2XnbckxFKUxa7uEroZcMwvKBy469K0Au0zVTxs1zNtf\n"
+ + "Ol3QkNgPwzOPeHhOnpzcenyPgNEm+HQ0FPTnB4HeKBqTeLpkM7h4gq5MZ2TPmfuX\n"
+ + "KDz3AHrWLLdH\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=certdemo-ev-revoked.ssl.d-trust.net, O=D-Trust GmbH, OU=IT,
+ // STREET=Berlin, OID.2.5.4.17=10969, L=Berlin, ST=Berlin, C=DE,
+ // SERIALNUMBER=HRB74346, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.1=Berlin, OID.1.3.6.1.4.1.311.60.2.1.2=Berlin,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=DE, DNQ=4028175542
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIGZDCCBUygAwIBAgIDExFtMA0GCSqGSIb3DQEBCwUAME8xCzAJBgNVBAYTAkRF\n"
+ + "MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKTAnBgNVBAMMIEQtVFJVU1QgU1NMIENs\n"
+ + "YXNzIDMgQ0EgMSBFViAyMDA5MB4XDTE0MDYyNjE2NDMyOFoXDTE1MDYyOTE2NDMy\n"
+ + "OFowggEwMRMwEQYDVQQuEwo0MDI4MTc1NTQyMRMwEQYLKwYBBAGCNzwCAQMMAkRF\n"
+ + "MRcwFQYLKwYBBAGCNzwCAQIMBkJlcmxpbjEXMBUGCysGAQQBgjc8AgEBDAZCZXJs\n"
+ + "aW4xHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMREwDwYDVQQFEwhIUkI3\n"
+ + "NDM0NjELMAkGA1UEBhMCREUxDzANBgNVBAgTBkJlcmxpbjEPMA0GA1UEBxMGQmVy\n"
+ + "bGluMQ4wDAYDVQQRDAUxMDk2OTEPMA0GA1UECRMGQmVybGluMQswCQYDVQQLEwJJ\n"
+ + "VDEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSwwKgYDVQQDEyNjZXJ0ZGVtby1ldi1y\n"
+ + "ZXZva2VkLnNzbC5kLXRydXN0Lm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC\n"
+ + "AQoCggEBAMjX4zZxaSl+7eLXXVyO1HzQTymgsI4WlMpVMczyA21kXnx4iBZ9JeHW\n"
+ + "W3Jv4SxxqtHut98eCq30r7yniCy7zGX35iuSy2zMf0u0tRraP5b2c590UMRgKOSU\n"
+ + "DvahC+SlyJWGimt2Dtej2T1kcQvhUmonUkIimQOpM0MOIFxB5d494TzkQAYOV6yb\n"
+ + "AHoIsMWMeMm24Rr6o8QnJqhb9A13keYRK8t0u7F5+fvONlFT2YnjbCoRlxa48i1b\n"
+ + "PZwtE/NZ4bpZmv765tyfl9R5FatANnuja04Dd9StbTbjDezYzilF4qpSWtSKwmEl\n"
+ + "J6fRxJ1kNAEThyzNZMnFjh8htZ7PL18CAwEAAaOCAmQwggJgMB0GA1UdJQQWMBQG\n"
+ + "CCsGAQUFBwMBBggrBgEFBQcDAjAfBgNVHSMEGDAWgBSs7aWdeqK2Q/EYiiVqbLHM\n"
+ + "qPJa1DBGBggrBgEFBQcBAQQ6MDgwNgYIKwYBBQUHMAGGKmh0dHA6Ly9zc2wtYzMt\n"
+ + "Y2ExLWV2LTIwMDkub2NzcC5kLXRydXN0Lm5ldDBmBgNVHSAEXzBdMFsGCysGAQQB\n"
+ + "pTQCgUoBMEwwSgYIKwYBBQUHAgEWPmh0dHA6Ly93d3cuZC10cnVzdC5uZXQvaW50\n"
+ + "ZXJuZXQvZmlsZXMvRC1UUlVTVF9Sb290X1BLSV9DUFMucGRmMIHZBgNVHR8EgdEw\n"
+ + "gc4wgcuggciggcWGfmxkYXA6Ly9kaXJlY3RvcnkuZC10cnVzdC5uZXQvQ049RC1U\n"
+ + "UlVTVCUyMFNTTCUyMENsYXNzJTIwMyUyMENBJTIwMSUyMEVWJTIwMjAwOSxPPUQt\n"
+ + "VHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdIZDaHR0\n"
+ + "cDovL2NybC5kLXRydXN0Lm5ldC9jcmwvZC10cnVzdF9zc2xfY2xhc3NfM19jYV8x\n"
+ + "X2V2XzIwMDkuZGVyLmNybDAzBgNVHRIELDAqgRBpbmZvQGQtdHJ1c3QubmV0hhZo\n"
+ + "dHRwOi8vd3d3LmQtdHJ1c3QubmV0MB0GA1UdDgQWBBTFei056yoNM1HWYbBCixQw\n"
+ + "wXnf0TAOBgNVHQ8BAf8EBAMCBLAwLgYDVR0RBCcwJYIjY2VydGRlbW8tZXYtcmV2\n"
+ + "b2tlZC5zc2wuZC10cnVzdC5uZXQwDQYJKoZIhvcNAQELBQADggEBALv0OA+x401T\n"
+ + "CvGQL1Ah7rclRgtxT3UjmphiLs9EE1YbweIUrN3R4tZuryyv9xslAoLCfMrHUe+f\n"
+ + "jv1hsKqw+gGlrA8d5VnAqKfUR+KCiZivdlQ2sl4PDTZWpUQYlBnjQrD8h6UrcgTA\n"
+ + "g1zUpDnioAKAQSWWxHVpcOX0IXCl3RgRz0GqUIZQ0Q8ZwYbIDEI+JzDEJgKkTzet\n"
+ + "uzin8P54PjuJO801gENp43z++xHVuBcEWkU0TMDbmdL9vPZqnxsaoL5e/llGzor5\n"
+ + "6JbU6Fc0MkuziaLPUsIxVVx3ZhZ6UFdv34swKyq6ycvKW2fgccwsQCFMrVjIo6HR\n"
+ + "qiZC9Z+23vM=\n"
+ + "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator, boolean ocspEnabled)
+ throws Exception {
+ // Validate valid
+ // Valid cert received as test artifact was revoked so remove test
+
+ // Validate Revoked
+ if (ocspEnabled) {
+ // Revoked certificates are expired in 2015
+ // and backdated revocation check is only possible with OCSP
+ pathValidator.setValidationDate("Jan 01, 2015");
+ }
+
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Jun 26 09:45:14 PDT 2014", System.out);
+
+ // reset validation date back to current date
+ pathValidator.resetValidationDate();
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/EntrustCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/EntrustCA.java
new file mode 100644
index 0000000000..d8d6d4f5f8
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/EntrustCA.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2018, 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 8195774
+ * @summary Interoperability tests with Entrust EC CA
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath EntrustCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath EntrustCA CRL
+ */
+
+/*
+ * Obtain test artifacts for Entrust EC CA from:
+ *
+ * Valid https://validec.entrust.net
+ *
+ * Revoked https://revokedec.entrust.net
+ */
+public class EntrustCA {
+
+ // Owner: CN=Entrust Certification Authority - L1J, OU="(c) 2016 Entrust, Inc. - for authorized use only",
+ // OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
+ // Issuer: CN=Entrust Root Certification Authority - EC1, OU="(c) 2012 Entrust, Inc. - for authorized use only",
+ // OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+ "MIID5zCCA2ygAwIBAgIQCoPUgD5+n1EAAAAAUdTB9zAKBggqhkjOPQQDAzCBvzEL\n" +
+ "MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1Nl\n" +
+ "ZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEy\n" +
+ "IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UE\n" +
+ "AxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4X\n" +
+ "DTE2MDQwNTIwMTk1NFoXDTM3MTAwNTIwNDk1NFowgboxCzAJBgNVBAYTAlVTMRYw\n" +
+ "FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu\n" +
+ "bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNiBFbnRydXN0LCBJbmMu\n" +
+ "IC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLjAsBgNVBAMTJUVudHJ1c3QgQ2Vy\n" +
+ "dGlmaWNhdGlvbiBBdXRob3JpdHkgLSBMMUowdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n" +
+ "AAT14eFXmpQX/dEf7NAxrMH13n0btz1KKvH2S1rROGPAKex2CY8yxznbffK/MbCk\n" +
+ "F7ByYXGs1+8kL5xmTysU/c+YmjOZx2mMSAk2DPw30fijJ3tRrwChZ+TBpgtB6+A5\n" +
+ "MsCjggEuMIIBKjAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAz\n" +
+ "BggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3Qu\n" +
+ "bmV0MDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvZWMx\n" +
+ "cm9vdC5jcmwwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEWGmh0dHA6\n" +
+ "Ly93d3cuZW50cnVzdC5uZXQvcnBhMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF\n" +
+ "BQcDAjAdBgNVHQ4EFgQUw/lFA77I+Qs8RTXz63Ls5+jrlJswHwYDVR0jBBgwFoAU\n" +
+ "t2PnGt2N6QimVYOk4GpQQWURQkkwCgYIKoZIzj0EAwMDaQAwZgIxAPnVAOqxKDd7\n" +
+ "v37EBmpPqWCCWBFPKW6HpRx3GUWc9caeQIw8rO2HXYgf92pb/TsJYAIxAJhI0MpR\n" +
+ "z5L42xF1R9UIPfQxCMwgsnWBqIqcfMrMO+2DxQy6GIP3cFFj9gRyxguKWw==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=validec.entrust.net, SERIALNUMBER=D15576572, OID.2.5.4.15=Private Organization, O="Entrust, Inc.",
+ // OID.1.3.6.1.4.1.311.60.2.1.2=Maryland, OID.1.3.6.1.4.1.311.60.2.1.3=US, L=Kanata, ST=Ontario, C=CA
+ // Issuer: CN=Entrust Certification Authority - L1J, OU="(c) 2016 Entrust, Inc. - for authorized use only",
+ // OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFrTCCBTKgAwIBAgIQYtgW4DLwh74AAAAAVqBXkTAKBggqhkjOPQQDAjCBujEL\n" +
+ "MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1Nl\n" +
+ "ZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDE2\n" +
+ "IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwGA1UE\n" +
+ "AxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxSjAeFw0xODA2\n" +
+ "MjUxMzE1NTdaFw0xOTA2MjUxMzQ1NTBaMIHJMQswCQYDVQQGEwJDQTEQMA4GA1UE\n" +
+ "CBMHT250YXJpbzEPMA0GA1UEBxMGS2FuYXRhMRMwEQYLKwYBBAGCNzwCAQMTAlVT\n" +
+ "MRkwFwYLKwYBBAGCNzwCAQITCE1hcnlsYW5kMRYwFAYDVQQKEw1FbnRydXN0LCBJ\n" +
+ "bmMuMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjESMBAGA1UEBRMJRDE1\n" +
+ "NTc2NTcyMRwwGgYDVQQDExN2YWxpZGVjLmVudHJ1c3QubmV0MFkwEwYHKoZIzj0C\n" +
+ "AQYIKoZIzj0DAQcDQgAEHQe7lUaAUgIwR9EiLJlhkbx+HfSr22M3JvQD6+fnYgqd\n" +
+ "55e6E1UE45fk92UpqPi1CEbXrdpmWKu1Z470B9cPGaOCAwcwggMDMB4GA1UdEQQX\n" +
+ "MBWCE3ZhbGlkZWMuZW50cnVzdC5uZXQwggF/BgorBgEEAdZ5AgQCBIIBbwSCAWsB\n" +
+ "aQB1AFWB1MIWkDYBSuoLm1c8U/DA5Dh4cCUIFy+jqh0HE9MMAAABZDcxpMkAAAQD\n" +
+ "AEYwRAIgIb0PwjCcNOchJg8Zywz/0Lwm2vEOJUSao6BqNUIsyaYCIElHHexB06LE\n" +
+ "yXWDXO7UqOtWT6uqkdJN8V4TzwT9B4o4AHcA3esdK3oNT6Ygi4GtgWhwfi6OnQHV\n" +
+ "XIiNPRHEzbbsvswAAAFkNzGkvgAABAMASDBGAiEAlxy/kxB9waIifYn+EV550pvA\n" +
+ "C3jUfS/bjsKbcsBH9cQCIQDSHTJORz6fZu8uLFhpV525pw7iHVh2dSn3gpcteObh\n" +
+ "DQB3ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABZDcxpTsAAAQD\n" +
+ "AEgwRgIhAPCBqVqSvAEIXMPloV0tfBEEdjRrAhiG407cPqYwt9AFAiEAuQf4R5os\n" +
+ "MLkD3XhxvrTDvnD+PUOf8PzPevsWkuxNqcQwDgYDVR0PAQH/BAQDAgeAMB0GA1Ud\n" +
+ "JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBjBggrBgEFBQcBAQRXMFUwIwYIKwYB\n" +
+ "BQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MC4GCCsGAQUFBzAChiJodHRw\n" +
+ "Oi8vYWlhLmVudHJ1c3QubmV0L2wxai1lYzEuY2VyMDMGA1UdHwQsMCowKKAmoCSG\n" +
+ "Imh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvbGV2ZWwxai5jcmwwSgYDVR0gBEMwQTA2\n" +
+ "BgpghkgBhvpsCgECMCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuZW50cnVzdC5u\n" +
+ "ZXQvcnBhMAcGBWeBDAEBMB8GA1UdIwQYMBaAFMP5RQO+yPkLPEU18+ty7Ofo65Sb\n" +
+ "MB0GA1UdDgQWBBT+J7OhS6gskCanmOGnx10DPSF8ATAJBgNVHRMEAjAAMAoGCCqG\n" +
+ "SM49BAMCA2kAMGYCMQCQLUQABT74TmdHzAtB97uNF5+Zy15wzkmlKeRSOXCIf2C5\n" +
+ "YKjsgdkR1OdzZXcpjNgCMQDfWcdPhodNXZC4l1lLPOPaTzPPw6uVqqoITQlc6r1t\n" +
+ "dRkkD6K9ii/X8EtwoFp7s80=\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=revokedec.entrust.net, SERIALNUMBER=115868500, OID.2.5.4.15=Private Organization, O="Entrust, Inc.",
+ // OID.1.3.6.1.4.1.311.60.2.1.2=Texas, OID.1.3.6.1.4.1.311.60.2.1.3=US, L=Kanata, ST=Ontario, C=CA
+ // Issuer: CN=Entrust Certification Authority - L1J, OU="(c) 2016 Entrust, Inc. - for authorized use only",
+ // OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGJzCCBaygAwIBAgIRAM0WDfag1taIAAAAAFagJ5gwCgYIKoZIzj0EAwIwgbox\n" +
+ "CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9T\n" +
+ "ZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAx\n" +
+ "NiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLjAsBgNV\n" +
+ "BAMTJUVudHJ1c3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBMMUowHhcNMTcw\n" +
+ "NTI0MTcwNzA4WhcNMTkwNTI0MTczNjU1WjCByDELMAkGA1UEBhMCQ0ExEDAOBgNV\n" +
+ "BAgTB09udGFyaW8xDzANBgNVBAcTBkthbmF0YTETMBEGCysGAQQBgjc8AgEDEwJV\n" +
+ "UzEWMBQGCysGAQQBgjc8AgECEwVUZXhhczEWMBQGA1UEChMNRW50cnVzdCwgSW5j\n" +
+ "LjEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEjAQBgNVBAUTCTExNTg2\n" +
+ "ODUwMDEeMBwGA1UEAxMVcmV2b2tlZGVjLmVudHJ1c3QubmV0MFkwEwYHKoZIzj0C\n" +
+ "AQYIKoZIzj0DAQcDQgAEN5MP/59yrs9uwVM/Mrc8IuHonMChAZgN2twwvh8KTnR2\n" +
+ "3stfem/R+NtLccq+4ds1+8ktnXgP7u1x0as6IJOH1qOCA4EwggN9MCAGA1UdEQQZ\n" +
+ "MBeCFXJldm9rZWRlYy5lbnRydXN0Lm5ldDCCAfcGCisGAQQB1nkCBAIEggHnBIIB\n" +
+ "4wHhAHYA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFcO4iiogAA\n" +
+ "BAMARzBFAiAgHVpryyNVgnsUIihu+5DC2/vuP8Cy5iXq8NhCBXg8UgIhAKi5jImT\n" +
+ "f1FJksvHboc0EZh9TWhWljVZ6E5jB2CL+qzeAHcAVhQGmi/XwuzT9eG9RLI+x0Z2\n" +
+ "ubyZEVzA75SYVdaJ0N0AAAFcO4ij9QAABAMASDBGAiEA4B2p2726ISSkKC9WVlzj\n" +
+ "BVwYZ1Hr7mTjPrFqkoGpEHYCIQC5iuInkJXGBANLTH06BHIQkkr4KnFRl9QBOSw4\n" +
+ "b+kNqgB1AN3rHSt6DU+mIIuBrYFocH4ujp0B1VyIjT0RxM227L7MAAABXDuIpkcA\n" +
+ "AAQDAEYwRAIgQ9ssw19wIhHWW6IWgwnIyB7e30HacBNX6S1eQ3GUX04CICffGj3A\n" +
+ "WWmK9lixmk35YklMnSXNqHQezSYRiCYtXxejAHcApLkJkLQYWBSHuxOizGdwCjw1\n" +
+ "mAT5G9+443fNDsgN3BAAAAFcO4inUwAABAMASDBGAiEA+8T9tpPw/mU/STsNv0oz\n" +
+ "8Nla21fKlpEOyWqDKWPSUeYCIQCwI5tDyyaJtyFY9/OVqLG+BKPKjscUtTqGJYl4\n" +
+ "XbOo1jAOBgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n" +
+ "BwMCMGMGCCsGAQUFBwEBBFcwVTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50\n" +
+ "cnVzdC5uZXQwLgYIKwYBBQUHMAKGImh0dHA6Ly9haWEuZW50cnVzdC5uZXQvbDFq\n" +
+ "LWVjMS5jZXIwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5l\n" +
+ "dC9sZXZlbDFqLmNybDBKBgNVHSAEQzBBMDYGCmCGSAGG+mwKAQIwKDAmBggrBgEF\n" +
+ "BQcCARYaaHR0cDovL3d3dy5lbnRydXN0Lm5ldC9ycGEwBwYFZ4EMAQEwHwYDVR0j\n" +
+ "BBgwFoAUw/lFA77I+Qs8RTXz63Ls5+jrlJswHQYDVR0OBBYEFIj28ytR8ulo1p2t\n" +
+ "ZnBQOLK0rlLUMAkGA1UdEwQCMAAwCgYIKoZIzj0EAwIDaQAwZgIxANzqGRI0en5P\n" +
+ "gSUDcdwoQSNKrBPBfGz2AQVLHAXsxvIlGhKZAQtM49zxA8AdFy/agwIxAMEjJH6A\n" +
+ "4UbcGZc40eYu6wUbAxiUDD3gwSElNQ8Z6IhNLPCCdMM6KZORyaagAcXn4A==\n" +
+ "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Wed May 24 10:39:28 PDT 2017", System.out);
+ }
+
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java
new file mode 100644
index 0000000000..1f279a3a7c
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/GlobalSignR6CA.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2019, 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 8216577
+ * @summary Interoperability tests with GlobalSign R6 CA
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath GlobalSignR6CA OCSP
+ * @run main/othervm -Djava.security.debug=certpath GlobalSignR6CA CRL
+ */
+
+ /*
+ *
+ * Obtain TLS test artifacts for GlobalSign R6 CA from:
+ *
+ * Valid TLS Certificates:
+ * https://valid.r6.roots.globalsign.com/
+ *
+ * Revoked TLS Certificates:
+ * https://revoked.r6.roots.globalsign.com/
+ */
+public class GlobalSignR6CA {
+
+ // Owner: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+ // Issuer: CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R6
+ // Serial number: 48a402ddb5defd50accfc0fcf13f
+ // Valid from: Tue Sep 20 17:00:00 PDT 2016 until: Mon Sep 20 17:00:00 PDT 2021
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIFmjCCA4KgAwIBAgIOSKQC3bXe/VCsz8D88T8wDQYJKoZIhvcNAQELBQAwTDEg\n" +
+ "MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh\n" +
+ "bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTYwOTIxMDAwMDAwWhcNMjEw\n" +
+ "OTIxMDAwMDAwWjBXMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBu\n" +
+ "di1zYTEtMCsGA1UEAxMkR2xvYmFsU2lnbiBSNiBBZG1pbiBDQSAtIFNIQTI1NiAt\n" +
+ "IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmyyfJA4reymawDG1\n" +
+ "FNDCSFBqst/+Jih2Zg1ThovSfkxVWcviBhIZfu0t/Hv9hmolN2dxPibKCHhjyfMp\n" +
+ "WaGj+S8VPPaR3xoeOvHtuf/2uOyBZa/3mgiWWRF50fLy0fzyWNJL9lbTH459oUci\n" +
+ "QN2H0nFEuD1tGGzFdjtXCRVjWy9dZW8Vv2831buzuPLTtOPSKhqOiigpXFTo6SL9\n" +
+ "n/NHQ4HI7WV+DMB7yOPEERqQzfi28v1B2j4GOT4wqXncbw5uFZdYobBfRNv3VNdk\n" +
+ "p/2Frtm15ePBIAAb4o28du+orJUuVVpxreeEyVBGJuaP0RWksjSnqkSbPm9MEY0k\n" +
+ "dS7tgwIDAQABo4IBbTCCAWkwDgYDVR0PAQH/BAQDAgEGMCcGA1UdJQQgMB4GCCsG\n" +
+ "AQUFBwMBBggrBgEFBQcDAgYIKwYBBQUHAwkwEgYDVR0TAQH/BAgwBgEB/wIBADAd\n" +
+ "BgNVHQ4EFgQUgUlc6QW/DIigOJayXUEDWun/14cwHwYDVR0jBBgwFoAUrmwFo5MT\n" +
+ "4qLn4tcc1sfwf8hnU6AwPgYIKwYBBQUHAQEEMjAwMC4GCCsGAQUFBzABhiJodHRw\n" +
+ "Oi8vb2NzcDIuZ2xvYmFsc2lnbi5jb20vcm9vdHI2MDYGA1UdHwQvMC0wK6ApoCeG\n" +
+ "JWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yNi5jcmwwYgYDVR0gBFsw\n" +
+ "WTAHBgVngQwBATALBgkrBgEEAaAyAQEwQQYJKwYBBAGgMgFfMDQwMgYIKwYBBQUH\n" +
+ "AgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMA0GCSqG\n" +
+ "SIb3DQEBCwUAA4ICAQBovPHk0rWZ5tGQ3NiYORqZNfSh2KH0RxweRE+ZTpnGOZjE\n" +
+ "vRQYLYm/vf2q+v2IcESmpVCjq1eN0k75wc/4475Y9RH6xK7ai1+O8HHDgj8GK4iZ\n" +
+ "0ILbKtJQ2/ih19TMO7M3Y/tZByLPcdy8cuDMoCWoQJqUFtM8l784S5lEjefrcwkZ\n" +
+ "uNOdTrZbsqXY71Xfa61DNuW3lIt/w34myrKG0xRyGicI9P9VpcWYdWCKpwVe10MP\n" +
+ "d4WQ/lclJZLrLljmn76bc+q/L2Sw+tpadsD2qP3l05FhRqcF5iI9lIw77KIU15Jt\n" +
+ "QysmI7xTjByjny/OiIYP/7PKQjh+KEe/17GOg0AamdI9dbaOHRcyHFht01ymaphf\n" +
+ "kU3hjWb2bdtVLuDsIKfGN/QDXSmv0ThKsgkj3OOiLUpllApr5SU2tY40rpZ210iD\n" +
+ "/jA18LYwBmR64t3e7ud/tDz4c/YLY8p6vPLdASbbwyptj93n0c0HXpjdcrx/XOQa\n" +
+ "ogw6JzJ2v3Kok94frBKKdoxg4SnMvZoakM1SbY6Q3XlC24qVnVuWJ142rVkCFixZ\n" +
+ "Sb5ZEB7fxk/2YfaWkSW3uejwh2qN7qXji0S1ALNbASJATYqMgdJVz+25yOBfxFN6\n" +
+ "KzNbvmVmEM/hnKaQxePhwForQjDFaep1RO5Yg4wnIcLRC3atKgkIIA6YDNUcog==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=valid.r6.roots.globalsign.com, O=GMO GlobalSign Inc., STREET="Two International Drive, Suite 150",
+ // L=Portsmouth, ST=New Hampshire, C=US, OID.1.3.6.1.4.1.311.60.2.1.2=New Hampshire, OID.1.3.6.1.4.1.311.60.2.1.3=US,
+ // SERIALNUMBER=578611, OID.2.5.4.15=Private Organization
+ // Issuer: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+ // Serial number: 1355071ec648a599cea67b3b
+ // Valid from: Wed Jun 13 21:31:05 PDT 2018 until: Sat Jun 13 21:31:05 PDT 2020
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHUjCCBjqgAwIBAgIME1UHHsZIpZnOpns7MA0GCSqGSIb3DQEBCwUAMFcxCzAJ\n" +
+ "BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRH\n" +
+ "bG9iYWxTaWduIFI2IEFkbWluIENBIC0gU0hBMjU2IC0gRzMwHhcNMTgwNjE0MDQz\n" +
+ "MTA1WhcNMjAwNjE0MDQzMTA1WjCCARIxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5p\n" +
+ "emF0aW9uMQ8wDQYDVQQFEwY1Nzg2MTExEzARBgsrBgEEAYI3PAIBAxMCVVMxHjAc\n" +
+ "BgsrBgEEAYI3PAIBAhMNTmV3IEhhbXBzaGlyZTELMAkGA1UEBhMCVVMxFjAUBgNV\n" +
+ "BAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxKzApBgNVBAkT\n" +
+ "IlR3byBJbnRlcm5hdGlvbmFsIERyaXZlLCBTdWl0ZSAxNTAxHDAaBgNVBAoTE0dN\n" +
+ "TyBHbG9iYWxTaWduIEluYy4xJjAkBgNVBAMTHXZhbGlkLnI2LnJvb3RzLmdsb2Jh\n" +
+ "bHNpZ24uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArh1lHcNS\n" +
+ "cfvFI/vGrfu3sC561NL6VTm9WQpq0UcdQpVlOjnmlScZaUhTlcJ2aWz4tqNnT/SF\n" +
+ "EO48kgIy0c07n0z1igBGOvM6shPtdIT3Yik2KwKdnt2Oaw/RqyXQxZhMvvGGyXLP\n" +
+ "hEyRdUrcNEXzOh+/AFzV2Ayo2OfZB/SEJW2BMhYEvZ89ziniab7vaNfVVUwsR6yD\n" +
+ "JX/3bdgRpG3gvKpdawAXMkhX5yAJaLInp5gHfCKNsW7l5gSrW/IYmPZvmEovLLmF\n" +
+ "lJfEDltnaNrO3jFzCjzEVRsurBrn1lMgKuCCkCZhzUgy5w8fR7OiGDpI/DmprRxn\n" +
+ "WQomtZBRd9VG1wIDAQABo4IDXzCCA1swDgYDVR0PAQH/BAQDAgWgMIGWBggrBgEF\n" +
+ "BQcBAQSBiTCBhjBHBggrBgEFBQcwAoY7aHR0cDovL3NlY3VyZS5nbG9iYWxzaWdu\n" +
+ "LmNvbS9jYWNlcnQvZ3NyNmFkbWluY2FzaGEyNTZnMy5jcnQwOwYIKwYBBQUHMAGG\n" +
+ "L2h0dHA6Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9nc3I2YWRtaW5jYXNoYTI1Nmcz\n" +
+ "MFUGA1UdIAROMEwwQQYJKwYBBAGgMgEBMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v\n" +
+ "d3d3Lmdsb2JhbHNpZ24uY29tL3JlcG9zaXRvcnkvMAcGBWeBDAEBMAkGA1UdEwQC\n" +
+ "MAAwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9n\n" +
+ "c3I2YWRtaW5jYXNoYTI1NmczLmNybDAoBgNVHREEITAfgh12YWxpZC5yNi5yb290\n" +
+ "cy5nbG9iYWxzaWduLmNvbTAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw\n" +
+ "HQYDVR0OBBYEFPTkCvZs787YEtziawL5ju/rC8XwMB8GA1UdIwQYMBaAFIFJXOkF\n" +
+ "vwyIoDiWsl1BA1rp/9eHMIIBfwYKKwYBBAHWeQIEAgSCAW8EggFrAWkAdwBVgdTC\n" +
+ "FpA2AUrqC5tXPFPwwOQ4eHAlCBcvo6odBxPTDAAAAWP8j7bvAAAEAwBIMEYCIQDH\n" +
+ "FRH+VkQ4RgVRYaO47rC83fQrzEO9Pb45BD5ZEHfrRwIhALY75BbrPhtAZSXWfpVN\n" +
+ "MoDQzA6X0DQFSf29dlnCMYCmAHcApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fN\n" +
+ "DsgN3BAAAAFj/I+4QgAABAMASDBGAiEA3kcOlf4Az7R+/MkV5GurWnpUmIhCUB3v\n" +
+ "a/tNz+Dd8HgCIQC22RG+EW4OYdaoWN/B3MeI95OlNofD/OqJB/med+quWwB1AG9T\n" +
+ "dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABY/yPt6kAAAQDAEYwRAIg\n" +
+ "THH7eeWpo5vDtjDNKzpkkrR/McYDgmQIRRnLKXkKMsoCIC9cY4xj9LlXPVRF9bLH\n" +
+ "1DvP9qmONga9pO7kxuyYtd8YMA0GCSqGSIb3DQEBCwUAA4IBAQA0Ufq4QDCiWxm4\n" +
+ "5D3MrfbQnC9apSMpzRT2udD/gFDbtqTJ7Rx4CJjNWa9ANkKWNlJ6zVASpVzV7KB7\n" +
+ "otvqO4iR5V0EE4+9fitJ3zRe9nl76uDf2upCHLcWsYurq/eIxIuXnIByLJvTS3jS\n" +
+ "42i07D6JsgNg9SR8rIKyYiz4KX2975GlMSue/SOMFcf/AC7amYzs6U+FA68y8GBV\n" +
+ "yDGpYvQW9zfnQ2Z/XVcLE1tVERrEs3Ba08g+uk1dICyibSz83yrX3Eas/bq6kZEy\n" +
+ "kRvhD1fnk3wAlgiuUED65Rn3ezm2AjsFJBIitdDyHFzgZiu/DKccakuuk8NwDZjJ\n" +
+ "NrTZIL32\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=revoked.r6.roots.globalsign.com, O=GMO GlobalSign Inc., STREET="Two International Drive, Suite 150",
+ // L=Portsmouth, ST=New Hampshire, C=US, OID.1.3.6.1.4.1.311.60.2.1.2=New Hampshire, OID.1.3.6.1.4.1.311.60.2.1.3=US,
+ // SERIALNUMBER=578611, OID.2.5.4.15=Private Organization
+ // Issuer: CN=GlobalSign R6 Admin CA - SHA256 - G3, O=GlobalSign nv-sa, C=BE
+ // Serial number: 535589c9d767cf1cd892f1dc
+ // Valid from: Wed Jun 13 21:36:04 PDT 2018 until: Sat Jun 13 21:36:04 PDT 2020
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHVTCCBj2gAwIBAgIMU1WJyddnzxzYkvHcMA0GCSqGSIb3DQEBCwUAMFcxCzAJ\n" +
+ "BgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMS0wKwYDVQQDEyRH\n" +
+ "bG9iYWxTaWduIFI2IEFkbWluIENBIC0gU0hBMjU2IC0gRzMwHhcNMTgwNjE0MDQz\n" +
+ "NjA0WhcNMjAwNjE0MDQzNjA0WjCCARQxHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5p\n" +
+ "emF0aW9uMQ8wDQYDVQQFEwY1Nzg2MTExEzARBgsrBgEEAYI3PAIBAxMCVVMxHjAc\n" +
+ "BgsrBgEEAYI3PAIBAhMNTmV3IEhhbXBzaGlyZTELMAkGA1UEBhMCVVMxFjAUBgNV\n" +
+ "BAgTDU5ldyBIYW1wc2hpcmUxEzARBgNVBAcTClBvcnRzbW91dGgxKzApBgNVBAkT\n" +
+ "IlR3byBJbnRlcm5hdGlvbmFsIERyaXZlLCBTdWl0ZSAxNTAxHDAaBgNVBAoTE0dN\n" +
+ "TyBHbG9iYWxTaWduIEluYy4xKDAmBgNVBAMTH3Jldm9rZWQucjYucm9vdHMuZ2xv\n" +
+ "YmFsc2lnbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6SJ+O\n" +
+ "PX5/ECfblZpVByiogO5sUCS23Sry3Ucn1fxFO3b6tOKppUtgZjJUxUOHj9jRIsmS\n" +
+ "8Tvbn+Iu35Cjj2vTsJNoFzxiMj/FBl3IqfF7w4ghLNZ+wE91cMwG0LUtDeAKTlJa\n" +
+ "j4Q2Gj1ZOGLPyr4flSig2bOvcIBWYjbXqwBMZek9EC58D34HF+h2fdzXPrqHHWqg\n" +
+ "NQpj7lxkr4XA1jXSgZJZnRfoVW+BCVidbNw9LEteF+WGcg3P9sd8XUWJtG/pb4w1\n" +
+ "GsCMf/ig8gkrsQvrMYPsYgQJMdypXm9eAqZmVcE94E0Uz1dbJL9zCa8y4ue9yDnp\n" +
+ "+gzXxToJvNzrlmUPAgMBAAGjggNgMIIDXDAOBgNVHQ8BAf8EBAMCBaAwgZYGCCsG\n" +
+ "AQUFBwEBBIGJMIGGMEcGCCsGAQUFBzAChjtodHRwOi8vc2VjdXJlLmdsb2JhbHNp\n" +
+ "Z24uY29tL2NhY2VydC9nc3I2YWRtaW5jYXNoYTI1NmczLmNydDA7BggrBgEFBQcw\n" +
+ "AYYvaHR0cDovL29jc3AyLmdsb2JhbHNpZ24uY29tL2dzcjZhZG1pbmNhc2hhMjU2\n" +
+ "ZzMwVQYDVR0gBE4wTDBBBgkrBgEEAaAyAQEwNDAyBggrBgEFBQcCARYmaHR0cHM6\n" +
+ "Ly93d3cuZ2xvYmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wBwYFZ4EMAQEwCQYDVR0T\n" +
+ "BAIwADBCBgNVHR8EOzA5MDegNaAzhjFodHRwOi8vY3JsLmdsb2JhbHNpZ24uY29t\n" +
+ "L2dzcjZhZG1pbmNhc2hhMjU2ZzMuY3JsMCoGA1UdEQQjMCGCH3Jldm9rZWQucjYu\n" +
+ "cm9vdHMuZ2xvYmFsc2lnbi5jb20wHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUF\n" +
+ "BwMCMB0GA1UdDgQWBBR66TcwHJ5KRJZqtNB3Cqj8rWUAYzAfBgNVHSMEGDAWgBSB\n" +
+ "SVzpBb8MiKA4lrJdQQNa6f/XhzCCAX4GCisGAQQB1nkCBAIEggFuBIIBagFoAHYA\n" +
+ "VYHUwhaQNgFK6gubVzxT8MDkOHhwJQgXL6OqHQcT0wwAAAFj/JRH/gAABAMARzBF\n" +
+ "AiBtxn2bgwXrjx2zX3RPP3L4iFEZ1bK71oZ67RvNpI/pWQIhAK1Wg3wEdSqUUa9I\n" +
+ "VKSNaDaMqtI7s5yQvIV3YdDDxl+hAHcAu9nfvB+KcbWTlCOXqpJ7RzhXlQqrUuga\n" +
+ "kJZkNo4e0YUAAAFj/JRJMQAABAMASDBGAiEAkwpftFhujb0p9wNDywVgZPPxGdLy\n" +
+ "7c7WnpBLkViuvVgCIQCtWUK5pfYn+FWPKX82XmG0Hw1VgeQRPZZNAy0HQu/V0QB1\n" +
+ "AG9Tdqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABY/yUSPUAAAQDAEYw\n" +
+ "RAIgEN2Y70rpA+zoK1C5bKEOYUDy6Km5pgymDEPcMBgmh5ECIEAWEPdNA9FeCwqW\n" +
+ "S1Mi3uOhB4dmJKNbToFWtL2lBeDrMA0GCSqGSIb3DQEBCwUAA4IBAQCDoIyqZlvt\n" +
+ "YeqjVCR2rvb1ZHyB5UI5rfYuoNstjaxLKP2tIDByeGwllT0vSb2otM6XjXGVuTTO\n" +
+ "sbVUf4aQQb82pkKXYtB6L7cfPkqrnZXJrmPYb+3xzAsr+HXyyPOu0FIVrtB/WTvd\n" +
+ "Qo/JyVMm7Duke/e5gudw9Lv6sb2P5B3BVcNzbv1f7589wydNvrTgdVeldyPNfuZ4\n" +
+ "gMT/ICoNaX+U6O3EiqYB+gLDBKVAIDsQV1k/fYq5uZr1FsTzOMesaCT4me/4I4tR\n" +
+ "2H7WrVajYEJ73gWUclDLxy7hoDNwR/ZuLcilAaqdwIdmVD0aFiw8RFsyZkXO5J0R\n" +
+ "BuecWspICLIw\n" +
+ "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Wed Jun 13 23:36:02 PDT 2018", System.out);
+
+ }
+}
+
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/GoDaddyCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/GoDaddyCA.java
new file mode 100644
index 0000000000..e8971b987c
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/GoDaddyCA.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2018, 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 8196141
+ * @summary Interoperability tests with GoDaddy/Starfield CA
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath GoDaddyCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath GoDaddyCA CRL
+ */
+
+/*
+ * Obtain test artifacts for GoDaddy/Starfield CAs from:
+ *
+ * Go Daddy Root Certificate Authority - G2:
+ * valid: https://valid.gdig2.catest.godaddy.com/
+ * expired: https://expired.gdig2.catest.godaddy.com/
+ * revoked: https://revoked.gdig2.catest.godaddy.com/
+ *
+ * Starfield Root Certificate Authority - G2:
+ * valid: https://valid.sfig2.catest.starfieldtech.com/
+ * expired: https://expired.sfig2.catest.starfieldtech.com/
+ * revoked: https://revoked.sfig2.catest.starfieldtech.com/
+ */
+public class GoDaddyCA {
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ // CRL check
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ new GoDaddyGdig2().runTest(pathValidator);
+ new GoDaddySfig2().runTest(pathValidator);
+ }
+}
+
+class GoDaddyGdig2 {
+
+ // Owner: CN=Go Daddy Secure Certificate Authority - G2,
+ // OU=http://certs.godaddy.com/repository/, O="GoDaddy.com, Inc.",
+ // L=Scottsdale, ST=Arizona, C=US
+ // Issuer: CN=Go Daddy Root Certificate Authority - G2, O="GoDaddy.com, Inc.",
+ // L=Scottsdale, ST=Arizona, C=US
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx\n"
+ + "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT\n"
+ + "EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp\n"
+ + "ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAwMFoXDTMxMDUwMzA3\n"
+ + "MDAwMFowgbQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH\n"
+ + "EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UE\n"
+ + "CxMkaHR0cDovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQD\n"
+ + "EypHbyBEYWRkeSBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi\n"
+ + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC54MsQ1K92vdSTYuswZLiBCGzD\n"
+ + "BNliF44v/z5lz4/OYuY8UhzaFkVLVat4a2ODYpDOD2lsmcgaFItMzEUz6ojcnqOv\n"
+ + "K/6AYZ15V8TPLvQ/MDxdR/yaFrzDN5ZBUY4RS1T4KL7QjL7wMDge87Am+GZHY23e\n"
+ + "cSZHjzhHU9FGHbTj3ADqRay9vHHZqm8A29vNMDp5T19MR/gd71vCxJ1gO7GyQ5HY\n"
+ + "pDNO6rPWJ0+tJYqlxvTV0KaudAVkV4i1RFXULSo6Pvi4vekyCgKUZMQWOlDxSq7n\n"
+ + "eTOvDCAHf+jfBDnCaQJsY1L6d8EbyHSHyLmTGFBUNUtpTrw700kuH9zB0lL7AgMB\n"
+ + "AAGjggEaMIIBFjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV\n"
+ + "HQ4EFgQUQMK9J47MNIMwojPX+2yz8LQsgM4wHwYDVR0jBBgwFoAUOpqFBxBnKLbv\n"
+ + "9r0FQW4gwZTaD94wNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v\n"
+ + "b2NzcC5nb2RhZGR5LmNvbS8wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5n\n"
+ + "b2RhZGR5LmNvbS9nZHJvb3QtZzIuY3JsMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEG\n"
+ + "CCsGAQUFBwIBFiVodHRwczovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv\n"
+ + "MA0GCSqGSIb3DQEBCwUAA4IBAQAIfmyTEMg4uJapkEv/oV9PBO9sPpyIBslQj6Zz\n"
+ + "91cxG7685C/b+LrTW+C05+Z5Yg4MotdqY3MxtfWoSKQ7CC2iXZDXtHwlTxFWMMS2\n"
+ + "RJ17LJ3lXubvDGGqv+QqG+6EnriDfcFDzkSnE3ANkR/0yBOtg2DZ2HKocyQetawi\n"
+ + "DsoXiWJYRBuriSUBAA/NxBti21G00w9RKpv0vHP8ds42pM3Z2Czqrpv1KrKQ0U11\n"
+ + "GIo/ikGQI31bS/6kA1ibRrLDYGCD+H1QQc7CoZDDu+8CL9IVVO5EFdkKrqeKM+2x\n"
+ + "LXY2JtwE65/3YR8V3Idv7kaWKK2hJn0KCacuBKONvPi8BDAB\n"
+ + "-----END CERTIFICATE-----";
+
+ // 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/businessCategory=Private
+ // Organization/serialNumber=5510922, C=US, ST=Arizona, L=Scottsdale, O=GoDaddy INC., CN=valid.gdig2.catest.godaddy.com
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHbzCCBlegAwIBAgIIC3Go9uPeseowDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV\n" +
+ "BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow\n" +
+ "GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UECxMkaHR0cDovL2NlcnRz\n" +
+ "LmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQDEypHbyBEYWRkeSBTZWN1\n" +
+ "cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwHhcNMTcwOTE1MjMyMzAyWhcN\n" +
+ "MTkwOTE1MjMyMzAyWjCB1TETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQB\n" +
+ "gjc8AgECEwhEZWxhd2FyZTEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x\n" +
+ "EDAOBgNVBAUTBzU1MTA5MjIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25h\n" +
+ "MRMwEQYDVQQHEwpTY290dHNkYWxlMRUwEwYDVQQKEwxHb0RhZGR5IElOQy4xJzAl\n" +
+ "BgNVBAMTHnZhbGlkLmdkaWcyLmNhdGVzdC5nb2RhZGR5LmNvbTCCASIwDQYJKoZI\n" +
+ "hvcNAQEBBQADggEPADCCAQoCggEBAO3xTbLfdIHiG1MIsBCz0oIg5vBxlzZyK5Rw\n" +
+ "DM6A/TWUDelFWyYj6fZDXYyHby4nAK9ibfhiT2f+q+5lEslye5Mt9gC39pZbpHE2\n" +
+ "eyJgmtNgmPGq15pf/87JE697BRwp9CWJP3yNYeamFl/F2THZOqlXCiSRbIGZ5TsZ\n" +
+ "sVb1vjFPmh249Ujw1zSThY9hA669Cyp3xb4iTowjCqdNYqbn22Jbk0SEXPYzLMf0\n" +
+ "mlY8xZ/e/8NxzJgev3N1LR3bPEijLYDZeZJ6WKc75pqNvgo8A+dEeX9bxFkCnstY\n" +
+ "6Iq0HTJua0TTD6V585YXNm4Z5OxjBE5kPkkFfwW0bb5dRZp86HUCAwEAAaOCA2Aw\n" +
+ "ggNcMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC\n" +
+ "MA4GA1UdDwEB/wQEAwIFoDA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLmdv\n" +
+ "ZGFkZHkuY29tL2dkaWcyczMtOS5jcmwwXAYDVR0gBFUwUzBIBgtghkgBhv1tAQcX\n" +
+ "AzA5MDcGCCsGAQUFBwIBFitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29t\n" +
+ "L3JlcG9zaXRvcnkvMAcGBWeBDAEBMHYGCCsGAQUFBwEBBGowaDAkBggrBgEFBQcw\n" +
+ "AYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMEAGCCsGAQUFBzAChjRodHRwOi8v\n" +
+ "Y2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RpZzIuY3J0MB8G\n" +
+ "A1UdIwQYMBaAFEDCvSeOzDSDMKIz1/tss/C0LIDOME0GA1UdEQRGMESCHnZhbGlk\n" +
+ "LmdkaWcyLmNhdGVzdC5nb2RhZGR5LmNvbYIid3d3LnZhbGlkLmdkaWcyLmNhdGVz\n" +
+ "dC5nb2RhZGR5LmNvbTAdBgNVHQ4EFgQUKSs41O+5SnkjAEaNyHk6sxq5sn8wggF/\n" +
+ "BgorBgEEAdZ5AgQCBIIBbwSCAWsBaQB3AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFc\n" +
+ "wO+UmFXWidDdAAABXofbjGMAAAQDAEgwRgIhAPZEqPZAlYpSTx+R/+7mOUa+BcBz\n" +
+ "U1JHZDpcy98am0glAiEA1u2FxjgAa4L5HVGYV2LSQZIltGRJ8mBT8V0JVsdm3dsA\n" +
+ "dgDuS723dc5guuFCaR+r4Z5mow9+X7By2IMAxHuJeqj9ywAAAV6H25ASAAAEAwBH\n" +
+ "MEUCIQCFowkRXyR8gkX8cL7RbPSwiKCHy/1I1WVzpinmrHlZFQIgE5nShGeK7cqT\n" +
+ "j2C9FfrPc/Axe3/pzAFxD/BNQD1RO5sAdgCkuQmQtBhYFIe7E6LMZ3AKPDWYBPkb\n" +
+ "37jjd80OyA3cEAAAAV6H25GdAAAEAwBHMEUCIBQrE+FqILUhI0wdp2X+lf/e3UG1\n" +
+ "gyxHmSVeN2+CkrXPAiEA1mIIVmLNURGyI8wnZ5KRnBPOKYM2MC54RJ8CFrEHIz4w\n" +
+ "DQYJKoZIhvcNAQELBQADggEBADInvf3eS6SgQ1qxPx4RT2hPeU5frlWJWcOWUdZB\n" +
+ "6mVNcmUQMkYnjkg8+PQ782HGP0DvAfcIRDhSfXdIqzEk8MPUq1XHEOfwRzLpTiCN\n" +
+ "FQDQIt1LXnzESCUurJS8r4mxgaVLAwHFytOTDrQn0Xfs93dm0tnRGAg7iBg+N33V\n" +
+ "zOR4aqojdDUWa1Rr4WFqZMkZIxzREQCYC8HXSYqLA1oPuoMMog8dId7XSalBmGJ4\n" +
+ "KQVsZ0/Hpi0y9k/Zw5obGcEYJWMbuU1iaEkvdtXOiXEQfJ1WS+Yy55J4GSjpIiop\n" +
+ "qDZD88xA9r7ttzM/khao7jfIpVWG2HuX0JlHWdh3y9aegiw=\n" +
+ "-----END CERTIFICATE-----";
+
+ // 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Delaware/businessCategory=Private
+ // Organization/serialNumber=5510922, C=US, ST=Arizona, L=Scottsdale, O=GoDaddy INC., CN=revoked.gdig2.catest.godaddy.com
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHdDCCBlygAwIBAgIIEBJV3vmogM8wDQYJKoZIhvcNAQELBQAwgbQxCzAJBgNV\n" +
+ "BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRow\n" +
+ "GAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UECxMkaHR0cDovL2NlcnRz\n" +
+ "LmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQDEypHbyBEYWRkeSBTZWN1\n" +
+ "cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwHhcNMTcwOTE1MjMyMzAzWhcN\n" +
+ "MTkwOTE1MjMyMzAzWjCB1zETMBEGCysGAQQBgjc8AgEDEwJVUzEZMBcGCysGAQQB\n" +
+ "gjc8AgECEwhEZWxhd2FyZTEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24x\n" +
+ "EDAOBgNVBAUTBzU1MTA5MjIxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25h\n" +
+ "MRMwEQYDVQQHEwpTY290dHNkYWxlMRUwEwYDVQQKEwxHb0RhZGR5IElOQy4xKTAn\n" +
+ "BgNVBAMTIHJldm9rZWQuZ2RpZzIuY2F0ZXN0LmdvZGFkZHkuY29tMIIBIjANBgkq\n" +
+ "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCuBsAR2XGf05mYOuag+0aS4lBuLO5/f\n" +
+ "kEO7KNo7BcdY7J78yXYRYW0jGnV29bjrQZJfu5yv5bU+OjTIDVbCWZAwtBXEKrJj\n" +
+ "riIOUXi3hXphtlyMMAaiXQoA84jwS634DsD0w6XUUP2Lem8jC3RudjvmkDQHoY3M\n" +
+ "uhhS7jLxKnYKnXbLwlqxpdwmEgbqIb5DN5snLAyinTkALLVWZ6RneIuSjhKWbuef\n" +
+ "cEKFScHm6SFsKraltV/T17SWi6zQd/AypKA8JeWXD9WZcsSR9z/41VMJbvTeuP+d\n" +
+ "ZBA4dqPsBTl4N4i54rNEyzMyxDwdvIGrJJ+FVRMKoYjuUi5wY9zO4QIDAQABo4ID\n" +
+ "YzCCA18wDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH\n" +
+ "AwIwDgYDVR0PAQH/BAQDAgWgMDUGA1UdHwQuMCwwKqAooCaGJGh0dHA6Ly9jcmwu\n" +
+ "Z29kYWRkeS5jb20vZ2RpZzJzMy05LmNybDBcBgNVHSAEVTBTMEgGC2CGSAGG/W0B\n" +
+ "BxcDMDkwNwYIKwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j\n" +
+ "b20vcmVwb3NpdG9yeS8wBwYFZ4EMAQEwdgYIKwYBBQUHAQEEajBoMCQGCCsGAQUF\n" +
+ "BzABhhhodHRwOi8vb2NzcC5nb2RhZGR5LmNvbS8wQAYIKwYBBQUHMAKGNGh0dHA6\n" +
+ "Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS9nZGlnMi5jcnQw\n" +
+ "HwYDVR0jBBgwFoAUQMK9J47MNIMwojPX+2yz8LQsgM4wUQYDVR0RBEowSIIgcmV2\n" +
+ "b2tlZC5nZGlnMi5jYXRlc3QuZ29kYWRkeS5jb22CJHd3dy5yZXZva2VkLmdkaWcy\n" +
+ "LmNhdGVzdC5nb2RhZGR5LmNvbTAdBgNVHQ4EFgQUCJELlWq8+ntmR5JTjmZMG+HI\n" +
+ "e5EwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB1AFYUBpov18Ls0/XhvUSyPsdG\n" +
+ "drm8mRFcwO+UmFXWidDdAAABXofbk3cAAAQDAEYwRAIgHo8UllsN8FcaF16xx7kT\n" +
+ "vQU1wM7qUKnhN38/z8dU4QUCIFrzGJyajoVPQ2fzOTb9ygzA7T3wqsnT3ML5/KJ6\n" +
+ "+6+CAHYA7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFeh9uXHQAA\n" +
+ "BAMARzBFAiEA5DENZZT7SBxNRvo9yFHNNeWqH2d4uqGUwc1rKILrMGsCIHZ3N4dZ\n" +
+ "zv/J+7fbLP1nrAmdUT92ow1bhtMPuq2PfXsAAHcApLkJkLQYWBSHuxOizGdwCjw1\n" +
+ "mAT5G9+443fNDsgN3BAAAAFeh9uYjAAABAMASDBGAiEAyY8ylnGHiH5L3yXE7BsH\n" +
+ "v75ja2RtuuYbMADAlDK/ZDoCIQDwuCq3x+egpB/GISxTnwkrDwhNhhIJNyk5F4j1\n" +
+ "/J8A0DANBgkqhkiG9w0BAQsFAAOCAQEAMGot6gBZ77HIDMb1n/HPrKdSHN0ngq7Z\n" +
+ "rhrkgbp+mH1Cs1lZA3qldMDxKXgNiodFqU/e4VewasQ9tJMmDXrTZIHualJGmIvq\n" +
+ "ISvV0ZUfSW/sJmo0ZDw8iBM993LDkA4wSc6SunhjOwu3LBfl9aKkeq6IhUEAG8X7\n" +
+ "54oO4iApt+APLMyeV9lZ/T7MGVbAjwdm+T1RMa/Ca99BahaRWN7hiM+zS3Ly+l6G\n" +
+ "7kqAkBFuJWbbZImADZ2RPldY6hBzTk6MT2hLCV40UD8JqwJo+qq7nGfJdTaFyZI6\n" +
+ "nJvrVATO7jL64YFP3xlVi8EQaCeKdZdn+BCCNA/ja0mWMj8EU9Islg==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED, null, System.out);
+ }
+}
+
+class GoDaddySfig2 {
+
+ // Owner: CN=Starfield Secure Certificate Authority - G2,
+ // OU=http://certs.starfieldtech.com/repository/, O="Starfield Technologies, Inc.",
+ // L=Scottsdale, ST=Arizona, C=US
+ // Issuer: CN=Starfield Root Certificate Authority - G2,
+ // O="Starfield Technologies, Inc.", L=Scottsdale, ST=Arizona, C=US
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFADCCA+igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx\n"
+ + "EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT\n"
+ + "HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs\n"
+ + "ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAw\n"
+ + "MFoXDTMxMDUwMzA3MDAwMFowgcYxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6\n"
+ + "b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj\n"
+ + "aG5vbG9naWVzLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydHMuc3RhcmZpZWxk\n"
+ + "dGVjaC5jb20vcmVwb3NpdG9yeS8xNDAyBgNVBAMTK1N0YXJmaWVsZCBTZWN1cmUg\n"
+ + "Q2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n"
+ + "DwAwggEKAoIBAQDlkGZL7PlGcakgg77pbL9KyUhpgXVObST2yxcT+LBxWYR6ayuF\n"
+ + "pDS1FuXLzOlBcCykLtb6Mn3hqN6UEKwxwcDYav9ZJ6t21vwLdGu4p64/xFT0tDFE\n"
+ + "3ZNWjKRMXpuJyySDm+JXfbfYEh/JhW300YDxUJuHrtQLEAX7J7oobRfpDtZNuTlV\n"
+ + "Bv8KJAV+L8YdcmzUiymMV33a2etmGtNPp99/UsQwxaXJDgLFU793OGgGJMNmyDd+\n"
+ + "MB5FcSM1/5DYKp2N57CSTTx/KgqT3M0WRmX3YISLdkuRJ3MUkuDq7o8W6o0OPnYX\n"
+ + "v32JgIBEQ+ct4EMJddo26K3biTr1XRKOIwSDAgMBAAGjggEsMIIBKDAPBgNVHRMB\n"
+ + "Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUJUWBaFAmOD07LSy+\n"
+ + "zWrZtj2zZmMwHwYDVR0jBBgwFoAUfAwyH6fZMH/EfWijYqihzqsHWycwOgYIKwYB\n"
+ + "BQUHAQEELjAsMCoGCCsGAQUFBzABhh5odHRwOi8vb2NzcC5zdGFyZmllbGR0ZWNo\n"
+ + "LmNvbS8wOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5zdGFyZmllbGR0ZWNo\n"
+ + "LmNvbS9zZnJvb3QtZzIuY3JsMEwGA1UdIARFMEMwQQYEVR0gADA5MDcGCCsGAQUF\n"
+ + "BwIBFitodHRwczovL2NlcnRzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkv\n"
+ + "MA0GCSqGSIb3DQEBCwUAA4IBAQBWZcr+8z8KqJOLGMfeQ2kTNCC+Tl94qGuc22pN\n"
+ + "QdvBE+zcMQAiXvcAngzgNGU0+bE6TkjIEoGIXFs+CFN69xpk37hQYcxTUUApS8L0\n"
+ + "rjpf5MqtJsxOYUPl/VemN3DOQyuwlMOS6eFfqhBJt2nk4NAfZKQrzR9voPiEJBjO\n"
+ + "eT2pkb9UGBOJmVQRDVXFJgt5T1ocbvlj2xSApAer+rKluYjdkf5lO6Sjeb6JTeHQ\n"
+ + "sPTIFwwKlhR8Cbds4cLYVdQYoKpBaXAko7nv6VrcPuuUSvC33l8Odvr7+2kDRUBQ\n"
+ + "7nIMpBKGgc0T0U7EPMpODdIm8QC3tKai4W56gf0wrHofx1l7\n"
+ + "-----END CERTIFICATE-----";
+
+ // 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Arizona/businessCategory=Private
+ // Organization/serialNumber=R17247416, C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, LLC,
+ // CN=valid.sfig2.catest.starfieldtech.com
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHuzCCBqOgAwIBAgIIaZoUcUIjkGwwDQYJKoZIhvcNAQELBQAwgcYxCzAJBgNV\n" +
+ "BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUw\n" +
+ "IwYDVQQKExxTdGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTMwMQYDVQQLEypo\n" +
+ "dHRwOi8vY2VydHMuc3RhcmZpZWxkdGVjaC5jb20vcmVwb3NpdG9yeS8xNDAyBgNV\n" +
+ "BAMTK1N0YXJmaWVsZCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIw\n" +
+ "HhcNMTcwOTE3MDM0ODAxWhcNMTkwOTE3MDM0ODAxWjCB6zETMBEGCysGAQQBgjc8\n" +
+ "AgEDEwJVUzEYMBYGCysGAQQBgjc8AgECEwdBcml6b25hMR0wGwYDVQQPExRQcml2\n" +
+ "YXRlIE9yZ2FuaXphdGlvbjESMBAGA1UEBRMJUjE3MjQ3NDE2MQswCQYDVQQGEwJV\n" +
+ "UzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEkMCIGA1UE\n" +
+ "ChMbU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgTExDMS0wKwYDVQQDEyR2YWxpZC5z\n" +
+ "ZmlnMi5jYXRlc3Quc3RhcmZpZWxkdGVjaC5jb20wggEiMA0GCSqGSIb3DQEBAQUA\n" +
+ "A4IBDwAwggEKAoIBAQDVxhI45IQtNrJuun7HU8v2CKg/h/euysft2VrRsaGSMAln\n" +
+ "V6TtpWj2UGm7OmzE2NNzOhD9JJQSc1W6aHEsCTVJ148sgldFFmP39cboBFoLCFlJ\n" +
+ "DxsVGeyKu+KlDKq7Vp2+ty3TeFNOBXEVtEc8SsC8mVjsk2VWW7X/fCVFYEzzyPUI\n" +
+ "sJPWahNOW2wVxNWKeW5jwzeNMOFVQiT9+YpZVQnV06uK3rPd9tVYU5SfdfPVpScY\n" +
+ "/O/tyZyflTGuXZ+YXn1CYRsOq3VypVFfhXunV5prQ/vTnyjddVWce1wwoUT5DvFO\n" +
+ "/0vcWolHktiOAJkmAiGRfHvjhxW8mkjKqaMnstKRAgMBAAGjggOEMIIDgDAMBgNV\n" +
+ "HRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNVHQ8B\n" +
+ "Af8EBAMCBaAwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5zdGFyZmllbGR0\n" +
+ "ZWNoLmNvbS9zZmlnMnMzLTEuY3JsMGIGA1UdIARbMFkwTgYLYIZIAYb9bgEHFwMw\n" +
+ "PzA9BggrBgEFBQcCARYxaHR0cDovL2NlcnRpZmljYXRlcy5zdGFyZmllbGR0ZWNo\n" +
+ "LmNvbS9yZXBvc2l0b3J5LzAHBgVngQwBATCBggYIKwYBBQUHAQEEdjB0MCoGCCsG\n" +
+ "AQUFBzABhh5odHRwOi8vb2NzcC5zdGFyZmllbGR0ZWNoLmNvbS8wRgYIKwYBBQUH\n" +
+ "MAKGOmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuc3RhcmZpZWxkdGVjaC5jb20vcmVwb3Np\n" +
+ "dG9yeS9zZmlnMi5jcnQwHwYDVR0jBBgwFoAUJUWBaFAmOD07LSy+zWrZtj2zZmMw\n" +
+ "WQYDVR0RBFIwUIIkdmFsaWQuc2ZpZzIuY2F0ZXN0LnN0YXJmaWVsZHRlY2guY29t\n" +
+ "gih3d3cudmFsaWQuc2ZpZzIuY2F0ZXN0LnN0YXJmaWVsZHRlY2guY29tMB0GA1Ud\n" +
+ "DgQWBBTxiYdHMn55sMWTFgp7xif7ludWTjCCAX4GCisGAQQB1nkCBAIEggFuBIIB\n" +
+ "agFoAHcAVhQGmi/XwuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFejfR7OAAA\n" +
+ "BAMASDBGAiEA/s7a5OGhtaCutT1l4KNE7dUbM3WGUExG/ZJ+Y6IH3nUCIQCvpVJf\n" +
+ "Y0XBInIUv391hNzSEhv6nvIBEjZtKdvGcP8/5QB2AO5Lvbd1zmC64UJpH6vhnmaj\n" +
+ "D35fsHLYgwDEe4l6qP3LAAABXo30fxEAAAQDAEcwRQIhANqG9yfi3ax0pTnwr4Ti\n" +
+ "wVfUrZclJDS06ePkTHppLkLTAiBTRKkVf1df4Irvmd7neT1wdS2fhDxmnVIYAN5J\n" +
+ "6tOGDQB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7IDdwQAAABXo30gFsA\n" +
+ "AAQDAEYwRAIgb8Xc54M+QD4wfSWLj5Ae/wrSEgRp7Kbf4Lf4vT4W0usCIGAShkJI\n" +
+ "CRxoudQDRxooNJhfXgsTB8QhwFC9PUPo3ZV+MA0GCSqGSIb3DQEBCwUAA4IBAQBt\n" +
+ "TqvwxqrkPYm/ssbN9cpVWlrQPw3DblsAEV6gnrrTJMd7HB042H3HLUiitddRjO40\n" +
+ "0EJM/tUOSGcWfqnJHWFDKoWzdrF5lHAzSRkMjdXgY9TTN5K5tUMEpfRjtink/zoY\n" +
+ "pNyc5ua4SXn94KfMZcOYGRvUM+0q6vLRBBMH541E3M6q6JbEBqZJFY8gBWwYqHH0\n" +
+ "xNGahm5++v4trFFCJzSfvfV1v+rnqy8tRivi7ZFLXWCcSyAqMH+T9Q36lKeFtaw4\n" +
+ "Sapf+dh2yrd2IBLW5eaAD13nCAjO/W0GuC7zw4+4mhW5+DTVJXrCkK5XddkVLhML\n" +
+ "k5pMoIv5EsFIm0Cs+DfF\n" +
+ "-----END CERTIFICATE-----";
+
+ // 1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Arizona/businessCategory=Private
+ // Organization/serialNumber=R17247416, C=US, ST=Arizona, L=Scottsdale, O=Starfield Technologies, LLC,
+ // CN=revoked.sfig2.catest.starfieldtech.com
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHwTCCBqmgAwIBAgIJAPc1qVz+WDxpMA0GCSqGSIb3DQEBCwUAMIHGMQswCQYD\n" +
+ "VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEl\n" +
+ "MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEzMDEGA1UECxMq\n" +
+ "aHR0cDovL2NlcnRzLnN0YXJmaWVsZHRlY2guY29tL3JlcG9zaXRvcnkvMTQwMgYD\n" +
+ "VQQDEytTdGFyZmllbGQgU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcy\n" +
+ "MB4XDTE3MDkxOTEzMDkwMVoXDTE5MDkxOTEzMDkwMVowge0xEzARBgsrBgEEAYI3\n" +
+ "PAIBAxMCVVMxGDAWBgsrBgEEAYI3PAIBAhMHQXJpem9uYTEdMBsGA1UEDxMUUHJp\n" +
+ "dmF0ZSBPcmdhbml6YXRpb24xEjAQBgNVBAUTCVIxNzI0NzQxNjELMAkGA1UEBhMC\n" +
+ "VVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJDAiBgNV\n" +
+ "BAoTG1N0YXJmaWVsZCBUZWNobm9sb2dpZXMsIExMQzEvMC0GA1UEAxMmcmV2b2tl\n" +
+ "ZC5zZmlnMi5jYXRlc3Quc3RhcmZpZWxkdGVjaC5jb20wggEiMA0GCSqGSIb3DQEB\n" +
+ "AQUAA4IBDwAwggEKAoIBAQCWsAZC9goWW6yzg9HiLjCG4Gv2PCHlUIQGqyhc1y9a\n" +
+ "YZVXUI27/NhHjNNMTwP9TKmncrxnGaTZ9+ZCS1JlSgsNYQcLKKZW+SiEOzwpOfwV\n" +
+ "dOCSWrt/EDyJHktx3VIbfi+mD7dvzH3B/iGxMrmdCGIy3xiVAc7MkfsWzcLlPUP3\n" +
+ "oUpPBYyzWqZ2tVsBDigoirERFqZNfHZ7ZNMnn8FcmAt7udKjAAewNRlwzR7ZVp5s\n" +
+ "f5pbnRlRikF30msSHVJoPBICEYmzCxUI+zFlDBjf4vlJojwV0/Rfq85it2yhN/MV\n" +
+ "we2IBC+z9FAAogYo+JFw7Uxq8nsLCKX1tTPsqxGXWNonAgMBAAGjggOHMIIDgzAM\n" +
+ "BgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV\n" +
+ "HQ8BAf8EBAMCBaAwOwYDVR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5zdGFyZmll\n" +
+ "bGR0ZWNoLmNvbS9zZmlnMnMzLTEuY3JsMGIGA1UdIARbMFkwTgYLYIZIAYb9bgEH\n" +
+ "FwMwPzA9BggrBgEFBQcCARYxaHR0cDovL2NlcnRpZmljYXRlcy5zdGFyZmllbGR0\n" +
+ "ZWNoLmNvbS9yZXBvc2l0b3J5LzAHBgVngQwBATCBggYIKwYBBQUHAQEEdjB0MCoG\n" +
+ "CCsGAQUFBzABhh5odHRwOi8vb2NzcC5zdGFyZmllbGR0ZWNoLmNvbS8wRgYIKwYB\n" +
+ "BQUHMAKGOmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuc3RhcmZpZWxkdGVjaC5jb20vcmVw\n" +
+ "b3NpdG9yeS9zZmlnMi5jcnQwHwYDVR0jBBgwFoAUJUWBaFAmOD07LSy+zWrZtj2z\n" +
+ "ZmMwXQYDVR0RBFYwVIImcmV2b2tlZC5zZmlnMi5jYXRlc3Quc3RhcmZpZWxkdGVj\n" +
+ "aC5jb22CKnd3dy5yZXZva2VkLnNmaWcyLmNhdGVzdC5zdGFyZmllbGR0ZWNoLmNv\n" +
+ "bTAdBgNVHQ4EFgQU9hCSl7QoQ8KdsGgwMDwlvSurKNcwggF9BgorBgEEAdZ5AgQC\n" +
+ "BIIBbQSCAWkBZwB1AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFcwO+UmFXWidDdAAAB\n" +
+ "XppC0cEAAAQDAEYwRAIgIO8sIG88JlA73P2myZ7EshemxaR8qBgf3wlYZpg5aZEC\n" +
+ "IGtlcUL7Il1uOLN0LTAzNTQ7pfb7oFYbr0R4LWe2ZvBIAHYA7ku9t3XOYLrhQmkf\n" +
+ "q+GeZqMPfl+wctiDAMR7iXqo/csAAAFemkLVbwAABAMARzBFAiEAmWkzcotxZSwb\n" +
+ "xPS3MG13TVXGu2+MiXXjOIf42DR8zJQCIBL4cSOJh+LX5kpPub6KOiEOn7TVE1Zv\n" +
+ "IQUxuf+vyAD4AHYApLkJkLQYWBSHuxOizGdwCjw1mAT5G9+443fNDsgN3BAAAAFe\n" +
+ "mkLXRQAABAMARzBFAiBX8foh/KrYr34O2c9cH6uyWW2XjBHNLsYX1mr+8VuNaAIh\n" +
+ "AObDQwpDYh/bNp6k547gDxnR73LeU3kvl1Y76GjgxLAhMA0GCSqGSIb3DQEBCwUA\n" +
+ "A4IBAQDJ5vlagzOH8/ORUMgT33muSDFXCe5el/sQzVg8dridw9qjnxOpkGibdCiT\n" +
+ "b9Il1bdi7UnG8MlA3XpDjGgp6J/mUTijD9WcFx4lp5JnPaIbShHWCyIlRVZJzrZc\n" +
+ "UYhR56xXOKDYKYOIvM6qTqegXyEynJrIVTArMk7jQf0oNQLLHzXE1fVS1zut0H5l\n" +
+ "GE+TBgjasMEa1o1e/H/heSytb2zFNsZr8oxojzGBmlKyfCoIIcCv3PxX2ur57zJE\n" +
+ "9ADWoYK/7gYVba0JmLV4nQltDPp06nOYT9imxBWTrFahgPx1jOQDLgIpitkjyCy4\n" +
+ "xpmxUk8L6yc3O3aSD9OU/fzk/t/d\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator) throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED, null, System.out);
+ }
+}
+
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java
new file mode 100644
index 0000000000..f7cdbe0638
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/LetsEncryptCA.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2017, 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 8189131
+ * @summary Interoperability tests with Let's Encrypt CA
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath LetsEncryptCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath LetsEncryptCA CRL
+ */
+
+ /*
+ * "Lets Encrypt Authority X1" intermediate CA is retired.
+ * Test certs should be chained through "Lets Encrypt Authority X3" CA.
+ *
+ * Obtain TLS test artifacts for Let's Encrypt CA from:
+ *
+ * Valid TLS Certificates:
+ * https://valid-isrgrootx1.letsencrypt.org/
+ *
+ * Revoked TLS Certificates:
+ * https://revoked-isrgrootx1.letsencrypt.org/
+ *
+ * Test artifacts don't have CRLs listed.
+ */
+public class LetsEncryptCA {
+
+ // Owner: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
+ // Issuer: CN=ISRG Root X1, O=Internet Security Research Group, C=US
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFjTCCA3WgAwIBAgIRANOxciY0IzLc9AUoUSrsnGowDQYJKoZIhvcNAQELBQAw\n"
+ + "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n"
+ + "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTYxMDA2MTU0MzU1\n"
+ + "WhcNMjExMDA2MTU0MzU1WjBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg\n"
+ + "RW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwggEi\n"
+ + "MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCc0wzwWuUuR7dyXTeDs2hjMOrX\n"
+ + "NSYZJeG9vjXxcJIvt7hLQQWrqZ41CFjssSrEaIcLo+N15Obzp2JxunmBYB/XkZqf\n"
+ + "89B4Z3HIaQ6Vkc/+5pnpYDxIzH7KTXcSJJ1HG1rrueweNwAcnKx7pwXqzkrrvUHl\n"
+ + "Npi5y/1tPJZo3yMqQpAMhnRnyH+lmrhSYRQTP2XpgofL2/oOVvaGifOFP5eGr7Dc\n"
+ + "Gu9rDZUWfcQroGWymQQ2dYBrrErzG5BJeC+ilk8qICUpBMZ0wNAxzY8xOJUWuqgz\n"
+ + "uEPxsR/DMH+ieTETPS02+OP88jNquTkxxa/EjQ0dZBYzqvqEKbbUC8DYfcOTAgMB\n"
+ + "AAGjggFnMIIBYzAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADBU\n"
+ + "BgNVHSAETTBLMAgGBmeBDAECATA/BgsrBgEEAYLfEwEBATAwMC4GCCsGAQUFBwIB\n"
+ + "FiJodHRwOi8vY3BzLnJvb3QteDEubGV0c2VuY3J5cHQub3JnMB0GA1UdDgQWBBSo\n"
+ + "SmpjBH3duubRObemRWXv86jsoTAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3Js\n"
+ + "LnJvb3QteDEubGV0c2VuY3J5cHQub3JnMHIGCCsGAQUFBwEBBGYwZDAwBggrBgEF\n"
+ + "BQcwAYYkaHR0cDovL29jc3Aucm9vdC14MS5sZXRzZW5jcnlwdC5vcmcvMDAGCCsG\n"
+ + "AQUFBzAChiRodHRwOi8vY2VydC5yb290LXgxLmxldHNlbmNyeXB0Lm9yZy8wHwYD\n"
+ + "VR0jBBgwFoAUebRZ5nu25eQBc4AIiMgaWPbpm24wDQYJKoZIhvcNAQELBQADggIB\n"
+ + "ABnPdSA0LTqmRf/Q1eaM2jLonG4bQdEnqOJQ8nCqxOeTRrToEKtwT++36gTSlBGx\n"
+ + "A/5dut82jJQ2jxN8RI8L9QFXrWi4xXnA2EqA10yjHiR6H9cj6MFiOnb5In1eWsRM\n"
+ + "UM2v3e9tNsCAgBukPHAg1lQh07rvFKm/Bz9BCjaxorALINUfZ9DD64j2igLIxle2\n"
+ + "DPxW8dI/F2loHMjXZjqG8RkqZUdoxtID5+90FgsGIfkMpqgRS05f4zPbCEHqCXl1\n"
+ + "eO5HyELTgcVlLXXQDgAWnRzut1hFJeczY1tjQQno6f6s+nMydLN26WuU4s3UYvOu\n"
+ + "OsUxRlJu7TSRHqDC3lSE5XggVkzdaPkuKGQbGpny+01/47hfXXNB7HntWNZ6N2Vw\n"
+ + "p7G6OfY+YQrZwIaQmhrIqJZuigsrbe3W+gdn5ykE9+Ky0VgVUsfxo52mwFYs1JKY\n"
+ + "2PGDuWx8M6DlS6qQkvHaRUo0FMd8TsSlbF0/v965qGFKhSDeQoMpYnwcmQilRh/0\n"
+ + "ayLThlHLN81gSkJjVrPI0Y8xCVPB4twb1PFUd2fPM3sA1tJ83sZ5v8vgFv2yofKR\n"
+ + "PB0t6JzUA81mSqM3kxl5e+IZwhYAyO0OTg3/fs8HqGTNKd9BqoUwSRBzp06JMg5b\n"
+ + "rUCGwbCUDI0mxadJ3Bz4WxR6fyNpBK2yAinWEsikxqEt\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=valid-isrgrootx1.letsencrypt.org
+ // Issuer: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
+ // Serial number: 36916d6db9151ad4428d458a32eae518671
+ // Valid from: Wed Nov 08 07:00:24 PST 2017 until: Tue Feb 06 07:00:24 PST 2018
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFIzCCBAugAwIBAgISA2kW1tuRUa1EKNRYoy6uUYZxMA0GCSqGSIb3DQEBCwUA\n"
+ + "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n"
+ + "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzExMDgxNTAwMjRaFw0x\n"
+ + "ODAyMDYxNTAwMjRaMCsxKTAnBgNVBAMTIHZhbGlkLWlzcmdyb290eDEubGV0c2Vu\n"
+ + "Y3J5cHQub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyugIOCxl\n"
+ + "4p0Rrs4aggnzKGYezhMyyvqlBgVBkf3DJV5uHbz/B/CxcoFo2rZzIetJEsb7Qnt1\n"
+ + "U8L2O5BKnBeOsI5eFv6WUAQs96VayQ09+xCV3jSNjVpbmKKp1TNWboF/V+EDFq6f\n"
+ + "fxK9h+b88RhBn4gfe+BorPnVTmZZQHgcZCjMGyzlXt68r45dXmZOuh0855Y7z6Et\n"
+ + "wCHTT8k/7VC0DTIs0+veKv+yblUqwGD0htdOh7POkQGfBeJ432FsCCcLCDjg2Jj2\n"
+ + "oYQNpLao55ZnVJGXfP8dJpHqJvuEQVuNT1TbHTs4x7IMftqGcPuhXKhA5FCVf0Hb\n"
+ + "osbVmZ/b2b/WswIDAQABo4ICIDCCAhwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQW\n"
+ + "MBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQZ\n"
+ + "Mod3QzNPUL56tDMtELpCiwkQOTAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv\n"
+ + "86jsoTBvBggrBgEFBQcBAQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmlu\n"
+ + "dC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0Lmlu\n"
+ + "dC14My5sZXRzZW5jcnlwdC5vcmcvMCsGA1UdEQQkMCKCIHZhbGlkLWlzcmdyb290\n"
+ + "eDEubGV0c2VuY3J5cHQub3JnMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsr\n"
+ + "BgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlw\n"
+ + "dC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25s\n"
+ + "eSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4g\n"
+ + "YWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQg\n"
+ + "aHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQEL\n"
+ + "BQADggEBAFBiwKeCZfIh8a7x0Y5QEqGwejil/BY6MOVuIU9FRIJKmhJGdh6lI6ln\n"
+ + "zlBbMZBAjZ+TqDxU0pvM1AsRDyCqt8GbCAC2xQsGyATLdCjedLQ7U7ORm7pBZdbe\n"
+ + "cT7h9Sblj53o5MKa1yFeS89WGjI4UueUemGxp7EQjat0NeAvbnpU+YmuevNYKX2M\n"
+ + "kK33reMC+rgD+wKet1CXcB/ZYl3fDzVH3SwkT/bKW5bsuwxBuD2noScnKCitRgiv\n"
+ + "Ew7YjwqNOm2naki/xr2sfJirR+lJtZ9KC3H8xWeEHrD8Cf7pnmMYqV59uR+hJwMP\n"
+ + "YsjjDbDFCmNN9FBqDwvXs7g86ttkdC8=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=revoked-isrgrootx1.letsencrypt.org
+ // Issuer: CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US
+ // Serial number: 3ddd39c0755648d6687a5d8ded37775657e
+ // Valid from: Wed Nov 08 07:00:32 PST 2017 until: Tue Feb 06 07:00:32 PST 2018
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIFJzCCBA+gAwIBAgISA93TnAdVZI1mh6XY3tN3dWV+MA0GCSqGSIb3DQEBCwUA\n"
+ + "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n"
+ + "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xNzExMDgxNTAwMzJaFw0x\n"
+ + "ODAyMDYxNTAwMzJaMC0xKzApBgNVBAMTInJldm9rZWQtaXNyZ3Jvb3R4MS5sZXRz\n"
+ + "ZW5jcnlwdC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5qlZ0\n"
+ + "jslNLn/1uICdZPwflcvsoA2S2Nk+O7cPNew+KQmSIf+LK9AbaWHCkABKx1GdMtfN\n"
+ + "4Q/nKBtzqZ5jX1V1XbPqPd1eeyJo0rNaDFk/gEUHw/zIYi1AtsxVHztMqOXRcsw+\n"
+ + "6QHRKU2XFVsfSctMv+MKnMTEJZARyhr5ur9bQ4/LmxPMhrlHAst97hiSsXKXeyMK\n"
+ + "DWPHmUDn1vz/1mwLMaeYYmuhuRP5HNwYq+LdYvjMV580i6LHY72TwQCfVgOHfqI0\n"
+ + "larISk2p4q6DmTEEiAzJB3yEYaxDn0kEXbKhL9efDC+eirVFa0ta2OnH87s9L8z9\n"
+ + "fm9JIiSFM9ATQ16/AgMBAAGjggIiMIICHjAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0l\n"
+ + "BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYE\n"
+ + "FP64lxiV8KwkkzoNaM7iuwX8UBG/MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZF\n"
+ + "Ze/zqOyhMG8GCCsGAQUFBwEBBGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3Au\n"
+ + "aW50LXgzLmxldHNlbmNyeXB0Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQu\n"
+ + "aW50LXgzLmxldHNlbmNyeXB0Lm9yZy8wLQYDVR0RBCYwJIIicmV2b2tlZC1pc3Jn\n"
+ + "cm9vdHgxLmxldHNlbmNyeXB0Lm9yZzCB/gYDVR0gBIH2MIHzMAgGBmeBDAECATCB\n"
+ + "5gYLKwYBBAGC3xMBAQEwgdYwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2Vu\n"
+ + "Y3J5cHQub3JnMIGrBggrBgEFBQcCAjCBngyBm1RoaXMgQ2VydGlmaWNhdGUgbWF5\n"
+ + "IG9ubHkgYmUgcmVsaWVkIHVwb24gYnkgUmVseWluZyBQYXJ0aWVzIGFuZCBvbmx5\n"
+ + "IGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgQ2VydGlmaWNhdGUgUG9saWN5IGZvdW5k\n"
+ + "IGF0IGh0dHBzOi8vbGV0c2VuY3J5cHQub3JnL3JlcG9zaXRvcnkvMA0GCSqGSIb3\n"
+ + "DQEBCwUAA4IBAQCBiokogdgIZxwuPSr43S4GZ9FwrpZNMHADMEZB8ykuotJBGyr1\n"
+ + "QLWDVeoAJ8OIi1AzjcdwKFQks/MKUJwxJ9hYmm9aM14d5lMKGTyoLSI/Z/Vrpx8w\n"
+ + "0GpktSK0WfPeLBHuSpMdrIMWyziSu/bdZtiOIIvMasFwyRhDgII++CIdsnboWXF+\n"
+ + "DZcwy0Yd6XzirXuwENwaWrkrbZPr/JB0xLFmydqXAnA1VFTudwL87q4CTlEo8EiD\n"
+ + "ucKZ/vAhD+ip3/kQFXg90om+9TdHo8D8GxTC1CLZteJt+nqWFRj0e/7eCXIZuUBE\n"
+ + "aSsFCd5RNTHs6tioN9vYJqLojObgF75MgIAC\n"
+ + "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+
+ // Validate int, EE certs don't have CRLs
+ pathValidator.validate(new String[]{INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ return;
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Wed Nov 08 08:00:35 PST 2017", System.out);
+
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java
new file mode 100644
index 0000000000..94a317b2a4
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/QuoVadisCA.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2017, 2018, 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 8189131 8207059
+ * @summary Interoperability tests with QuoVadis Root CA1, CA2, and CA3 CAs
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath QuoVadisCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath QuoVadisCA CRL
+ */
+
+/*
+ * Obtain TLS test artifacts for QuoVadis CAs from:
+ *
+ * https://www.quovadisglobal.com/QVRepository/TestCertificates.aspx
+ *
+ */
+public class QuoVadisCA {
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ new RootCA1G3().runTest(pathValidator);
+ new RootCA2G3().runTest(pathValidator);
+ new RootCA3G3().runTest(pathValidator);
+ }
+}
+
+class RootCA1G3 {
+
+ // Owner: CN=QuoVadis QVRCA1G3 SSL ICA, O=QuoVadis Limited, C=BM
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGszCCBJugAwIBAgIUdJ4w/GwP08WekbUIXvYTsQrO+a8wDQYJKoZIhvcNAQEL\n" +
+ "BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc\n" +
+ "BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xNzA0MTkxNTAzMzZaFw0y\n" +
+ "NzA0MTkxNTAzMzZaMEwxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBM\n" +
+ "aW1pdGVkMSIwIAYDVQQDDBlRdW9WYWRpcyBRVlJDQTFHMyBTU0wgSUNBMIICIjAN\n" +
+ "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqVn6XxE+YKKifggi6EPcx7mOOrhA\n" +
+ "HVxHFsFV/OR/dtQlx2oOTAGPpa8o3ZPVubtNH5QiiMBBiPDW1KqBaU+rmgUeGCj0\n" +
+ "hWKbdNGRQ5h3rV+4Vhs45BYxQcUzGTZ+oobao8gNo1LuhPIhOQComGOjZtUP0+qQ\n" +
+ "nXsWJn5004TvCzu7mmt3aTlMeyjSbpoXa3ojwU2BvUzJwcLg0BD49kNXZsM0JLbY\n" +
+ "QgfEfluWFkb5QzjnE45sBni4LJNfSodhNB+mL/VmETO+0m/A1H6in1rG1n4Ao2G6\n" +
+ "KYgtk9rXWfF3g7JqwuZUULfI0467h14oG1PzqVcLgZ1B+wrdyiBJJSpRmhf00xSB\n" +
+ "WM/p93s2xkyQZ2Uh0b0tP90S6spwwpL8PSW3J8x46LaZDEVON/Gm9H891ZgwHLaf\n" +
+ "3idGX93XHFafve8CrJFMhK2AZElwYaz2H6iJuPftyhR3oQIgLst8l+/2LoqDRyaI\n" +
+ "6c+tVnk8LcvUgDEPuA70aNthQQ6PWA7iuI2Oies6GEPm7gKVNxIrg6rp2T9RghLm\n" +
+ "vLnf6Gyn1ONLI7Ib3EyzjE8CJIAtor5KZcs8xm8iPNsDQza+1ugx8D8Zsla64vVw\n" +
+ "w2W2qNH4orutsAQKRImtbDkEnMb3nGDe0ZPohVyw3Fy+b9g6MX7wQzFjIx3UkzZG\n" +
+ "QQqGdIh940Qq3wUCAwEAAaOCAY8wggGLMBIGA1UdEwEB/wQIMAYBAf8CAQAwSQYD\n" +
+ "VR0gBEIwQDA+BgRVHSAAMDYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cucXVvdmFk\n" +
+ "aXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwdAYIKwYBBQUHAQEEaDBmMCoGCCsGAQUF\n" +
+ "BzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wOAYIKwYBBQUHMAKG\n" +
+ "LGh0dHA6Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2ExZzMuY3J0MA4G\n" +
+ "A1UdDwEB/wQEAwIBBjAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsG\n" +
+ "AQUFBwMJMB8GA1UdIwQYMBaAFKOX1vNeohDhq0WfPBdkPO4BcJzMMDsGA1UdHwQ0\n" +
+ "MDIwMKAuoCyGKmh0dHA6Ly9jcmwucXVvdmFkaXNnbG9iYWwuY29tL3F2cmNhMWcz\n" +
+ "LmNybDAdBgNVHQ4EFgQUIAYNQkuk2dMocCdjvExpRiGBHTwwDQYJKoZIhvcNAQEL\n" +
+ "BQADggIBAEu/Bea66BZPfGNE4Np+PCRrTag/U7EBK/Yhjmf3mHtFMZzZ94QLH1km\n" +
+ "4iJ5dPKTR/+1iYYNHfO7fY2Lj/Tg/E+q2SEfA0n6Y/lYHAlbmnaYGGdtfTOjaQgL\n" +
+ "0Bf0TmLPyc/gf9uKHe230vIaN4QcodBnCmCJOAk/lvIl7b7gRNPN/HuJNQlBohNx\n" +
+ "ih9VAtLXJ6xO6Xfs5o8ZkZkHb2nG/M1yxySEyU3mqQ5PTgy8kg59szWr2ufT8PvL\n" +
+ "JuyGNQmT/PHcLp2zaCC0+5Ra65umjhG8IW2haXu8g8aRAgr9ZRPrcgg2npLBA0Qf\n" +
+ "MTEJPPptGx2GQgE+lMdn5Gff82d3Y35pDmxNTA7hy+4CnWKfmoey7ll8kwGxC+W1\n" +
+ "OUVgzfdXcpsm+HP2z4E/zw6uB0cAFgMJbxgnm6ZW9+R2yEbD6EOpqR8HqCvhVkkv\n" +
+ "CdQBNkk432pKD3+L7o6vkwONFOFWVpbXHIxDf9ys8Jr4B8qYWDUnR6jz/HG9aWPV\n" +
+ "k4vBYYWuahANZCfCKH2B9SqCdK6DjwKihYmallClwsUQnSwW8H7xqmLtAHX0ek7z\n" +
+ "1Ipj/BNS6c52cPxeAoFbUcVt6+M8xURIJ5qrobTYVaJ8AtfW+3Ml2oqT/EiItXOk\n" +
+ "W1319hZuAGD5qaG3dg9aLYUqpD948xJVhYVxwIIwvL4G9ZEVyYmE\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca1g3-ssl-v.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGJzCCBA+gAwIBAgIUGCzNOZhcLiPYbOjRFAp5n04dPNowDQYJKoZIhvcNAQEL\n" +
+ "BQAwTDELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxIjAg\n" +
+ "BgNVBAMMGVF1b1ZhZGlzIFFWUkNBMUczIFNTTCBJQ0EwHhcNMTcwNTAyMTcwMDA4\n" +
+ "WhcNMjAwNTAyMTcxMDAwWjB9MQswCQYDVQQGEwJCTTERMA8GA1UECAwIUGVtYnJv\n" +
+ "a2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVk\n" +
+ "MS0wKwYDVQQDDCRxdnNzbHJjYTFnMy1zc2wtdi5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCLgSX0nduUm87/qmfTdofL\n" +
+ "5P/Xtrly8Z9GaiLPLu1syNqT/Sri4ngYQGXXwF8h6gnHgEb6gDI2p3Q3gb75NthO\n" +
+ "WfWMD6FqafV47pUeNml6JvNbsYAPc8qGxMPtgQ8HhQuU+Trykx3onq/Se5HRYlve\n" +
+ "7MMJixiYQKYwwThHh9G1uGYPMQJT2TQfueIAu0MT6Ljc2YB6noXpzTzU63dvmC1Q\n" +
+ "8TMmFoJYL276lQ3p3vRKEW1nVmjeVoqvK/3Vpg440KbQL5D7Gj/pQPL4d7ljyS/I\n" +
+ "UN3q7QPS7BojsvF90u0YpvYEuBXsxdFnqivj5owSuSENG4nqcZUO8/nY+4b+NbJd\n" +
+ "AgMBAAGjggHOMIIByjB6BggrBgEFBQcBAQRuMGwwPgYIKwYBBQUHMAKGMmh0dHA6\n" +
+ "Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2ExZzNzc2xpY2EuY3J0MCoG\n" +
+ "CCsGAQUFBzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wHQYDVR0O\n" +
+ "BBYEFIDk6mMLdh49CFbFiUDnjZhWatYzMB8GA1UdIwQYMBaAFCAGDUJLpNnTKHAn\n" +
+ "Y7xMaUYhgR08MGkGA1UdIARiMGAwRgYMKwYBBAG+WAABZAEBMDYwNAYIKwYBBQUH\n" +
+ "AgEWKGh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwCAYG\n" +
+ "Z4EMAQICMAwGCisGAQQBvlgBhFgwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny\n" +
+ "bC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2ExZzNzc2xpY2EuY3JsMA4GA1UdDwEB\n" +
+ "/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwLwYDVR0RBCgw\n" +
+ "JoIkcXZzc2xyY2ExZzMtc3NsLXYucXVvdmFkaXNnbG9iYWwuY29tMA0GCSqGSIb3\n" +
+ "DQEBCwUAA4ICAQB2XiV2msE7M8Qp0YIcihD86T8U91PJH7Pb3F/3+8fyX08/oKDo\n" +
+ "s80sE50tiI5lw+tSFQZuvpOFefejEh1uAwu1slZOlvICHOAJNG1EXPa8pEmDU2i5\n" +
+ "nd5r7rM757/+cgsPLvwegVuIL4vIYhnoKzPiXpkl8FkNrhRjqeUIAXf2sLjbbbng\n" +
+ "oYRCypkSovpijPf7Cid19wKh/ipp8DxCNnGMit55mnx7eFNAWpb9cFljd+WaABCA\n" +
+ "IcvcZhZrLKYrbUErdQzzu0sa3IlEC5QBgz+IvT62RHT+vWRiv0LYhkHVLsDQUHpJ\n" +
+ "uTa1xi0qvBVGIP1jxIQv5W3hGPLYt7B/8A8v+xOn4m1VWfGIa4V3RGpbBMw19DH+\n" +
+ "JvLjg8coDWKhqZ150V31Ve8wczSjT+KZHFRWTb4TZt8GSXa56kJV5xadPW8A3EKV\n" +
+ "kulcspO1njb73ImrwTPIOLnDAsMDrAO41FEob87bdZacpg+kHjiAP9BzpgSSX1x5\n" +
+ "b/qy2uRtsf3ZlOb1J6fCqb8lRwSU7uGUStUx4tVMpjR5LQfNVroiDEthN5BE6sye\n" +
+ "zVRq8vyGvG40jSMBZF1KyW4GW6JlgM1THr1egNFhNkHBs7pSTHJp1Ea+QJjB1uVe\n" +
+ "A8kBL0iUlI5PPOqe5KdEXcFy3L+gRh34gyckC4vrLzfNLjKHQvdRHYnQBA==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca1g3-ssl-r.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGJzCCBA+gAwIBAgIUGeTgdhQ6UoMWie3kBh4IGxDH4AQwDQYJKoZIhvcNAQEL\n" +
+ "BQAwTDELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxIjAg\n" +
+ "BgNVBAMMGVF1b1ZhZGlzIFFWUkNBMUczIFNTTCBJQ0EwHhcNMTcwNTAyMTY1OTQ4\n" +
+ "WhcNMjAwNTAyMTcwOTAwWjB9MQswCQYDVQQGEwJCTTERMA8GA1UECAwIUGVtYnJv\n" +
+ "a2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVk\n" +
+ "MS0wKwYDVQQDDCRxdnNzbHJjYTFnMy1zc2wtci5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDR/0pcsSc4mmqVkzCO5h1m\n" +
+ "BlZ0uxmakNTNnWqeOXmMgl2KBni6MzIdxBkPmII5TI3nc+DXrWrtBCJKRtww3mbF\n" +
+ "ZoBhrscODv3OjfVqsVfhUPjqLwUEE9X/8IlxFpcsKRH1mC7weLg56kfnHuK2WHPQ\n" +
+ "dbnVgzzjk8mSi8HL3szIiojGC0ZwilrV/LCXBqETC3aMe8PtGnMW96TcvqQEdYFa\n" +
+ "4MEXuYnUwXB0WoKAJkHw/MMc0RytrICtlpaMQ7ZnloW8LvoQ1wIM7nWwCr+dieh6\n" +
+ "lZCWRN/Au+h6qdyDUDUPQFoGpp7AfE2OJmeCY30gp4GdAKtGpTG++gfJrtkc8FnZ\n" +
+ "AgMBAAGjggHOMIIByjB6BggrBgEFBQcBAQRuMGwwPgYIKwYBBQUHMAKGMmh0dHA6\n" +
+ "Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2ExZzNzc2xpY2EuY3J0MCoG\n" +
+ "CCsGAQUFBzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wHQYDVR0O\n" +
+ "BBYEFGffDkPGAcip01jKnnvEt1jpKNRnMB8GA1UdIwQYMBaAFCAGDUJLpNnTKHAn\n" +
+ "Y7xMaUYhgR08MGkGA1UdIARiMGAwRgYMKwYBBAG+WAABZAEBMDYwNAYIKwYBBQUH\n" +
+ "AgEWKGh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwCAYG\n" +
+ "Z4EMAQICMAwGCisGAQQBvlgBhFgwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny\n" +
+ "bC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2ExZzNzc2xpY2EuY3JsMA4GA1UdDwEB\n" +
+ "/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwLwYDVR0RBCgw\n" +
+ "JoIkcXZzc2xyY2ExZzMtc3NsLXIucXVvdmFkaXNnbG9iYWwuY29tMA0GCSqGSIb3\n" +
+ "DQEBCwUAA4ICAQBI/zlzisJLwBNaVZkQDMh1gYY8uRUad6Jn7yBFQbJ796VVlD1A\n" +
+ "yxJD+y9cpwzXvwKau8jIMi96OXo6xtsTDxKY9PzW8DkrlrxqdzLI7s5M30tGu8Sk\n" +
+ "WitIWPC3FU0oZqa9jBPkfujllR5FNuYikMOFIi2+/3haEK/6kviLpe5WyK4yJ3a9\n" +
+ "7dLq0If4vhNbKsuW1ROnq5CpPy+iIuZy3CWtq8WJSHDyZzhzrW48QHmTkoAU5lAb\n" +
+ "3KLMBo/gtUTjABVauADeVZVN6GgLflSIdz1P/aMJQ88q/88w+6KYJlBtg3mWSRHc\n" +
+ "Vh+BkIiKmfTG+N9SJ5jv7VKt8PjcKgqCzOHUslLHgUDFhJ5gdYIixD24ikRHYriH\n" +
+ "UCO3ltEppIUm/xgins75F6V9YBxHA1Ks/S5MfMnI6N+fFurIwIsas5w6gTPNwbBC\n" +
+ "z6G1fu6schk73uvfK4W6PiuMTURsQ1M746K2BlV+FIclTk8jYHe+EyLFgIsgVigo\n" +
+ "JJs0DsIp0RoGvw+bxxyA9CHeFFi+MlAVEj2+qJnwrD3ZqNFFw87/HDIWW+Ue8ERs\n" +
+ "HfPDZvEQZ1BHGzD/H04F0+HwwfItxvgiQVC2L/yjmh7St311OLiK8RM3Ur0X15bZ\n" +
+ "3g4c1gsHx9Gmlk3l8YIOk0yxvLaF03YsNbrfykXHuJM9Phy8Ya3nTpsqtw==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator)
+ throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Tue May 02 10:15:37 PDT 2017", System.out);
+ }
+}
+
+class RootCA2G3 {
+
+ // Owner: CN=QuoVadis EV SSL ICA G3, O=QuoVadis Limited, C=BM
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGuDCCBKCgAwIBAgIUUk/B8W400XArhKE/sEK7zHw8kDIwDQYJKoZIhvcNAQEL\n" +
+ "BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc\n" +
+ "BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xNjExMzAxNjIxMDFaFw0y\n" +
+ "NjExMzAxNjIxMDFaMEkxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBM\n" +
+ "aW1pdGVkMR8wHQYDVQQDDBZRdW9WYWRpcyBFViBTU0wgSUNBIEczMIICIjANBgkq\n" +
+ "hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAonyczmwRSnw5BhWIrfcD19EbE7bYu5dF\n" +
+ "tD8o/5NtQCW+XdoLX+X9uNTuvnPw9Hv2RdhYrJgeLgF2wZ52XMGknRdB8tQYrknA\n" +
+ "l/j0N5f8DD82xP2eBkCpIB0UED4zNVwwWcdWvBUgNEdNobz9vQKb7B5LlbXm9kaO\n" +
+ "uxYgcv8WsNMivSP3mkJShEOh4RZ3ZdBM/vtJyuvUyEPjyiSzfN94tZHx/H194S4D\n" +
+ "VAPgE7ny3ISzN+Aa3kjyLebP/sPzI1AY0DWx8Yg4STG1j0PJeuTb6Ago2kmx4Kqn\n" +
+ "4q4kSPL8CgITYHiKaJx6Dt8Q90ieJ7ywG4Mb/YADOIlmoXZ6kXhzGAxyWXFgolLb\n" +
+ "4UToIh6U66v3Iyq+gXyCeMXGT4nUgs3+PduzOei9668jeKQaoU5d7LjJUL+ZH2+Y\n" +
+ "1bPmMAypHFLZryziOzC5kRo4TamgAf3LHHr2C7yIUuo+avlv3cic3NUodcfMi7Ax\n" +
+ "OQFLb32CtDoDeVb5v3x88R0tIEJTizk6M1B/0pGtZiFfXtrNVfHmEYvY2rOLbgWK\n" +
+ "M831ykqZSYHUpiqgnaNJb4Qs8WcxqUw1xki64WwiPclUSn5XgGMIwxSDGjUIJHKR\n" +
+ "rzgQ9lneHOHVb8pXHNFkdBDHTb1KNmDOyLsg3q0LJP6P3nzT/aWDAj3glpJvGQ5d\n" +
+ "kjAbjx+NFk8CAwEAAaOCAZcwggGTMBIGA1UdEwEB/wQIMAYBAf8CAQAwUQYDVR0g\n" +
+ "BEowSDBGBgwrBgEEAb5YAAJkAQIwNjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5x\n" +
+ "dW92YWRpc2dsb2JhbC5jb20vcmVwb3NpdG9yeTB0BggrBgEFBQcBAQRoMGYwKgYI\n" +
+ "KwYBBQUHMAGGHmh0dHA6Ly9vY3NwLnF1b3ZhZGlzZ2xvYmFsLmNvbTA4BggrBgEF\n" +
+ "BQcwAoYsaHR0cDovL3RydXN0LnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdnJjYTJnMy5j\n" +
+ "cnQwDgYDVR0PAQH/BAQDAgEGMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggrBgEFBQcD\n" +
+ "AgYIKwYBBQUHAwkwHwYDVR0jBBgwFoAU7edvdlq/YOxJW8ald7tyFnGbxD0wOwYD\n" +
+ "VR0fBDQwMjAwoC6gLIYqaHR0cDovL2NybC5xdW92YWRpc2dsb2JhbC5jb20vcXZy\n" +
+ "Y2EyZzMuY3JsMB0GA1UdDgQWBBTlhFTQkEmfOLryyeEqCMVOn6BIPzANBgkqhkiG\n" +
+ "9w0BAQsFAAOCAgEAY/EHWbpNwCgGVQ1B7cIn530n6Rnht8ryN6E4Sis2GG09801s\n" +
+ "eCVMoGUB1uBCWm7uqQqydjTbjLhuub7hTjSJ1J30SOK1CZbk+c1VP9DcjY46hycy\n" +
+ "tUKQ2WbgkaY+l/tZNDKu0djc2hA5apljQCmiIzckbcHr6yRnFK7ZPjSPCAUKm20D\n" +
+ "vORQ7hsIaomsIlqXm5BPssMcxjI48Ezgv/s8ynASI8S5P2vOnBo08sJBM/a0Kbuw\n" +
+ "351SubTzjxG+o1SHe6lAzvIQMuSwxUca8YkiB19w5YZt+Ss2JXNc6F2jZwpr0hto\n" +
+ "IXe+N9/x0CohYRRa+IivRGgdDQc3w2P+pffNQP/qdPuUYyMkYWiuHH/YvwXyuDxv\n" +
+ "yGQfvKmHr1uq/qiqbK1bDSUoEq4Su8yX8YoF9TuxYraIpp9iErO5rarDO6GTNVHh\n" +
+ "1OXAJ/ePhOWzqo3flLTlAdTcs3Mq97kKW8XWCnu/cjJJglf2zVfLAlv95p56B9If\n" +
+ "0pXbN74qDkYEC8TdLOwryhcv8yyimh90/AvW9LpB7swkWnUUYNTep/XMX/RLpHLn\n" +
+ "JOVtnRpn3coVfSR/0rz0XKVXeZGnKztGdIMQhWMTxvZ1UpmRAH2Ab2QnVo1fkPVy\n" +
+ "qNSJces5Y/VKpIvLBk5Jj55fvK8ME/9ASa+LtLrIms8iYHl75cupuYZZlg8=\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca2g3-ev-v.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM, SERIALNUMBER=28474, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=BM
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH4DCCBcigAwIBAgIUUZsNAKy8C5AlCfpCZWUQY2R6VawwDQYJKoZIhvcNAQEL\n" +
+ "BQAwSTELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHzAd\n" +
+ "BgNVBAMMFlF1b1ZhZGlzIEVWIFNTTCBJQ0EgRzMwHhcNMTcwNDE4MTg1NjEyWhcN\n" +
+ "MTkwNDE4MTkwNjAwWjCBwDETMBEGCysGAQQBgjc8AgEDEwJCTTEdMBsGA1UEDwwU\n" +
+ "UHJpdmF0ZSBPcmdhbml6YXRpb24xDjAMBgNVBAUTBTI4NDc0MQswCQYDVQQGEwJC\n" +
+ "TTERMA8GA1UECAwIUGVtYnJva2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQK\n" +
+ "DBBRdW9WYWRpcyBMaW1pdGVkMSwwKgYDVQQDDCNxdnNzbHJjYTJnMy1ldi12LnF1\n" +
+ "b3ZhZGlzZ2xvYmFsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" +
+ "ALo9QJVNVNVfG//nZiOPX/j2O8GTVlSAfIMliEj78G0xmPZiQD3n/70KcYlsI7No\n" +
+ "ilytC8e/m4Mic9PpYfmhAwiUSmb3ba8qjekUgmBFXuQqj3fH6Na+8f5WC9cYpwlc\n" +
+ "Ew3NuL2WBs86mjM/3GIa61IXrGpRxN6UQJwSxhqlb1QqEGtuwBiy9FJQd0xekCTC\n" +
+ "GBe2zFT1WhyVSMWlxwkcy1p2LeUmlvnV6FHQYcM9te8UPhgY53O6+u0tnnnsED37\n" +
+ "UOU3MLev8T++WL7VPOrjgjXydMC9ndXKRttQFIeJ1r+W7rdMLCWkrTzvJ6GtBZZr\n" +
+ "8jjHNabWPkBslML7oGwvUHMCAwEAAaOCA0YwggNCMHgGCCsGAQUFBwEBBGwwajA5\n" +
+ "BggrBgEFBQcwAoYtaHR0cDovL3RydXN0LnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdmV2\n" +
+ "c3NsZzMuY3J0MC0GCCsGAQUFBzABhiFodHRwOi8vZXYub2NzcC5xdW92YWRpc2ds\n" +
+ "b2JhbC5jb20wHQYDVR0OBBYEFLVK7rSs4x+DZrwYaWl2mjhhAtV/MAwGA1UdEwEB\n" +
+ "/wQCMAAwHwYDVR0jBBgwFoAU5YRU0JBJnzi68snhKgjFTp+gSD8wWgYDVR0gBFMw\n" +
+ "UTBGBgwrBgEEAb5YAAJkAQIwNjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5xdW92\n" +
+ "YWRpc2dsb2JhbC5jb20vcmVwb3NpdG9yeTAHBgVngQwBATA8BgNVHR8ENTAzMDGg\n" +
+ "L6AthitodHRwOi8vY3JsLnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdmV2c3NsZzMuY3Js\n" +
+ "MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw\n" +
+ "LgYDVR0RBCcwJYIjcXZzc2xyY2EyZzMtZXYtdi5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggF9BgorBgEEAdZ5AgQCBIIBbQSCAWkBZwB2ALvZ37wfinG1k5Qjl6qSe0c4V5UK\n" +
+ "q1LoGpCWZDaOHtGFAAABW4J1OtsAAAQDAEcwRQIhANABKS1i5uxEm/HMivDJFyNJ\n" +
+ "gOKRrApqmx3KV0/pWMzqAiAui21HV9lVJ1OT6dEA9mlZAH4NmzklmY9WI978GMYG\n" +
+ "mgB2AFYUBpov18Ls0/XhvUSyPsdGdrm8mRFcwO+UmFXWidDdAAABW4J1Os0AAAQD\n" +
+ "AEcwRQIgTWLHrhex17UyIlr0HC9LXNUv0kyOudo7MpxoWFy1xGICIQCHFSoQGwvv\n" +
+ "zzpQ3JmHSLHy0AQQfWlbV9rFv37F4A7AaAB1AKS5CZC0GFgUh7sTosxncAo8NZgE\n" +
+ "+RvfuON3zQ7IDdwQAAABW4J1OvYAAAQDAEYwRAIgWLm8u/bcMZt5oXAPIqP9/Qqj\n" +
+ "Q61VYX+II6RFK+EJCnwCIBrXxQgngqO7X/aaeWnEjfQeSu7WCK9Md3tcqXsn+gMd\n" +
+ "MA0GCSqGSIb3DQEBCwUAA4ICAQAu0Y29voXdwt/68hwbdj8L50yecl2Z0OkOA31v\n" +
+ "UhAHgRVhQ+WiAgoeGEgjdntQ5pL7Wtr314gHpG6iR849Zr56WOliA6pfBYDk3qkH\n" +
+ "UiRgqQBUEV8oRzgp0E+Ebev+p9leM4RPYmUNsP3K4Z/BY24HNOtNKMC3clqKO35K\n" +
+ "D7B9ObYUb0+IjreKgUyQB7wMgFi7393gXDraVDhDoLrcktAkvkv3Mbt+A3IO5VrO\n" +
+ "4mQwjrLHzj8nFCmsP4RbCIKFO2QZE8sJYwplKUWOk1ngjpOvObPYpMt5M1kiRvau\n" +
+ "agkQ+WvnvuMEgAgafHtI4uu0ZNDW1ib0H+xq5X/x2w1RjEElbXCKMbnf3Pdvh9FG\n" +
+ "mLpkVITXIKzT0Jm+oIs+Vk4ktNEe8hQIzcqimmtlVl2hgMWkmIfRio1+41EY4Din\n" +
+ "QXBVsbRqftamzSpLbW54ryGJB8dSiGe4P53DOcNKiyie7une95ouZY/1DfQIlVG/\n" +
+ "9XexhqdGMKp6qUjgd9hOfHrD+mZHeBdIIONOHOhy6ESIUgpSzaAAM7QXZFqlzLzY\n" +
+ "okRp6cJKDfUmXrk80MopQMhRHJwdxfeZ/A/xAkrWlVPshG+qltSGIZWrNjhQIwk3\n" +
+ "49zFQCuDS+FrkubRueV+MB8Abp+V1nv5PNbhwfPzGSqwn9XX3vUnsp9uLv+3WlrL\n" +
+ "Kl1DeA==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca2g3-ev-r.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM, SERIALNUMBER=28474, OID.2.5.4.15=Private Organization,
+ // OID.1.3.6.1.4.1.311.60.2.1.3=BM
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIH4TCCBcmgAwIBAgIUZTuy16qm4LnioIRmiaQZuThb38gwDQYJKoZIhvcNAQEL\n" +
+ "BQAwSTELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxHzAd\n" +
+ "BgNVBAMMFlF1b1ZhZGlzIEVWIFNTTCBJQ0EgRzMwHhcNMTcwNDE4MTg1NjQ0WhcN\n" +
+ "MTkwNDE4MTkwNjAwWjCBwDETMBEGCysGAQQBgjc8AgEDEwJCTTEdMBsGA1UEDwwU\n" +
+ "UHJpdmF0ZSBPcmdhbml6YXRpb24xDjAMBgNVBAUTBTI4NDc0MQswCQYDVQQGEwJC\n" +
+ "TTERMA8GA1UECAwIUGVtYnJva2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQK\n" +
+ "DBBRdW9WYWRpcyBMaW1pdGVkMSwwKgYDVQQDDCNxdnNzbHJjYTJnMy1ldi1yLnF1\n" +
+ "b3ZhZGlzZ2xvYmFsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" +
+ "ALXMNTuogjC2wpziEXbKztdgzBflORLxoAo5Y8HNAZVo8MgJJucshZ5S6cmRjreY\n" +
+ "fOlwo85Vu9s39EMRR+I0AZLbxw2PZxNSHUxTCzWlmJ4yValRPRZjz2LXJ+mjpkc3\n" +
+ "hsVHtCawvPqh2uNwM2qUD6zKfRGdKC27NeICjYe7RtfhLRdrZ8MNtVWMrrFt3Dzd\n" +
+ "SRJXFcLkN4rPzRFCxldU2yH6V4cZwnVz4XxV/nbljVtGyMJWGVzU0Bhy1fedAJ9x\n" +
+ "KGJbM6wackOlpUm0XMQdFxHF2tW4Sus6Mcf+2N8FgXk4PnwXarIc/Sj5Tx+Bvf5y\n" +
+ "TwBOGS02Hzs07ILV3w4dp00CAwEAAaOCA0cwggNDMHgGCCsGAQUFBwEBBGwwajA5\n" +
+ "BggrBgEFBQcwAoYtaHR0cDovL3RydXN0LnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdmV2\n" +
+ "c3NsZzMuY3J0MC0GCCsGAQUFBzABhiFodHRwOi8vZXYub2NzcC5xdW92YWRpc2ds\n" +
+ "b2JhbC5jb20wHQYDVR0OBBYEFALFAuUwkAiTXc+DIW861Mu1o/7RMAwGA1UdEwEB\n" +
+ "/wQCMAAwHwYDVR0jBBgwFoAU5YRU0JBJnzi68snhKgjFTp+gSD8wWgYDVR0gBFMw\n" +
+ "UTBGBgwrBgEEAb5YAAJkAQIwNjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5xdW92\n" +
+ "YWRpc2dsb2JhbC5jb20vcmVwb3NpdG9yeTAHBgVngQwBATA8BgNVHR8ENTAzMDGg\n" +
+ "L6AthitodHRwOi8vY3JsLnF1b3ZhZGlzZ2xvYmFsLmNvbS9xdmV2c3NsZzMuY3Js\n" +
+ "MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw\n" +
+ "LgYDVR0RBCcwJYIjcXZzc2xyY2EyZzMtZXYtci5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2AFYUBpov18Ls0/XhvUSyPsdGdrm8\n" +
+ "mRFcwO+UmFXWidDdAAABW4J1uUEAAAQDAEcwRQIhAK2LD7cJrN7YYjyBqFDoZva+\n" +
+ "fae1CiuYyxpREVes1c8OAiBLVt/dGKnvwY2CW2TN3/WyRM7al2sLnM+XwNUGZDrJ\n" +
+ "pgB2ALvZ37wfinG1k5Qjl6qSe0c4V5UKq1LoGpCWZDaOHtGFAAABW4J1uVQAAAQD\n" +
+ "AEcwRQIhAIA9IjxIT69JGX+sl1okMiGsXfCOPq5crSX+m04Q7LcgAiBJWUsLDtm9\n" +
+ "5TKsGZvlJRKOn1CcA94sApQ4v+1D+uz+JQB2AKS5CZC0GFgUh7sTosxncAo8NZgE\n" +
+ "+RvfuON3zQ7IDdwQAAABW4J1uWwAAAQDAEcwRQIhAIWbEqGnZSIwrI5eWCIzfMRY\n" +
+ "A+onO3IjQrVAE6ZuGu2bAiAlyoRSfH4s8+lVL225AYD45OkJJfG41T6k+wVLM5Hg\n" +
+ "ezANBgkqhkiG9w0BAQsFAAOCAgEAPwvRI5GmzR72cDoh+7VPj7PihQDG4HBYq5Ta\n" +
+ "bF7NK2v9DoaU99vv01K3WBNIydjQX4j+IK8MoGp9dXV+LDUTsebnsY+nr3O4R0pK\n" +
+ "I2TAazN7zcy3SYc/MtaW7JI+/ckjHaJw+AT+qUz+l20p9shBFlg4QvH2cx2OOCat\n" +
+ "/CRnG2Nqc5nN1xVcS3aVDrGl36XIcjV+ab+3zicm3OhWqn/hlfBBWimuhix68i/L\n" +
+ "k+qUyN6A8Bz7NwsouzG7keS17VZbLFkOuczq9KxJLHtlI1OYFNzrLEx6aXeM5VoH\n" +
+ "mlwETxagSL6fjRvcCaM6As9WVRS08p/RldUrEw+O6r3ob7FaOywwIzSMFV1GbVFG\n" +
+ "eIrSMuSVwbQRa5Duakoe5vz1vOddrZPm3kqpvyT7j51nuedrjc8YgisuyMbxkf5s\n" +
+ "8tesqxdltXjFNwpwveYlgHAi3sZvO2dm6bEZcioxLEWEpwmYXrkBJWLhcILdfY99\n" +
+ "SWFAmwGtmCqh8Sxla77o+gaZkNKf3zBn/34Q91Z96qKgqjXDAGefsZiy4tQeEUJc\n" +
+ "2qIqjb2rWi5Vo7hn2eolNXzp6ZdanicpecpqwpmW9/v6YRxKLGTsdVz82TGWPnpt\n" +
+ "q3rCll0NIAfcjekFmRzmBWF1jOn4fCcF/WOxKW1T4JcMIcNoa5iI9M1WcVKQvJKA\n" +
+ "Zd5LLu4=\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator)
+ throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Tue Apr 18 12:23:14 PDT 2017", System.out);
+ }
+}
+
+class RootCA3G3 {
+
+ // Owner: CN=QuoVadis QVRCA3G3 SSL ICA, O=QuoVadis Limited, C=BM
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGszCCBJugAwIBAgIURUME8OY/YBHyokbgxoTKpPcoiHYwDQYJKoZIhvcNAQEL\n" +
+ "BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc\n" +
+ "BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xNzA0MTkxNDQ4NDBaFw0y\n" +
+ "NzA0MTkxNDQ4NDBaMEwxCzAJBgNVBAYTAkJNMRkwFwYDVQQKDBBRdW9WYWRpcyBM\n" +
+ "aW1pdGVkMSIwIAYDVQQDDBlRdW9WYWRpcyBRVlJDQTNHMyBTU0wgSUNBMIICIjAN\n" +
+ "BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAt8UIgFvcneWgv29aR2/UV810uW9N\n" +
+ "VpvdEgQDPHao5+i3IwCH1GrV8KeC25vfJAuW2TJ5gHeN5fmWAtWU8NDaNwGxJq/w\n" +
+ "jlOe/UW0KSosuuOBltLY9fl+7lDYqBjEwmCGvZMQOzpsbm8QUYTuZmtw96sT5beZ\n" +
+ "Kwqub/NBDE59IZ+b82obreNFFOgwcHv9E00bfRW7kizNfaC8AiwgV9WfIFgvtb4+\n" +
+ "YflcgGbdWnmNvwL8aZGWpGYjw/H/0kpwfMgrVF3Q7h8Y0yTg/jj8ZdXLdaE/PQzx\n" +
+ "8RUU4xJGxply/RrNUEvm9xeXZG3ssLW56WDEhRLkORX/zF4/mVyO2DpGJs06IUSP\n" +
+ "VWe+JuJGT1UxWqIsDIIHqJNa2BYl6O/XOjE2oGxiCb9w0/kQ8tKWWynFx4XOtrjA\n" +
+ "pGktsjw66tqE08XWOuoKwAXH2Llwz+VGSMzrCDH98VHtAu/XpEjuW3iP+I7EHksm\n" +
+ "W2eLdQdvTJ5DBdLsspIG4HC9Ke+c/gCEJHvOURPXoY7j9JPcQLc+5O7kBqiIjEBU\n" +
+ "NpPX37x7z3msac/IiG/SOYl+kiBESV44QFIOl8sHYmj9HGNlkQz4B/inuGwifIux\n" +
+ "rfdvm6nrpC7jhd/5Ptk4PO1kcAtgwcB99BnRCw47Xl7hrERTpoRISReNG0JMK7Op\n" +
+ "wVFqyi7bV1U/l4MCAwEAAaOCAY8wggGLMBIGA1UdEwEB/wQIMAYBAf8CAQAwSQYD\n" +
+ "VR0gBEIwQDA+BgRVHSAAMDYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cucXVvdmFk\n" +
+ "aXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwdAYIKwYBBQUHAQEEaDBmMCoGCCsGAQUF\n" +
+ "BzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wOAYIKwYBBQUHMAKG\n" +
+ "LGh0dHA6Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2EzZzMuY3J0MA4G\n" +
+ "A1UdDwEB/wQEAwIBBjAnBgNVHSUEIDAeBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsG\n" +
+ "AQUFBwMJMB8GA1UdIwQYMBaAFMYX0Lyo6gJD8hsGmV0rkCC515zkMDsGA1UdHwQ0\n" +
+ "MDIwMKAuoCyGKmh0dHA6Ly9jcmwucXVvdmFkaXNnbG9iYWwuY29tL3F2cmNhM2cz\n" +
+ "LmNybDAdBgNVHQ4EFgQUTknx5HQLmDQSOuWxVX3EknK1r6QwDQYJKoZIhvcNAQEL\n" +
+ "BQADggIBAHfmIJkd+URmnVm0X1/43QXu08RTzUr1zjf4ZBVtzUFoEkfZm+zKlhb7\n" +
+ "QeYJ5lprX1tdRfHLI+JC7oyI5+7/0q1j2FN2g0oKYN63dIgtppoCNpBu58f69YxL\n" +
+ "Y3GPSCfgs+ld+HegNSTjQVzelr16aFo9sj1fzUwY4Xj+xEYDjYxFmNGSXY37+DdN\n" +
+ "3WPm1iahBNNCZGfXq5T4qr6+R6RWwxsaBdQfZh3efGB1WG4DVSQBoiCKjS7Eg+Mf\n" +
+ "LT+KEZgawLUVrt/sT5lNfw23XA1gxIOcNRBHjsTWbtTBHJeb8hYvXB38UGK4GfIo\n" +
+ "NxtvRyXgG/U8+OuCQPS2SpJ1VH+yZ4Tn3G4k2+WillxfpqCVgHDVuT8wigw1xUNb\n" +
+ "0Ft9F3OWftWCVILaYEcyuJrnL3jjcZXc/zG01wIGDFvlPshRifVs/69Xq9UQmMfB\n" +
+ "GUh6MteDIsN9NdiArcumSC1dNoA/9eESp1pb186lDx9KxRQ/3NJRDMOIsMYN8Lyu\n" +
+ "cDNzsnymtQyIm3YG7VmZi/6k99n9vT8Ff9PvQ49cdfPl8GIONMdYmhTtLtuC00AU\n" +
+ "550HVLnpFW8d1NX3+XKxQ5FG04nsTxUD2FtT+trEQouktPq9iFqZN+PLPi8UdrBW\n" +
+ "AGUDCnO/TNo7IPW6arQrFpYbRLStiOJw7204Mjuqco/1KcqnEiIC\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca3g3-ssl-v.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGJzCCBA+gAwIBAgIUatc95M2rfpt/opXnck37WXW2RpAwDQYJKoZIhvcNAQEL\n" +
+ "BQAwTDELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxIjAg\n" +
+ "BgNVBAMMGVF1b1ZhZGlzIFFWUkNBM0czIFNTTCBJQ0EwHhcNMTcwNTAyMTY1OTAy\n" +
+ "WhcNMjAwNTAyMTcwOTAwWjB9MQswCQYDVQQGEwJCTTERMA8GA1UECAwIUGVtYnJv\n" +
+ "a2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVk\n" +
+ "MS0wKwYDVQQDDCRxdnNzbHJjYTNnMy1zc2wtdi5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+S725uLLelMIYHWuh6fbT\n" +
+ "lGdi7wf1BlsfQY/ZnLvsFbT1KHodE407RXP0NB6AeEBOlO8xQxaZ5b38aF+HROJw\n" +
+ "TcvUAgQHmNE+ER0JCMi42jSFC2dc93PhdcUEeesxIfu1iIKXxFmlbJtJxG3l27yJ\n" +
+ "L4ufum9iQYeZeoGXAr54x6JMY29kl5t9QM018d9sA9bHY+0iVJevM3xgxVe7xApw\n" +
+ "MSKoZH/OmkX8FaEW9b7TqrWfWcAdD8fkXK8lHCDqmUzSiDGJP16YeQA/4dmFO2vr\n" +
+ "ItXY8rTPjXoaolebHxf5WG5Qosxv0mPyklUb+SVSJagv66zl/H2Uk0bLyFFmuNAd\n" +
+ "AgMBAAGjggHOMIIByjB6BggrBgEFBQcBAQRuMGwwPgYIKwYBBQUHMAKGMmh0dHA6\n" +
+ "Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2EzZzNzc2xpY2EuY3J0MCoG\n" +
+ "CCsGAQUFBzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wHQYDVR0O\n" +
+ "BBYEFFhZXE0P1SMuntLc7JYoHTcD8JKfMB8GA1UdIwQYMBaAFE5J8eR0C5g0Ejrl\n" +
+ "sVV9xJJyta+kMGkGA1UdIARiMGAwRgYMKwYBBAG+WAADZAEBMDYwNAYIKwYBBQUH\n" +
+ "AgEWKGh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwCAYG\n" +
+ "Z4EMAQICMAwGCisGAQQBvlgBhFgwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny\n" +
+ "bC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2EzZzNzc2xpY2EuY3JsMA4GA1UdDwEB\n" +
+ "/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwLwYDVR0RBCgw\n" +
+ "JoIkcXZzc2xyY2EzZzMtc3NsLXYucXVvdmFkaXNnbG9iYWwuY29tMA0GCSqGSIb3\n" +
+ "DQEBCwUAA4ICAQB6QV56jPZzFbFNnKq4xRglTkZSLDMnyrmquWJr4xUWkWIqhQqC\n" +
+ "s+wAchy39Uuu+Nv99N1AxJhorpdbyIOd7B2NAnUXPeOa1Rm34mh2a/df0gTVrrWJ\n" +
+ "YSUd3Tv7tcGrMXa7kNaP0N3lTITC0F0fu0rLyCH5I28t4zkCXadcWTqHUKIDNS1h\n" +
+ "fwx1Y6Dq4fBhKQGpqBq4ThEpBgJdj5aGCNiYfKO/MTDrLxD1BpIjV88O+54cdtYp\n" +
+ "3K+UDN2lP03PNH4Z/0jF4K43DHpwDM0r6qP4yLqFf3K1NlzGkYgNlMrKUPSlu+M8\n" +
+ "F6R45TWkcHndk3SUxbtGsxhiLG4xJKY7Zm/0vSxNqia+UJ5wL5s+IoiXhj22RrPe\n" +
+ "kcx7u3MxB+KWSrtQd8y624J6tqbE7R+aaAX95KTQZoawjypX99P8Kir/NynFHYri\n" +
+ "RAX9qFU8nYQEAe47oxl0bIr7URiQrlz+FJ/bzJZQwROWY723JPXgv7wUMifCYvJz\n" +
+ "4pLkuc4KE+LIEqk5LUuoYGEhKhKVu8YnmDifPPrBBADNvAnnGfDZF9FRvIcD6h8H\n" +
+ "icZBXJHOgu70Rh8Zc77x+v29tKlAJVtswLlV0mVClDUk7U36XL+mAvYntnG9kH5x\n" +
+ "qQ2Fl7AkUewOd4tLeiN4fl+S+ceW9sOZPSWx5aLui9p2mmxuyxhC5egCzg==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=qvsslrca3g3-ssl-r.quovadisglobal.com, O=QuoVadis Limited, L=Hamilton,
+ // ST=Pembroke, C=BM
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGJzCCBA+gAwIBAgIUTgJvLquqZ+Padg/W5Y0bTu9jimswDQYJKoZIhvcNAQEL\n" +
+ "BQAwTDELMAkGA1UEBhMCQk0xGTAXBgNVBAoMEFF1b1ZhZGlzIExpbWl0ZWQxIjAg\n" +
+ "BgNVBAMMGVF1b1ZhZGlzIFFWUkNBM0czIFNTTCBJQ0EwHhcNMTcwNTAyMTY1ODQy\n" +
+ "WhcNMjAwNTAyMTcwODAwWjB9MQswCQYDVQQGEwJCTTERMA8GA1UECAwIUGVtYnJv\n" +
+ "a2UxETAPBgNVBAcMCEhhbWlsdG9uMRkwFwYDVQQKDBBRdW9WYWRpcyBMaW1pdGVk\n" +
+ "MS0wKwYDVQQDDCRxdnNzbHJjYTNnMy1zc2wtci5xdW92YWRpc2dsb2JhbC5jb20w\n" +
+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCOdbnnY8GsO002xJ6Snu2W\n" +
+ "snpPmW9ZJ4cEKzdBA4fYKP2V/8ibbOZVH5gI4tSSW+mcMrepS9Jw49sZaKOOGf/7\n" +
+ "YsjFOp4DQ0+w/7FOj4WrKWBhymDGKI8SsDqoCkxjCYkAc7cutm5Ge67Yto2mvkzW\n" +
+ "vThV7o9pJ4z2kMg+Q527908zvP1eqT2g+72X1L3o3RSdGM5V35R+lGiBDum8ojZm\n" +
+ "+QGCGuc6zROgumfYrh11iTNhXJw6KVAS9KJ5GSHzmua/Cu1dwC2SPxp/hRRHlvPp\n" +
+ "07EjY2oGhfe6Hvsu9YuoQCm95H4HPTmTDUCKURRIGcC8jdrjXBowEuH15vUocSIJ\n" +
+ "AgMBAAGjggHOMIIByjB6BggrBgEFBQcBAQRuMGwwPgYIKwYBBQUHMAKGMmh0dHA6\n" +
+ "Ly90cnVzdC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2EzZzNzc2xpY2EuY3J0MCoG\n" +
+ "CCsGAQUFBzABhh5odHRwOi8vb2NzcC5xdW92YWRpc2dsb2JhbC5jb20wHQYDVR0O\n" +
+ "BBYEFLzYzgqJRXrnLc5OYHF/koTdbIzeMB8GA1UdIwQYMBaAFE5J8eR0C5g0Ejrl\n" +
+ "sVV9xJJyta+kMGkGA1UdIARiMGAwRgYMKwYBBAG+WAADZAEBMDYwNAYIKwYBBQUH\n" +
+ "AgEWKGh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL3JlcG9zaXRvcnkwCAYG\n" +
+ "Z4EMAQICMAwGCisGAQQBvlgBhFgwQQYDVR0fBDowODA2oDSgMoYwaHR0cDovL2Ny\n" +
+ "bC5xdW92YWRpc2dsb2JhbC5jb20vcXZyY2EzZzNzc2xpY2EuY3JsMA4GA1UdDwEB\n" +
+ "/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwLwYDVR0RBCgw\n" +
+ "JoIkcXZzc2xyY2EzZzMtc3NsLXIucXVvdmFkaXNnbG9iYWwuY29tMA0GCSqGSIb3\n" +
+ "DQEBCwUAA4ICAQAge+6VZgaEFxN38q0MYKs/QbdGowLd5n2CfQfpdOTRnpOtKQw6\n" +
+ "Bc/o1O8O/y0XUl1Be7TCgfXKWgw+rKX+ZrI6wCm7MxYlWXV2guWU/AeEl2uv14s/\n" +
+ "KnKhzZHfb0eQyItfk23flubc7pbh99LaVqozsLCTL78lOB7N7ZQwsNCrEghHWMxl\n" +
+ "w1/IX/h9XOJoBzu4ulebJoQ3hdIYJY7+lkw64uH1FNrCu7P/jjU9ZlPaobZOUy64\n" +
+ "sYIt4GsZbMFaUiamNzBUvULw+ZkZq0hTK0cuyA85MXd+3rm5z2AMemC/29XTUYRU\n" +
+ "L9LkxMF71w8BJzgpVx3s0a6dfi6XtgacP407IhMc3EW1McsSWdT6jL0zidbjXisU\n" +
+ "vfvuzA50b3HwYz8PsRN0Zfi2R1BubaZQ9fQW2fe1EWgq80CqOdO7eNZeaBxbW/qB\n" +
+ "smGA1wiHIVEtyHbwZslcKNy8VPKurfKClwZQxf17/oK6QrhOgxiKJGYBUDTa7Ln7\n" +
+ "Qslp/y3G721NOXzborchs8XB+BYEETtWWkKoWFDiV7vkfyn3x2cYNiv5JCWDszhZ\n" +
+ "RyVrW26YOQ3MqBAiYqgbU2jMdqeRRfMIFqUvvXwoTvYXuN4Yc2ZAOmCBPpUxo66V\n" +
+ "zHDu+QK/2/pI1SMLvU3KG526gUtDd67t8JUHqxyo3NsXUCD8tUYpaJy/vg==\n" +
+ "-----END CERTIFICATE-----";
+
+ public void runTest(ValidatePathWithParams pathValidator)
+ throws Exception {
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Tue May 02 10:15:53 PDT 2017", System.out);
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/TeliaSoneraCA.java b/test/security/infra/java/security/cert/CertPathValidator/certification/TeliaSoneraCA.java
new file mode 100644
index 0000000000..3dc0c94abc
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/TeliaSoneraCA.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2018, 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 8210432
+ * @summary Interoperability tests with TeliaSonera Root CA v1
+ * @build ValidatePathWithParams
+ * @run main/othervm -Djava.security.debug=certpath TeliaSoneraCA OCSP
+ * @run main/othervm -Djava.security.debug=certpath TeliaSoneraCA CRL
+ */
+
+/*
+ * Obtain TLS test artifacts for TeliaSonera Root CA v1 from:
+ *
+ * Valid TLS Certificates:
+ * https://juolukka.cover.sonera.net:10443/
+ *
+ * Revoked TLS Certificates:
+ * https://juolukka.cover.sonera.net:10444/
+ */
+public class TeliaSoneraCA {
+
+ // Owner: CN=TeliaSonera Server CA v2, O=TeliaSonera, C=FI
+ // Issuer: CN=TeliaSonera Root CA v1, O=TeliaSonera
+ private static final String INT = "-----BEGIN CERTIFICATE-----\n"
+ + "MIIHHjCCBQagAwIBAgIQTEYq9tv794BPhMF8/qlytjANBgkqhkiG9w0BAQsFADA3\n"
+ + "MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9v\n"
+ + "dCBDQSB2MTAeFw0xNDEwMTYwODA5NTdaFw0zMjEwMTYwNTA0MDBaMEYxCzAJBgNV\n"
+ + "BAYTAkZJMRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEhMB8GA1UEAwwYVGVsaWFTb25l\n"
+ + "cmEgU2VydmVyIENBIHYyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA\n"
+ + "rwQN5rfRLbVAiYWLJF9SI4YLm8oqrtf8OjGybgoLyiMIo8nhY/atuGRFWCQNOnUK\n"
+ + "caZn29C360PlC5yYrsrSHuouROisqHSJcgA7HvV+37Rcry7daeDj6rfyx4yI5dmj\n"
+ + "LwHkK0j1NzhX1JxFDgPeLNuebgzv/j8OfRhYK/BttpystC4Zgm3gZheKDjYsDS5D\n"
+ + "gjffuOysP3vewrcuw0EIZFx+HawuwNBLq4tMf4VSitYDHJSLIM2TeXZGGY5slTbT\n"
+ + "yLnrU5mIzG9WKqxyy7qHuFw1JtlAXkCLmUEVaF9M+dRPiGIjlDrpBgbDD9mT2CSk\n"
+ + "V/XG1696/voY5xB8KNIC1cOSmSO7kdJyR5tWiDIJiwMXrTwG+kZiqlbcKDsZeJ9p\n"
+ + "5bZxXO0pEpde3wgEYRvFr5Cx4vcz4h5pom9coJOCW9tqXU43KcueTrt4Ks9f92q1\n"
+ + "ehjyEnCh0BCdrjUOXsUtFosm9qxJnDwVlThYhS9EHuCTNBgj1Yxj6A+8fwwJP9DN\n"
+ + "CbWQx5afT+h+9FNDNRC/nEcesP1Yh9s15Se270pQW0CejUNziYG7Dft7T+PVH/fU\n"
+ + "zaWU8g0tJjtuQgiCWVqw4WkUmYY2S0R89zAotcpz2mvNO8ma2iJbubHi3c0ULfHH\n"
+ + "nkWKsdpzZmK4N0Wi6/V5yWdmL5RFkFecL8r7+9OtCB0CAwEAAaOCAhUwggIRMIGK\n"
+ + "BggrBgEFBQcBAQR+MHwwLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnRydXN0LnRl\n"
+ + "bGlhc29uZXJhLmNvbTBLBggrBgEFBQcwAoY/aHR0cDovL3JlcG9zaXRvcnkudHJ1\n"
+ + "c3QudGVsaWFzb25lcmEuY29tL3RlbGlhc29uZXJhcm9vdGNhdjEuY2VyMBIGA1Ud\n"
+ + "EwEB/wQIMAYBAf8CAQAwVQYDVR0gBE4wTDBKBgwrBgEEAYIPAgMBAQIwOjA4Bggr\n"
+ + "BgEFBQcCARYsaHR0cHM6Ly9yZXBvc2l0b3J5LnRydXN0LnRlbGlhc29uZXJhLmNv\n"
+ + "bS9DUFMwDgYDVR0PAQH/BAQDAgEGMIHGBgNVHR8Egb4wgbswQKA+oDyGOmh0dHA6\n"
+ + "Ly9jcmwtMy50cnVzdC50ZWxpYXNvbmVyYS5jb20vdGVsaWFzb25lcmFyb290Y2F2\n"
+ + "MS5jcmwwd6B1oHOGcWxkYXA6Ly9jcmwtMS50cnVzdC50ZWxpYXNvbmVyYS5jb20v\n"
+ + "Y249VGVsaWFTb25lcmElMjBSb290JTIwQ0ElMjB2MSxvPVRlbGlhU29uZXJhP2Nl\n"
+ + "cnRpZmljYXRlcmV2b2NhdGlvbmxpc3Q7YmluYXJ5MB0GA1UdDgQWBBQvSTwpT9cH\n"
+ + "JfnGjNVk9WY9EoMilTAfBgNVHSMEGDAWgBTwj1k4ALP1j5qWDNXr+nuqF+gTEjAN\n"
+ + "BgkqhkiG9w0BAQsFAAOCAgEAg9EVFW6ioZ2ctrX8KqvW9XPYZR01yNgqlO7pwBWf\n"
+ + "HzuBCbUdyVzumfQnU24Sce92oMtEfyuxIOmhvoXU7LpnYlH3Q29UGP5dL0D3edGz\n"
+ + "HeU6Tf8bkcOEHtnTrkd+y+rfFSDWYl9r1y993NAcrBHhroQCE53mlrO7TjXa3zDq\n"
+ + "6LGR8T8VgvGw0IBz6mzAks0wMYB0b4uREPmWXi+m+RqG3lnpl+eBzz6YVLkxIYMq\n"
+ + "QIXJIBsu4/ybmadsfdql6E8Lo3dKVD4UG10mtd+iPbJiBiW/a9VbEe3NVKIv4H2y\n"
+ + "HqYcxDXAeUI66E3K2cjCmKoQaa0Ywt02ikZFd0v1OWNPS7YWbEJWkVR1PcPMESK9\n"
+ + "6HKI4xhG2tJesmXjQ8q8aSx2u79Zts3ewjKqTmurf6FXW3u9TpSCUe6Drr/3X7Ve\n"
+ + "nBy4M0sLwCecD/L9gjTa+EItQTYzCkpxiMO49tQdX/BpwgWju4Kg3qkaBNTzvSlk\n"
+ + "gdnRJqCUkVuzwK4yBqUoyRz3prlhvvRGdZJKf6IXRDhncpey5pm0PQYQ4cArx7Go\n"
+ + "AaAKz0ZTHOKjnM2KIdUhBJQybL7oPklSfkeMWoUoYED6R4YMTt/JXX4ixEb5DgDJ\n"
+ + "0F+bNcF7qGrJTkTx0Ccy4BuuY05hJckd72E7WdmjN7DDeosghgWZNV/6D7N5tfxo\n"
+ + "nlU=\n"
+ + "-----END CERTIFICATE-----";
+
+ // Owner: CN=juolukka.cover.sonera.net, OU=security, O=Telia Finland Oyj, L=helsinki, C=FI
+ // Issuer: CN=TeliaSonera Server CA v2, O=TeliaSonera, C=FI
+ private static final String VALID = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIHiDCCBXCgAwIBAgIPAWOq14hk136UDQY3WSjLMA0GCSqGSIb3DQEBCwUAMEYx\n" +
+ "CzAJBgNVBAYTAkZJMRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEhMB8GA1UEAwwYVGVs\n" +
+ "aWFTb25lcmEgU2VydmVyIENBIHYyMB4XDTE4MDUyOTA3NDA0MVoXDTE5MDUyOTA3\n" +
+ "NDA0MVowczELMAkGA1UEBhMCRkkxETAPBgNVBAcMCGhlbHNpbmtpMRowGAYDVQQK\n" +
+ "DBFUZWxpYSBGaW5sYW5kIE95ajERMA8GA1UECwwIc2VjdXJpdHkxIjAgBgNVBAMM\n" +
+ "GWp1b2x1a2thLmNvdmVyLnNvbmVyYS5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" +
+ "DwAwggEKAoIBAQDLks9F8ZUqV9G4jn3fY234OX09Dmqqtuk0qAmjWpF0JAn2o64t\n" +
+ "whVxFLx9e2IwUPTQgyo6FwRsiT19m99BhgxYnJOxVRwURxSL3mqlV9gX4oFMmT4O\n" +
+ "EOYEjaJXi8ne1pJX80y2hVQ48XqgODnKdKZVwa5YoeWZQJiaq+C5JkMDN8qzpiyQ\n" +
+ "X3EfJspLkKy2E+UVxWmfnyf0v70ES9TQ8qgxwvsf7LRZ8Jixq7TTO5VbqWsdBvJC\n" +
+ "9Zm2aBOYJ7ptSZQ5YDfeUJG2c9S/zFmngoPnTrvAZwUeU3YTrbdZQy899ZOatWac\n" +
+ "6lHUYU2EagEmbj/jtIvJ6wMbzhleIXRQFWibAgMBAAGjggNEMIIDQDAfBgNVHSME\n" +
+ "GDAWgBQvSTwpT9cHJfnGjNVk9WY9EoMilTAdBgNVHQ4EFgQUbMozh4osL4gFJvb5\n" +
+ "baELpQSKEhIwDgYDVR0PAQH/BAQDAgSwME4GA1UdIARHMEUwQwYGZ4EMAQICMDkw\n" +
+ "NwYIKwYBBQUHAgEWK2h0dHA6Ly9yZXBvc2l0b3J5LnRydXN0LnRlbGlhc29uZXJh\n" +
+ "LmNvbS9DUFMwJAYDVR0RBB0wG4IZanVvbHVra2EuY292ZXIuc29uZXJhLm5ldDBN\n" +
+ "BgNVHR8ERjBEMEKgQKA+hjxodHRwOi8vY3JsLTMudHJ1c3QudGVsaWFzb25lcmEu\n" +
+ "Y29tL3RlbGlhc29uZXJhc2VydmVyY2F2Mi5jcmwwHQYDVR0lBBYwFAYIKwYBBQUH\n" +
+ "AwIGCCsGAQUFBwMBMIGGBggrBgEFBQcBAQR6MHgwJwYIKwYBBQUHMAGGG2h0dHA6\n" +
+ "Ly9vY3NwLnRydXN0LnRlbGlhLmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL3JlcG9z\n" +
+ "aXRvcnkudHJ1c3QudGVsaWFzb25lcmEuY29tL3RlbGlhc29uZXJhc2VydmVyY2F2\n" +
+ "Mi5jZXIwggF/BgorBgEEAdZ5AgQCBIIBbwSCAWsBaQB2AG9Tdqwx8DEZ2JkApFEV\n" +
+ "/3cVHBHZAsEAKQaNsgiaN9kTAAABY6rXpS0AAAQDAEcwRQIgfMLEFYxQcncL3am/\n" +
+ "W2x7DMZ1+Vh1tDLw/0qIQB40VBQCIQC1eyF8Q6CcQs+gIgzpy7OiZSosSlykyOgW\n" +
+ "qHkj/0UPygB3AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAABY6rX\n" +
+ "pLEAAAQDAEgwRgIhAJxveFVsFrfttSJIxHsMPAvvevptaV2CxsGwubAi8wDDAiEA\n" +
+ "jNbbYfUiYtmQ5v4yc6T+GcixztNIlMzQ7OTK+u9zqSoAdgBVgdTCFpA2AUrqC5tX\n" +
+ "PFPwwOQ4eHAlCBcvo6odBxPTDAAAAWOq16YXAAAEAwBHMEUCIQCCkCL2zn/AoMVI\n" +
+ "BdsoJelUBLsAnQ+GlIafiyZYcCwhBAIgdsFM05eNmL5hfn3+WtfgmipwcK1qp7kO\n" +
+ "ONzO69aqrnEwDQYJKoZIhvcNAQELBQADggIBAIl5UWSwCXF85+2lU6t89K7I4TvZ\n" +
+ "Ggof0NLngea9qxBq00opfnl9i2LPRnsjh9s3iA29i2daTEuJn3qt3Ygcm27Jd7WM\n" +
+ "5StcxQ483GAaL5s5m2QqkZB8eLfez3tIyCMGCAyixBDNRNPVI4xZr6sSOenWtipo\n" +
+ "gMt+/gvRIMdMT79IXPFz4W9RWCwnfJNOlfH2OkS3KZYaPSaEvs6sfMW1DDZosrBy\n" +
+ "6F+DITPLllOVSE4+PTxvXLKVy+srFwF1VocQXKkWMHQ7AfWNnOGzb7B1qg7gsw0n\n" +
+ "axqinyCjkhMpHpcVtmD9Pi15HLFDIy9yI2S+FHJQfhUSmM/LdCWzQpnee6/Wo+uw\n" +
+ "p0Jg2v6v9GGaqfpuiVJPFN9dOv3OjMU7DL5lgMRWFRo2T8+wBHXDyBhT0W0y5kRJ\n" +
+ "eWA7t6CnkziHuaOihZAHUH3nn5exjqUFVS0ThbF6hxN7HAlq/xIbTKlZjkLlc14W\n" +
+ "fB8vkxJyy/tgBZ4dCj9Y1Y32d4eFT5JZJgqgkN59SmX56BswNXncGrk/vWZFFx+g\n" +
+ "9dgb8QSe8KseD1iSLc7SsqVDv8NPYdaI3eZ90W8Wv0/CDls321O6UbAmURzQwFGB\n" +
+ "w8WnteoVBi6Wf6M1TxIfJsXBYeIN0BB6AYc8cmZIOtx2C8aH4JJT45MyFnBv3ac5\n" +
+ "Ahs9pGn/+K+5yb2e\n" +
+ "-----END CERTIFICATE-----";
+
+ // Owner: CN=juolukka.cover.sonera.net, OU=Security, O=TeliaSonera Finland, L=Helsinki, C=FI
+ // Issuer: CN=TeliaSonera Server CA v2, O=TeliaSonera, C=FI
+ private static final String REVOKED = "-----BEGIN CERTIFICATE-----\n" +
+ "MIIGEDCCA/igAwIBAgIRAKWJTjs6v04ZTyb2wJxfnJswDQYJKoZIhvcNAQELBQAw\n" +
+ "RjELMAkGA1UEBhMCRkkxFDASBgNVBAoMC1RlbGlhU29uZXJhMSEwHwYDVQQDDBhU\n" +
+ "ZWxpYVNvbmVyYSBTZXJ2ZXIgQ0EgdjIwHhcNMTYxMjIzMDcwMTQ2WhcNMTkxMjIz\n" +
+ "MDcwMTQ2WjB1MQswCQYDVQQGEwJGSTERMA8GA1UEBwwISGVsc2lua2kxHDAaBgNV\n" +
+ "BAoME1RlbGlhU29uZXJhIEZpbmxhbmQxETAPBgNVBAsMCFNlY3VyaXR5MSIwIAYD\n" +
+ "VQQDDBlqdW9sdWtrYS5jb3Zlci5zb25lcmEubmV0MIIBIjANBgkqhkiG9w0BAQEF\n" +
+ "AAOCAQ8AMIIBCgKCAQEAt2u92TgTFdm1OEfmWFPe+ESBi+2ox4y1EDoin8RydMyO\n" +
+ "DI6+0HHnKfDZa1YViI5b6MLJKWIAyUszAg5hc0S3upElfSsBvUW6zuQTxMi2vTYE\n" +
+ "4tcqwIEyCUaiv4wC+DuO5CyGR32yR6HB/W5Ny200dPs2SO03ESEJ+LH4Tw5AI8JJ\n" +
+ "UZHW+lA+yUHnlc3q47svpbspjt0C/THyukd1hbXTBB0mPXqPux+ClvtZBWUJb7ti\n" +
+ "1cPfcCNd79KRObzcgxqcOIaUFz4LjjKezhzVSL7tJOANOHZ09qDeOAkk/X9POx4h\n" +
+ "a5XyWfH1zaQ0QlZ2mKBeHebCIJkgTZZVipagRVOgcwIDAQABo4IByDCCAcQwgY0G\n" +
+ "CCsGAQUFBwEBBIGAMH4wLQYIKwYBBQUHMAGGIWh0dHA6Ly9vY3NwLnRydXN0LnRl\n" +
+ "bGlhc29uZXJhLmNvbTBNBggrBgEFBQcwAoZBaHR0cDovL3JlcG9zaXRvcnkudHJ1\n" +
+ "c3QudGVsaWFzb25lcmEuY29tL3RlbGlhc29uZXJhc2VydmVyY2F2Mi5jZXIwHwYD\n" +
+ "VR0jBBgwFoAUL0k8KU/XByX5xozVZPVmPRKDIpUwTgYDVR0gBEcwRTBDBgZngQwB\n" +
+ "AgIwOTA3BggrBgEFBQcCARYraHR0cDovL3JlcG9zaXRvcnkudHJ1c3QudGVsaWFz\n" +
+ "b25lcmEuY29tL0NQUzBNBgNVHR8ERjBEMEKgQKA+hjxodHRwOi8vY3JsLTMudHJ1\n" +
+ "c3QudGVsaWFzb25lcmEuY29tL3RlbGlhc29uZXJhc2VydmVyY2F2Mi5jcmwwHQYD\n" +
+ "VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA4GA1UdDwEB/wQEAwIEsDAkBgNV\n" +
+ "HREEHTAbghlqdW9sdWtrYS5jb3Zlci5zb25lcmEubmV0MB0GA1UdDgQWBBSa+vJH\n" +
+ "I6Lt9Aqw5ondhoZu4/IJezANBgkqhkiG9w0BAQsFAAOCAgEASRK1l1MZb/IRlyi+\n" +
+ "XjfZcxJdFuNzW2kpZstW6Ni2XiD3p7aROBfDFtu7GajzZHb6p76auDb4NwJgeE/3\n" +
+ "6gnXoIK00HwpF2RAhxDpkF8r3q0jSqGhSv/xz9Nx7JBzgqfSw3Ha4ohioIed3uc+\n" +
+ "nMDyvVenio4GYgtxIIubSybCxMv/lBA/S4daIVCYK3VOoBbM2F36ecAKvRU5vIWM\n" +
+ "urXsfANL3u4qgJpaM0DclzFsOkVsRPffzToko/Nr6pGXYjt47IzTRlwLMnLehoZW\n" +
+ "ZZMGMVVOlR7XGf81UjWB6OsKeoQ4FWgcb/rIJcZusm+LqvnsCHuC3gtuC2nGA7lr\n" +
+ "fseUlG7QZN9/QfUIyvL69wAzeVj1cUcd7GHcAH9DyZJfI8orv4PyUvitDdgISkFu\n" +
+ "GZ562O7cGmCv00/6I4t0z9wZal8a5lRDoKXAYy+u/adrO1JjLwi11y/DTw9LQ7sJ\n" +
+ "gVP/v2GsI0ajF9A6z33UHN9uxXZVmQNvOiMkcJiGLovFgu5zxoAg2W3pHjbBbeL8\n" +
+ "v5MPqgsKafgzaSRtXBBvaISHi9hhRR8v/qSwO3NyLm8uAhQD4x+OPHrmQ/s16j45\n" +
+ "Ib53UHj1k6byXGUqDgzFBsmEPV6Shf2C4/HcRHpAX8wQx3xVwDtRzDpNUR6vnNfi\n" +
+ "PwzRU1xsQKd8llmgl4l+fYV0tBA=\n" +
+ "-----END CERTIFICATE-----";
+
+ public static void main(String[] args) throws Exception {
+
+ ValidatePathWithParams pathValidator = new ValidatePathWithParams(null);
+
+ if (args.length >= 1 && "CRL".equalsIgnoreCase(args[0])) {
+ pathValidator.enableCRLCheck();
+ } else {
+ // OCSP check by default
+ pathValidator.enableOCSPCheck();
+ }
+
+ // Validate valid
+ pathValidator.validate(new String[]{VALID, INT},
+ ValidatePathWithParams.Status.GOOD, null, System.out);
+
+ // Validate Revoked
+ pathValidator.validate(new String[]{REVOKED, INT},
+ ValidatePathWithParams.Status.REVOKED,
+ "Thu Dec 22 23:14:55 PST 2016", System.out);
+
+ // reset validation date back to current date
+ pathValidator.resetValidationDate();
+ }
+}
diff --git a/test/security/infra/java/security/cert/CertPathValidator/certification/ValidatePathWithParams.java b/test/security/infra/java/security/cert/CertPathValidator/certification/ValidatePathWithParams.java
new file mode 100644
index 0000000000..ddc63da737
--- /dev/null
+++ b/test/security/infra/java/security/cert/CertPathValidator/certification/ValidatePathWithParams.java
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2017, 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.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Security;
+import java.security.cert.CertPath;
+import java.security.cert.CertPathValidator;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertificateRevokedException;
+import java.security.cert.PKIXParameters;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.Locale;
+
+/**
+ * Utility class to validate certificate path. It supports OCSP and/or CRL
+ * validation.
+ */
+public class ValidatePathWithParams {
+
+ private static final String FS = System.getProperty("file.separator");
+ private static final String CACERTS_STORE = System.getProperty("test.jdk")
+ + FS + "jre" + FS + "lib" + FS + "security" + FS + "cacerts";
+
+ private final String[] trustedRootCerts;
+
+ // use this for expired cert validation
+ private Date validationDate = null;
+
+ // expected certificate status
+ private Status expectedStatus = Status.UNKNOWN;
+ private Date expectedRevDate = null;
+
+ private final CertPathValidator certPathValidator;
+ private final PKIXRevocationChecker certPathChecker;
+ private final CertificateFactory cf;
+
+ /**
+ * Possible status values supported for EE certificate
+ */
+ public static enum Status {
+ UNKNOWN, GOOD, REVOKED, EXPIRED;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param additionalTrustRoots trusted root certificates
+ * @throws IOException
+ * @throws CertificateException
+ * @throws NoSuchAlgorithmException
+ */
+ public ValidatePathWithParams(String[] additionalTrustRoots)
+ throws IOException, CertificateException, NoSuchAlgorithmException {
+
+ cf = CertificateFactory.getInstance("X509");
+ certPathValidator = CertPathValidator.getInstance("PKIX");
+ certPathChecker
+ = (PKIXRevocationChecker) certPathValidator.getRevocationChecker();
+
+ if ((additionalTrustRoots == null) || (additionalTrustRoots[0] == null)) {
+ trustedRootCerts = null;
+ } else {
+ trustedRootCerts = additionalTrustRoots.clone();
+ }
+ }
+
+ /**
+ * Validate certificates
+ *
+ * @param certsToValidate Certificates to validate
+ * @param st expected certificate status
+ * @param revDate if revoked, expected revocation date
+ * @param out PrintStream to log messages
+ * @throws IOException
+ * @throws CertificateException
+ * @throws InvalidAlgorithmParameterException
+ * @throws ParseException
+ * @throws NoSuchAlgorithmException
+ * @throws KeyStoreException
+ */
+ public void validate(String[] certsToValidate,
+ Status st,
+ String revDate,
+ PrintStream out)
+ throws IOException, CertificateException,
+ InvalidAlgorithmParameterException, ParseException,
+ NoSuchAlgorithmException, KeyStoreException {
+
+ expectedStatus = st;
+ if (expectedStatus == Status.REVOKED) {
+ if (revDate != null) {
+ expectedRevDate = new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy",
+ Locale.US).parse(revDate);
+ }
+ }
+
+ Status certStatus = null;
+ Date revocationDate = null;
+
+ logSettings(out);
+
+ try {
+ doCertPathValidate(certsToValidate, out);
+ certStatus = Status.GOOD;
+ } catch (IOException ioe) {
+ // Some machines don't have network setup correctly to be able to
+ // reach outside world, skip such failures
+ out.println("WARNING: Network setup issue, skip this test");
+ ioe.printStackTrace(System.err);
+ return;
+ } catch (CertPathValidatorException cpve) {
+ out.println("Received exception: " + cpve);
+
+ if (cpve.getCause() instanceof IOException) {
+ out.println("WARNING: CertPathValidatorException caused by IO"
+ + " error, skip this test");
+ return;
+ }
+
+ if (cpve.getReason() == CertPathValidatorException.BasicReason.ALGORITHM_CONSTRAINED) {
+ out.println("WARNING: CertPathValidatorException caused by"
+ + " restricted algorithm, skip this test");
+ return;
+ }
+
+ if (cpve.getReason() == CertPathValidatorException.BasicReason.REVOKED
+ || cpve.getCause() instanceof CertificateRevokedException) {
+ certStatus = Status.REVOKED;
+ if (cpve.getCause() instanceof CertificateRevokedException) {
+ CertificateRevokedException cre
+ = (CertificateRevokedException) cpve.getCause();
+ revocationDate = cre.getRevocationDate();
+ }
+ } else if (cpve.getReason() == CertPathValidatorException.BasicReason.EXPIRED
+ || cpve.getCause() instanceof CertificateExpiredException) {
+ certStatus = Status.EXPIRED;
+ } else {
+ throw new RuntimeException(
+ "TEST FAILED: couldn't determine EE certificate status");
+ }
+ }
+
+ out.println("Expected Certificate status: " + expectedStatus);
+ out.println("Certificate status after validation: " + certStatus.name());
+
+ // Don't want test to fail in case certificate is expired when not expected
+ // Simply skip the test.
+ if (expectedStatus != Status.EXPIRED && certStatus == Status.EXPIRED) {
+ out.println("WARNING: Certificate expired, skip the test");
+ return;
+ }
+
+ if (certStatus != expectedStatus) {
+ throw new RuntimeException(
+ "TEST FAILED: unexpected status of EE certificate");
+ }
+
+ if (certStatus == Status.REVOKED) {
+ // Check revocation date
+ if (revocationDate != null) {
+ out.println(
+ "Certificate revocation date:" + revocationDate.toString());
+ if (expectedRevDate != null) {
+ out.println(
+ "Expected revocation date:" + expectedRevDate.toString());
+ if (!expectedRevDate.equals(revocationDate)) {
+ throw new RuntimeException(
+ "TEST FAILED: unexpected revocation date");
+ }
+ }
+ } else {
+ throw new RuntimeException("TEST FAILED: no revocation date");
+ }
+ }
+ }
+
+ private void logSettings(PrintStream out) {
+ out.println();
+ out.println("=====================================================");
+ out.println("CONFIGURATION");
+ out.println("=====================================================");
+ out.println("http.proxyHost :" + System.getProperty("http.proxyHost"));
+ out.println("http.proxyPort :" + System.getProperty("http.proxyPort"));
+ out.println("https.proxyHost :" + System.getProperty("https.proxyHost"));
+ out.println("https.proxyPort :" + System.getProperty("https.proxyPort"));
+ out.println("https.socksProxyHost :"
+ + System.getProperty("https.socksProxyHost"));
+ out.println("https.socksProxyPort :"
+ + System.getProperty("https.socksProxyPort"));
+ out.println("jdk.certpath.disabledAlgorithms :"
+ + Security.getProperty("jdk.certpath.disabledAlgorithms"));
+ out.println("Revocation options :" + certPathChecker.getOptions());
+ out.println("OCSP responder set :" + certPathChecker.getOcspResponder());
+ out.println("Trusted root set: " + (trustedRootCerts != null));
+
+ if (validationDate != null) {
+ out.println("Validation Date:" + validationDate.toString());
+ }
+ out.println("Expected EE Status:" + expectedStatus.name());
+ if (expectedStatus == Status.REVOKED && expectedRevDate != null) {
+ out.println(
+ "Expected EE Revocation Date:" + expectedRevDate.toString());
+ }
+ out.println("=====================================================");
+ }
+
+ private void doCertPathValidate(String[] certsToValidate, PrintStream out)
+ throws IOException, CertificateException,
+ InvalidAlgorithmParameterException, ParseException,
+ NoSuchAlgorithmException, CertPathValidatorException, KeyStoreException {
+
+ if (certsToValidate == null) {
+ throw new RuntimeException("Require atleast one cert to validate");
+ }
+
+ // Generate CertPath with certsToValidate
+ ArrayList<X509Certificate> certs = new ArrayList<>();
+ for (String cert : certsToValidate) {
+ if (cert != null) {
+ certs.add(getCertificate(cert));
+ }
+ }
+ CertPath certPath = (CertPath) cf.generateCertPath(certs);
+
+ // Set cacerts as anchor
+ KeyStore cacerts = KeyStore.getInstance("JKS");
+ try (FileInputStream fis = new FileInputStream(CACERTS_STORE)) {
+ cacerts.load(fis, "changeit".toCharArray());
+ } catch (IOException | NoSuchAlgorithmException | CertificateException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ // Set additional trust certificates
+ if (trustedRootCerts != null) {
+ for (int i = 0; i < trustedRootCerts.length; i++) {
+ X509Certificate rootCACert = getCertificate(trustedRootCerts[i]);
+ cacerts.setCertificateEntry("tempca" + i, rootCACert);
+ }
+ }
+
+ PKIXParameters params;
+ params = new PKIXParameters(cacerts);
+ params.addCertPathChecker(certPathChecker);
+
+ // Set backdated validation if requested, if null, current date is set
+ params.setDate(validationDate);
+
+ // Validate
+ certPathValidator.validate(certPath, params);
+ out.println("Successful CertPath validation");
+ }
+
+ private X509Certificate getCertificate(String encodedCert)
+ throws IOException, CertificateException {
+ ByteArrayInputStream is
+ = new ByteArrayInputStream(encodedCert.getBytes());
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(is);
+ return cert;
+ }
+
+ /**
+ * Set list of disabled algorithms
+ *
+ * @param algos algorithms to disable
+ */
+ public static void setDisabledAlgorithms(String algos) {
+ Security.setProperty("jdk.certpath.disabledAlgorithms", algos);
+ }
+
+ /**
+ * Enable OCSP only revocation checks, treat network error as success
+ */
+ public void enableOCSPCheck() {
+ // OCSP is by default, disable fallback to CRL
+ certPathChecker.setOptions(EnumSet.of(
+ PKIXRevocationChecker.Option.NO_FALLBACK));
+ }
+
+ /**
+ * Enable CRL only revocation check, treat network error as success
+ */
+ public void enableCRLCheck() {
+ certPathChecker.setOptions(EnumSet.of(
+ PKIXRevocationChecker.Option.PREFER_CRLS,
+ PKIXRevocationChecker.Option.NO_FALLBACK));
+ }
+
+ /**
+ * Overrides OCSP responder URL in AIA extension of certificate
+ *
+ * @param url OCSP responder
+ * @throws URISyntaxException
+ */
+ public void setOCSPResponderURL(String url) throws URISyntaxException {
+ certPathChecker.setOcspResponder(new URI(url));
+ }
+
+ /**
+ * Set validation date for EE certificate
+ *
+ * @param vDate string formatted date
+ * @throws ParseException if vDate is incorrect
+ */
+ public void setValidationDate(String vDate) throws ParseException {
+ validationDate = DateFormat.getDateInstance(DateFormat.MEDIUM,
+ Locale.US).parse(vDate);
+ }
+
+ /**
+ * Reset validation date for EE certificate to current date
+ */
+ public void resetValidationDate() {
+ validationDate = null;
+ }
+}
diff --git a/test/sun/net/www/protocol/http/TestTransparentNTLM.java b/test/sun/net/www/protocol/http/TestTransparentNTLM.java
new file mode 100644
index 0000000000..d588500fa5
--- /dev/null
+++ b/test/sun/net/www/protocol/http/TestTransparentNTLM.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2018, 2019, 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 8225425
+ * @summary Verifies that transparent NTLM (on Windows) is not used by default,
+ * and is used only when the relevant property is set.
+ * @requires os.family == "windows"
+ * @library ../../../../../lib/testlibrary
+ * @run testng/othervm
+ * -Dtest.auth.succeed=false
+ * TestTransparentNTLM
+ * @run testng/othervm
+ * -Djdk.http.ntlm.transparentAuth=allHosts
+ * -Dtest.auth.succeed=true
+ * TestTransparentNTLM
+ * @run testng/othervm
+ * -Djdk.http.ntlm.transparentAuth=blahblah
+ * -Dtest.auth.succeed=false
+ * TestTransparentNTLM
+ * @run testng/othervm
+ * -Djdk.http.ntlm.transparentAuth=trustedHosts
+ * -Dtest.auth.succeed=false
+ * TestTransparentNTLM
+ */
+
+// Run with `trustedHosts` to exercise the native code, nothing more.
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URL;
+import jdk.testlibrary.net.URIBuilder;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+import org.testng.SkipException;
+import static java.lang.System.out;
+import static java.net.Proxy.NO_PROXY;
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+public class TestTransparentNTLM {
+
+ boolean succeed; // true if authentication is expected to succeed
+ Server server;
+ URL url;
+
+ @Test
+ public void testNTLM() throws IOException {
+ out.println("connecting to url: " + url);
+ HttpURLConnection uc = (HttpURLConnection)url.openConnection(NO_PROXY);
+ int respCode = uc.getResponseCode();
+ out.println("received: " + respCode);
+
+ if (succeed) {
+ assertEquals(respCode, HttpURLConnection.HTTP_OK);
+ InputStream is = uc.getInputStream();
+ BufferedReader r = new BufferedReader(new InputStreamReader(is, UTF_8));
+ String body = r.readLine();
+ out.print("received body: ");
+ do {
+ out.print(body);
+ body = r.readLine();
+ } while (body != null);
+ } else {
+ assertEquals(respCode, HttpURLConnection.HTTP_UNAUTHORIZED);
+ }
+ }
+
+ static class Server extends Thread implements Closeable {
+
+ static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
+ final ServerSocket serverSocket;
+ final boolean expectAuthToSucceed;
+
+ Server(boolean expectAuthToSucceed) throws IOException {
+ super("TestTransparentNTLM-Server");
+ serverSocket = new ServerSocket();
+ serverSocket.bind(new InetSocketAddress(LOOPBACK, 0));
+ this.expectAuthToSucceed = expectAuthToSucceed;
+ }
+
+ int port() {
+ return serverSocket.getLocalPort();
+ }
+
+ static final String AUTH_REQUIRED =
+ "HTTP/1.1 401 Unauthorized\r\n" +
+ "Content-Length: 0\r\n" +
+ "Connection: close\r\n" +
+ "WWW-Authenticate: NTLM\r\n\r\n";
+
+ static final String AUTH_STAGE_TWO =
+ "HTTP/1.1 401 Unauthorized\r\n" +
+ "Content-Length: 0\r\n" +
+ "WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==\r\n\r\n";
+
+ static final String AUTH_SUCCESSFUL =
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 11\r\n\r\n" +
+ "Hello world";
+
+ @Override
+ public void run() {
+ try {
+ try (Socket s = serverSocket.accept()) {
+ out.println("Server accepted connection - 1");
+ readRequestHeaders(s.getInputStream());
+ s.getOutputStream().write(AUTH_REQUIRED.getBytes(UTF_8));
+ }
+
+ if (expectAuthToSucceed) {
+ // await the second follow up connection
+ try (Socket s = serverSocket.accept()) {
+ out.println("Server accepted connection - 2");
+ readRequestHeaders(s.getInputStream());
+ s.getOutputStream().write(AUTH_STAGE_TWO.getBytes(UTF_8));
+ readRequestHeaders(s.getInputStream());
+ s.getOutputStream().write(AUTH_SUCCESSFUL.getBytes(UTF_8));
+ }
+ }
+ } catch (IOException e) {
+ fail("Unexpected exception", e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ serverSocket.close();
+ }
+
+ static final byte[] REQUEST_END = new byte[] {'\r', '\n', '\r', '\n'};
+
+ // Read until the end of the HTTP request headers
+ static void readRequestHeaders(InputStream is) throws IOException {
+ int requestEndCount = 0, r;
+ while ((r = is.read()) != -1) {
+ if (r == REQUEST_END[requestEndCount]) {
+ requestEndCount++;
+ if (requestEndCount == 4) {
+ break;
+ }
+ } else {
+ requestEndCount = 0;
+ }
+ }
+ }
+ }
+
+ @BeforeTest
+ public void setup() throws Exception {
+ succeed = System.getProperty("test.auth.succeed").equals("true");
+ if (succeed)
+ out.println("Expect client to succeed, with 200 Ok");
+ else
+ out.println("Expect client to fail, with 401 Unauthorized");
+
+ server = new Server(succeed);
+ server.start();
+ url = URIBuilder.newBuilder()
+ .scheme("http")
+ .loopback()
+ .port(server.port())
+ .path("/xxyyzz")
+ .toURL();
+ }
+
+ @AfterTest
+ public void teardown() throws Exception {
+ server.close();
+ server.join();
+ }
+}
diff --git a/test/sun/nio/cs/MalformedSurrogates.java b/test/sun/nio/cs/MalformedSurrogates.java
index 36481dafbf..462e1651d0 100644
--- a/test/sun/nio/cs/MalformedSurrogates.java
+++ b/test/sun/nio/cs/MalformedSurrogates.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,64 +22,132 @@
*/
/* @test
- @bug 4153987
- @summary Malformed surrogates should be handled by the converter in
- substitution mode.
+ * @bug 4153987
+ * @summary Malformed surrogates should be handled by the converter in
+ * substitution mode.
*/
-
import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.CharBuffer;
+import java.nio.ByteBuffer;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import java.util.SortedMap;
public class MalformedSurrogates {
- public static void main(String[] args) throws Exception {
+ private static final String PREFIX = "abc";
+ private static final String SUFFIX = "efgh";
+ private static final String MALFORMED_SURROGATE = PREFIX + "\uD800\uDB00" + SUFFIX;
+ private static final String NORMAL_SURROGATE = PREFIX + "\uD800\uDC00" + SUFFIX;
+ private static final String REVERSED_SURROGATE = PREFIX + "\uDC00\uD800" + SUFFIX;
+ private static final String SOLITARY_HIGH_SURROGATE = PREFIX + "\uD800" + SUFFIX;
+ private static final String SOLITARY_LOW_SURROGATE = PREFIX + "\uDC00" + SUFFIX;
- String fe = System.getProperty("file.encoding");
- if ( fe.equalsIgnoreCase("UTF8")
- || fe.equalsIgnoreCase("UTF-8")
- || fe.equalsIgnoreCase("UTF_8"))
- // This test is meaningless if the default charset
- // does handle surrogates
- return;
+ public static void main(String[] args) throws IOException {
+ SortedMap<String, Charset> map = Charset.availableCharsets();
+ for (String name : map.keySet()) {
+ Charset charset = map.get(name);
+ if (charset.canEncode() && !charset.name().equals("x-COMPOUND_TEXT")) {
+ testNormalSurrogate(charset, NORMAL_SURROGATE);
+ testMalformedSurrogate(charset, MALFORMED_SURROGATE);
+ testMalformedSurrogate(charset, REVERSED_SURROGATE);
+ testMalformedSurrogate(charset, SOLITARY_HIGH_SURROGATE);
+ testMalformedSurrogate(charset, SOLITARY_LOW_SURROGATE);
+ testSurrogateWithReplacement(charset, NORMAL_SURROGATE);
+ testSurrogateWithReplacement(charset, MALFORMED_SURROGATE);
+ testSurrogateWithReplacement(charset, REVERSED_SURROGATE);
+ testSurrogateWithReplacement(charset, SOLITARY_HIGH_SURROGATE);
+ testSurrogateWithReplacement(charset, SOLITARY_LOW_SURROGATE);
+ }
+ }
+ }
+
+ public static void testMalformedSurrogate(Charset cs, String surrogate) throws IOException {
+ CharsetEncoder en = cs.newEncoder();
+ if (en.canEncode(surrogate)) {
+ throw new RuntimeException("testMalformedSurrogate failed with charset " + cs.name());
+ }
+
+ try {
+ en.encode(CharBuffer.wrap(surrogate));
+ throw new RuntimeException("Should throw MalformedInputException or UnmappableCharacterException");
+ } catch (MalformedInputException | UnmappableCharacterException ex) {
+ } finally {
+ en.reset();
+ }
- System.out.println("Testing string conversion...");
- /* Example with malformed surrogate, and an offset */
- String t = "abc\uD800\uDB00efgh";
- String t2 = t.substring(2);
- byte[] b = t2.getBytes();
- System.err.println(b.length);
- for (int i = 0; i < b.length; i++)
- System.err.println("[" + i + "]" + "=" + (char) b[i]
- + "=" + (int) b[i]);
- if (b.length != 7) {
- throw new Exception("Bad string conversion for bad surrogate");
+ try (OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream(), en)) {
+ osw.write(surrogate);
+ throw new RuntimeException("Should throw MalformedInputException or UnmappableCharacterException");
+ } catch (MalformedInputException | UnmappableCharacterException ex) {
+ }
+ }
+
+ public static void testNormalSurrogate(Charset cs, String surrogate) throws IOException {
+ CharsetEncoder en = cs.newEncoder();
+ try {
+ en.encode(CharBuffer.wrap(surrogate));
+ } catch (UnmappableCharacterException ex) {
+ } finally {
+ en.reset();
}
- /* Example with a proper surrogate, no offset. Always worked */
- String t3 = "abc\uD800\uDC00efgh";
- byte[] b2 = t3.getBytes();
- System.out.println(b2.length);
- for(int i = 0; i < b2.length; i++)
- System.err.println("[" + i + "]" + "=" + (char) b2[i]);
- if (b2.length != 8) {
- throw new Exception("Bad string conversion for good surrogate");
+ try (OutputStreamWriter osw = new OutputStreamWriter(new ByteArrayOutputStream(), en)) {
+ osw.write(surrogate);
+ } catch (UnmappableCharacterException ex) {
}
+ }
- OutputStream os = new ByteArrayOutputStream();
- OutputStreamWriter osw = new OutputStreamWriter(os);
- System.out.println("Testing flush....");
- /* Check for the case where the converter has a left over
- high surrogate when flush is called on the converter */
- osw.flush();
- String s = "abc\uD800"; // High surrogate
- char[] c = s.toCharArray();
- osw.write(s, 0, 4);
- osw.flush();
+ public static void testSurrogateWithReplacement(Charset cs, String surrogate) throws IOException {
+ CharsetEncoder en = cs.newEncoder();
+ CharsetDecoder de = cs.newDecoder();
+ if (!en.canEncode(NORMAL_SURROGATE)) {
+ return;
+ }
+ String expected = null;
+ String replace = new String(en.replacement(), cs);
+ switch (surrogate) {
+ case MALFORMED_SURROGATE:
+ case REVERSED_SURROGATE:
+ expected = PREFIX + replace + replace + SUFFIX;
+ break;
+ case SOLITARY_HIGH_SURROGATE:
+ case SOLITARY_LOW_SURROGATE:
+ expected = PREFIX + replace + SUFFIX;
+ break;
+ default:
+ expected = NORMAL_SURROGATE;
+ }
- System.out.println("Testing convert...");
- /* Verify that all other characters go through */
- for (int k = 1; k < 65535 ; k++) {
- osw.write("Char[" + k + "]=\"" + ((char) k) + "\"");
+ try {
+ en.onMalformedInput(CodingErrorAction.REPLACE);
+ en.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ ByteBuffer bbuf = en.encode(CharBuffer.wrap(surrogate));
+ CharBuffer cbuf = de.decode(bbuf);
+ if (!cbuf.toString().equals(expected)) {
+ throw new RuntimeException("charset " + cs.name() + " (en)decoded the surrogate " + surrogate + " to " + cbuf.toString() + " which is not same as the expected " + expected);
+ }
+ } finally {
+ en.reset();
+ de.reset();
}
+ try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(bos, en);) {
+ osw.write(surrogate);
+ osw.flush();
+ try (InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(bos.toByteArray()), de)) {
+ CharBuffer cbuf = CharBuffer.allocate(expected.length());
+ isr.read(cbuf);
+ cbuf.rewind();
+ if (!cbuf.toString().equals(expected)) {
+ throw new RuntimeException("charset " + cs.name() + " (en)decoded the surrogate " + surrogate + " to " + cbuf.toString() + " which is not same as the expected " + expected);
+ }
+ }
+ }
}
}
diff --git a/test/sun/security/ec/InvalidCurve.java b/test/sun/security/ec/InvalidCurve.java
new file mode 100644
index 0000000000..9321c2617c
--- /dev/null
+++ b/test/sun/security/ec/InvalidCurve.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, 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 8182999
+ * @summary Ensure that SunEC behaves correctly for unsupported curves.
+ * @run main InvalidCurve
+ */
+
+import java.security.*;
+import java.security.spec.*;
+import java.math.*;
+
+public class InvalidCurve {
+
+ public static void main(String[] args) {
+
+ KeyPairGenerator keyGen;
+ try {
+ keyGen = KeyPairGenerator.getInstance("EC", "SunEC");
+ ECGenParameterSpec brainpoolSpec =
+ new ECGenParameterSpec("brainpoolP256r1");
+ keyGen.initialize(brainpoolSpec);
+ } catch (InvalidAlgorithmParameterException ex) {
+ System.out.println(ex.getMessage());
+ // this is expected
+ return;
+ } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
+ throw new RuntimeException(ex);
+ }
+
+ keyGen.generateKeyPair();
+
+ // If we make it to here, then the test is not working correctly.
+ throw new RuntimeException("The expected exception was not thrown.");
+
+ }
+
+}
+
diff --git a/test/sun/security/ec/SignatureDigestTruncate.java b/test/sun/security/ec/SignatureDigestTruncate.java
new file mode 100644
index 0000000000..a0ebbb2cf5
--- /dev/null
+++ b/test/sun/security/ec/SignatureDigestTruncate.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2019, 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 jdk.testlibrary.Convert;
+
+import java.security.*;
+import java.security.spec.*;
+import java.math.*;
+import java.util.*;
+
+/*
+ * @test
+ * @bug 8147502
+ * @summary Test that digests are properly truncated before the signature
+ * is applied. The digest should be truncated to the bit length of the
+ * group order.
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Convert
+ * @run main SignatureDigestTruncate
+ */
+public class SignatureDigestTruncate {
+
+ /*
+ * A SecureRandom that produces nextBytes in a way that causes the nonce
+ * to be set to the value supplied to the constructor. This class
+ * is specific to the way that the native ECDSA implementation in
+ * SunEC produces nonces from random input. It may not work for all
+ * test cases, and it will need to be updated when the behavior of
+ * SunEC changes.
+ */
+ private static class FixedRandom extends SecureRandom {
+
+ private final byte[] val;
+
+ public FixedRandom(byte[] val) {
+ // SunEC adds one to the value returned, so subtract one here in
+ // order to get back to the correct value.
+ BigInteger biVal = new BigInteger(1, val);
+ biVal = biVal.subtract(BigInteger.ONE);
+ byte[] temp = biVal.toByteArray();
+ this.val = new byte[val.length];
+ int inStartPos = Math.max(0, temp.length - val.length);
+ int outStartPos = Math.max(0, val.length - temp.length);
+ System.arraycopy(temp, inStartPos, this.val, outStartPos,
+ temp.length - inStartPos);
+ }
+
+ @Override
+ public void nextBytes(byte[] bytes) {
+ // SunEC samples (n + 1) * 2 bytes, but only n*2 bytes are used by
+ // the native implementation. So the value must be offset slightly.
+ Arrays.fill(bytes, (byte) 0);
+ int copyLength = Math.min(val.length, bytes.length - 2);
+ System.arraycopy(val, 0, bytes, bytes.length - copyLength - 2,
+ copyLength);
+ }
+ }
+
+ private static void assertEquals(byte[] expected, byte[] actual,
+ String name) {
+ if (!Arrays.equals(actual, expected)) {
+ System.out.println("expect: "
+ + Convert.byteArrayToHexString(expected));
+ System.out.println("actual: "
+ + Convert.byteArrayToHexString(actual));
+ throw new RuntimeException("Incorrect " + name + " value");
+ }
+ }
+
+ private static void runTest(String alg, String curveName,
+ String privateKeyStr, String msgStr, String kStr, String sigStr)
+ throws Exception {
+
+ byte[] privateKey = Convert.hexStringToByteArray(privateKeyStr);
+ byte[] msg = Convert.hexStringToByteArray(msgStr);
+ byte[] k = Convert.hexStringToByteArray(kStr);
+ byte[] expectedSig = Convert.hexStringToByteArray(sigStr);
+
+ AlgorithmParameters params = AlgorithmParameters.getInstance("EC");
+ params.init(new ECGenParameterSpec(curveName));
+ ECParameterSpec ecParams =
+ params.getParameterSpec(ECParameterSpec.class);
+
+ KeyFactory kf = KeyFactory.getInstance("EC");
+ BigInteger s = new BigInteger(1, privateKey);
+ ECPrivateKeySpec privKeySpec = new ECPrivateKeySpec(s, ecParams);
+ PrivateKey privKey = kf.generatePrivate(privKeySpec);
+
+ Signature sig = Signature.getInstance(alg);
+ sig.initSign(privKey, new FixedRandom(k));
+ sig.update(msg);
+ byte[] computedSig = sig.sign();
+ assertEquals(expectedSig, computedSig, "signature");
+ }
+
+ public static void main(String[] args) throws Exception {
+ runTest("SHA384withECDSA", "sect283r1",
+ "abcdef10234567", "010203040506070809",
+ "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d" +
+ "1e1f20212223",
+ "304c022401d7544b5d3935216bd45e2f8042537e1e0296a11e0eb9666619" +
+ "9281b40942abccd5358a0224035de8a314d3e6c2a97614daebf5fb131354" +
+ "0eec3f9a3272068aa10922ccae87d255c84c");
+ }
+}
diff --git a/test/sun/security/lib/cacerts/VerifyCACerts.java b/test/sun/security/lib/cacerts/VerifyCACerts.java
new file mode 100644
index 0000000000..585f1e9cc6
--- /dev/null
+++ b/test/sun/security/lib/cacerts/VerifyCACerts.java
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2017, 2019, 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 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779
+ * 8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137 8222136
+ * 8223499
+ * @summary Check root CA entries in cacerts file
+ */
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.KeyStore;
+import java.security.MessageDigest;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+public class VerifyCACerts {
+
+ private static final String CACERTS
+ = System.getProperty("java.home") + File.separator + "lib"
+ + File.separator + "security" + File.separator + "cacerts";
+
+ // The numbers of certs now.
+ private static final int COUNT = 88;
+
+ // map of cert alias to SHA-256 fingerprint
+ @SuppressWarnings("serial")
+ private static final Map<String, String> FINGERPRINT_MAP
+ = new HashMap<String, String>() {
+ {
+ put("actalisauthenticationrootca [jdk]",
+ "55:92:60:84:EC:96:3A:64:B9:6E:2A:BE:01:CE:0B:A8:6A:64:FB:FE:BC:C7:AA:B5:AF:C1:55:B3:7F:D7:60:66");
+ put("buypassclass2ca [jdk]",
+ "9A:11:40:25:19:7C:5B:B9:5D:94:E6:3D:55:CD:43:79:08:47:B6:46:B2:3C:DF:11:AD:A4:A0:0E:FF:15:FB:48");
+ put("buypassclass3ca [jdk]",
+ "ED:F7:EB:BC:A2:7A:2A:38:4D:38:7B:7D:40:10:C6:66:E2:ED:B4:84:3E:4C:29:B4:AE:1D:5B:93:32:E6:B2:4D");
+ put("camerfirmachambersca [jdk]",
+ "06:3E:4A:FA:C4:91:DF:D3:32:F3:08:9B:85:42:E9:46:17:D8:93:D7:FE:94:4E:10:A7:93:7E:E2:9D:96:93:C0");
+ put("camerfirmachambersignca [jdk]",
+ "13:63:35:43:93:34:A7:69:80:16:A0:D3:24:DE:72:28:4E:07:9D:7B:52:20:BB:8F:BD:74:78:16:EE:BE:BA:CA");
+ put("camerfirmachamberscommerceca [jdk]",
+ "0C:25:8A:12:A5:67:4A:EF:25:F2:8B:A7:DC:FA:EC:EE:A3:48:E5:41:E6:F5:CC:4E:E6:3B:71:B3:61:60:6A:C3");
+ put("certumca [jdk]",
+ "D8:E0:FE:BC:1D:B2:E3:8D:00:94:0F:37:D2:7D:41:34:4D:99:3E:73:4B:99:D5:65:6D:97:78:D4:D8:14:36:24");
+ put("certumtrustednetworkca [jdk]",
+ "5C:58:46:8D:55:F5:8E:49:7E:74:39:82:D2:B5:00:10:B6:D1:65:37:4A:CF:83:A7:D4:A3:2D:B7:68:C4:40:8E");
+ put("chunghwaepkirootca [jdk]",
+ "C0:A6:F4:DC:63:A2:4B:FD:CF:54:EF:2A:6A:08:2A:0A:72:DE:35:80:3E:2F:F5:FF:52:7A:E5:D8:72:06:DF:D5");
+ put("comodorsaca [jdk]",
+ "52:F0:E1:C4:E5:8E:C6:29:29:1B:60:31:7F:07:46:71:B8:5D:7E:A8:0D:5B:07:27:34:63:53:4B:32:B4:02:34");
+ put("comodoaaaca [jdk]",
+ "D7:A7:A0:FB:5D:7E:27:31:D7:71:E9:48:4E:BC:DE:F7:1D:5F:0C:3E:0A:29:48:78:2B:C8:3E:E0:EA:69:9E:F4");
+ put("comodoeccca [jdk]",
+ "17:93:92:7A:06:14:54:97:89:AD:CE:2F:8F:34:F7:F0:B6:6D:0F:3A:E3:A3:B8:4D:21:EC:15:DB:BA:4F:AD:C7");
+ put("usertrustrsaca [jdk]",
+ "E7:93:C9:B0:2F:D8:AA:13:E2:1C:31:22:8A:CC:B0:81:19:64:3B:74:9C:89:89:64:B1:74:6D:46:C3:D4:CB:D2");
+ put("usertrusteccca [jdk]",
+ "4F:F4:60:D5:4B:9C:86:DA:BF:BC:FC:57:12:E0:40:0D:2B:ED:3F:BC:4D:4F:BD:AA:86:E0:6A:DC:D2:A9:AD:7A");
+ put("utnuserfirstobjectca [jdk]",
+ "6F:FF:78:E4:00:A7:0C:11:01:1C:D8:59:77:C4:59:FB:5A:F9:6A:3D:F0:54:08:20:D0:F4:B8:60:78:75:E5:8F");
+ put("addtrustclass1ca [jdk]",
+ "8C:72:09:27:9A:C0:4E:27:5E:16:D0:7F:D3:B7:75:E8:01:54:B5:96:80:46:E3:1F:52:DD:25:76:63:24:E9:A7");
+ put("addtrustexternalca [jdk]",
+ "68:7F:A4:51:38:22:78:FF:F0:C8:B1:1F:8D:43:D5:76:67:1C:6E:B2:BC:EA:B4:13:FB:83:D9:65:D0:6D:2F:F2");
+ put("addtrustqualifiedca [jdk]",
+ "80:95:21:08:05:DB:4B:BC:35:5E:44:28:D8:FD:6E:C2:CD:E3:AB:5F:B9:7A:99:42:98:8E:B8:F4:DC:D0:60:16");
+ put("baltimorecybertrustca [jdk]",
+ "16:AF:57:A9:F6:76:B0:AB:12:60:95:AA:5E:BA:DE:F2:2A:B3:11:19:D6:44:AC:95:CD:4B:93:DB:F3:F2:6A:EB");
+ put("digicertglobalrootca [jdk]",
+ "43:48:A0:E9:44:4C:78:CB:26:5E:05:8D:5E:89:44:B4:D8:4F:96:62:BD:26:DB:25:7F:89:34:A4:43:C7:01:61");
+ put("digicertglobalrootg2 [jdk]",
+ "CB:3C:CB:B7:60:31:E5:E0:13:8F:8D:D3:9A:23:F9:DE:47:FF:C3:5E:43:C1:14:4C:EA:27:D4:6A:5A:B1:CB:5F");
+ put("digicertglobalrootg3 [jdk]",
+ "31:AD:66:48:F8:10:41:38:C7:38:F3:9E:A4:32:01:33:39:3E:3A:18:CC:02:29:6E:F9:7C:2A:C9:EF:67:31:D0");
+ put("digicerttrustedrootg4 [jdk]",
+ "55:2F:7B:DC:F1:A7:AF:9E:6C:E6:72:01:7F:4F:12:AB:F7:72:40:C7:8E:76:1A:C2:03:D1:D9:D2:0A:C8:99:88");
+ put("digicertassuredidrootca [jdk]",
+ "3E:90:99:B5:01:5E:8F:48:6C:00:BC:EA:9D:11:1E:E7:21:FA:BA:35:5A:89:BC:F1:DF:69:56:1E:3D:C6:32:5C");
+ put("digicertassuredidg2 [jdk]",
+ "7D:05:EB:B6:82:33:9F:8C:94:51:EE:09:4E:EB:FE:FA:79:53:A1:14:ED:B2:F4:49:49:45:2F:AB:7D:2F:C1:85");
+ put("digicertassuredidg3 [jdk]",
+ "7E:37:CB:8B:4C:47:09:0C:AB:36:55:1B:A6:F4:5D:B8:40:68:0F:BA:16:6A:95:2D:B1:00:71:7F:43:05:3F:C2");
+ put("digicerthighassuranceevrootca [jdk]",
+ "74:31:E5:F4:C3:C1:CE:46:90:77:4F:0B:61:E0:54:40:88:3B:A9:A0:1E:D0:0B:A6:AB:D7:80:6E:D3:B1:18:CF");
+ put("geotrustglobalca [jdk]",
+ "FF:85:6A:2D:25:1D:CD:88:D3:66:56:F4:50:12:67:98:CF:AB:AA:DE:40:79:9C:72:2D:E4:D2:B5:DB:36:A7:3A");
+ put("geotrustprimaryca [jdk]",
+ "37:D5:10:06:C5:12:EA:AB:62:64:21:F1:EC:8C:92:01:3F:C5:F8:2A:E9:8E:E5:33:EB:46:19:B8:DE:B4:D0:6C");
+ put("geotrustprimarycag2 [jdk]",
+ "5E:DB:7A:C4:3B:82:A0:6A:87:61:E8:D7:BE:49:79:EB:F2:61:1F:7D:D7:9B:F9:1C:1C:6B:56:6A:21:9E:D7:66");
+ put("geotrustprimarycag3 [jdk]",
+ "B4:78:B8:12:25:0D:F8:78:63:5C:2A:A7:EC:7D:15:5E:AA:62:5E:E8:29:16:E2:CD:29:43:61:88:6C:D1:FB:D4");
+ put("geotrustuniversalca [jdk]",
+ "A0:45:9B:9F:63:B2:25:59:F5:FA:5D:4C:6D:B3:F9:F7:2F:F1:93:42:03:35:78:F0:73:BF:1D:1B:46:CB:B9:12");
+ put("thawteprimaryrootca [jdk]",
+ "8D:72:2F:81:A9:C1:13:C0:79:1D:F1:36:A2:96:6D:B2:6C:95:0A:97:1D:B4:6B:41:99:F4:EA:54:B7:8B:FB:9F");
+ put("thawteprimaryrootcag2 [jdk]",
+ "A4:31:0D:50:AF:18:A6:44:71:90:37:2A:86:AF:AF:8B:95:1F:FB:43:1D:83:7F:1E:56:88:B4:59:71:ED:15:57");
+ put("thawteprimaryrootcag3 [jdk]",
+ "4B:03:F4:58:07:AD:70:F2:1B:FC:2C:AE:71:C9:FD:E4:60:4C:06:4C:F5:FF:B6:86:BA:E5:DB:AA:D7:FD:D3:4C");
+ put("thawtepremiumserverca [jdk]",
+ "3F:9F:27:D5:83:20:4B:9E:09:C8:A3:D2:06:6C:4B:57:D3:A2:47:9C:36:93:65:08:80:50:56:98:10:5D:BC:E9");
+ put("verisigntsaca [jdk]",
+ "CB:6B:05:D9:E8:E5:7C:D8:82:B1:0B:4D:B7:0D:E4:BB:1D:E4:2B:A4:8A:7B:D0:31:8B:63:5B:F6:E7:78:1A:9D");
+ put("verisignclass2g2ca [jdk]",
+ "3A:43:E2:20:FE:7F:3E:A9:65:3D:1E:21:74:2E:AC:2B:75:C2:0F:D8:98:03:05:BC:50:2C:AF:8C:2D:9B:41:A1");
+ put("verisignclass3ca [jdk]",
+ "A4:B6:B3:99:6F:C2:F3:06:B3:FD:86:81:BD:63:41:3D:8C:50:09:CC:4F:A3:29:C2:CC:F0:E2:FA:1B:14:03:05");
+ put("verisignclass3g2ca [jdk]",
+ "83:CE:3C:12:29:68:8A:59:3D:48:5F:81:97:3C:0F:91:95:43:1E:DA:37:CC:5E:36:43:0E:79:C7:A8:88:63:8B");
+ put("verisignuniversalrootca [jdk]",
+ "23:99:56:11:27:A5:71:25:DE:8C:EF:EA:61:0D:DF:2F:A0:78:B5:C8:06:7F:4E:82:82:90:BF:B8:60:E8:4B:3C");
+ put("verisignclass3g3ca [jdk]",
+ "EB:04:CF:5E:B1:F3:9A:FA:76:2F:2B:B1:20:F2:96:CB:A5:20:C1:B9:7D:B1:58:95:65:B8:1C:B9:A1:7B:72:44");
+ put("verisignclass3g4ca [jdk]",
+ "69:DD:D7:EA:90:BB:57:C9:3E:13:5D:C8:5E:A6:FC:D5:48:0B:60:32:39:BD:C4:54:FC:75:8B:2A:26:CF:7F:79");
+ put("verisignclass3g5ca [jdk]",
+ "9A:CF:AB:7E:43:C8:D8:80:D0:6B:26:2A:94:DE:EE:E4:B4:65:99:89:C3:D0:CA:F1:9B:AF:64:05:E4:1A:B7:DF");
+ put("keynectisrootca [jdk]",
+ "42:10:F1:99:49:9A:9A:C3:3C:8D:E0:2B:A6:DB:AA:14:40:8B:DD:8A:6E:32:46:89:C1:92:2D:06:97:15:A3:32");
+ put("dtrustclass3ca2 [jdk]",
+ "49:E7:A4:42:AC:F0:EA:62:87:05:00:54:B5:25:64:B6:50:E4:F4:9E:42:E3:48:D6:AA:38:E0:39:E9:57:B1:C1");
+ put("dtrustclass3ca2ev [jdk]",
+ "EE:C5:49:6B:98:8C:E9:86:25:B9:34:09:2E:EC:29:08:BE:D0:B0:F3:16:C2:D4:73:0C:84:EA:F1:F3:D3:48:81");
+ put("identrustdstx3 [jdk]",
+ "06:87:26:03:31:A7:24:03:D9:09:F1:05:E6:9B:CF:0D:32:E1:BD:24:93:FF:C6:D9:20:6D:11:BC:D6:77:07:39");
+ put("identrustpublicca [jdk]",
+ "30:D0:89:5A:9A:44:8A:26:20:91:63:55:22:D1:F5:20:10:B5:86:7A:CA:E1:2C:78:EF:95:8F:D4:F4:38:9F:2F");
+ put("identrustcommercial [jdk]",
+ "5D:56:49:9B:E4:D2:E0:8B:CF:CA:D0:8A:3E:38:72:3D:50:50:3B:DE:70:69:48:E4:2F:55:60:30:19:E5:28:AE");
+ put("letsencryptisrgx1 [jdk]",
+ "96:BC:EC:06:26:49:76:F3:74:60:77:9A:CF:28:C5:A7:CF:E8:A3:C0:AA:E1:1A:8F:FC:EE:05:C0:BD:DF:08:C6");
+ put("luxtrustglobalrootca [jdk]",
+ "A1:B2:DB:EB:64:E7:06:C6:16:9E:3C:41:18:B2:3B:AA:09:01:8A:84:27:66:6D:8B:F0:E2:88:91:EC:05:19:50");
+ put("quovadisrootca [jdk]",
+ "A4:5E:DE:3B:BB:F0:9C:8A:E1:5C:72:EF:C0:72:68:D6:93:A2:1C:99:6F:D5:1E:67:CA:07:94:60:FD:6D:88:73");
+ put("quovadisrootca1g3 [jdk]",
+ "8A:86:6F:D1:B2:76:B5:7E:57:8E:92:1C:65:82:8A:2B:ED:58:E9:F2:F2:88:05:41:34:B7:F1:F4:BF:C9:CC:74");
+ put("quovadisrootca2 [jdk]",
+ "85:A0:DD:7D:D7:20:AD:B7:FF:05:F8:3D:54:2B:20:9D:C7:FF:45:28:F7:D6:77:B1:83:89:FE:A5:E5:C4:9E:86");
+ put("quovadisrootca2g3 [jdk]",
+ "8F:E4:FB:0A:F9:3A:4D:0D:67:DB:0B:EB:B2:3E:37:C7:1B:F3:25:DC:BC:DD:24:0E:A0:4D:AF:58:B4:7E:18:40");
+ put("quovadisrootca3 [jdk]",
+ "18:F1:FC:7F:20:5D:F8:AD:DD:EB:7F:E0:07:DD:57:E3:AF:37:5A:9C:4D:8D:73:54:6B:F4:F1:FE:D1:E1:8D:35");
+ put("quovadisrootca3g3 [jdk]",
+ "88:EF:81:DE:20:2E:B0:18:45:2E:43:F8:64:72:5C:EA:5F:BD:1F:C2:D9:D2:05:73:07:09:C5:D8:B8:69:0F:46");
+ put("secomscrootca1 [jdk]",
+ "E7:5E:72:ED:9F:56:0E:EC:6E:B4:80:00:73:A4:3F:C3:AD:19:19:5A:39:22:82:01:78:95:97:4A:99:02:6B:6C");
+ put("secomscrootca2 [jdk]",
+ "51:3B:2C:EC:B8:10:D4:CD:E5:DD:85:39:1A:DF:C6:C2:DD:60:D8:7B:B7:36:D2:B5:21:48:4A:A4:7A:0E:BE:F6");
+ put("swisssigngoldg2ca [jdk]",
+ "62:DD:0B:E9:B9:F5:0A:16:3E:A0:F8:E7:5C:05:3B:1E:CA:57:EA:55:C8:68:8F:64:7C:68:81:F2:C8:35:7B:95");
+ put("swisssignplatinumg2ca [jdk]",
+ "3B:22:2E:56:67:11:E9:92:30:0D:C0:B1:5A:B9:47:3D:AF:DE:F8:C8:4D:0C:EF:7D:33:17:B4:C1:82:1D:14:36");
+ put("swisssignsilverg2ca [jdk]",
+ "BE:6C:4D:A2:BB:B9:BA:59:B6:F3:93:97:68:37:42:46:C3:C0:05:99:3F:A9:8F:02:0D:1D:ED:BE:D4:8A:81:D5");
+ put("soneraclass2ca [jdk]",
+ "79:08:B4:03:14:C1:38:10:0B:51:8D:07:35:80:7F:FB:FC:F8:51:8A:00:95:33:71:05:BA:38:6B:15:3D:D9:27");
+ put("securetrustca [jdk]",
+ "F1:C1:B5:0A:E5:A2:0D:D8:03:0E:C9:F6:BC:24:82:3D:D3:67:B5:25:57:59:B4:E7:1B:61:FC:E9:F7:37:5D:73");
+ put("xrampglobalca [jdk]",
+ "CE:CD:DC:90:50:99:D8:DA:DF:C5:B1:D2:09:B7:37:CB:E2:C1:8C:FB:2C:10:C0:FF:0B:CF:0D:32:86:FC:1A:A2");
+ put("godaddyrootg2ca [jdk]",
+ "45:14:0B:32:47:EB:9C:C8:C5:B4:F0:D7:B5:30:91:F7:32:92:08:9E:6E:5A:63:E2:74:9D:D3:AC:A9:19:8E:DA");
+ put("godaddyclass2ca [jdk]",
+ "C3:84:6B:F2:4B:9E:93:CA:64:27:4C:0E:C6:7C:1E:CC:5E:02:4F:FC:AC:D2:D7:40:19:35:0E:81:FE:54:6A:E4");
+ put("starfieldclass2ca [jdk]",
+ "14:65:FA:20:53:97:B8:76:FA:A6:F0:A9:95:8E:55:90:E4:0F:CC:7F:AA:4F:B7:C2:C8:67:75:21:FB:5F:B6:58");
+ put("starfieldrootg2ca [jdk]",
+ "2C:E1:CB:0B:F9:D2:F9:E1:02:99:3F:BE:21:51:52:C3:B2:DD:0C:AB:DE:1C:68:E5:31:9B:83:91:54:DB:B7:F5");
+ put("entrustrootcaec1 [jdk]",
+ "02:ED:0E:B2:8C:14:DA:45:16:5C:56:67:91:70:0D:64:51:D7:FB:56:F0:B2:AB:1D:3B:8E:B0:70:E5:6E:DF:F5");
+ put("entrust2048ca [jdk]",
+ "6D:C4:71:72:E0:1C:BC:B0:BF:62:58:0D:89:5F:E2:B8:AC:9A:D4:F8:73:80:1E:0C:10:B9:C8:37:D2:1E:B1:77");
+ put("entrustrootcag2 [jdk]",
+ "43:DF:57:74:B0:3E:7F:EF:5F:E4:0D:93:1A:7B:ED:F1:BB:2E:6B:42:73:8C:4E:6D:38:41:10:3D:3A:A7:F3:39");
+ put("entrustevca [jdk]",
+ "73:C1:76:43:4F:1B:C6:D5:AD:F4:5B:0E:76:E7:27:28:7C:8D:E5:76:16:C1:E6:E6:14:1A:2B:2C:BC:7D:8E:4C");
+ put("affirmtrustnetworkingca [jdk]",
+ "0A:81:EC:5A:92:97:77:F1:45:90:4A:F3:8D:5D:50:9F:66:B5:E2:C5:8F:CD:B5:31:05:8B:0E:17:F3:F0:B4:1B");
+ put("affirmtrustpremiumca [jdk]",
+ "70:A7:3F:7F:37:6B:60:07:42:48:90:45:34:B1:14:82:D5:BF:0E:69:8E:CC:49:8D:F5:25:77:EB:F2:E9:3B:9A");
+ put("affirmtrustcommercialca [jdk]",
+ "03:76:AB:1D:54:C5:F9:80:3C:E4:B2:E2:01:A0:EE:7E:EF:7B:57:B6:36:E8:A9:3C:9B:8D:48:60:C9:6F:5F:A7");
+ put("affirmtrustpremiumeccca [jdk]",
+ "BD:71:FD:F6:DA:97:E4:CF:62:D1:64:7A:DD:25:81:B0:7D:79:AD:F8:39:7E:B4:EC:BA:9C:5E:84:88:82:14:23");
+ put("ttelesecglobalrootclass3ca [jdk]",
+ "FD:73:DA:D3:1C:64:4F:F1:B4:3B:EF:0C:CD:DA:96:71:0B:9C:D9:87:5E:CA:7E:31:70:7A:F3:E9:6D:52:2B:BD");
+ put("ttelesecglobalrootclass2ca [jdk]",
+ "91:E2:F5:78:8D:58:10:EB:A7:BA:58:73:7D:E1:54:8A:8E:CA:CD:01:45:98:BC:0B:14:3E:04:1B:17:05:25:52");
+ put("starfieldservicesrootg2ca [jdk]",
+ "56:8D:69:05:A2:C8:87:08:A4:B3:02:51:90:ED:CF:ED:B1:97:4A:60:6A:13:C6:E5:29:0F:CB:2A:E6:3E:DA:B5");
+ put("globalsignca [jdk]",
+ "EB:D4:10:40:E4:BB:3E:C7:42:C9:E3:81:D3:1E:F2:A4:1A:48:B6:68:5C:96:E7:CE:F3:C1:DF:6C:D4:33:1C:99");
+ put("globalsignr3ca [jdk]",
+ "CB:B5:22:D7:B7:F1:27:AD:6A:01:13:86:5B:DF:1C:D4:10:2E:7D:07:59:AF:63:5A:7C:F4:72:0D:C9:63:C5:3B");
+ put("globalsigneccrootcar5 [jdk]",
+ "17:9F:BC:14:8A:3D:D0:0F:D2:4E:A1:34:58:CC:43:BF:A7:F5:9C:81:82:D7:83:A5:13:F6:EB:EC:10:0C:89:24");
+ put("globalsigneccrootcar4 [jdk]",
+ "BE:C9:49:11:C2:95:56:76:DB:6C:0A:55:09:86:D7:6E:3B:A0:05:66:7C:44:2C:97:62:B4:FB:B7:73:DE:22:8C");
+ put("globalsignr2ca [jdk]",
+ "CA:42:DD:41:74:5F:D0:B8:1E:B9:02:36:2C:F9:D8:BF:71:9D:A1:BD:1B:1E:FC:94:6F:5B:4C:99:F4:2C:1B:9E");
+ put("teliasonerarootcav1 [jdk]",
+ "DD:69:36:FE:21:F8:F0:77:C1:23:A1:A5:21:C1:22:24:F7:22:55:B7:3E:03:A7:26:06:93:E8:A2:4B:0F:A3:89");
+ put("globalsignrootcar6 [jdk]",
+ "2C:AB:EA:FE:37:D0:6C:A2:2A:BA:73:91:C0:03:3D:25:98:29:52:C4:53:64:73:49:76:3A:3A:B5:AD:6C:CF:69");
+ }
+ };
+
+ // Exception list to 90 days expiry policy
+ // No error will be reported if certificate in this list expires
+ @SuppressWarnings("serial")
+ private static final HashSet<String> EXPIRY_EXC_ENTRIES = new HashSet<String>() {
+ {
+ // Valid until: Tue Jul 09 14:40:36 EDT 2019
+ add("utnuserfirstobjectca [jdk]");
+ }
+ };
+
+ // Ninety days in milliseconds
+ private static final long NINETY_DAYS = 7776000000L;
+
+ private static boolean atLeastOneFailed = false;
+
+ private static MessageDigest md;
+
+ public static void main(String[] args) throws Exception {
+ System.out.println("cacerts file: " + CACERTS);
+ md = MessageDigest.getInstance("SHA-256");
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new FileInputStream(CACERTS), "changeit".toCharArray());
+
+ // check the count of certs inside
+ if (ks.size() != COUNT) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: " + ks.size() + " entries, should be "
+ + COUNT);
+ }
+
+ // check that all entries in the map are in the keystore
+ for (String alias : FINGERPRINT_MAP.keySet()) {
+ if (!ks.isCertificateEntry(alias)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: " + alias + " is not in cacerts");
+ }
+ }
+
+ // pull all the trusted self-signed CA certs out of the cacerts file
+ // and verify their signatures
+ Enumeration<String> aliases = ks.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ System.out.println("\nVerifying " + alias);
+ if (!ks.isCertificateEntry(alias)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: " + alias
+ + " is not a trusted cert entry");
+ }
+ X509Certificate cert = (X509Certificate) ks.getCertificate(alias);
+ if (!checkFingerprint(alias, cert)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: " + alias + " SHA-256 fingerprint is incorrect");
+ }
+ // Make sure cert can be self-verified
+ try {
+ cert.verify(cert.getPublicKey());
+ } catch (Exception e) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: cert cannot be verified:"
+ + e.getMessage());
+ }
+
+ // Make sure cert is not expired or not yet valid
+ try {
+ cert.checkValidity();
+ } catch (CertificateExpiredException cee) {
+ if (!EXPIRY_EXC_ENTRIES.contains(alias)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: cert is expired");
+ }
+ } catch (CertificateNotYetValidException cne) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: cert is not yet valid");
+ }
+
+ // If cert is within 90 days of expiring, mark as failure so
+ // that cert can be scheduled to be removed/renewed.
+ Date notAfter = cert.getNotAfter();
+ if (notAfter.getTime() - System.currentTimeMillis() < NINETY_DAYS) {
+ if (!EXPIRY_EXC_ENTRIES.contains(alias)) {
+ atLeastOneFailed = true;
+ System.err.println("ERROR: cert \"" + alias + "\" expiry \""
+ + notAfter.toString() + "\" will expire within 90 days");
+ }
+ }
+ }
+
+ if (atLeastOneFailed) {
+ throw new Exception("At least one cacert test failed");
+ }
+ }
+
+ private static boolean checkFingerprint(String alias, Certificate cert)
+ throws Exception {
+ String fingerprint = FINGERPRINT_MAP.get(alias);
+ if (fingerprint == null) {
+ // no entry for alias
+ return true;
+ }
+ System.out.println("Checking fingerprint of " + alias);
+ byte[] digest = md.digest(cert.getEncoded());
+ return fingerprint.equals(toHexString(digest));
+ }
+
+ private static String toHexString(byte[] block) {
+ StringBuilder buf = new StringBuilder();
+ int len = block.length;
+ for (int i = 0; i < len; i++) {
+ buf.append(String.format("%02X", block[i]));
+ if (i < len - 1) {
+ buf.append(":");
+ }
+ }
+ return buf.toString();
+ }
+}
diff --git a/test/sun/security/rsa/SpecTest.java b/test/sun/security/rsa/SpecTest.java
index d2ab0a8e79..7b3c52e5d1 100644
--- a/test/sun/security/rsa/SpecTest.java
+++ b/test/sun/security/rsa/SpecTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -20,31 +20,31 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
-import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.interfaces.RSAKey;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAKeyGenParameterSpec;
/**
* @test
- * @bug 8044199
+ * @bug 8044199 8137231
* @summary Check same KeyPair's private key and public key have same modulus.
- * also check public key's public exponent equals to given spec's public
- * exponent.
+ * also check public key's public exponent equals to given spec's public
+ * exponent. Only key size 1024 is tested with RSAKeyGenParameterSpec.F0 (3).
* @run main SpecTest 512
* @run main SpecTest 768
* @run main SpecTest 1024
+ * @run main SpecTest 1024 3
* @run main SpecTest 2048
* @run main/timeout=240 SpecTest 4096
* @run main/timeout=240 SpecTest 5120
*/
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.RSAKeyGenParameterSpec;
+
public class SpecTest {
+
/**
* ALGORITHM name, fixed as RSA.
*/
@@ -69,14 +69,14 @@ public class SpecTest {
// test the getModulus method
if ((priv instanceof RSAKey) && (pub instanceof RSAKey)) {
if (!priv.getModulus().equals(pub.getModulus())) {
- System.err.println("priv.getModulus() = " + priv.getModulus());
- System.err.println("pub.getModulus() = " + pub.getModulus());
+ System.out.println("priv.getModulus() = " + priv.getModulus());
+ System.out.println("pub.getModulus() = " + pub.getModulus());
passed = false;
}
if (!pubExponent.equals(pub.getPublicExponent())) {
- System.err.println("pubExponent = " + pubExponent);
- System.err.println("pub.getPublicExponent() = "
+ System.out.println("pubExponent = " + pubExponent);
+ System.out.println("pub.getPublicExponent() = "
+ pub.getPublicExponent());
passed = false;
}
@@ -84,36 +84,26 @@ public class SpecTest {
return passed;
}
- public static void main(String[] args) {
- int failCount = 0;
+ public static void main(String[] args) throws Exception {
- // Test key size.
- int size = Integer.parseInt(args[0]);
+ int size = 0;
- try {
- KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
- kpg1.initialize(new RSAKeyGenParameterSpec(size,
- RSAKeyGenParameterSpec.F4));
- if (!specTest(kpg1.generateKeyPair(),
- RSAKeyGenParameterSpec.F4)) {
- failCount++;
- }
-
- KeyPairGenerator kpg2 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
- kpg2.initialize(new RSAKeyGenParameterSpec(size,
- RSAKeyGenParameterSpec.F0));
- if (!specTest(kpg2.generateKeyPair(), RSAKeyGenParameterSpec.F0)) {
- failCount++;
- }
- } catch (NoSuchAlgorithmException | NoSuchProviderException
- | InvalidAlgorithmParameterException ex) {
- ex.printStackTrace(System.err);
- failCount++;
+ if (args.length >= 1) {
+ size = Integer.parseInt(args[0]);
+ } else {
+ throw new RuntimeException("Missing keysize to test with");
}
- if (failCount != 0) {
- throw new RuntimeException("There are " + failCount
- + " tests failed.");
+ BigInteger publicExponent
+ = (args.length >= 2) ? new BigInteger(args[1]) : RSAKeyGenParameterSpec.F4;
+
+ System.out.println("Running test with key size: " + size
+ + " and public exponent: " + publicExponent);
+
+ KeyPairGenerator kpg1 = KeyPairGenerator.getInstance(KEYALG, PROVIDER);
+ kpg1.initialize(new RSAKeyGenParameterSpec(size, publicExponent));
+ if (!specTest(kpg1.generateKeyPair(), publicExponent)) {
+ throw new RuntimeException("Test failed.");
}
}
}
diff --git a/test/sun/security/ssl/SSLContextImpl/DefautlCacheSize.java b/test/sun/security/ssl/SSLContextImpl/DefautlCacheSize.java
new file mode 100644
index 0000000000..184db8f930
--- /dev/null
+++ b/test/sun/security/ssl/SSLContextImpl/DefautlCacheSize.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, 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 8210985
+ * @summary Update the default SSL session cache size to 20480
+ * @run main/othervm DefautlCacheSize
+ */
+
+// The SunJSSE provider cannot use System Properties in samevm/agentvm mode.
+// Please run JSSE test in othervm mode.
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSessionContext;
+
+public class DefautlCacheSize {
+
+ public static void main(String[] args) throws Exception {
+ SSLServerSocketFactory sssf =
+ (SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
+
+ try (SSLServerSocket serverSocket =
+ (SSLServerSocket)sssf.createServerSocket()) {
+
+ String[] protocols = serverSocket.getSupportedProtocols();
+ for (int i = 0; i < protocols.length; i++) {
+ if (protocols[i].equals("SSLv2Hello")) {
+ continue;
+ }
+ SSLContext sslContext = SSLContext.getInstance(protocols[i]);
+ SSLSessionContext sessionContext =
+ sslContext.getServerSessionContext();
+ if (sessionContext.getSessionCacheSize() == 0) {
+ throw new Exception(
+ "the default server session cache size is infinite");
+ }
+
+ sessionContext = sslContext.getClientSessionContext();
+ if (sessionContext.getSessionCacheSize() == 0) {
+ throw new Exception(
+ "the default client session cache size is infinite");
+ }
+ }
+ }
+ }
+}
diff --git a/test/sun/security/ssl/SessionIdCollisionTest.java b/test/sun/security/ssl/SessionIdCollisionTest.java
new file mode 100644
index 0000000000..16582f4e07
--- /dev/null
+++ b/test/sun/security/ssl/SessionIdCollisionTest.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2019, Red Hat Inc. 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.reflect.Constructor;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @test
+ * @bug 8203190
+ * @summary Manual test to verify number of collisions in
+ * sun.security.ssl.SessionId.hashCode()
+ * @run main/manual SessionIdCollisionTest 100 20480 10000000
+ */
+
+/**
+ *
+ * Notes:
+ * - This is a manual test, not run automatically.
+ * - New default value of javax.net.ssl.sessionCacheSize in JDK 12+ is 20480
+ * - According to JDK-8210985 24 hours expired cache may exceed several million
+ * entries = > 10_000_000
+ *
+ * Example usage: java SessionIdCollissionTest 100 20480 10000000
+ *
+ * Expected outcome of running the test is to see fewer collisions and, more
+ * importantly fewer elements in buckets when there are collisions. See:
+ * http://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-May/009345.html
+ *
+ */
+public class SessionIdCollisionTest {
+
+ private List<Integer> prepareHashCodes(int total) throws Exception {
+ Class<?> sessionIdClass = Class.forName("sun.security.ssl.SessionId");
+ Constructor<?> c = sessionIdClass.getDeclaredConstructor(byte[].class);
+ c.setAccessible(true);
+ // case of rejoinable session ids generates 32 random bytes
+ byte[] sessionIdBytes = new byte[32];
+ List<Integer> hashCodes = new ArrayList<>();
+ for (int i = 0; i < total; i++) {
+ SecureRandom random = new SecureRandom();
+ random.nextBytes(sessionIdBytes);
+ Object sessionId = c.newInstance(sessionIdBytes);
+ int hashCode = sessionId.hashCode();
+ hashCodes.add(hashCode);
+ }
+ return hashCodes;
+ }
+
+ private void printSummary(boolean withDistribution,
+ List<Integer> hashCodes) throws Exception {
+ final int bound = hashCodes.size();
+ Collections.sort(hashCodes);
+ int collisions = 0;
+ Map<Integer, List<Integer>> collCountsReverse = new HashMap<>();
+ for (int i = 0; i < bound - 1; i++) {
+ int oldval = hashCodes.get(i);
+ int nextval = hashCodes.get(i+1);
+ if (oldval == nextval) {
+ collisions++;
+ if (i == bound - 2) { // last elements
+ updateCollCountsReverse(collisions, collCountsReverse, oldval);
+ }
+ } else {
+ updateCollCountsReverse(collisions, collCountsReverse, oldval);
+ collisions = 0;
+ if (i == bound - 2) { // last elements
+ updateCollCountsReverse(collisions, collCountsReverse, nextval);
+ }
+ }
+ }
+ if (withDistribution) {
+ System.out.println("---- distribution ----");
+ }
+ int collCount = 0;
+ int maxLength = 0;
+ List<Integer> sorted = new ArrayList<>(collCountsReverse.size());
+ sorted.addAll(collCountsReverse.keySet());
+ Collections.sort(sorted);
+ for (Integer coll: sorted) {
+ List<Integer> hc = collCountsReverse.get(coll);
+ if (withDistribution) {
+ System.out.printf("Hashcodes with %02d collisions | " +
+ "hashCodes: %s\n", coll, hc.toString());
+ }
+ collCount += coll * hc.size();
+ if (coll > maxLength) {
+ maxLength = coll;
+ }
+ }
+ if (withDistribution) {
+ System.out.println("---- distribution ----");
+ }
+ System.out.println("Total number of collisions: " + collCount);
+ if (collCount > 0) {
+ System.out.println("Max length of collision list over all buckets: " +
+ maxLength);
+ }
+ }
+
+ private void updateCollCountsReverse(int collisions,
+ Map<Integer, List<Integer>> reverse, int val) {
+ List<Integer> hc = reverse.get(collisions);
+ if (hc == null) {
+ hc = new ArrayList<>();
+ hc.add(val);
+ reverse.put(collisions, hc);
+ } else {
+ hc.add(val);
+ }
+ }
+
+ public void doCollissionTest(int total) throws Exception {
+ System.out.println("Collision test for " + total + " sessions:");
+ System.out.println("------------------------------------------------");
+ List<Integer> hashcodes = prepareHashCodes(total);
+ printSummary(false, hashcodes);
+ System.out.println();
+ }
+
+ public static void main(String[] args) throws Exception {
+ if (args.length < 1) {
+ System.err.println("java " + SessionIdCollisionTest.class.getSimpleName() +
+ "<num-sessions> [<num-sessions> ...]");
+ System.exit(1);
+ }
+ SessionIdCollisionTest collTest = new SessionIdCollisionTest();
+ for (int i = 0; i < args.length; i++) {
+ int total = Integer.parseInt(args[i]);
+ collTest.doCollissionTest(total);
+ }
+ }
+
+}
diff --git a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java
index 93355acf93..b4eee2eeb1 100644
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLContextImpl/BadTSProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -21,18 +21,21 @@
* questions.
*/
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
/*
* @test
* @bug 4919147
* @summary Support for token-based KeyStores
* @run main/othervm BadTSProvider
- *
- * SunJSSE does not support dynamic system properties, no way to re-use
- * system properties in samevm/agentvm mode.
*/
import java.io.*;
import java.net.*;
+import java.security.*;
import javax.net.ssl.*;
public class BadTSProvider {
@@ -179,13 +182,19 @@ public class BadTSProvider {
// XXX this test must be updated if the exception message changes
Throwable cause = se.getCause();
- if (cause instanceof java.security.NoSuchAlgorithmException == false) {
+ if (!(cause instanceof NoSuchAlgorithmException)) {
+ se.printStackTrace();
+ throw new Exception("Unexpected exception" + se);
+ }
+
+ cause = cause.getCause();
+ if (!(cause instanceof KeyStoreException)) {
se.printStackTrace();
throw new Exception("Unexpected exception" + se);
}
cause = cause.getCause();
- if (cause instanceof java.security.NoSuchProviderException == false) {
+ if (!(cause instanceof NoSuchProviderException)) {
se.printStackTrace();
throw new Exception("Unexpected exception" + se);
}
diff --git a/test/sun/security/util/math/BigIntegerModuloP.java b/test/sun/security/util/math/BigIntegerModuloP.java
new file mode 100644
index 0000000000..55498c95b0
--- /dev/null
+++ b/test/sun/security/util/math/BigIntegerModuloP.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import sun.security.util.math.*;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Optional;
+
+/**
+ * Arithmetic in the field of integers modulo a prime value implemented using
+ * BigInteger. This implementation is very versatile, but it is slow and none
+ * of the operations are value-independent. This class is intended for use in
+ * testing and prototyping, and production code should probably use a more
+ * specialized arithmetic implementation.
+ */
+
+public class BigIntegerModuloP implements IntegerFieldModuloP {
+
+ private final BigInteger p;
+
+ public BigIntegerModuloP(BigInteger p) {
+ this.p = p;
+ }
+
+ @Override
+ public BigInteger getSize() {
+ return p;
+ }
+
+ @Override
+ public ImmutableElement get0() {
+ return new ImmutableElement(BigInteger.ZERO);
+ }
+ @Override
+ public ImmutableElement get1() {
+ return new ImmutableElement(BigInteger.ONE);
+ }
+ @Override
+ public ImmutableElement getElement(BigInteger v) {
+ return new ImmutableElement(v);
+ }
+ @Override
+ public ImmutableElement getElement(byte[] v, int offset, int length,
+ byte highByte) {
+ byte[] bigIntIn = new byte[length + 1];
+ System.arraycopy(v, offset, bigIntIn, 0, length);
+ bigIntIn[length] = highByte;
+ reverse(bigIntIn);
+ return new ImmutableElement(new BigInteger(1, bigIntIn).mod(getSize()));
+ }
+ @Override
+ public SmallValue getSmallValue(int i) {
+ return new SmallElement(i);
+ }
+
+ private abstract class Element implements IntegerModuloP {
+
+ protected BigInteger v;
+
+ protected Element(BigInteger v) {
+ this.v = v;
+ }
+
+ protected Element(boolean v) {
+ this.v = BigInteger.valueOf(v ? 1 : 0);
+ }
+
+ private BigInteger getModulus() {
+ return getField().getSize();
+ }
+
+ @Override
+ public IntegerFieldModuloP getField() {
+ return BigIntegerModuloP.this;
+ }
+
+ @Override
+ public BigInteger asBigInteger() {
+ return v;
+ }
+
+ @Override
+ public MutableElement mutable() {
+ return new MutableElement(v);
+ }
+
+ @Override
+ public ImmutableElement fixed() {
+ return new ImmutableElement(v);
+ }
+
+ @Override
+ public ImmutableElement add(IntegerModuloP b) {
+ return new ImmutableElement(
+ v.add(b.asBigInteger()).mod(getModulus()));
+ }
+
+ @Override
+ public ImmutableElement additiveInverse() {
+ return new ImmutableElement(v.negate().mod(getModulus()));
+ }
+
+ @Override
+ public ImmutableElement multiply(IntegerModuloP b) {
+ return new ImmutableElement(
+ v.multiply(b.asBigInteger()).mod(getModulus()));
+ }
+
+ @Override
+ public void addModPowerTwo(IntegerModuloP arg, byte[] result) {
+ BigInteger biThis = asBigInteger();
+ BigInteger biArg = arg.asBigInteger();
+ bigIntAsByteArray(biThis.add(biArg), result);
+ }
+
+ private void bigIntAsByteArray(BigInteger arg, byte[] result) {
+ byte[] bytes = arg.toByteArray();
+ // bytes is backwards and possibly too big
+ // Copy the low-order bytes into result in reverse
+ int sourceIndex = bytes.length - 1;
+ for (int i = 0; i < result.length; i++) {
+ if (sourceIndex >= 0) {
+ result[i] = bytes[sourceIndex--];
+ } else {
+ result[i] = 0;
+ }
+ }
+ }
+
+ @Override
+ public void asByteArray(byte[] result) {
+ bigIntAsByteArray(v, result);
+ }
+ }
+
+ private class ImmutableElement extends Element
+ implements ImmutableIntegerModuloP {
+
+ private ImmutableElement(BigInteger v) {
+ super(v);
+ }
+ }
+
+ private class MutableElement extends Element
+ implements MutableIntegerModuloP {
+
+ private MutableElement(BigInteger v) {
+ super(v);
+ }
+
+ @Override
+ public void conditionalSet(IntegerModuloP b, int set) {
+ if (set == 1) {
+ v = b.asBigInteger();
+ }
+ }
+
+ @Override
+ public void conditionalSwapWith(MutableIntegerModuloP b, int swap) {
+ if (swap == 1) {
+ BigInteger temp = v;
+ v = b.asBigInteger();
+ ((Element) b).v = temp;
+ }
+ }
+
+ @Override
+ public MutableElement setValue(IntegerModuloP v) {
+ this.v = ((Element) v).v;
+
+ return this;
+ }
+
+ @Override
+ public MutableElement setValue(byte[] arr, int offset, int length,
+ byte highByte) {
+ byte[] bigIntIn = new byte[length + 1];
+ System.arraycopy(arr, offset, bigIntIn, 0, length);
+ bigIntIn[length] = highByte;
+ reverse(bigIntIn);
+ v = new BigInteger(bigIntIn).mod(getSize());
+
+ return this;
+ }
+
+ @Override
+ public MutableElement setValue(ByteBuffer buf, int length,
+ byte highByte) {
+ byte[] bigIntIn = new byte[length + 1];
+ buf.get(bigIntIn, 0, length);
+ bigIntIn[length] = highByte;
+ reverse(bigIntIn);
+ v = new BigInteger(bigIntIn).mod(getSize());
+
+ return this;
+ }
+
+ @Override
+ public MutableElement setSquare() {
+ v = v.multiply(v).mod(getSize());
+ return this;
+ }
+
+ @Override
+ public MutableElement setProduct(IntegerModuloP b) {
+ Element other = (Element) b;
+ v = v.multiply(other.v).mod(getSize());
+ return this;
+ }
+
+ @Override
+ public MutableElement setProduct(SmallValue value) {
+ BigInteger bigIntValue = ((SmallElement) value).asBigInteger();
+ v = v.multiply(bigIntValue).mod(getSize());
+ return this;
+ }
+
+ @Override
+ public MutableElement setSum(IntegerModuloP b) {
+ Element other = (Element) b;
+ v = v.add(other.v).mod(getSize());
+ return this;
+ }
+
+ @Override
+ public MutableElement setDifference(IntegerModuloP b) {
+ Element other = (Element) b;
+ v = v.subtract(other.v).mod(getSize());
+ return this;
+ }
+
+ @Override
+ public MutableElement setAdditiveInverse() {
+ v = BigInteger.ZERO.subtract(v);
+ return this;
+ }
+
+ @Override
+ public MutableElement setReduced() {
+ // do nothing
+ return this;
+ }
+
+ }
+
+ private class SmallElement extends ImmutableElement implements SmallValue {
+
+ public SmallElement(int v) {
+ super(BigInteger.valueOf(v).mod(getSize()));
+ }
+ }
+
+ private static void swap(byte[] arr, int i, int j) {
+ byte tmp = arr[i];
+ arr[i] = arr[j];
+ arr[j] = tmp;
+ }
+
+ private static void reverse(byte [] arr) {
+ int i = 0;
+ int j = arr.length - 1;
+
+ while (i < j) {
+ swap(arr, i, j);
+ i++;
+ j--;
+ }
+ }
+
+}
diff --git a/test/sun/security/util/math/TestIntegerModuloP.java b/test/sun/security/util/math/TestIntegerModuloP.java
new file mode 100644
index 0000000000..b9fc6e3b58
--- /dev/null
+++ b/test/sun/security/util/math/TestIntegerModuloP.java
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2018, 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 8181594 8208648
+ * @summary Test proper operation of integer field arithmetic
+ * @modules java.base/sun.security.util java.base/sun.security.util.math java.base/sun.security.util.math.intpoly
+ * @build BigIntegerModuloP
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial25519 32 0
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial448 56 1
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomial1305 16 2
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP256 32 5
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP384 48 6
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.IntegerPolynomialP521 66 7
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P256OrderField 32 8
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P384OrderField 48 9
+ * @run main TestIntegerModuloP sun.security.util.math.intpoly.P521OrderField 66 10
+ */
+
+import sun.security.util.math.*;
+import sun.security.util.math.intpoly.*;
+import java.util.function.*;
+
+import java.util.*;
+import java.math.*;
+import java.nio.*;
+
+public class TestIntegerModuloP {
+
+ static BigInteger TWO = BigInteger.valueOf(2);
+
+ // The test has a list of functions, and it selects randomly from that list
+
+ // The function types
+ interface ElemFunction extends BiFunction
+ <MutableIntegerModuloP, IntegerModuloP, IntegerModuloP> { }
+ interface ElemArrayFunction extends BiFunction
+ <MutableIntegerModuloP, IntegerModuloP, byte[]> { }
+ interface TriConsumer <T, U, V> {
+ void accept(T t, U u, V v);
+ }
+ interface ElemSetFunction extends TriConsumer
+ <MutableIntegerModuloP, IntegerModuloP, byte[]> { }
+
+ // The lists of functions. Multiple lists are needed because the test
+ // respects the limitations of the arithmetic implementations.
+ static final List<ElemFunction> ADD_FUNCTIONS = new ArrayList<>();
+ static final List<ElemFunction> MULT_FUNCTIONS = new ArrayList<>();
+ static final List<ElemArrayFunction> ARRAY_FUNCTIONS = new ArrayList<>();
+ static final List<ElemSetFunction> SET_FUNCTIONS = new ArrayList<>();
+
+ static void setUpFunctions(IntegerFieldModuloP field, int length) {
+
+ ADD_FUNCTIONS.clear();
+ MULT_FUNCTIONS.clear();
+ SET_FUNCTIONS.clear();
+ ARRAY_FUNCTIONS.clear();
+
+ byte highByte = (byte)
+ (field.getSize().bitLength() > length * 8 ? 1 : 0);
+
+ // add functions are (im)mutable add/subtract
+ ADD_FUNCTIONS.add(IntegerModuloP::add);
+ ADD_FUNCTIONS.add(IntegerModuloP::subtract);
+ ADD_FUNCTIONS.add(MutableIntegerModuloP::setSum);
+ ADD_FUNCTIONS.add(MutableIntegerModuloP::setDifference);
+ // also include functions that return the first/second argument
+ ADD_FUNCTIONS.add((a, b) -> a);
+ ADD_FUNCTIONS.add((a, b) -> b);
+
+ // mult functions are (im)mutable multiply and square
+ MULT_FUNCTIONS.add(IntegerModuloP::multiply);
+ MULT_FUNCTIONS.add((a, b) -> a.square());
+ MULT_FUNCTIONS.add((a, b) -> b.square());
+ MULT_FUNCTIONS.add(MutableIntegerModuloP::setProduct);
+ MULT_FUNCTIONS.add((a, b) -> a.setSquare());
+ // also test multiplication by a small value
+ MULT_FUNCTIONS.add((a, b) -> a.setProduct(b.getField().getSmallValue(
+ b.asBigInteger().mod(BigInteger.valueOf(262144)).intValue())));
+
+ // set functions are setValue with various argument types
+ SET_FUNCTIONS.add((a, b, c) -> a.setValue(b));
+ SET_FUNCTIONS.add((a, b, c) ->
+ a.setValue(c, 0, c.length, (byte) 0));
+ SET_FUNCTIONS.add((a, b, c) ->
+ a.setValue(ByteBuffer.wrap(c, 0, c.length).order(ByteOrder.LITTLE_ENDIAN),
+ c.length, highByte));
+
+ // array functions return the (possibly modified) value as byte array
+ ARRAY_FUNCTIONS.add((a, b ) -> a.asByteArray(length));
+ ARRAY_FUNCTIONS.add((a, b) -> a.addModPowerTwo(b, length));
+ }
+
+ public static void main(String[] args) {
+
+ String className = args[0];
+ final int length = Integer.parseInt(args[1]);
+ int seed = Integer.parseInt(args[2]);
+
+ Class<IntegerFieldModuloP> fieldBaseClass = IntegerFieldModuloP.class;
+ try {
+ Class<? extends IntegerFieldModuloP> clazz =
+ Class.forName(className).asSubclass(fieldBaseClass);
+ IntegerFieldModuloP field =
+ clazz.getDeclaredConstructor().newInstance();
+
+ setUpFunctions(field, length);
+
+ runFieldTest(field, length, seed);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ System.out.println("All tests passed");
+ }
+
+ static void assertEqual(IntegerModuloP e1, IntegerModuloP e2) {
+
+ if (!e1.asBigInteger().equals(e2.asBigInteger())) {
+ throw new RuntimeException("values not equal: "
+ + e1.asBigInteger() + " != " + e2.asBigInteger());
+ }
+ }
+
+ // A class that holds pairs of actual/expected values, and allows
+ // computation on these pairs.
+ static class TestPair<T extends IntegerModuloP> {
+ private final T test;
+ private final T baseline;
+
+ public TestPair(T test, T baseline) {
+ this.test = test;
+ this.baseline = baseline;
+ }
+
+ public T getTest() {
+ return test;
+ }
+ public T getBaseline() {
+ return baseline;
+ }
+
+ private void assertEqual() {
+ TestIntegerModuloP.assertEqual(test, baseline);
+ }
+
+ public TestPair<MutableIntegerModuloP> mutable() {
+ return new TestPair<>(test.mutable(), baseline.mutable());
+ }
+
+ public
+ <R extends IntegerModuloP, X extends IntegerModuloP>
+ TestPair<X> apply(BiFunction<T, R, X> func, TestPair<R> right) {
+ X testResult = func.apply(test, right.test);
+ X baselineResult = func.apply(baseline, right.baseline);
+ return new TestPair(testResult, baselineResult);
+ }
+
+ public
+ <U extends IntegerModuloP, V>
+ void apply(TriConsumer<T, U, V> func, TestPair<U> right, V argV) {
+ func.accept(test, right.test, argV);
+ func.accept(baseline, right.baseline, argV);
+ }
+
+ public
+ <R extends IntegerModuloP>
+ void applyAndCheckArray(BiFunction<T, R, byte[]> func,
+ TestPair<R> right) {
+ byte[] testResult = func.apply(test, right.test);
+ byte[] baselineResult = func.apply(baseline, right.baseline);
+ if (!Arrays.equals(testResult, baselineResult)) {
+ throw new RuntimeException("Array values do not match: "
+ + byteArrayToHexString(testResult) + " != "
+ + byteArrayToHexString(baselineResult));
+ }
+ }
+
+ }
+
+ static String byteArrayToHexString(byte[] arr) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < arr.length; ++i) {
+ byte curVal = arr[i];
+ result.append(Character.forDigit(curVal >> 4 & 0xF, 16));
+ result.append(Character.forDigit(curVal & 0xF, 16));
+ }
+ return result.toString();
+ }
+
+ static TestPair<IntegerModuloP>
+ applyAndCheck(ElemFunction func, TestPair<MutableIntegerModuloP> left,
+ TestPair<IntegerModuloP> right) {
+
+ TestPair<IntegerModuloP> result = left.apply(func, right);
+ result.assertEqual();
+ left.assertEqual();
+ right.assertEqual();
+
+ return result;
+ }
+
+ static void
+ setAndCheck(ElemSetFunction func, TestPair<MutableIntegerModuloP> left,
+ TestPair<IntegerModuloP> right, byte[] argV) {
+
+ left.apply(func, right, argV);
+ left.assertEqual();
+ right.assertEqual();
+ }
+
+ static TestPair<MutableIntegerModuloP>
+ applyAndCheckMutable(ElemFunction func,
+ TestPair<MutableIntegerModuloP> left,
+ TestPair<IntegerModuloP> right) {
+
+ TestPair<IntegerModuloP> result = applyAndCheck(func, left, right);
+
+ TestPair<MutableIntegerModuloP> mutableResult = result.mutable();
+ mutableResult.assertEqual();
+ result.assertEqual();
+ left.assertEqual();
+ right.assertEqual();
+
+ return mutableResult;
+ }
+
+ static void
+ cswapAndCheck(int swap, TestPair<MutableIntegerModuloP> left,
+ TestPair<MutableIntegerModuloP> right) {
+
+ left.getTest().conditionalSwapWith(right.getTest(), swap);
+ left.getBaseline().conditionalSwapWith(right.getBaseline(), swap);
+
+ left.assertEqual();
+ right.assertEqual();
+
+ }
+
+ // Request arithmetic that should overflow, and ensure that overflow is
+ // detected.
+ static void runOverflowTest(TestPair<IntegerModuloP> elem) {
+
+ TestPair<MutableIntegerModuloP> mutableElem = elem.mutable();
+
+ try {
+ for (int i = 0; i < 1000; i++) {
+ applyAndCheck(MutableIntegerModuloP::setSum, mutableElem, elem);
+ }
+ applyAndCheck(MutableIntegerModuloP::setProduct, mutableElem, elem);
+ } catch (ArithmeticException ex) {
+ // this is expected
+ }
+
+ mutableElem = elem.mutable();
+ try {
+ for (int i = 0; i < 1000; i++) {
+ elem = applyAndCheck(IntegerModuloP::add,
+ mutableElem, elem);
+ }
+ applyAndCheck(IntegerModuloP::multiply, mutableElem, elem);
+ } catch (ArithmeticException ex) {
+ // this is expected
+ }
+ }
+
+ // Run a large number of random operations and ensure that
+ // results are correct
+ static void runOperationsTest(Random random, int length,
+ TestPair<IntegerModuloP> elem,
+ TestPair<IntegerModuloP> right) {
+
+ TestPair<MutableIntegerModuloP> left = elem.mutable();
+
+ for (int i = 0; i < 10000; i++) {
+
+ ElemFunction addFunc1 =
+ ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size()));
+ TestPair<MutableIntegerModuloP> result1 =
+ applyAndCheckMutable(addFunc1, left, right);
+
+ // left could have been modified, so turn it back into a summand
+ applyAndCheckMutable((a, b) -> a.setSquare(), left, right);
+
+ ElemFunction addFunc2 =
+ ADD_FUNCTIONS.get(random.nextInt(ADD_FUNCTIONS.size()));
+ TestPair<IntegerModuloP> result2 =
+ applyAndCheck(addFunc2, left, right);
+
+ if (elem.test.getField() instanceof IntegerPolynomial) {
+ IntegerPolynomial field =
+ (IntegerPolynomial) elem.test.getField();
+ int numAdds = field.getMaxAdds();
+ for (int j = 1; j < numAdds; j++) {
+ ElemFunction addFunc3 = ADD_FUNCTIONS.
+ get(random.nextInt(ADD_FUNCTIONS.size()));
+ result2 = applyAndCheck(addFunc3, left, right);
+ }
+ }
+
+ ElemFunction multFunc2 =
+ MULT_FUNCTIONS.get(random.nextInt(MULT_FUNCTIONS.size()));
+ TestPair<MutableIntegerModuloP> multResult =
+ applyAndCheckMutable(multFunc2, result1, result2);
+
+ int swap = random.nextInt(2);
+ cswapAndCheck(swap, left, multResult);
+
+ ElemSetFunction setFunc =
+ SET_FUNCTIONS.get(random.nextInt(SET_FUNCTIONS.size()));
+ byte[] valueArr = new byte[length];
+ random.nextBytes(valueArr);
+ setAndCheck(setFunc, result1, result2, valueArr);
+
+ // left could have been modified, so to turn it back into a summand
+ applyAndCheckMutable((a, b) -> a.setSquare(), left, right);
+
+ ElemArrayFunction arrayFunc =
+ ARRAY_FUNCTIONS.get(random.nextInt(ARRAY_FUNCTIONS.size()));
+ left.applyAndCheckArray(arrayFunc, right);
+ }
+ }
+
+ // Run all the tests for a given field
+ static void runFieldTest(IntegerFieldModuloP testField,
+ int length, int seed) {
+ System.out.println("Testing: " + testField.getClass().getSimpleName());
+
+ Random random = new Random(seed);
+
+ IntegerFieldModuloP baselineField =
+ new BigIntegerModuloP(testField.getSize());
+
+ int numBits = testField.getSize().bitLength();
+ BigInteger r =
+ new BigInteger(numBits, random).mod(testField.getSize());
+ TestPair<IntegerModuloP> rand =
+ new TestPair(testField.getElement(r), baselineField.getElement(r));
+
+ runOverflowTest(rand);
+
+ // check combinations of operations for different kinds of elements
+ List<TestPair<IntegerModuloP>> testElements = new ArrayList<>();
+ testElements.add(rand);
+ testElements.add(new TestPair(testField.get0(), baselineField.get0()));
+ testElements.add(new TestPair(testField.get1(), baselineField.get1()));
+ byte[] testArr = {121, 37, -100, -5, 76, 33};
+ testElements.add(new TestPair(testField.getElement(testArr),
+ baselineField.getElement(testArr)));
+
+ testArr = new byte[length];
+ random.nextBytes(testArr);
+ testElements.add(new TestPair(testField.getElement(testArr),
+ baselineField.getElement(testArr)));
+
+ random.nextBytes(testArr);
+ byte highByte = (byte) (numBits > length * 8 ? 1 : 0);
+ testElements.add(
+ new TestPair(
+ testField.getElement(testArr, 0, testArr.length, highByte),
+ baselineField.getElement(testArr, 0, testArr.length, highByte)
+ )
+ );
+
+ for (int i = 0; i < testElements.size(); i++) {
+ for (int j = 0; j < testElements.size(); j++) {
+ runOperationsTest(random, length, testElements.get(i),
+ testElements.get(j));
+ }
+ }
+ }
+}
+
diff --git a/test/sun/security/validator/EndEntityExtensionCheck.java b/test/sun/security/validator/EndEntityExtensionCheck.java
index 122bae237f..3cff8fcb5e 100644
--- a/test/sun/security/validator/EndEntityExtensionCheck.java
+++ b/test/sun/security/validator/EndEntityExtensionCheck.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -44,7 +44,7 @@ import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
-import sun.security.validator.KeyStores;
+import sun.security.validator.TrustStoreUtil;
import sun.security.validator.Validator;
@@ -112,7 +112,7 @@ public class EndEntityExtensionCheck {
Validator v = Validator.getInstance(Validator.TYPE_SIMPLE,
Validator.VAR_TLS_CLIENT,
- KeyStores.getTrustedCerts(ks));
+ TrustStoreUtil.getTrustedCerts(ks));
try {
v.validate(chain);
throw new Exception("Chain should not have validated " +
diff --git a/test/sun/text/IntHashtable/Bug4170614Test.java b/test/sun/text/IntHashtable/Bug4170614Test.java
new file mode 100644
index 0000000000..97e08a1bdd
--- /dev/null
+++ b/test/sun/text/IntHashtable/Bug4170614Test.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 1999, 2016, 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.
+ */
+
+/*
+ (this test doesn't have an at-test tag because it's run by a shell
+ script instead of directly by the test harness)
+*/
+
+/*
+ *
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
+ *
+ * Portions copyright (c) 2007 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ *
+ * The original version of this source code and documentation
+ * is copyrighted and owned by Taligent, Inc., a wholly-owned
+ * subsidiary of IBM. These materials are provided under terms
+ * of a License Agreement between Taligent and Sun. This technology
+ * is protected by multiple US and International patents.
+ *
+ * This notice and attribution to Taligent may not be removed.
+ * Taligent is a registered trademark of Taligent, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for NON-COMMERCIAL purposes and without
+ * fee is hereby granted provided that this copyright notice
+ * appears in all copies. Please refer to the file "copyright.html"
+ * for further important copyright and licensing information.
+ *
+ * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
+ * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
+ * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
+ * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
+ *
+ */
+package java.text;
+import sun.text.IntHashtable;
+
+
+/**
+ * This class tests some internal hashCode() functions.
+ * Bug #4170614 complained that we had two iternal classes that
+ * break the invariant that if a.equals(b) than a.hashCode() ==
+ * b.hashCode(). This is because these classes overrode equals()
+ * but not hashCode(). These are both purely internal classes, and
+ * the library itself doesn't actually call hashCode(), so this isn't
+ * actually causing anyone problems yet. But if these classes are
+ * ever exposed in the API, their hashCode() methods need to work right.
+ * PatternEntry will never be exposed in the API, but IntHashtable
+ * might be. This is a shell test to allow us to access classes that
+ * are declared package private.
+ * @author Richard Gillam
+ */
+public class Bug4170614Test {
+ public static void main(String[] args) throws Exception {
+ testIntHashtable();
+ testPatternEntry();
+ }
+
+
+ public static void testIntHashtable() throws Exception {
+ IntHashtable fred = new IntHashtable();
+ fred.put(1, 10);
+ fred.put(2, 20);
+ fred.put(3, 30);
+
+ IntHashtable barney = new IntHashtable();
+ barney.put(1, 10);
+ barney.put(3, 30);
+ barney.put(2, 20);
+
+ IntHashtable homer = new IntHashtable();
+ homer.put(3, 30);
+ homer.put(1, 10);
+ homer.put(7, 900);
+
+ if (fred.equals(barney)) {
+ System.out.println("fred.equals(barney)");
+ }
+ else {
+ System.out.println("!fred.equals(barney)");
+ }
+ System.out.println("fred.hashCode() == " + fred.hashCode());
+ System.out.println("barney.hashCode() == " + barney.hashCode());
+
+ if (!fred.equals(barney)) {
+ throw new Exception("equals() failed on two hashtables that are equal");
+ }
+
+ if (fred.hashCode() != barney.hashCode()) {
+ throw new Exception("hashCode() failed on two hashtables that are equal");
+ }
+
+ System.out.println();
+ if (fred.equals(homer)) {
+ System.out.println("fred.equals(homer)");
+ }
+ else {
+ System.out.println("!fred.equals(homer)");
+ }
+ System.out.println("fred.hashCode() == " + fred.hashCode());
+ System.out.println("homer.hashCode() == " + homer.hashCode());
+
+ if (fred.equals(homer)) {
+ throw new Exception("equals() failed on two hashtables that are not equal");
+ }
+
+ if (fred.hashCode() == homer.hashCode()) {
+ throw new Exception("hashCode() failed on two hashtables that are not equal");
+ }
+
+ System.out.println();
+ System.out.println("testIntHashtable() passed.\n");
+ }
+
+ public static void testPatternEntry() throws Exception {
+ PatternEntry fred = new PatternEntry(1,
+ new StringBuffer("hello"),
+ new StringBuffer("up"));
+ PatternEntry barney = new PatternEntry(1,
+ new StringBuffer("hello"),
+ new StringBuffer("down"));
+ // (equals() only considers the "chars" field, so fred and barney are equal)
+ PatternEntry homer = new PatternEntry(1,
+ new StringBuffer("goodbye"),
+ new StringBuffer("up"));
+
+ if (fred.equals(barney)) {
+ System.out.println("fred.equals(barney)");
+ }
+ else {
+ System.out.println("!fred.equals(barney)");
+ }
+ System.out.println("fred.hashCode() == " + fred.hashCode());
+ System.out.println("barney.hashCode() == " + barney.hashCode());
+
+ if (!fred.equals(barney)) {
+ throw new Exception("equals() failed on two hashtables that are equal");
+ }
+
+ if (fred.hashCode() != barney.hashCode()) {
+ throw new Exception("hashCode() failed on two hashtables that are equal");
+ }
+
+ System.out.println();
+ if (fred.equals(homer)) {
+ System.out.println("fred.equals(homer)");
+ }
+ else {
+ System.out.println("!fred.equals(homer)");
+ }
+ System.out.println("fred.hashCode() == " + fred.hashCode());
+ System.out.println("homer.hashCode() == " + homer.hashCode());
+
+ if (fred.equals(homer)) {
+ throw new Exception("equals() failed on two hashtables that are not equal");
+ }
+
+ if (fred.hashCode() == homer.hashCode()) {
+ throw new Exception("hashCode() failed on two hashtables that are not equal");
+ }
+
+ System.out.println();
+ System.out.println("testPatternEntry() passed.\n");
+ }
+}
diff --git a/test/sun/text/IntHashtable/Bug4170614Test.sh b/test/sun/text/IntHashtable/Bug4170614Test.sh
new file mode 100644
index 0000000000..b8dad0084a
--- /dev/null
+++ b/test/sun/text/IntHashtable/Bug4170614Test.sh
@@ -0,0 +1,81 @@
+#!/bin/sh
+
+#
+# Copyright (c) 1999, 2016, 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 4170614
+# @summary Test internal hashCode() functions
+#
+
+set -x
+if [ "${TESTSRC}" = "" ]
+then
+ echo "TESTSRC not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTSRC=${TESTSRC}"
+if [ "${TESTJAVA}" = "" ]
+then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTJAVA=${TESTJAVA}"
+if [ "${COMPILEJAVA}" = "" ]; then
+ COMPILEJAVA="${TESTJAVA}"
+fi
+echo "COMPILEJAVA=${COMPILEJAVA}"
+if [ "${TESTCLASSES}" = "" ]
+then
+ echo "TESTCLASSES not set. Test cannot execute. Failed."
+ exit 1
+fi
+echo "TESTCLASSES=${TESTCLASSES}"
+
+goback=`pwd`
+
+cd ${TESTSRC}
+
+TEST_JAVABASE=${TESTCLASSES}/java.base
+mkdir -p ${TEST_JAVABASE}
+${COMPILEJAVA}/bin/javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} \
+ -Xmodule:java.base \
+ -d ${TEST_JAVABASE} Bug4170614Test.java
+
+${TESTJAVA}/bin/java ${TESTVMOPTS} -Xpatch:java.base=${TEST_JAVABASE} java.text.Bug4170614Test
+
+result=$?
+
+cd ${goback}
+
+if [ $result -eq 0 ]
+then
+ echo "Passed"
+else
+ echo "Failed"
+fi
+exit $result
+
+
+
diff --git a/test/sun/text/IntHashtable/Bug4705389.java b/test/sun/text/IntHashtable/Bug4705389.java
new file mode 100644
index 0000000000..d2f6e49a82
--- /dev/null
+++ b/test/sun/text/IntHashtable/Bug4705389.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2002, 2016, 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 4705389
+ * @summary Make sure to find removed slots, which test case will be timed out without the fix.
+ * @modules java.base/sun.text
+ * @run main/timeout=10 Bug4705389
+ */
+
+import sun.text.IntHashtable;
+
+public class Bug4705389 {
+ public static void main(String args[]) {
+ IntHashtable table = new IntHashtable();
+ for (int i = 1; i < 132; ++i) {
+ table.put(i, 0);
+ table.remove(i);
+ }
+ table.put(132, 0);
+ }
+}
diff --git a/test/sun/text/resources/LocaleData b/test/sun/text/resources/LocaleData
index f4c26f6def..f8a517eb21 100644
--- a/test/sun/text/resources/LocaleData
+++ b/test/sun/text/resources/LocaleData
@@ -614,8 +614,6 @@ FormatData/es_PE/DatePatterns/1=d' de 'MMMM' de 'yyyy
FormatData/es_PE/DatePatterns/2=dd/MM/yyyy
FormatData/es_PE/DatePatterns/3=dd/MM/yy
FormatData/es_PE/DateTimePatterns/0={1} {0}
-FormatData/es_PE/NumberElements/0=,
-FormatData/es_PE/NumberElements/1=.
FormatData/es_PE/NumberElements/2=;
FormatData/es_PR/NumberPatterns/0=#,##0.###;-#,##0.###
# FormatData/es_PR/NumberPatterns/1=$#,##0.00;($#,##0.00) # Changed; see bug 4122840
@@ -6399,7 +6397,6 @@ CurrencyNames//afn=Afghan Afghani
CurrencyNames//ang=Netherlands Antillean Guilder
CurrencyNames//awg=Aruban Florin
CurrencyNames//azm=Azerbaijani Manat (1993-2006)
-CurrencyNames//azn=Azerbaijani Manat
CurrencyNames//bbd=Barbadian Dollar
CurrencyNames//bdt=Bangladeshi Taka
CurrencyNames//bgn=Bulgarian Lev
@@ -8296,3 +8293,20 @@ CurrencyNames//pen=Peruvian Sol
# bug #8145952
CurrencyNames//byn=Belarusian Ruble
CurrencyNames/be_BY/BYN=\u0420\u0443\u0431
+
+# bug #8187946
+CurrencyNames//stn=S\u00e3o Tom\u00e9 and Pr\u00edncipe Dobra
+CurrencyNames//lak=Lao Kip
+CurrencyNames//php=Philippine Peso
+CurrencyNames//azn=Azerbaijan Manat
+
+# bug #8193552
+CurrencyNames//mru=Mauritanian Ouguiya
+
+# bug #8208746
+CurrencyNames//ves=Venezuelan Bol\u00edvar Soberano
+
+# bug# 8206879
+# For Peru decimal separator is changed to dot(.) and grouping separator is changed to comma(,)
+FormatData/es_PE/NumberElements/0=.
+FormatData/es_PE/NumberElements/1=,
diff --git a/test/sun/text/resources/LocaleDataTest.java b/test/sun/text/resources/LocaleDataTest.java
index 94e92b95db..4ca9415d5d 100644
--- a/test/sun/text/resources/LocaleDataTest.java
+++ b/test/sun/text/resources/LocaleDataTest.java
@@ -36,8 +36,8 @@
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
* 7114053 7074882 7040556 8013836 8021121 6192407 6931564 8027695 7090826
- * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361
- * 8145952 8164784
+ * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8145952
+ * 8164784 8187946 8195478 8193552 8202026 8204269 8208746 8209775
* @summary Verify locale data
*
*/
diff --git a/test/sun/util/calendar/zi/TestZoneInfo310.java b/test/sun/util/calendar/zi/TestZoneInfo310.java
index f6fc60efa6..b8c5d29f70 100644
--- a/test/sun/util/calendar/zi/TestZoneInfo310.java
+++ b/test/sun/util/calendar/zi/TestZoneInfo310.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -22,10 +22,14 @@
*/
/*
- *@test
- *@bug 8007572 8008161
- *@summary Test whether the TimeZone generated from JSR310 tzdb is the same
- *as the one from the tz data from javazic
+ * @test
+ * @bug 8007572 8008161 8157792 8224560
+ * @summary Test whether the TimeZone generated from JSR310 tzdb is the same
+ * as the one from the tz data from javazic
+ * @build BackEnd Checksum DayOfWeek Gen GenDoc Main Mappings Month
+ * Rule RuleDay RuleRec Simple TestZoneInfo310 Time Timezone
+ * TzIDOldMapping Zone ZoneInfoFile ZoneInfoOld ZoneRec Zoneinfo
+ * @run main TestZoneInfo310
*/
import java.io.File;
@@ -163,12 +167,17 @@ public class TestZoneInfo310 {
}
for (String zid : zids_new) {
- if (zid.equals("Asia/Oral") || zid.equals("Asia/Qyzylorda")) {
- // JDK-8157792 tracking this issue
- continue;
- }
ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid));
ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid);
+ /*
+ * Temporary ignoring the failing TimeZones which are having zone
+ * rules defined till year 2037 and/or above and have negative DST
+ * save time in IANA tzdata. This bug is tracked via JDK-8223388.
+ */
+ if (zid.equals("Africa/Casablanca") || zid.equals("Africa/El_Aaiun")
+ || zid.equals("Asia/Tehran") || zid.equals("Iran")) {
+ continue;
+ }
if (! zi.equalsTo(ziOLD)) {
System.out.println(zi.diffsTo(ziOLD));
throw new RuntimeException(" FAILED: " + zid);
diff --git a/test/sun/util/calendar/zi/Zoneinfo.java b/test/sun/util/calendar/zi/Zoneinfo.java
index 9e48655181..e58fd188a3 100644
--- a/test/sun/util/calendar/zi/Zoneinfo.java
+++ b/test/sun/util/calendar/zi/Zoneinfo.java
@@ -373,6 +373,7 @@ class Zoneinfo {
tz.getOffsetIndex(zrec.getGmtOffset());
int lastGmtOffsetValue = -1;
+ ZoneRec prevzrec = null;
int currentSave = 0;
boolean usedZone;
for (int zindex = 0; zindex < zone.size(); zindex++) {
@@ -441,6 +442,15 @@ class Zoneinfo {
currentSave);
if (zrec.hasUntil()) {
if (transition >= zrec.getUntilTime(currentSave)) {
+ // If the GMT offset changed from the previous one,
+ // record fromTime as a transition.
+ if (!fromTimeUsed && prevzrec != null
+ && gmtOffset != prevzrec.getGmtOffset()) {
+ tz.addTransition(fromTime,
+ tz.getOffsetIndex(gmtOffset+currentSave),
+ tz.getDstOffsetIndex(currentSave));
+ fromTimeUsed = true; // for consistency
+ }
break year_loop;
}
}
@@ -452,8 +462,6 @@ class Zoneinfo {
if (fromTime != minTime) {
int prevsave;
- ZoneRec prevzrec = zone.get(zindex - 1);
-
// See if until time in the previous
// ZoneRec is the same thing as the
// local time in the next rule.
@@ -555,6 +563,7 @@ class Zoneinfo {
fromYear = zrec.getUntilYear();
year = zrec.getUntilYear();
}
+ prevzrec = zrec;
}
if (tz.getDSTType() == Timezone.UNDEF_DST) {
diff --git a/test/sun/util/calendar/zi/tzdata/VERSION b/test/sun/util/calendar/zi/tzdata/VERSION
index e3fa9222bc..f058737a34 100644
--- a/test/sun/util/calendar/zi/tzdata/VERSION
+++ b/test/sun/util/calendar/zi/tzdata/VERSION
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2018g
+tzdata2019a
diff --git a/test/sun/util/calendar/zi/tzdata/africa b/test/sun/util/calendar/zi/tzdata/africa
index e2ffac25ec..94f627c48f 100644
--- a/test/sun/util/calendar/zi/tzdata/africa
+++ b/test/sun/util/calendar/zi/tzdata/africa
@@ -387,6 +387,11 @@ Zone Africa/Cairo 2:05:09 - LMT 1900 Oct
# See Africa/Lagos.
# Eritrea
+# See Africa/Nairobi.
+
+# Eswatini (formerly Swaziland)
+# See Africa/Johannesburg.
+
# Ethiopia
# See Africa/Nairobi.
#
@@ -870,8 +875,41 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis
# From Mohamed Essedik Najd (2018-10-26):
# Today, a Moroccan government council approved the perpetual addition
# of 60 minutes to the regular Moroccan timezone.
-# From Brian Inglis (2018-10-26):
-# http://www.maroc.ma/fr/actualites/le-conseil-de-gouvernement-adopte-un-projet-de-decret-relatif-lheure-legale-stipulant-le
+# From Matt Johnson (2018-10-28):
+# http://www.sgg.gov.ma/Portals/1/BO/2018/BO_6720-bis_Ar.pdf
+#
+# From Maamar Abdelkader (2018-11-01):
+# We usually move clocks back the previous week end and come back to the +1
+# the week end after.... The government does not announce yet the decision
+# about this temporary change. But it s 99% sure that it will be the case,
+# as in previous years. An unofficial survey was done these days, showing
+# that 64% of asked peopke are ok for moving from +1 to +0 during Ramadan.
+# https://leconomiste.com/article/1035870-enquete-l-economiste-sunergia-64-des-marocains-plebiscitent-le-gmt-pendant-ramadan
+#
+# From Paul Eggert (2018-11-01):
+# For now, guess that Morocco will fall back at 03:00 the last Sunday
+# before Ramadan, and spring forward at 02:00 the first Sunday after
+# Ramadan, as this has been the practice since 2012. To implement this,
+# transition dates for 2019 through 2037 were determined by running the
+# following program under GNU Emacs 26.1.
+# (let ((islamic-year 1440))
+# (require 'cal-islam)
+# (while (< islamic-year 1460)
+# (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+# (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+# (sunday 0))
+# (while (/= sunday (mod (setq a (1- a)) 7)))
+# (while (/= sunday (mod b 7))
+# (setq b (1+ b)))
+# (setq a (calendar-gregorian-from-absolute a))
+# (setq b (calendar-gregorian-from-absolute b))
+# (insert
+# (format
+# (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t-1:00\t-\n"
+# "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t0\t-\n")
+# (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+# (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# (setq islamic-year (+ 1 islamic-year))))
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 -
@@ -903,7 +941,7 @@ Rule Morocco 2012 only - Aug 20 2:00 1:00 -
Rule Morocco 2012 only - Sep 30 3:00 0 -
Rule Morocco 2013 only - Jul 7 3:00 0 -
Rule Morocco 2013 only - Aug 10 2:00 1:00 -
-Rule Morocco 2013 2018 - Oct lastSun 3:00 0 -
+Rule Morocco 2013 2017 - Oct lastSun 3:00 0 -
Rule Morocco 2014 2018 - Mar lastSun 2:00 1:00 -
Rule Morocco 2014 only - Jun 28 3:00 0 -
Rule Morocco 2014 only - Aug 2 2:00 1:00 -
@@ -915,13 +953,53 @@ Rule Morocco 2017 only - May 21 3:00 0 -
Rule Morocco 2017 only - Jul 2 2:00 1:00 -
Rule Morocco 2018 only - May 13 3:00 0 -
Rule Morocco 2018 only - Jun 17 2:00 1:00 -
+Rule Morocco 2019 only - May 5 3:00 0 -
+Rule Morocco 2019 only - Jun 9 2:00 1:00 -
+Rule Morocco 2020 only - Apr 19 3:00 0 -
+Rule Morocco 2020 only - May 24 2:00 1:00 -
+Rule Morocco 2021 only - Apr 11 3:00 0 -
+Rule Morocco 2021 only - May 16 2:00 1:00 -
+Rule Morocco 2022 only - Mar 27 3:00 0 -
+Rule Morocco 2022 only - May 8 2:00 1:00 -
+Rule Morocco 2023 only - Mar 19 3:00 0 -
+Rule Morocco 2023 only - Apr 23 2:00 1:00 -
+Rule Morocco 2024 only - Mar 10 3:00 0 -
+Rule Morocco 2024 only - Apr 14 2:00 1:00 -
+Rule Morocco 2025 only - Feb 23 3:00 0 -
+Rule Morocco 2025 only - Apr 6 2:00 1:00 -
+Rule Morocco 2026 only - Feb 15 3:00 0 -
+Rule Morocco 2026 only - Mar 22 2:00 1:00 -
+Rule Morocco 2027 only - Feb 7 3:00 0 -
+Rule Morocco 2027 only - Mar 14 2:00 1:00 -
+Rule Morocco 2028 only - Jan 23 3:00 0 -
+Rule Morocco 2028 only - Feb 27 2:00 1:00 -
+Rule Morocco 2029 only - Jan 14 3:00 0 -
+Rule Morocco 2029 only - Feb 18 2:00 1:00 -
+Rule Morocco 2029 only - Dec 30 3:00 0 -
+Rule Morocco 2030 only - Feb 10 2:00 1:00 -
+Rule Morocco 2030 only - Dec 22 3:00 0 -
+Rule Morocco 2031 only - Jan 26 2:00 1:00 -
+Rule Morocco 2031 only - Dec 14 3:00 0 -
+Rule Morocco 2032 only - Jan 18 2:00 1:00 -
+Rule Morocco 2032 only - Nov 28 3:00 0 -
+Rule Morocco 2033 only - Jan 9 2:00 1:00 -
+Rule Morocco 2033 only - Nov 20 3:00 0 -
+Rule Morocco 2033 only - Dec 25 2:00 1:00 -
+Rule Morocco 2034 only - Nov 5 3:00 0 -
+Rule Morocco 2034 only - Dec 17 2:00 1:00 -
+Rule Morocco 2035 only - Oct 28 3:00 0 -
+Rule Morocco 2035 only - Dec 2 2:00 1:00 -
+Rule Morocco 2036 only - Oct 19 3:00 0 -
+Rule Morocco 2036 only - Nov 23 2:00 1:00 -
+Rule Morocco 2037 only - Oct 4 3:00 0 -
+Rule Morocco 2037 only - Nov 15 2:00 1:00 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
0:00 Morocco +00/+01 1984 Mar 16
1:00 - +01 1986
- 0:00 Morocco +00/+01 2018 Oct 27
- 1:00 - +01
+ 0:00 Morocco +00/+01 2018 Oct 28 3:00
+ 0:00 Morocco +00/+01
# Western Sahara
#
@@ -936,8 +1014,8 @@ Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
Zone Africa/El_Aaiun -0:52:48 - LMT 1934 Jan # El Aaiún
-1:00 - -01 1976 Apr 14
- 0:00 Morocco +00/+01 2018 Oct 27
- 1:00 - +01
+ 0:00 Morocco +00/+01 2018 Oct 28 3:00
+ 0:00 Morocco +00/+01
# Mozambique
#
@@ -1094,10 +1172,20 @@ Zone Indian/Reunion 3:41:52 - LMT 1911 Jun # Saint-Denis
# the switch is from 01:00 to 02:00 ... [Decree No. 25/2017]
# http://www.mnec.gov.st/index.php/publicacoes/documentos/file/90-decreto-lei-n-25-2017
+# From Vadim Nasardinov (2018-12-29):
+# São Tomé and Príncipe is about to do the following on Jan 1, 2019:
+# https://www.stp-press.st/2018/12/05/governo-jesus-ja-decidiu-repor-hora-legal-sao-tomense/
+#
+# From Michael Deckers (2018-12-30):
+# https://www.legis-palop.org/download.jsp?idFile=102818
+# ... [The legal time of the country, which coincides with universal
+# coordinated time, will be restituted at 2 o'clock on day 1 of January, 2019.]
+
Zone Africa/Sao_Tome 0:26:56 - LMT 1884
-0:36:45 - LMT 1912 Jan 1 00:00u # Lisbon MT
0:00 - GMT 2018 Jan 1 01:00
- 1:00 - WAT
+ 1:00 - WAT 2019 Jan 1 02:00
+ 0:00 - GMT
# Senegal
# See Africa/Abidjan.
@@ -1128,7 +1216,7 @@ Zone Africa/Johannesburg 1:52:00 - LMT 1892 Feb 8
1:30 - SAST 1903 Mar
2:00 SA SAST
Link Africa/Johannesburg Africa/Maseru # Lesotho
-Link Africa/Johannesburg Africa/Mbabane # Swaziland
+Link Africa/Johannesburg Africa/Mbabane # Eswatini
#
# Marion and Prince Edward Is
# scientific station since 1947
@@ -1170,9 +1258,6 @@ Zone Africa/Juba 2:06:28 - LMT 1931
2:00 Sudan CA%sT 2000 Jan 15 12:00
3:00 - EAT
-# Swaziland
-# See Africa/Johannesburg.
-
# Tanzania
# See Africa/Nairobi.
diff --git a/test/sun/util/calendar/zi/tzdata/asia b/test/sun/util/calendar/zi/tzdata/asia
index 9847e91f4f..cc2e0fc711 100644
--- a/test/sun/util/calendar/zi/tzdata/asia
+++ b/test/sun/util/calendar/zi/tzdata/asia
@@ -609,12 +609,82 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# obtained from
# http://www.hko.gov.hk/gts/time/Summertime.htm
-# From Arthur David Olson (2009-10-28):
+# From Phake Nick (2018-10-27):
+# According to Singaporean newspaper
+# http://eresources.nlb.gov.sg/newspapers/Digitised/Article/singfreepresswk19041102-1.2.37
+# the day that Hong Kong start using GMT+8 should be Oct 30, 1904.
+#
+# From Paul Eggert (2018-11-17):
+# Hong Kong had a time ball near the Marine Police Station, Tsim Sha Tsui.
+# "The ball was raised manually each day and dropped at exactly 1pm
+# (except on Sundays and Government holidays)."
+# Dyson AD. From Time Ball to Atomic Clock. Hong Kong Government. 1983.
+# <https://www.hko.gov.hk/publica/gen_pub/timeball_atomic_clock.pdf>
+# "From 1904 October 30 the time-ball at Hong Kong has been dropped by order
+# of the Governor of the Colony at 17h 0m 0s G.M.T., which is 23m 18s.14 in
+# advance of 1h 0m 0s of Hong Kong mean time."
+# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc.
+# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382
+#
+# From Joseph Myers (2018-11-18):
+# An astronomer before 1925 referring to GMT would have been using the old
+# astronomical convention where the day started at noon, not midnight.
+#
+# From Steve Allen (2018-11-17):
+# Meteorological Observations made at the Hongkong Observatory in the year 1904
+# page 4 <https://books.google.com/books?id=kgw5AQAAMAAJ&pg=RA4-PA4>
+# ... the log of drop times in Table II shows that on Sunday 1904-10-30 the
+# ball was dropped. So that looks like a special case drop for the sake
+# of broadcasting the new local time.
+#
+# From Phake Nick (2018-11-18):
+# According to The Hong Kong Weekly Press, 1904-10-29, p.324, the
+# governor of Hong Kong at the time stated that "We are further desired to
+# make it known that the change will be effected by firing the gun and by the
+# dropping of the Ball at 23min. 18sec. before one."
+# From Paul Eggert (2018-11-18):
+# See <https://mmis.hkpl.gov.hk> for this; unfortunately Flash is required.
+
+# From Phake Nick (2018-10-26):
+# I went to check microfilm records stored at Hong Kong Public Library....
+# on September 30 1941, according to Ta Kung Pao (Hong Kong edition), it was
+# stated that fallback would occur on the next day (the 1st)'s "03:00 am (Hong
+# Kong Time 04:00 am)" and the clock will fall back for a half hour. (03:00
+# probably refer to the time commonly used in mainland China at the time given
+# the paper's background) ... the sunrise/sunset time given by South China
+# Morning Post for October 1st was indeed moved by half an hour compares to
+# before. After that, in December, the battle to capture Hong Kong started and
+# the library doesn't seems to have any record stored about press during that
+# period of time. Some media resumed publication soon after that within the
+# same month, but there were not much information about time there. Later they
+# started including a radio program guide when they restored radio service,
+# explicitly mentioning it use Tokyo standard time, and later added a note
+# saying it's half an hour ahead of the old Hong Kong standard time, and it
+# also seems to indicate that Hong Kong was not using GMT+8 when it was
+# captured by Japan.
+#
+# Image of related sections on newspaper:
+# * 1941-09-30, Ta Kung Pao (Hong Kong), "Winter Time start tomorrow".
+# https://i.imgur.com/6waY51Z.jpg (Chinese)
+# * 1941-09-29, South China Morning Post, Information on sunrise/sunset
+# time and other things for September 30 and October 1.
+# https://i.imgur.com/kCiUR78.jpg
+# * 1942-02-05. The Hong Kong News, Radio Program Guide.
+# https://i.imgur.com/eVvDMzS.jpg
+# * 1941-06-14. Hong Kong Daily Press, Daylight Saving from 3am Tomorrow.
+# https://i.imgur.com/05KkvtC.png
+# * 1941-09-30, Hong Kong Daily Press, Winter Time Warning.
+# https://i.imgur.com/dge4kFJ.png
+# Also, the Liberation day of Hong Kong after WWII which British rule
+# over the territory resumed was August 30, 1945, which I think should
+# be the termination date for the use of JST in the territory....
+
+# From Paul Eggert (2018-11-17):
# Here are the dates given at
-# http://www.hko.gov.hk/gts/time/Summertime.htm
-# as of 2009-10-28:
+# https://www.hko.gov.hk/gts/time/Summertime.htm
+# as of 2014-06-19:
# Year Period
-# 1941 1 Apr to 30 Sep
+# 1941 15 Jun to 30 Sep
# 1942 Whole year
# 1943 Whole year
# 1944 Whole year
@@ -625,7 +695,7 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# 1949 3 Apr to 30 Oct
# 1950 2 Apr to 29 Oct
# 1951 1 Apr to 28 Oct
-# 1952 6 Apr to 25 Oct
+# 1952 6 Apr to 2 Nov
# 1953 5 Apr to 1 Nov
# 1954 21 Mar to 31 Oct
# 1955 20 Mar to 6 Nov
@@ -654,25 +724,25 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# 1978 Nil
# 1979 13 May to 21 Oct
# 1980 to Now Nil
-# The page does not give start or end times of day.
-# The page does not give a start date for 1942.
-# The page does not givw an end date for 1945.
-# The Japanese occupation of Hong Kong began on 1941-12-25.
-# The Japanese surrender of Hong Kong was signed 1945-09-15.
-# For lack of anything better, use start of those days as the transition times.
+# The page does not give times of day for transitions,
+# or dates for the 1942 and 1945 transitions.
+# The Japanese occupation of Hong Kong began 1941-12-25.
+# The Japanese surrender of Hong Kong was signed 1945-09-16; see:
+# Heaver S. The days after the Pacific war ended: unsettling times
+# in Hong Kong. Post Magazine. 2016-06-13.
+# https://www.scmp.com/magazines/post-magazine/article/1852990/days-after-pacific-war-ended-unsettling-times-hong-kong
+# For lack of anything better, use start of those days as the
+# transition times.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule HK 1941 only - Apr 1 3:30 1:00 S
-Rule HK 1941 only - Sep 30 3:30 0 -
Rule HK 1946 only - Apr 20 3:30 1:00 S
Rule HK 1946 only - Dec 1 3:30 0 -
Rule HK 1947 only - Apr 13 3:30 1:00 S
Rule HK 1947 only - Dec 30 3:30 0 -
Rule HK 1948 only - May 2 3:30 1:00 S
Rule HK 1948 1951 - Oct lastSun 3:30 0 -
-Rule HK 1952 only - Oct 25 3:30 0 -
+Rule HK 1952 1953 - Nov Sun>=1 3:30 0 -
Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S
-Rule HK 1953 only - Nov 1 3:30 0 -
Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
Rule HK 1954 only - Oct 31 3:30 0 -
Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
@@ -682,9 +752,11 @@ Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30
- 8:00 HK HK%sT 1941 Dec 25
- 9:00 - JST 1945 Sep 15
+Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 0:36:42
+ 8:00 - HKT 1941 Jun 15 3:30
+ 8:00 1:00 HKST 1941 Oct 1 4:00
+ 8:30 - HKT 1941 Dec 25
+ 9:00 - JST 1945 Sep 16
8:00 HK HK%sT
###############################################################################
@@ -1080,6 +1152,16 @@ Zone Asia/Dili 8:22:20 - LMT 1912 Jan 1
# India
+# British astronomer Henry Park Hollis disliked India Standard Time's offset:
+# "A new time system has been proposed for India, Further India, and Burmah.
+# The scheme suggested is that the times of the meridians 5½ and 6½ hours
+# east of Greenwich should be adopted in these territories. No reason is
+# given why hourly meridians five hours and six hours east should not be
+# chosen; a plan which would bring the time of India into harmony with
+# that of almost the whole of the civilised world."
+# Hollis HP. Universal Time, Longitudes, and Geodesy. Mon Not R Astron Soc.
+# 1905-02-10;65(4):405-6. https://doi.org/10.1093/mnras/65.4.382
+
# From Ian P. Beacock, in "A brief history of (modern) time", The Atlantic
# https://www.theatlantic.com/technology/archive/2015/12/the-creation-of-modern-time/421419/
# (2015-12-22):
@@ -1250,12 +1332,65 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
# leap year calculation involved. There has never been any serious
# plan to change that law....
#
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2018-11-30):
# Go with Shanks & Pottenger before Sept. 1991, and with Pournader thereafter.
-# I used Ed Reingold's cal-persia in GNU Emacs 21.2 to check Persian dates,
-# stopping after 2037 when 32-bit time_t's overflow.
-# That cal-persia used Birashk's approximation, which disagrees with the solar
-# calendar predictions for the year 2025, so I corrected those dates by hand.
+# I used the following code in GNU Emacs 26.1 to generate the "Rule Iran"
+# lines from 2008 through 2087. Emacs 26.1 uses Ed Reingold's
+# cal-persia implementation of Birashk's approximation, which in the
+# 2008-2087 range disagrees with the the astronomical Persian calendar
+# for Persian years 1404 (Gregorian 2025) and 1437 (Gregorian 2058),
+# so the following code special-case those years. See Table 15.1, page 264, of:
+# Edward M. Reingold and Nachum Dershowitz, Calendrical Calculations:
+# The Ultimate Edition, Cambridge University Press (2018).
+# https://www.cambridge.org/fr/academic/subjects/computer-science/computing-general-interest/calendrical-calculations-ultimate-edition-4th-edition
+# Page 258, footnote 2, of this book says there is some dispute over what will
+# happen in 2091 (and some other years after that), so this code
+# stops in 2087, as 2088 and 2089 agree with the "max" rule below.
+# (cl-loop
+# initially (require 'cal-persia)
+# with first-persian-year = 1387
+# with last-persian-year = 1466
+# ;; Exceptional years in the above range,
+# ;; from Reingold & Dershowitz Table 15.1, page 264:
+# with exceptional-persian-years = '(1404 1437)
+# with range-start = nil
+# for persian-year from first-persian-year to last-persian-year
+# do
+# (let*
+# ((exceptional-year-offset
+# (if (member persian-year exceptional-persian-years) 1 0))
+# (beg-dst-absolute
+# (+ (calendar-persian-to-absolute (list 1 1 persian-year))
+# exceptional-year-offset))
+# (end-dst-absolute
+# (+ (calendar-persian-to-absolute (list 6 30 persian-year))
+# exceptional-year-offset))
+# (next-year-beg-dst-absolute
+# (+ (calendar-persian-to-absolute (list 1 1 (1+ persian-year)))
+# (if (member (1+ persian-year) exceptional-persian-years) 1 0)))
+# (beg-dst (calendar-gregorian-from-absolute beg-dst-absolute))
+# (end-dst (calendar-gregorian-from-absolute end-dst-absolute))
+# (next-year-beg-dst (calendar-gregorian-from-absolute
+# next-year-beg-dst-absolute))
+# (year (calendar-extract-year beg-dst))
+# (range-end (if range-start year "only")))
+# (setq range-start (or range-start year))
+# (when (or (/= (calendar-extract-day beg-dst)
+# (calendar-extract-day next-year-beg-dst))
+# (= persian-year last-persian-year))
+# (insert
+# (format
+# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t1:00\t-\n"
+# range-start range-end
+# (calendar-month-name (calendar-extract-month beg-dst) t)
+# (calendar-extract-day beg-dst)))
+# (insert
+# (format
+# "Rule\tIran\t%d\t%s\t-\t%s\t%2d\t24:00\t0\t-\n"
+# range-start range-end
+# (calendar-month-name (calendar-extract-month end-dst) t)
+# (calendar-extract-day end-dst)))
+# (setq range-start nil))))
#
# From Oscar van Vlijmen (2005-03-30), writing about future
# discrepancies between cal-persia and the Iranian calendar:
@@ -1290,61 +1425,113 @@ Zone Asia/Jayapura 9:22:48 - LMT 1932 Nov
# thirtieth day of Shahrivar.
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Iran 1978 1980 - Mar 21 0:00 1:00 -
-Rule Iran 1978 only - Oct 21 0:00 0 -
-Rule Iran 1979 only - Sep 19 0:00 0 -
-Rule Iran 1980 only - Sep 23 0:00 0 -
-Rule Iran 1991 only - May 3 0:00 1:00 -
-Rule Iran 1992 1995 - Mar 22 0:00 1:00 -
-Rule Iran 1991 1995 - Sep 22 0:00 0 -
-Rule Iran 1996 only - Mar 21 0:00 1:00 -
-Rule Iran 1996 only - Sep 21 0:00 0 -
-Rule Iran 1997 1999 - Mar 22 0:00 1:00 -
-Rule Iran 1997 1999 - Sep 22 0:00 0 -
-Rule Iran 2000 only - Mar 21 0:00 1:00 -
-Rule Iran 2000 only - Sep 21 0:00 0 -
-Rule Iran 2001 2003 - Mar 22 0:00 1:00 -
-Rule Iran 2001 2003 - Sep 22 0:00 0 -
-Rule Iran 2004 only - Mar 21 0:00 1:00 -
-Rule Iran 2004 only - Sep 21 0:00 0 -
-Rule Iran 2005 only - Mar 22 0:00 1:00 -
-Rule Iran 2005 only - Sep 22 0:00 0 -
-Rule Iran 2008 only - Mar 21 0:00 1:00 -
-Rule Iran 2008 only - Sep 21 0:00 0 -
-Rule Iran 2009 2011 - Mar 22 0:00 1:00 -
-Rule Iran 2009 2011 - Sep 22 0:00 0 -
-Rule Iran 2012 only - Mar 21 0:00 1:00 -
-Rule Iran 2012 only - Sep 21 0:00 0 -
-Rule Iran 2013 2015 - Mar 22 0:00 1:00 -
-Rule Iran 2013 2015 - Sep 22 0:00 0 -
-Rule Iran 2016 only - Mar 21 0:00 1:00 -
-Rule Iran 2016 only - Sep 21 0:00 0 -
-Rule Iran 2017 2019 - Mar 22 0:00 1:00 -
-Rule Iran 2017 2019 - Sep 22 0:00 0 -
-Rule Iran 2020 only - Mar 21 0:00 1:00 -
-Rule Iran 2020 only - Sep 21 0:00 0 -
-Rule Iran 2021 2023 - Mar 22 0:00 1:00 -
-Rule Iran 2021 2023 - Sep 22 0:00 0 -
-Rule Iran 2024 only - Mar 21 0:00 1:00 -
-Rule Iran 2024 only - Sep 21 0:00 0 -
-Rule Iran 2025 2027 - Mar 22 0:00 1:00 -
-Rule Iran 2025 2027 - Sep 22 0:00 0 -
-Rule Iran 2028 2029 - Mar 21 0:00 1:00 -
-Rule Iran 2028 2029 - Sep 21 0:00 0 -
-Rule Iran 2030 2031 - Mar 22 0:00 1:00 -
-Rule Iran 2030 2031 - Sep 22 0:00 0 -
-Rule Iran 2032 2033 - Mar 21 0:00 1:00 -
-Rule Iran 2032 2033 - Sep 21 0:00 0 -
-Rule Iran 2034 2035 - Mar 22 0:00 1:00 -
-Rule Iran 2034 2035 - Sep 22 0:00 0 -
-#
-# The following rules are approximations starting in the year 2038.
-# These are the best post-2037 approximations available, given the
-# restrictions of a single rule using a Gregorian-based data format.
+Rule Iran 1978 1980 - Mar 20 24:00 1:00 -
+Rule Iran 1978 only - Oct 20 24:00 0 -
+Rule Iran 1979 only - Sep 18 24:00 0 -
+Rule Iran 1980 only - Sep 22 24:00 0 -
+Rule Iran 1991 only - May 2 24:00 1:00 -
+Rule Iran 1992 1995 - Mar 21 24:00 1:00 -
+Rule Iran 1991 1995 - Sep 21 24:00 0 -
+Rule Iran 1996 only - Mar 20 24:00 1:00 -
+Rule Iran 1996 only - Sep 20 24:00 0 -
+Rule Iran 1997 1999 - Mar 21 24:00 1:00 -
+Rule Iran 1997 1999 - Sep 21 24:00 0 -
+Rule Iran 2000 only - Mar 20 24:00 1:00 -
+Rule Iran 2000 only - Sep 20 24:00 0 -
+Rule Iran 2001 2003 - Mar 21 24:00 1:00 -
+Rule Iran 2001 2003 - Sep 21 24:00 0 -
+Rule Iran 2004 only - Mar 20 24:00 1:00 -
+Rule Iran 2004 only - Sep 20 24:00 0 -
+Rule Iran 2005 only - Mar 21 24:00 1:00 -
+Rule Iran 2005 only - Sep 21 24:00 0 -
+Rule Iran 2008 only - Mar 20 24:00 1:00 -
+Rule Iran 2008 only - Sep 20 24:00 0 -
+Rule Iran 2009 2011 - Mar 21 24:00 1:00 -
+Rule Iran 2009 2011 - Sep 21 24:00 0 -
+Rule Iran 2012 only - Mar 20 24:00 1:00 -
+Rule Iran 2012 only - Sep 20 24:00 0 -
+Rule Iran 2013 2015 - Mar 21 24:00 1:00 -
+Rule Iran 2013 2015 - Sep 21 24:00 0 -
+Rule Iran 2016 only - Mar 20 24:00 1:00 -
+Rule Iran 2016 only - Sep 20 24:00 0 -
+Rule Iran 2017 2019 - Mar 21 24:00 1:00 -
+Rule Iran 2017 2019 - Sep 21 24:00 0 -
+Rule Iran 2020 only - Mar 20 24:00 1:00 -
+Rule Iran 2020 only - Sep 20 24:00 0 -
+Rule Iran 2021 2023 - Mar 21 24:00 1:00 -
+Rule Iran 2021 2023 - Sep 21 24:00 0 -
+Rule Iran 2024 only - Mar 20 24:00 1:00 -
+Rule Iran 2024 only - Sep 20 24:00 0 -
+Rule Iran 2025 2027 - Mar 21 24:00 1:00 -
+Rule Iran 2025 2027 - Sep 21 24:00 0 -
+Rule Iran 2028 2029 - Mar 20 24:00 1:00 -
+Rule Iran 2028 2029 - Sep 20 24:00 0 -
+Rule Iran 2030 2031 - Mar 21 24:00 1:00 -
+Rule Iran 2030 2031 - Sep 21 24:00 0 -
+Rule Iran 2032 2033 - Mar 20 24:00 1:00 -
+Rule Iran 2032 2033 - Sep 20 24:00 0 -
+Rule Iran 2034 2035 - Mar 21 24:00 1:00 -
+Rule Iran 2034 2035 - Sep 21 24:00 0 -
+Rule Iran 2036 2037 - Mar 20 24:00 1:00 -
+Rule Iran 2036 2037 - Sep 20 24:00 0 -
+Rule Iran 2038 2039 - Mar 21 24:00 1:00 -
+Rule Iran 2038 2039 - Sep 21 24:00 0 -
+Rule Iran 2040 2041 - Mar 20 24:00 1:00 -
+Rule Iran 2040 2041 - Sep 20 24:00 0 -
+Rule Iran 2042 2043 - Mar 21 24:00 1:00 -
+Rule Iran 2042 2043 - Sep 21 24:00 0 -
+Rule Iran 2044 2045 - Mar 20 24:00 1:00 -
+Rule Iran 2044 2045 - Sep 20 24:00 0 -
+Rule Iran 2046 2047 - Mar 21 24:00 1:00 -
+Rule Iran 2046 2047 - Sep 21 24:00 0 -
+Rule Iran 2048 2049 - Mar 20 24:00 1:00 -
+Rule Iran 2048 2049 - Sep 20 24:00 0 -
+Rule Iran 2050 2051 - Mar 21 24:00 1:00 -
+Rule Iran 2050 2051 - Sep 21 24:00 0 -
+Rule Iran 2052 2053 - Mar 20 24:00 1:00 -
+Rule Iran 2052 2053 - Sep 20 24:00 0 -
+Rule Iran 2054 2055 - Mar 21 24:00 1:00 -
+Rule Iran 2054 2055 - Sep 21 24:00 0 -
+Rule Iran 2056 2057 - Mar 20 24:00 1:00 -
+Rule Iran 2056 2057 - Sep 20 24:00 0 -
+Rule Iran 2058 2059 - Mar 21 24:00 1:00 -
+Rule Iran 2058 2059 - Sep 21 24:00 0 -
+Rule Iran 2060 2062 - Mar 20 24:00 1:00 -
+Rule Iran 2060 2062 - Sep 20 24:00 0 -
+Rule Iran 2063 only - Mar 21 24:00 1:00 -
+Rule Iran 2063 only - Sep 21 24:00 0 -
+Rule Iran 2064 2066 - Mar 20 24:00 1:00 -
+Rule Iran 2064 2066 - Sep 20 24:00 0 -
+Rule Iran 2067 only - Mar 21 24:00 1:00 -
+Rule Iran 2067 only - Sep 21 24:00 0 -
+Rule Iran 2068 2070 - Mar 20 24:00 1:00 -
+Rule Iran 2068 2070 - Sep 20 24:00 0 -
+Rule Iran 2071 only - Mar 21 24:00 1:00 -
+Rule Iran 2071 only - Sep 21 24:00 0 -
+Rule Iran 2072 2074 - Mar 20 24:00 1:00 -
+Rule Iran 2072 2074 - Sep 20 24:00 0 -
+Rule Iran 2075 only - Mar 21 24:00 1:00 -
+Rule Iran 2075 only - Sep 21 24:00 0 -
+Rule Iran 2076 2078 - Mar 20 24:00 1:00 -
+Rule Iran 2076 2078 - Sep 20 24:00 0 -
+Rule Iran 2079 only - Mar 21 24:00 1:00 -
+Rule Iran 2079 only - Sep 21 24:00 0 -
+Rule Iran 2080 2082 - Mar 20 24:00 1:00 -
+Rule Iran 2080 2082 - Sep 20 24:00 0 -
+Rule Iran 2083 only - Mar 21 24:00 1:00 -
+Rule Iran 2083 only - Sep 21 24:00 0 -
+Rule Iran 2084 2086 - Mar 20 24:00 1:00 -
+Rule Iran 2084 2086 - Sep 20 24:00 0 -
+Rule Iran 2087 only - Mar 21 24:00 1:00 -
+Rule Iran 2087 only - Sep 21 24:00 0 -
+#
+# The following rules are approximations starting in the year 2088.
+# These are the best post-2088 approximations available, given the
+# restrictions of a single rule using ordinary Gregorian dates.
# At some point this table will need to be extended, though quite
# possibly Iran will change the rules first.
-Rule Iran 2036 max - Mar 21 0:00 1:00 -
-Rule Iran 2036 max - Sep 21 0:00 0 -
+Rule Iran 2088 max - Mar 20 24:00 1:00 -
+Rule Iran 2088 max - Sep 20 24:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Tehran 3:25:44 - LMT 1916
@@ -1456,6 +1643,24 @@ Rule Zion 1974 only - Jul 7 0:00 1:00 D
Rule Zion 1974 only - Oct 13 0:00 0 S
Rule Zion 1975 only - Apr 20 0:00 1:00 D
Rule Zion 1975 only - Aug 31 0:00 0 S
+
+# From Alois Treindl (2019-03-06):
+# http://www.moin.gov.il/Documents/שעון קיץ/clock-50-years-7-2014.pdf
+# From Isaac Starkman (2019-03-06):
+# Summer time was in that period in 1980 and 1984, see
+# https://www.ynet.co.il/articles/0,7340,L-3951073,00.html
+# You can of course read it in translation.
+# I checked the local newspapers for that years.
+# It started on midnight and end at 01.00 am.
+# From Paul Eggert (2019-03-06):
+# Also see this thread about the moin.gov.il URL:
+# https://mm.icann.org/pipermail/tz/2018-November/027194.html
+Rule Zion 1980 only - Aug 2 0:00 1:00 D
+Rule Zion 1980 only - Sep 13 1:00 0 S
+Rule Zion 1984 only - May 5 0:00 1:00 D
+Rule Zion 1984 only - Aug 25 1:00 0 S
+
+# From Shanks & Pottenger:
Rule Zion 1985 only - Apr 14 0:00 1:00 D
Rule Zion 1985 only - Sep 15 0:00 0 S
Rule Zion 1986 only - May 18 0:00 1:00 D
@@ -1714,7 +1919,9 @@ Rule Japan 1950 1951 - May Sat>=1 24:00 1:00 D
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Tokyo 9:18:59 - LMT 1887 Dec 31 15:00u
9:00 Japan J%sT
-# Since 1938, all Japanese possessions have been like Asia/Tokyo.
+# Since 1938, all Japanese possessions have been like Asia/Tokyo,
+# except that Truk (Chuuk), Ponape (Pohnpei), and Jaluit (Kosrae) did not
+# switch from +10 to +09 until 1941-04-01; see the 'australasia' file.
# Jordan
#
@@ -2004,8 +2211,10 @@ Zone Asia/Amman 2:23:44 - LMT 1931
# and in Byalokoz) lists Ural river (plus 10 versts on its left bank) in
# the third time belt (before 1930 this means +03).
-# From Paul Eggert (2016-12-06):
-# The tables below reflect Golosunov's remarks, with exceptions as noted.
+# From Alexander Konzurovski (2018-12-20):
+# Qyzyolrda Region (Asia/Qyzylorda) is changing its time zone from
+# UTC+6 to UTC+5 effective December 21st, 2018. The legal document is
+# located here: http://adilet.zan.kz/rus/docs/P1800000817 (russian language).
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
@@ -2019,8 +2228,6 @@ Zone Asia/Almaty 5:07:48 - LMT 1924 May 2 # or Alma-Ata
6:00 RussiaAsia +06/+07 2004 Oct 31 2:00s
6:00 - +06
# Qyzylorda (aka Kyzylorda, Kizilorda, Kzyl-Orda, etc.) (KZ-KZY)
-# This currently includes Qostanay (aka Kostanay, Kustanay) (KZ-KUS);
-# see comments below.
Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
5:00 - +05 1981 Apr 1
@@ -2031,21 +2238,22 @@ Zone Asia/Qyzylorda 4:21:52 - LMT 1924 May 2
5:00 RussiaAsia +05/+06 1992 Jan 19 2:00s
6:00 RussiaAsia +06/+07 1992 Mar 29 2:00s
5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
- 6:00 - +06
-# The following zone is like Asia/Qyzylorda except for being one
-# hour earlier from 1991-09-29 to 1992-03-29. The 1991/2 rules for
-# Qostanay are unclear partly because of the 1997 Turgai
-# reorganization, so this zone is commented out for now.
-#Zone Asia/Qostanay 4:14:20 - LMT 1924 May 2
-# 4:00 - +04 1930 Jun 21
-# 5:00 - +05 1981 Apr 1
-# 5:00 1:00 +06 1981 Oct 1
-# 6:00 - +06 1982 Apr 1
-# 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
-# 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
-# 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
-# 6:00 - +06
+ 6:00 - +06 2018 Dec 21 0:00
+ 5:00 - +05
#
+# Qostanay (aka Kostanay, Kustanay) (KZ-KUS)
+# The 1991/2 rules are unclear partly because of the 1997 Turgai
+# reorganization.
+Zone Asia/Qostanay 4:14:28 - LMT 1924 May 2
+ 4:00 - +04 1930 Jun 21
+ 5:00 - +05 1981 Apr 1
+ 5:00 1:00 +06 1981 Oct 1
+ 6:00 - +06 1982 Apr 1
+ 5:00 RussiaAsia +05/+06 1991 Mar 31 2:00s
+ 4:00 RussiaAsia +04/+05 1992 Jan 19 2:00s
+ 5:00 RussiaAsia +05/+06 2004 Oct 31 2:00s
+ 6:00 - +06
+
# Aqtöbe (aka Aktobe, formerly Aktyubinsk) (KZ-AKT)
Zone Asia/Aqtobe 3:48:40 - LMT 1924 May 2
4:00 - +04 1930 Jun 21
@@ -2139,21 +2347,43 @@ Zone Asia/Bishkek 4:58:24 - LMT 1924 May 2
# started at June 1 in that year. For another example, the article in
# 1988 said that DST started at 2:00 AM in that year.
+# From Phake Nick (2018-10-27):
+# 1. According to official announcement from Korean government, the DST end
+# date in South Korea should be
+# 1955-09-08 without specifying time
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027977557
+# 1956-09-29 without specifying time
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027978341
+# 1957-09-21 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027979690#3
+# 1958-09-20 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027981189
+# 1959-09-19 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0027982974#2
+# 1960-09-17 24 o'clock
+# http://theme.archives.go.kr/next/common/viewEbook.do?singleData=N&archiveEventId=0028044104
+# ...
+# 2.... https://namu.wiki/w/대한민국%20표준시 ... [says]
+# when Korea was using GMT+8:30 as standard time, the international
+# aviation/marine/meteorological industry in the country refused to
+# follow and continued to use GMT+9:00 for interoperability.
+
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule ROK 1948 only - Jun 1 0:00 1:00 D
-Rule ROK 1948 only - Sep 13 0:00 0 S
-Rule ROK 1949 only - Apr 3 0:00 1:00 D
-Rule ROK 1949 1951 - Sep Sun>=8 0:00 0 S
-Rule ROK 1950 only - Apr 1 0:00 1:00 D
-Rule ROK 1951 only - May 6 0:00 1:00 D
-Rule ROK 1955 only - May 5 0:00 1:00 D
-Rule ROK 1955 only - Sep 9 0:00 0 S
-Rule ROK 1956 only - May 20 0:00 1:00 D
-Rule ROK 1956 only - Sep 30 0:00 0 S
-Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
-Rule ROK 1957 1960 - Sep Sun>=18 0:00 0 S
-Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
-Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
+Rule ROK 1948 only - Jun 1 0:00 1:00 D
+Rule ROK 1948 only - Sep 12 24:00 0 S
+Rule ROK 1949 only - Apr 3 0:00 1:00 D
+Rule ROK 1949 1951 - Sep Sat>=7 24:00 0 S
+Rule ROK 1950 only - Apr 1 0:00 1:00 D
+Rule ROK 1951 only - May 6 0:00 1:00 D
+Rule ROK 1955 only - May 5 0:00 1:00 D
+Rule ROK 1955 only - Sep 8 24:00 0 S
+Rule ROK 1956 only - May 20 0:00 1:00 D
+Rule ROK 1956 only - Sep 29 24:00 0 S
+Rule ROK 1957 1960 - May Sun>=1 0:00 1:00 D
+Rule ROK 1957 1960 - Sep Sat>=17 24:00 0 S
+Rule ROK 1987 1988 - May Sun>=8 2:00 1:00 D
+Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
# From Paul Eggert (2016-08-23):
# The Korean Wikipedia entry gives the following sources for UT offsets:
@@ -2882,9 +3112,15 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# the official website, though the decree did not specify the exact
# time of the time shift.
# http://www.palestinecabinet.gov.ps/Website/AR/NDecrees/ViewFile.ashx?ID=e7a42ab7-ee23-435a-b9c8-a4f7e81f3817
+
+# From Even Scharning (2019-03-23):
+# DST in Palestine will start on 30 March this year, not 23 March as the time
+# zone database predicted.
+# https://ramallah.news/post/123610
#
-# From Paul Eggert (2018-03-16):
-# For 2016 on, predict spring transitions on March's fourth Saturday at 01:00.
+# From Tim Parenti (2019-03-23):
+# Combining this with the rules observed since 2016, adjust our spring
+# transition guess to Mar Sat>=24.
# From Sharef Mustafa (2018-03-16):
# Palestine summer time will start on Mar 24th 2018 by advancing the
@@ -2925,7 +3161,7 @@ Rule Palestine 2012 only - Sep 21 1:00 0 -
Rule Palestine 2013 only - Sep Fri>=21 0:00 0 -
Rule Palestine 2014 2015 - Oct Fri>=21 0:00 0 -
Rule Palestine 2015 only - Mar lastFri 24:00 1:00 S
-Rule Palestine 2016 max - Mar Sat>=22 1:00 1:00 S
+Rule Palestine 2016 max - Mar Sat>=24 1:00 1:00 S
Rule Palestine 2016 max - Oct lastSat 1:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -2953,6 +3189,11 @@ Zone Asia/Hebron 2:20:23 - LMT 1900 Oct
# no information
# Philippines
+
+# From Paul Eggert (2018-11-18):
+# The Spanish initially used American (west-of-Greenwich) time.
+# It is unknown what time Manila kept when the British occupied it from
+# 1762-10-06 through 1764-04; for now assume it kept American time.
# On 1844-08-16, Narciso Clavería, governor-general of the
# Philippines, issued a proclamation announcing that 1844-12-30 was to
# be immediately followed by 1845-01-01; see R.H. van Gent's
@@ -3038,8 +3279,8 @@ Link Asia/Qatar Asia/Bahrain
# going to run on Higgins Time.' And so, until last year, it did." See:
# Antar E. Dinner at When? Saudi Aramco World, 1969 March/April. 2-3.
# http://archive.aramcoworld.com/issue/196902/dinner.at.when.htm
-# newspapers.com says a similar story about Higgins was published in the Port
-# Angeles (WA) Evening News, 1965-03-10, page 5, but I lack access to the text.
+# Also see: Antar EN. Arabian flying is confusing.
+# Port Angeles (WA) Evening News. 1965-03-10. page 3.
#
# The TZ database cannot represent quasi-solar time; airline time is the best
# we can do. The 1946 foreign air news digest of the U.S. Civil Aeronautics
@@ -3412,5 +3653,17 @@ Zone Asia/Ho_Chi_Minh 7:06:40 - LMT 1906 Jul 1
8:00 - +08 1975 Jun 13
7:00 - +07
+# From Paul Eggert (2019-02-19):
+#
+# The Ho Chi Minh entry suffices for most purposes as it agrees with all of
+# Vietnam since 1975-06-13. Presumably clocks often changed in south Vietnam
+# in the early 1970s as locations changed hands during the war; however the
+# details are unknown and would likely be too voluminous for this database.
+#
+# For timestamps in north Vietnam back to 1970 (the tzdb cutoff),
+# use Asia/Bangkok; see the VN entries in the file zone1970.tab.
+# For timestamps before 1970, see Asia/Hanoi in the file 'backzone'.
+
+
# Yemen
# See Asia/Riyadh.
diff --git a/test/sun/util/calendar/zi/tzdata/australasia b/test/sun/util/calendar/zi/tzdata/australasia
index 82e88c51e9..887203e45e 100644
--- a/test/sun/util/calendar/zi/tzdata/australasia
+++ b/test/sun/util/calendar/zi/tzdata/australasia
@@ -425,10 +425,44 @@ Zone Pacific/Tahiti -9:58:16 - LMT 1912 Oct # Papeete
# it is uninhabited.
# Guam
+
+# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
+# http://guamlegislature.com/Public_Laws_5th/PL05-025.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-59-7-Guam-Daylight-Savings-Time-May-6-1959.pdf
+Rule Guam 1959 only - Jun 27 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-61-5-Revocation-of-Daylight-Saving-Time-and-Restoratio.pdf
+Rule Guam 1961 only - Jan 29 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-67-13-Guam-Daylight-Savings-Time.pdf
+Rule Guam 1967 only - Sep 1 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-69-2-Repeal-of-Guam-Daylight-Saving-Time.pdf
+Rule Guam 1969 only - Jan 26 0:01 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-69-10-Guam-Daylight-Saving-Time.pdf
+Rule Guam 1969 only - Jun 22 2:00 1:00 D
+Rule Guam 1969 only - Aug 31 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-70-10-Guam-Daylight-Saving-Time.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-70-30-End-of-Guam-Daylight-Saving-Time.pdf
+# http://documents.guam.gov/wp-content/uploads/E.O.-71-5-Guam-Daylight-Savings-Time.pdf
+Rule Guam 1970 1971 - Apr lastSun 2:00 1:00 D
+Rule Guam 1970 1971 - Sep Sun>=1 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-73-28.-Guam-Day-light-Saving-Time.pdf
+Rule Guam 1973 only - Dec 16 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-74-7-Guam-Daylight-Savings-Time-Rescinded.pdf
+Rule Guam 1974 only - Feb 24 2:00 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-76-13-Daylight-Savings-Time.pdf
+Rule Guam 1976 only - May 26 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-76-25-Revocation-of-E.O.-76-13.pdf
+Rule Guam 1976 only - Aug 22 2:01 0 S
+# http://documents.guam.gov/wp-content/uploads/E.O.-77-4-Daylight-Savings-Time.pdf
+Rule Guam 1977 only - Apr 24 2:00 1:00 D
+# http://documents.guam.gov/wp-content/uploads/E.O.-77-18-Guam-Standard-Time.pdf
+Rule Guam 1977 only - Aug 28 2:00 0 S
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Guam -14:21:00 - LMT 1844 Dec 31
9:39:00 - LMT 1901 # Agana
- 10:00 - GST 2000 Dec 23 # Guam
+ 10:00 - GST 1941 Dec 10 # Guam
+ 9:00 - +09 1944 Jul 31
+ 10:00 Guam G%sT 2000 Dec 23
10:00 - ChST # Chamorro Standard Time
Link Pacific/Guam Pacific/Saipan # N Mariana Is
@@ -450,31 +484,56 @@ Zone Pacific/Kiritimati -10:29:20 - LMT 1901
# Marshall Is
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Majuro 11:24:48 - LMT 1901
- 11:00 - +11 1969 Oct
- 12:00 - +12
-Zone Pacific/Kwajalein 11:09:20 - LMT 1901
- 11:00 - +11 1969 Oct
- -12:00 - -12 1993 Aug 20
- 12:00 - +12
+Zone Pacific/Majuro 11:24:48 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1944 Jan 30
+ 11:00 - +11 1969 Oct
+ 12:00 - +12
+Zone Pacific/Kwajalein 11:09:20 - LMT 1901
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1944 Feb 6
+ 11:00 - +11 1969 Oct
+ -12:00 - -12 1993 Aug 20 24:00
+ 12:00 - +12
# Micronesia
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Chuuk 10:07:08 - LMT 1901
- 10:00 - +10
-Zone Pacific/Pohnpei 10:32:52 - LMT 1901 # Kolonia
- 11:00 - +11
-Zone Pacific/Kosrae 10:51:56 - LMT 1901
- 11:00 - +11 1969 Oct
- 12:00 - +12 1999
- 11:00 - +11
+Zone Pacific/Chuuk -13:52:52 - LMT 1844 Dec 31
+ 10:07:08 - LMT 1901
+ 10:00 - +10 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 10:00 - +10
+Zone Pacific/Pohnpei -13:27:08 - LMT 1844 Dec 31 # Kolonia
+ 10:32:52 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 11:00 - +11
+Zone Pacific/Kosrae -13:08:04 - LMT 1844 Dec 31
+ 10:51:56 - LMT 1901
+ 11:00 - +11 1914 Oct
+ 9:00 - +09 1919 Feb 1
+ 11:00 - +11 1937
+ 10:00 - +10 1941 Apr 1
+ 9:00 - +09 1945 Aug
+ 11:00 - +11 1969 Oct
+ 12:00 - +12 1999
+ 11:00 - +11
# Nauru
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Pacific/Nauru 11:07:40 - LMT 1921 Jan 15 # Uaobe
- 11:30 - +1130 1942 Mar 15
- 9:00 - +09 1944 Aug 15
- 11:30 - +1130 1979 May
+ 11:30 - +1130 1942 Aug 29
+ 9:00 - +09 1945 Sep 8
+ 11:30 - +1130 1979 Feb 10 2:00
12:00 - +12
# New Caledonia
@@ -575,8 +634,9 @@ Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston
# Palau (Belau)
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Pacific/Palau 8:57:56 - LMT 1901 # Koror
- 9:00 - +09
+Zone Pacific/Palau -15:02:04 - LMT 1844 Dec 31 # Koror
+ 8:57:56 - LMT 1901
+ 9:00 - +09
# Papua New Guinea
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -838,7 +898,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
-# From Paul Eggert (2017-02-10):
+# From Paul Eggert (2018-11-18):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@@ -863,6 +923,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# A reliable and entertaining source about time zones is
# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
#
+# I invented the abbreviation marked "*".
# The following abbreviations are from other sources.
# Corrections are welcome!
# std dst
@@ -870,7 +931,7 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# 8:00 AWST AWDT Western Australia
# 9:30 ACST ACDT Central Australia
# 10:00 AEST AEDT Eastern Australia
-# 10:00 GST Guam through 2000
+# 10:00 GST GDT* Guam through 2000
# 10:00 ChST Chamorro
# 11:30 NZMT NZST New Zealand through 1945
# 12:00 NZST NZDT New Zealand 1946-present
@@ -1569,28 +1630,70 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# Kwajalein
-# In comp.risks 14.87 (26 August 1993), Peter Neumann writes:
-# I wonder what happened in Kwajalein, where there was NO Friday,
-# 1993-08-20. Thursday night at midnight Kwajalein switched sides with
-# respect to the International Date Line, to rejoin its fellow islands,
-# going from 11:59 p.m. Thursday to 12:00 m. Saturday in a blink.
+# From an AP article (1993-08-22):
+# "The nearly 3,000 Americans living on this remote Pacific atoll have a good
+# excuse for not remembering Saturday night: there wasn't one. Residents were
+# going to bed Friday night and waking up Sunday morning because at midnight
+# -- 8 A.M. Eastern daylight time on Saturday -- Kwajalein was jumping from
+# one side of the international date line to the other."
+# "In Marshall Islands, Friday is followed by Sunday", NY Times. 1993-08-22.
+# https://www.nytimes.com/1993/08/22/world/in-marshall-islands-friday-is-followed-by-sunday.html
+
+# From Phake Nick (2018-10-27):
+# <https://wiki.suikawiki.org/n/南洋群島の標準時> ... pointed out that
+# currently tzdata say Pacific/Kwajalein switched from GMT+11 to GMT-12 in
+# 1969 October without explanation, however an 1993 article from NYT say it
+# synchorized its day with US mainland about 40 years ago and thus the switch
+# should occur at around 1950s instead.
+#
+# From Paul Eggert (2018-11-18):
+# The NYT (actually, AP) article is vague and possibly wrong about this.
+# The article says the earlier switch was "40 years ago when the United States
+# Army established a missile test range here". However, the Kwajalein Test
+# Center was established on 1960-10-01 and was run by the US Navy. It was
+# transferred to the US Army on 1964-07-01. See "Seize the High Ground"
+# <https://history.army.mil/html/books/070/70-88-1/cmhPub_70-88-1.pdf>.
+# Given that Shanks was right on the money about the 1993 change, I'm inclined
+# to take Shanks's word for the 1969 change unless we find better evidence.
# N Mariana Is, Guam
+# From Phake Nick (2018-10-27):
+# Guam Island was briefly annexed by Japan during ... year 1941-1944 ...
+# however there are no detailed information about what time it use during that
+# period. It would probably be reasonable to assume Guam use GMT+9 during
+# that period of time like the surrounding area.
+
+# From Paul Eggert (2018-11-18):
# Howse writes (p 153) "The Spaniards, on the other hand, reached the
# Philippines and the Ladrones from America," and implies that the Ladrones
# (now called the Marianas) kept American date for quite some time.
# For now, we assume the Ladrones switched at the same time as the Philippines;
# see Asia/Manila.
-
+#
+# Use 1941-12-10 and 1944-07-31 for Guam WWII transitions, as the rough start
+# and end of Japanese control of Agana. We don't know whether the Northern
+# Marianas followed Guam's DST rules from 1959 through 1977; for now, assume
+# they did as that avoids the need for a separate zone due to our 1970 cutoff.
+#
# US Public Law 106-564 (2000-12-23) made UT +10 the official standard time,
# under the name "Chamorro Standard Time". There is no official abbreviation,
# but Congressman Robert A. Underwood, author of the bill that became law,
# wrote in a press release (2000-12-27) that he will seek the use of "ChST".
+# See also the commentary for Micronesia.
-# Micronesia
+
+# Marshall Is
+# See the commentary for Micronesia.
+
+
+# Micronesia (and nearby)
+
+# From Paul Eggert (2018-11-18):
+# Like the Ladrones (see Guam commentary), assume the Spanish East Indies
+# kept American time until the Philippines switched at the end of 1844.
# Alan Eugene Davis writes (1996-03-16),
# "I am certain, having lived there for the past decade, that 'Truk'
@@ -1606,6 +1709,95 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# that Truk and Yap are UT +10, and Ponape and Kosrae are +11.
# We don't know when Kosrae switched from +12; assume January 1 for now.
+# From Phake Nick (2018-10-27):
+#
+# From a Japanese wiki site https://wiki.suikawiki.org/n/南洋群島の標準時
+# ...
+# For "Southern Islands" (modern region of Mariana + Palau + Federation of
+# Micronesia + Marshall Islands):
+#
+# A 1906 Japanese magazine shown the Caroline Islands and Mariana Islands
+# who was occupied by Germany at the time as GMT+10, together with the like
+# of German New Guinea. However there is a marking saying it have not been
+# implemented (yet). No further information after that were found.
+#
+# Japan invaded those islands in 1914, and records shows that they were
+# instructed to use JST at the time.
+#
+# 1915 January telecommunication record on the Jaluit Atoll shows they use
+# the meridian of 170E as standard time (GMT+11:20), which is similar to the
+# longitude of the atoll.
+# 1915 February record say the 170E standard time is to be used until
+# February 9 noon, and after February 9 noon they are to use JST.
+# However these are time used within the Japanese Military at the time and
+# probably does not reflect the time used by local resident at the time (that
+# is if they keep their own time back then)
+#
+# In January 1919 the occupying force issued a command that split the area
+# into three different timezone with meridian of 135E, 150E, 165E (JST+0, +1,
+# +2), and the command was to become effective from February 1 of the same
+# year. Despite the target of the command is still only for the occupying
+# force itself, further publication have described the time as the standard
+# time for the occupied area and thus it can probably be seen as such.
+# * Area that use meridian of 135E: Palau and Yap civil administration area
+# (Southern Islands Western Standard Time)
+# * Area that use meridian of 150E: Truk (Chuuk) and Saipan civil
+# administration area (Southern Islands Central Standard Time)
+# * Area that use meridian of 165E: Ponape (Pohnpei) and Jaluit civil
+# administration area (Southern Islands Eastern Standard Time).
+# * In the next few years Japanese occupation of those islands have been
+# formalized via League of Nation Mandate (South Pacific Mandate) and formal
+# governance structure have been established, these district [become
+# subprefectures] and timezone classification have been inherited as standard
+# time of the area.
+# * Saipan subprefecture include Mariana islands (exclude Guam which was
+# occupied by America at the time), Palau and Yap subprefecture rule the
+# Western Caroline Islands with 137E longitude as border, Truk and Ponape
+# subprefecture rule the Eastern Caroline Islands with 154E as border, Ponape
+# subprefecture also rule part of Marshall Islands to the west of 164E
+# starting from (1918?) and Jaluit subprefecture rule the rest of the
+# Marshall Islands.
+#
+# And then in year 1937, an announcement was made to change the time in the
+# area into 2 timezones:
+# * Area that use meridian of 135E: area administered by Palau, Yap and
+# Saipan subprefecture (Southern Islands Western Standard Time)
+# * Area that use meridian of 150E: area administered by Truk (Chuuk),
+# Ponape (Pohnpei) and Jaluit subprefecture (Southern Islands Eastern
+# Standard Time)
+#
+# Another announcement issued in 1941 say that on April 1 that year,
+# standard time of the Southern Islands would be changed to use the meridian
+# of 135E (GMT+9), and thus abolishing timezone different within the area.
+#
+# Then Pacific theater of WWII started and Japan slowly lose control on the
+# island. The webpage I linked above contain no information during this
+# period of time....
+#
+# After the end of WWII, in 1946 February, a document written by the
+# (former?) Japanese military personnel describe there are 3 hours time
+# different between Caroline islands time/Wake island time and the Chungking
+# time, which would mean the time being used there at the time was GMT+10.
+#
+# After that, the area become Trust Territories of the Pacific Islands
+# under American administration from year 1947. The site listed some
+# American/International books/maps/publications about time used in those
+# area during this period of time but they doesn't seems to be reliable
+# information so it would be the best if someone know where can more reliable
+# information can be found.
+#
+#
+# From Paul Eggert (2018-11-18):
+#
+# For the above, use vague dates like "1914" and "1945" for transitions that
+# plausibly exist but for which the details are not known. The information
+# for Wake is too sketchy to act on.
+#
+# The 1906 GMT+10 info about German-controlled islands might not have been
+# done, so omit it from the data for now.
+#
+# The Jaluit info governs Kwajalein.
+
# Midway
@@ -1623,6 +1815,29 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# started DST on June 3. Possibly DST was observed other years
# in Midway, but we have no record of it.
+# Nauru
+
+# From Phake Nick (2018-10-31):
+# Currently, the tz database say Nauru use LMT until 1921, and then
+# switched to GMT+11:30 for the next two decades.
+# However, a number of timezone map published in America/Japan back then
+# showed its timezone as GMT+11 per https://wiki.suikawiki.org/n/ナウルの標準時
+# And it would also be nice if the 1921 transition date could be sourced.
+# ...
+# The "Nauru Standard Time Act 1978 Time Change"
+# http://ronlaw.gov.nr/nauru_lpms/files/gazettes/4b23a17d2030150404db7a5fa5872f52.pdf#page=3
+# based on "Nauru Standard Time Act 1978 Time Change"
+# http://www.paclii.org/nr/legis/num_act/nsta1978207/ defined that "Nauru
+# Alternative Time" (GMT+12) should be in effect from 1979 Feb.
+#
+# From Paul Eggert (2018-11-19):
+# The 1921-01-15 introduction of standard time is in Shanks; it is also in
+# "Standard Time Throughout the World", US National Bureau of Standards (1935),
+# page 3, which does not give the UT offset. In response to a comment by
+# Phake Nick I set the Nauru time of occupation by Japan to
+# 1942-08-29/1945-09-08 by using dates from:
+# https://en.wikipedia.org/wiki/Japanese_occupation_of_Nauru
+
# Norfolk
# From Alexander Krivenyshev (2015-09-23):
@@ -1638,6 +1853,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# other than in 1974/5. See:
# https://www.timeanddate.com/time/australia/norfolk-island.html
+# Palau
+# See commentary for Micronesia.
+
# Pitcairn
# From Rives McDow (1999-11-08):
@@ -1802,6 +2020,9 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# From Paul Eggert (2003-03-23):
# We have no other report of DST in Wake Island, so omit this info for now.
+# See also the commentary for Micronesia.
+
+
###############################################################################
# The International Date Line
diff --git a/test/sun/util/calendar/zi/tzdata/backward b/test/sun/util/calendar/zi/tzdata/backward
index f30f30e511..2a41a98010 100644
--- a/test/sun/util/calendar/zi/tzdata/backward
+++ b/test/sun/util/calendar/zi/tzdata/backward
@@ -100,6 +100,7 @@ Link Pacific/Easter Chile/EasterIsland
Link America/Havana Cuba
Link Africa/Cairo Egypt
Link Europe/Dublin Eire
+Link Etc/UTC Etc/UCT
Link Europe/London Europe/Belfast
Link Europe/Chisinau Europe/Tiraspol
Link Europe/London GB
@@ -134,7 +135,7 @@ Link Asia/Taipei ROC
Link Asia/Seoul ROK
Link Asia/Singapore Singapore
Link Europe/Istanbul Turkey
-Link Etc/UCT UCT
+Link Etc/UTC UCT
Link America/Anchorage US/Alaska
Link America/Adak US/Aleutian
Link America/Phoenix US/Arizona
diff --git a/test/sun/util/calendar/zi/tzdata/etcetera b/test/sun/util/calendar/zi/tzdata/etcetera
index db5937879e..7c7eab1f6a 100644
--- a/test/sun/util/calendar/zi/tzdata/etcetera
+++ b/test/sun/util/calendar/zi/tzdata/etcetera
@@ -42,7 +42,6 @@
Zone Etc/GMT 0 - GMT
Zone Etc/UTC 0 - UTC
-Zone Etc/UCT 0 - UCT
# The following link uses older naming conventions,
# but it belongs here, not in the file 'backward',
diff --git a/test/sun/util/calendar/zi/tzdata/europe b/test/sun/util/calendar/zi/tzdata/europe
index e434b7e9fc..56a38839e5 100644
--- a/test/sun/util/calendar/zi/tzdata/europe
+++ b/test/sun/util/calendar/zi/tzdata/europe
@@ -1878,7 +1878,7 @@ Zone Europe/Luxembourg 0:24:36 - LMT 1904 Jun
1:00 Belgium CE%sT 1977
1:00 EU CE%sT
-# Macedonia
+# North Macedonia
# See Europe/Belgrade.
# Malta
@@ -3382,7 +3382,7 @@ Zone Europe/Belgrade 1:22:00 - LMT 1884
Link Europe/Belgrade Europe/Ljubljana # Slovenia
Link Europe/Belgrade Europe/Podgorica # Montenegro
Link Europe/Belgrade Europe/Sarajevo # Bosnia and Herzegovina
-Link Europe/Belgrade Europe/Skopje # Macedonia
+Link Europe/Belgrade Europe/Skopje # North Macedonia
Link Europe/Belgrade Europe/Zagreb # Croatia
# Slovakia
diff --git a/test/sun/util/calendar/zi/tzdata/iso3166.tab b/test/sun/util/calendar/zi/tzdata/iso3166.tab
index 38a3a1ed52..544b3034c1 100644
--- a/test/sun/util/calendar/zi/tzdata/iso3166.tab
+++ b/test/sun/util/calendar/zi/tzdata/iso3166.tab
@@ -32,8 +32,8 @@
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
-# ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1
-# http://isotc.iso.org/livelink/livelink/Open/16944257
+# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1
+# https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists.
# This is not the same as the English name in the ISO 3166 tables.
@@ -189,7 +189,7 @@ ME Montenegro
MF St Martin (French)
MG Madagascar
MH Marshall Islands
-MK Macedonia
+MK North Macedonia
ML Mali
MM Myanmar (Burma)
MN Mongolia
@@ -258,7 +258,7 @@ ST Sao Tome & Principe
SV El Salvador
SX St Maarten (Dutch)
SY Syria
-SZ Swaziland
+SZ Eswatini (Swaziland)
TC Turks & Caicos Is
TD Chad
TF French Southern & Antarctic Lands
diff --git a/test/sun/util/calendar/zi/tzdata/leapseconds b/test/sun/util/calendar/zi/tzdata/leapseconds
index 8b539e6ef4..2d05e87c63 100644
--- a/test/sun/util/calendar/zi/tzdata/leapseconds
+++ b/test/sun/util/calendar/zi/tzdata/leapseconds
@@ -42,9 +42,12 @@
# See: Levine J. Coordinated Universal Time and the leap second.
# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995
# <https://ieeexplore.ieee.org/document/7909995>.
+
# There were no leap seconds before 1972, because the official mechanism
# accounting for the discrepancy between atomic time and the earth's rotation
-# did not exist.
+# did not exist. The first ("1 Jan 1972") data line in leap-seconds.list
+# does not denote a leap second; it denotes the start of the current definition
+# of UTC.
# The correction (+ or -) is made at the given time, so lines
# will typically look like:
@@ -83,7 +86,7 @@ Leap 2016 Dec 31 23:59:60 + S
# POSIX timestamps for the data in this file:
#updated 1467936000
-#expires 1561680000
+#expires 1577491200
-# Updated through IERS Bulletin C56
-# File expires on: 28 June 2019
+# Updated through IERS Bulletin C57
+# File expires on: 28 December 2019
diff --git a/test/sun/util/calendar/zi/tzdata/northamerica b/test/sun/util/calendar/zi/tzdata/northamerica
index 297a10a384..c460a4b1ff 100644
--- a/test/sun/util/calendar/zi/tzdata/northamerica
+++ b/test/sun/util/calendar/zi/tzdata/northamerica
@@ -622,6 +622,26 @@ Zone America/Los_Angeles -7:52:58 - LMT 1883 Nov 18 12:07:02
# between AKST and AKDT from now on....
# https://www.krbd.org/2015/10/30/annette-island-times-they-are-a-changing/
+# From Ryan Stanley (2018-11-06):
+# The Metlakatla community in Alaska has decided not to change its
+# clock back an hour starting on November 4th, 2018 (day before yesterday).
+# They will be gmtoff=-28800 year-round.
+# https://www.facebook.com/141055983004923/photos/pb.141055983004923.-2207520000.1541465673./569081370202380/
+
+# From Paul Eggert (2018-12-16):
+# In a 2018-12-11 special election, Metlakatla voted to go back to
+# Alaska time (including daylight saving time) starting next year.
+# https://www.krbd.org/2018/12/12/metlakatla-to-follow-alaska-standard-time-allow-liquor-sales/
+#
+# From Ryan Stanley (2019-01-11):
+# The community will be changing back on the 20th of this month...
+# From Tim Parenti (2019-01-11):
+# Per an announcement on the Metlakatla community's official Facebook page, the
+# "fall back" will be on Sunday 2019-01-20 at 02:00:
+# https://www.facebook.com/141055983004923/photos/607150969728753/
+# So they won't be waiting for Alaska to join them on 2019-03-10, but will
+# rather change their clocks twice in seven weeks.
+
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Juneau 15:02:19 - LMT 1867 Oct 19 15:33:32
-8:57:41 - LMT 1900 Aug 20 12:00
@@ -648,6 +668,8 @@ Zone America/Metlakatla 15:13:42 - LMT 1867 Oct 19 15:44:55
-8:00 - PST 1969
-8:00 US P%sT 1983 Oct 30 2:00
-8:00 - PST 2015 Nov 1 2:00
+ -9:00 US AK%sT 2018 Nov 4 2:00
+ -8:00 - PST 2019 Jan 20 2:00
-9:00 US AK%sT
Zone America/Yakutat 14:41:05 - LMT 1867 Oct 19 15:12:18
-9:18:55 - LMT 1900 Aug 20 12:00
@@ -808,6 +830,22 @@ Zone America/Boise -7:44:49 - LMT 1883 Nov 18 12:15:11
# For a map of Indiana's time zone regions, see:
# https://en.wikipedia.org/wiki/Time_in_Indiana
#
+# From Paul Eggert (2018-11-30):
+# A brief but entertaining history of time in Indiana describes a 1949 debate
+# in the Indiana House where city legislators (who favored "fast time")
+# tussled with farm legislators (who didn't) over a bill to outlaw DST:
+# "Lacking enough votes, the city faction tries to filibuster until time runs
+# out on the session at midnight, but rural champion Rep. Herbert Copeland,
+# R-Madison, leans over the gallery railing and forces the official clock
+# back to 9 p.m., breaking it in the process. The clock sticks on 9 as the
+# debate rages on into the night. The filibuster finally dies out and the
+# bill passes, while outside the chamber, clocks read 3:30 a.m. In the end,
+# it doesn't matter which side won. The law has no enforcement powers and
+# is simply ignored by fast-time communities."
+# How Indiana went from 'God's time' to split zones and daylight-saving.
+# Indianapolis Star. 2018-11-27 14:58 -05.
+# https://www.indystar.com/story/news/politics/2018/11/27/indianapolis-indiana-time-zone-history-central-eastern-daylight-savings-time/2126300002/
+#
# From Paul Eggert (2007-08-17):
# Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
# with the following exceptions:
diff --git a/test/sun/util/calendar/zi/tzdata/zone.tab b/test/sun/util/calendar/zi/tzdata/zone.tab
index 2a985868d2..4959859585 100644
--- a/test/sun/util/calendar/zi/tzdata/zone.tab
+++ b/test/sun/util/calendar/zi/tzdata/zone.tab
@@ -262,6 +262,7 @@ KW +2920+04759 Asia/Kuwait
KY +1918-08123 America/Cayman
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
KZ +5017+05710 Asia/Aqtobe Aqtobe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystau/Mankistau
KZ +4707+05156 Asia/Atyrau Atyrau/Atirau/Gur'yev
@@ -355,9 +356,9 @@ RS +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
RU +4457+03406 Europe/Simferopol MSK+00 - Crimea
-RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
+RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
diff --git a/test/tools/launcher/RunpathTest.java b/test/tools/launcher/RunpathTest.java
index 26233b2856..87dec4d4c2 100644
--- a/test/tools/launcher/RunpathTest.java
+++ b/test/tools/launcher/RunpathTest.java
@@ -57,14 +57,14 @@ public class RunpathTest extends TestHelper {
final TestResult tr = doExec(elfreaderCmd, "-d", javacmd);
if (!tr.matches(expectedRpath)) {
System.out.println(tr);
- throw new RuntimeException("FAILED: RPATH strings " +
+ throw new RuntimeException("FAILED: RPATH/RUNPATH strings " +
expectedRpath + " not found in " + javaCmd);
}
- System.out.println(javacmd + " contains expected RPATHS");
+ System.out.println(javacmd + " contains expected RPATHS/RUNPATH");
}
void testRpath() {
- String expectedRpath = ".*RPATH.*\\$ORIGIN/../lib/" + getJreArch() + ".*";
+ String expectedRpath = ".*R(UN)?PATH.*\\$ORIGIN/../lib/" + getJreArch() + ".*";
elfCheck(javaCmd, expectedRpath);
}
diff --git a/testjbu/quality/text/BundledFontTest.java b/testjbu/quality/text/BundledFontTest.java
new file mode 100644
index 0000000000..1e0aee1084
--- /dev/null
+++ b/testjbu/quality/text/BundledFontTest.java
@@ -0,0 +1,120 @@
+package quality.text;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.Locale;
+
+public class BundledFontTest {
+ /* Tests for the following font names:
+ "droid sans"
+ "droid sans bold"
+ "droid sans mono"
+ "droid sans mono slashed"
+ "droid sans mono dotted"
+ "droid serif"
+ "droid serif bold"
+ "fira code"
+ "fira code light"
+ "fira code medium"
+ "fira code retina"
+ "inconsolata"
+ "roboto light"
+ "roboto thin"
+ "source code pro"
+ */
+
+ @SuppressWarnings("SameParameterValue")
+ private void doTestFont(String aliasName, String name)
+ throws Exception {
+
+
+ Font f = new Font(aliasName, Font.PLAIN, 20);
+ String family = f.getFamily(Locale.ENGLISH);
+
+ Assert.assertTrue(family.equalsIgnoreCase(name));
+ }
+
+ private void doTestFont(String name)
+ throws Exception {
+ doTestFont(name, name);
+ }
+
+ @Test
+ public void testDroidSans() throws Exception {
+ doTestFont("Droid Sans");
+ }
+
+ @Test
+ public void testDroidSansBold() throws Exception {
+ doTestFont("Droid Sans");
+ doTestFont("Droid Sans Bold", "Droid Sans");
+ }
+
+ @Test
+ public void testDroidSansMono() throws Exception {
+ doTestFont("Droid Sans Mono");
+ }
+
+ @Test
+ public void testDroidSansMonoSlashed() throws Exception {
+ doTestFont("Droid Sans Mono Slashed");
+ }
+
+ @Test
+ public void testDroidSansMonoDotted() throws Exception {
+ doTestFont("Droid Sans Mono Dotted");
+ }
+
+ @Test
+ public void testDroidSerif() throws Exception {
+ doTestFont("Droid Serif");
+ }
+
+ @Test
+ public void testDroidSerifBold() throws Exception {
+ doTestFont("Droid Serif");
+ doTestFont("Droid Serif Bold", "Droid Serif");
+ }
+
+ @Test
+ public void testDroidSerifItalic() throws Exception {
+ doTestFont("Droid Serif");
+ doTestFont("Droid Serif Italic", "Droid Serif");
+ }
+
+ @Test
+ public void testFiraCode() throws Exception {
+ doTestFont("Fira Code");
+ }
+
+ @Test
+ public void testFiraCodeLight() throws Exception {
+ doTestFont("Fira Code Light");
+ }
+
+ @Test
+ public void testFiraCodeMedium() throws Exception {
+ doTestFont("Fira Code Medium");
+ }
+
+ @Test
+ public void testInconsolata() throws Exception {
+ doTestFont("Inconsolata");
+ }
+
+ @Test
+ public void testRobotoLight() throws Exception {
+ doTestFont("Roboto Light");
+ }
+ @Test
+ public void testRobotoThin() throws Exception {
+ doTestFont("Roboto Thin");
+ }
+
+ @Test
+ public void testSourceCodePro() throws Exception {
+ doTestFont("Source Code Pro");
+ }
+}