From 86d36e5d55b37512aace2759dfb81effb8e377ab Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sun, 11 Nov 2012 10:05:37 +0000 Subject: [PATCH 01/18] 8003253: TEST_BUG: java/nio/channels/AsynchronousChannelGroup/Unbounded.java hang intermittently [win] Reviewed-by: chegar --- .../channels/AsynchronousChannelGroup/Unbounded.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java index 0ca96fbbb3d..6e764a2b671 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java @@ -36,6 +36,9 @@ public class Unbounded { // number of concurrent completion handlers static final int CONCURRENCY_COUNT = 256; + // set to true if an I/O operation fails + static volatile boolean failed; + public static void main(String[] args) throws Exception { // all accepted connections are added to a queue final ArrayBlockingQueue queue = @@ -51,6 +54,8 @@ public class Unbounded { listener.accept((Void)null, this); } public void failed(Throwable exc, Void att) { + failed = true; + System.err.println("accept failed: " + exc); } }); System.out.println("Listener created."); @@ -94,6 +99,9 @@ public class Unbounded { } } public void failed(Throwable exc, AsynchronousSocketChannel ch) { + failed = true; + System.err.println("read failed: " + exc); + completed(0, ch); } }); } @@ -104,6 +112,7 @@ public class Unbounded { while (remaining > 0) { AsynchronousSocketChannel ch = queue.take(); ch.write(ByteBuffer.wrap("welcome".getBytes())).get(); + ch.shutdownOutput(); ch.close(); remaining--; } @@ -112,5 +121,7 @@ public class Unbounded { System.out.println("Waiting for all threads to reach barrier"); barrier.await(); listener.close(); + if (failed) + throw new RuntimeException("I/O failed failed, see log for details"); } } From aaa52056e9577bfcdd13e3744510f5a0dbb761af Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Mon, 12 Nov 2012 11:12:29 +0900 Subject: [PATCH 02/18] 8000986: Split java.util.spi.CalendarDataProvider into week parameters and field names portions Reviewed-by: naoto --- jdk/make/java/java/FILES_java.gmk | 2 + .../HostLocaleProviderAdapterImpl.java | 35 ++- jdk/src/share/classes/java/util/Calendar.java | 7 +- .../java/util/spi/CalendarDataProvider.java | 224 +-------------- .../java/util/spi/CalendarNameProvider.java | 264 ++++++++++++++++++ .../provider/AuxLocaleProviderAdapter.java | 5 + .../provider/CalendarDataProviderImpl.java | 150 +--------- .../locale/provider/CalendarDataUtility.java | 62 +++- .../provider/CalendarNameProviderImpl.java | 234 ++++++++++++++++ .../provider/JRELocaleProviderAdapter.java | 27 +- .../provider/LocaleProviderAdapter.java | 9 + .../provider/SPILocaleProviderAdapter.java | 59 +++- .../HostLocaleProviderAdapterImpl.java | 52 ++-- .../CalendarDataProviderTest.java | 51 +--- .../CalendarDataProviderTest.sh | 2 +- .../CalendarNameProviderTest.java | 104 +++++++ .../CalendarNameProviderTest.sh | 27 ++ .../util/PluggableLocale/GenericTest.java | 2 + .../java/util/PluggableLocale/barprovider.jar | Bin 13747 -> 14629 bytes .../java/util/PluggableLocale/fooprovider.jar | Bin 16866 -> 16866 bytes .../providersrc/CalendarDataProviderImpl.java | 58 ---- .../providersrc/CalendarNameProviderImpl.java | 102 +++++++ .../util/PluggableLocale/providersrc/Makefile | 9 +- .../java.util.spi.CalendarNameProvider | 7 + 24 files changed, 963 insertions(+), 529 deletions(-) create mode 100644 jdk/src/share/classes/java/util/spi/CalendarNameProvider.java create mode 100644 jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java create mode 100644 jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java create mode 100644 jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh create mode 100644 jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java create mode 100644 jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 246acf3e3aa..c35bb29989c 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -206,6 +206,7 @@ JAVA_JAVA_java = \ sun/util/locale/provider/BreakIteratorProviderImpl.java \ sun/util/locale/provider/CalendarDataProviderImpl.java \ sun/util/locale/provider/CalendarDataUtility.java \ + sun/util/locale/provider/CalendarNameProviderImpl.java \ sun/util/locale/provider/CollationRules.java \ sun/util/locale/provider/CollatorProviderImpl.java \ sun/util/locale/provider/CurrencyNameProviderImpl.java \ @@ -396,6 +397,7 @@ JAVA_JAVA_java = \ java/util/prefs/Base64.java \ java/util/prefs/XmlSupport.java \ java/util/spi/CalendarDataProvider.java \ + java/util/spi/CalendarNameProvider.java \ java/util/spi/CurrencyNameProvider.java \ java/util/spi/LocaleNameProvider.java \ java/util/spi/LocaleServiceProvider.java \ diff --git a/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java index 6a6aec83b89..f571512d30b 100644 --- a/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java +++ b/jdk/src/macosx/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java @@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.TimeZoneNameProvider; @@ -323,6 +324,30 @@ public class HostLocaleProviderAdapterImpl { return isSupportedCalendarLocale(locale); } + @Override + public int getFirstDayOfWeek(Locale locale) { + return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK); + } + + @Override + public int getMinimalDaysInFirstWeek(Locale locale) { + return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK); + } + }; + } + + public static CalendarNameProvider getCalendarNameProvider() { + return new CalendarNameProvider() { + @Override + public Locale[] getAvailableLocales() { + return getSupportedCalendarLocales(); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return isSupportedCalendarLocale(locale); + } + @Override public String getDisplayName(String calType, int field, int value, int style, Locale locale) { @@ -334,16 +359,6 @@ public class HostLocaleProviderAdapterImpl { int field, int style, Locale locale) { return null; } - - @Override - public int getFirstDayOfWeek(Locale locale) { - return getCalendarInt(locale.toLanguageTag(), CD_FIRSTDAYOFWEEK); - } - - @Override - public int getMinimalDaysInFirstWeek(Locale locale) { - return getCalendarInt(locale.toLanguageTag(), CD_MINIMALDAYSINFIRSTWEEK); - } }; } diff --git a/jdk/src/share/classes/java/util/Calendar.java b/jdk/src/share/classes/java/util/Calendar.java index bae9cacfc60..f641a37e632 100644 --- a/jdk/src/share/classes/java/util/Calendar.java +++ b/jdk/src/share/classes/java/util/Calendar.java @@ -2699,12 +2699,9 @@ public abstract class Calendar implements Serializable, Cloneable, ComparableCalendar Types - * - *

Calendar types are used to specify calendar systems for which the {@link - * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link - * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide - * calendar field value names. See {@link Calendar#getCalendarType()} for details. - * - *

Calendar Fields - * - *

Calendar fields are specified with the constants defined in {@link - * Calendar}. The following are calendar-common fields and their values to be - * supported for each calendar system. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
FieldValueDescription
{@link Calendar#MONTH}{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}Month numbering is 0-based (e.g., 0 - January, ..., 11 - - * December). Some calendar systems have 13 months. Month - * names need to be supported in both the formatting and - * stand-alone forms if required by the supported locales. If there's - * no distinction in the two forms, the same names should be returned - * in both of the forms.
{@link Calendar#DAY_OF_WEEK}{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday, - * ..., 7 - Saturday).
{@link Calendar#AM_PM}{@link Calendar#AM} to {@link Calendar#PM}0 - AM, 1 - PM
- * - *

The following are calendar-specific fields and their values to be supported. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Calendar TypeFieldValueDescription
{@code "gregory"}{@link Calendar#ERA}0{@link java.util.GregorianCalendar#BC} (BCE)
1{@link java.util.GregorianCalendar#AD} (CE)
{@code "buddhist"}{@link Calendar#ERA}0BC (BCE)
1B.E. (Buddhist Era)
{@code "japanese"}{@link Calendar#ERA}0Seireki (Before Meiji)
1Meiji
2Taisho
3Showa
4Heisei
{@link Calendar#YEAR}1the first year in each era. It should be returned when a long - * style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is - * specified. See also the - * Year representation in {@code SimpleDateFormat}.
- * - *

Calendar field value names for {@code "gregory"} must be consistent with - * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}. - * - *

Time zone names are supported by {@link TimeZoneNameProvider}. + * An abstract class for service providers that provide locale-dependent {@link + * Calendar} parameters. * * @author Masayoshi Okutsu * @since 1.8 - * @see Locale#getUnicodeLocaleType(String) + * @see CalendarNameProvider */ public abstract class CalendarDataProvider extends LocaleServiceProvider { @@ -188,112 +78,4 @@ public abstract class CalendarDataProvider extends LocaleServiceProvider { * @see java.util.Calendar#getMinimalDaysInFirstWeek() */ public abstract int getMinimalDaysInFirstWeek(Locale locale); - - /** - * Returns the string representation (display name) of the calendar - * field value in the given style and - * locale. If no string representation is - * applicable, null is returned. - * - *

{@code field} is a {@code Calendar} field index, such as {@link - * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and - * {@link Calendar#DST_OFFSET}, are not supported by this - * method. {@code null} must be returned if any time zone fields are - * specified. - * - *

{@code value} is the numeric representation of the {@code field} value. - * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid - * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY} - * (inclusive). - * - *

{@code style} gives the style of the string representation. It is one - * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), - * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} - * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}. - * - *

For example, the following call will return {@code "Sunday"}. - *

-     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
-     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
-     * 
- * - * @param calendarType - * the calendar type. (Any calendar type given by {@code locale} - * is ignored.) - * @param field - * the {@code Calendar} field index, - * such as {@link Calendar#DAY_OF_WEEK} - * @param value - * the value of the {@code Calendar field}, - * such as {@link Calendar#MONDAY} - * @param style - * the string representation style: one of {@link - * Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), - * {@link Calendar#SHORT_STANDALONE}, {@link - * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or - * {@link Calendar#LONG_STANDALONE} - * @param locale - * the desired locale - * @return the string representation of the {@code field value}, or {@code - * null} if the string representation is not applicable or - * the given calendar type is unknown - * @throws IllegalArgumentException - * if {@code field} or {@code style} is invalid - * @throws NullPointerException if {@code locale} is {@code null} - * @see TimeZoneNameProvider - * @see java.util.Calendar#get(int) - * @see java.util.Calendar#getDisplayName(int, int, Locale) - */ - public abstract String getDisplayName(String calendarType, - int field, int value, - int style, Locale locale); - - /** - * Returns a {@code Map} containing all string representations (display - * names) of the {@code Calendar} {@code field} in the given {@code style} - * and {@code locale} and their corresponding field values. - * - *

{@code field} is a {@code Calendar} field index, such as {@link - * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and - * {@link Calendar#DST_OFFSET}, are not supported by this - * method. {@code null} must be returned if any time zone fields are specified. - * - *

{@code style} gives the style of the string representation. It must be - * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link - * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link - * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link - * Calendar#LONG_STANDALONE}. - * - *

For example, the following call will return a {@code Map} containing - * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link - * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY}, - * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on. - *

-     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
-     * 
- * - * @param calendarType - * the calendar type. (Any calendar type given by {@code locale} - * is ignored.) - * @param field - * the calendar field for which the display names are returned - * @param style - * the style applied to the display names; one of - * {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} - * ({@link Calendar#SHORT SHORT}), {@link - * Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} - * ({@link Calendar#LONG LONG}), or {@link - * Calendar#LONG_STANDALONE}. - * @param locale - * the desired locale - * @return a {@code Map} containing all display names of {@code field} in - * {@code style} and {@code locale} and their {@code field} values, - * or {@code null} if no display names are defined for {@code field} - * @throws NullPointerException - * if {@code locale} is {@code null} - * @see Calendar#getDisplayNames(int, int, Locale) - */ - public abstract Map getDisplayNames(String calendarType, - int field, int style, - Locale locale); } diff --git a/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java b/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java new file mode 100644 index 00000000000..20122cf5466 --- /dev/null +++ b/jdk/src/share/classes/java/util/spi/CalendarNameProvider.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.spi; + +import java.util.Calendar; +import java.util.Locale; +import java.util.Map; + +/** + * An abstract class for service providers that provide localized string + * representations (display names) of {@code Calendar} field values. + * + *

Calendar Types + * + *

Calendar types are used to specify calendar systems for which the {@link + * #getDisplayName(String, int, int, int, Locale) getDisplayName} and {@link + * #getDisplayNames(String, int, int, Locale) getDisplayNames} methods provide + * calendar field value names. See {@link Calendar#getCalendarType()} for details. + * + *

Calendar Fields + * + *

Calendar fields are specified with the constants defined in {@link + * Calendar}. The following are calendar-common fields and their values to be + * supported for each calendar system. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FieldValueDescription
{@link Calendar#MONTH}{@link Calendar#JANUARY} to {@link Calendar#UNDECIMBER}Month numbering is 0-based (e.g., 0 - January, ..., 11 - + * December). Some calendar systems have 13 months. Month + * names need to be supported in both the formatting and + * stand-alone forms if required by the supported locales. If there's + * no distinction in the two forms, the same names should be returned + * in both of the forms.
{@link Calendar#DAY_OF_WEEK}{@link Calendar#SUNDAY} to {@link Calendar#SATURDAY}Day-of-week numbering is 1-based starting from Sunday (i.e., 1 - Sunday, + * ..., 7 - Saturday).
{@link Calendar#AM_PM}{@link Calendar#AM} to {@link Calendar#PM}0 - AM, 1 - PM
+ * + *

The following are calendar-specific fields and their values to be supported. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Calendar TypeFieldValueDescription
{@code "gregory"}{@link Calendar#ERA}0{@link java.util.GregorianCalendar#BC} (BCE)
1{@link java.util.GregorianCalendar#AD} (CE)
{@code "buddhist"}{@link Calendar#ERA}0BC (BCE)
1B.E. (Buddhist Era)
{@code "japanese"}{@link Calendar#ERA}0Seireki (Before Meiji)
1Meiji
2Taisho
3Showa
4Heisei
{@link Calendar#YEAR}1the first year in each era. It should be returned when a long + * style ({@link Calendar#LONG_FORMAT} or {@link Calendar#LONG_STANDALONE}) is + * specified. See also the + * Year representation in {@code SimpleDateFormat}.
+ * + *

Calendar field value names for {@code "gregory"} must be consistent with + * the date-time symbols provided by {@link java.text.spi.DateFormatSymbolsProvider}. + * + *

Time zone names are supported by {@link TimeZoneNameProvider}. + * + * @author Masayoshi Okutsu + * @since 1.8 + * @see CalendarDataProvider + * @see Locale#getUnicodeLocaleType(String) + */ +public abstract class CalendarNameProvider extends LocaleServiceProvider { + /** + * Sole constructor. (For invocation by subclass constructors, typically + * implicit.) + */ + protected CalendarNameProvider() { + } + + /** + * Returns the string representation (display name) of the calendar + * field value in the given style and + * locale. If no string representation is + * applicable, null is returned. + * + *

{@code field} is a {@code Calendar} field index, such as {@link + * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and + * {@link Calendar#DST_OFFSET}, are not supported by this + * method. {@code null} must be returned if any time zone fields are + * specified. + * + *

{@code value} is the numeric representation of the {@code field} value. + * For example, if {@code field} is {@link Calendar#DAY_OF_WEEK}, the valid + * values are {@link Calendar#SUNDAY} to {@link Calendar#SATURDAY} + * (inclusive). + * + *

{@code style} gives the style of the string representation. It is one + * of {@link Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), + * {@link Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} + * ({@link Calendar#LONG LONG}), or {@link Calendar#LONG_STANDALONE}. + * + *

For example, the following call will return {@code "Sunday"}. + *

+     * getDisplayName("gregory", Calendar.DAY_OF_WEEK, Calendar.SUNDAY,
+     *                Calendar.LONG_STANDALONE, Locale.ENGLISH);
+     * 
+ * + * @param calendarType + * the calendar type. (Any calendar type given by {@code locale} + * is ignored.) + * @param field + * the {@code Calendar} field index, + * such as {@link Calendar#DAY_OF_WEEK} + * @param value + * the value of the {@code Calendar field}, + * such as {@link Calendar#MONDAY} + * @param style + * the string representation style: one of {@link + * Calendar#SHORT_FORMAT} ({@link Calendar#SHORT SHORT}), + * {@link Calendar#SHORT_STANDALONE}, {@link + * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or + * {@link Calendar#LONG_STANDALONE} + * @param locale + * the desired locale + * @return the string representation of the {@code field value}, or {@code + * null} if the string representation is not applicable or + * the given calendar type is unknown + * @throws IllegalArgumentException + * if {@code field} or {@code style} is invalid + * @throws NullPointerException if {@code locale} is {@code null} + * @see TimeZoneNameProvider + * @see java.util.Calendar#get(int) + * @see java.util.Calendar#getDisplayName(int, int, Locale) + */ + public abstract String getDisplayName(String calendarType, + int field, int value, + int style, Locale locale); + + /** + * Returns a {@code Map} containing all string representations (display + * names) of the {@code Calendar} {@code field} in the given {@code style} + * and {@code locale} and their corresponding field values. + * + *

{@code field} is a {@code Calendar} field index, such as {@link + * Calendar#MONTH}. The time zone fields, {@link Calendar#ZONE_OFFSET} and + * {@link Calendar#DST_OFFSET}, are not supported by this + * method. {@code null} must be returned if any time zone fields are specified. + * + *

{@code style} gives the style of the string representation. It must be + * one of {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} ({@link + * Calendar#SHORT SHORT}), {@link Calendar#SHORT_STANDALONE}, {@link + * Calendar#LONG_FORMAT} ({@link Calendar#LONG LONG}), or {@link + * Calendar#LONG_STANDALONE}. + * + *

For example, the following call will return a {@code Map} containing + * {@code "January"} to {@link Calendar#JANUARY}, {@code "Jan"} to {@link + * Calendar#JANUARY}, {@code "February"} to {@link Calendar#FEBRUARY}, + * {@code "Feb"} to {@link Calendar#FEBRUARY}, and so on. + *

+     * getDisplayNames("gregory", Calendar.MONTH, Calendar.ALL_STYLES, Locale.ENGLISH);
+     * 
+ * + * @param calendarType + * the calendar type. (Any calendar type given by {@code locale} + * is ignored.) + * @param field + * the calendar field for which the display names are returned + * @param style + * the style applied to the display names; one of + * {@link Calendar#ALL_STYLES}, {@link Calendar#SHORT_FORMAT} + * ({@link Calendar#SHORT SHORT}), {@link + * Calendar#SHORT_STANDALONE}, {@link Calendar#LONG_FORMAT} + * ({@link Calendar#LONG LONG}), or {@link + * Calendar#LONG_STANDALONE}. + * @param locale + * the desired locale + * @return a {@code Map} containing all display names of {@code field} in + * {@code style} and {@code locale} and their {@code field} values, + * or {@code null} if no display names are defined for {@code field} + * @throws NullPointerException + * if {@code locale} is {@code null} + * @see Calendar#getDisplayNames(int, int, Locale) + */ + public abstract Map getDisplayNames(String calendarType, + int field, int style, + Locale locale); +} diff --git a/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java index 9afb8b04b01..a68a8ba956d 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java @@ -38,6 +38,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -135,6 +136,10 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { return getLocaleServiceProvider(CalendarDataProvider.class); } + @Override + public CalendarNameProvider getCalendarNameProvider() { + return getLocaleServiceProvider(CalendarNameProvider.class); + } @Override public LocaleResources getLocaleResources(Locale locale) { diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java index 48ef4712ee5..16d08b3cbe3 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java @@ -24,10 +24,9 @@ */ package sun.util.locale.provider; +import java.util.Calendar; import static java.util.Calendar.*; -import java.util.HashMap; import java.util.Locale; -import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.spi.CalendarDataProvider; @@ -58,115 +57,11 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av return getIntData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK, locale); } - @Override - public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - String name = null; - String key = getKey(calendarType, field, style); - if (key != null) { - ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); - if (rb.containsKey(key)) { - String[] strings = rb.getStringArray(key); - if (strings.length > 0) { - if (field == DAY_OF_WEEK || field == YEAR) { - --value; - } - name = strings[value]; - // If name is empty in standalone, try its `format' style. - if (name.length() == 0 - && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) { - name = getDisplayName(calendarType, field, value, - style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT, - locale); - } - } - } - } - return name; - } - - @Override - public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - Map names; - if (style == ALL_STYLES) { - names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); - if (field != AM_PM) { - for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) { - names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); - } - } - } else { - // specific style - names = getDisplayNamesImpl(calendarType, field, style, locale); - } - return names.isEmpty() ? null : names; - } - - private Map getDisplayNamesImpl(String calendarType, int field, - int style, Locale locale) { - String key = getKey(calendarType, field, style); - Map map = new HashMap<>(); - if (key != null) { - ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); - if (rb.containsKey(key)) { - String[] strings = rb.getStringArray(key); - if (field == YEAR) { - if (strings.length > 0) { - map.put(strings[0], 1); - } - } else { - int base = (field == DAY_OF_WEEK) ? 1 : 0; - for (int i = 0; i < strings.length; i++) { - String name = strings[i]; - // Ignore any empty string (some standalone month names - // are not defined) - if (name.length() == 0) { - continue; - } - map.put(name, base + i); - } - } - } - } - return map; - } - @Override public Locale[] getAvailableLocales() { return LocaleProviderAdapter.toLocaleArray(langtags); } - @Override - public boolean isSupportedLocale(Locale locale) { - if (Locale.ROOT.equals(locale)) { - return true; - } - String calendarType = null; - if (locale.hasExtensions()) { - calendarType = locale.getUnicodeLocaleType("ca"); - locale = locale.stripExtensions(); - } - - if (calendarType != null) { - switch (calendarType) { - case "buddhist": - case "japanese": - case "gregory": - break; - default: - // Unknown calendar type - return false; - } - } - if (langtags.contains(locale.toLanguageTag())) { - return true; - } - if (type == LocaleProviderAdapter.Type.JRE) { - String oldname = locale.toString().replace('_', '-'); - return langtags.contains(oldname); - } - return false; - } - @Override public Set getAvailableLanguageTags() { return langtags; @@ -178,49 +73,6 @@ public class CalendarDataProviderImpl extends CalendarDataProvider implements Av String firstday = rb.getString(key); return Integer.parseInt(firstday); } - // Note that the base bundle of CLDR doesn't have the Calendar week parameters. return 0; } - - private String getKey(String type, int field, int style) { - boolean standalone = (style & 0x8000) != 0; - style &= ~0x8000; - - if ("gregory".equals(type)) { - type = null; - } - - StringBuilder key = new StringBuilder(); - switch (field) { - case ERA: - if (type != null) { - key.append(type).append('.'); - } - if (style == SHORT) { - key.append("short."); - } - key.append("Eras"); - break; - - case YEAR: - key.append(type).append(".FirstYear"); - break; - - case MONTH: - if (standalone) { - key.append("standalone."); - } - key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); - break; - - case DAY_OF_WEEK: - key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); - break; - - case AM_PM: - key.append("AmPmMarkers"); - break; - } - return key.length() > 0 ? key.toString() : null; - } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java index 274be8e8787..e86e27234bd 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarDataUtility.java @@ -25,9 +25,12 @@ package sun.util.locale.provider; +import java.util.Calendar; +import static java.util.Calendar.*; import java.util.Locale; import java.util.Map; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; /** * {@code CalendarDataUtility} is a utility class for calling the @@ -44,16 +47,32 @@ public class CalendarDataUtility { private CalendarDataUtility() { } - public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) { + public static int retrieveFirstDayOfWeek(Locale locale) { LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE, + locale, FIRST_DAY_OF_WEEK); + return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY; + } + + public static int retrieveMinimalDaysInFirstWeek(Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE, + locale, MINIMAL_DAYS_IN_FIRST_WEEK); + return (value != null && (value >= 1 && value <= 7)) ? value : 1; + } + + public static String retrieveFieldValueName(String id, int field, int value, int style, Locale locale) { + LocaleServiceProviderPool pool = + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNameGetter.INSTANCE, locale, id, field, value, style); } public static Map retrieveFieldValueNames(String id, int field, int style, Locale locale) { LocaleServiceProviderPool pool = - LocaleServiceProviderPool.getPool(CalendarDataProvider.class); + LocaleServiceProviderPool.getPool(CalendarNameProvider.class); return pool.getLocalizedObject(CalendarFieldValueNamesMapGetter.INSTANCE, locale, id, field, style); } @@ -62,13 +81,13 @@ public class CalendarDataUtility { * implementation. */ private static class CalendarFieldValueNameGetter - implements LocaleServiceProviderPool.LocalizedObjectGetter { private static final CalendarFieldValueNameGetter INSTANCE = new CalendarFieldValueNameGetter(); @Override - public String getObject(CalendarDataProvider calendarDataProvider, + public String getObject(CalendarNameProvider calendarNameProvider, Locale locale, String requestID, // calendarType Object... params) { @@ -76,7 +95,7 @@ public class CalendarDataUtility { int field = (int) params[0]; int value = (int) params[1]; int style = (int) params[2]; - return calendarDataProvider.getDisplayName(requestID, field, value, style, locale); + return calendarNameProvider.getDisplayName(requestID, field, value, style, locale); } } @@ -85,20 +104,47 @@ public class CalendarDataUtility { * implementation. */ private static class CalendarFieldValueNamesMapGetter - implements LocaleServiceProviderPool.LocalizedObjectGetter> { private static final CalendarFieldValueNamesMapGetter INSTANCE = new CalendarFieldValueNamesMapGetter(); @Override - public Map getObject(CalendarDataProvider calendarDataProvider, + public Map getObject(CalendarNameProvider calendarNameProvider, Locale locale, String requestID, // calendarType Object... params) { assert params.length == 2; int field = (int) params[0]; int style = (int) params[1]; - return calendarDataProvider.getDisplayNames(requestID, field, style, locale); + return calendarNameProvider.getDisplayNames(requestID, field, style, locale); + } + } + + private static class CalendarWeekParameterGetter + implements LocaleServiceProviderPool.LocalizedObjectGetter { + private static final CalendarWeekParameterGetter INSTANCE = + new CalendarWeekParameterGetter(); + + @Override + public Integer getObject(CalendarDataProvider calendarDataProvider, + Locale locale, + String requestID, // resource key + Object... params) { + assert params.length == 0; + int value; + switch (requestID) { + case FIRST_DAY_OF_WEEK: + value = calendarDataProvider.getFirstDayOfWeek(locale); + break; + case MINIMAL_DAYS_IN_FIRST_WEEK: + value = calendarDataProvider.getMinimalDaysInFirstWeek(locale); + break; + default: + throw new InternalError("invalid requestID: " + requestID); + } + return (value != 0) ? value : null; } } } diff --git a/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java new file mode 100644 index 00000000000..1f262a8445a --- /dev/null +++ b/jdk/src/share/classes/sun/util/locale/provider/CalendarNameProviderImpl.java @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.util.locale.provider; + +import static java.util.Calendar.*; +import java.util.Comparator; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.Set; +import java.util.TreeMap; +import java.util.spi.CalendarNameProvider; + +/** + * Concrete implementation of the {@link java.util.spi.CalendarDataProvider + * CalendarDataProvider} class for the JRE LocaleProviderAdapter. + * + * @author Masayoshi Okutsu + * @author Naoto Sato + */ +public class CalendarNameProviderImpl extends CalendarNameProvider implements AvailableLanguageTags { + private final LocaleProviderAdapter.Type type; + private final Set langtags; + + public CalendarNameProviderImpl(LocaleProviderAdapter.Type type, Set langtags) { + this.type = type; + this.langtags = langtags; + } + + @Override + public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + String name = null; + String key = getKey(calendarType, field, style); + if (key != null) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); + if (rb.containsKey(key)) { + String[] strings = rb.getStringArray(key); + if (strings.length > 0) { + if (field == DAY_OF_WEEK || field == YEAR) { + --value; + } + name = strings[value]; + // If name is empty in standalone, try its `format' style. + if (name.length() == 0 + && (style == SHORT_STANDALONE || style == LONG_STANDALONE)) { + name = getDisplayName(calendarType, field, value, + style == SHORT_STANDALONE ? SHORT_FORMAT : LONG_FORMAT, + locale); + } + } + } + } + return name; + } + + @Override + public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { + Map names; + if (style == ALL_STYLES) { + names = getDisplayNamesImpl(calendarType, field, SHORT_FORMAT, locale); + if (field != AM_PM) { + for (int st : new int[] { SHORT_STANDALONE, LONG_FORMAT, LONG_STANDALONE }) { + names.putAll(getDisplayNamesImpl(calendarType, field, st, locale)); + } + } + } else { + // specific style + names = getDisplayNamesImpl(calendarType, field, style, locale); + } + return names.isEmpty() ? null : names; + } + + private Map getDisplayNamesImpl(String calendarType, int field, + int style, Locale locale) { + String key = getKey(calendarType, field, style); + Map map = new TreeMap<>(LengthBasedComparator.INSTANCE); + if (key != null) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getDateFormatData(locale); + if (rb.containsKey(key)) { + String[] strings = rb.getStringArray(key); + if (field == YEAR) { + if (strings.length > 0) { + map.put(strings[0], 1); + } + } else { + int base = (field == DAY_OF_WEEK) ? 1 : 0; + for (int i = 0; i < strings.length; i++) { + String name = strings[i]; + // Ignore any empty string (some standalone month names + // are not defined) + if (name.length() == 0) { + continue; + } + map.put(name, base + i); + } + } + } + } + return map; + } + + /** + * Comparator implementation for TreeMap which iterates keys from longest + * to shortest. + */ + private static class LengthBasedComparator implements Comparator { + private static final LengthBasedComparator INSTANCE = new LengthBasedComparator(); + + private LengthBasedComparator() { + } + + @Override + public int compare(String o1, String o2) { + int n = o2.length() - o1.length(); + return (n == 0) ? o1.compareTo(o2) : n; + } + } + + @Override + public Locale[] getAvailableLocales() { + return LocaleProviderAdapter.toLocaleArray(langtags); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + if (Locale.ROOT.equals(locale)) { + return true; + } + String calendarType = null; + if (locale.hasExtensions()) { + calendarType = locale.getUnicodeLocaleType("ca"); + locale = locale.stripExtensions(); + } + + if (calendarType != null) { + switch (calendarType) { + case "buddhist": + case "japanese": + case "gregory": + break; + default: + // Unknown calendar type + return false; + } + } + if (langtags.contains(locale.toLanguageTag())) { + return true; + } + if (type == LocaleProviderAdapter.Type.JRE) { + String oldname = locale.toString().replace('_', '-'); + return langtags.contains(oldname); + } + return false; + } + + @Override + public Set getAvailableLanguageTags() { + return langtags; + } + + private int getIntData(String key, Locale locale) { + ResourceBundle rb = LocaleProviderAdapter.forType(type).getLocaleData().getCalendarData(locale); + if (rb.containsKey(key)) { + String firstday = rb.getString(key); + return Integer.parseInt(firstday); + } + // Note that the base bundle of CLDR doesn't have the Calendar week parameters. + return 0; + } + + private String getKey(String type, int field, int style) { + boolean standalone = (style & 0x8000) != 0; + style &= ~0x8000; + + if ("gregory".equals(type)) { + type = null; + } + + StringBuilder key = new StringBuilder(); + switch (field) { + case ERA: + if (type != null) { + key.append(type).append('.'); + } + if (style == SHORT) { + key.append("short."); + } + key.append("Eras"); + break; + + case YEAR: + key.append(type).append(".FirstYear"); + break; + + case MONTH: + if (standalone) { + key.append("standalone."); + } + key.append(style == SHORT ? "MonthAbbreviations" : "MonthNames"); + break; + + case DAY_OF_WEEK: + key.append(style == SHORT ? "DayAbbreviations" : "DayNames"); + break; + + case AM_PM: + key.append("AmPmMarkers"); + break; + } + return key.length() > 0 ? key.toString() : null; + } +} diff --git a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java index e6b3d9e1e32..9f86f7a35ab 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java @@ -41,6 +41,7 @@ import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -101,6 +102,8 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { return (P) getTimeZoneNameProvider(); case "CalendarDataProvider": return (P) getCalendarDataProvider(); + case "CalendarNameProvider": + return (P) getCalendarNameProvider(); default: throw new InternalError("should not come down here"); } @@ -117,6 +120,7 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { private volatile LocaleNameProvider localeNameProvider = null; private volatile TimeZoneNameProvider timeZoneNameProvider = null; private volatile CalendarDataProvider calendarDataProvider = null; + private volatile CalendarNameProvider calendarNameProvider = null; /* * Getter methods for java.text.spi.* providers @@ -252,11 +256,9 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { @Override public CalendarDataProvider getCalendarDataProvider() { if (calendarDataProvider == null) { - Set set = new HashSet<>(); - set.addAll(getLanguageTagSet("FormatData")); - set.addAll(getLanguageTagSet("CalendarData")); - CalendarDataProvider provider = new CalendarDataProviderImpl(getAdapterType(), - set); + CalendarDataProvider provider; + provider = new CalendarDataProviderImpl(getAdapterType(), + getLanguageTagSet("CalendarData")); synchronized (this) { if (calendarDataProvider == null) { calendarDataProvider = provider; @@ -266,6 +268,21 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter { return calendarDataProvider; } + @Override + public CalendarNameProvider getCalendarNameProvider() { + if (calendarNameProvider == null) { + CalendarNameProvider provider; + provider = new CalendarNameProviderImpl(getAdapterType(), + getLanguageTagSet("FormatData")); + synchronized (this) { + if (calendarNameProvider == null) { + calendarNameProvider = provider; + } + } + } + return calendarNameProvider; + } + @Override public LocaleResources getLocaleResources(Locale locale) { LocaleResources lr = localeResourcesMap.get(locale); diff --git a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index 7db4560f81c..17f5c0999d5 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -38,6 +38,7 @@ import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleNameProvider; import java.util.spi.LocaleServiceProvider; @@ -387,6 +388,14 @@ public abstract class LocaleProviderAdapter { */ public abstract CalendarDataProvider getCalendarDataProvider(); + /** + * Returns a CalendarNameProvider for this LocaleProviderAdapter, or null if no + * CalendarNameProvider is available. + * + * @return a CalendarNameProvider + */ + public abstract CalendarNameProvider getCalendarNameProvider(); + public abstract LocaleResources getLocaleResources(Locale locale); public abstract LocaleData getLocaleData(); diff --git a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java index cb4f9aee7de..1d380e38ac2 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java @@ -28,11 +28,29 @@ package sun.util.locale.provider; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.text.*; -import java.text.spi.*; -import java.util.*; -import java.util.concurrent.*; -import java.util.spi.*; +import java.text.BreakIterator; +import java.text.Collator; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.spi.BreakIteratorProvider; +import java.text.spi.CollatorProvider; +import java.text.spi.DateFormatProvider; +import java.text.spi.DateFormatSymbolsProvider; +import java.text.spi.DecimalFormatSymbolsProvider; +import java.text.spi.NumberFormatProvider; +import java.util.Locale; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; +import java.util.spi.CurrencyNameProvider; +import java.util.spi.LocaleNameProvider; +import java.util.spi.LocaleServiceProvider; +import java.util.spi.TimeZoneNameProvider; /** * LocaleProviderAdapter implementation for the installed SPI implementations. @@ -411,12 +429,39 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { assert cdp != null; return cdp.getMinimalDaysInFirstWeek(locale); } + } + + static class CalendarNameProviderDelegate extends CalendarNameProvider + implements Delegate { + private ConcurrentMap map = new ConcurrentHashMap<>(); + + @Override + public void addImpl(CalendarNameProvider impl) { + for (Locale l : impl.getAvailableLocales()) { + map.put(l, impl); + } + } + + @Override + public CalendarNameProvider getImpl(Locale locale) { + return SPILocaleProviderAdapter.getImpl(map, locale); + } + + @Override + public Locale[] getAvailableLocales() { + return map.keySet().toArray(new Locale[0]); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return map.containsKey(locale); + } @Override public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - CalendarDataProvider cdp = getImpl(locale); + CalendarNameProvider cdp = getImpl(locale); assert cdp != null; return cdp.getDisplayName(calendarType, field, value, style, locale); } @@ -425,7 +470,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - CalendarDataProvider cdp = getImpl(locale); + CalendarNameProvider cdp = getImpl(locale); assert cdp != null; return cdp.getDisplayNames(calendarType, field, style, locale); } diff --git a/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java b/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java index 53875abea44..a5666f6b6a9 100644 --- a/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java +++ b/jdk/src/windows/classes/sun/util/locale/provider/HostLocaleProviderAdapterImpl.java @@ -25,7 +25,12 @@ package sun.util.locale.provider; import java.lang.ref.SoftReference; -import java.text.*; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; +import java.text.SimpleDateFormat; import java.text.spi.DateFormatProvider; import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; @@ -34,12 +39,13 @@ import java.util.Collections; import java.util.HashSet; import java.util.Locale; import java.util.Map; -import java.util.Set; import java.util.ResourceBundle.Control; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.spi.CalendarDataProvider; +import java.util.spi.CalendarNameProvider; /** * LocaleProviderdapter implementation for the Windows locale data. @@ -88,7 +94,7 @@ public class HostLocaleProviderAdapterImpl { private static final Set supportedLocaleSet; static { - Set tmpSet = new HashSet(); + Set tmpSet = new HashSet<>(); if (initialize()) { // Assuming the default locales do not include any extensions, so // no stripping is needed here. @@ -258,7 +264,7 @@ public class HostLocaleProviderAdapterImpl { if (ref == null || (patterns = ref.get()) == null) { String langtag = locale.toLanguageTag(); - patterns = new AtomicReferenceArray(NF_MAX+1); + patterns = new AtomicReferenceArray<>(NF_MAX+1); for (int i = 0; i <= NF_MAX; i++) { patterns.compareAndSet(i, null, getNumberPattern(i, langtag)); } @@ -329,18 +335,6 @@ public class HostLocaleProviderAdapterImpl { return isSupportedCalendarLocale(locale); } - @Override - public String getDisplayName(String calType, int field, int value, - int style, Locale locale) { - return null; - } - - @Override - public Map getDisplayNames(String calType, - int field, int style, Locale locale) { - return null; - } - @Override public int getFirstDayOfWeek(Locale locale) { int first = getCalendarDataValue( @@ -360,6 +354,32 @@ public class HostLocaleProviderAdapterImpl { }; } + public static CalendarNameProvider getCalendarNameProvider() { + return new CalendarNameProvider() { + @Override + public Locale[] getAvailableLocales() { + return getSupportedCalendarLocales(); + } + + @Override + public boolean isSupportedLocale(Locale locale) { + return isSupportedCalendarLocale(locale); + } + + @Override + public String getDisplayName(String calType, int field, int value, + int style, Locale locale) { + return null; + } + + @Override + public Map getDisplayNames(String calType, + int field, int style, Locale locale) { + return null; + } + }; + } + private static String convertDateTimePattern(String winPattern) { String ret = winPattern.replaceAll("dddd", "EEEE"); ret = ret.replaceAll("ddd", "EEE"); diff --git a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java index 5ee6b4d8306..1ef683b300f 100644 --- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java +++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.java @@ -36,17 +36,11 @@ import com.bar.CalendarDataProviderImpl; * * Test strategy: * com.bar.CalendarDataProviderImpl supports only ja_JP_kids locale. It returns - * month names only in full-width digits, followed by "gatsu" in Hiragana if - * it's a long style, and also returns unusual week parameter values, WEDNESDAY - * - first day of week, 7 - minimal days in the first week. The standalone - * styles are used because DateFormatSymbols has precedence for the format - * styles. + * unusual week parameter values, WEDNESDAY - first day of week, 7 - minimal + * days in the first week. * * A Calendar instance created with ja_JP_kids should use the week parameters - * provided by com.bar.CalendarDataProviderImpl. Calendar.getDisplayName(s) - * should be called with kids to get the month names provided by - * com.bar.CalendarDataProviderImpl. Other display names should be the same as - * what a Calendar constructed with ja_JP returns. + * provided by com.bar.CalendarDataProviderImpl. */ public class CalendarDataProviderTest { @@ -62,45 +56,6 @@ public class CalendarDataProviderTest { // check the week parameters checkResult("firstDayOfWeek", kcal.getFirstDayOfWeek(), WEDNESDAY); checkResult("minimalDaysInFirstWeek", kcal.getMinimalDaysInFirstWeek(), 7); - - // check month names and week day names - Map mapAllStyles = new HashMap<>(); - for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) { - // Check month names provided by com.bar.CalendarDataProviderImpl - Map map = new HashMap<>(); - for (int month = JANUARY; month <= DECEMBER; month++) { - kcal.set(DAY_OF_MONTH, 1); - kcal.set(MONTH, month); - kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions... - kcal.getTimeInMillis(); - String name = kcal.getDisplayName(MONTH, style, kids); - checkResult("Month name", - name, - CalendarDataProviderImpl.toMonthName(kcal.get(MONTH) + 1, style)); - - // Builds the map with name to its integer value. - map.put(name, kcal.get(MONTH)); - } - checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map", - kcal.getDisplayNames(MONTH, style, kids), map); - mapAllStyles.putAll(map); - if (style == LONG_STANDALONE) { - checkResult("Short and long month names map", - kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles); - } - - // Check week names: kcal and jcal should return the same names and maps. - for (int dow = SUNDAY; dow <= SATURDAY; dow++) { - kcal.set(DAY_OF_WEEK, dow); - jcal.setTimeInMillis(kcal.getTimeInMillis()); - String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids); - checkResult("Day of week name", name, - jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN)); - } - checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids), - jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN)); - } - } private void checkResult(String msg, T got, T expected) { diff --git a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh index 2e8f7924c00..c4d1f90d76c 100644 --- a/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/CalendarDataProviderTest.sh @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 7058206 +# @bug 7058207 8000986 # @summary CalendarDataProvider tests # @run shell ExecTest.sh bar CalendarDataProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java new file mode 100644 index 00000000000..4910f1596fe --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 static java.util.Calendar.*; +import sun.util.locale.provider.*; +import sun.util.resources.*; +import com.bar.CalendarNameProviderImpl; + +/** + * Test case for CalendarNameProvider. + * + * Test strategy: + * com.bar.CalendarNameProviderImpl supports only ja_JP_kids locale. It returns + * month names only in full-width digits, followed by "gatsu" in Hiragana if + * it's a long style. The standalone styles are used because DateFormatSymbols + * has precedence for the format styles. + * + * Calendar.getDisplayName(s) should be called with kids to get the month + * names provided by com.bar.CalendarNameProviderImpl. Other display names + * should be the same as what a Calendar constructed with ja_JP returns. + */ +public class CalendarNameProviderTest { + + public static void main(String[] s) { + new CalendarNameProviderTest().test(); + } + + void test() { + Locale kids = new Locale("ja", "JP", "kids"); // test provider's supported locale + Calendar kcal = Calendar.getInstance(kids); + Calendar jcal = Calendar.getInstance(Locale.JAPAN); + + // check month names and week day names + Map mapAllStyles = new HashMap<>(); + for (int style : new int[] { SHORT_STANDALONE, LONG_STANDALONE }) { + // Check month names provided by com.bar.CalendarNameProviderImpl + Map map = new HashMap<>(); + for (int month = JANUARY; month <= DECEMBER; month++) { + kcal.set(DAY_OF_MONTH, 1); + kcal.set(MONTH, month); + kcal.set(HOUR_OF_DAY, 12); // avoid any standard-daylight transitions... + kcal.getTimeInMillis(); + String name = kcal.getDisplayName(MONTH, style, kids); + checkResult("Month name", + name, + CalendarNameProviderImpl.toMonthName(kcal.get(MONTH) + 1, style)); + + // Builds the map with name to its integer value. + map.put(name, kcal.get(MONTH)); + } + checkResult((style == SHORT_STANDALONE ? "Short" : "Long") + " month names map", + kcal.getDisplayNames(MONTH, style, kids), map); + mapAllStyles.putAll(map); + if (style == LONG_STANDALONE) { + checkResult("Short and long month names map", + kcal.getDisplayNames(MONTH, ALL_STYLES, kids), mapAllStyles); + } + + // Check week names: kcal and jcal should return the same names and maps. + for (int dow = SUNDAY; dow <= SATURDAY; dow++) { + kcal.set(DAY_OF_WEEK, dow); + jcal.setTimeInMillis(kcal.getTimeInMillis()); + String name = kcal.getDisplayName(DAY_OF_WEEK, style, kids); + checkResult("Day of week name", name, + jcal.getDisplayName(DAY_OF_WEEK, style, Locale.JAPAN)); + } + checkResult("Short day of week names", kcal.getDisplayNames(DAY_OF_WEEK, style, kids), + jcal.getDisplayNames(DAY_OF_WEEK, style, Locale.JAPAN)); + } + + } + + private void checkResult(String msg, T got, T expected) { + if (!expected.equals(got)) { + String s = String.format("%s: got='%s', expected='%s'", msg, got, expected); + throw new RuntimeException(s); + } + } +} diff --git a/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh new file mode 100644 index 00000000000..a772292b936 --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/CalendarNameProviderTest.sh @@ -0,0 +1,27 @@ +# +# Copyright (c) 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. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 8000986 +# @summary CalendarNameProvider tests +# @run shell ExecTest.sh bar CalendarNameProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/GenericTest.java b/jdk/test/java/util/PluggableLocale/GenericTest.java index 29a49fb3f26..8be74cdca91 100644 --- a/jdk/test/java/util/PluggableLocale/GenericTest.java +++ b/jdk/test/java/util/PluggableLocale/GenericTest.java @@ -42,6 +42,7 @@ public class GenericTest { com.bar.LocaleNameProviderImpl localeNP = new com.bar.LocaleNameProviderImpl(); com.bar.TimeZoneNameProviderImpl tzNP = new com.bar.TimeZoneNameProviderImpl(); com.bar.CalendarDataProviderImpl calDataP = new com.bar.CalendarDataProviderImpl(); + com.bar.CalendarNameProviderImpl calNameP = new com.bar.CalendarNameProviderImpl(); public static void main(String[] s) { new GenericTest(); @@ -73,6 +74,7 @@ public class GenericTest { expected.addAll(Arrays.asList(localeNP.getAvailableLocales())); expected.addAll(Arrays.asList(tzNP.getAvailableLocales())); expected.addAll(Arrays.asList(calDataP.getAvailableLocales())); + expected.addAll(Arrays.asList(calNameP.getAvailableLocales())); if (!result.equals(expected)) { throw new RuntimeException("Locale.getAvailableLocales() does not return the union of locales: diff=" + getDiff(result, expected)); diff --git a/jdk/test/java/util/PluggableLocale/barprovider.jar b/jdk/test/java/util/PluggableLocale/barprovider.jar index 901b2b2b7f6264a4f8fe6b7e4af75f573897e55e..7f621fa3c67efb04fdf6b540bf94461bfdb87d0c 100644 GIT binary patch delta 3146 zcmZ`*2|Sc*7k`amY~$JoBgD02AG@+#T>CO3l%=@HGO~wC%fx7q<>DUSs_>!MY^w8003YKy)+MO z0Kfv!Jb+vBiZmDCih?TWrjSaPTNE4j%pnN29)aGtu;57iDethrq$8YHR5;oqZMhS& z++q@#La!ohOmJ_F49rJv*GN{@eyi9KKki7Tmf%8LGGMy);SQ07j9S);`O;)hQ&~i! zx|Wy4ia<{>vX$I@+t@Ho(9eEyq|bHD$7Hj-Fe6-2%rmWDN1_`MDr1_nvmm(tDq6h;@8*{m4pntorB&Xua4UGJlXd# zgElceMsg zA{e!5-gH@yZ@gce-JX}^Q0T3a3CuDv)5v8Vl*M!8M_~t%r1q=@9waDbrbS41mM;=^ zxz;>Xkn`x})Az|T(t@$~HL#kWokw4hta{F5>s9m#-7D@nZA*4j5S;t&5s}4Le6B6` zPWIQyn_lxi`Zu~xMRu4kjG2jdh-jSkHCJ>P9r_sVeoA|KZs);LkKCus^yPy@f^~mR ziG5Ai=klHDKTg*TYTC4i-*50KB1Fk%nzoGf=u8zm+~VFg*QHvXds0nOc)o`S}3|^CMoI+i$tMJcO1^Yy2c1#2@$I1KQun@bas4$A%aI(4+GjDk7>3I@Kv5$Fh zLLxUdwm^L8Ngjyw6q44kuo7EPYMgT} z^k4tjI`_yuvh3QmJBOCuu5oL@dC_J~jg^A;E^Ms}JImIYw-l_-w965$$G==vQW@uH zD9O*k_~H^?w~U_9=fXZdG``7Jz15;{7Nr$3`==t2U1@d)W#b8pn_<#1!log5wXa30 zh{*T5;BAwwy~Jk!Sh2W$&-r>&Qqx3&MwJ-;$#c6=c$i6CqWxew*-%_BYpur@`4ERiRY z$m7OnIn3mL;Gj#;4BuVqvSg=cKQBC=+HS^mRrI5?dn=0VV%#=iW+?UUgrs_1JU3az zN@vLIB6eVnUBb;eTfVh?K1J^N89+0ITn3d8kYqAL1L`&Fp zdNo;1HpWo~dG!b<^e$elcWE0NuMRFKgtfB@ova=F?#}(j&5glPI?lzoyUuTsMXNI3 zyGC-va&Js)i3QtV`ZySCkBeV0=$ z9@nyXJ%ooc6Kfeesqza-2df59rQS-NSeAzgg$HG<;2;Ol#Y6ONDk-EJ<|W=p*Mz3#273sWO%U)-kNefixT7->f`7KPv$n3d2@ z%_XD;Qb~%&f%(G~g61DeNT-FZNiTbg7T1GHt5=uXC zOudwOa|`#YjZmx|@$p>42)`$pnsk0-z#pRkMkWSyj7UWcf0}5;+omlomBw6ORF`qE zeVs5ko0D>+l+Zu32|nSrDK05~H9Ll0&TE!zIW%AXl z!p1>kxd$;5@ZW2T=P&87IKGY`@pp*5yCgci6BTo3vqN4tRfY|}kTQQ^&9du$VeZ2b z^xNERb8YU3$f2#oMbqdt5_;#UlU|w8cV6*m)fy-GB@#i~CI4nr;hAi0VFr(ce6~gF z>Iaflb>VsEd3`)J<9gDq{7bYlQ(D6A9@+(gy?9>^)B$AZZMu; zOm|OQsiR?y4B&vGI`~eVgM}Ut>Q_Llh5+mm44RjK%vr#G zbwP2OP9!jZ7z_ov1HJ0Bh`Zw#M!Io_x;Wjhr3MW9|3iGd&c_T2v3hNI%>}X8cr=4lt;k;kci=hi7YFyL?h-uk{)c*wsX zMDgH0XciYlMgV*+hTJ97*mXR-3Nr46jOF$j+wnrif?$&nALy?7gZY0BBLM6tE;JV*X3sl(DxEJ<1%I{Xj@4Kq9h+HgvPE^0rf@M`EIy-Gh;%_lhce{I=} m(n*F#koz>qy}-U@SXTlcs|oWlLDT^N1wCj40IXqXe}4hwnCABY delta 2388 zcmZWq4LFl~8-HvwY?c}3V=JbNP0TP`yqs3avTBo$ilsv+nQxj(t$fv?yz$ggokr%X zLv<=-WPPBLk<>|YPRd6SeQ=al3h%RZE-&YOp6kB;_s8$P|Mz|Wuj{@`;wmFBd@dZJ z4`^y?0_g$XIT&ZS^6>Ow50zTr^NNefr%J7NO&VH|2aBn!K|_N9LyMn*>WIJM#^Tff zK37BYQ?u)&Hvj-W5GiA!06-H^#sYg0rpjO-Tz#qPbVZZEKb-JliC;jp-e&AfwtVD; zaD5+(K9F(;0b7Jv#jPb{YMIDE7}761x1sY!m`KtPkW)TUvZ zXHyKkAJ!Zt8}r>134*5ymOe%2=|_ii%L&@mHM!_2Ax&1-kuR>YFE32ALpUdTi*6Ww8|&0U z7PgSn|+PyUW&tqXP`8%~A{~p2+@oN^>Y?uGwoYz_9p20~LHFY9Z!=Eqm?mD;o zL^WvVdOxv%>OAsHQeW6(>J_gqD>7>0w+Z*RR3|$8k;7TmvZg1}<3Xu_QOUaaCd;lu zlp!*Dn0H(}+dZ0}*_X&U9d?29cB^+H+9^GMN_^N^v_JC6vh|x4yZ3k)zTU*`+MjeO zi8^wJxG^r`d4q3V=ata9@sZ^pj$7hFHKq4LPPjO%z1r;ALhUk+ux`yBeP#y<9cwmzV?pR$68liW5l$g*V|s$r?N6+h->-mwGBe7 z$s41yHKDtV{QVgF-U&%%XFil#Hs0JMldHcl)6|Y_RM?lg(4WNZ`1#kn7i&+~-Ps_V z?yA*Cn`iB{{bYu}(o83?1+X#i%Dc}`47Yk)EE`C%3-St0ZSJ?l2(V7X4;Zzl{v3_5o_$WA9_svJ>qA*GGgQ zPjR%*)=wTYzbMA{rnJReYbCymk_X$kc)k+_+eFaBH#+Mw3vC1U3@v?)T`xSD{8d2b zaKGV+lJT|0)vW^^ZFw|onPJQAWQS2{W>nWPwv9hZG@c}`|G43c-*0*fT3~dYZ1tI~ zJ#n%v!D+O;y{JiIQRT;aqdcCtra<1hr!xGD)vZQ2#cOL$B zRXN(?q?WK;%h>W=-5j2&4*9_L;QOi7(cKJ#_umS)WxQX;>%S!JEyHqj1g>Km1IRI+ z&*eMJTGZ@#f!V*(yUg6&UquiFsgAYCGaIQ5Ehs9X$pEqW%1#5{_Wxw*kgmPHV7Hi* zHyldaI@19Ev<=zAR(~i(4#r{)AF&NRm=6NQ^;tEp{8j0{w-ic9TvLs^*}7IAzNBh+ zc40h|Fjhf^7Z_ zr3?;pUQvb*vYY;0C87%RQ7*h67G1IYEuV2TAbdOfbO^2Fg-5s!zdQBhD7Hjm_TE=K z#p^T4pdZ%#^PW}dE++35|ATot&n~+Lm+xw@s}O)!(v^b|EQlYKy8vDnVNd1%76Tf8ph>s}50GsGxu%FFXtZ3MSc zG7J;)Z73hasRf-Bm%vW>t; zYW;5!blZ|uq2RP}7<%4@$a!j`)PqY9ba2*QAM{i^Fee{`OH_P|n*48_45J3q2j(&a z;r1*H^uqPk-BjgW^>7d3Ukr zHqkK~(S*!fP=7cLS0BC~> zrOsugWHOB*FiYhMC6-HsBqH=~M3q~p+fHsctbgq@FvSx)q!pnfihz_3JidGF=XtmgYK`s%juc3R9z@+zTOcTu{S+61PePqBHm3 z{}D1CfXIFUsM-bsnS)=|aLfPkHf*?2=Heg-d>EpIkrQoIPCSG@p3hZ>dIA6j&>sqM IESggKFEwp|b^rhX diff --git a/jdk/test/java/util/PluggableLocale/fooprovider.jar b/jdk/test/java/util/PluggableLocale/fooprovider.jar index 125dbe17756199ab64388fa372f656af7e74440d..cfc6616019c95d85eeef900d50997cec213d4f45 100644 GIT binary patch delta 1012 zcmZ8gUr1AN6h8NEb94R~+FDz;~Oe#C~_mj2T#*goC&i8%yJHNZlXNCE! zP?1jQ^j0vLOfWorFjpb#RM>t-1$@5M&+tTOnqgJ=CBsC^Glnz4NrnsIdu2r~qrv;7 zW&jf~%U3ljC--Bs3i+IQr=ArbDj)K~DeM+m=f;{m@3gw+c+uuu;-g;ABVIImj~Gh} zar52wx11@}ZR3PN-DO_bN(S`*Qs6|u%^vb1@J*}`L@N|b@Ma{ej_^|?UPG9KqEB^E z4e$g;=9d$QhLt+DK4UwTk&svj78!8DibG^Da8SEvuES;dn z^&KbA#2sa3D7+c;$g} z=}&64nX%7qMQ?N?k2D(_|1JPr(*uMxk&G6+CAYJ6Qc+3lsUn>RN1`64yJ)xsCrJ}3 z1!&Uf>^AIldhvI(nh|$3959>~0qQ7fyN0;9o`@ZIeKlNTOcK93u_M;VboTyVPrXKf zzDfYMMmOa`*;`*&YKp?O)KfUW+G5%{|Mb}vS}LOhkThB%t+Y0{tBwAZB9P*_fmZh4_1+yYJ~9`2YHoADi|FcWLh&`PnpH Z;~{(>u-nopLy6jV(AP)*#4+|e`wNXF1Hb?P delta 903 zcmY*WOH30{6n*n%TKb_>v}tIb)CSsuq_v=>(CN^R(S@=QjWKTM#+`^w{49vzro^}~ zn0j}9hznP`=%O1CG)6^@5;y*$5EpDTgdH1F67bHQrgmmBx%Ztp_niCgT`Nj!MaeZX zEGr&nv)S0xgjRB?vK~&}4q?c#hDX8tLSa0n^Bs)Yn9hfm4cQ!Ou`WDr3*ic^7n$S;U@*JTSX_4Z6{+Z%i=?lfMvfz@qht=l+<>Vm! zSx;stzS2beLwynwcd&XdrfK1L8lH6q?jf&!efT&e_#O!+V?l7HI|wRg1s{`PIjhpq zo)g?|MMfuVW%dTJDEDKkI%mNJq?#D(XwYSB+5vWJ5Oy-nM0|1&cCRAwJ^BYt#GfsY zcZ78!ne?UwpWO#HTaUusv;n!Wjk9eCbwS>1tuw30>~DvKbPs64UuVxE+#5hx3*cmP zE78R}yAopsnK5B9ZV5p#dyq^oX9Pdj1up*qcv|aY9wC1Ze9uIj4WooS&fsAm+{pPz z{qLbs={aYtgje&L)R+3;WunbJGHhA}L{!1w#NmV*pskH+f^WuQTN!|jR5L-3Qi9L- zBh&$_sr>|9!lG*lf}W{)+>VqJ5${xxs5Kr U3`o_y9*b4i@ZlT51wAIkf0|wCzW@LL diff --git a/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java index 7a8fff62a83..274d468df08 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java +++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarDataProviderImpl.java @@ -47,66 +47,8 @@ public class CalendarDataProviderImpl extends CalendarDataProvider { return 7; } - @Override - public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { - if (calendarType == null || locale == null) { - throw new NullPointerException(); - } - if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { - throw new IllegalArgumentException("locale is not one of available locales: "+ locale); - } - if (field != MONTH) { - return null; - } - return toMonthName(value + 1, style); - } - - @Override - public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { - if (calendarType == null || locale == null) { - throw new NullPointerException(); - } - if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { - throw new IllegalArgumentException("locale is not one of available locales: " + locale); - } - if (field != MONTH) { - return null; - } - Map map = new HashMap<>(); - if (style == LONG_STANDALONE) { - style = LONG; - } else if (style == SHORT_STANDALONE) { - style = SHORT; - } - for (int month = JANUARY; month <= DECEMBER; month++) { - if (style == ALL_STYLES || style == LONG) { - map.put(toMonthName(month + 1, LONG), month); - } - if (style == ALL_STYLES || style == SHORT) { - map.put(toMonthName(month + 1, SHORT), month); - } - } - return map; - } - @Override public Locale[] getAvailableLocales() { return avail.clone(); } - - // month is 1-based. - public static String toMonthName(int month, int style) { - StringBuilder sb = new StringBuilder(); - if (month >= 10) { - sb.append((char)(FULLWIDTH_ZERO + 1)); - sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10))); - } else { - sb.appendCodePoint((char)(FULLWIDTH_ZERO + month)); - } - if (style == SHORT || style == SHORT_STANDALONE) { - return sb.toString(); // full-width digit(s) - } - sb.append("\u304c\u3064"); // + "gatsu" in Hiragana - return sb.toString(); - } } diff --git a/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java b/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java new file mode 100644 index 00000000000..d93ba36229b --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/CalendarNameProviderImpl.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.bar; + +import com.foobar.Utils; +import java.util.Arrays; +import static java.util.Calendar.*; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.spi.CalendarNameProvider; + +public class CalendarNameProviderImpl extends CalendarNameProvider { + static final char FULLWIDTH_ZERO = '\uff10'; + static final Locale[] avail = { + new Locale("ja", "JP", "kids"), + }; + + @Override + public String getDisplayName(String calendarType, int field, int value, int style, Locale locale) { + if (calendarType == null || locale == null) { + throw new NullPointerException(); + } + if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { + throw new IllegalArgumentException("locale is not one of available locales: "+ locale); + } + if (field != MONTH) { + return null; + } + return toMonthName(value + 1, style); + } + + @Override + public Map getDisplayNames(String calendarType, int field, int style, Locale locale) { + if (calendarType == null || locale == null) { + throw new NullPointerException(); + } + if (!Utils.supportsLocale(Arrays.asList(avail), locale)) { + throw new IllegalArgumentException("locale is not one of available locales: " + locale); + } + if (field != MONTH) { + return null; + } + Map map = new HashMap<>(); + if (style == LONG_STANDALONE) { + style = LONG; + } else if (style == SHORT_STANDALONE) { + style = SHORT; + } + for (int month = JANUARY; month <= DECEMBER; month++) { + if (style == ALL_STYLES || style == LONG) { + map.put(toMonthName(month + 1, LONG), month); + } + if (style == ALL_STYLES || style == SHORT) { + map.put(toMonthName(month + 1, SHORT), month); + } + } + return map; + } + + @Override + public Locale[] getAvailableLocales() { + return avail.clone(); + } + + // month is 1-based. + public static String toMonthName(int month, int style) { + StringBuilder sb = new StringBuilder(); + if (month >= 10) { + sb.append((char)(FULLWIDTH_ZERO + 1)); + sb.appendCodePoint((char)(FULLWIDTH_ZERO + (month % 10))); + } else { + sb.appendCodePoint((char)(FULLWIDTH_ZERO + month)); + } + if (style == SHORT || style == SHORT_STANDALONE) { + return sb.toString(); // full-width digit(s) + } + sb.append("\u304c\u3064"); // + "gatsu" in Hiragana + return sb.toString(); + } +} diff --git a/jdk/test/java/util/PluggableLocale/providersrc/Makefile b/jdk/test/java/util/PluggableLocale/providersrc/Makefile index 3c550992691..2af60665a36 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/Makefile +++ b/jdk/test/java/util/PluggableLocale/providersrc/Makefile @@ -20,7 +20,8 @@ BARSERVICES = \ java.util.spi.CurrencyNameProvider \ java.util.spi.TimeZoneNameProvider \ java.util.spi.LocaleNameProvider \ - java.util.spi.CalendarDataProvider + java.util.spi.CalendarDataProvider \ + java.util.spi.CalendarNameProvider FOOFILES_JAVA = \ BreakIteratorProviderImpl.java \ @@ -39,6 +40,7 @@ BARFILES_JAVA = \ TimeZoneNameProviderImpl.java \ LocaleNameProviderImpl.java \ CalendarDataProviderImpl.java \ + CalendarNameProviderImpl.java \ Utils.java BARFILES_PROPERTIES = \ @@ -68,3 +70,8 @@ $(DESTDIR)/barprovider.jar: $(BARSERVICES) $(BARFILES_JAVA) $(BARFILES_PROPERTIE cp $(BARFILES_PROPERTIES) $(BARDIR)/com/bar rm -f $(DESTDIR)/barprovider.jar $(BINDIR)/jar cvf $(DESTDIR)/barprovider.jar -C $(BARDIR) . + +clean: + rm -rf $(BARDIR) $(FOODIR) + +.PHONY: all clean diff --git a/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider new file mode 100644 index 00000000000..dd6f8ec9909 --- /dev/null +++ b/jdk/test/java/util/PluggableLocale/providersrc/java.util.spi.CalendarNameProvider @@ -0,0 +1,7 @@ +# +# +# +# fully-qualified name of the java.util.spi.CalendarNameProvider +# implementation class +# +com.bar.CalendarNameProviderImpl From 96aa3fad5ae48b22c2aabee8b261efa690a288a5 Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 13 Nov 2012 20:02:48 -0800 Subject: [PATCH 03/18] 7088913: Add compatible static hashCode(primitive) to primitive wrapper classes Adds static utility methods to each primitive wrapper class to allow calculation of a hashCode value from an unboxed primitive. Reviewed-by: darcy, smarks, dholmes --- jdk/src/share/classes/java/lang/Boolean.java | 15 +++- jdk/src/share/classes/java/lang/Byte.java | 13 ++++ .../share/classes/java/lang/Character.java | 13 ++++ jdk/src/share/classes/java/lang/Double.java | 13 ++++ jdk/src/share/classes/java/lang/Float.java | 13 ++++ jdk/src/share/classes/java/lang/Integer.java | 13 ++++ jdk/src/share/classes/java/lang/Long.java | 13 ++++ jdk/src/share/classes/java/lang/Short.java | 13 ++++ jdk/test/java/lang/HashCode.java | 75 +++++++++++++++++-- 9 files changed, 172 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/java/lang/Boolean.java b/jdk/src/share/classes/java/lang/Boolean.java index feb199465ec..2c4754c8a61 100644 --- a/jdk/src/share/classes/java/lang/Boolean.java +++ b/jdk/src/share/classes/java/lang/Boolean.java @@ -196,11 +196,24 @@ public final class Boolean implements java.io.Serializable, * {@code true}; returns the integer {@code 1237} if this * object represents {@code false}. */ + @Override public int hashCode() { - return value ? 1231 : 1237; + return Boolean.hashCode(value); } /** + * Returns a hash code for a {@code boolean} value; compatible with + * {@code Boolean.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code boolean} value. + */ + public static int hashCode(boolean value) { + return value ? 1231 : 1237; + } + + /** * Returns {@code true} if and only if the argument is not * {@code null} and is a {@code Boolean} object that * represents the same {@code boolean} value as this object. diff --git a/jdk/src/share/classes/java/lang/Byte.java b/jdk/src/share/classes/java/lang/Byte.java index 799936f4a44..c4dd62ecf6d 100644 --- a/jdk/src/share/classes/java/lang/Byte.java +++ b/jdk/src/share/classes/java/lang/Byte.java @@ -389,7 +389,20 @@ public final class Byte extends Number implements Comparable { * * @return a hash code value for this {@code Byte} */ + @Override public int hashCode() { + return Byte.hashCode(value); + } + + /** + * Returns a hash code for a {@code byte} value; compatible with + * {@code Byte.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code byte} value. + */ + public static int hashCode(byte value) { return (int)value; } diff --git a/jdk/src/share/classes/java/lang/Character.java b/jdk/src/share/classes/java/lang/Character.java index 53bb738ea02..03134d06dbd 100644 --- a/jdk/src/share/classes/java/lang/Character.java +++ b/jdk/src/share/classes/java/lang/Character.java @@ -4588,7 +4588,20 @@ class Character implements java.io.Serializable, Comparable { * * @return a hash code value for this {@code Character} */ + @Override public int hashCode() { + return Character.hashCode(value); + } + + /** + * Returns a hash code for a {@code char} value; compatible with + * {@code Character.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code char} value. + */ + public static int hashCode(char value) { return (int)value; } diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index 5e1afaea747..040cca70033 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -740,7 +740,20 @@ public final class Double extends Number implements Comparable { * * @return a {@code hash code} value for this object. */ + @Override public int hashCode() { + return Double.hashCode(value); + } + + /** + * Returns a hash code for a {@code double} value; compatible with + * {@code Double.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code double} value. + */ + public static int hashCode(double value) { long bits = doubleToLongBits(value); return (int)(bits ^ (bits >>> 32)); } diff --git a/jdk/src/share/classes/java/lang/Float.java b/jdk/src/share/classes/java/lang/Float.java index 4e73507911b..1e8f6e354a9 100644 --- a/jdk/src/share/classes/java/lang/Float.java +++ b/jdk/src/share/classes/java/lang/Float.java @@ -648,7 +648,20 @@ public final class Float extends Number implements Comparable { * * @return a hash code value for this object. */ + @Override public int hashCode() { + return Float.hashCode(value); + } + + /** + * Returns a hash code for a {@code float} value; compatible with + * {@code Float.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code float} value. + */ + public static int hashCode(float value) { return floatToIntBits(value); } diff --git a/jdk/src/share/classes/java/lang/Integer.java b/jdk/src/share/classes/java/lang/Integer.java index 0943a347368..50627e99133 100644 --- a/jdk/src/share/classes/java/lang/Integer.java +++ b/jdk/src/share/classes/java/lang/Integer.java @@ -918,7 +918,20 @@ public final class Integer extends Number implements Comparable { * primitive {@code int} value represented by this * {@code Integer} object. */ + @Override public int hashCode() { + return Integer.hashCode(value); + } + + /** + * Returns a hash code for a {@code int} value; compatible with + * {@code Integer.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code int} value. + */ + public static int hashCode(int value) { return value; } diff --git a/jdk/src/share/classes/java/lang/Long.java b/jdk/src/share/classes/java/lang/Long.java index 55f7b1a7e9d..9197a6d1e26 100644 --- a/jdk/src/share/classes/java/lang/Long.java +++ b/jdk/src/share/classes/java/lang/Long.java @@ -1021,7 +1021,20 @@ public final class Long extends Number implements Comparable { * * @return a hash code value for this object. */ + @Override public int hashCode() { + return Long.hashCode(value); + } + + /** + * Returns a hash code for a {@code long} value; compatible with + * {@code Long.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code long} value. + */ + public static int hashCode(long value) { return (int)(value ^ (value >>> 32)); } diff --git a/jdk/src/share/classes/java/lang/Short.java b/jdk/src/share/classes/java/lang/Short.java index 2a1d8b5502d..f117095abe2 100644 --- a/jdk/src/share/classes/java/lang/Short.java +++ b/jdk/src/share/classes/java/lang/Short.java @@ -394,7 +394,20 @@ public final class Short extends Number implements Comparable { * * @return a hash code value for this {@code Short} */ + @Override public int hashCode() { + return Short.hashCode(value); + } + + /** + * Returns a hash code for a {@code short} value; compatible with + * {@code Short.hashCode()}. + * + * @since 1.8 + * + * @return a hash code value for a {@code short} value. + */ + public static int hashCode(short value) { return (int)value; } diff --git a/jdk/test/java/lang/HashCode.java b/jdk/test/java/lang/HashCode.java index adf773090c5..d113cb0d0fd 100644 --- a/jdk/test/java/lang/HashCode.java +++ b/jdk/test/java/lang/HashCode.java @@ -23,18 +23,20 @@ /* * @test - * @bug 4245470 + * @bug 4245470 7088913 * @summary Test the primitive wrappers hashCode() */ +import java.util.Objects; import java.util.Random; public class HashCode { final Random rnd = new Random(); - void test(String args[]) throws Exception { - int[] ints = { + void testOrdinals(String args[]) throws Exception { + long[] longs = { + Long.MIN_VALUE, Integer.MIN_VALUE, Short.MIN_VALUE, Character.MIN_VALUE, @@ -44,20 +46,73 @@ public class HashCode { Character.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE, + Long.MAX_VALUE, rnd.nextInt(), }; - for (int x : ints) { + for (long x : longs) { check( new Long(x).hashCode() == (int)((long)x ^ (long)x>>>32)); check(Long.valueOf(x).hashCode() == (int)((long)x ^ (long)x>>>32)); - check( new Integer(x).hashCode() == x); - check(Integer.valueOf(x).hashCode() == x); + check( (new Long(x)).hashCode() == Long.hashCode(x)); + check( new Integer((int)x).hashCode() == (int) x); + check(Integer.valueOf((int)x).hashCode() == (int) x); + check( (new Integer((int)x)).hashCode() == Integer.hashCode((int)x)); check( new Short((short)x).hashCode() == (short) x); check(Short.valueOf((short)x).hashCode() == (short) x); + check( (new Short((short)x)).hashCode() == Short.hashCode((short)x)); check( new Character((char) x).hashCode() == (char) x); check(Character.valueOf((char) x).hashCode() == (char) x); + check( (new Character((char)x)).hashCode() == Character.hashCode((char)x)); check( new Byte((byte) x).hashCode() == (byte) x); check(Byte.valueOf((byte) x).hashCode() == (byte) x); + check( (new Byte((byte)x)).hashCode() == Byte.hashCode((byte)x)); + } + } + + void testBoolean() { + check( Boolean.FALSE.hashCode() == 1237); + check( Boolean.TRUE.hashCode() == 1231); + check( Boolean.valueOf(false).hashCode() == 1237); + check( Boolean.valueOf(true).hashCode() == 1231); + check( (new Boolean(false)).hashCode() == 1237); + check( (new Boolean(true)).hashCode() == 1231); + check( Boolean.hashCode(false) == 1237); + check( Boolean.hashCode(true) == 1231); + } + + void testFloat() { + float[] floats = { + Float.NaN, + Float.NEGATIVE_INFINITY, + -1f, + 0f, + 1f, + Float.POSITIVE_INFINITY + }; + + for(float f : floats) { + check( Float.hashCode(f) == Float.floatToIntBits(f)); + check( Float.valueOf(f).hashCode() == Float.floatToIntBits(f)); + check( (new Float(f)).hashCode() == Float.floatToIntBits(f)); + } + } + + void testDouble() { + double[] doubles = { + Double.NaN, + Double.NEGATIVE_INFINITY, + -1f, + 0f, + 1f, + Double.POSITIVE_INFINITY + }; + + for(double d : doubles) { + long bits = Double.doubleToLongBits(d); + int bitsHash = (int)(bits^(bits>>>32)); + check( Double.hashCode(d) == bitsHash); + check( Double.valueOf(d).hashCode() == bitsHash); + check( (new Double(d)).hashCode() == bitsHash); } } @@ -69,12 +124,16 @@ public class HashCode { void unexpected(Throwable t) {failed++; t.printStackTrace();} void check(boolean cond) {if (cond) pass(); else fail();} void equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) pass(); + if (Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);} public static void main(String[] args) throws Throwable { new HashCode().instanceMain(args);} public void instanceMain(String[] args) throws Throwable { - try {test(args);} catch (Throwable t) {unexpected(t);} + try { testOrdinals(args); + testBoolean(); + testFloat(); + testDouble(); + } catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} } From 6bb3dd6ea2ec75946f0e974a88497d1cc98d96cf Mon Sep 17 00:00:00 2001 From: Sean Chou Date: Wed, 14 Nov 2012 13:26:55 +0800 Subject: [PATCH 04/18] 7201156: jar tool fails to convert file separation characters for list and extract Reviewed-by: alanb, chegar, sherman --- jdk/src/share/classes/sun/tools/jar/Main.java | 4 +- jdk/test/tools/jar/JarBackSlash.java | 135 ++++++++++++++++++ 2 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 jdk/test/tools/jar/JarBackSlash.java diff --git a/jdk/src/share/classes/sun/tools/jar/Main.java b/jdk/src/share/classes/sun/tools/jar/Main.java index 54f4deab1e8..73a3d0e1502 100644 --- a/jdk/src/share/classes/sun/tools/jar/Main.java +++ b/jdk/src/share/classes/sun/tools/jar/Main.java @@ -839,8 +839,8 @@ class Main { void replaceFSC(String files[]) { if (files != null) { - for (String file : files) { - file = file.replace(File.separatorChar, '/'); + for (int i = 0; i < files.length; i++) { + files[i] = files[i].replace(File.separatorChar, '/'); } } } diff --git a/jdk/test/tools/jar/JarBackSlash.java b/jdk/test/tools/jar/JarBackSlash.java new file mode 100644 index 00000000000..40629131738 --- /dev/null +++ b/jdk/test/tools/jar/JarBackSlash.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2012 IBM Corporation + */ + +/* + * @test + * @bug 7201156 + * @summary jar tool fails to convert file separation characters for list and extract + * @author Sean Chou + */ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; + +import sun.tools.jar.Main; + +public class JarBackSlash { + + // used construct an entry JarBackSlash/dir/file.txt + private static String JARBACKSLASH = "JarBackSlash"; + private static String DIR = "dir"; + private static String FILENAME = "file.txt"; + + private static File createJarFile() throws IOException { + File jarFile = File.createTempFile("JarBackSlashTest", ".jar"); + jarFile.deleteOnExit(); + + try (JarOutputStream output = new JarOutputStream(new FileOutputStream(jarFile))) { + JarEntry entry = new JarEntry(JARBACKSLASH + "/" + DIR + "/" + FILENAME); + output.putNextEntry(entry); + } + + return jarFile; + } + + private static void testJarList(String jarFile) throws IOException { + List argList = new ArrayList(); + argList.add("-tvf"); + argList.add(jarFile); + argList.add(JARBACKSLASH + File.separatorChar + DIR + File.separatorChar + FILENAME); + + String jarArgs[] = new String[argList.size()]; + jarArgs = argList.toArray(jarArgs); + + PipedOutputStream pipedOutput = new PipedOutputStream(); + PipedInputStream pipedInput = new PipedInputStream(pipedOutput); + PrintStream out = new PrintStream(pipedOutput); + + Main jarTool = new Main(out, System.err, "jar"); + if (!jarTool.run(jarArgs)) { + fail("Could not list jar file."); + } + + out.flush(); + check(pipedInput.available() > 0); + } + + + private static void testJarExtract(String jarFile) throws IOException { + List argList = new ArrayList(); + argList.add("-xvf"); + argList.add(jarFile); + argList.add(JARBACKSLASH + File.separatorChar + DIR + File.separatorChar + FILENAME); + + String jarArgs[] = new String[argList.size()]; + jarArgs = argList.toArray(jarArgs); + + PipedOutputStream pipedOutput = new PipedOutputStream(); + PipedInputStream pipedInput = new PipedInputStream(pipedOutput); + PrintStream out = new PrintStream(pipedOutput); + + Main jarTool = new Main(out, System.err, "jar"); + if (!jarTool.run(jarArgs)) { + fail("Could not list jar file."); + } + + out.flush(); + check(pipedInput.available() > 0); + } + + public static void realMain(String[] args) throws Throwable { + File tmpJarFile = createJarFile(); + String tmpJarFilePath = tmpJarFile.getAbsolutePath(); + + testJarList(tmpJarFilePath); + testJarExtract(tmpJarFilePath); + } + + + //--------------------- Infrastructure --------------------------- + static volatile int passed = 0, failed = 0; + static void pass() {passed++;} + static void fail() {failed++; Thread.dumpStack();} + static void fail(String msg) {System.out.println(msg); fail();} + static void unexpected(Throwable t) {failed++; t.printStackTrace();} + static void check(boolean cond) {if (cond) pass(); else fail();} + static void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + try {realMain(args);} catch (Throwable t) {unexpected(t);} + System.out.println("\nPassed = " + passed + " failed = " + failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} From 8c308db5795fbd085cb5c4481d4b2eae224b8aa0 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 14 Nov 2012 12:56:26 +0000 Subject: [PATCH 05/18] 8003285: TEST_BUG: java/nio/channels/AsynchronousChannelGroup/Unbounded.java fails again [macosx] Reviewed-by: chegar --- .../AsynchronousChannelGroup/Unbounded.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java index 6e764a2b671..cc1d71e1beb 100644 --- a/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java +++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java @@ -39,6 +39,9 @@ public class Unbounded { // set to true if an I/O operation fails static volatile boolean failed; + // set to true when the test is done + static volatile boolean finished; + public static void main(String[] args) throws Exception { // all accepted connections are added to a queue final ArrayBlockingQueue queue = @@ -54,8 +57,10 @@ public class Unbounded { listener.accept((Void)null, this); } public void failed(Throwable exc, Void att) { - failed = true; - System.err.println("accept failed: " + exc); + if (!finished) { + failed = true; + System.err.println("accept failed: " + exc); + } } }); System.out.println("Listener created."); @@ -120,8 +125,11 @@ public class Unbounded { // wait for all threads to reach the barrier System.out.println("Waiting for all threads to reach barrier"); barrier.await(); + + // finish up + finished = true; listener.close(); if (failed) - throw new RuntimeException("I/O failed failed, see log for details"); + throw new RuntimeException("I/O operation failed, see log for details"); } } From 78499292e16691ac15574a05b8882546173608d3 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Wed, 14 Nov 2012 07:08:50 -0800 Subject: [PATCH 06/18] 8000404: rename javax.tools.GenerateNativeHeader to java.lang.annotation.Native Reviewed-by: alanb --- .../classes/java/lang/annotation/Native.java | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 jdk/src/share/classes/java/lang/annotation/Native.java diff --git a/jdk/src/share/classes/java/lang/annotation/Native.java b/jdk/src/share/classes/java/lang/annotation/Native.java new file mode 100644 index 00000000000..861c1ffb996 --- /dev/null +++ b/jdk/src/share/classes/java/lang/annotation/Native.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.annotation; + + +/** + * Indicates that a field defining a constant value may be referenced + * from native code. + * + * The annotation may be used as a hint by tools that generate native + * header files to determine whether a header file is required, and + * if so, what declarations it should contain. + * + * @since 1.8 + */ +@Documented +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.SOURCE) +public @interface Native { +} From b2926d97241829807228a4dd24a59bd499152dec Mon Sep 17 00:00:00 2001 From: Mike Duigou Date: Tue, 13 Nov 2012 20:02:39 -0800 Subject: [PATCH 07/18] 7088952: Add size in bytes constant "BYTES" to primitive type wrapper types Adds a constant BYTES to each of the primitive wrapper classes (Byte, Character, Double, Float, Integer, Long, Short) with the calculation Primitive.SIZE / Byte.SIZE already made. Reviewed-by: dholmes --- jdk/src/share/classes/java/lang/Byte.java | 8 ++++++++ jdk/src/share/classes/java/lang/Character.java | 8 ++++++++ jdk/src/share/classes/java/lang/Double.java | 7 +++++++ jdk/src/share/classes/java/lang/Float.java | 7 +++++++ jdk/src/share/classes/java/lang/Integer.java | 8 ++++++++ jdk/src/share/classes/java/lang/Long.java | 8 ++++++++ jdk/src/share/classes/java/lang/Short.java | 8 ++++++++ 7 files changed, 54 insertions(+) diff --git a/jdk/src/share/classes/java/lang/Byte.java b/jdk/src/share/classes/java/lang/Byte.java index c4dd62ecf6d..43a558ade43 100644 --- a/jdk/src/share/classes/java/lang/Byte.java +++ b/jdk/src/share/classes/java/lang/Byte.java @@ -507,6 +507,14 @@ public final class Byte extends Number implements Comparable { */ public static final int SIZE = 8; + /** + * The number of bytes used to represent a {@code byte} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -7183698231559129828L; } diff --git a/jdk/src/share/classes/java/lang/Character.java b/jdk/src/share/classes/java/lang/Character.java index 03134d06dbd..0f440067b45 100644 --- a/jdk/src/share/classes/java/lang/Character.java +++ b/jdk/src/share/classes/java/lang/Character.java @@ -7170,6 +7170,14 @@ class Character implements java.io.Serializable, Comparable { */ public static final int SIZE = 16; + /** + * The number of bytes used to represent a {@code char} value in unsigned + * binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * Returns the value obtained by reversing the order of the bytes in the * specified char value. diff --git a/jdk/src/share/classes/java/lang/Double.java b/jdk/src/share/classes/java/lang/Double.java index 040cca70033..a20f79e6cb3 100644 --- a/jdk/src/share/classes/java/lang/Double.java +++ b/jdk/src/share/classes/java/lang/Double.java @@ -122,6 +122,13 @@ public final class Double extends Number implements Comparable { */ public static final int SIZE = 64; + /** + * The number of bytes used to represent a {@code double} value. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * The {@code Class} instance representing the primitive type * {@code double}. diff --git a/jdk/src/share/classes/java/lang/Float.java b/jdk/src/share/classes/java/lang/Float.java index 1e8f6e354a9..0c071e2b0f4 100644 --- a/jdk/src/share/classes/java/lang/Float.java +++ b/jdk/src/share/classes/java/lang/Float.java @@ -120,6 +120,13 @@ public final class Float extends Number implements Comparable { */ public static final int SIZE = 32; + /** + * The number of bytes used to represent a {@code float} value. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * The {@code Class} instance representing the primitive type * {@code float}. diff --git a/jdk/src/share/classes/java/lang/Integer.java b/jdk/src/share/classes/java/lang/Integer.java index 50627e99133..3496d039c1c 100644 --- a/jdk/src/share/classes/java/lang/Integer.java +++ b/jdk/src/share/classes/java/lang/Integer.java @@ -1297,6 +1297,14 @@ public final class Integer extends Number implements Comparable { */ public static final int SIZE = 32; + /** + * The number of bytes used to represent a {@code int} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * Returns an {@code int} value with at most a single one-bit, in the * position of the highest-order ("leftmost") one-bit in the specified diff --git a/jdk/src/share/classes/java/lang/Long.java b/jdk/src/share/classes/java/lang/Long.java index 9197a6d1e26..6509f88f177 100644 --- a/jdk/src/share/classes/java/lang/Long.java +++ b/jdk/src/share/classes/java/lang/Long.java @@ -1319,6 +1319,14 @@ public final class Long extends Number implements Comparable { */ public static final int SIZE = 64; + /** + * The number of bytes used to represent a {@code long} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * Returns a {@code long} value with at most a single one-bit, in the * position of the highest-order ("leftmost") one-bit in the specified diff --git a/jdk/src/share/classes/java/lang/Short.java b/jdk/src/share/classes/java/lang/Short.java index f117095abe2..6042b13f905 100644 --- a/jdk/src/share/classes/java/lang/Short.java +++ b/jdk/src/share/classes/java/lang/Short.java @@ -470,6 +470,14 @@ public final class Short extends Number implements Comparable { */ public static final int SIZE = 16; + /** + * The number of bytes used to represent a {@code short} value in two's + * complement binary form. + * + * @since 1.8 + */ + public static final int BYTES = SIZE / Byte.SIZE; + /** * Returns the value obtained by reversing the order of the bytes in the * two's complement representation of the specified {@code short} value. From f439018255b1d56a37c42b7637a5779ca1ed1a99 Mon Sep 17 00:00:00 2001 From: Jim Gish Date: Thu, 15 Nov 2012 13:46:45 +0000 Subject: [PATCH 08/18] 6244047: impossible to specify directories to logging FileHandler unless they exist Reviewed-by: alanb --- .../java/util/logging/FileHandler.java | 85 ++++--- .../util/logging/CheckLockLocationTest.java | 210 ++++++++++++++++++ 2 files changed, 266 insertions(+), 29 deletions(-) create mode 100644 jdk/test/java/util/logging/CheckLockLocationTest.java diff --git a/jdk/src/share/classes/java/util/logging/FileHandler.java b/jdk/src/share/classes/java/util/logging/FileHandler.java index 6bb88f78d63..8d3b28d8d52 100644 --- a/jdk/src/share/classes/java/util/logging/FileHandler.java +++ b/jdk/src/share/classes/java/util/logging/FileHandler.java @@ -25,10 +25,19 @@ package java.util.logging; -import java.io.*; +import static java.nio.file.StandardOpenOption.CREATE_NEW; +import static java.nio.file.StandardOpenOption.WRITE; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.security.*; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Paths; +import java.security.AccessController; +import java.security.PrivilegedAction; /** * Simple file logging Handler. @@ -137,14 +146,16 @@ public class FileHandler extends StreamHandler { private int count; private String pattern; private String lockFileName; - private FileOutputStream lockStream; + private FileChannel lockFileChannel; private File files[]; private static final int MAX_LOCKS = 100; private static java.util.HashMap locks = new java.util.HashMap<>(); - // A metered stream is a subclass of OutputStream that - // (a) forwards all its output to a target stream - // (b) keeps track of how many bytes have been written + /** + * A metered stream is a subclass of OutputStream that + * (a) forwards all its output to a target stream + * (b) keeps track of how many bytes have been written + */ private class MeteredStream extends OutputStream { OutputStream out; int written; @@ -189,9 +200,10 @@ public class FileHandler extends StreamHandler { setOutputStream(meter); } - // Private method to configure a FileHandler from LogManager - // properties and/or default values as specified in the class - // javadoc. + /** + * Configure a FileHandler from LogManager properties and/or default values + * as specified in the class javadoc. + */ private void configure() { LogManager manager = LogManager.getLogManager(); @@ -287,7 +299,8 @@ public class FileHandler extends StreamHandler { * the caller does not have LoggingPermission("control"). * @exception IllegalArgumentException if pattern is an empty string */ - public FileHandler(String pattern, boolean append) throws IOException, SecurityException { + public FileHandler(String pattern, boolean append) throws IOException, + SecurityException { if (pattern.length() < 1 ) { throw new IllegalArgumentException(); } @@ -376,8 +389,10 @@ public class FileHandler extends StreamHandler { openFiles(); } - // Private method to open the set of output files, based on the - // configured instance variables. + /** + * Open the set of output files, based on the configured + * instance variables. + */ private void openFiles() throws IOException { LogManager manager = LogManager.getLogManager(); manager.checkPermission(); @@ -413,18 +428,18 @@ public class FileHandler extends StreamHandler { // object. Try again. continue; } - FileChannel fc; + try { - lockStream = new FileOutputStream(lockFileName); - fc = lockStream.getChannel(); - } catch (IOException ix) { - // We got an IOException while trying to open the file. - // Try the next file. + lockFileChannel = FileChannel.open(Paths.get(lockFileName), + CREATE_NEW, WRITE); + } catch (FileAlreadyExistsException ix) { + // try the next lock file name in the sequence continue; } + boolean available; try { - available = fc.tryLock() != null; + available = lockFileChannel.tryLock() != null; // We got the lock OK. } catch (IOException ix) { // We got an IOException while trying to get the lock. @@ -440,7 +455,7 @@ public class FileHandler extends StreamHandler { } // We failed to get the lock. Try next file. - fc.close(); + lockFileChannel.close(); } } @@ -472,8 +487,17 @@ public class FileHandler extends StreamHandler { setErrorManager(new ErrorManager()); } - // Generate a filename from a pattern. - private File generate(String pattern, int generation, int unique) throws IOException { + /** + * Generate a file based on a user-supplied pattern, generation number, + * and an integer uniqueness suffix + * @param pattern the pattern for naming the output file + * @param generation the generation number to distinguish rotated logs + * @param unique a unique number to resolve conflicts + * @return the generated File + * @throws IOException + */ + private File generate(String pattern, int generation, int unique) + throws IOException { File file = null; String word = ""; int ix = 0; @@ -548,7 +572,9 @@ public class FileHandler extends StreamHandler { return file; } - // Rotate the set of output files + /** + * Rotate the set of output files + */ private synchronized void rotate() { Level oldLevel = getLevel(); setLevel(Level.OFF); @@ -615,9 +641,8 @@ public class FileHandler extends StreamHandler { return; } try { - // Closing the lock file's FileOutputStream will close - // the underlying channel and free any locks. - lockStream.close(); + // Close the lock file channel (which also will free any locks) + lockFileChannel.close(); } catch (Exception ex) { // Problems closing the stream. Punt. } @@ -626,7 +651,7 @@ public class FileHandler extends StreamHandler { } new File(lockFileName).delete(); lockFileName = null; - lockStream = null; + lockFileChannel = null; } private static class InitializationErrorManager extends ErrorManager { @@ -636,6 +661,8 @@ public class FileHandler extends StreamHandler { } } - // Private native method to check if we are in a set UID program. + /** + * check if we are in a set UID program. + */ private static native boolean isSetUID(); } diff --git a/jdk/test/java/util/logging/CheckLockLocationTest.java b/jdk/test/java/util/logging/CheckLockLocationTest.java new file mode 100644 index 00000000000..0eb98c0d4a0 --- /dev/null +++ b/jdk/test/java/util/logging/CheckLockLocationTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 6244047 + * @author Jim Gish + * @summary throw more precise IOException when pattern specifies invalid directory + * + * @run main/othervm CheckLockLocationTest + */ +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.AccessDeniedException; +import java.nio.file.FileSystemException; +import java.nio.file.NoSuchFileException; +import java.util.logging.FileHandler; +public class CheckLockLocationTest { + + private static final String NON_WRITABLE_DIR = "non-writable-dir"; + private static final String NOT_A_DIR = "not-a-dir"; + private static final String WRITABLE_DIR = "writable-dir"; + private static final String NON_EXISTENT_DIR = "non-existent-dir"; + + public static void main(String... args) throws IOException { + // we'll base all file creation attempts on the system temp directory, + // %t and also try specifying non-existent directories and plain files + // that should be directories, and non-writable directories, + // to exercise all code paths of checking the lock location + File writableDir = setup(); + // we now have three files/directories to work with: + // writableDir + // notAdir + // nonWritableDir + // nonExistentDir (which doesn't exist) + runTests(writableDir); + } + + /** + * @param writableDir in which log and lock file are created + * @throws SecurityException + * @throws RuntimeException + * @throws IOException + */ + private static void runTests(File writableDir) throws SecurityException, + RuntimeException, IOException { + // Test 1: make sure we can create FileHandler in writable directory + try { + new FileHandler("%t/" + WRITABLE_DIR + "/log.log"); + } catch (IOException ex) { + throw new RuntimeException("Test failed: should have been able" + + " to create FileHandler for " + "%t/" + WRITABLE_DIR + + "/log.log in writable directory.", ex); + } finally { + // the above test leaves files in the directory. Get rid of the + // files created and the directory + delete(writableDir); + } + + // Test 2: creating FileHandler in non-writable directory should fail + try { + new FileHandler("%t/" + NON_WRITABLE_DIR + "/log.log"); + throw new RuntimeException("Test failed: should not have been able" + + " to create FileHandler for " + "%t/" + NON_WRITABLE_DIR + + "/log.log in non-writable directory."); + } catch (IOException ex) { + // check for the right exception + if (!(ex instanceof AccessDeniedException)) { + throw new RuntimeException("Test failed: Expected exception was not an AccessDeniedException", ex); + } + } + + // Test 3: creating FileHandler in non-directory should fail + try { + new FileHandler("%t/" + NOT_A_DIR + "/log.log"); + throw new RuntimeException("Test failed: should not have been able" + + " to create FileHandler for " + "%t/" + NOT_A_DIR + + "/log.log in non-directory."); + } catch (IOException ex) { + // check for the right exception + if (!(ex instanceof FileSystemException && ex.getMessage().contains("Not a directory"))) { + throw new RuntimeException("Test failed: Expected exception was not a FileSystemException", ex); + } + } + + // Test 4: make sure we can't create a FileHandler in a non-existent dir + try { + new FileHandler("%t/" + NON_EXISTENT_DIR + "/log.log"); + throw new RuntimeException("Test failed: should not have been able" + + " to create FileHandler for " + "%t/" + NON_EXISTENT_DIR + + "/log.log in a non-existent directory."); + } catch (IOException ex) { + // check for the right exception + if (!(ex instanceof NoSuchFileException)) { + throw new RuntimeException("Test failed: Expected exception was not a NoSuchFileException", ex); + } + } + } + + /** + * Setup all the files and directories needed for the tests + * + * @return writable directory created that needs to be deleted when done + * @throws RuntimeException + */ + private static File setup() throws RuntimeException { + // First do some setup in the temporary directory (using same logic as + // FileHandler for %t pattern) + String tmpDir = System.getProperty("java.io.tmpdir"); // i.e. %t + if (tmpDir == null) { + tmpDir = System.getProperty("user.home"); + } + File tmpOrHomeDir = new File(tmpDir); + // Create a writable directory here (%t/writable-dir) + File writableDir = new File(tmpOrHomeDir, WRITABLE_DIR); + if (!createFile(writableDir, true)) { + throw new RuntimeException("Test setup failed: unable to create" + + " writable working directory " + + writableDir.getAbsolutePath() ); + } + // writableDirectory and its contents will be deleted after the test + // that uses it + + // Create a plain file which we will attempt to use as a directory + // (%t/not-a-dir) + File notAdir = new File(tmpOrHomeDir, NOT_A_DIR); + if (!createFile(notAdir, false)) { + throw new RuntimeException("Test setup failed: unable to a plain" + + " working file " + notAdir.getAbsolutePath() ); + } + notAdir.deleteOnExit(); + + // Create a non-writable directory (%t/non-writable-dir) + File nonWritableDir = new File(tmpOrHomeDir, NON_WRITABLE_DIR); + if (!createFile(nonWritableDir, true)) { + throw new RuntimeException("Test setup failed: unable to create" + + " a non-" + + "writable working directory " + + nonWritableDir.getAbsolutePath() ); + } + nonWritableDir.deleteOnExit(); + + // make it non-writable + if (!nonWritableDir.setWritable(false)) { + throw new RuntimeException("Test setup failed: unable to make" + + " working directory " + nonWritableDir.getAbsolutePath() + + " non-writable."); + } + + // make sure non-existent directory really doesn't exist + File nonExistentDir = new File(tmpOrHomeDir, NON_EXISTENT_DIR); + if (nonExistentDir.exists()) { + nonExistentDir.delete(); + } + return writableDir; + } + + /** + * @param newFile + * @return true if file already exists or creation succeeded + */ + private static boolean createFile(File newFile, boolean makeDirectory) { + if (newFile.exists()) { + return true; + } + if (makeDirectory) { + return newFile.mkdir(); + } else { + try { + return newFile.createNewFile(); + } catch (IOException ioex) { + ioex.printStackTrace(); + return false; + } + } + } + + /* + * Recursively delete all files starting at specified file + */ + private static void delete(File f) throws IOException { + if (f != null && f.isDirectory()) { + for (File c : f.listFiles()) + delete(c); + } + if (!f.delete()) + throw new FileNotFoundException("Failed to delete file: " + f); + } +} From 78ff6a33ee93ddbb3f4d521e31b64ac63b71730d Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 16 Nov 2012 10:34:14 +0800 Subject: [PATCH 09/18] 8003263: redundant cast build failure after 8003120 Reviewed-by: alanb --- .../share/classes/com/sun/naming/internal/ResourceManager.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java b/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java index 7443fbcf71a..bfee9dbfb39 100644 --- a/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java +++ b/jdk/src/share/classes/com/sun/naming/internal/ResourceManager.java @@ -560,8 +560,7 @@ public final class ResourceManager { } } finally { while (resources.hasMore()) { - InputStream istream = (InputStream)resources.next(); - istream.close(); + resources.next().close(); } } From 6c62e2d0f18bbdc5177b64edfd9563571b07b6aa Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 15 Nov 2012 20:17:05 -0800 Subject: [PATCH 10/18] 7199750: Loading sequence of service provider is changed Reviewed-by: okutsu --- .../provider/SPILocaleProviderAdapter.java | 26 +++++++++--------- .../CurrencyNameProviderTest.sh | 2 +- .../java/util/PluggableLocale/barprovider.jar | Bin 14629 -> 14680 bytes .../CurrencyNameProviderImpl2.java | 19 +++++++++---- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java index 1d380e38ac2..15de9f52283 100644 --- a/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java +++ b/jdk/src/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java @@ -91,7 +91,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { IllegalAccessException e) { LocaleServiceProviderPool.config(SPILocaleProviderAdapter.class, e.toString()); return null; - } + } } ((Delegate)delegate).addImpl(provider); @@ -112,7 +112,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { interface Delegate

{ public void addImpl(P impl); public P getImpl(Locale locale); -} + } /* * Obtain the real SPI implementation, using locale fallback @@ -137,7 +137,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(BreakIteratorProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -192,7 +192,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(CollatorProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -226,7 +226,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(DateFormatProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -274,7 +274,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(DateFormatSymbolsProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -308,7 +308,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(DecimalFormatSymbolsProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -342,7 +342,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(NumberFormatProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -397,7 +397,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(CalendarDataProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -438,7 +438,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(CalendarNameProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -483,7 +483,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(CurrencyNameProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -524,7 +524,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(LocaleNameProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } @@ -579,7 +579,7 @@ public class SPILocaleProviderAdapter extends AuxLocaleProviderAdapter { @Override public void addImpl(TimeZoneNameProvider impl) { for (Locale l : impl.getAvailableLocales()) { - map.put(l, impl); + map.putIfAbsent(l, impl); } } diff --git a/jdk/test/java/util/PluggableLocale/CurrencyNameProviderTest.sh b/jdk/test/java/util/PluggableLocale/CurrencyNameProviderTest.sh index 9cfc700766a..8fb9459116c 100644 --- a/jdk/test/java/util/PluggableLocale/CurrencyNameProviderTest.sh +++ b/jdk/test/java/util/PluggableLocale/CurrencyNameProviderTest.sh @@ -23,6 +23,6 @@ #!/bin/sh # # @test -# @bug 4052440 8000997 +# @bug 4052440 7199750 8000997 # @summary CurrencyNameProvider tests # @run shell ExecTest.sh bar CurrencyNameProviderTest true diff --git a/jdk/test/java/util/PluggableLocale/barprovider.jar b/jdk/test/java/util/PluggableLocale/barprovider.jar index 7f621fa3c67efb04fdf6b540bf94461bfdb87d0c..deed5facccbba17157bb62d49f5f82c70e7bbaf6 100644 GIT binary patch delta 1909 zcmZux3pkWn82;y$VTJ~SVO+*wG^S!OW=e9aTqc){TPwGrtJ}JyHZ(4~vb4GU4BN^^ zF1wLp6nV-DZ6qWs#p)i_Ls3Lg?f?Hu?C$xW^Ze(W@BPks&-b18D~q}lCF{z^V95X; zj|X@$;n}k5G4RjP-TGO%o^pO^DI>3(wP#jEk1<+mz#COjdZMBy2F{1Pj+%@@0j_*0 z{8YQetN;K2cc{aA$p8QzfcF9)VzuDSKnzX?`CAaQ!67qc$q8jV8eWiC5O(1(TnJ%7 zP?K2Eu~=mCN@|_R-AB;pO8V#=Azia$HLWBKw^^_%H-qjZ-Cy0(xW zDWtOLH0=O)8$4S+XkL9(n4A%(klbJ>bZfzEjhwAZQO&iE;L+xaoJQJ0H z7E_Y1HmHdl5HW+qW0xAMA_HEzbzJb!d3D7sG}?b?+jw3{ zS!U*hY2eg@EtG+8eVb1iX$Ea?291h@KNNpjnW^OKMMy8IC6txyYskF+)T6V1Yf5ot z(U{PokBPIbf7!3tU-(;Ks#rTUtXO2j44Tj7l70(|g^* zG6j{pt*S*cAro$XZ=Q(D)Xa&kvYG?$D%?*v*UEk34x}FJ<**p3au**`$3xo!DsR`C zcnZ%ntzk9_Mg>9EJBRan@`oBweJY1fi+qGW&rT)uIn5nOe{7i;Zr#{-gm#y&W~o{) zC%&@rQ1dUkwna6+2ItzipS1AU^FT4)ZhyPE?p$Q0C_O$Cn2%|qJ&~TDRK#vPIYYiO z#{C(QNqvf;g(x4p%I`avuZp9xJ+fHSthzcjp9KmlMJZ3LD?`f#TF1kHhHePYa zDx^*|vfVy_c&b3>Vq#?J-l6Ish5F0;K16vDCe>y?jpek3i|=&BT^h-vU$h?+rwzZ} z9!sA-Yqlv1*Q1n`;xFIv-o;_lppHg%w{dlFZPNWiDg&0SUX~_)Pkl4f<_WO=y1eDX z=okQqTd|0Q6I2f$O*=$zw`40s-w9 zdXi337W%U~RV7_i*A>!Vr9HTof$V@We1j$|(R_CQ8bs=vST^{{m<&3i5|+&IV2242 z>_NvZt{ujlK*rZmmp`vH$fD3>V39S5G3LoawZeL_%z*aB91gq!)tkkJT^zxKTTl;* z2s3o$qtG(I64s_v>eOeOFfaoV6}WJIUjl21KAvX%-roGJVx;6w<20KZzpaYkP+^z0B@efVtO(n_#0Am?A zSr^>TT}@aT*-$fGhfSPMzm6%hf)+9PIfX!P2k(7@>Ef2SqUn2M&Z z1yQEtW$}We(hQmSut_J!L<_mYIOtLp2+>J`y6G}nB*O)q6!gj{2v$8TG$jJU6#oa? z2V-pz5Str!EdT-}K;0PXUt6gW1fqj;D23Ha^9UyZLrK^8e-^=P#K{FqR(9p%p!flR N3iMH>06-tv{vWgKjVJ&B delta 1793 zcmaJ>4K!3~7{2o(Gh-&d!*C~Qn8}zh7-qyNHYuhuB4Lm6Ta=PfYqvcaD?93(N_bA%v_KCqxhLoKN{vPS z(q64ZVGPDpwaX@`4OkQyBRfhm0(^8`weHS>vt{|E8Zs*edG76g? zv#$N}W2;jBYu7((`-HJwQG#)Rq2(Dbx>U&S6|Rc2*~jJ899~b?&!_Cl=s;r!L4O;TgUk3=UX^(qlgjfNa=u;&9{n?b;n~moP7J`A-mol zhE$$hl%INwT7>uZ3hCrY?mo(#Ig`#zsXY5sIJ5oEgJ)4kHoUo$+mUmi$X#yIBWu+i z5>@bJ=hitkJ;onesfm5(ay3x_h5Bok8r2y+HJtui9Q{Fl(R=*DrF#)O8iHoe`dRL@ zqev$_yE1bMd`Qx5H6pLgabHQ_OLKA}vTha`x20ga>f#RW!k3=3Y?F+nci*l!ucxIM z3_IlnpTD@N#JkhEEt`Bg^K|G4ogIF2BCtH}(Y%@1d!H~ST?Qq4zjWf;)Y+O7C@J6rA( zTd>77f^z>>OYzIZDyLbO*@@)Ihr;WgPBpf^^xC2F!aVz+gtDOWj|J9mUgl|(dZ~r* z10?m&Hr-U$6h10Re==#9D4{_$s~eemxS^PJU6>-^ds}-nK{g-8G=o|$6$J9hL>0$XJp~^I z9`dP}DFip2pD8qyohpE_H5gFG<$>1%G77cuVeBz10x=M#9x$GVEfJ;*4uzuyCMa_l zfwb`;(Z)d{5@N6|iWc1Dvwsp(@b<#%5`O zHhX>G>|lsO0roJ~TNi=oKnZJsKY4Rif)T?2eIS@Oyn(Q?X$VVz#xJiR*BT=iDv<&~ ztR?ZU!XVeo90c2uQR4o_eJ@&Z5OiJr-$X+Ok|;_<(;y)M*0PWQG_c;@0EMD?FxHg~ zPVy`?7L^`cbAY2-t>%inCnn~T?&{Uzy5EH&J5I4U~MDl9rAE>0v= SLk=*^b+&w0{7bdXGo| diff --git a/jdk/test/java/util/PluggableLocale/providersrc/CurrencyNameProviderImpl2.java b/jdk/test/java/util/PluggableLocale/providersrc/CurrencyNameProviderImpl2.java index 5ed7222f95e..80dab1715fc 100644 --- a/jdk/test/java/util/PluggableLocale/providersrc/CurrencyNameProviderImpl2.java +++ b/jdk/test/java/util/PluggableLocale/providersrc/CurrencyNameProviderImpl2.java @@ -32,7 +32,8 @@ import java.util.spi.*; import com.foobar.Utils; public class CurrencyNameProviderImpl2 extends CurrencyNameProvider { - static Locale[] avail = {new Locale("ja", "JP", "tokyo")}; + static Locale[] avail = {new Locale("ja", "JP", "tokyo"), + new Locale("ja", "JP", "osaka"), }; public Locale[] getAvailableLocales() { return avail; } @@ -43,8 +44,12 @@ public class CurrencyNameProviderImpl2 extends CurrencyNameProvider { throw new IllegalArgumentException("locale is not supported: "+locale); } - if (c.equals("JPY") && Utils.supportsLocale(avail[0], locale)) { - return "JPY-tokyo"; + if (c.equals("JPY")) { + if (Utils.supportsLocale(avail[0], locale)) { + return "JPY-tokyo"; + } else if (Utils.supportsLocale(avail[1], locale)) { + return "JPY-osaka"; + } } return null; } @@ -55,8 +60,12 @@ public class CurrencyNameProviderImpl2 extends CurrencyNameProvider { throw new IllegalArgumentException("locale is not supported: "+locale); } - if (c.equals("JPY") && Utils.supportsLocale(avail[0], locale)) { - return "JPY-tokyo"; + if (c.equals("JPY")) { + if (Utils.supportsLocale(avail[0], locale)) { + return "JPY-tokyo"; + } else if (Utils.supportsLocale(avail[1], locale)) { + return "JPY-osaka"; + } } return null; } From ef1950d024389cce882bb96d806f41adf8bc3f79 Mon Sep 17 00:00:00 2001 From: Kurchi Subhra Hazra Date: Fri, 16 Nov 2012 12:28:45 -0800 Subject: [PATCH 11/18] 8003518: (prefs) Tests in jdk/test/java/util/prefs should not be run concurrently Add java/util/prefs to exclusiveAccess.dirs in TEST.ROOT Reviewed-by: alanb, mchung --- jdk/test/TEST.ROOT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index e8e3fda5f85..91c9dacebb2 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -9,4 +9,4 @@ keys=2d dnd i18n othervm.dirs=java/awt java/beans java/rmi javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces sun/rmi # Tests that cannot run concurrently -exclusiveAccess.dirs=java/rmi/Naming sun/management/jmxremote sun/tools/jstatd +exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd From a9594cbcebcd5f839978b4748e0ca48961f59851 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Fri, 16 Nov 2012 17:01:19 -0800 Subject: [PATCH 12/18] 7178922: (props) re-visit how os.name is determined on Mac Reviewed-by: alanb, mchung, skovatch, serb --- .../native/java/lang/java_props_macosx.c | 31 ++++++++----------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/jdk/src/solaris/native/java/lang/java_props_macosx.c b/jdk/src/solaris/native/java/lang/java_props_macosx.c index 4afca2a2ae5..c890ea8c538 100644 --- a/jdk/src/solaris/native/java/lang/java_props_macosx.c +++ b/jdk/src/solaris/native/java/lang/java_props_macosx.c @@ -145,27 +145,22 @@ PreferredToolkit getPreferredToolkit() { return pref = HToolkit; } -void setUnknownOSAndVersion(java_props_t *sprops) { - sprops->os_name = strdup("Unknown"); - sprops->os_version = strdup("Unknown"); -} - void setOSNameAndVersion(java_props_t *sprops) { + /* Don't rely on JRSCopyOSName because there's no guarantee the value will + * remain the same, or even if the JRS functions will continue to be part of + * Mac OS X. So hardcode os_name, and fill in os_version if we can. + */ + sprops->os_name = strdup("Mac OS X"); + void *jrsFwk = getJRSFramework(); - if (jrsFwk == NULL) { - setUnknownOSAndVersion(sprops); - return; + if (jrsFwk != NULL) { + char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion"); + if (copyOSVersion != NULL) { + sprops->os_version = copyOSVersion(); + return; + } } - - char *(*copyOSName)() = dlsym(jrsFwk, "JRSCopyOSName"); - char *(*copyOSVersion)() = dlsym(jrsFwk, "JRSCopyOSVersion"); - if (copyOSName == NULL || copyOSVersion == NULL) { - setUnknownOSAndVersion(sprops); - return; - } - - sprops->os_name = copyOSName(); - sprops->os_version = copyOSVersion(); + sprops->os_version = strdup("Unknown"); } From 28ca680a317f33a119a7649b6854ee5dbb3f8cfb Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Sun, 18 Nov 2012 01:31:44 -0800 Subject: [PATCH 13/18] 8003587: Warning cleanup in package javax.net.ssl Removes unnecessary imports and adds missing Override annotations Reviewed-by: xuelei --- .../classes/javax/net/ssl/HandshakeCompletedEvent.java | 1 - .../share/classes/javax/net/ssl/HostnameVerifier.java | 1 + .../share/classes/javax/net/ssl/HttpsURLConnection.java | 2 +- .../share/classes/javax/net/ssl/KeyManagerFactory.java | 1 + jdk/src/share/classes/javax/net/ssl/SSLContext.java | 1 - jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java | 1 - jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java | 1 + jdk/src/share/classes/javax/net/ssl/SSLParameters.java | 2 -- jdk/src/share/classes/javax/net/ssl/SSLPermission.java | 5 ----- .../classes/javax/net/ssl/SSLServerSocketFactory.java | 6 ++++++ jdk/src/share/classes/javax/net/ssl/SSLSession.java | 1 - jdk/src/share/classes/javax/net/ssl/SSLSocket.java | 3 --- .../share/classes/javax/net/ssl/SSLSocketFactory.java | 9 +++++++++ .../share/classes/javax/net/ssl/TrustManagerFactory.java | 1 + jdk/src/share/classes/javax/net/ssl/X509KeyManager.java | 1 - 15 files changed, 20 insertions(+), 16 deletions(-) diff --git a/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java b/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java index 39e802c4d86..f6abafaea85 100644 --- a/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java +++ b/jdk/src/share/classes/javax/net/ssl/HandshakeCompletedEvent.java @@ -29,7 +29,6 @@ import java.util.EventObject; import java.security.cert.Certificate; import java.security.Principal; import java.security.cert.X509Certificate; -import javax.security.auth.x500.X500Principal; /** * This event indicates that an SSL handshake completed on a given diff --git a/jdk/src/share/classes/javax/net/ssl/HostnameVerifier.java b/jdk/src/share/classes/javax/net/ssl/HostnameVerifier.java index d2f504f0576..402a8cd66a2 100644 --- a/jdk/src/share/classes/javax/net/ssl/HostnameVerifier.java +++ b/jdk/src/share/classes/javax/net/ssl/HostnameVerifier.java @@ -40,6 +40,7 @@ package javax.net.ssl; * verification fail. * * @author Brad R. Wetmore + * @see HostnameVerifierFactory * @since 1.4 */ diff --git a/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java b/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java index 5027b9a5788..b4c9ffe1113 100644 --- a/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java +++ b/jdk/src/share/classes/javax/net/ssl/HttpsURLConnection.java @@ -29,7 +29,6 @@ import java.net.URL; import java.net.HttpURLConnection; import java.security.Principal; import java.security.cert.X509Certificate; -import javax.security.auth.x500.X500Principal; /** * HttpsURLConnection extends HttpURLConnection @@ -196,6 +195,7 @@ class HttpsURLConnection extends HttpURLConnection */ private static class DefaultHostnameVerifier implements HostnameVerifier { + @Override public boolean verify(String hostname, SSLSession session) { return false; } diff --git a/jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java b/jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java index e7fe89f65f1..f9611c0f1d4 100644 --- a/jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/KeyManagerFactory.java @@ -68,6 +68,7 @@ public class KeyManagerFactory { public final static String getDefaultAlgorithm() { String type; type = AccessController.doPrivileged(new PrivilegedAction() { + @Override public String run() { return Security.getProperty( "ssl.KeyManagerFactory.algorithm"); diff --git a/jdk/src/share/classes/javax/net/ssl/SSLContext.java b/jdk/src/share/classes/javax/net/ssl/SSLContext.java index d3cb9700ba9..c40d7060c39 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLContext.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLContext.java @@ -26,7 +26,6 @@ package javax.net.ssl; import java.security.*; -import java.util.*; import sun.security.jca.GetInstance; diff --git a/jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java b/jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java index e4def55a09e..0b06191cc5a 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLContextSpi.java @@ -25,7 +25,6 @@ package javax.net.ssl; -import java.util.*; import java.security.*; /** diff --git a/jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java b/jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java index dd63ea4803a..45dcddbdeca 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLEngineResult.java @@ -230,6 +230,7 @@ public class SSLEngineResult { /** * Returns a String representation of this object. */ + @Override public String toString() { return ("Status = " + status + " HandshakeStatus = " + handshakeStatus + diff --git a/jdk/src/share/classes/javax/net/ssl/SSLParameters.java b/jdk/src/share/classes/javax/net/ssl/SSLParameters.java index d207f6f9e6f..c499b666091 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLParameters.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLParameters.java @@ -28,13 +28,11 @@ package javax.net.ssl; import java.security.AlgorithmConstraints; import java.util.Map; import java.util.List; -import java.util.HashSet; import java.util.HashMap; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; -import java.util.regex.Pattern; /** * Encapsulates parameters for an SSL/TLS connection. The parameters diff --git a/jdk/src/share/classes/javax/net/ssl/SSLPermission.java b/jdk/src/share/classes/javax/net/ssl/SSLPermission.java index f596925e0c0..04ebfe1543c 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLPermission.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLPermission.java @@ -26,11 +26,6 @@ package javax.net.ssl; import java.security.*; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.StringTokenizer; -import java.security.Permissions; -import java.lang.SecurityManager; /** * This class is for various network permissions. diff --git a/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java b/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java index 24911295adf..8efbd41669e 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLServerSocketFactory.java @@ -160,23 +160,27 @@ class DefaultSSLServerSocketFactory extends SSLServerSocketFactory { new SocketException(reason.toString()).initCause(reason); } + @Override public ServerSocket createServerSocket() throws IOException { return throwException(); } + @Override public ServerSocket createServerSocket(int port) throws IOException { return throwException(); } + @Override public ServerSocket createServerSocket(int port, int backlog) throws IOException { return throwException(); } + @Override public ServerSocket createServerSocket(int port, int backlog, InetAddress ifAddress) throws IOException @@ -184,10 +188,12 @@ class DefaultSSLServerSocketFactory extends SSLServerSocketFactory { return throwException(); } + @Override public String [] getDefaultCipherSuites() { return new String[0]; } + @Override public String [] getSupportedCipherSuites() { return new String[0]; } diff --git a/jdk/src/share/classes/javax/net/ssl/SSLSession.java b/jdk/src/share/classes/javax/net/ssl/SSLSession.java index 93f066744fc..7cbcf283661 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLSession.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLSession.java @@ -25,7 +25,6 @@ package javax.net.ssl; -import java.net.InetAddress; import java.security.Principal; /** diff --git a/jdk/src/share/classes/javax/net/ssl/SSLSocket.java b/jdk/src/share/classes/javax/net/ssl/SSLSocket.java index ab090130f2d..58f943ace5d 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLSocket.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLSocket.java @@ -28,9 +28,6 @@ package javax.net.ssl; import java.io.IOException; import java.net.*; -import java.util.Enumeration; -import java.util.Vector; - /** * This class extends Sockets and provides secure diff --git a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java index 73f48d197a4..151880d026f 100644 --- a/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/SSLSocketFactory.java @@ -127,6 +127,7 @@ public abstract class SSLSocketFactory extends SocketFactory static String getSecurityProperty(final String name) { return AccessController.doPrivileged(new PrivilegedAction() { + @Override public String run() { String s = java.security.Security.getProperty(name); if (s != null) { @@ -247,18 +248,21 @@ class DefaultSSLSocketFactory extends SSLSocketFactory new SocketException(reason.toString()).initCause(reason); } + @Override public Socket createSocket() throws IOException { return throwException(); } + @Override public Socket createSocket(String host, int port) throws IOException { return throwException(); } + @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException @@ -266,12 +270,14 @@ class DefaultSSLSocketFactory extends SSLSocketFactory return throwException(); } + @Override public Socket createSocket(InetAddress address, int port) throws IOException { return throwException(); } + @Override public Socket createSocket(String host, int port, InetAddress clientAddress, int clientPort) throws IOException @@ -279,6 +285,7 @@ class DefaultSSLSocketFactory extends SSLSocketFactory return throwException(); } + @Override public Socket createSocket(InetAddress address, int port, InetAddress clientAddress, int clientPort) throws IOException @@ -286,10 +293,12 @@ class DefaultSSLSocketFactory extends SSLSocketFactory return throwException(); } + @Override public String [] getDefaultCipherSuites() { return new String[0]; } + @Override public String [] getSupportedCipherSuites() { return new String[0]; } diff --git a/jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java b/jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java index b1762fc6449..91b6a0e46c1 100644 --- a/jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java +++ b/jdk/src/share/classes/javax/net/ssl/TrustManagerFactory.java @@ -65,6 +65,7 @@ public class TrustManagerFactory { public final static String getDefaultAlgorithm() { String type; type = AccessController.doPrivileged(new PrivilegedAction() { + @Override public String run() { return Security.getProperty( "ssl.TrustManagerFactory.algorithm"); diff --git a/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java b/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java index 3fcf2225b57..5174adfe412 100644 --- a/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java +++ b/jdk/src/share/classes/javax/net/ssl/X509KeyManager.java @@ -25,7 +25,6 @@ package javax.net.ssl; -import java.security.KeyManagementException; import java.security.PrivateKey; import java.security.Principal; import java.security.cert.X509Certificate; From 2aea4cbc8c0844297d3654e542bebfd9011d1d1c Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Mon, 19 Nov 2012 11:13:08 +0800 Subject: [PATCH 14/18] 8002344: Krb5LoginModule config class does not return proper KDC list from DNS Co-authored-by: Severin Gehwolf Reviewed-by: weijun --- .../classes/sun/security/krb5/Config.java | 19 +++--- jdk/test/sun/security/krb5/config/DNS.java | 38 ++++++++++++ .../security/krb5/config/NamingManager.java | 60 +++++++++++++++++++ jdk/test/sun/security/krb5/config/dns.sh | 41 +++++++++++++ 4 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 jdk/test/sun/security/krb5/config/DNS.java create mode 100644 jdk/test/sun/security/krb5/config/NamingManager.java create mode 100644 jdk/test/sun/security/krb5/config/dns.sh diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index 486f59f2ef2..1b63cd60295 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -1123,7 +1123,7 @@ public class Config { */ private String getKDCFromDNS(String realm) throws KrbException { // use DNS to locate KDC - String kdcs = null; + String kdcs = ""; String[] srvs = null; // locate DNS SRV record using UDP if (DEBUG) { @@ -1133,7 +1133,7 @@ public class Config { if (srvs == null) { // locate DNS SRV record using TCP if (DEBUG) { - System.out.println("getKDCFromDNS using UDP"); + System.out.println("getKDCFromDNS using TCP"); } srvs = KrbServiceLocator.getKerberosService(realm, "_tcp"); } @@ -1142,14 +1142,15 @@ public class Config { throw new KrbException(Krb5.KRB_ERR_GENERIC, "Unable to locate KDC for realm " + realm); } + if (srvs.length == 0) { + return null; + } for (int i = 0; i < srvs.length; i++) { - String value = srvs[i]; - for (int j = 0; j < srvs[i].length(); j++) { - // filter the KDC name - if (value.charAt(j) == ':') { - kdcs = (value.substring(0, j)).trim(); - } - } + kdcs += srvs[i].trim() + " "; + } + kdcs = kdcs.trim(); + if (kdcs.equals("")) { + return null; } return kdcs; } diff --git a/jdk/test/sun/security/krb5/config/DNS.java b/jdk/test/sun/security/krb5/config/DNS.java new file mode 100644 index 00000000000..8c574be92d5 --- /dev/null +++ b/jdk/test/sun/security/krb5/config/DNS.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// See dns.sh. +import sun.security.krb5.Config; + +public class DNS { + public static void main(String[] args) throws Exception { + System.setProperty("java.security.krb5.conf", + System.getProperty("test.src", ".") +"/nothing.conf"); + Config config = Config.getInstance(); + String kdcs = config.getKDCList("X"); + if (!kdcs.equals("a.com.:88 b.com.:99") && + !kdcs.equals("a.com. b.com.:99")) { + throw new Exception("Strange KDC: [" + kdcs + "]"); + }; + } +} diff --git a/jdk/test/sun/security/krb5/config/NamingManager.java b/jdk/test/sun/security/krb5/config/NamingManager.java new file mode 100644 index 00000000000..47f4f412deb --- /dev/null +++ b/jdk/test/sun/security/krb5/config/NamingManager.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 javax.naming.spi; + +import com.sun.jndi.dns.DnsContext; +import java.util.Hashtable; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.Attributes; +import javax.naming.directory.BasicAttribute; +import javax.naming.directory.BasicAttributes; + +/** + * A fake javax.naming.spi.NamingManager. It allows reading a DNS + * record without contacting a real server. + * + * See DNS.java and dns.sh. + */ +public class NamingManager { + NamingManager() {} + public static Context getURLContext( + String scheme, Hashtable environment) + throws NamingException { + return new DnsContext("", null, new Hashtable()) { + public Attributes getAttributes(String name, String[] attrIds) + throws NamingException { + return new BasicAttributes() { + public Attribute get(String attrID) { + BasicAttribute ba = new BasicAttribute(attrID); + ba.add("1 1 99 b.com."); + ba.add("0 0 88 a.com."); // 2nd has higher priority + return ba; + } + }; + } + }; + } +} diff --git a/jdk/test/sun/security/krb5/config/dns.sh b/jdk/test/sun/security/krb5/config/dns.sh new file mode 100644 index 00000000000..5c85f8aa776 --- /dev/null +++ b/jdk/test/sun/security/krb5/config/dns.sh @@ -0,0 +1,41 @@ +# +# Copyright (c) 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. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please 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 8002344 +# @summary Krb5LoginModule config class does not return proper KDC list from DNS +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +if [ "${TESTSRC}" = "" ] ; then + TESTSRC="." +fi + +$TESTJAVA/bin/javac -d . \ + ${TESTSRC}/NamingManager.java ${TESTSRC}/DNS.java +$TESTJAVA/bin/java -Xbootclasspath/p:. DNS + From c94385feb8f42918c56882f86bc166bc82b38694 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 19 Nov 2012 13:17:40 +0000 Subject: [PATCH 15/18] 8003607: More ProblemList.txt updates (11/2012) Reviewed-by: lancea --- jdk/test/ProblemList.txt | 6 +++--- jdk/test/TEST.ROOT | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 80fc546756b..975a54b06c0 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -148,9 +148,6 @@ java/lang/management/MemoryMXBean/LowMemoryTest2.sh generic-all # 6959636 javax/management/loading/LibraryLoader/LibraryLoaderTest.java windows-all -# 7144846 -javax/management/remote/mandatory/connection/ReconnectTest.java generic-all - # 7120365 javax/management/remote/mandatory/notif/DiffHBTest.java generic-all @@ -376,6 +373,9 @@ java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java generic-all # Filed 6772009 java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all +# 8003596 +java/util/logging/CheckLockLocationTest.java windows-all + # 7041639, Solaris DSA keypair generation bug java/util/TimeZone/TimeZoneDatePermissionCheck.sh solaris-all diff --git a/jdk/test/TEST.ROOT b/jdk/test/TEST.ROOT index 91c9dacebb2..1645f6b26da 100644 --- a/jdk/test/TEST.ROOT +++ b/jdk/test/TEST.ROOT @@ -9,4 +9,4 @@ keys=2d dnd i18n othervm.dirs=java/awt java/beans java/rmi javax/accessibility javax/imageio javax/sound javax/print javax/management com/sun/awt sun/awt sun/java2d sun/pisces sun/rmi # Tests that cannot run concurrently -exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd +exclusiveAccess.dirs=java/rmi/Naming java/util/prefs sun/management/jmxremote sun/tools/jstatd sun/security/mscapi From 0bb98e7294ce0ad5249d506fa484e72b520231da Mon Sep 17 00:00:00 2001 From: John Zavgren Date: Tue, 20 Nov 2012 09:26:38 +0000 Subject: [PATCH 16/18] 8000476: Memory Leaks and uninitialized memory access in PKCS11 and other native code Reviewed-by: dsamersoff, valeriep, chegar --- jdk/src/share/bin/wildcard.c | 5 ++++ .../sun/security/jgss/wrapper/GSSLibStub.c | 2 +- .../sun/security/pkcs11/wrapper/p11_mutex.c | 30 +++++++++++++++---- jdk/src/solaris/bin/java_md_solinux.c | 2 ++ 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/bin/wildcard.c b/jdk/src/share/bin/wildcard.c index 9ed1b494c69..f8f664450e3 100644 --- a/jdk/src/share/bin/wildcard.c +++ b/jdk/src/share/bin/wildcard.c @@ -356,8 +356,13 @@ wildcardFileList(const char *wildcard) const char *basename; FileList fl = FileList_new(16); WildcardIterator it = WildcardIterator_for(wildcard); + if (it == NULL) + { + FileList_free(fl); return NULL; + } + while ((basename = WildcardIterator_next(it)) != NULL) if (isJarFileName(basename)) FileList_add(fl, wildcardConcat(wildcard, basename)); diff --git a/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c b/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c index abd2c2d5295..33cd3644e97 100644 --- a/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c +++ b/jdk/src/share/native/sun/security/jgss/wrapper/GSSLibStub.c @@ -571,7 +571,7 @@ Java_sun_security_jgss_wrapper_GSSLibStub_releaseCred(JNIEnv *env, */ void inquireCred(JNIEnv *env, jobject jobj, gss_cred_id_t pCred, jint type, void *result) { - OM_uint32 minor, major=GSS_C_QOP_DEFAULT; + OM_uint32 minor, major=0; OM_uint32 routineErr; gss_cred_id_t credHdl; diff --git a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c index 92ba7d8e207..5c39b105333 100644 --- a/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c +++ b/jdk/src/share/native/sun/security/pkcs11/wrapper/p11_mutex.c @@ -112,22 +112,34 @@ CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) ckpInitArgs->UnlockMutex = NULL_PTR; #else fieldID = (*env)->GetFieldID(env, jInitArgsClass, "CreateMutex", "Lsun/security/pkcs11/wrapper/CK_CREATEMUTEX;"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); ckpInitArgs->CreateMutex = (jMutexHandler != NULL) ? &callJCreateMutex : NULL_PTR; fieldID = (*env)->GetFieldID(env, jInitArgsClass, "DestroyMutex", "Lsun/security/pkcs11/wrapper/CK_DESTROYMUTEX;"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); ckpInitArgs->DestroyMutex = (jMutexHandler != NULL) ? &callJDestroyMutex : NULL_PTR; fieldID = (*env)->GetFieldID(env, jInitArgsClass, "LockMutex", "Lsun/security/pkcs11/wrapper/CK_LOCKMUTEX;"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); ckpInitArgs->LockMutex = (jMutexHandler != NULL) ? &callJLockMutex : NULL_PTR; fieldID = (*env)->GetFieldID(env, jInitArgsClass, "UnlockMutex", "Lsun/security/pkcs11/wrapper/CK_UNLOCKMUTEX;"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jMutexHandler = (*env)->GetObjectField(env, jInitArgs, fieldID); ckpInitArgs->UnlockMutex = (jMutexHandler != NULL) ? &callJUnlockMutex : NULL_PTR; @@ -151,13 +163,19 @@ CK_C_INITIALIZE_ARGS_PTR makeCKInitArgsAdapter(JNIEnv *env, jobject jInitArgs) /* convert and set the flags field */ fieldID = (*env)->GetFieldID(env, jInitArgsClass, "flags", "J"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jFlags = (*env)->GetLongField(env, jInitArgs, fieldID); ckpInitArgs->flags = jLongToCKULong(jFlags); /* pReserved should be NULL_PTR in this version */ fieldID = (*env)->GetFieldID(env, jInitArgsClass, "pReserved", "Ljava/lang/Object;"); - if (fieldID == NULL) { return NULL; } + if (fieldID == NULL) { + free(ckpInitArgs); + return NULL; + } jReserved = (*env)->GetObjectField(env, jInitArgs, fieldID); /* we try to convert the reserved parameter also */ diff --git a/jdk/src/solaris/bin/java_md_solinux.c b/jdk/src/solaris/bin/java_md_solinux.c index fc8bc99d5f9..46ae9d635ea 100644 --- a/jdk/src/solaris/bin/java_md_solinux.c +++ b/jdk/src/solaris/bin/java_md_solinux.c @@ -478,9 +478,11 @@ CreateExecutionEnvironment(int *pargc, char ***pargv, JLI_TraceLauncher("mustsetenv: %s\n", mustsetenv ? "TRUE" : "FALSE"); if (mustsetenv == JNI_FALSE) { + JLI_MemFree(newargv); return; } #else + JLI_MemFree(newargv); return; #endif /* SETENV_REQUIRED */ } else { /* do the same speculatively or exit */ From 5f0debc0052156076b54468b7da1d34a67c4f3a5 Mon Sep 17 00:00:00 2001 From: David Dehaven Date: Mon, 19 Nov 2012 19:49:38 -0800 Subject: [PATCH 17/18] 8001533: java launcher must launch javafx applications Reviewed-by: ksrini, mchung, kcr, alanb --- jdk/src/share/bin/java.c | 36 ++- .../classes/sun/launcher/LauncherHelper.java | 239 ++++++++++++------ .../launcher/resources/launcher.properties | 5 +- jdk/test/tools/launcher/TestHelper.java | 10 + 4 files changed, 214 insertions(+), 76 deletions(-) diff --git a/jdk/src/share/bin/java.c b/jdk/src/share/bin/java.c index 2d9d5b4e47f..f08a52a9db2 100644 --- a/jdk/src/share/bin/java.c +++ b/jdk/src/share/bin/java.c @@ -105,6 +105,7 @@ static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv, InvocationFunctions *ifn); static jstring NewPlatformString(JNIEnv *env, char *s); static jclass LoadMainClass(JNIEnv *env, int mode, char *name); +static jclass GetApplicationClass(JNIEnv *env); static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv); static jboolean AddApplicationOptions(int cpathc, const char **cpathv); @@ -346,6 +347,7 @@ JavaMain(void * _args) JavaVM *vm = 0; JNIEnv *env = 0; jclass mainClass = NULL; + jclass appClass = NULL; // actual application class being launched jmethodID mainID; jobjectArray mainArgs; int ret = 0; @@ -419,10 +421,28 @@ JavaMain(void * _args) * all environments, * 2) Remove the vestages of maintaining main_class through * the environment (and remove these comments). + * + * This method also correctly handles launching existing JavaFX + * applications that may or may not have a Main-Class manifest entry. */ mainClass = LoadMainClass(env, mode, what); CHECK_EXCEPTION_NULL_LEAVE(mainClass); - PostJVMInit(env, mainClass, vm); + /* + * In some cases when launching an application that needs a helper, e.g., a + * JavaFX application with no main method, the mainClass will not be the + * applications own main class but rather a helper class. To keep things + * consistent in the UI we need to track and report the application main class. + */ + appClass = GetApplicationClass(env); + NULL_CHECK(appClass); + /* + * PostJVMInit uses the class name as the application name for GUI purposes, + * for example, on OSX this sets the application name in the menu bar for + * both SWT and JavaFX. So we'll pass the actual application class here + * instead of mainClass as that may be a launcher or helper class instead + * of the application class. + */ + PostJVMInit(env, appClass, vm); /* * The LoadMainClass not only loads the main class, it will also ensure * that the main method's signature is correct, therefore further checking @@ -1215,6 +1235,20 @@ LoadMainClass(JNIEnv *env, int mode, char *name) return (jclass)result; } +static jclass +GetApplicationClass(JNIEnv *env) +{ + jmethodID mid; + jobject result; + jclass cls = GetLauncherHelperClass(env); + NULL_CHECK0(cls); + NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, + "getApplicationClass", + "()Ljava/lang/Class;")); + + return (*env)->CallStaticObjectMethod(env, cls, mid); +} + /* * For tools, convert command line args thus: * javac -cp foo:foo/"*" -J-ms32m ... diff --git a/jdk/src/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/share/classes/sun/launcher/LauncherHelper.java index b58e3ca1543..3b899bcca4d 100644 --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java @@ -69,7 +69,6 @@ import java.util.jar.Manifest; public enum LauncherHelper { INSTANCE; private static final String MAIN_CLASS = "Main-Class"; - private static StringBuilder outBuf = new StringBuilder(); private static final String INDENT = " "; @@ -87,6 +86,9 @@ public enum LauncherHelper { private static final ResourceBundle RB = ResourceBundle.getBundle(defaultBundleName); } + private static PrintStream ostream; + private static final ClassLoader scloader = ClassLoader.getSystemClassLoader(); + private static Class appClass; // application class, for GUI/reporting purposes /* * A method called by the launcher to print out the standard settings, @@ -114,27 +116,27 @@ public enum LauncherHelper { long initialHeapSize, long maxHeapSize, long stackSize, boolean isServer) { - PrintStream ostream = (printToStderr) ? System.err : System.out; + initOutput(printToStderr); String opts[] = optionFlag.split(":"); String optStr = (opts.length > 1 && opts[1] != null) ? opts[1].trim() : "all"; switch (optStr) { case "vm": - printVmSettings(ostream, initialHeapSize, maxHeapSize, - stackSize, isServer); + printVmSettings(initialHeapSize, maxHeapSize, + stackSize, isServer); break; case "properties": - printProperties(ostream); + printProperties(); break; case "locale": - printLocale(ostream); + printLocale(); break; default: - printVmSettings(ostream, initialHeapSize, maxHeapSize, - stackSize, isServer); - printProperties(ostream); - printLocale(ostream); + printVmSettings(initialHeapSize, maxHeapSize, stackSize, + isServer); + printProperties(); + printLocale(); break; } } @@ -142,7 +144,7 @@ public enum LauncherHelper { /* * prints the main vm settings subopt/section */ - private static void printVmSettings(PrintStream ostream, + private static void printVmSettings( long initialHeapSize, long maxHeapSize, long stackSize, boolean isServer) { @@ -172,14 +174,14 @@ public enum LauncherHelper { /* * prints the properties subopt/section */ - private static void printProperties(PrintStream ostream) { + private static void printProperties() { Properties p = System.getProperties(); ostream.println(PROP_SETTINGS); List sortedPropertyKeys = new ArrayList<>(); sortedPropertyKeys.addAll(p.stringPropertyNames()); Collections.sort(sortedPropertyKeys); for (String x : sortedPropertyKeys) { - printPropertyValue(ostream, x, p.getProperty(x)); + printPropertyValue(x, p.getProperty(x)); } ostream.println(); } @@ -188,8 +190,7 @@ public enum LauncherHelper { return key.endsWith(".dirs") || key.endsWith(".path"); } - private static void printPropertyValue(PrintStream ostream, - String key, String value) { + private static void printPropertyValue(String key, String value) { ostream.print(INDENT + key + " = "); if (key.equals("line.separator")) { for (byte b : value.getBytes()) { @@ -229,7 +230,7 @@ public enum LauncherHelper { /* * prints the locale subopt/section */ - private static void printLocale(PrintStream ostream) { + private static void printLocale() { Locale locale = Locale.getDefault(); ostream.println(LOCALE_SETTINGS); ostream.println(INDENT + "default locale = " + @@ -238,11 +239,11 @@ public enum LauncherHelper { Locale.getDefault(Category.DISPLAY).getDisplayName()); ostream.println(INDENT + "default format locale = " + Locale.getDefault(Category.FORMAT).getDisplayName()); - printLocales(ostream); + printLocales(); ostream.println(); } - private static void printLocales(PrintStream ostream) { + private static void printLocales() { Locale[] tlocales = Locale.getAvailableLocales(); final int len = tlocales == null ? 0 : tlocales.length; if (len < 1 ) { @@ -370,7 +371,7 @@ public enum LauncherHelper { * initHelpSystem must be called before using this method. */ static void printHelpMessage(boolean printToStderr) { - PrintStream ostream = (printToStderr) ? System.err : System.out; + initOutput(printToStderr); outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer", File.pathSeparator)); ostream.println(outBuf.toString()); @@ -380,7 +381,7 @@ public enum LauncherHelper { * Prints the Xusage text to the desired output stream. */ static void printXUsageMessage(boolean printToStderr) { - PrintStream ostream = (printToStderr) ? System.err : System.out; + initOutput(printToStderr); ostream.println(getLocalizedMessage("java.launcher.X.usage", File.pathSeparator)); if (System.getProperty("os.name").contains("OS X")) { @@ -389,36 +390,32 @@ public enum LauncherHelper { } } - static String getMainClassFromJar(PrintStream ostream, String jarname) { - try { - JarFile jarFile = null; - try { - jarFile = new JarFile(jarname); - Manifest manifest = jarFile.getManifest(); - if (manifest == null) { - abort(ostream, null, "java.launcher.jar.error2", jarname); - } - Attributes mainAttrs = manifest.getMainAttributes(); - if (mainAttrs == null) { - abort(ostream, null, "java.launcher.jar.error3", jarname); - } - String mainValue = mainAttrs.getValue(MAIN_CLASS); - if (mainValue == null) { - abort(ostream, null, "java.launcher.jar.error3", jarname); - } - return mainValue.trim(); - } finally { - if (jarFile != null) { - jarFile.close(); - } + static void initOutput(boolean printToStderr) { + ostream = (printToStderr) ? System.err : System.out; + } + + static String getMainClassFromJar(String jarname) { + String mainValue = null; + try (JarFile jarFile = new JarFile(jarname)) { + Manifest manifest = jarFile.getManifest(); + if (manifest == null) { + abort(null, "java.launcher.jar.error2", jarname); } + Attributes mainAttrs = manifest.getMainAttributes(); + if (mainAttrs == null) { + abort(null, "java.launcher.jar.error3", jarname); + } + mainValue = mainAttrs.getValue(MAIN_CLASS); + if (mainValue == null) { + abort(null, "java.launcher.jar.error3", jarname); + } + return mainValue.trim(); } catch (IOException ioe) { - abort(ostream, ioe, "java.launcher.jar.error1", jarname); + abort(ioe, "java.launcher.jar.error1", jarname); } return null; } - // From src/share/bin/java.c: // enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR }; @@ -426,7 +423,7 @@ public enum LauncherHelper { private static final int LM_CLASS = 1; private static final int LM_JAR = 2; - static void abort(PrintStream ostream, Throwable t, String msgKey, Object... args) { + static void abort(Throwable t, String msgKey, Object... args) { if (msgKey != null) { ostream.println(getLocalizedMessage(msgKey, args)); } @@ -450,19 +447,22 @@ public enum LauncherHelper { * b. is there a main * c. is the main public * d. is the main static - * c. does the main take a String array for args - * 4. and off we go...... + * e. does the main take a String array for args + * 4. if no main method and if the class extends FX Application, then call + * on FXHelper to determine the main class to launch + * 5. and off we go...... * - * @param printToStderr - * @param isJar - * @param name - * @return + * @param printToStderr if set, all output will be routed to stderr + * @param mode LaunchMode as determined by the arguments passed on the + * command line + * @param what either the jar file to launch or the main class when using + * LM_CLASS mode + * @return the application's main class */ public static Class checkAndLoadMain(boolean printToStderr, int mode, String what) { - final PrintStream ostream = (printToStderr) ? System.err : System.out; - final ClassLoader ld = ClassLoader.getSystemClassLoader(); + initOutput(printToStderr); // get the class name String cn = null; switch (mode) { @@ -470,44 +470,75 @@ public enum LauncherHelper { cn = what; break; case LM_JAR: - cn = getMainClassFromJar(ostream, what); + cn = getMainClassFromJar(what); break; default: // should never happen throw new InternalError("" + mode + ": Unknown launch mode"); } cn = cn.replace('/', '.'); - Class c = null; + Class mainClass = null; try { - c = ld.loadClass(cn); - } catch (ClassNotFoundException cnfe) { - abort(ostream, cnfe, "java.launcher.cls.error1", cn); + mainClass = scloader.loadClass(cn); + } catch (NoClassDefFoundError | ClassNotFoundException cnfe) { + abort(cnfe, "java.launcher.cls.error1", cn); } - getMainMethod(ostream, c); - return c; + // set to mainClass, FXHelper may return something else + appClass = mainClass; + + Method m = getMainMethod(mainClass); + if (m != null) { + // this will abort if main method has the wrong signature + validateMainMethod(m); + return mainClass; + } + + // Check if FXHelper can launch it using the FX launcher + Class fxClass = FXHelper.getFXMainClass(mainClass); + if (fxClass != null) { + return fxClass; + } + + // not an FX application either, abort with an error + abort(null, "java.launcher.cls.error4", mainClass.getName(), + FXHelper.JAVAFX_APPLICATION_CLASS_NAME); + return null; // avoid compiler error... } - static Method getMainMethod(PrintStream ostream, Class clazz) { - String classname = clazz.getName(); - Method method = null; + /* + * Accessor method called by the launcher after getting the main class via + * checkAndLoadMain(). The "application class" is the class that is finally + * executed to start the application and in this case is used to report + * the correct application name, typically for UI purposes. + */ + public static Class getApplicationClass() { + return appClass; + } + + // Check for main method or return null if not found + static Method getMainMethod(Class clazz) { try { - method = clazz.getMethod("main", String[].class); - } catch (NoSuchMethodException nsme) { - abort(ostream, null, "java.launcher.cls.error4", classname); - } + return clazz.getMethod("main", String[].class); + } catch (NoSuchMethodException nsme) {} + return null; + } + + // Check the signature of main and abort if it's incorrect + static void validateMainMethod(Method mainMethod) { /* * getMethod (above) will choose the correct method, based * on its name and parameter type, however, we still have to * ensure that the method is static and returns a void. */ - int mod = method.getModifiers(); + int mod = mainMethod.getModifiers(); if (!Modifier.isStatic(mod)) { - abort(ostream, null, "java.launcher.cls.error2", "static", classname); + abort(null, "java.launcher.cls.error2", "static", + mainMethod.getDeclaringClass().getName()); } - if (method.getReturnType() != java.lang.Void.TYPE) { - abort(ostream, null, "java.launcher.cls.error3", classname); + if (mainMethod.getReturnType() != java.lang.Void.TYPE) { + abort(null, "java.launcher.cls.error3", + mainMethod.getDeclaringClass().getName()); } - return method; } private static final String encprop = "sun.jnu.encoding"; @@ -519,7 +550,7 @@ public enum LauncherHelper { * previously implemented as a native method in the launcher. */ static String makePlatformString(boolean printToStderr, byte[] inArray) { - final PrintStream ostream = (printToStderr) ? System.err : System.out; + initOutput(printToStderr); if (encoding == null) { encoding = System.getProperty(encprop); isCharsetSupported = Charset.isSupported(encoding); @@ -530,7 +561,7 @@ public enum LauncherHelper { : new String(inArray); return out; } catch (UnsupportedEncodingException uee) { - abort(ostream, uee, null); + abort(uee, null); } return null; // keep the compiler happy } @@ -611,5 +642,65 @@ public enum LauncherHelper { return "StdArg{" + "arg=" + arg + ", needsExpansion=" + needsExpansion + '}'; } } + + static final class FXHelper { + private static final String JAVAFX_APPLICATION_CLASS_NAME = + "javafx.application.Application"; + private static final String JAVAFX_LAUNCHER_CLASS_NAME = + "com.sun.javafx.application.LauncherImpl"; + + /* + * FX application launcher and launch method, so we can launch + * applications with no main method. + */ + private static Class fxLauncherClass = null; + private static Method fxLauncherMethod = null; + + /* + * We can assume that the class does NOT have a main method or it would + * have been handled already. We do, however, need to check if the class + * extends Application and the launcher is available and abort with an + * error if it's not. + */ + private static Class getFXMainClass(Class mainClass) { + // Check if mainClass extends Application + if (!doesExtendFXApplication(mainClass)) { + return null; + } + + // Check for the FX launcher classes + try { + fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME); + fxLauncherMethod = fxLauncherClass.getMethod("launchApplication", + Class.class, String[].class); + } catch (ClassNotFoundException | NoSuchMethodException ex) { + abort(ex, "java.launcher.cls.error5", ex); + } + + // That's all, return this class so we can launch later + return FXHelper.class; + } + + /* + * Check if the given class is a JavaFX Application class. This is done + * in a way that does not cause the Application class to load or throw + * ClassNotFoundException if the JavaFX runtime is not available. + */ + private static boolean doesExtendFXApplication(Class mainClass) { + for (Class sc = mainClass.getSuperclass(); sc != null; + sc = sc.getSuperclass()) { + if (sc.getName().equals(JAVAFX_APPLICATION_CLASS_NAME)) { + return true; + } + } + return false; + } + + // preloader ? + public static void main(String... args) throws Exception { + // launch appClass via fxLauncherMethod + fxLauncherMethod.invoke(null, new Object[] {appClass, args}); + } + } } diff --git a/jdk/src/share/classes/sun/launcher/resources/launcher.properties b/jdk/src/share/classes/sun/launcher/resources/launcher.properties index 5603953e75d..bfa05181784 100644 --- a/jdk/src/share/classes/sun/launcher/resources/launcher.properties +++ b/jdk/src/share/classes/sun/launcher/resources/launcher.properties @@ -131,7 +131,10 @@ java.launcher.cls.error3=\ \ public static void main(String[] args) java.launcher.cls.error4=\ Error: Main method not found in class {0}, please define the main method as:\n\ -\ public static void main(String[] args) +\ public static void main(String[] args)\n\ + or a JavaFX application class must extend {1} +java.launcher.cls.error5=\ + Error: JavaFX runtime components are missing, and are required to run this application java.launcher.jar.error1=\ Error: An unexpected error occurred while trying to open file {0} java.launcher.jar.error2=manifest not found in {0} diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 6738eba5e19..e630dd5df54 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -559,6 +559,16 @@ public class TestHelper { return false; } + boolean notContains(String str) { + for (String x : testOutput) { + if (x.contains(str)) { + appendError("string <" + str + "> found"); + return false; + } + } + return true; + } + boolean matches(String stringToMatch) { for (String x : testOutput) { if (x.matches(stringToMatch)) { From 6dfea5e847148d6e7f4e919f39f8d45b4efb7276 Mon Sep 17 00:00:00 2001 From: Steve Sides Date: Mon, 19 Nov 2012 19:50:39 -0800 Subject: [PATCH 18/18] 8003660: (launcher) 8001533 regression tests Reviewed-by: ksrini, mchung, kcr, ddehaven --- jdk/test/tools/launcher/FXLauncherTest.java | 307 ++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 jdk/test/tools/launcher/FXLauncherTest.java diff --git a/jdk/test/tools/launcher/FXLauncherTest.java b/jdk/test/tools/launcher/FXLauncherTest.java new file mode 100644 index 00000000000..9b58c0846c0 --- /dev/null +++ b/jdk/test/tools/launcher/FXLauncherTest.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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 8001533 + * @summary Test launching FX application with java -jar + * Test uses main method and blank main method, a jfx app class and an incorrest + * jfx app class, a main-class for the manifest, a bogus one and none. + * All should execute except the incorrect fx app class entries. + * @run main FXLauncherTest + */ +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class FXLauncherTest extends TestHelper { + private static final String FX_MARKER_CLASS = "javafx.application.Application"; + private static void line() { + System.out.println("_____________________________________________"); + } + private static File MainJavaFile = null; + private static final File FXtestJar = new File("fxtest.jar"); + private static final File ManifestFile = new File("manifest.txt"); + private static final File ScratchDir = new File("."); + + /* standard main class can be used as java main for fx app class */ + static final String StdMainClass = "helloworld.HelloWorld"; + static int testcount = 0; + + /* a main method and a blank. */ + static final String[] MAIN_METHODS = { + "public static void main(String[] args) { launch(args); }", + " " + }; + + // Array of parameters to pass to fx application. + static final String[] APP_PARMS = { "one", "two" }; + + // Create fx java file for test application + static void createJavaFile(String mainmethod) { + try { + String mainClass = "HelloWorld"; + List contents = new ArrayList<>(); + contents.add("package helloworld;"); + contents.add("import javafx.application.Application;"); + contents.add("import javafx.event.ActionEvent;"); + contents.add("import javafx.event.EventHandler;"); + contents.add("import javafx.scene.Scene;"); + contents.add("import javafx.scene.control.Button;"); + contents.add("import javafx.scene.layout.StackPane;"); + contents.add("import javafx.stage.Stage;"); + contents.add("public class HelloWorld extends Application {"); + contents.add(mainmethod); + contents.add("@Override"); + contents.add("public void start(Stage primaryStage) {"); + contents.add(" primaryStage.setTitle(\"Hello World!\");"); + contents.add(" Button btn = new Button();"); + contents.add(" btn.setText(\"Say 'Hello World'\");"); + contents.add(" btn.setOnAction(new EventHandler() {"); + contents.add(" @Override"); + contents.add(" public void handle(ActionEvent event) {"); + contents.add(" System.out.println(\"Hello World!\");"); + contents.add(" }"); + contents.add(" });"); + contents.add(" StackPane root = new StackPane();"); + contents.add(" root.getChildren().add(btn);"); + contents.add(" primaryStage.setScene(new Scene(root, 300, 250));"); + contents.add("// primaryStage.show(); no GUI for auto tests. "); + contents.add(" System.out.println(\"HelloWorld.primaryStage.show();\");"); + contents.add(" System.out.println(\"Parameters:\");" ); + contents.add(" for(String p : getParameters().getUnnamed())"); + contents.add(" System.out.println(\"parameter: \" + p );" ); + contents.add(" System.exit(0);"); + contents.add("}"); + contents.add("}"); + + // Create and compile java source. + MainJavaFile = new File(mainClass + JAVA_FILE_EXT); + createFile(MainJavaFile, contents); + compile("-d", ".", mainClass + JAVA_FILE_EXT); + } catch (java.io.IOException ioe) { + ioe.printStackTrace(); + throw new RuntimeException("Failed creating HelloWorld."); + } + } + + /* + * Create class to extend fx java file for test application + * TODO: make test to create java file and this extension of the java file + * and jar them together an run app via this java class. + */ + static void createExtJavaFile(String mainmethod) { + try { + String mainClass = "ExtHello"; + List contents = new ArrayList<>(); + contents.add("package helloworld;"); + contents.add("public class ExtHello extends HelloWorld {"); + contents.add(mainmethod); + contents.add("}"); + // Create and compile java source. + MainJavaFile = new File(mainClass + JAVA_FILE_EXT); + createFile(MainJavaFile, contents); + compile("-cp", ".", "-d", ".", mainClass + JAVA_FILE_EXT); + } catch (java.io.IOException ioe) { + ioe.printStackTrace(); + throw new RuntimeException("Failed creating HelloWorld."); + } + } + + // Create manifest for test fx application + static List createManifestContents(String mainclassentry) { + List mcontents = new ArrayList<>(); + mcontents.add("Manifest-Version: 1.0"); + mcontents.add("Created-By: FXLauncherTest"); + mcontents.add("Main-Class: " + mainclassentry); + return mcontents; + } + + // Method to marshal createJar to TestHelper.createJar() + static void createJar(File theJar, File manifestFile) { + createJar("cvmf", manifestFile.getName(), + theJar.getAbsolutePath(), "helloworld"); + } + + static void saveFile(String tname, int testcount, File srcFile) { + File newFile = new File(tname + "-" + testcount + "-" + srcFile.getName()); + System.out.println("renaming " + srcFile.getName() + + " to " + newFile.getName()); + srcFile.renameTo(newFile); + } + + static void cleanupFiles() throws IOException { + for(File f : ScratchDir.listFiles()) { + recursiveDelete(f); + } + } + + static void checkStatus(TestResult tr, String testName, int testCount, + String mainclass) throws Exception { + if (tr.testStatus) { + System.out.println("PASS: " + testName + ":" + testCount + + " : test with " + mainclass); + cleanupFiles(); + } else { + saveFile(testName, testcount, FXtestJar); + System.out.println("FAIL: " + testName + ":" + testCount + + " : test with " + mainclass); + cleanupFiles(); + System.err.println(tr); + throw new Exception("Failed: " + testName + ":" + testCount); + } + } + + /* + * Set Main-Class and iterate main_methods. + * Try launching with both -jar and -cp methods. + * All cases should run. + */ + @Test + static void testBasicFXApp() throws Exception { + testBasicFXApp(true); + testBasicFXApp(false); + } + + static void testBasicFXApp(boolean useCP) throws Exception { + String testname = "testBasicFXApp"; + for (String mm : MAIN_METHODS) { + testcount++; + line(); + System.out.println("test# " + testcount + + "- Main method: " + mm + + "; MF main class: " + StdMainClass); + createJavaFile(mm); + createFile(ManifestFile, createManifestContents(StdMainClass)); + createJar(FXtestJar, ManifestFile); + String sTestJar = FXtestJar.getAbsolutePath(); + TestResult tr; + if (useCP) { + tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]); + testname = testname.concat("_useCP"); + } else { + tr = doExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]); + } + tr.checkPositive(); + if (tr.testStatus && tr.contains("HelloWorld.primaryStage.show()")) { + for (String p : APP_PARMS) { + if (!tr.contains(p)) { + System.err.println("ERROR: Did not find " + + p + " in output!"); + } + } + } + checkStatus(tr, testname, testcount, StdMainClass); + } + } + + /* + * Set Main-Class and iterate main methods. + * Main class extends another class that extends Application. + * Try launching with both -jar and -cp methods. + * All cases should run. + */ + @Test + static void testExtendFXApp() throws Exception { + testExtendFXApp(true); + testExtendFXApp(false); + } + + static void testExtendFXApp(boolean useCP) throws Exception { + String testname = "testExtendFXApp"; + for (String mm : MAIN_METHODS) { + testcount++; + line(); + System.out.println("test# " + testcount + + "- Main method: " + mm + "; MF main class: " + StdMainClass); + createJavaFile(mm); + createExtJavaFile(mm); + createFile(ManifestFile, createManifestContents(StdMainClass)); + createJar(FXtestJar, ManifestFile); + String sTestJar = FXtestJar.getAbsolutePath(); + TestResult tr; + if (useCP) { + tr = doExec(javaCmd, "-cp", sTestJar, StdMainClass, APP_PARMS[0], APP_PARMS[1]); + testname = testname.concat("_useCP"); + } else { + tr = doExec(javaCmd, "-jar", sTestJar, APP_PARMS[0], APP_PARMS[1]); + } + tr.checkPositive(); + if (tr.testStatus && tr.contains("HelloWorld.primaryStage.show()")) { + for (String p : APP_PARMS) { + if (!tr.contains(p)) { + System.err.println("ERROR: Did not find " + + p + " in output!"); + } + } + } + checkStatus(tr, testname, testcount, StdMainClass); + } + } + + /* + * test to ensure that we don't load any extraneous fx jars when + * launching a standard java application + */ + @Test + static void testExtraneousJars()throws Exception { + String testname = "testExtraneousJars"; + testcount++; + line(); + System.out.println("test# " + testcount); + TestResult tr = doExec(javacCmd, "-J-verbose:class", "-version"); + if (!tr.notContains("jfxrt.jar")) { + System.out.println("testing for extraneous jfxrt jar"); + System.out.println(tr); + throw new Exception("jfxrt.jar is being loaded by javac!!!"); + } + checkStatus(tr, testname, testcount, StdMainClass); + } + + public static void main(String... args) throws Exception { + //check if fx is part of jdk + Class fxClass = null; + try { + fxClass = Class.forName(FX_MARKER_CLASS); + } catch (ClassNotFoundException ex) { + // do nothing + } + if (fxClass != null) { + FXLauncherTest fxt = new FXLauncherTest(); + fxt.run(args); + if (testExitValue > 0) { + System.out.println("Total of " + testExitValue + + " failed. Test cases covered: " + + FXLauncherTest.testcount); + System.exit(1); + } else { + System.out.println("All tests pass. Test cases covered: " + + FXLauncherTest.testcount); + } + } else { + System.err.println("Warning: JavaFX components missing or not supported"); + System.err.println(" test passes vacuosly."); + } + } +}