author | lana |
Wed, 18 Nov 2009 18:56:59 -0800 | |
changeset 4284 | 12d5126755c0 |
parent 4268 | 505b39f182af (current diff) |
parent 4283 | 06d5378aaff3 (diff) |
child 4285 | aba524fe54db |
jdk/src/share/classes/javax/swing/JTextField.java | file | annotate | diff | comparison | revisions | |
jdk/src/share/classes/javax/swing/SwingUtilities.java | file | annotate | diff | comparison | revisions |
--- a/jdk/make/sun/javazic/tzdata/VERSION Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/VERSION Wed Nov 18 18:56:59 2009 -0800 @@ -21,4 +21,4 @@ # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. # -tzdata2009l +tzdata2009r
--- a/jdk/make/sun/javazic/tzdata/antarctica Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/antarctica Wed Nov 18 18:56:59 2009 -0800 @@ -102,15 +102,38 @@ # Davis, Vestfold Hills, -6835+07759, since 1957-01-13 # (except 1964-11 - 1969-02) # Mawson, Holme Bay, -6736+06253, since 1954-02-13 + +# From Steffen Thorsen (2009-03-11): +# Three Australian stations in Antarctica have changed their time zone: +# Casey moved from UTC+8 to UTC+11 +# Davis moved from UTC+7 to UTC+5 +# Mawson moved from UTC+6 to UTC+5 +# The changes occurred on 2009-10-18 at 02:00 (local times). +# +# Government source: (Australian Antarctic Division) +# <a href="http://www.aad.gov.au/default.asp?casid=37079"> +# http://www.aad.gov.au/default.asp?casid=37079 +# </a> +# +# We have more background information here: +# <a href="http://www.timeanddate.com/news/time/antarctica-new-times.html"> +# http://www.timeanddate.com/news/time/antarctica-new-times.html +# </a> + # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Antarctica/Casey 0 - zzz 1969 - 8:00 - WST # Western (Aus) Standard Time + 8:00 - WST 2009 Oct 18 2:00 + # Western (Aus) Standard Time + 11:00 - CAST # Casey Time Zone Antarctica/Davis 0 - zzz 1957 Jan 13 7:00 - DAVT 1964 Nov # Davis Time 0 - zzz 1969 Feb - 7:00 - DAVT + 7:00 - DAVT 2009 Oct 18 2:0 + 5:00 - DAVT Zone Antarctica/Mawson 0 - zzz 1954 Feb 13 - 6:00 - MAWT # Mawson Time + 6:00 - MAWT 2009 Oct 18 2:00 + # Mawson Time + 5:00 - MAWT # References: # <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html"> # Casey Weather (1998-02-26)
--- a/jdk/make/sun/javazic/tzdata/asia Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/asia Wed Nov 18 18:56:59 2009 -0800 @@ -21,7 +21,6 @@ # CA 95054 USA or visit www.sun.com if you need additional information or # have any questions. # -# <pre> # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. @@ -194,11 +193,30 @@ # # No DST end date has been announced yet. -# From Arthur David Olson (2009-07-11): -# Arbitrarily end DST at the end of 2009 so that a POSIX-sytle time zone string -# can appear in the Dhaka binary file and for the benefit of old glibc -# reimplementations of the time zone software that mishandle permanent DST. -# A change will be required once the end date is known. +# From Alexander Krivenyshev (2009-09-25): +# Bangladesh won't go back to Standard Time from October 1, 2009, +# instead it will continue DST measure till the cabinet makes a fresh decision. +# +# Following report by same newspaper-"The Daily Star Friday": +# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1" +# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=107021"> +# http://www.thedailystar.net/newDesign/news-details.php?nid=107021 +# </a> +# or +# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html"> +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html +# </a> + +# From Steffen Thorsen (2009-10-13): +# IANS (Indo-Asian News Service) now reports: +# Bangladesh has decided that the clock advanced by an hour to make +# maximum use of daylight hours as an energy saving measure would +# "continue for an indefinite period." +# +# One of many places where it is published: +# <a href="http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html"> +# http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html +# </a> # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Dhaka 6:01:40 - LMT 1890 @@ -208,8 +226,7 @@ 6:30 - BURT 1951 Sep 30 6:00 - DACT 1971 Mar 26 # Dacca Time 6:00 - BDT 2009 Jun 19 23:00 # Bangladesh Time - 6:00 1:00 BDST 2010 - 6:00 - BDT + 6:00 1:00 BDST # Bhutan # Zone NAME GMTOFF RULES FORMAT [UNTIL] @@ -373,14 +390,84 @@ 5:00 - KAST 1980 May 8:00 PRC C%sT + +# From Lee Yiu Chung (2009-10-24): +# I found there are some mistakes for the historial DST rule for Hong +# Kong. Accoring to the DST record from Hong Kong Observatory (actually, +# it is not [an] observatory, but the official meteorological agency of HK, +# and also serves as the official timing agency), there are some missing +# and incorrect rules. Although the exact switch over time is missing, I +# think 3:30 is correct. The official DST record for Hong Kong can be +# obtained from +# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm"> +# http://www.hko.gov.hk/gts/time/Summertime.htm +# </a>. + +# From Arthur David Olson (2009-10-28): +# Here are the dates given at +# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm"> +# http://www.hko.gov.hk/gts/time/Summertime.htm +# </a> +# as of 2009-10-28: +# Year Period +# 1941 1 Apr to 30 Sep +# 1942 Whole year +# 1943 Whole year +# 1944 Whole year +# 1945 Whole year +# 1946 20 Apr to 1 Dec +# 1947 13 Apr to 30 Dec +# 1948 2 May to 31 Oct +# 1949 3 Apr to 30 Oct +# 1950 2 Apr to 29 Oct +# 1951 1 Apr to 28 Oct +# 1952 6 Apr to 25 Oct +# 1953 5 Apr to 1 Nov +# 1954 21 Mar to 31 Oct +# 1955 20 Mar to 6 Nov +# 1956 18 Mar to 4 Nov +# 1957 24 Mar to 3 Nov +# 1958 23 Mar to 2 Nov +# 1959 22 Mar to 1 Nov +# 1960 20 Mar to 6 Nov +# 1961 19 Mar to 5 Nov +# 1962 18 Mar to 4 Nov +# 1963 24 Mar to 3 Nov +# 1964 22 Mar to 1 Nov +# 1965 18 Apr to 17 Oct +# 1966 17 Apr to 16 Oct +# 1967 16 Apr to 22 Oct +# 1968 21 Apr to 20 Oct +# 1969 20 Apr to 19 Oct +# 1970 19 Apr to 18 Oct +# 1971 18 Apr to 17 Oct +# 1972 16 Apr to 22 Oct +# 1973 22 Apr to 21 Oct +# 1973/74 30 Dec 73 to 20 Oct 74 +# 1975 20 Apr to 19 Oct +# 1976 18 Apr to 17 Oct +# 1977 Nil +# 1978 Nil +# 1979 13 May to 21 Oct +# 1980 to Now Nil +# The page does not give start or end times of day. +# The page does not give a start date for 1942. +# The page does not givw an end date for 1945. +# The Japanese occupation of Hong Kong began on 1941-12-25. +# The Japanese surrender of Hong Kong was signed 1945-09-15. +# For lack of anything better, use start of those days as the transition times. + # Hong Kong (Xianggang) # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S +Rule HK 1941 only - Apr 1 3:30 1:00 S +Rule HK 1941 only - Sep 30 3:30 0 - Rule HK 1946 only - Apr 20 3:30 1:00 S Rule HK 1946 only - Dec 1 3:30 0 - Rule HK 1947 only - Apr 13 3:30 1:00 S Rule HK 1947 only - Dec 30 3:30 0 - Rule HK 1948 only - May 2 3:30 1:00 S -Rule HK 1948 1952 - Oct lastSun 3:30 0 - +Rule HK 1948 1951 - Oct lastSun 3:30 0 - +Rule HK 1952 only - Oct 25 3:30 0 - Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S Rule HK 1953 only - Nov 1 3:30 0 - Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S @@ -388,13 +475,15 @@ Rule HK 1955 1964 - Nov Sun>=1 3:30 0 - Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S Rule HK 1965 1977 - Oct Sun>=16 3:30 0 - -Rule HK 1979 1980 - May Sun>=8 3:30 1:00 S -Rule HK 1979 1980 - Oct Sun>=16 3:30 0 - +Rule HK 1973 only - Dec 30 3:30 1:00 S +Rule HK 1979 only - May Sun>=8 3:30 1:00 S +Rule HK 1979 only - Oct Sun>=16 3:30 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30 + 8:00 HK HK%sT 1941 Dec 25 + 9:00 - JST 1945 Sep 15 8:00 HK HK%sT - ############################################################################### # Taiwan @@ -1696,16 +1785,66 @@ # advance clocks in the country by one hour from April 15 to # conserve energy" -# From Arthur David Olson (2009-04-10): -# Assume for now that Pakistan will end DST in 2009 as it did in 2008. +# From Steffen Thorsen (2009-09-17): +# "The News International," Pakistan reports that: "The Federal +# Government has decided to restore the previous time by moving the +# clocks backward by one hour from October 1. A formal announcement to +# this effect will be made after the Prime Minister grants approval in +# this regard." +# <a href="http://www.thenews.com.pk/updates.asp?id=87168"> +# http://www.thenews.com.pk/updates.asp?id=87168 +# </a> + +# From Alexander Krivenyshev (2009-09-28): +# According to Associated Press Of Pakistan, it is confirmed that +# Pakistan clocks across the country would be turned back by an hour from October +# 1, 2009. +# +# "Clocks to go back one hour from 1 Oct" +# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2"> +# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2 +# </a> +# or +# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm"> +# http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm +# </a> + +# From Steffen Thorsen (2009-09-29): +# Alexander Krivenyshev wrote: +# > According to Associated Press Of Pakistan, it is confirmed that +# > Pakistan clocks across the country would be turned back by an hour from October +# > 1, 2009. +# +# Now they seem to have changed their mind, November 1 is the new date: +# <a href="http://www.thenews.com.pk/top_story_detail.asp?Id=24742"> +# http://www.thenews.com.pk/top_story_detail.asp?Id=24742 +# </a> +# "The country's clocks will be reversed by one hour on November 1. +# Officials of Federal Ministry for Interior told this to Geo News on +# Monday." +# +# And more importantly, it seems that these dates will be kept every year: +# "It has now been decided that clocks will be wound forward by one hour +# on April 15 and reversed by an hour on November 1 every year without +# obtaining prior approval, the officials added." +# +# We have confirmed this year's end date with both with the Ministry of +# Water and Power and the Pakistan Electric Power Company: +# <a href="http://www.timeanddate.com/news/time/pakistan-ends-dst09.html"> +# http://www.timeanddate.com/news/time/pakistan-ends-dst09.html +# </a> + +# From Christoph Goehre (2009-10-01): +# [T]he German Consulate General in Karachi reported me today that Pakistan +# will go back to standard time on 1st of November. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Pakistan 2002 only - Apr Sun>=2 0:01 1:00 S Rule Pakistan 2002 only - Oct Sun>=2 0:01 0 - Rule Pakistan 2008 only - Jun 1 0:00 1:00 S Rule Pakistan 2008 only - Nov 1 0:00 0 - -Rule Pakistan 2009 only - Apr 15 0:00 1:00 S -Rule Pakistan 2009 only - Nov 1 0:00 0 - +Rule Pakistan 2009 max - Apr 15 0:00 1:00 S +Rule Pakistan 2009 max - Nov 1 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Karachi 4:28:12 - LMT 1907 5:30 - IST 1942 Sep @@ -1858,6 +1997,42 @@ # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html # </a> +# From Steffen Thorsen (2009-08-31): +# Palestine's Council of Ministers announced that they will revert back to +# winter time on Friday, 2009-09-04. +# +# One news source: +# <a href="http://www.safa.ps/ara/?action=showdetail&seid=4158"> +# http://www.safa.ps/ara/?action=showdetail&seid=4158 +# </a> +# (Palestinian press agency, Arabic), +# Google translate: "Decided that the Palestinian government in Ramallah +# headed by Salam Fayyad, the start of work in time for the winter of +# 2009, starting on Friday approved the fourth delay Sept. clock sixty +# minutes per hour as of Friday morning." +# +# We are not sure if Gaza will do the same, last year they had a different +# end date, we will keep this page updated: +# <a href="http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html"> +# http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html +# </a> + +# From Alexander Krivenyshev (2009-09-02): +# Seems that Gaza Strip will go back to Winter Time same date as West Bank. +# +# According to Palestinian Ministry Of Interior, West Bank and Gaza Strip plan +# to change time back to Standard time on September 4, 2009. +# +# "Winter time unite the West Bank and Gaza" +# (from Palestinian National Authority): +# <a href="http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505 +# http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505 +# </a> +# or +# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html> +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html +# </a> + # The rules for Egypt are stolen from the `africa' file. # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule EgyptAsia 1957 only - May 10 0:00 1:00 S @@ -1876,7 +2051,7 @@ Rule Palestine 2007 only - Sep Thu>=8 2:00 0 - Rule Palestine 2008 only - Aug lastFri 2:00 0 - Rule Palestine 2009 max - Mar lastFri 0:00 1:00 S -Rule Palestine 2009 max - Sep lastMon 2:00 0 - +Rule Palestine 2009 max - Sep Fri>=1 2:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Gaza 2:17:52 - LMT 1900 Oct @@ -2154,9 +2329,23 @@ # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html # </a> +# From Steffen Thorsen (2009-10-27): +# The Syrian Arab News Network on 2009-09-29 reported that Syria will +# revert back to winter (standard) time on midnight between Thursday +# 2009-10-29 and Friday 2009-10-30: +# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm"> +# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic) +# </a> + +# From Arthur David Olson (2009-10-28): +# We'll see if future DST switching times turn out to be end of the last +# Thursday of the month or the start of the last Friday of the month or +# something else. For now, use the start of the last Friday. + Rule Syria 2008 only - Apr Fri>=1 0:00 1:00 S -Rule Syria 2008 max - Nov 1 0:00 0 - +Rule Syria 2008 only - Nov 1 0:00 0 - Rule Syria 2009 max - Mar lastFri 0:00 1:00 S +Rule Syria 2009 max - Oct lastFri 0:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
--- a/jdk/make/sun/javazic/tzdata/australasia Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/australasia Wed Nov 18 18:56:59 2009 -0800 @@ -465,10 +465,56 @@ # http://www.worldtimezone.com/dst_news/dst_news_samoa01.html # </a> +# From Steffen Thorsen (2009-08-27): +# Samoa's parliament passed the Daylight Saving Bill 2009, and will start +# daylight saving time on the first Sunday of October 2009 and end on the +# last Sunday of March 2010. We hope that the full text will be published +# soon, but we believe that the bill is only valid for 2009-2010. Samoa's +# Daylight Saving Act 2009 will be enforced as soon as the Head of State +# executes a proclamation publicizing this Act. +# +# Some background information here, which will be updated once we have +# more details: +# <a href="http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html"> +# http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html +# </a> + +# From Alexander Krivenyshev (2009-10-03): +# First, my deepest condolences to people of Samoa islands and all families and +# loved ones around the world who lost their lives in the earthquake and tsunami. +# +# Considering the recent devastation on Samoa by earthquake and tsunami and that +# many government offices/ ministers are closed- not sure if "Daylight Saving +# Bill 2009" will be implemented in next few days- on October 4, 2009. +# +# Here is reply from Consulate-General of Samoa in New Zealand +# --------------------------- +# Consul General +# consulgeneral@samoaconsulate.org.nz +# +# Talofa Alexander, +# +# Thank you for your sympathy for our country but at this time we have not +# been informed about the Daylight Savings Time Change. Most Ministries in +# Apia are closed or relocating due to weather concerns. +# +# When we do find out if they are still proceeding with the time change we +# will advise you soonest. +# +# Kind Regards, +# Lana +# for: Consul General + +# From Steffen Thorsen (2009-10-05): +# We have called a hotel in Samoa and asked about local time there - they +# are still on standard time. + Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5 -11:26:56 - LMT 1911 -11:30 - SAMT 1950 # Samoa Time - -11:00 - WST # Samoa Time + -11:00 - WST 2009 Oct 4 + -11:00 1:00 WSDT 2010 Mar 28 + -11:00 - WST # Solomon Is # excludes Bougainville, for which see Papua New Guinea
--- a/jdk/make/sun/javazic/tzdata/europe Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/europe Wed Nov 18 18:56:59 2009 -0800 @@ -2094,9 +2094,43 @@ 6:00 Russia NOV%sT 1992 Jan 19 2:00s 7:00 Russia NOV%sT 1993 May 23 # say Shanks & P. 6:00 Russia NOV%sT + +# From Alexander Krivenyshev (2009-10-13): +# Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on +# March 28, 2010: +# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700 +# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600 +# +# This is according to Government of Russia decree # 740, on September +# 14, 2009 "Application in the territory of the Kemerovo region the Fifth +# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600) +# +# Russian Government web site (Russian language) +# <a href="http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archiv"> +# http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm +# </a> +# or Russian-English translation by WorldTimeZone.com with reference +# map to local region and new Russia Time Zone map after March 28, 2010 +# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia03.html"> +# http://www.worldtimezone.com/dst_news/dst_news_russia03.html +# </a> +# +# Thus, when Russia will switch to DST on the night of March 28, 2010 +# Kemerovo region (Kemerovo oblast') will not change the clock. +# +# As a result, Kemerovo oblast' will be in the same time zone as +# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic. + +Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6 + 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time + 7:00 Russia KRA%sT 1991 Mar 31 2:00s + 6:00 Russia KRA%sT 1992 Jan 19 2:00s + 7:00 Russia KRA%sT 2010 Mar 28 2:00s + 6:00 Russia NOV%sT # Novosibirsk/Novokuznetsk Time + # # From Oscar van Vlijmen (2001-08-25): [This region consists of] -# Kemerovskaya oblast', Krasnoyarskij kraj, +# Krasnoyarskij kraj, # Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug, # Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug. Zone Asia/Krasnoyarsk 6:11:20 - LMT 1920 Jan 6
--- a/jdk/make/sun/javazic/tzdata/southamerica Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/southamerica Wed Nov 18 18:56:59 2009 -0800 @@ -237,9 +237,23 @@ # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc # </a> +# From fullinet (2009-10-18): +# As announced in +# <a hef="http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356"> +# http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356 +# </a> +# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change") +# +# "Por el momento, el Gobierno Nacional resolvio no modificar la hora +# oficial, decision que estaba en estudio para su implementacion el +# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio +# que la Argentina hoy, en estas condiciones meteorologicas, no necesita +# la modificacion del huso horario, ya que 2009 nos encuentra con +# crecimiento en la produccion y distribucion energetica." + Rule Arg 2007 only - Dec 30 0:00 1:00 S -Rule Arg 2008 max - Mar Sun>=15 0:00 0 - -Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S +Rule Arg 2008 2009 - Mar Sun>=15 0:00 0 - +Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S # From Mariano Absatz (2004-05-21): # Today it was officially published that the Province of Mendoza is changing @@ -411,15 +425,40 @@ # during 2009, this timezone change will run from 00:00 the third Sunday # in March until 24:00 of the second Saturday in October. -# From Arthur David Olson (2009-03-16): -# The unofficial claim at -# <a href="http://www.timeanddate.com/news/time/san-luis-new-time-zone.html"> -# http://www.timeanddate.com/news/time/san-luis-new-time-zone.html +# From Mariano Absatz (2009-10-16): +# ...the Province of San Luis is a case in itself. +# +# The Law at +# <a href="http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276>" +# http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276 # </a> -# is that "The province will most likely follow the next daylight saving schedule, -# which is planned for the second Sunday in October." +# is ambiguous because establishes a calendar from the 2nd Sunday in +# October at 0:00 thru the 2nd Saturday in March at 24:00 and the +# complement of that starting on the 2nd Sunday of March at 0:00 and +# ending on the 2nd Saturday of March at 24:00. +# +# This clearly breaks every time the 1st of March or October is a Sunday. +# +# IMHO, the "spirit of the Law" is to make the changes at 0:00 on the 2nd +# Sunday of October and March. +# +# The problem is that the changes in the rest of the Provinces that did +# change in 2007/2008, were made according to the Federal Law and Decrees +# that did so on the 3rd Sunday of October and March. +# +# In fact, San Luis actually switched from UTC-4 to UTC-3 last Sunday +# (October 11th) at 0:00. +# +# So I guess a new set of rules, besides "Arg", must be made and the last +# America/Argentina/San_Luis entries should change to use these... +# +# I'm enclosing a patch that does what I say... regretfully, the San Luis +# timezone must be called "WART/WARST" even when most of the time (like, +# right now) WARST == ART... that is, since last Sunday, all the country +# is using UTC-3, but in my patch, San Luis calls it "WARST" and the rest +# of the country calls it "ART". +# ... -# # Zone NAME GMTOFF RULES FORMAT [UNTIL] # # Buenos Aires (BA), Capital Federal (CF), @@ -552,6 +591,10 @@ -3:00 - ART # # San Luis (SL) + +Rule SanLuis 2008 max - Mar Sun>=8 0:00 0 - +Rule SanLuis 2007 max - Oct Sun>=8 0:00 1:00 S + Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31 -4:16:48 - CMT 1920 May -4:00 - ART 1930 Dec @@ -566,8 +609,7 @@ -3:00 - ART 2004 May 31 -4:00 - WART 2004 Jul 25 -3:00 Arg AR%sT 2008 Jan 21 - -3:00 - ART 2009 Mar 15 - -4:00 Arg WAR%sT + -4:00 SanLuis WAR%sT # # Santa Cruz (SC) Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
--- a/jdk/make/sun/javazic/tzdata/zone.tab Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/make/sun/javazic/tzdata/zone.tab Wed Nov 18 18:56:59 2009 -0800 @@ -352,6 +352,7 @@ RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk +RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River
--- a/jdk/src/share/classes/java/awt/font/NumericShaper.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/java/awt/font/NumericShaper.java Wed Nov 18 18:56:59 2009 -0800 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,13 @@ package java.awt.font; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Comparator; +import java.util.EnumSet; +import java.util.Set; + /** * The <code>NumericShaper</code> class is used to convert Latin-1 (European) * digits to other Unicode decimal digits. Users of this class will @@ -64,13 +71,261 @@ * NumericShaper.getContextualShaper(NumericShaper.ARABIC | * NumericShaper.TAMIL, * NumericShaper.EUROPEAN); - * shaper.shape(text. start, count); + * shaper.shape(text, start, count); + * </pre></blockquote> + * + * <p><b>Bit mask- and enum-based Unicode ranges</b></p> + * + * <p>This class supports two different programming interfaces to + * represent Unicode ranges for script-specific digits: bit + * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and + * enum-based ones, such as {@link NumericShaper.Range#ARABIC}. + * Multiple ranges can be specified by ORing bit mask-based constants, + * such as: + * <blockquote><pre> + * NumericShaper.ARABIC | NumericShaper.TAMIL * </pre></blockquote> + * or creating a {@code Set} with the {@link NumericShaper.Range} + * constants, such as: + * <blockquote><pre> + * EnumSet.of(NumericShaper.Scirpt.ARABIC, NumericShaper.Range.TAMIL) + * </pre></blockquote> + * The enum-based ranges are a super set of the bit mask-based ones. + * + * <p>If the two interfaces are mixed (including serialization), + * Unicode range values are mapped to their counterparts where such + * mapping is possible, such as {@code NumericShaper.Range.ARABIC} + * from/to {@code NumericShaper.ARABIC}. If any unmappable range + * values are specified, such as {@code NumericShaper.Range.BALINESE}, + * those ranges are ignored. * * @since 1.4 */ public final class NumericShaper implements java.io.Serializable { + /** + * A {@code NumericShaper.Range} represents a Unicode range of a + * script having its own decimal digits. For example, the {@link + * NumericShaper.Range#THAI} range has the Thai digits, THAI DIGIT + * ZERO (U+0E50) to THAI DIGIT NINE (U+0E59). + * + * <p>The <code>Range</code> enum replaces the traditional bit + * mask-based values (e.g., {@link NumericShaper#ARABIC}), and + * supports more Unicode ranges than the bit mask-based ones. For + * example, the following code using the bit mask: + * <blockquote><pre> + * NumericShaper.getContextualShaper(NumericShaper.ARABIC | + * NumericShaper.TAMIL, + * NumericShaper.EUROPEAN); + * </pre></blockquote> + * can be written using this enum as: + * <blockquote><pre> + * NumericShaper.getContextualShaper(EnumSet.of( + * NumericShaper.Range.ARABIC, + * NumericShaper.Range.TAMIL), + * NumericShaper.Range.EUROPEAN); + * </pre></blockquote> + * + * @since 1.7 + */ + public static enum Range { + /** + * The Latin (European) range with the Latin (ASCII) digits. + */ + EUROPEAN ('\u0030', '\u0000', '\u0300'), + /** + * The Arabic range with the Arabic-Indic digits. + */ + ARABIC ('\u0660', '\u0600', '\u0780'), + /** + * The Arabic range with the Eastern Arabic-Indic digits. + */ + EASTERN_ARABIC ('\u06f0', '\u0600', '\u0780'), + /** + * The Devanagari range with the Devanagari digits. + */ + DEVANAGARI ('\u0966', '\u0900', '\u0980'), + /** + * The Bengali range with the Bengali digits. + */ + BENGALI ('\u09e6', '\u0980', '\u0a00'), + /** + * The Gurmukhi range with the Gurmukhi digits. + */ + GURMUKHI ('\u0a66', '\u0a00', '\u0a80'), + /** + * The Gujarati range with the Gujarati digits. + */ + GUJARATI ('\u0ae6', '\u0b00', '\u0b80'), + /** + * The Oriya range with the Oriya digits. + */ + ORIYA ('\u0b66', '\u0b00', '\u0b80'), + /** + * The Tamil range with the Tamil digits. + */ + TAMIL ('\u0be6', '\u0b80', '\u0c00'), + /** + * The Telugu range with the Telugu digits. + */ + TELUGU ('\u0c66', '\u0c00', '\u0c80'), + /** + * The Kannada range with the Kannada digits. + */ + KANNADA ('\u0ce6', '\u0c80', '\u0d00'), + /** + * The Malayalam range with the Malayalam digits. + */ + MALAYALAM ('\u0d66', '\u0d00', '\u0d80'), + /** + * The Thai range with the Thai digits. + */ + THAI ('\u0e50', '\u0e00', '\u0e80'), + /** + * The Lao range with the Lao digits. + */ + LAO ('\u0ed0', '\u0e80', '\u0f00'), + /** + * The Tibetan range with the Tibetan digits. + */ + TIBETAN ('\u0f20', '\u0f00', '\u1000'), + /** + * The Myanmar range with the Myanmar digits. + */ + MYANMAR ('\u1040', '\u1000', '\u1080'), + /** + * The Ethiopic range with the Ethiopic digits. Ethiopic + * does not have a decimal digit 0 so Latin (European) 0 is + * used. + */ + ETHIOPIC ('\u1369', '\u1200', '\u1380') { + @Override + char getNumericBase() { return 1; } + }, + /** + * The Khmer range with the Khmer digits. + */ + KHMER ('\u17e0', '\u1780', '\u1800'), + /** + * The Mongolian range with the Mongolian digits. + */ + MONGOLIAN ('\u1810', '\u1800', '\u1900'), + /** + * The N'Ko range with the N'Ko digits. + */ + NKO ('\u07c0', '\u07c0', '\u0800'), + /** + * The Myanmar range with the Myanmar Shan digits. + */ + MYANMAR_SHAN ('\u1090', '\u1000', '\u10a0'), + /** + * The Limbu range with the Limbu digits. + */ + LIMBU ('\u1946', '\u1900', '\u1950'), + /** + * The New Tai Lue range with the New Tai Lue digits. + */ + NEW_TAI_LUE ('\u19d0', '\u1980', '\u19e0'), + /** + * The Balinese range with the Balinese digits. + */ + BALINESE ('\u1b50', '\u1b00', '\u1b80'), + /** + * The Sundanese range with the Sundanese digits. + */ + SUNDANESE ('\u1bb0', '\u1b80', '\u1bc0'), + /** + * The Lepcha range with the Lepcha digits. + */ + LEPCHA ('\u1c40', '\u1c00', '\u1c50'), + /** + * The Ol Chiki range with the Ol Chiki digits. + */ + OL_CHIKI ('\u1c50', '\u1c50', '\u1c80'), + /** + * The Vai range with the Vai digits. + */ + VAI ('\ua620', '\ua500', '\ua640'), + /** + * The Saurashtra range with the Saurashtra digits. + */ + SAURASHTRA ('\ua8d0', '\ua880', '\ua8e0'), + /** + * The Kayah Li range with the Kayah Li digits. + */ + KAYAH_LI ('\ua900', '\ua900', '\ua930'), + /** + * The Cham range with the Cham digits. + */ + CHAM ('\uaa50', '\uaa00', '\uaa60'); + + private static final Range[] ranges = Range.class.getEnumConstants(); + static { + // sort ranges[] by base for binary search + Arrays.sort(ranges, + new Comparator<Range>() { + public int compare(Range s1, Range s2) { + return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1; + } + }); + } + + private static int toRangeIndex(Range script) { + int index = script.ordinal(); + return index < NUM_KEYS ? index : -1; + } + + private static Range indexToRange(int index) { + return index < NUM_KEYS ? Range.values()[index] : null; + } + + private static int toRangeMask(Set<Range> ranges) { + int m = 0; + for (Range range : ranges) { + int index = range.ordinal(); + if (index < NUM_KEYS) { + m |= 1 << index; + } + } + return m; + } + + private static Set<Range> maskToRangeSet(int mask) { + Set<Range> set = EnumSet.noneOf(Range.class); + Range[] a = Range.values(); + for (int i = 0; i < NUM_KEYS; i++) { + if ((mask & (1 << i)) != 0) { + set.add(a[i]); + } + } + return set; + } + + // base character of range digits + private final int base; + // Unicode range + private final int start, // inclusive + end; // exclusive + + private Range(int base, int start, int end) { + this.base = base - ('0' + getNumericBase()); + this.start = start; + this.end = end; + } + + private int getDigitBase() { + return base; + } + + char getNumericBase() { + return 0; + } + + private boolean inRange(int c) { + return start <= c && c < end; + } + } + /** index of context for contextual shaping - values range from 0 to 18 */ private int key; @@ -79,6 +334,25 @@ */ private int mask; + /** + * The context {@code Range} for contextual shaping or the {@code + * Range} for non-contextual shaping. {@code null} for the bit + * mask-based API. + * + * @since 1.7 + */ + private Range shapingRange; + + /** + * {@code Set<Range>} indicating which Unicode ranges to + * shape. {@code null} for the bit mask-based API. + * + * @since 1.7 + */ + private transient Set<Range> rangeSet; + + private static final long serialVersionUID = -8022764705923730308L; + /** Identifies the Latin-1 (European) and extended range, and * Latin-1 (European) decimal base. */ @@ -105,9 +379,8 @@ /** Identifies the ORIYA range and decimal base. */ public static final int ORIYA = 1<<7; - /** Identifies the TAMIL range and decimal base. Tamil does not have a - * decimal digit 0 so Latin-1 (European) 0 is used. - */ + /** Identifies the TAMIL range and decimal base. */ + // TAMIL DIGIT ZERO was added in Unicode 4.1 public static final int TAMIL = 1<<8; /** Identifies the TELUGU range and decimal base. */ @@ -140,7 +413,12 @@ /** Identifies the MONGOLIAN range and decimal base. */ public static final int MONGOLIAN = 1<<18; - /** Identifies all ranges, for full contextual shaping. */ + /** Identifies all ranges, for full contextual shaping. + * + * <p>This constant specifies all of the bit mask-based + * ranges. Use {@code EmunSet.allOf(NumericShaper.Range.class)} to + * specify all of the enum-based ranges. + */ public static final int ALL_RANGES = 0x0007ffff; private static final int EUROPEAN_KEY = 0; @@ -163,42 +441,20 @@ private static final int KHMER_KEY = 17; private static final int MONGOLIAN_KEY = 18; - private static final int NUM_KEYS = 19; - - private static final String[] keyNames = { - "EUROPEAN", - "ARABIC", - "EASTERN_ARABIC", - "DEVANAGARI", - "BENGALI", - "GURMUKHI", - "GUJARATI", - "ORIYA", - "TAMIL", - "TELUGU", - "KANNADA", - "MALAYALAM", - "THAI", - "LAO", - "TIBETAN", - "MYANMAR", - "ETHIOPIC", - "KHMER", - "MONGOLIAN" - }; + private static final int NUM_KEYS = MONGOLIAN_KEY + 1; // fixed private static final int CONTEXTUAL_MASK = 1<<31; private static final char[] bases = { '\u0030' - '\u0030', // EUROPEAN - '\u0660' - '\u0030', // ARABIC - '\u06f0' - '\u0030', // EASTERN_ARABIC + '\u0660' - '\u0030', // ARABIC-INDIC + '\u06f0' - '\u0030', // EXTENDED ARABIC-INDIC (EASTERN_ARABIC) '\u0966' - '\u0030', // DEVANAGARI '\u09e6' - '\u0030', // BENGALI '\u0a66' - '\u0030', // GURMUKHI '\u0ae6' - '\u0030', // GUJARATI '\u0b66' - '\u0030', // ORIYA - '\u0be7' - '\u0030', // TAMIL - note missing zero + '\u0be6' - '\u0030', // TAMIL - zero was added in Unicode 4.1 '\u0c66' - '\u0030', // TELUGU '\u0ce6' - '\u0030', // KANNADA '\u0d66' - '\u0030', // MALAYALAM @@ -206,7 +462,7 @@ '\u0ed0' - '\u0030', // LAO '\u0f20' - '\u0030', // TIBETAN '\u1040' - '\u0030', // MYANMAR - '\u1369' - '\u0030', // ETHIOPIC + '\u1369' - '\u0031', // ETHIOPIC - no zero '\u17e0' - '\u0030', // KHMER '\u1810' - '\u0030', // MONGOLIAN }; @@ -215,14 +471,14 @@ private static final char[] contexts = { '\u0000', '\u0300', // 'EUROPEAN' (really latin-1 and extended) - '\u0600', '\u0700', // ARABIC - '\u0600', '\u0700', // EASTERN_ARABIC -- note overlap with arabic + '\u0600', '\u0780', // ARABIC + '\u0600', '\u0780', // EASTERN_ARABIC -- note overlap with arabic '\u0900', '\u0980', // DEVANAGARI '\u0980', '\u0a00', // BENGALI '\u0a00', '\u0a80', // GURMUKHI '\u0a80', '\u0b00', // GUJARATI '\u0b00', '\u0b80', // ORIYA - '\u0b80', '\u0c00', // TAMIL - note missing zero + '\u0b80', '\u0c00', // TAMIL '\u0c00', '\u0c80', // TELUGU '\u0c80', '\u0d00', // KANNADA '\u0d00', '\u0d80', // MALAYALAM @@ -230,7 +486,7 @@ '\u0e80', '\u0f00', // LAO '\u0f00', '\u1000', // TIBETAN '\u1000', '\u1080', // MYANMAR - '\u1200', '\u1380', // ETHIOPIC + '\u1200', '\u1380', // ETHIOPIC - note missing zero '\u1780', '\u1800', // KHMER '\u1800', '\u1900', // MONGOLIAN '\uffff', @@ -254,378 +510,290 @@ return (ctCache & 0x1) == 0 ? (ctCache / 2) : EUROPEAN_KEY; } + // cache for the NumericShaper.Range version + private transient volatile Range currentRange = Range.EUROPEAN; + + private Range rangeForCodePoint(int codepoint) { + Range range = currentRange; + if (range.inRange(codepoint)) { + return range; + } + + final Range[] ranges = Range.ranges; + int lo = 0; + int hi = ranges.length - 1; + while (lo <= hi) { + int mid = (lo + hi) / 2; + range = ranges[mid]; + if (codepoint < range.start) { + hi = mid - 1; + } else if (codepoint >= range.end) { + lo = mid + 1; + } else { + currentRange = range; + return range; + } + } + return Range.EUROPEAN; + } + /* * A range table of strong directional characters (types L, R, AL). * Even (left) indexes are starts of ranges of non-strong-directional (or undefined) * characters, odd (right) indexes are starts of ranges of strong directional * characters. */ - private static char[] strongTable = { - '\u0000', '\u0041', - '\u005b', '\u0061', - '\u007b', '\u00aa', - '\u00ab', '\u00b5', - '\u00b6', '\u00ba', - '\u00bb', '\u00c0', - '\u00d7', '\u00d8', - '\u00f7', '\u00f8', - '\u0220', '\u0222', - '\u0234', '\u0250', - '\u02ae', '\u02b0', - '\u02b9', '\u02bb', - '\u02c2', '\u02d0', - '\u02d2', '\u02e0', - '\u02e5', '\u02ee', - '\u02ef', '\u037a', - '\u037b', '\u0386', - '\u0387', '\u0388', - '\u038b', '\u038c', - '\u038d', '\u038e', - '\u03a2', '\u03a3', - '\u03cf', '\u03d0', - '\u03d8', '\u03da', - '\u03f4', '\u0400', - '\u0483', '\u048c', - '\u04c5', '\u04c7', - '\u04c9', '\u04cb', - '\u04cd', '\u04d0', - '\u04f6', '\u04f8', - '\u04fa', '\u0531', - '\u0557', '\u0559', - '\u0560', '\u0561', - '\u0588', '\u0589', - '\u058a', '\u05be', - '\u05bf', '\u05c0', - '\u05c1', '\u05c3', - '\u05c4', '\u05d0', - '\u05eb', '\u05f0', - '\u05f5', '\u061b', - '\u061c', '\u061f', - '\u0620', '\u0621', - '\u063b', '\u0640', - '\u064b', '\u066d', - '\u066e', '\u0671', - '\u06d6', '\u06e5', - '\u06e7', '\u06fa', - '\u06ff', '\u0700', - '\u070e', '\u0710', - '\u0711', '\u0712', - '\u072d', '\u0780', - '\u07a6', '\u0903', - '\u0904', '\u0905', - '\u093a', '\u093d', - '\u0941', '\u0949', - '\u094d', '\u0950', - '\u0951', '\u0958', - '\u0962', '\u0964', - '\u0971', '\u0982', - '\u0984', '\u0985', - '\u098d', '\u098f', - '\u0991', '\u0993', - '\u09a9', '\u09aa', - '\u09b1', '\u09b2', - '\u09b3', '\u09b6', - '\u09ba', '\u09be', - '\u09c1', '\u09c7', - '\u09c9', '\u09cb', - '\u09cd', '\u09d7', - '\u09d8', '\u09dc', - '\u09de', '\u09df', - '\u09e2', '\u09e6', - '\u09f2', '\u09f4', - '\u09fb', '\u0a05', - '\u0a0b', '\u0a0f', - '\u0a11', '\u0a13', - '\u0a29', '\u0a2a', - '\u0a31', '\u0a32', - '\u0a34', '\u0a35', - '\u0a37', '\u0a38', - '\u0a3a', '\u0a3e', - '\u0a41', '\u0a59', - '\u0a5d', '\u0a5e', - '\u0a5f', '\u0a66', - '\u0a70', '\u0a72', - '\u0a75', '\u0a83', - '\u0a84', '\u0a85', - '\u0a8c', '\u0a8d', - '\u0a8e', '\u0a8f', - '\u0a92', '\u0a93', - '\u0aa9', '\u0aaa', - '\u0ab1', '\u0ab2', - '\u0ab4', '\u0ab5', - '\u0aba', '\u0abd', - '\u0ac1', '\u0ac9', - '\u0aca', '\u0acb', - '\u0acd', '\u0ad0', - '\u0ad1', '\u0ae0', - '\u0ae1', '\u0ae6', - '\u0af0', '\u0b02', - '\u0b04', '\u0b05', - '\u0b0d', '\u0b0f', - '\u0b11', '\u0b13', - '\u0b29', '\u0b2a', - '\u0b31', '\u0b32', - '\u0b34', '\u0b36', - '\u0b3a', '\u0b3d', - '\u0b3f', '\u0b40', - '\u0b41', '\u0b47', - '\u0b49', '\u0b4b', - '\u0b4d', '\u0b57', - '\u0b58', '\u0b5c', - '\u0b5e', '\u0b5f', - '\u0b62', '\u0b66', - '\u0b71', '\u0b83', - '\u0b84', '\u0b85', - '\u0b8b', '\u0b8e', - '\u0b91', '\u0b92', - '\u0b96', '\u0b99', - '\u0b9b', '\u0b9c', - '\u0b9d', '\u0b9e', - '\u0ba0', '\u0ba3', - '\u0ba5', '\u0ba8', - '\u0bab', '\u0bae', - '\u0bb6', '\u0bb7', - '\u0bba', '\u0bbe', - '\u0bc0', '\u0bc1', - '\u0bc3', '\u0bc6', - '\u0bc9', '\u0bca', - '\u0bcd', '\u0bd7', - '\u0bd8', '\u0be7', - '\u0bf3', '\u0c01', - '\u0c04', '\u0c05', - '\u0c0d', '\u0c0e', - '\u0c11', '\u0c12', - '\u0c29', '\u0c2a', - '\u0c34', '\u0c35', - '\u0c3a', '\u0c41', - '\u0c45', '\u0c60', - '\u0c62', '\u0c66', - '\u0c70', '\u0c82', - '\u0c84', '\u0c85', - '\u0c8d', '\u0c8e', - '\u0c91', '\u0c92', - '\u0ca9', '\u0caa', - '\u0cb4', '\u0cb5', - '\u0cba', '\u0cbe', - '\u0cbf', '\u0cc0', - '\u0cc5', '\u0cc7', - '\u0cc9', '\u0cca', - '\u0ccc', '\u0cd5', - '\u0cd7', '\u0cde', - '\u0cdf', '\u0ce0', - '\u0ce2', '\u0ce6', - '\u0cf0', '\u0d02', - '\u0d04', '\u0d05', - '\u0d0d', '\u0d0e', - '\u0d11', '\u0d12', - '\u0d29', '\u0d2a', - '\u0d3a', '\u0d3e', - '\u0d41', '\u0d46', - '\u0d49', '\u0d4a', - '\u0d4d', '\u0d57', - '\u0d58', '\u0d60', - '\u0d62', '\u0d66', - '\u0d70', '\u0d82', - '\u0d84', '\u0d85', - '\u0d97', '\u0d9a', - '\u0db2', '\u0db3', - '\u0dbc', '\u0dbd', - '\u0dbe', '\u0dc0', - '\u0dc7', '\u0dcf', - '\u0dd2', '\u0dd8', - '\u0de0', '\u0df2', - '\u0df5', '\u0e01', - '\u0e31', '\u0e32', - '\u0e34', '\u0e40', - '\u0e47', '\u0e4f', - '\u0e5c', '\u0e81', - '\u0e83', '\u0e84', - '\u0e85', '\u0e87', - '\u0e89', '\u0e8a', - '\u0e8b', '\u0e8d', - '\u0e8e', '\u0e94', - '\u0e98', '\u0e99', - '\u0ea0', '\u0ea1', - '\u0ea4', '\u0ea5', - '\u0ea6', '\u0ea7', - '\u0ea8', '\u0eaa', - '\u0eac', '\u0ead', - '\u0eb1', '\u0eb2', - '\u0eb4', '\u0ebd', - '\u0ebe', '\u0ec0', - '\u0ec5', '\u0ec6', - '\u0ec7', '\u0ed0', - '\u0eda', '\u0edc', - '\u0ede', '\u0f00', - '\u0f18', '\u0f1a', - '\u0f35', '\u0f36', - '\u0f37', '\u0f38', - '\u0f39', '\u0f3e', - '\u0f48', '\u0f49', - '\u0f6b', '\u0f7f', - '\u0f80', '\u0f85', - '\u0f86', '\u0f88', - '\u0f8c', '\u0fbe', - '\u0fc6', '\u0fc7', - '\u0fcd', '\u0fcf', - '\u0fd0', '\u1000', - '\u1022', '\u1023', - '\u1028', '\u1029', - '\u102b', '\u102c', - '\u102d', '\u1031', - '\u1032', '\u1038', - '\u1039', '\u1040', - '\u1058', '\u10a0', - '\u10c6', '\u10d0', - '\u10f7', '\u10fb', - '\u10fc', '\u1100', - '\u115a', '\u115f', - '\u11a3', '\u11a8', - '\u11fa', '\u1200', - '\u1207', '\u1208', - '\u1247', '\u1248', - '\u1249', '\u124a', - '\u124e', '\u1250', - '\u1257', '\u1258', - '\u1259', '\u125a', - '\u125e', '\u1260', - '\u1287', '\u1288', - '\u1289', '\u128a', - '\u128e', '\u1290', - '\u12af', '\u12b0', - '\u12b1', '\u12b2', - '\u12b6', '\u12b8', - '\u12bf', '\u12c0', - '\u12c1', '\u12c2', - '\u12c6', '\u12c8', - '\u12cf', '\u12d0', - '\u12d7', '\u12d8', - '\u12ef', '\u12f0', - '\u130f', '\u1310', - '\u1311', '\u1312', - '\u1316', '\u1318', - '\u131f', '\u1320', - '\u1347', '\u1348', - '\u135b', '\u1361', - '\u137d', '\u13a0', - '\u13f5', '\u1401', - '\u1677', '\u1681', - '\u169b', '\u16a0', - '\u16f1', '\u1780', - '\u17b7', '\u17be', - '\u17c6', '\u17c7', - '\u17c9', '\u17d4', - '\u17db', '\u17dc', - '\u17dd', '\u17e0', - '\u17ea', '\u1810', - '\u181a', '\u1820', - '\u1878', '\u1880', - '\u18a9', '\u1e00', - '\u1e9c', '\u1ea0', - '\u1efa', '\u1f00', - '\u1f16', '\u1f18', - '\u1f1e', '\u1f20', - '\u1f46', '\u1f48', - '\u1f4e', '\u1f50', - '\u1f58', '\u1f59', - '\u1f5a', '\u1f5b', - '\u1f5c', '\u1f5d', - '\u1f5e', '\u1f5f', - '\u1f7e', '\u1f80', - '\u1fb5', '\u1fb6', - '\u1fbd', '\u1fbe', - '\u1fbf', '\u1fc2', - '\u1fc5', '\u1fc6', - '\u1fcd', '\u1fd0', - '\u1fd4', '\u1fd6', - '\u1fdc', '\u1fe0', - '\u1fed', '\u1ff2', - '\u1ff5', '\u1ff6', - '\u1ffd', '\u200e', - '\u2010', '\u207f', - '\u2080', '\u2102', - '\u2103', '\u2107', - '\u2108', '\u210a', - '\u2114', '\u2115', - '\u2116', '\u2119', - '\u211e', '\u2124', - '\u2125', '\u2126', - '\u2127', '\u2128', - '\u2129', '\u212a', - '\u212e', '\u212f', - '\u2132', '\u2133', - '\u213a', '\u2160', - '\u2184', '\u2336', - '\u237b', '\u2395', - '\u2396', '\u249c', - '\u24ea', '\u3005', - '\u3008', '\u3021', - '\u302a', '\u3031', - '\u3036', '\u3038', - '\u303b', '\u3041', - '\u3095', '\u309d', - '\u309f', '\u30a1', - '\u30fb', '\u30fc', - '\u30ff', '\u3105', - '\u312d', '\u3131', - '\u318f', '\u3190', - '\u31b8', '\u3200', - '\u321d', '\u3220', - '\u3244', '\u3260', - '\u327c', '\u327f', - '\u32b1', '\u32c0', - '\u32cc', '\u32d0', - '\u32ff', '\u3300', - '\u3377', '\u337b', - '\u33de', '\u33e0', - '\u33ff', '\u3400', - '\u4db6', '\u4e00', - '\u9fa6', '\ua000', - '\ua48d', '\uac00', - '\ud7a4', '\uf900', - '\ufa2e', '\ufb00', - '\ufb07', '\ufb13', - '\ufb18', '\ufb1d', - '\ufb1e', '\ufb1f', - '\ufb29', '\ufb2a', - '\ufb37', '\ufb38', - '\ufb3d', '\ufb3e', - '\ufb3f', '\ufb40', - '\ufb42', '\ufb43', - '\ufb45', '\ufb46', - '\ufbb2', '\ufbd3', - '\ufd3e', '\ufd50', - '\ufd90', '\ufd92', - '\ufdc8', '\ufdf0', - '\ufdfc', '\ufe70', - '\ufe73', '\ufe74', - '\ufe75', '\ufe76', - '\ufefd', '\uff21', - '\uff3b', '\uff41', - '\uff5b', '\uff66', - '\uffbf', '\uffc2', - '\uffc8', '\uffca', - '\uffd0', '\uffd2', - '\uffd8', '\uffda', - '\uffdd', '\uffff' // last entry is sentinel, actually never checked + private static int[] strongTable = { + 0x0000, 0x0041, + 0x005b, 0x0061, + 0x007b, 0x00aa, + 0x00ab, 0x00b5, + 0x00b6, 0x00ba, + 0x00bb, 0x00c0, + 0x00d7, 0x00d8, + 0x00f7, 0x00f8, + 0x02b9, 0x02bb, + 0x02c2, 0x02d0, + 0x02d2, 0x02e0, + 0x02e5, 0x02ee, + 0x02ef, 0x0370, + 0x0374, 0x0376, + 0x037e, 0x0386, + 0x0387, 0x0388, + 0x03f6, 0x03f7, + 0x0483, 0x048a, + 0x058a, 0x05be, + 0x05bf, 0x05c0, + 0x05c1, 0x05c3, + 0x05c4, 0x05c6, + 0x05c7, 0x05d0, + 0x0600, 0x0608, + 0x0609, 0x060b, + 0x060c, 0x060d, + 0x060e, 0x061b, + 0x064b, 0x066d, + 0x0670, 0x0671, + 0x06d6, 0x06e5, + 0x06e7, 0x06ee, + 0x06f0, 0x06fa, + 0x070f, 0x0710, + 0x0711, 0x0712, + 0x0730, 0x074d, + 0x07a6, 0x07b1, + 0x07eb, 0x07f4, + 0x07f6, 0x07fa, + 0x0901, 0x0903, + 0x093c, 0x093d, + 0x0941, 0x0949, + 0x094d, 0x0950, + 0x0951, 0x0958, + 0x0962, 0x0964, + 0x0981, 0x0982, + 0x09bc, 0x09bd, + 0x09c1, 0x09c7, + 0x09cd, 0x09ce, + 0x09e2, 0x09e6, + 0x09f2, 0x09f4, + 0x0a01, 0x0a03, + 0x0a3c, 0x0a3e, + 0x0a41, 0x0a59, + 0x0a70, 0x0a72, + 0x0a75, 0x0a83, + 0x0abc, 0x0abd, + 0x0ac1, 0x0ac9, + 0x0acd, 0x0ad0, + 0x0ae2, 0x0ae6, + 0x0af1, 0x0b02, + 0x0b3c, 0x0b3d, + 0x0b3f, 0x0b40, + 0x0b41, 0x0b47, + 0x0b4d, 0x0b57, + 0x0b62, 0x0b66, + 0x0b82, 0x0b83, + 0x0bc0, 0x0bc1, + 0x0bcd, 0x0bd0, + 0x0bf3, 0x0c01, + 0x0c3e, 0x0c41, + 0x0c46, 0x0c58, + 0x0c62, 0x0c66, + 0x0c78, 0x0c7f, + 0x0cbc, 0x0cbd, + 0x0ccc, 0x0cd5, + 0x0ce2, 0x0ce6, + 0x0cf1, 0x0d02, + 0x0d41, 0x0d46, + 0x0d4d, 0x0d57, + 0x0d62, 0x0d66, + 0x0dca, 0x0dcf, + 0x0dd2, 0x0dd8, + 0x0e31, 0x0e32, + 0x0e34, 0x0e40, + 0x0e47, 0x0e4f, + 0x0eb1, 0x0eb2, + 0x0eb4, 0x0ebd, + 0x0ec8, 0x0ed0, + 0x0f18, 0x0f1a, + 0x0f35, 0x0f36, + 0x0f37, 0x0f38, + 0x0f39, 0x0f3e, + 0x0f71, 0x0f7f, + 0x0f80, 0x0f85, + 0x0f86, 0x0f88, + 0x0f90, 0x0fbe, + 0x0fc6, 0x0fc7, + 0x102d, 0x1031, + 0x1032, 0x1038, + 0x1039, 0x103b, + 0x103d, 0x103f, + 0x1058, 0x105a, + 0x105e, 0x1061, + 0x1071, 0x1075, + 0x1082, 0x1083, + 0x1085, 0x1087, + 0x108d, 0x108e, + 0x135f, 0x1360, + 0x1390, 0x13a0, + 0x1680, 0x1681, + 0x169b, 0x16a0, + 0x1712, 0x1720, + 0x1732, 0x1735, + 0x1752, 0x1760, + 0x1772, 0x1780, + 0x17b7, 0x17be, + 0x17c6, 0x17c7, + 0x17c9, 0x17d4, + 0x17db, 0x17dc, + 0x17dd, 0x17e0, + 0x17f0, 0x1810, + 0x18a9, 0x18aa, + 0x1920, 0x1923, + 0x1927, 0x1929, + 0x1932, 0x1933, + 0x1939, 0x1946, + 0x19de, 0x1a00, + 0x1a17, 0x1a19, + 0x1b00, 0x1b04, + 0x1b34, 0x1b35, + 0x1b36, 0x1b3b, + 0x1b3c, 0x1b3d, + 0x1b42, 0x1b43, + 0x1b6b, 0x1b74, + 0x1b80, 0x1b82, + 0x1ba2, 0x1ba6, + 0x1ba8, 0x1baa, + 0x1c2c, 0x1c34, + 0x1c36, 0x1c3b, + 0x1dc0, 0x1e00, + 0x1fbd, 0x1fbe, + 0x1fbf, 0x1fc2, + 0x1fcd, 0x1fd0, + 0x1fdd, 0x1fe0, + 0x1fed, 0x1ff2, + 0x1ffd, 0x200e, + 0x2010, 0x2071, + 0x2074, 0x207f, + 0x2080, 0x2090, + 0x20a0, 0x2102, + 0x2103, 0x2107, + 0x2108, 0x210a, + 0x2114, 0x2115, + 0x2116, 0x2119, + 0x211e, 0x2124, + 0x2125, 0x2126, + 0x2127, 0x2128, + 0x2129, 0x212a, + 0x212e, 0x212f, + 0x213a, 0x213c, + 0x2140, 0x2145, + 0x214a, 0x214e, + 0x2153, 0x2160, + 0x2190, 0x2336, + 0x237b, 0x2395, + 0x2396, 0x249c, + 0x24ea, 0x26ac, + 0x26ad, 0x2800, + 0x2900, 0x2c00, + 0x2ce5, 0x2d00, + 0x2de0, 0x3005, + 0x3008, 0x3021, + 0x302a, 0x3031, + 0x3036, 0x3038, + 0x303d, 0x3041, + 0x3099, 0x309d, + 0x30a0, 0x30a1, + 0x30fb, 0x30fc, + 0x31c0, 0x31f0, + 0x321d, 0x3220, + 0x3250, 0x3260, + 0x327c, 0x327f, + 0x32b1, 0x32c0, + 0x32cc, 0x32d0, + 0x3377, 0x337b, + 0x33de, 0x33e0, + 0x33ff, 0x3400, + 0x4dc0, 0x4e00, + 0xa490, 0xa500, + 0xa60d, 0xa610, + 0xa66f, 0xa680, + 0xa700, 0xa722, + 0xa788, 0xa789, + 0xa802, 0xa803, + 0xa806, 0xa807, + 0xa80b, 0xa80c, + 0xa825, 0xa827, + 0xa828, 0xa840, + 0xa874, 0xa880, + 0xa8c4, 0xa8ce, + 0xa926, 0xa92e, + 0xa947, 0xa952, + 0xaa29, 0xaa2f, + 0xaa31, 0xaa33, + 0xaa35, 0xaa40, + 0xaa43, 0xaa44, + 0xaa4c, 0xaa4d, + 0xfb1e, 0xfb1f, + 0xfb29, 0xfb2a, + 0xfd3e, 0xfd50, + 0xfdfd, 0xfe70, + 0xfeff, 0xff21, + 0xff3b, 0xff41, + 0xff5b, 0xff66, + 0xffe0, 0x10000, + 0x10101, 0x10102, + 0x10140, 0x101d0, + 0x101fd, 0x10280, + 0x1091f, 0x10920, + 0x10a01, 0x10a10, + 0x10a38, 0x10a40, + 0x1d167, 0x1d16a, + 0x1d173, 0x1d183, + 0x1d185, 0x1d18c, + 0x1d1aa, 0x1d1ae, + 0x1d200, 0x1d360, + 0x1d7ce, 0x20000, + 0xe0001, 0xf0000, + 0x10fffe, 0x10ffff // sentinel }; // use a binary search with a cache - private static int stCache = 0; + private transient volatile int stCache = 0; - // warning, synchronize access to this as it modifies state - private static boolean isStrongDirectional(char c) { - if (c < strongTable[stCache]) { - stCache = search(c, strongTable, 0, stCache); - } else if (c >= strongTable[stCache + 1]) { - stCache = search(c, strongTable, stCache + 1, strongTable.length - stCache - 1); + private boolean isStrongDirectional(char c) { + int cachedIndex = stCache; + if (c < strongTable[cachedIndex]) { + cachedIndex = search(c, strongTable, 0, cachedIndex); + } else if (c >= strongTable[cachedIndex + 1]) { + cachedIndex = search(c, strongTable, cachedIndex + 1, + strongTable.length - cachedIndex - 1); } - return (stCache & 0x1) == 1; + boolean val = (cachedIndex & 0x1) == 1; + stCache = cachedIndex; + return val; } - static private int getKeyFromMask(int mask) { + private static int getKeyFromMask(int mask) { int key = 0; while (key < NUM_KEYS && ((mask & (1<<key)) == 0)) { ++key; @@ -644,12 +812,27 @@ * @return a non-contextual numeric shaper * @throws IllegalArgumentException if the range is not a single range */ - static public NumericShaper getShaper(int singleRange) { + public static NumericShaper getShaper(int singleRange) { int key = getKeyFromMask(singleRange); return new NumericShaper(key, singleRange); } /** + * Returns a shaper for the provided Unicode + * range. All Latin-1 (EUROPEAN) digits are converted to the + * corresponding decimal digits of the specified Unicode range. + * + * @param singleRange the Unicode range given by a {@link + * NumericShaper.Range} constant. + * @return a non-contextual {@code NumericShaper}. + * @throws NullPointerException if {@code singleRange} is {@code null} + * @since 1.7 + */ + public static NumericShaper getShaper(Range singleRange) { + return new NumericShaper(singleRange, EnumSet.of(singleRange)); + } + + /** * Returns a contextual shaper for the provided unicode range(s). * Latin-1 (EUROPEAN) digits are converted to the decimal digits * corresponding to the range of the preceding text, if the @@ -663,12 +846,34 @@ * @param ranges the specified Unicode ranges * @return a shaper for the specified ranges */ - static public NumericShaper getContextualShaper(int ranges) { + public static NumericShaper getContextualShaper(int ranges) { ranges |= CONTEXTUAL_MASK; return new NumericShaper(EUROPEAN_KEY, ranges); } /** + * Returns a contextual shaper for the provided Unicode + * range(s). The Latin-1 (EUROPEAN) digits are converted to the + * decimal digits corresponding to the range of the preceding + * text, if the range is one of the provided ranges. + * + * <p>The shaper assumes EUROPEAN as the starting context, that + * is, if EUROPEAN digits are encountered before any strong + * directional text in the string, the context is presumed to be + * EUROPEAN, and so the digits will not shape. + * + * @param ranges the specified Unicode ranges + * @return a contextual shaper for the specified ranges + * @throws NullPointerException if {@code ranges} is {@code null}. + * @since 1.7 + */ + public static NumericShaper getContextualShaper(Set<Range> ranges) { + NumericShaper shaper = new NumericShaper(Range.EUROPEAN, ranges); + shaper.mask = CONTEXTUAL_MASK; + return shaper; + } + + /** * Returns a contextual shaper for the provided unicode range(s). * Latin-1 (EUROPEAN) digits will be converted to the decimal digits * corresponding to the range of the preceding text, if the @@ -683,13 +888,38 @@ * @throws IllegalArgumentException if the specified * <code>defaultContext</code> is not a single valid range. */ - static public NumericShaper getContextualShaper(int ranges, int defaultContext) { + public static NumericShaper getContextualShaper(int ranges, int defaultContext) { int key = getKeyFromMask(defaultContext); ranges |= CONTEXTUAL_MASK; return new NumericShaper(key, ranges); } /** + * Returns a contextual shaper for the provided Unicode range(s). + * The Latin-1 (EUROPEAN) digits will be converted to the decimal + * digits corresponding to the range of the preceding text, if the + * range is one of the provided ranges. The shaper uses {@code + * defaultContext} as the starting context. + * + * @param ranges the specified Unicode ranges + * @param defaultContext the starting context, such as + * {@code NumericShaper.Range.EUROPEAN} + * @return a contextual shaper for the specified Unicode ranges. + * @throws NullPointerException + * if {@code ranges} or {@code defaultContext} is {@code null} + * @since 1.7 + */ + public static NumericShaper getContextualShaper(Set<Range> ranges, + Range defaultContext) { + if (defaultContext == null) { + throw new NullPointerException(); + } + NumericShaper shaper = new NumericShaper(defaultContext, ranges); + shaper.mask = CONTEXTUAL_MASK; + return shaper; + } + + /** * Private constructor. */ private NumericShaper(int key, int mask) { @@ -697,6 +927,11 @@ this.mask = mask; } + private NumericShaper(Range defaultContext, Set<Range> ranges) { + this.shapingRange = defaultContext; + this.rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null. + } + /** * Converts the digits in the text that occur between start and * start + count. @@ -710,19 +945,13 @@ * @throws NullPointerException if text is null */ public void shape(char[] text, int start, int count) { - if (text == null) { - throw new NullPointerException("text is null"); - } - if ((start < 0) - || (start > text.length) - || ((start + count) < 0) - || ((start + count) > text.length)) { - throw new IndexOutOfBoundsException( - "bad start or count for text of length " + text.length); - } - + checkParams(text, start, count); if (isContextual()) { - shapeContextually(text, start, count, key); + if (rangeSet == null) { + shapeContextually(text, start, count, key); + } else { + shapeContextually(text, start, count, shapingRange); + } } else { shapeNonContextually(text, start, count); } @@ -747,6 +976,60 @@ * range. */ public void shape(char[] text, int start, int count, int context) { + checkParams(text, start, count); + if (isContextual()) { + int ctxKey = getKeyFromMask(context); + if (rangeSet == null) { + shapeContextually(text, start, count, ctxKey); + } else { + shapeContextually(text, start, count, Range.values()[ctxKey]); + } + } else { + shapeNonContextually(text, start, count); + } + } + + /** + * Converts the digits in the text that occur between {@code + * start} and {@code start + count}, using the provided {@code + * context}. {@code Context} is ignored if the shaper is not a + * contextual shaper. + * + * @param text a {@code char} array + * @param start the index into {@code text} to start converting + * @param count the number of {@code char}s in {@code text} + * to convert + * @param context the context to which to convert the characters, + * such as {@code NumericShaper.Range.EUROPEAN} + * @throws IndexOutOfBoundsException + * if {@code start} or {@code start + count} is out of bounds + * @throws NullPointerException + * if {@code text} or {@code context} is null + * @since 1.7 + */ + public void shape(char[] text, int start, int count, Range context) { + checkParams(text, start, count); + if (context == null) { + throw new NullPointerException("context is null"); + } + + if (isContextual()) { + if (rangeSet != null) { + shapeContextually(text, start, count, context); + } else { + int key = Range.toRangeIndex(context); + if (key >= 0) { + shapeContextually(text, start, count, key); + } else { + shapeContextually(text, start, count, shapingRange); + } + } + } else { + shapeNonContextually(text, start, count); + } + } + + private void checkParams(char[] text, int start, int count) { if (text == null) { throw new NullPointerException("text is null"); } @@ -757,13 +1040,6 @@ throw new IndexOutOfBoundsException( "bad start or count for text of length " + text.length); } - - if (isContextual()) { - int ctxKey = getKeyFromMask(context); - shapeContextually(text, start, count, ctxKey); - } else { - shapeNonContextually(text, start, count); - } } /** @@ -785,6 +1061,10 @@ * <blockquote> * <code>if ((shaper.getRanges() & shaper.ARABIC) != 0) { ... </code> * </blockquote> + * + * <p>Note that this method supports only the bit mask-based + * ranges. Call {@link #getRangeSet()} for the enum-based ranges. + * * @return the values for all the ranges to be shaped. */ public int getRanges() { @@ -792,11 +1072,34 @@ } /** + * Returns a {@code Set} representing all the Unicode ranges in + * this {@code NumericShaper} that will be shaped. + * + * @return all the Unicode ranges to be shaped. + * @since 1.7 + */ + public Set<Range> getRangeSet() { + if (rangeSet != null) { + return EnumSet.copyOf(rangeSet); + } + return Range.maskToRangeSet(mask); + } + + /** * Perform non-contextual shaping. */ private void shapeNonContextually(char[] text, int start, int count) { - int base = bases[key]; - char minDigit = key == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero + int base; + char minDigit = '0'; + if (shapingRange != null) { + base = shapingRange.getDigitBase(); + minDigit += shapingRange.getNumericBase(); + } else { + base = bases[key]; + if (key == ETHIOPIC_KEY) { + minDigit++; // Ethiopic doesn't use decimal zero + } + } for (int i = start, e = start + count; i < e; ++i) { char c = text[i]; if (c >= minDigit && c <= '\u0039') { @@ -807,7 +1110,7 @@ /** * Perform contextual shaping. - * Synchronized to protect caches used in getContextKey and isStrongDirectional. + * Synchronized to protect caches used in getContextKey. */ private synchronized void shapeContextually(char[] text, int start, int count, int ctxKey) { @@ -818,29 +1121,64 @@ int lastkey = ctxKey; int base = bases[ctxKey]; - char minDigit = ctxKey == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero + char minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero + + synchronized (NumericShaper.class) { + for (int i = start, e = start + count; i < e; ++i) { + char c = text[i]; + if (c >= minDigit && c <= '\u0039') { + text[i] = (char)(c + base); + } + + if (isStrongDirectional(c)) { + int newkey = getContextKey(c); + if (newkey != lastkey) { + lastkey = newkey; - for (int i = start, e = start + count; i < e; ++i) { + ctxKey = newkey; + if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) { + ctxKey = EASTERN_ARABIC_KEY; + } else if ((mask & (1<<ctxKey)) == 0) { + ctxKey = EUROPEAN_KEY; + } + + base = bases[ctxKey]; + + minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero + } + } + } + } + } + + private void shapeContextually(char[] text, int start, int count, Range ctxKey) { + if (ctxKey == null) { + ctxKey = Range.EUROPEAN; + } + + Range lastKey = ctxKey; + int base = ctxKey.getDigitBase(); + char minDigit = (char)('0' + ctxKey.getNumericBase()); + for (int i = start, end = start + count; i < end; ++i) { char c = text[i]; - if (c >= minDigit && c <= '\u0039') { + if (c >= minDigit && c <= '9') { text[i] = (char)(c + base); + continue; } - if (isStrongDirectional(c)) { - int newkey = getContextKey(c); - if (newkey != lastkey) { - lastkey = newkey; - - ctxKey = newkey; - if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) { - ctxKey = EASTERN_ARABIC_KEY; - } else if ((mask & (1<<ctxKey)) == 0) { - ctxKey = EUROPEAN_KEY; + Range newKey = rangeForCodePoint(c); + if (newKey != lastKey) { + lastKey = newKey; + ctxKey = newKey; + if (rangeSet.contains(Range.EUROPEAN) + && (ctxKey == Range.ARABIC || ctxKey == Range.EASTERN_ARABIC)) { + ctxKey = Range.EASTERN_ARABIC; + } else if (!rangeSet.contains(ctxKey)) { + ctxKey = Range.EUROPEAN; } - base = bases[ctxKey]; - - minDigit = ctxKey == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero + base = ctxKey.getDigitBase(); + minDigit = (char)('0' + ctxKey.getNumericBase()); } } } @@ -852,12 +1190,28 @@ * @see java.lang.Object#hashCode */ public int hashCode() { - return mask; + int hash = mask; + if (rangeSet != null) { + // Use the CONTEXTUAL_MASK bit only for the enum-based + // NumericShaper. A deserialized NumericShaper might have + // bit masks. + hash &= CONTEXTUAL_MASK; + hash ^= rangeSet.hashCode(); + } + return hash; } /** - * Returns true if the specified object is an instance of - * <code>NumericShaper</code> and shapes identically to this one. + * Returns {@code true} if the specified object is an instance of + * <code>NumericShaper</code> and shapes identically to this one, + * regardless of the range representations, the bit mask or the + * enum. For example, the following code produces {@code "true"}. + * <blockquote><pre> + * NumericShaper ns1 = NumericShaper.getShaper(NumericShaper.ARABIC); + * NumericShaper ns2 = NumericShaper.getShaper(NumericShaper.Range.ARABIC); + * System.out.println(ns1.equals(ns2)); + * </pre></blockquote> + * * @param o the specified object to compare to this * <code>NumericShaper</code> * @return <code>true</code> if <code>o</code> is an instance @@ -869,6 +1223,22 @@ if (o != null) { try { NumericShaper rhs = (NumericShaper)o; + if (rangeSet != null) { + if (rhs.rangeSet != null) { + return isContextual() == rhs.isContextual() + && rangeSet.equals(rhs.rangeSet) + && shapingRange == rhs.shapingRange; + } + return isContextual() == rhs.isContextual() + && rangeSet.equals(Range.maskToRangeSet(rhs.mask)) + && shapingRange == Range.indexToRange(rhs.key); + } else if (rhs.rangeSet != null) { + Set<Range> rset = Range.maskToRangeSet(mask); + Range srange = Range.indexToRange(key); + return isContextual() == rhs.isContextual() + && rset.equals(rhs.rangeSet) + && srange == rhs.shapingRange; + } return rhs.mask == mask && rhs.key == key; } catch (ClassCastException e) { @@ -885,23 +1255,29 @@ public String toString() { StringBuilder buf = new StringBuilder(super.toString()); - buf.append("[contextual:" + isContextual()); + buf.append("[contextual:").append(isContextual()); + String[] keyNames = null; if (isContextual()) { - buf.append(", context:" + keyNames[key]); + buf.append(", context:"); + buf.append(shapingRange == null ? Range.values()[key] : shapingRange); } - buf.append(", range(s): "); - boolean first = true; - for (int i = 0; i < NUM_KEYS; ++i) { - if ((mask & (1 << i)) != 0) { - if (first) { - first = false; - } else { - buf.append(", "); + if (rangeSet == null) { + buf.append(", range(s): "); + boolean first = true; + for (int i = 0; i < NUM_KEYS; ++i) { + if ((mask & (1 << i)) != 0) { + if (first) { + first = false; + } else { + buf.append(", "); + } + buf.append(Range.values()[i]); } - buf.append(keyNames[i]); } + } else { + buf.append(", range set: ").append(rangeSet); } buf.append(']'); @@ -940,7 +1316,6 @@ } if (value >= 1 << 1) { - value >>= 1; bit += 1; } @@ -950,7 +1325,7 @@ /** * fast binary search over subrange of array. */ - private static int search(char value, char[] array, int start, int length) + private static int search(int value, int[] array, int start, int length) { int power = 1 << getHighBit(length); int extra = length - power; @@ -971,4 +1346,27 @@ return index; } + + /** + * Converts the {@code NumericShaper.Range} enum-based parameters, + * if any, to the bit mask-based counterparts and writes this + * object to the {@code stream}. Any enum constants that have no + * bit mask-based counterparts are ignored in the conversion. + * + * @param stream the output stream to write to + * @throws IOException if an I/O error occurs while writing to {@code stream} + * @since 1.7 + */ + private void writeObject(ObjectOutputStream stream) throws IOException { + if (shapingRange != null) { + int index = Range.toRangeIndex(shapingRange); + if (index >= 0) { + key = index; + } + } + if (rangeSet != null) { + mask |= Range.toRangeMask(rangeSet); + } + stream.defaultWriteObject(); + } }
--- a/jdk/src/share/classes/javax/swing/JEditorPane.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/JEditorPane.java Wed Nov 18 18:56:59 2009 -0800 @@ -1330,7 +1330,7 @@ */ public Dimension getPreferredSize() { Dimension d = super.getPreferredSize(); - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { TextUI ui = getUI(); int prefWidth = d.width; @@ -1452,7 +1452,7 @@ * match its own, false otherwise */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { TextUI ui = getUI(); int w = port.getWidth(); @@ -1474,7 +1474,7 @@ * false otherwise */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { TextUI ui = getUI(); int h = port.getHeight();
--- a/jdk/src/share/classes/javax/swing/JList.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/JList.java Wed Nov 18 18:56:59 2009 -0800 @@ -2722,7 +2722,7 @@ getVisibleRowCount() <= 0) { return true; } - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return port.getWidth() > getPreferredSize().width; } @@ -2748,7 +2748,7 @@ getVisibleRowCount() <= 0) { return true; } - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return port.getHeight() > getPreferredSize().height; }
--- a/jdk/src/share/classes/javax/swing/JTable.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/JTable.java Wed Nov 18 18:56:59 2009 -0800 @@ -57,6 +57,7 @@ import sun.swing.SwingUtilities2.Section; import static sun.swing.SwingUtilities2.Section.*; import sun.swing.PrintingStatus; +import sun.swing.SwingLazyValue; /** * The <code>JTable</code> is used to display and edit regular two-dimensional tables @@ -718,7 +719,7 @@ * @see #addNotify */ protected void configureEnclosingScrollPane() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { Container gp = port.getParent(); if (gp instanceof JScrollPane) { @@ -727,7 +728,8 @@ // example, the rowHeaderView of the scrollPane - // an implementor of fixed columns might do this. JViewport viewport = scrollPane.getViewport(); - if (viewport == null || viewport.getView() != this) { + if (viewport == null || + SwingUtilities.getUnwrappedView(viewport) != this) { return; } scrollPane.setColumnHeaderView(getTableHeader()); @@ -750,7 +752,7 @@ * from configureEnclosingScrollPane() and updateUI() in a safe manor. */ private void configureEnclosingScrollPaneUI() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { Container gp = port.getParent(); if (gp instanceof JScrollPane) { @@ -759,7 +761,8 @@ // example, the rowHeaderView of the scrollPane - // an implementor of fixed columns might do this. JViewport viewport = scrollPane.getViewport(); - if (viewport == null || viewport.getView() != this) { + if (viewport == null || + SwingUtilities.getUnwrappedView(viewport) != this) { return; } // scrollPane.getViewport().setBackingStoreEnabled(true); @@ -819,7 +822,7 @@ * @since 1.3 */ protected void unconfigureEnclosingScrollPane() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { Container gp = port.getParent(); if (gp instanceof JScrollPane) { @@ -828,7 +831,8 @@ // example, the rowHeaderView of the scrollPane - // an implementor of fixed columns might do this. JViewport viewport = scrollPane.getViewport(); - if (viewport == null || viewport.getView() != this) { + if (viewport == null || + SwingUtilities.getUnwrappedView(viewport) != this) { return; } scrollPane.setColumnHeaderView(null); @@ -5215,7 +5219,7 @@ * @see #getFillsViewportHeight */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); return getFillsViewportHeight() && port != null && port.getHeight() > getPreferredSize().height; @@ -5316,7 +5320,7 @@ } private void setLazyValue(Hashtable h, Class c, String s) { - h.put(c, new UIDefaults.ProxyLazyValue(s)); + h.put(c, new SwingLazyValue(s)); } private void setLazyRenderer(Class c, String s) {
--- a/jdk/src/share/classes/javax/swing/JTextField.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/JTextField.java Wed Nov 18 18:56:59 2009 -0800 @@ -292,7 +292,7 @@ */ @Override public boolean isValidateRoot() { - return SwingUtilities2.getViewport(this) == null; + return SwingUtilities.getParentViewport(this) == null; }
--- a/jdk/src/share/classes/javax/swing/JTree.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/JTree.java Wed Nov 18 18:56:59 2009 -0800 @@ -3498,7 +3498,7 @@ * @see Scrollable#getScrollableTracksViewportWidth */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return port.getWidth() > getPreferredSize().width; } @@ -3515,7 +3515,7 @@ * @see Scrollable#getScrollableTracksViewportHeight */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return port.getHeight() > getPreferredSize().height; }
--- a/jdk/src/share/classes/javax/swing/SwingUtilities.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/SwingUtilities.java Wed Nov 18 18:56:59 2009 -0800 @@ -1969,6 +1969,66 @@ } /** + * Looks for the first ancestor of the {@code component} + * which is not an instance of {@link JLayer}. + * If this ancestor is an instance of {@code JViewport}, + * this {@code JViewport} is returned, otherwise returns {@code null}. + * The following way of obtaining the parent {@code JViewport} + * is not recommended any more: + * <pre> + * JViewport port = null; + * Container parent = component.getParent(); + * // not recommended any more + * if(parent instanceof JViewport) { + * port = (JViewport) parent; + * } + * </pre> + * Here is the way to go: + * <pre> + * // the correct way: + * JViewport port = SwingUtilities.getParentViewport(component); + * </pre> + * @param component {@code Component} to get the parent {@code JViewport} of. + * @return the {@code JViewport} instance for the {@code component} + * or {@code null} + * @throws NullPointerException if {@code component} is {@code null} + * + * @since 1.7 + */ + public static JViewport getParentViewport(Component component) { + do { + component = component.getParent(); + if (component instanceof JViewport) { + return (JViewport) component; + } + } while(component instanceof JLayer); + return null; + } + + /** + * Returns the first {@code JViewport}'s descendant + * which is not an instance of {@code JLayer} or {@code null}. + * + * If the {@code viewport}'s view component is not a {@code JLayer}, + * this method is equal to {@link JViewport#getView()} + * otherwise {@link JLayer#getView()} will be recursively tested + * + * @return the first {@code JViewport}'s descendant + * which is not an instance of {@code JLayer} or {@code null}. + * + * @throws NullPointerException if {@code viewport} is {@code null} + * @see JViewport#getView() + * @see JLayer + */ + static Component getUnwrappedView(JViewport viewport) { + Component view = viewport.getView(); + while (view instanceof JLayer) { + view = ((JLayer)view).getView(); + } + return view; + } + + /** * Retrieves the validate root of a given container. * * If the container is contained within a {@code CellRendererPane}, this
--- a/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java Wed Nov 18 18:56:59 2009 -0800 @@ -33,7 +33,8 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.text.MessageFormat; -import java.util.Vector; +import java.util.List; +import java.util.ArrayList; import java.lang.ref.WeakReference; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; @@ -173,22 +174,27 @@ * @since 1.4 */ public String getSystemDisplayName(File f) { - String name = null; - if (f != null) { - name = f.getName(); - if (!name.equals("..") && !name.equals(".") && - (useSystemExtensionHiding || - !isFileSystem(f) || - isFileSystemRoot(f)) && - ((f instanceof ShellFolder) || - f.exists())) { + if (f == null) { + return null; + } + + String name = f.getName(); + if (!name.equals("..") && !name.equals(".") && + (useSystemExtensionHiding || !isFileSystem(f) || isFileSystemRoot(f)) && + (f instanceof ShellFolder || f.exists())) { + + try { name = getShellFolder(f).getDisplayName(); - if (name == null || name.length() == 0) { - name = f.getPath(); // e.g. "/" - } + } catch (FileNotFoundException e) { + return null; + } + + if (name == null || name.length() == 0) { + name = f.getPath(); // e.g. "/" } } + return name; } @@ -222,16 +228,24 @@ * @since 1.4 */ public Icon getSystemIcon(File f) { - if (f != null) { - ShellFolder sf = getShellFolder(f); - Image img = sf.getIcon(false); - if (img != null) { - return new ImageIcon(img, sf.getFolderType()); - } else { - return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon"); - } + if (f == null) { + return null; + } + + ShellFolder sf; + + try { + sf = getShellFolder(f); + } catch (FileNotFoundException e) { + return null; + } + + Image img = sf.getIcon(false); + + if (img != null) { + return new ImageIcon(img, sf.getFolderType()); } else { - return null; + return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon"); } } @@ -446,24 +460,28 @@ * Gets the list of shown (i.e. not hidden) files. */ public File[] getFiles(File dir, boolean useFileHiding) { - Vector<File> files = new Vector<File>(); - + List<File> files = new ArrayList<File>(); // add all files in dir - File[] names; - if (!(dir instanceof ShellFolder)) { + if (!(dir instanceof ShellFolder)) { + try { dir = getShellFolder(dir); + } catch (FileNotFoundException e) { + return new File[0]; } + } - names = ((ShellFolder)dir).listFiles(!useFileHiding); - File f; + File[] names = ((ShellFolder) dir).listFiles(!useFileHiding); - int nameCount = (names == null) ? 0 : names.length; - for (int i = 0; i < nameCount; i++) { + if (names == null) { + return new File[0]; + } + + for (File f : names) { if (Thread.currentThread().isInterrupted()) { break; } - f = names[i]; + if (!(f instanceof ShellFolder)) { if (isFileSystemRoot(f)) { f = createFileSystemRoot(f); @@ -481,7 +499,7 @@ } } if (!useFileHiding || !isHiddenFile(f)) { - files.addElement(f); + files.add(f); } } @@ -497,42 +515,50 @@ * <code>null</code> if <code>dir</code> is <code>null</code> */ public File getParentDirectory(File dir) { - if (dir != null && dir.exists()) { - ShellFolder sf = getShellFolder(dir); - File psf = sf.getParentFile(); - if (psf != null) { - if (isFileSystem(psf)) { - File f = psf; - if (f != null && !f.exists()) { - // This could be a node under "Network Neighborhood". - File ppsf = psf.getParentFile(); - if (ppsf == null || !isFileSystem(ppsf)) { - // We're mostly after the exists() override for windows below. - f = createFileSystemRoot(f); - } - } - return f; - } else { - return psf; + if (dir == null || !dir.exists()) { + return null; + } + + ShellFolder sf; + + try { + sf = getShellFolder(dir); + } catch (FileNotFoundException e) { + return null; + } + + File psf = sf.getParentFile(); + + if (psf == null) { + return null; + } + + if (isFileSystem(psf)) { + File f = psf; + if (!f.exists()) { + // This could be a node under "Network Neighborhood". + File ppsf = psf.getParentFile(); + if (ppsf == null || !isFileSystem(ppsf)) { + // We're mostly after the exists() override for windows below. + f = createFileSystemRoot(f); } } + return f; + } else { + return psf; } - return null; } - ShellFolder getShellFolder(File f) { - if (!(f instanceof ShellFolder) - && !(f instanceof FileSystemRoot) - && isFileSystemRoot(f)) { - + /** + * Throws {@code FileNotFoundException} if file not found or current thread was interrupted + */ + ShellFolder getShellFolder(File f) throws FileNotFoundException { + if (!(f instanceof ShellFolder) && !(f instanceof FileSystemRoot) && isFileSystemRoot(f)) { f = createFileSystemRoot(f); } + try { return ShellFolder.getShellFolder(f); - } catch (FileNotFoundException e) { - System.err.println("FileSystemView.getShellFolder: f="+f); - e.printStackTrace(); - return null; } catch (InternalError e) { System.err.println("FileSystemView.getShellFolder: f="+f); e.printStackTrace(); @@ -596,9 +622,9 @@ // Unix - using OpenWindows' default folder name. Can't find one for Motif/CDE. newFolder = createFileObject(containingDir, newFolderString); int i = 1; - while (newFolder.exists() && (i < 100)) { + while (newFolder.exists() && i < 100) { newFolder = createFileObject(containingDir, MessageFormat.format( - newFolderNextString, new Object[] { new Integer(i) })); + newFolderNextString, new Integer(i))); i++; } @@ -612,7 +638,7 @@ } public boolean isFileSystemRoot(File dir) { - return (dir != null && dir.getAbsolutePath().equals("/")); + return dir != null && dir.getAbsolutePath().equals("/"); } public boolean isDrive(File dir) { @@ -654,7 +680,7 @@ public File getChild(File parent, String fileName) { if (fileName.startsWith("\\") - && !(fileName.startsWith("\\\\")) + && !fileName.startsWith("\\\\") && isFileSystem(parent)) { //Path is relative to the root of parent's drive @@ -677,9 +703,13 @@ * The Windows implementation gets information from the ShellFolder class. */ public String getSystemTypeDescription(File f) { - if (f != null) { + if (f == null) { + return null; + } + + try { return getShellFolder(f).getFolderType(); - } else { + } catch (FileNotFoundException e) { return null; } } @@ -701,9 +731,9 @@ // Using NT's default folder name File newFolder = createFileObject(containingDir, newFolderString); int i = 2; - while (newFolder.exists() && (i < 100)) { + while (newFolder.exists() && i < 100) { newFolder = createFileObject(containingDir, MessageFormat.format( - newFolderNextString, new Object[] { new Integer(i) })); + newFolderNextString, new Integer(i))); i++; } @@ -727,7 +757,7 @@ } }); - return (path != null && (path.equals("A:\\") || path.equals("B:\\"))); + return path != null && (path.equals("A:\\") || path.equals("B:\\")); } /**
--- a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java Wed Nov 18 18:56:59 2009 -0800 @@ -71,33 +71,410 @@ * Subclasses should override this method and use * the specified {@code Graphics} object to * render the content of the component. + * <p/> + * If {@code g} is not an instance of {@code Graphics2D}, + * this method is no-op. * * @param g the {@code Graphics} context in which to paint; * @param c the component being painted; - * it can be safely cast to the {@code JLayer<V>} + * it can be safely cast to {@code JLayer<? extends V>} + * + * @see #configureGraphics(Graphics2D, JLayer) + * @see #paintLayer(Graphics2D, JLayer) */ - @Override public void paint(Graphics g, JComponent c) { - c.paint(g); + if (g instanceof Graphics2D) { + Graphics2D g2 = (Graphics2D) g.create(); + JLayer<? extends V> l = (JLayer<? extends V>) c; + configureGraphics(g2, l); + paintLayer(g2, l); + g2.dispose(); + } + } + + /** + * This method is called by the {@link #paint} method prior to + * {@link #paintLayer} to configure the {@code Graphics2D} object. + * The default implementation is empty. + * + * @param g2 the {@code Graphics2D} object to configure + * @param l the {@code JLayer} being painted + * + * @see #paintLayer(Graphics2D, JLayer) + */ + protected void configureGraphics(Graphics2D g2, JLayer<? extends V> l) { + } + + /** + * Called by the {@link #paint} method, + * subclasses should override this method + * to perform any custom painting operations. + * <p/> + * The default implementation paints the passed {@code JLayer} as is. + * + * @param g2 the {@code Graphics2D} context in which to paint + * @param l the {@code JLayer} being painted + * + * @see #configureGraphics(Graphics2D, JLayer) + */ + protected void paintLayer(Graphics2D g2, JLayer<? extends V> l) { + l.paint(g2); } /** * Dispatches {@code AWTEvent}s for {@code JLayer} - * and <b>all it subcomponents</b> to this {@code LayerUI} instance. - * <p> - * To enable the {@code AWTEvent} of the particular type, - * you call {@link javax.swing.JLayer#setLayerEventMask} + * and <b>all its subcomponents</b> to this {@code LayerUI} instance. + * <p/> + * To enable the {@code AWTEvent}s of a particular type, + * you call {@link JLayer#setLayerEventMask} * in {@link #installUI(javax.swing.JComponent)} * and set the layer event mask to {@code 0} - * in {@link #uninstallUI(javax.swing.JComponent)} after that + * in {@link #uninstallUI(javax.swing.JComponent)} after that. + * By default this method calls the appropriate + * {@code process<event type>Event} + * method for the given class of event. * * @param e the event to be dispatched * @param l the layer this LayerUI is set to * * @see JLayer#setLayerEventMask(long) - * @see javax.swing.JLayer#getLayerEventMask() + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + * @see #processComponentEvent + * @see #processFocusEvent + * @see #processKeyEvent + * @see #processMouseEvent + * @see #processMouseMotionEvent + * @see #processInputMethodEvent + * @see #processHierarchyEvent + * @see #processMouseWheelEvent */ public void eventDispatched(AWTEvent e, JLayer<? extends V> l){ + if (e instanceof FocusEvent) { + processFocusEvent((FocusEvent)e, l); + + } else if (e instanceof MouseEvent) { + switch(e.getID()) { + case MouseEvent.MOUSE_PRESSED: + case MouseEvent.MOUSE_RELEASED: + case MouseEvent.MOUSE_CLICKED: + case MouseEvent.MOUSE_ENTERED: + case MouseEvent.MOUSE_EXITED: + processMouseEvent((MouseEvent)e, l); + break; + case MouseEvent.MOUSE_MOVED: + case MouseEvent.MOUSE_DRAGGED: + processMouseMotionEvent((MouseEvent)e, l); + break; + case MouseEvent.MOUSE_WHEEL: + processMouseWheelEvent((MouseWheelEvent)e, l); + break; + } + } else if (e instanceof KeyEvent) { + processKeyEvent((KeyEvent)e, l); + } else if (e instanceof ComponentEvent) { + processComponentEvent((ComponentEvent)e, l); + } else if (e instanceof InputMethodEvent) { + processInputMethodEvent((InputMethodEvent)e, l); + } else if (e instanceof HierarchyEvent) { + switch (e.getID()) { + case HierarchyEvent.HIERARCHY_CHANGED: + processHierarchyEvent((HierarchyEvent)e, l); + break; + case HierarchyEvent.ANCESTOR_MOVED: + case HierarchyEvent.ANCESTOR_RESIZED: + processHierarchyBoundsEvent((HierarchyEvent)e, l); + break; + } + } + } + + /** + * Processes component events occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless component events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Component events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.COMPONENT_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code ComponentEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processComponentEvent(ComponentEvent e, JLayer<? extends V> l) { + } + + /** + * Processes focus events occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless focus events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Focus events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.FOCUS_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code FocusEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processFocusEvent(FocusEvent e, JLayer<? extends V> l) { + } + + /** + * Processes key events occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless key events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Key events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.KEY_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code KeyEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processKeyEvent(KeyEvent e, JLayer<? extends V> l) { + } + + /** + * Processes mouse events occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless mouse events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Mouse events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code MouseEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processMouseEvent(MouseEvent e, JLayer<? extends V> l) { + } + + /** + * Processes mouse motion event occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless mouse motion events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Mouse motion events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code MouseEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends V> l) { + } + + /** + * Processes mouse wheel event occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless mouse wheel events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Mouse wheel events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code MouseEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processMouseWheelEvent(MouseWheelEvent e, JLayer<? extends V> l) { + } + + /** + * Processes input event occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless input events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Input events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.INPUT_METHOD_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code InputMethodEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processInputMethodEvent(InputMethodEvent e, JLayer<? extends V> l) { + } + + /** + * Processes hierarchy event occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless hierarchy events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Hierarchy events are enabled in the overridden {@link #installUI} method + * and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.HIERARCHY_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code HierarchyEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processHierarchyEvent(HierarchyEvent e, JLayer<? extends V> l) { + } + + /** + * Processes hierarchy bounds event occurring on the {@link JLayer} + * or any of its subcomponents. + * <p/> + * This method is not called unless hierarchy bounds events are + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to. + * Hierarchy bounds events are enabled in the overridden {@link #installUI} + * method and should be disabled in the {@link #uninstallUI} method after that. + * <pre> + * public void installUI(JComponent c) { + * super.installUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK); + * } + * + * public void unistallUI(JComponent c) { + * super.uninstallUI(c); + * JLayer l = (JLayer) c; + * l.setLayerEventMask(0); + * } + * </pre> + * + * @param e the {@code HierarchyEvent} to be processed + * @param l the layer this {@code LayerUI} instance is set to + * + * @see JLayer#setLayerEventMask(long) + * @see #installUI(javax.swing.JComponent) + * @see #uninstallUI(javax.swing.JComponent) + */ + protected void processHierarchyBoundsEvent(HierarchyEvent e, JLayer<? extends V> l) { } /** @@ -251,13 +628,28 @@ } /** + * Repaints all {@code JLayer} instances this {@code LayerUI} is set to. + * Call this method when the state of this {@code LayerUI} is changed + * and the visual appearance of its {@code JLayer} objects needs to be updated. + * + * @see Component#repaint() + */ + protected void repaintLayer() { + firePropertyChange("dirty", null, null); + } + + /** * Notifies the {@code LayerUI} when any of its property are changed - * and enables updating every {@code JLayer} this {@code LayerUI} instance is set to. + * and enables updating every {@code JLayer} + * this {@code LayerUI} instance is set to. * * @param evt the PropertyChangeEvent generated by this {@code LayerUI} * @param l the {@code JLayer} this LayerUI is set to */ public void applyPropertyChange(PropertyChangeEvent evt, JLayer<? extends V> l) { + if ("dirty".equals(evt.getPropertyName())) { + l.repaint(); + } } /**
--- a/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Wed Nov 18 18:56:59 2009 -0800 @@ -486,7 +486,7 @@ } if (remSize > 0 && addSize == 0) { fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1); - } else if (addSize > 0 && remSize == 0 && fileCache.size() > addSize) { + } else if (addSize > 0 && remSize == 0 && addStart + addSize <= fileCache.size()) { fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1); } else { fireContentsChanged();
--- a/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/plaf/metal/OceanTheme.java Wed Nov 18 18:56:59 2009 -0800 @@ -32,6 +32,7 @@ import javax.swing.plaf.*; import sun.swing.SwingUtilities2; import sun.swing.PrintColorUIResource; +import sun.swing.SwingLazyValue; /** * The default theme for the {@code MetalLookAndFeel}. @@ -128,7 +129,7 @@ * @throws NullPointerException if {@code table} is {@code null} */ public void addCustomEntriesToTable(UIDefaults table) { - Object focusBorder = new UIDefaults.ProxyLazyValue( + Object focusBorder = new SwingLazyValue( "javax.swing.plaf.BorderUIResource$LineBorderUIResource", new Object[] {getPrimary1()}); // .30 0 DDE8F3 white secondary2
--- a/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java Wed Nov 18 18:56:59 2009 -0800 @@ -638,7 +638,7 @@ if ((b == null || b instanceof UIResource || component instanceof SynthBooleanTableCellRenderer) && !table.isCellSelected(row, column)) { - if (alternateColor != null && row % 2 == 0) { + if (alternateColor != null && row % 2 != 0) { component.setBackground(alternateColor); } }
--- a/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java Wed Nov 18 18:56:59 2009 -0800 @@ -214,8 +214,9 @@ : table.getBackground(); if (background == null || background instanceof javax.swing.plaf.UIResource) { Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor"); - if (alternateColor != null && row % 2 == 0) + if (alternateColor != null && row % 2 != 0) { background = alternateColor; + } } super.setForeground(unselectedForeground != null ? unselectedForeground
--- a/jdk/src/share/classes/javax/swing/text/JTextComponent.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/javax/swing/text/JTextComponent.java Wed Nov 18 18:56:59 2009 -0800 @@ -2069,7 +2069,7 @@ * width to match its own */ public boolean getScrollableTracksViewportWidth() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return port.getWidth() > getPreferredSize().width; } @@ -2090,7 +2090,7 @@ * to match its own */ public boolean getScrollableTracksViewportHeight() { - JViewport port = SwingUtilities2.getViewport(this); + JViewport port = SwingUtilities.getParentViewport(this); if (port != null) { return (port.getHeight() > getPreferredSize().height); }
--- a/jdk/src/share/classes/sun/awt/shell/ShellFolder.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/awt/shell/ShellFolder.java Wed Nov 18 18:56:59 2009 -0800 @@ -201,6 +201,8 @@ private static ShellFolderManager shellFolderManager; + private static Invoker invoker; + static { String managerClassName = (String)Toolkit.getDefaultToolkit(). getDesktopProperty("Shell.shellFolderManager"); @@ -225,6 +227,8 @@ throw new Error ("Could not access Shell Folder Manager: " + managerClass.getName()); } + + invoker = shellFolderManager.createInvoker(); } /** @@ -486,21 +490,6 @@ return null; } - private static Invoker invoker; - - /** - * Provides the single access point to the {@link Invoker}. It is guaranteed that the value - * returned by this method will be always the same. - * - * @return the singleton instance of {@link Invoker} - */ - public static Invoker getInvoker() { - if (invoker == null) { - invoker = shellFolderManager.createInvoker(); - } - return invoker; - } - /** * Invokes the {@code task} which doesn't throw checked exceptions * from its {@code call} method. If invokation is interrupted then Thread.currentThread().isInterrupted() will @@ -522,7 +511,7 @@ public static <T, E extends Throwable> T invoke(Callable<T> task, Class<E> exceptionClass) throws InterruptedException, E { try { - return getInvoker().invoke(task); + return invoker.invoke(task); } catch (Exception e) { if (e instanceof RuntimeException) { // Rethrow unchecked exceptions
--- a/jdk/src/share/classes/sun/swing/SwingLazyValue.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/swing/SwingLazyValue.java Wed Nov 18 18:56:59 2009 -0800 @@ -26,6 +26,9 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.AccessibleObject; +import java.security.AccessController; +import java.security.PrivilegedAction; import javax.swing.UIDefaults; /** @@ -65,13 +68,15 @@ if (methodName != null) { Class[] types = getClassArray(args); Method m = c.getMethod(methodName, types); + makeAccessible(m); return m.invoke(c, args); } else { Class[] types = getClassArray(args); Constructor constructor = c.getConstructor(types); + makeAccessible(constructor); return constructor.newInstance(args); } - } catch(Exception e) { + } catch (Exception e) { // Ideally we would throw an exception, unfortunately // often times there are errors as an initial look and // feel is loaded before one can be switched. Perhaps a @@ -81,6 +86,15 @@ return null; } + private void makeAccessible(final AccessibleObject object) { + AccessController.doPrivileged(new PrivilegedAction<Void>() { + public Void run() { + object.setAccessible(true); + return null; + } + }); + } + private Class[] getClassArray(Object[] args) { Class[] types = null; if (args!=null) {
--- a/jdk/src/share/classes/sun/swing/SwingUtilities2.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/swing/SwingUtilities2.java Wed Nov 18 18:56:59 2009 -0800 @@ -1807,22 +1807,4 @@ boolean three) { return liesIn(rect, p, false, false, three); } - - /** - * Returns the {@code JViewport} instance for the {@code component} - * or {@code null}. - * - * @return the {@code JViewport} instance for the {@code component} - * or {@code null} - * @throws NullPointerException if {@code component} is {@code null} - */ - public static JViewport getViewport(Component component) { - do { - component = component.getParent(); - if (component instanceof JViewport) { - return (JViewport) component; - } - } while(component instanceof JLayer); - return null; - } }
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Malaysia Summer Time", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha Time", "FNT", "Fernando de Noronha Summer Time", "FNST"}; + String NOVT[] = new String[] {"Novosibirsk Time", "NOVT", + "Novosibirsk Summer Time", "NOVST"}; String NPT[] = new String[] {"Nepal Time", "NPT", "Nepal Summer Time", "NPST"}; String NST[] = new String[] {"Newfoundland Standard Time", "NST", @@ -441,7 +443,8 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, + {"Antarctica/Casey", new String[] {"Casey Time", "CAST", + "Casey Summer Time", "CAST"}}, {"Antarctica/Davis", new String[] {"Davis Time", "DAVT", "Davis Summer Time", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Time", "DDUT", @@ -529,8 +532,8 @@ "Philippines Summer Time", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Novosibirsk Time", "NOVT", - "Novosibirsk Summer Time", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral Time", "ORAT", "Oral Summer Time", "ORAST"}}, {"Asia/Omsk", new String[] {"Omsk Time", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_de.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Malaysische Sommerzeit", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha Zeit", "FNT", "Fernando de Noronha Sommerzeit", "FNST"}; + String NOVT[] = new String[] {"Nowosibirsker Zeit", "NOVT", + "Nowosibirsker Sommerzeit", "NOVST"}; String NPT[] = new String[] {"Nepalesische Zeit", "NPT", "Nepalesische Sommerzeit", "NPST"}; String NST[] = new String[] {"Neufundland Normalzeit", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Davis Zeit", "DAVT", "Davis Sommerzeit", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Zeit", "DDUT", @@ -529,8 +530,8 @@ "Philippinische Sommerzeit", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Nowosibirsker Zeit", "NOVT", - "Nowosibirsker Sommerzeit", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral Zeit", "ORAT", "Oral Sommerzeit", "ORAST"}}, {"Asia/Omsk", new String[] {"Omsk Zeit", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_es.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Hora de verano de Malasia", "MYST"}; String NORONHA[] = new String[] {"Hora de Fernando de Noronha", "FNT", "Hora de verano de Fernando de Noronha", "FNST"}; + String NOVT[] = new String[] {"Hora de Novosibirsk", "NOVT", + "Hora de verano de Novosibirsk", "NOVST"}; String NPT[] = new String[] {"Hora de Nepal", "NPT", "Hora de verano de Nepal", "NPST"}; String NST[] = new String[] {"Hora est\u00e1ndar de Terranova", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Hora de Davis", "DAVT", "Hora de verano de Davis", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Hora de Dumont-d'Urville", "DDUT", @@ -529,8 +530,9 @@ "Hora de verano de Filipinas", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Hora de Novosibirsk", "NOVT", - "Hora de verano de Novosibirsk", "NOVST"}}, + + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Hora de Uralsk", "ORAT", "Hora de verano de Uralsk", "ORAST"}}, {"Asia/Omsk", new String[] {"Hora de Omsk", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Heure d'\u00e9t\u00e9 de Malaisie", "MYST"}; String NORONHA[] = new String[] {"Heure de Fernando de Noronha", "FNT", "Heure d'\u00e9t\u00e9 de Fernando de Noronha", "FNST"}; + String NOVT[] = new String[] {"Heure de Novossibirsk", "NOVT", + "Heure d'\u00e9t\u00e9 de Novossibirsk", "NOVST"}; String NPT[] = new String[] {"Heure du N\u00e9pal", "NPT", "Heure d'\u00e9t\u00e9 du N\u00e9pal", "NPST"}; String NST[] = new String[] {"Heure normale de Terre-Neuve", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Heure de Davis", "DAVT", "Heure d'\u00e9t\u00e9 de Davis", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Heure de Dumont-d'Urville", "DDUT", @@ -529,8 +530,8 @@ "Heure d'\u00e9t\u00e9 des Philippines", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Heure de Novossibirsk", "NOVT", - "Heure d'\u00e9t\u00e9 de Novossibirsk", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Heure d'Oral", "ORAT", "Heure d'\u00e9t\u00e9 d'Oral", "ORAST"}}, {"Asia/Omsk", new String[] {"Heure d'Omsk", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_it.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Ora estiva della Malaysia", "MYST"}; String NORONHA[] = new String[] {"Ora di Fernando de Noronha", "FNT", "Ora estiva di Fernando de Noronha", "FNST"}; + String NOVT[] = new String[] {"Ora di Novosibirsk", "NOVT", + "Ora estiva di Novosibirsk", "NOVST"}; String NPT[] = new String[] {"Ora del Nepal", "NPT", "Ora estiva del Nepal", "NPST"}; String NST[] = new String[] {"Ora solare di Terranova", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Ora di Davis", "DAVT", "Ora estiva di Davis", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Ora di Dumont-d'Urville", "DDUT", @@ -529,8 +530,8 @@ "Ora estiva delle Filippine", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Ora di Novosibirsk", "NOVT", - "Ora estiva di Novosibirsk", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Ora di Oral", "ORAT", "Ora estiva di Oral", "ORAST"}}, {"Asia/Omsk", new String[] {"Ora di Omsk", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "\u30de\u30ec\u30fc\u30b7\u30a2\u590f\u6642\u9593", "MYST"}; String NORONHA[] = new String[] {"\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u6642\u9593", "FNT", "\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u590f\u6642\u9593", "FNST"}; + String NOVT[] = new String[] {"\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u6642\u9593", "NOVT", + "\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u590f\u6642\u9593", "NOVST"}; String NPT[] = new String[] {"\u30cd\u30d1\u30fc\u30eb\u6642\u9593", "NPT", "\u30cd\u30d1\u30fc\u30eb\u590f\u6642\u9593", "NPST"}; String NST[] = new String[] {"\u30cb\u30e5\u30fc\u30d5\u30a1\u30f3\u30c9\u30e9\u30f3\u30c9\u6a19\u6e96\u6642", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"\u30c7\u30a4\u30d3\u30b9\u6642\u9593", "DAVT", "\u30c7\u30a4\u30d3\u30b9\u590f\u6642\u9593", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"\u30c7\u30e5\u30e2\u30f3\u30c7\u30e5\u30eb\u30f4\u30a3\u30eb\u6642\u9593", "DDUT", @@ -529,8 +530,8 @@ "\u30d5\u30a3\u30ea\u30d4\u30f3\u590f\u6642\u9593", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u6642\u9593", "NOVT", - "\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u590f\u6642\u9593", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"\u30aa\u30e9\u30eb\u6642\u9593", "ORAT", "\u30aa\u30e9\u30eb\u590f\u6642\u9593", "ORAST"}}, {"Asia/Omsk", new String[] {"\u30aa\u30e0\u30b9\u30af\u6642\u9593", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "\ub9d0\ub808\uc774\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha \uc2dc\uac04", "FNT", "Fernando de Noronha \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "FNST"}; + String NOVT[] = new String[] {"\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc2dc\uac04", "NOVT", + "\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NOVST"}; String NPT[] = new String[] {"\ub124\ud314 \uc2dc\uac04", "NPT", "\ub124\ud314 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NPST"}; String NST[] = new String[] {"\ub274\ud380\ub4e4\ub79c\ub4dc \ud45c\uc900\uc2dc", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Davis \uc2dc\uac04", "DAVT", "Davis \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"\ub4a4\ubabd \ub4a4\ub974\ube4c \uc2dc\uac04", "DDUT", @@ -529,8 +530,8 @@ "\ud544\ub9ac\ud540 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc2dc\uac04", "NOVT", - "\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral \ud45c\uc900\uc2dc", "ORAT", "Oral \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ORAST"}}, {"Asia/Omsk", new String[] {"Omsk \uc2dc\uac04", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "Malaysia, sommartid", "MYST"}; String NORONHA[] = new String[] {"Fernando de Noronha, normaltid", "FNT", "Fernando de Noronha, sommartid", "FNST"}; + String NOVT[] = new String[] {"Novosibirsk, normaltid", "NOVT", + "Novosibirsk, sommartid", "NOVST"}; String NPT[] = new String[] {"Nepal, normaltid", "NPT", "Nepal, sommartid", "NPST"}; String NST[] = new String[] {"Newfoundland, normaltid", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"Davis, normaltid", "DAVT", "Davis, sommartid", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville, normaltid", "DDUT", @@ -529,8 +530,8 @@ "Filippinerna, sommartid", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Novosibirsk, normaltid", "NOVT", - "Novosibirsk, sommartid", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral, normaltid", "ORAT", "Oral, sommartid", "ORAST"}}, {"Asia/Omsk", new String[] {"Omsk, normaltid", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "\u9a6c\u6765\u897f\u4e9a\u590f\u4ee4\u65f6", "MYST"}; String NORONHA[] = new String[] {"\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u65f6\u95f4", "FNT", "\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u590f\u4ee4\u65f6", "FNST"}; + String NOVT[] = new String[] {"Novosibirsk \u65f6\u95f4", "NOVT", + "Novosibirsk \u590f\u4ee4\u65f6", "NOVST"}; String NPT[] = new String[] {"\u5c3c\u6cca\u5c14\u65f6\u95f4", "NPT", "\u5c3c\u6cca\u5c14\u590f\u4ee4\u65f6", "NPST"}; String NST[] = new String[] {"\u7ebd\u82ac\u5170\u6807\u51c6\u65f6\u95f4", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"\u6234\u7ef4\u65af\u65f6\u95f4", "DAVT", "\u6234\u7ef4\u65af\u590f\u4ee4\u65f6", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville \u65f6\u95f4", "DDUT", @@ -529,8 +530,8 @@ "\u83f2\u5f8b\u5bbe\u590f\u4ee4\u65f6", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Novosibirsk \u65f6\u95f4", "NOVT", - "Novosibirsk \u590f\u4ee4\u65f6", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral \u65f6\u95f4", "ORAT", "Oral \u590f\u4ee4\u65f6", "ORAST"}}, {"Asia/Omsk", new String[] {"\u9102\u6728\u65af\u514b\u65f6\u95f4", "OMST",
--- a/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Wed Nov 18 18:56:59 2009 -0800 @@ -141,6 +141,8 @@ "\u99ac\u4f86\u897f\u4e9e\u590f\u4ee4\u6642\u9593", "MYST"}; String NORONHA[] = new String[] {"\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u6642\u9593", "FNT", "\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u590f\u4ee4\u6642\u9593", "FNST"}; + String NOVT[] = new String[] {"Novosibirsk \u6642\u9593", "NOVT", + "Novosibirsk \u590f\u4ee4\u6642\u9593", "NOVST"}; String NPT[] = new String[] {"\u5c3c\u6cca\u723e\u6642\u9593", "NPT", "\u5c3c\u6cca\u723e\u590f\u4ee4\u6642\u9593", "NPST"}; String NST[] = new String[] {"\u7d10\u82ac\u862d\u6a19\u6e96\u6642\u9593", "NST", @@ -441,7 +443,6 @@ {"America/Winnipeg", CST}, {"America/Yakutat", AKST}, {"America/Yellowknife", MST}, - {"Antarctica/Casey", WST_AUS}, {"Antarctica/Davis", new String[] {"\u81fa\u7dad\u65af\u6642\u9593", "DAVT", "\u81fa\u7dad\u65af\u590f\u4ee4\u6642\u9593", "DAVST"}}, {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville \u6642\u9593", "DDUT", @@ -529,8 +530,8 @@ "\u83f2\u5f8b\u8cd3\u590f\u4ee4\u6642\u9593", "PHST"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novosibirsk", new String[] {"Novosibirsk \u6642\u9593", "NOVT", - "Novosibirsk \u590f\u4ee4\u6642\u9593", "NOVST"}}, + {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"\u6b50\u4f5b\u6642\u9593", "ORAT", "\u6b50\u4f5b\u590f\u4ee4\u6642\u9593", "ORAST"}}, {"Asia/Omsk", new String[] {"\u6b50\u59c6\u65af\u514b (Omsk) \u6642\u9593", "OMST",
--- a/jdk/src/solaris/native/sun/awt/gtk2_interface.c Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/solaris/native/sun/awt/gtk2_interface.c Wed Nov 18 18:56:59 2009 -0800 @@ -637,13 +637,13 @@ if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") || gtk_modules_env && strstr (gtk_modules_env, "gail")) { - gchar *tmp_env = strdup (gtk_modules_env); /* the new env will be smaller than the old one */ gchar *s, *new_env = malloc (sizeof(ENV_PREFIX)+strlen (gtk_modules_env)); if (new_env != NULL ) { /* careful, strtok modifies its args */ + gchar *tmp_env = strdup (gtk_modules_env); strcpy(new_env, ENV_PREFIX); /* strip out 'atk-bridge' and 'gail' */
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Wed Nov 18 18:56:59 2009 -0800 @@ -524,7 +524,7 @@ // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details private static native int compareIDs(long pParentIShellFolder, long pidl1, long pidl2); - private Boolean cachedIsFileSystem; + private volatile Boolean cachedIsFileSystem; /** * @return Whether this is a file system shell folder @@ -693,29 +693,32 @@ ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>(); long pEnumObjects = getEnumObjects(includeHiddenFiles); if (pEnumObjects != 0) { - long childPIDL; - int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; - do { - childPIDL = getNextChild(pEnumObjects); - boolean releasePIDL = true; - if (childPIDL != 0 && - (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { - Win32ShellFolder2 childFolder; - if (Win32ShellFolder2.this.equals(desktop) - && personal != null - && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) { - childFolder = personal; - } else { - childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL); - releasePIDL = false; + try { + long childPIDL; + int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR; + do { + childPIDL = getNextChild(pEnumObjects); + boolean releasePIDL = true; + if (childPIDL != 0 && + (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) { + Win32ShellFolder2 childFolder; + if (Win32ShellFolder2.this.equals(desktop) + && personal != null + && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) { + childFolder = personal; + } else { + childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL); + releasePIDL = false; + } + list.add(childFolder); } - list.add(childFolder); - } - if (releasePIDL) { - releasePIDL(childPIDL); - } - } while (childPIDL != 0 && !Thread.currentThread().isInterrupted()); - releaseEnumObjects(pEnumObjects); + if (releasePIDL) { + releasePIDL(childPIDL); + } + } while (childPIDL != 0 && !Thread.currentThread().isInterrupted()); + } finally { + releaseEnumObjects(pEnumObjects); + } } return Thread.currentThread().isInterrupted() ? new File[0] @@ -759,7 +762,7 @@ }, InterruptedException.class); } - private Boolean cachedIsLink; + private volatile Boolean cachedIsLink; /** * @return Whether this shell folder is a link
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Nov 18 17:17:56 2009 -0800 +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Nov 18 18:56:59 2009 -0800 @@ -79,9 +79,12 @@ // Shouldn't happen but watch for it anyway throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found"); } - Win32ShellFolder2 folder = createShellFolderFromRelativePIDL(parent, pIDL); - Win32ShellFolder2.releasePIDL(pIDL); - return folder; + + try { + return createShellFolderFromRelativePIDL(parent, pIDL); + } finally { + Win32ShellFolder2.releasePIDL(pIDL); + } } static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, long pIDL) @@ -269,7 +272,7 @@ Arrays.sort(secondLevelFolders); for (File secondLevelFolder : secondLevelFolders) { Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder; - if (!folder.isFileSystem() || folder.isDirectory()) { + if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) { folders.add(folder); // Add third level for "My Computer" if (folder.equals(drives)) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/NumericShaper/EqualsTest.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6842557 + * @summary confirm that an instance which is created with new Enum ranges is + * equivalent to another instance which is created with equivalent traditional + * ranges or the same Enum ranges. + */ + +import java.awt.font.NumericShaper; +import java.util.EnumSet; +import static java.awt.font.NumericShaper.*; + +public class EqualsTest { + public static void main(String[] args) { + NumericShaper ns1 = getContextualShaper(ARABIC | TAMIL, TAMIL); + NumericShaper ns2 = getContextualShaper( + EnumSet.of(Range.ARABIC, Range.TAMIL), + Range.TAMIL); + NumericShaper ns3 = getContextualShaper( + EnumSet.of(Range.ARABIC, Range.TAMIL), + Range.TAMIL); + NumericShaper ns4 = getContextualShaper( + EnumSet.of(Range.ARABIC, Range.TAMIL), + Range.ARABIC); + + if (!ns1.equals(ns2)) { + throw new RuntimeException("ns1 != ns2: ns1=" + ns1 + ", ns2=" + ns2); + } + if (!ns2.equals(ns1)) { + throw new RuntimeException("ns2 != ns1: ns1=" + ns1 + ", ns2=" + ns2); + } + if (!ns2.equals(ns3)) { + throw new RuntimeException("ns2 != ns3: ns2=" + ns2 + ", ns3=" + ns3); + } + if (ns1.equals(ns4)) { + throw new RuntimeException("ns1 == ns4: ns1=" + ns1 + ", ns4=" + ns4); + } + if (ns2.equals(ns4)) { + throw new RuntimeException("ns2 == ns4: ns2=" + ns2 + ", ns4=" + ns4); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/NumericShaper/MTTest.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6843181 + * @summary Confirm that NumericShaper is thread-safe. + * @run main/timeout=300/othervm MTTest + */ + +import java.awt.font.NumericShaper; +import java.util.Arrays; +import java.util.EnumSet; +import static java.awt.font.NumericShaper.*; + +public class MTTest { + static volatile boolean runrun = true; + static volatile boolean err = false; + + final static String text = "-123 (English) 456.00 (Arabic) \u0641\u0642\u0643 -789 (Thai) \u0e01\u0e33 01.23"; + static char[] t1, t2; + static NumericShaper ns1, ns2, ns3, ns4; + + public static void main(String[] args) { + System.out.println(" original: " + text); + ns1 = getContextualShaper(EnumSet.of(Range.ARABIC), Range.ARABIC); + t1 = text.toCharArray(); + ns1.shape(t1, 0, t1.length); + System.out.println("expected t1: " + String.valueOf(t1)); + + ns2 = getContextualShaper(EnumSet.of(Range.THAI), Range.THAI); + t2 = text.toCharArray(); + ns2.shape(t2, 0, t2.length); + System.out.println("expected t2: " + String.valueOf(t2)); + + ns3 = getContextualShaper(ARABIC, ARABIC); + ns4 = getContextualShaper(THAI, THAI); + + Thread th1 = new Thread(new Work(ns1, t1)); + Thread th2 = new Thread(new Work(ns2, t2)); + Thread th3 = new Thread(new Work(ns1, t1)); + Thread th4 = new Thread(new Work(ns2, t2)); + Thread th5 = new Thread(new Work(ns3, t1)); + Thread th6 = new Thread(new Work(ns4, t2)); + Thread th7 = new Thread(new Work(ns3, t1)); + Thread th8 = new Thread(new Work(ns4, t2)); + + th1.start(); + th2.start(); + th3.start(); + th4.start(); + th5.start(); + th6.start(); + th7.start(); + th8.start(); + + try { + for (int i = 0; runrun && i < 180; i++) { + Thread.sleep(1000); // 1 seconds + } + runrun = false; + th1.join(); + th2.join(); + th3.join(); + th4.join(); + th5.join(); + th6.join(); + th7.join(); + th8.join(); + } + catch (InterruptedException e) { + } + + if (err) { + throw new RuntimeException("Thread-safe test failed."); + } + } + + private static class Work implements Runnable { + NumericShaper ns; + char[] expectedText; + + Work(NumericShaper ns, char[] expectedText) { + this.ns = ns; + this.expectedText = expectedText; + + } + + public void run() { + int count = 0; + while (runrun) { + char[] t = text.toCharArray(); + try { + count++; + ns.shape(t, 0, t.length); + } catch (Exception e) { + System.err.println("Error: Unexpected exception: " + e); + runrun = false; + err = true; + return; + } + if (!Arrays.equals(t, expectedText)) { + System.err.println("Error: shape() returned unexpected value: "); + System.err.println("count = " + count); + System.err.println(" expected: " + String.valueOf(expectedText)); + System.err.println(" got: " + String.valueOf(t)); + runrun = false; + err = true; + return; + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/font/NumericShaper/ShapingTest.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6842557 + * @summary confirm that shaping works as expected. (Mainly for new characters which were added in Unicode 5) + * used where appropriate. + */ + +import java.awt.font.NumericShaper; +import java.util.EnumSet; +import static java.awt.font.NumericShaper.*; + +public class ShapingTest { + public static void main(String[] args) { + NumericShaper ns_old = getContextualShaper(ARABIC | TAMIL | ETHIOPIC, + EUROPEAN); + NumericShaper ns_new = getContextualShaper(EnumSet.of( + Range.ARABIC, Range.TAMIL, Range.ETHIOPIC), + Range.EUROPEAN); + + boolean err = false; + + String[][] data = { + // Arabic "October 10" + {"\u0623\u0643\u062a\u0648\u0628\u0631 10", + "\u0623\u0643\u062a\u0648\u0628\u0631 \u0661\u0660"}, + + // Tamil "Year 2009" + {"\u0b86\u0ba3\u0bcd\u0b9f\u0bc1 2009", + "\u0b86\u0ba3\u0bcd\u0b9f\u0bc1 \u0be8\u0be6\u0be6\u0bef"}, + // "\u0be800\u0bef is returned by pre-JDK7 because Tamil zero was not + // included in Unicode 4.0.0. + + // Ethiopic "Syllable<HA> 2009" + {"\u1200 2009", + "\u1200 \u136a00\u1371"}, + // Ethiopic zero doesn't exist even in Unicode 5.1.0. + }; + + for (int i = 0; i < data.length; i++) { + String expected = data[i][1]; + + char[] text = data[i][0].toCharArray(); + ns_old.shape(text, 0, text.length); + String got = new String(text); + + if (!expected.equals(got)) { + err = true; + System.err.println("Error with traditional range."); + System.err.println(" text = " + data[i][0]); + System.err.println(" got = " + got); + System.err.println(" expected = " + expected); + } else { + System.err.println("OK with traditional range."); + System.err.println(" text = " + data[i][0]); + System.err.println(" got = " + got); + System.err.println(" expected = " + expected); + } + + text = data[i][0].toCharArray(); + ns_new.shape(text, 0, text.length); + got = new String(text); + + if (!expected.equals(got)) { + err = true; + System.err.println("Error with new Enum range."); + System.err.println(" text = " + data[i][0]); + System.err.println(" got = " + got); + System.err.println(" expected = " + expected); + } else { + System.err.println("OK with new Enum range."); + System.err.println(" text = " + data[i][0]); + System.err.println(" got = " + got); + System.err.println(" expected = " + expected); + } + } + + if (err) { + throw new RuntimeException("shape() returned unexpected value."); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JFileChooser/6550546/bug6550546.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,57 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6550546 + @summary Win LAF: JFileChooser -> Look in Drop down should not display any shortcuts created on desktop + @author Pavel Porvatov + @run main bug6550546 +*/ + +import sun.awt.OSInfo; +import sun.awt.shell.ShellFolder; + +import javax.swing.*; +import java.io.File; + +public class bug6550546 { + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("The test is suitable only for Windows, skipped."); + + return; + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + File[] files = (File[]) ShellFolder.get("fileChooserComboBoxFolders"); + + for (File file : files) { + if (file instanceof ShellFolder && ((ShellFolder) file).isLink()) { + throw new RuntimeException("Link shouldn't be in FileChooser combobox, " + file.getPath()); + } + } + } + }); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JFileChooser/6741890/bug6741890.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,107 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6741890 + @summary Deadlock in Win32ShellFolderManager2 + @author Pavel Porvatov + @run main bug6741890 +*/ + +import sun.awt.shell.ShellFolder; +import sun.awt.OSInfo; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.concurrent.Callable; + +public class bug6741890 { + /** + * This mux is used to prevent NPE in the isLink and isFileSystem methods + */ + private static final Object mux = new Object(); + + private static final int COUNT = 100000; + + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("The test is applicable only for Windows. Skipped."); + + return; + } + + String tmpDir = System.getProperty("java.io.tmpdir"); + + if (tmpDir.length() == 0) { //'java.io.tmpdir' isn't guaranteed to be defined + tmpDir = System.getProperty("user.home"); + } + + final ShellFolder tmpFile = ShellFolder.getShellFolder(new File(tmpDir)); + + System.out.println("Temp directory: " + tmpDir); + + System.out.println("Stress test was run"); + + Thread thread = new Thread() { + public void run() { + while (!isInterrupted()) { + ShellFolder.invoke(new Callable<Void>() { + public Void call() throws Exception { + synchronized (mux) { + tmpFile.isFileSystem(); + tmpFile.isLink(); + } + + return null; + } + }); + } + } + }; + + thread.start(); + + for (int i = 0; i < COUNT; i++) { + synchronized (mux) { + clearField(tmpFile, "cachedIsLink"); + clearField(tmpFile, "cachedIsFileSystem"); + } + + tmpFile.isFileSystem(); + tmpFile.isLink(); + } + + thread.interrupt(); + thread.join(); + + System.out.println("Test passed successfully"); + } + + private static void clearField(Object o, String fieldName) throws Exception { + Field field = o.getClass().getDeclaredField(fieldName); + + field.setAccessible(true); + + field.set(o, null); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/JFileChooser/6868611/bug6868611.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6868611 + @summary FileSystemView throws NullPointerException + @author Pavel Porvatov + @run main bug6868611 +*/ + +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; +import java.io.File; + +public class bug6868611 { + private static final int COUNT = 1000; + + public static void main(String[] args) throws Exception { + String tempDirProp = System.getProperty("java.io.tmpdir"); + + final String tempDir = tempDirProp == null || !new File(tempDirProp).isDirectory() ? + System.getProperty("user.home") : tempDirProp; + + System.out.println("Temp directory: " + tempDir); + + // Create 1000 files + for (int i = 0; i < 1000; i++) { + new File(tempDir, "temp" + i).createNewFile(); + } + + // Init default FileSystemView + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + FileSystemView.getFileSystemView().getFiles(new File(tempDir), false); + } + }); + + for (int i = 0; i < COUNT; i++) { + Thread thread = new MyThread(tempDir); + + thread.start(); + + Thread.sleep((long) (Math.random() * 100)); + + thread.interrupt(); + + if (i % 100 == 0) { + System.out.print("*"); + } + } + + System.out.println(); + + // Remove 1000 files + for (int i = 0; i < 1000; i++) { + new File(tempDir, "temp" + i).delete(); + } + } + + private static class MyThread extends Thread { + private final String dir; + + private MyThread(String dir) { + this.dir = dir; + } + + public void run() { + FileSystemView fileSystemView = FileSystemView.getFileSystemView(); + + fileSystemView.getFiles(new File(dir), false); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,44 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6795356 + * @summary Checks that SwingLazyValue class correclty works + * @author Alexander Potochkin + * @run main SwingLazyValueTest + */ + +import sun.swing.SwingLazyValue; + +import javax.swing.*; + +public class SwingLazyValueTest { + + public static void main(String[] args) throws Exception { + if(new SwingLazyValue("javax.swing.JTable$DoubleRenderer"). + createValue(null) == null) { + throw new RuntimeException("SwingLazyValue doesn't work"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/UIDefaults/6795356/TableTest.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,52 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6795356 + * @summary Checks that SwingLazyValue class correclty works + * @author Alexander Potochkin + * @run main/othervm TableTest + */ + +import sun.applet.AppletSecurity; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import java.awt.*; + +public class TableTest { + + public static void main(String[] args) throws Exception { + + KeyboardFocusManager.getCurrentKeyboardFocusManager(); + System.setSecurityManager(new AppletSecurity()); + + JTable table = new JTable(); + TableCellEditor de = table.getDefaultEditor(Double.class); + if (de == null) { + throw new RuntimeException("Table default editor is null"); + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/swing/UIDefaults/6795356/bug6795356.java Wed Nov 18 18:56:59 2009 -0800 @@ -0,0 +1,100 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6795356 + * @summary Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc + * @author Alexander Potochkin + * @run main bug6795356 + */ + +import java.lang.ref.WeakReference; +import java.security.ProtectionDomain; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.AccessControlContext; +import java.util.LinkedList; +import java.util.List; +import javax.swing.*; + +public class bug6795356 { + volatile static WeakReference<ProtectionDomain> weakRef; + + public static void main(String[] args) throws Exception { + + ProtectionDomain domain = new ProtectionDomain(null, null); + + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + + // this initialize ProxyLazyValues + UIManager.getLookAndFeel(); + + return null; + } + }, new AccessControlContext(new ProtectionDomain[]{domain})); + + weakRef = new WeakReference<ProtectionDomain>(domain); + domain = null; + + // Generate OutOfMemory and check the weak ref + generateOOME(); + + if (weakRef.get() != null) { + throw new RuntimeException("Memory leak found!"); + } + System.out.println("Test passed"); + } + + static void generateOOME() { + List<Object> bigLeak = new LinkedList<Object>(); + boolean oome = false; + System.out.print("Filling the heap"); + try { + for(int i = 0; true ; i++) { + // Now, use up all RAM + bigLeak.add(new byte[1024 * 1024]); + System.out.print("."); + + // Give the GC a change at that weakref + if (i % 10 == 0) { + System.gc(); + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } catch (OutOfMemoryError e) { + bigLeak = null; + oome = true; + } + System.out.println(""); + if (!oome) { + throw new RuntimeException("Problem with test case - never got OOME"); + } + System.out.println("Got OOME"); + } +}