Merge
This commit is contained in:
commit
ae1cce3a74
@ -89,7 +89,7 @@ define FullPath
|
||||
$(shell $(CYGPATH_CMD) $1 2> $(DEV_NULL))
|
||||
endef
|
||||
define OptFullPath
|
||||
$(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1"; else echo "$1"; fi)
|
||||
$(shell if [ "$1" != "" -a -d "$1" ]; then $(CYGPATH_CMD) "$1" 2> $(DEV_NULL); else echo "$1"; fi)
|
||||
endef
|
||||
else
|
||||
# Temporary until we upgrade to MKS 8.7, MKS pwd returns mixed mode path
|
||||
|
@ -136,15 +136,20 @@ define GetVersion
|
||||
$(shell echo $1 | sed -e 's@[^0-9]*\([0-9][0-9]*\.[0-9][.0-9]*\).*@\1@' )
|
||||
endef
|
||||
|
||||
# Return one part of the version numbers, watch out for non digits.
|
||||
define VersionWord # Number Version
|
||||
$(word $1,$(subst ., ,$(subst -, ,$2)))
|
||||
endef
|
||||
|
||||
# Given a major.minor.micro version, return the major, minor, or micro number
|
||||
define MajorVersion
|
||||
$(if $(word 1, $(subst ., ,$1)),$(word 1, $(subst ., ,$1)),0)
|
||||
$(if $(call VersionWord,1,$1),$(call VersionWord,1,$1),0)
|
||||
endef
|
||||
define MinorVersion
|
||||
$(if $(word 2, $(subst ., ,$1)),$(word 2, $(subst ., ,$1)),0)
|
||||
$(if $(call VersionWord,2,$1),$(call VersionWord,2,$1),0)
|
||||
endef
|
||||
define MicroVersion
|
||||
$(if $(word 3, $(subst ., ,$1)),$(word 3, $(subst ., ,$1)),0)
|
||||
$(if $(call VersionWord,3,$1),$(call VersionWord,3,$1),0)
|
||||
endef
|
||||
|
||||
# Macro that returns missing, same, newer, or older $1=version $2=required
|
||||
|
@ -340,6 +340,10 @@ PATH="${path4sdk}"
|
||||
export PATH
|
||||
|
||||
# Export variables required for Zero
|
||||
if [ "${SHARK_BUILD}" = true ] ; then
|
||||
ZERO_BUILD=true
|
||||
export ZERO_BUILD
|
||||
fi
|
||||
if [ "${ZERO_BUILD}" = true ] ; then
|
||||
# ZERO_LIBARCH is the name of the architecture-specific
|
||||
# subdirectory under $JAVA_HOME/jre/lib
|
||||
@ -417,4 +421,55 @@ if [ "${ZERO_BUILD}" = true ] ; then
|
||||
fi
|
||||
export LIBFFI_CFLAGS
|
||||
export LIBFFI_LIBS
|
||||
|
||||
# LLVM_CFLAGS, LLVM_LDFLAGS and LLVM_LIBS tell the compiler how to
|
||||
# compile and link against LLVM
|
||||
if [ "${SHARK_BUILD}" = true ] ; then
|
||||
if [ "${LLVM_CONFIG}" = "" ] ; then
|
||||
LLVM_CONFIG=$(which llvm-config 2>/dev/null)
|
||||
fi
|
||||
if [ ! -x "${LLVM_CONFIG}" ] ; then
|
||||
echo "ERROR: Unable to locate llvm-config"
|
||||
exit 1
|
||||
fi
|
||||
llvm_components="jit engine nativecodegen"
|
||||
|
||||
unset LLVM_CFLAGS
|
||||
for flag in $("${LLVM_CONFIG}" --cxxflags $llvm_components); do
|
||||
if echo "${flag}" | grep -q '^-[ID]'; then
|
||||
if [ "${flag}" != "-D_DEBUG" ] ; then
|
||||
if [ "${LLVM_CFLAGS}" != "" ] ; then
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS} "
|
||||
fi
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS}${flag}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
llvm_version=$("${LLVM_CONFIG}" --version | sed 's/\.//; s/svn.*//')
|
||||
LLVM_CFLAGS="${LLVM_CFLAGS} -DSHARK_LLVM_VERSION=${llvm_version}"
|
||||
|
||||
unset LLVM_LDFLAGS
|
||||
for flag in $("${LLVM_CONFIG}" --ldflags $llvm_components); do
|
||||
if echo "${flag}" | grep -q '^-L'; then
|
||||
if [ "${LLVM_LDFLAGS}" != "" ] ; then
|
||||
LLVM_LDFLAGS="${LLVM_LDFLAGS} "
|
||||
fi
|
||||
LLVM_LDFLAGS="${LLVM_LDFLAGS}${flag}"
|
||||
fi
|
||||
done
|
||||
|
||||
unset LLVM_LIBS
|
||||
for flag in $("${LLVM_CONFIG}" --libs $llvm_components); do
|
||||
if echo "${flag}" | grep -q '^-l'; then
|
||||
if [ "${LLVM_LIBS}" != "" ] ; then
|
||||
LLVM_LIBS="${LLVM_LIBS} "
|
||||
fi
|
||||
LLVM_LIBS="${LLVM_LIBS}${flag}"
|
||||
fi
|
||||
done
|
||||
|
||||
export LLVM_CFLAGS
|
||||
export LLVM_LDFLAGS
|
||||
export LLVM_LIBS
|
||||
fi
|
||||
fi
|
||||
|
@ -21,4 +21,4 @@
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
tzdata2010i
|
||||
tzdata2010l
|
||||
|
@ -316,8 +316,25 @@ Rule Egypt 2007 only - Sep Thu>=1 23:00s 0 -
|
||||
# and can be found by searching for "winter" in their search engine
|
||||
# (at least today).
|
||||
|
||||
# From Alexander Krivenyshev (2010-07-20):
|
||||
# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has
|
||||
# decided that Daylight Saving Time will not be used in Egypt during
|
||||
# Ramadan.
|
||||
#
|
||||
# Arabic translation:
|
||||
# "Clocks to go back during Ramadan--and then forward again"
|
||||
# <a href="http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again">
|
||||
# http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
|
||||
# </a>
|
||||
# or
|
||||
# <a href="http://www.worldtimezone.com/dst_news/dst_news_egypt02.html">
|
||||
# http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
|
||||
# </a>
|
||||
|
||||
Rule Egypt 2008 only - Aug lastThu 23:00s 0 -
|
||||
Rule Egypt 2009 only - Aug 20 23:00s 0 -
|
||||
Rule Egypt 2010 only - Aug 11 0:00 0 -
|
||||
Rule Egypt 2010 only - Sep 10 0:00 1:00 S
|
||||
Rule Egypt 2010 max - Sep lastThu 23:00s 0 -
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
|
@ -2200,6 +2200,18 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
|
||||
# "At 12:01am Friday, clocks in Israel and the West Bank will change to
|
||||
# 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
|
||||
|
||||
# From Steffen Thorsen (2010-08-11):
|
||||
# According to several sources, including
|
||||
# <a href="http://www.maannews.net/eng/ViewDetails.aspx?ID=306795">
|
||||
# http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
|
||||
# </a>
|
||||
# the clocks were set back one hour at 2010-08-11 00:00:00 local time in
|
||||
# Gaza and the West Bank.
|
||||
# Some more background info:
|
||||
# <a href="http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html">
|
||||
# http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.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
|
||||
@ -2220,6 +2232,7 @@ Rule Palestine 2008 only - Aug lastFri 2:00 0 -
|
||||
Rule Palestine 2009 only - Mar lastFri 0:00 1:00 S
|
||||
Rule Palestine 2010 max - Mar lastSat 0:01 1:00 S
|
||||
Rule Palestine 2009 max - Sep Fri>=1 2:00 0 -
|
||||
Rule Palestine 2010 only - Aug 11 0:00 0 -
|
||||
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
|
||||
|
@ -368,10 +368,10 @@ Zone Pacific/Kwajalein 11:09:20 - LMT 1901
|
||||
|
||||
# Micronesia
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Pacific/Truk 10:07:08 - LMT 1901
|
||||
10:00 - TRUT # Truk Time
|
||||
Zone Pacific/Ponape 10:32:52 - LMT 1901 # Kolonia
|
||||
11:00 - PONT # Ponape Time
|
||||
Zone Pacific/Chuuk 10:07:08 - LMT 1901
|
||||
10:00 - CHUT # Chuuk Time
|
||||
Zone Pacific/Pohnpei 10:32:52 - LMT 1901 # Kolonia
|
||||
11:00 - PONT # Pohnpei Time
|
||||
Zone Pacific/Kosrae 10:51:56 - LMT 1901
|
||||
11:00 - KOST 1969 Oct # Kosrae Time
|
||||
12:00 - KOST 1999
|
||||
|
@ -112,7 +112,9 @@ Link Pacific/Chatham NZ-CHAT
|
||||
Link America/Denver Navajo
|
||||
Link Asia/Shanghai PRC
|
||||
Link Pacific/Pago_Pago Pacific/Samoa
|
||||
Link Pacific/Truk Pacific/Yap
|
||||
Link Pacific/Chuuk Pacific/Yap
|
||||
Link Pacific/Chuuk Pacific/Truk
|
||||
Link Pacific/Pohnpei Pacific/Ponape
|
||||
Link Europe/Warsaw Poland
|
||||
Link Europe/Lisbon Portugal
|
||||
Link Asia/Taipei ROC
|
||||
|
@ -1035,22 +1035,47 @@ Zone Europe/Tallinn 1:39:00 - LMT 1880
|
||||
2:00 EU EE%sT
|
||||
|
||||
# Finland
|
||||
#
|
||||
|
||||
# From Hannu Strang (1994-09-25 06:03:37 UTC):
|
||||
# Well, here in Helsinki we're just changing from summer time to regular one,
|
||||
# and it's supposed to change at 4am...
|
||||
|
||||
# From Janne Snabb (2010-0715):
|
||||
#
|
||||
# From Paul Eggert (2006-03-22):
|
||||
# Shanks & Pottenger say Finland has switched at 02:00 standard time
|
||||
# since 1981. Go with Strang instead.
|
||||
# I noticed that the Finland data is not accurate for years 1981 and 1982.
|
||||
# During these two first trial years the DST adjustment was made one hour
|
||||
# earlier than in forthcoming years. Starting 1983 the adjustment was made
|
||||
# according to the central European standards.
|
||||
#
|
||||
# This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
|
||||
# Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
|
||||
# Finnish) at
|
||||
#
|
||||
# <a href="http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf">
|
||||
# http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
|
||||
# </a>
|
||||
#
|
||||
# Page 105 (56 in PDF version) has a handy table of all past daylight savings
|
||||
# transitions. It is easy enough to interpret without Finnish skills.
|
||||
#
|
||||
# This is also confirmed by Finnish Broadcasting Company's archive at:
|
||||
#
|
||||
# <a href="http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401">
|
||||
# http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
|
||||
# </a>
|
||||
#
|
||||
# The news clip from 1981 says that "the time between 2 and 3 o'clock does not
|
||||
# exist tonight."
|
||||
|
||||
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
|
||||
Rule Finland 1942 only - Apr 3 0:00 1:00 S
|
||||
Rule Finland 1942 only - Oct 3 0:00 0 -
|
||||
Rule Finland 1981 1982 - Mar lastSun 2:00 1:00 S
|
||||
Rule Finland 1981 1982 - Sep lastSun 3:00 0 -
|
||||
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
|
||||
Zone Europe/Helsinki 1:39:52 - LMT 1878 May 31
|
||||
1:39:52 - HMT 1921 May # Helsinki Mean Time
|
||||
2:00 Finland EE%sT 1981 Mar 29 2:00
|
||||
2:00 Finland EE%sT 1983
|
||||
2:00 EU EE%sT
|
||||
|
||||
# Aaland Is
|
||||
|
@ -82,9 +82,9 @@ Leap 2008 Dec 31 23:59:60 + S
|
||||
# FAX : 33 (0) 1 40 51 22 91
|
||||
# Internet : services.iers@obspm.fr
|
||||
#
|
||||
# Paris, 4 July 2009
|
||||
# Paris, 14 July 2010
|
||||
#
|
||||
# Bulletin C 38
|
||||
# Bulletin C 40
|
||||
#
|
||||
# To authorities responsible
|
||||
# for the measurement and
|
||||
@ -92,9 +92,9 @@ Leap 2008 Dec 31 23:59:60 + S
|
||||
#
|
||||
# INFORMATION ON UTC - TAI
|
||||
#
|
||||
# NO positive leap second will be introduced at the end of December 2009.
|
||||
# NO positive leap second will be introduced at the end of December 2010.
|
||||
# The difference between Coordinated Universal Time UTC and the
|
||||
# International Atomic Time TAI is :
|
||||
# International Atomic Time TAI is :
|
||||
#
|
||||
# from 2009 January 1, 0h UTC, until further notice : UTC-TAI = -34 s
|
||||
#
|
||||
@ -104,6 +104,6 @@ Leap 2008 Dec 31 23:59:60 + S
|
||||
# will be no time step at the next possible date.
|
||||
#
|
||||
# Daniel GAMBIS
|
||||
# Director
|
||||
# Director
|
||||
# Earth Orientation Center of IERS
|
||||
# Observatoire de Paris, France
|
||||
|
@ -1346,6 +1346,83 @@ Zone America/Montreal -4:54:16 - LMT 1884
|
||||
# entry since our cutoff date of 1970, so we can move
|
||||
# America/Coral_Harbour to the 'backward' file.
|
||||
|
||||
# From Mark Brader (2010-03-06):
|
||||
#
|
||||
# Currently the database has:
|
||||
#
|
||||
# # Ontario
|
||||
#
|
||||
# # From Paul Eggert (2006-07-09):
|
||||
# # Shanks & Pottenger write that since 1970 most of Ontario has been like
|
||||
# # Toronto.
|
||||
# # Thunder Bay skipped DST in 1973.
|
||||
# # Many smaller locales did not observe peacetime DST until 1974;
|
||||
# # Nipigon (EST) and Rainy River (CST) are the largest that we know of.
|
||||
#
|
||||
# In the (Toronto) Globe and Mail for Saturday, 1955-09-24, in the bottom
|
||||
# right corner of page 1, it says that Toronto will return to standard
|
||||
# time at 2 am Sunday morning (which agrees with the database), and that:
|
||||
#
|
||||
# The one-hour setback will go into effect throughout most of Ontario,
|
||||
# except in areas like Windsor which remains on standard time all year.
|
||||
#
|
||||
# Windsor is, of course, a lot larger than Nipigon.
|
||||
#
|
||||
# I only came across this incidentally. I don't know if Windsor began
|
||||
# observing DST when Detroit did, or in 1974, or on some other date.
|
||||
#
|
||||
# By the way, the article continues by noting that:
|
||||
#
|
||||
# Some cities in the United States have pushed the deadline back
|
||||
# three weeks and will change over from daylight saving in October.
|
||||
|
||||
# From Arthur David Olson (2010-07-17):
|
||||
#
|
||||
# "Standard Time and Time Zones in Canada" appeared in
|
||||
# The Journal of The Royal Astronomical Society of Canada,
|
||||
# volume 26, number 2 (February 1932) and, as of 2010-07-17,
|
||||
# was available at
|
||||
# <a href="http://adsabs.harvard.edu/full/1932JRASC..26...49S">
|
||||
# http://adsabs.harvard.edu/full/1932JRASC..26...49S
|
||||
# </a>
|
||||
#
|
||||
# It includes the text below (starting on page 57):
|
||||
#
|
||||
# A list of the places in Canada using daylight saving time would
|
||||
# require yearly revision. From information kindly furnished by
|
||||
# the provincial governments and by the postmasters in many cities
|
||||
# and towns, it is found that the following places used daylight sav-
|
||||
# ing in 1930. The information for the province of Quebec is definite,
|
||||
# for the other provinces only approximate:
|
||||
#
|
||||
# Province Daylight saving time used
|
||||
# Prince Edward Island Not used.
|
||||
# Nova Scotia In Halifax only.
|
||||
# New Brunswick In St. John only.
|
||||
# Quebec In the following places:
|
||||
# Montreal Lachine
|
||||
# Quebec Mont-Royal
|
||||
# Levis Iberville
|
||||
# St. Lambert Cap de la Madeleine
|
||||
# Verdun Loretteville
|
||||
# Westmount Richmond
|
||||
# Outremont St. Jerome
|
||||
# Longueuil Greenfield Park
|
||||
# Arvida Waterloo
|
||||
# Chambly-Canton Beaulieu
|
||||
# Melbourne La Tuque
|
||||
# St. Theophile Buckingham
|
||||
# Ontario Used generally in the cities and towns along
|
||||
# the southerly part of the province. Not
|
||||
# used in the northwesterlhy part.
|
||||
# Manitoba Not used.
|
||||
# Saskatchewan In Regina only.
|
||||
# Alberta Not used.
|
||||
# British Columbia Not used.
|
||||
#
|
||||
# With some exceptions, the use of daylight saving may be said to be limited
|
||||
# to those cities and towns lying between Quebec city and Windsor, Ont.
|
||||
|
||||
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
|
||||
Rule Toronto 1919 only - Mar 30 23:30 1:00 D
|
||||
Rule Toronto 1919 only - Oct 26 0:00 0 S
|
||||
@ -2111,7 +2188,44 @@ Zone America/Hermosillo -7:23:52 - LMT 1921 Dec 31 23:36:08
|
||||
-8:00 - PST 1970
|
||||
-7:00 Mexico M%sT 1999
|
||||
-7:00 - MST
|
||||
|
||||
# From Alexander Krivenyshev (2010-04-21):
|
||||
# According to news, Bahía de Banderas (Mexican state of Nayarit)
|
||||
# changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
|
||||
# share the same time zone as nearby city Puerto Vallarta, Jalisco).
|
||||
#
|
||||
# (Spanish)
|
||||
# Bahía de Banderas homologa su horario al del centro del
|
||||
# país, a partir de este domingo
|
||||
# <a href="http://www.nayarit.gob.mx/notes.asp?id=20748">
|
||||
# http://www.nayarit.gob.mx/notes.asp?id=20748
|
||||
# </a>
|
||||
#
|
||||
# Bahía de Banderas homologa su horario con el del Centro del
|
||||
# País
|
||||
# <a href="http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50">
|
||||
# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
|
||||
# </a>
|
||||
#
|
||||
# (English)
|
||||
# Puerto Vallarta and Bahía de Banderas: One Time Zone
|
||||
# <a href="http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml">
|
||||
# http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
|
||||
# </a>
|
||||
#
|
||||
# or
|
||||
# <a href="http://www.worldtimezone.com/dst_news/dst_news_mexico08.html">
|
||||
# http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
|
||||
# </a>
|
||||
#
|
||||
# "Mexico's Senate approved the amendments to the Mexican Schedule System that
|
||||
# will allow Bahía de Banderas and Puerto Vallarta to share the same time
|
||||
# zone ..."
|
||||
# Baja California Sur, Nayarit, Sinaloa
|
||||
|
||||
# From Arthur David Olson (2010-05-01):
|
||||
# Use "Bahia_Banderas" to keep the name to fourteen characters.
|
||||
|
||||
Zone America/Mazatlan -7:05:40 - LMT 1921 Dec 31 23:54:20
|
||||
-7:00 - MST 1927 Jun 10 23:00
|
||||
-6:00 - CST 1930 Nov 15
|
||||
@ -2122,6 +2236,19 @@ Zone America/Mazatlan -7:05:40 - LMT 1921 Dec 31 23:54:20
|
||||
-7:00 - MST 1949 Jan 14
|
||||
-8:00 - PST 1970
|
||||
-7:00 Mexico M%sT
|
||||
|
||||
Zone America/Bahia_Banderas -7:01:00 - LMT 1921 Dec 31 23:59:00
|
||||
-7:00 - MST 1927 Jun 10 23:00
|
||||
-6:00 - CST 1930 Nov 15
|
||||
-7:00 - MST 1931 May 1 23:00
|
||||
-6:00 - CST 1931 Oct
|
||||
-7:00 - MST 1932 Apr 1
|
||||
-6:00 - CST 1942 Apr 24
|
||||
-7:00 - MST 1949 Jan 14
|
||||
-8:00 - PST 1970
|
||||
-7:00 Mexico M%sT 2010 Apr 4 2:00
|
||||
-6:00 Mexico C%sT
|
||||
|
||||
# Baja California (near US border)
|
||||
Zone America/Tijuana -7:48:04 - LMT 1922 Jan 1 0:11:56
|
||||
-7:00 - MST 1924
|
||||
|
@ -199,8 +199,8 @@ ET +0902+03842 Africa/Addis_Ababa
|
||||
FI +6010+02458 Europe/Helsinki
|
||||
FJ -1808+17825 Pacific/Fiji
|
||||
FK -5142-05751 Atlantic/Stanley
|
||||
FM +0725+15147 Pacific/Truk Truk (Chuuk) and Yap
|
||||
FM +0658+15813 Pacific/Ponape Ponape (Pohnpei)
|
||||
FM +0725+15147 Pacific/Chuuk Chuuk (Truk) and Yap
|
||||
FM +0658+15813 Pacific/Pohnpei Pohnpei (Ponape)
|
||||
FM +0519+16259 Pacific/Kosrae Kosrae
|
||||
FO +6201-00646 Atlantic/Faroe
|
||||
FR +4852+00220 Europe/Paris
|
||||
@ -310,6 +310,7 @@ MX +2934-10425 America/Ojinaga US Mountain Time - Chihuahua near US border
|
||||
MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora
|
||||
MX +3232-11701 America/Tijuana US Pacific Time - Baja California near US border
|
||||
MX +3018-11452 America/Santa_Isabel Mexican Pacific Time - Baja California away from US border
|
||||
MX +2048-10515 America/Bahia_Banderas Mexican Central Time - Bahia de Banderas
|
||||
MY +0310+10142 Asia/Kuala_Lumpur peninsular Malaysia
|
||||
MY +0133+11020 Asia/Kuching Sabah & Sarawak
|
||||
MZ -2558+03235 Africa/Maputo
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ package com.sun.java.util.jar.pack;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import com.sun.java.util.jar.pack.Package.Class;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.*;
|
||||
|
||||
/**
|
||||
@ -96,20 +95,20 @@ class Attribute implements Comparable, Constants {
|
||||
return this.def.compareTo(that.def);
|
||||
}
|
||||
|
||||
static private final byte[] noBytes = {};
|
||||
static private final HashMap canonLists = new HashMap();
|
||||
static private final HashMap attributes = new HashMap();
|
||||
static private final HashMap standardDefs = new HashMap();
|
||||
private static final byte[] noBytes = {};
|
||||
private static final Map<List<Attribute>, List<Attribute>> canonLists = new HashMap<>();
|
||||
private static final Map<Layout, Attribute> attributes = new HashMap<>();
|
||||
private static final Map<Layout, Attribute> standardDefs = new HashMap<>();
|
||||
|
||||
// Canonicalized lists of trivial attrs (Deprecated, etc.)
|
||||
// are used by trimToSize, in order to reduce footprint
|
||||
// of some common cases. (Note that Code attributes are
|
||||
// always zero size.)
|
||||
public static List getCanonList(List al) {
|
||||
public static List getCanonList(List<Attribute> al) {
|
||||
synchronized (canonLists) {
|
||||
List cl = (List) canonLists.get(al);
|
||||
List<Attribute> cl = canonLists.get(al);
|
||||
if (cl == null) {
|
||||
cl = new ArrayList(al.size());
|
||||
cl = new ArrayList<>(al.size());
|
||||
cl.addAll(al);
|
||||
cl = Collections.unmodifiableList(cl);
|
||||
canonLists.put(al, cl);
|
||||
@ -122,7 +121,7 @@ class Attribute implements Comparable, Constants {
|
||||
public static Attribute find(int ctype, String name, String layout) {
|
||||
Layout key = Layout.makeKey(ctype, name, layout);
|
||||
synchronized (attributes) {
|
||||
Attribute a = (Attribute) attributes.get(key);
|
||||
Attribute a = attributes.get(key);
|
||||
if (a == null) {
|
||||
a = new Layout(ctype, name, layout).canonicalInstance();
|
||||
attributes.put(key, a);
|
||||
@ -131,24 +130,29 @@ class Attribute implements Comparable, Constants {
|
||||
}
|
||||
}
|
||||
|
||||
public static Object keyForLookup(int ctype, String name) {
|
||||
public static Layout keyForLookup(int ctype, String name) {
|
||||
return Layout.makeKey(ctype, name);
|
||||
}
|
||||
|
||||
// Find canonical empty attribute with given ctype and name,
|
||||
// and with the standard layout.
|
||||
public static Attribute lookup(Map defs, int ctype, String name) {
|
||||
if (defs == null) defs = standardDefs;
|
||||
return (Attribute) defs.get(Layout.makeKey(ctype, name));
|
||||
public static Attribute lookup(Map<Layout, Attribute> defs, int ctype,
|
||||
String name) {
|
||||
if (defs == null) {
|
||||
defs = standardDefs;
|
||||
}
|
||||
return defs.get(Layout.makeKey(ctype, name));
|
||||
}
|
||||
public static Attribute define(Map defs, int ctype, String name, String layout) {
|
||||
|
||||
public static Attribute define(Map<Layout, Attribute> defs, int ctype,
|
||||
String name, String layout) {
|
||||
Attribute a = find(ctype, name, layout);
|
||||
defs.put(Layout.makeKey(ctype, name), a);
|
||||
return a;
|
||||
}
|
||||
|
||||
static {
|
||||
Map sd = standardDefs;
|
||||
Map<Layout, Attribute> sd = standardDefs;
|
||||
define(sd, ATTR_CONTEXT_CLASS, "Signature", "RSH");
|
||||
define(sd, ATTR_CONTEXT_CLASS, "Synthetic", "");
|
||||
define(sd, ATTR_CONTEXT_CLASS, "Deprecated", "");
|
||||
@ -244,7 +248,7 @@ class Attribute implements Comparable, Constants {
|
||||
+"\n ()[] ]"
|
||||
)
|
||||
};
|
||||
Map sd = standardDefs;
|
||||
Map<Layout, Attribute> sd = standardDefs;
|
||||
String defaultLayout = mdLayouts[2];
|
||||
String annotationsLayout = mdLayouts[1] + mdLayouts[2];
|
||||
String paramsLayout = mdLayouts[0] + annotationsLayout;
|
||||
@ -275,10 +279,6 @@ class Attribute implements Comparable, Constants {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Map getStandardDefs() {
|
||||
return new HashMap(standardDefs);
|
||||
}
|
||||
|
||||
/** Base class for any attributed object (Class, Field, Method, Code).
|
||||
* Flags are included because they are used to help transmit the
|
||||
* presence of attributes. That is, flags are a mix of modifier
|
||||
@ -291,7 +291,7 @@ class Attribute implements Comparable, Constants {
|
||||
protected abstract Entry[] getCPMap();
|
||||
|
||||
protected int flags; // defined here for convenience
|
||||
protected List attributes;
|
||||
protected List<Attribute> attributes;
|
||||
|
||||
public int attributeSize() {
|
||||
return (attributes == null) ? 0 : attributes.size();
|
||||
@ -301,16 +301,15 @@ class Attribute implements Comparable, Constants {
|
||||
if (attributes == null) {
|
||||
return;
|
||||
}
|
||||
if (attributes.size() == 0) {
|
||||
if (attributes.isEmpty()) {
|
||||
attributes = null;
|
||||
return;
|
||||
}
|
||||
if (attributes instanceof ArrayList) {
|
||||
ArrayList al = (ArrayList) attributes;
|
||||
ArrayList<Attribute> al = (ArrayList<Attribute>)attributes;
|
||||
al.trimToSize();
|
||||
boolean allCanon = true;
|
||||
for (Iterator i = al.iterator(); i.hasNext(); ) {
|
||||
Attribute a = (Attribute) i.next();
|
||||
for (Attribute a : al) {
|
||||
if (!a.isCanonical()) {
|
||||
allCanon = false;
|
||||
}
|
||||
@ -330,9 +329,9 @@ class Attribute implements Comparable, Constants {
|
||||
|
||||
public void addAttribute(Attribute a) {
|
||||
if (attributes == null)
|
||||
attributes = new ArrayList(3);
|
||||
attributes = new ArrayList<>(3);
|
||||
else if (!(attributes instanceof ArrayList))
|
||||
attributes = new ArrayList(attributes); // unfreeze it
|
||||
attributes = new ArrayList<>(attributes); // unfreeze it
|
||||
attributes.add(a);
|
||||
}
|
||||
|
||||
@ -340,32 +339,31 @@ class Attribute implements Comparable, Constants {
|
||||
if (attributes == null) return null;
|
||||
if (!attributes.contains(a)) return null;
|
||||
if (!(attributes instanceof ArrayList))
|
||||
attributes = new ArrayList(attributes); // unfreeze it
|
||||
attributes = new ArrayList<>(attributes); // unfreeze it
|
||||
attributes.remove(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
public Attribute getAttribute(int n) {
|
||||
return (Attribute) attributes.get(n);
|
||||
return attributes.get(n);
|
||||
}
|
||||
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
if (attributes == null) return;
|
||||
for (Iterator i = attributes.iterator(); i.hasNext(); ) {
|
||||
Attribute a = (Attribute) i.next();
|
||||
for (Attribute a : attributes) {
|
||||
a.visitRefs(this, mode, refs);
|
||||
}
|
||||
}
|
||||
|
||||
static final List noAttributes = Arrays.asList(new Object[0]);
|
||||
static final List<Attribute> noAttributes = Arrays.asList(new Attribute[0]);
|
||||
|
||||
public List getAttributes() {
|
||||
public List<Attribute> getAttributes() {
|
||||
if (attributes == null)
|
||||
return noAttributes;
|
||||
return attributes;
|
||||
}
|
||||
|
||||
public void setAttributes(List attrList) {
|
||||
public void setAttributes(List<Attribute> attrList) {
|
||||
if (attrList.isEmpty())
|
||||
attributes = null;
|
||||
else
|
||||
@ -374,8 +372,7 @@ class Attribute implements Comparable, Constants {
|
||||
|
||||
public Attribute getAttribute(String attrName) {
|
||||
if (attributes == null) return null;
|
||||
for (Iterator i = attributes.iterator(); i.hasNext(); ) {
|
||||
Attribute a = (Attribute) i.next();
|
||||
for (Attribute a : attributes) {
|
||||
if (a.name().equals(attrName))
|
||||
return a;
|
||||
}
|
||||
@ -384,8 +381,7 @@ class Attribute implements Comparable, Constants {
|
||||
|
||||
public Attribute getAttribute(Layout attrDef) {
|
||||
if (attributes == null) return null;
|
||||
for (Iterator i = attributes.iterator(); i.hasNext(); ) {
|
||||
Attribute a = (Attribute) i.next();
|
||||
for (Attribute a : attributes) {
|
||||
if (a.layout() == attrDef)
|
||||
return a;
|
||||
}
|
||||
@ -457,14 +453,8 @@ class Attribute implements Comparable, Constants {
|
||||
public String layout() { return layout; }
|
||||
public Attribute canonicalInstance() { return canon; }
|
||||
|
||||
// Cache of name reference.
|
||||
private Entry nameRef; // name, for use by visitRefs
|
||||
public Entry getNameRef() {
|
||||
Entry nameRef = this.nameRef;
|
||||
if (nameRef == null) {
|
||||
this.nameRef = nameRef = ConstantPool.getUtf8Entry(name());
|
||||
}
|
||||
return nameRef;
|
||||
return ConstantPool.getUtf8Entry(name());
|
||||
}
|
||||
|
||||
public boolean isEmpty() { return layout == ""; }
|
||||
@ -834,14 +824,14 @@ class Attribute implements Comparable, Constants {
|
||||
*/
|
||||
static //private
|
||||
Layout.Element[] tokenizeLayout(Layout self, int curCble, String layout) {
|
||||
ArrayList col = new ArrayList(layout.length());
|
||||
ArrayList<Layout.Element> col = new ArrayList<>(layout.length());
|
||||
tokenizeLayout(self, curCble, layout, col);
|
||||
Layout.Element[] res = new Layout.Element[col.size()];
|
||||
col.toArray(res);
|
||||
return res;
|
||||
}
|
||||
static //private
|
||||
void tokenizeLayout(Layout self, int curCble, String layout, ArrayList col) {
|
||||
void tokenizeLayout(Layout self, int curCble, String layout, ArrayList<Layout.Element> col) {
|
||||
boolean prevBCI = false;
|
||||
for (int len = layout.length(), i = 0; i < len; ) {
|
||||
int start = i;
|
||||
@ -899,7 +889,7 @@ class Attribute implements Comparable, Constants {
|
||||
case 'T': // union: 'T' any_int union_case* '(' ')' '[' body ']'
|
||||
kind = EK_UN;
|
||||
i = tokenizeSInt(e, layout, i);
|
||||
ArrayList cases = new ArrayList();
|
||||
ArrayList<Layout.Element> cases = new ArrayList<>();
|
||||
for (;;) {
|
||||
// Keep parsing cases until we hit the default case.
|
||||
if (layout.charAt(i++) != '(')
|
||||
@ -1053,7 +1043,7 @@ class Attribute implements Comparable, Constants {
|
||||
}
|
||||
static //private
|
||||
String[] splitBodies(String layout) {
|
||||
ArrayList bodies = new ArrayList();
|
||||
ArrayList<String> bodies = new ArrayList<>();
|
||||
// Parse several independent layout bodies: "[foo][bar]...[baz]"
|
||||
for (int i = 0; i < layout.length(); i++) {
|
||||
if (layout.charAt(i++) != '[')
|
||||
@ -1132,7 +1122,9 @@ class Attribute implements Comparable, Constants {
|
||||
int parseIntBefore(String layout, int dash) {
|
||||
int end = dash;
|
||||
int beg = end;
|
||||
while (beg > 0 && isDigit(layout.charAt(beg-1))) --beg;
|
||||
while (beg > 0 && isDigit(layout.charAt(beg-1))) {
|
||||
--beg;
|
||||
}
|
||||
if (beg == end) return Integer.parseInt("empty");
|
||||
// skip backward over a sign
|
||||
if (beg >= 1 && layout.charAt(beg-1) == '-') --beg;
|
||||
@ -1145,7 +1137,9 @@ class Attribute implements Comparable, Constants {
|
||||
int end = beg;
|
||||
int limit = layout.length();
|
||||
if (end < limit && layout.charAt(end) == '-') ++end;
|
||||
while (end < limit && isDigit(layout.charAt(end))) ++end;
|
||||
while (end < limit && isDigit(layout.charAt(end))) {
|
||||
++end;
|
||||
}
|
||||
if (beg == end) return Integer.parseInt("empty");
|
||||
return Integer.parseInt(layout.substring(beg, end));
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -40,20 +39,13 @@ class ConstantPool implements Constants {
|
||||
return Utils.currentPropMap().getInteger(Utils.DEBUG_VERBOSE);
|
||||
}
|
||||
|
||||
// Uniquification tables for factory methods:
|
||||
private static final HashMap utf8Entries = new HashMap();
|
||||
private static final HashMap classEntries = new HashMap();
|
||||
private static final HashMap literalEntries = new HashMap();
|
||||
private static final HashMap signatureEntries = new HashMap();
|
||||
private static final HashMap descriptorEntries = new HashMap();
|
||||
private static final HashMap memberEntries = new HashMap();
|
||||
|
||||
/** Factory for Utf8 string constants.
|
||||
* Used for well-known strings like "SourceFile", "<init>", etc.
|
||||
* Also used to back up more complex constant pool entries, like Class.
|
||||
*/
|
||||
public static synchronized Utf8Entry getUtf8Entry(String value) {
|
||||
Utf8Entry e = (Utf8Entry) utf8Entries.get(value);
|
||||
Map<String, Utf8Entry> utf8Entries = Utils.getUtf8Entries();
|
||||
Utf8Entry e = utf8Entries.get(value);
|
||||
if (e == null) {
|
||||
e = new Utf8Entry(value);
|
||||
utf8Entries.put(e.stringValue(), e);
|
||||
@ -62,9 +54,10 @@ class ConstantPool implements Constants {
|
||||
}
|
||||
/** Factory for Class constants. */
|
||||
public static synchronized ClassEntry getClassEntry(String name) {
|
||||
ClassEntry e = (ClassEntry) classEntries.get(name);
|
||||
Map<String, ClassEntry> classEntries = Utils.getClassEntries();
|
||||
ClassEntry e = classEntries.get(name);
|
||||
if (e == null) {
|
||||
e = (ClassEntry) new ClassEntry(getUtf8Entry(name));
|
||||
e = new ClassEntry(getUtf8Entry(name));
|
||||
assert(name.equals(e.stringValue()));
|
||||
classEntries.put(e.stringValue(), e);
|
||||
}
|
||||
@ -72,7 +65,8 @@ class ConstantPool implements Constants {
|
||||
}
|
||||
/** Factory for literal constants (String, Integer, etc.). */
|
||||
public static synchronized LiteralEntry getLiteralEntry(Comparable value) {
|
||||
LiteralEntry e = (LiteralEntry) literalEntries.get(value);
|
||||
Map<Object, LiteralEntry> literalEntries = Utils.getLiteralEntries();
|
||||
LiteralEntry e = literalEntries.get(value);
|
||||
if (e == null) {
|
||||
if (value instanceof String)
|
||||
e = new StringEntry(getUtf8Entry((String)value));
|
||||
@ -89,7 +83,8 @@ class ConstantPool implements Constants {
|
||||
|
||||
/** Factory for signature (type) constants. */
|
||||
public static synchronized SignatureEntry getSignatureEntry(String type) {
|
||||
SignatureEntry e = (SignatureEntry) signatureEntries.get(type);
|
||||
Map<String, SignatureEntry> signatureEntries = Utils.getSignatureEntries();
|
||||
SignatureEntry e = signatureEntries.get(type);
|
||||
if (e == null) {
|
||||
e = new SignatureEntry(type);
|
||||
assert(e.stringValue().equals(type));
|
||||
@ -104,8 +99,9 @@ class ConstantPool implements Constants {
|
||||
|
||||
/** Factory for descriptor (name-and-type) constants. */
|
||||
public static synchronized DescriptorEntry getDescriptorEntry(Utf8Entry nameRef, SignatureEntry typeRef) {
|
||||
Map<String, DescriptorEntry> descriptorEntries = Utils.getDescriptorEntries();
|
||||
String key = DescriptorEntry.stringValueOf(nameRef, typeRef);
|
||||
DescriptorEntry e = (DescriptorEntry) descriptorEntries.get(key);
|
||||
DescriptorEntry e = descriptorEntries.get(key);
|
||||
if (e == null) {
|
||||
e = new DescriptorEntry(nameRef, typeRef);
|
||||
assert(e.stringValue().equals(key))
|
||||
@ -121,8 +117,9 @@ class ConstantPool implements Constants {
|
||||
|
||||
/** Factory for member reference constants. */
|
||||
public static synchronized MemberEntry getMemberEntry(byte tag, ClassEntry classRef, DescriptorEntry descRef) {
|
||||
Map<String, MemberEntry> memberEntries = Utils.getMemberEntries();
|
||||
String key = MemberEntry.stringValueOf(tag, classRef, descRef);
|
||||
MemberEntry e = (MemberEntry) memberEntries.get(key);
|
||||
MemberEntry e = memberEntries.get(key);
|
||||
if (e == null) {
|
||||
e = new MemberEntry(tag, classRef, descRef);
|
||||
assert(e.stringValue().equals(key))
|
||||
@ -489,8 +486,9 @@ class ConstantPool implements Constants {
|
||||
String[] parts = structureSignature(value);
|
||||
formRef = getUtf8Entry(parts[0]);
|
||||
classRefs = new ClassEntry[parts.length-1];
|
||||
for (int i = 1; i < parts.length; i++)
|
||||
classRefs[i-1] = getClassEntry(parts[i]);
|
||||
for (int i = 1; i < parts.length; i++) {
|
||||
classRefs[i - 1] = getClassEntry(parts[i]);
|
||||
}
|
||||
hashCode(); // force computation of valueHash
|
||||
}
|
||||
protected int computeValueHash() {
|
||||
@ -527,8 +525,9 @@ class ConstantPool implements Constants {
|
||||
String stringValueOf(Utf8Entry formRef, ClassEntry[] classRefs) {
|
||||
String[] parts = new String[1+classRefs.length];
|
||||
parts[0] = formRef.stringValue();
|
||||
for (int i = 1; i < parts.length; i++)
|
||||
parts[i] = classRefs[i-1].stringValue();
|
||||
for (int i = 1; i < parts.length; i++) {
|
||||
parts[i] = classRefs[i - 1].stringValue();
|
||||
}
|
||||
return flattenSignature(parts).intern();
|
||||
}
|
||||
|
||||
@ -543,19 +542,23 @@ class ConstantPool implements Constants {
|
||||
int size = 0;
|
||||
for (int i = min; i < max; i++) {
|
||||
switch (form.charAt(i)) {
|
||||
case 'D':
|
||||
case 'J':
|
||||
if (countDoublesTwice) size++;
|
||||
break;
|
||||
case '[':
|
||||
// Skip rest of array info.
|
||||
while (form.charAt(i) == '[') ++i;
|
||||
break;
|
||||
case ';':
|
||||
continue;
|
||||
default:
|
||||
assert(0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
|
||||
break;
|
||||
case 'D':
|
||||
case 'J':
|
||||
if (countDoublesTwice) {
|
||||
size++;
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
// Skip rest of array info.
|
||||
while (form.charAt(i) == '[') {
|
||||
++i;
|
||||
}
|
||||
break;
|
||||
case ';':
|
||||
continue;
|
||||
default:
|
||||
assert (0 <= JAVA_SIGNATURE_CHARS.indexOf(form.charAt(i)));
|
||||
break;
|
||||
}
|
||||
size++;
|
||||
}
|
||||
@ -586,8 +589,9 @@ class ConstantPool implements Constants {
|
||||
s = "/" + formRef.stringValue();
|
||||
}
|
||||
int i;
|
||||
while ((i = s.indexOf(';')) >= 0)
|
||||
s = s.substring(0,i) + s.substring(i+1);
|
||||
while ((i = s.indexOf(';')) >= 0) {
|
||||
s = s.substring(0, i) + s.substring(i + 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@ -732,11 +736,11 @@ class ConstantPool implements Constants {
|
||||
clearIndex();
|
||||
this.cpMap = cpMap;
|
||||
}
|
||||
protected Index(String debugName, Collection cpMapList) {
|
||||
protected Index(String debugName, Collection<Entry> cpMapList) {
|
||||
this(debugName);
|
||||
setMap(cpMapList);
|
||||
}
|
||||
protected void setMap(Collection cpMapList) {
|
||||
protected void setMap(Collection<Entry> cpMapList) {
|
||||
cpMap = new Entry[cpMapList.size()];
|
||||
cpMapList.toArray(cpMap);
|
||||
setMap(cpMap);
|
||||
@ -756,11 +760,13 @@ class ConstantPool implements Constants {
|
||||
//
|
||||
// As a special hack, if flattenSigs, signatures are
|
||||
// treated as equivalent entries of cpMap. This is wrong
|
||||
// fron a Collection point of view, because contains()
|
||||
// from a Collection point of view, because contains()
|
||||
// reports true for signatures, but the iterator()
|
||||
// never produces them!
|
||||
private int findIndexOf(Entry e) {
|
||||
if (indexKey == null) initializeIndex();
|
||||
if (indexKey == null) {
|
||||
initializeIndex();
|
||||
}
|
||||
int probe = findIndexLocation(e);
|
||||
if (indexKey[probe] != e) {
|
||||
if (flattenSigs && e.tag == CONSTANT_Signature) {
|
||||
@ -832,7 +838,9 @@ class ConstantPool implements Constants {
|
||||
System.out.println("initialize Index "+debugName+" ["+size()+"]");
|
||||
int hsize0 = (int)((cpMap.length + 10) * 1.5);
|
||||
int hsize = 1;
|
||||
while (hsize < hsize0) hsize <<= 1;
|
||||
while (hsize < hsize0) {
|
||||
hsize <<= 1;
|
||||
}
|
||||
indexKey = new Entry[hsize];
|
||||
indexValue = new int[hsize];
|
||||
for (int i = 0; i < cpMap.length; i++) {
|
||||
@ -855,7 +863,7 @@ class ConstantPool implements Constants {
|
||||
return toArray(new Entry[size()]);
|
||||
}
|
||||
public Object clone() {
|
||||
return new Index(debugName, (Entry[]) cpMap.clone());
|
||||
return new Index(debugName, cpMap.clone());
|
||||
}
|
||||
public String toString() {
|
||||
return "Index "+debugName+" ["+size()+"]";
|
||||
@ -901,22 +909,24 @@ class ConstantPool implements Constants {
|
||||
public static
|
||||
Index[] partition(Index ix, int[] keys) {
|
||||
// %%% Should move this into class Index.
|
||||
ArrayList parts = new ArrayList();
|
||||
ArrayList<List<Entry>> parts = new ArrayList<>();
|
||||
Entry[] cpMap = ix.cpMap;
|
||||
assert(keys.length == cpMap.length);
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
int key = keys[i];
|
||||
if (key < 0) continue;
|
||||
while (key >= parts.size()) parts.add(null);
|
||||
ArrayList part = (ArrayList) parts.get(key);
|
||||
while (key >= parts.size()) {
|
||||
parts.add(null);
|
||||
}
|
||||
List<Entry> part = parts.get(key);
|
||||
if (part == null) {
|
||||
parts.set(key, part = new ArrayList());
|
||||
parts.set(key, part = new ArrayList<>());
|
||||
}
|
||||
part.add(cpMap[i]);
|
||||
}
|
||||
Index[] indexes = new Index[parts.size()];
|
||||
for (int key = 0; key < indexes.length; key++) {
|
||||
ArrayList part = (ArrayList) parts.get(key);
|
||||
List<Entry> part = parts.get(key);
|
||||
if (part == null) continue;
|
||||
indexes[key] = new Index(ix.debugName+"/part#"+key, part);
|
||||
assert(indexes[key].indexOf(part.get(0)) == 0);
|
||||
@ -1048,9 +1058,10 @@ class ConstantPool implements Constants {
|
||||
whichClasses[i] = whichClass;
|
||||
}
|
||||
perClassIndexes = partition(allMembers, whichClasses);
|
||||
for (int i = 0; i < perClassIndexes.length; i++)
|
||||
assert(perClassIndexes[i]==null
|
||||
|| perClassIndexes[i].assertIsSorted());
|
||||
for (int i = 0; i < perClassIndexes.length; i++) {
|
||||
assert (perClassIndexes[i] == null ||
|
||||
perClassIndexes[i].assertIsSorted());
|
||||
}
|
||||
indexByTagAndClass[tag] = perClassIndexes;
|
||||
}
|
||||
int whichClass = allClasses.indexOf(classRef);
|
||||
@ -1113,7 +1124,7 @@ class ConstantPool implements Constants {
|
||||
* Also, discard null from cpRefs.
|
||||
*/
|
||||
public static
|
||||
void completeReferencesIn(Set cpRefs, boolean flattenSigs) {
|
||||
void completeReferencesIn(Set<Entry> cpRefs, boolean flattenSigs) {
|
||||
cpRefs.remove(null);
|
||||
for (ListIterator work =
|
||||
new ArrayList(cpRefs).listIterator(cpRefs.size());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,7 +25,6 @@
|
||||
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import java.lang.Error;
|
||||
import java.io.*;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
@ -35,10 +34,11 @@ import java.util.zip.*;
|
||||
/** Command line interface for Pack200.
|
||||
*/
|
||||
class Driver {
|
||||
private static final ResourceBundle RESOURCE= ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
|
||||
private static final ResourceBundle RESOURCE =
|
||||
ResourceBundle.getBundle("com.sun.java.util.jar.pack.DriverResource");
|
||||
|
||||
public static void main(String[] ava) throws IOException {
|
||||
ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
|
||||
ArrayList<String> av = new ArrayList<>(Arrays.asList(ava));
|
||||
|
||||
boolean doPack = true;
|
||||
boolean doUnpack = false;
|
||||
@ -61,7 +61,7 @@ class Driver {
|
||||
}
|
||||
|
||||
// Collect engine properties here:
|
||||
HashMap<String,String> engProps = new HashMap<String,String>();
|
||||
HashMap<String,String> engProps = new HashMap<>();
|
||||
engProps.put(verboseProp, System.getProperty(verboseProp));
|
||||
|
||||
String optionMap;
|
||||
@ -75,7 +75,7 @@ class Driver {
|
||||
}
|
||||
|
||||
// Collect argument properties here:
|
||||
HashMap<String,String> avProps = new HashMap<String,String>();
|
||||
HashMap<String,String> avProps = new HashMap<>();
|
||||
try {
|
||||
for (;;) {
|
||||
String state = parseCommandOptions(av, optionMap, avProps);
|
||||
@ -133,8 +133,9 @@ class Driver {
|
||||
if (engProps.get(verboseProp) != null)
|
||||
fileProps.list(System.out);
|
||||
propIn.close();
|
||||
for (Map.Entry<Object,Object> me : fileProps.entrySet())
|
||||
engProps.put((String)me.getKey(), (String)me.getValue());
|
||||
for (Map.Entry<Object,Object> me : fileProps.entrySet()) {
|
||||
engProps.put((String) me.getKey(), (String) me.getValue());
|
||||
}
|
||||
} else if (state == "--version") {
|
||||
System.out.println(MessageFormat.format(RESOURCE.getString(DriverResource.VERSION), Driver.class.getName(), "1.31, 07/05/05"));
|
||||
return;
|
||||
@ -493,7 +494,7 @@ class Driver {
|
||||
String resultString = null;
|
||||
|
||||
// Convert options string into optLines dictionary.
|
||||
TreeMap<String,String[]> optmap = new TreeMap<String,String[]>();
|
||||
TreeMap<String,String[]> optmap = new TreeMap<>();
|
||||
loadOptmap:
|
||||
for (String optline : options.split("\n")) {
|
||||
String[] words = optline.split("\\p{Space}+");
|
||||
@ -687,7 +688,9 @@ class Driver {
|
||||
// Report number of arguments consumed.
|
||||
args.subList(0, argp.nextIndex()).clear();
|
||||
// Report any unconsumed partial argument.
|
||||
while (pbp.hasPrevious()) args.add(0, pbp.previous());
|
||||
while (pbp.hasPrevious()) {
|
||||
args.add(0, pbp.previous());
|
||||
}
|
||||
//System.out.println(args+" // "+properties+" -> "+resultString);
|
||||
return resultString;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,13 +28,8 @@ package com.sun.java.util.jar.pack;
|
||||
|
||||
import java.nio.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Date;
|
||||
import java.util.jar.*;
|
||||
import java.util.zip.*;
|
||||
import java.util.*;
|
||||
//import com.sun.java.util.jar.pack.Pack200;
|
||||
|
||||
|
||||
class NativeUnpack {
|
||||
// Pointer to the native unpacker obj
|
||||
@ -91,13 +86,13 @@ class NativeUnpack {
|
||||
NativeUnpack(UnpackerImpl p200) {
|
||||
super();
|
||||
_p200 = p200;
|
||||
_props = p200._props;
|
||||
_props = p200.props;
|
||||
p200._nunp = this;
|
||||
}
|
||||
|
||||
// for JNI callbacks
|
||||
static private Object currentInstance() {
|
||||
UnpackerImpl p200 = (UnpackerImpl) Utils.currentInstance.get();
|
||||
UnpackerImpl p200 = (UnpackerImpl) Utils.getTLGlobals();
|
||||
return (p200 == null)? null: p200._nunp;
|
||||
}
|
||||
|
||||
@ -216,10 +211,10 @@ class NativeUnpack {
|
||||
++_fileCount;
|
||||
updateProgress();
|
||||
}
|
||||
presetInput = getUnusedInput();
|
||||
long consumed = finish();
|
||||
if (_verbose > 0)
|
||||
Utils.log.info("bytes consumed = "+consumed);
|
||||
presetInput = getUnusedInput();
|
||||
if (presetInput == null &&
|
||||
!Utils.isPackMagic(Utils.readMagic(in))) {
|
||||
break;
|
||||
|
@ -25,9 +25,9 @@
|
||||
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import com.sun.java.util.jar.pack.Attribute.Layout;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.util.jar.*;
|
||||
import java.io.*;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.*;
|
||||
@ -77,10 +77,11 @@ class Package implements Constants {
|
||||
cp = new ConstantPool.IndexGroup();
|
||||
classes.clear();
|
||||
files.clear();
|
||||
BandStructure.nextSeqForDebug = 0;
|
||||
}
|
||||
|
||||
int getPackageVersion() {
|
||||
return (package_majver << 16) + (int)package_minver;
|
||||
return (package_majver << 16) + package_minver;
|
||||
}
|
||||
|
||||
// Special empty versions of Code and InnerClasses, used for markers.
|
||||
@ -89,7 +90,7 @@ class Package implements Constants {
|
||||
public static final Attribute.Layout attrSourceFileSpecial;
|
||||
public static final Map attrDefs;
|
||||
static {
|
||||
HashMap ad = new HashMap(2);
|
||||
HashMap<Layout, Attribute> ad = new HashMap<>(3);
|
||||
attrCodeEmpty = Attribute.define(ad, ATTR_CONTEXT_METHOD,
|
||||
"Code", "").layout();
|
||||
attrInnerClassesEmpty = Attribute.define(ad, ATTR_CONTEXT_CLASS,
|
||||
@ -159,9 +160,9 @@ class Package implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList classes = new ArrayList();
|
||||
ArrayList<Package.Class> classes = new ArrayList<>();
|
||||
|
||||
public List getClasses() {
|
||||
public List<Package.Class> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@ -186,11 +187,11 @@ class Package implements Constants {
|
||||
ClassEntry[] interfaces;
|
||||
|
||||
// Class parts
|
||||
ArrayList fields;
|
||||
ArrayList methods;
|
||||
ArrayList<Field> fields;
|
||||
ArrayList<Method> methods;
|
||||
//ArrayList attributes; // in Attribute.Holder.this.attributes
|
||||
// Note that InnerClasses may be collected at the package level.
|
||||
ArrayList innerClasses;
|
||||
ArrayList<InnerClass> innerClasses;
|
||||
|
||||
Class(int flags, ClassEntry thisClass, ClassEntry superClass, ClassEntry[] interfaces) {
|
||||
this.magic = JAVA_MAGIC;
|
||||
@ -270,7 +271,7 @@ class Package implements Constants {
|
||||
if (a != olda) {
|
||||
if (verbose > 2)
|
||||
Utils.log.fine("recoding obvious SourceFile="+obvious);
|
||||
List newAttrs = new ArrayList(getAttributes());
|
||||
List<Attribute> newAttrs = new ArrayList<>(getAttributes());
|
||||
int where = newAttrs.indexOf(olda);
|
||||
newAttrs.set(where, a);
|
||||
setAttributes(newAttrs);
|
||||
@ -295,12 +296,12 @@ class Package implements Constants {
|
||||
boolean hasInnerClasses() {
|
||||
return innerClasses != null;
|
||||
}
|
||||
List getInnerClasses() {
|
||||
List<InnerClass> getInnerClasses() {
|
||||
return innerClasses;
|
||||
}
|
||||
|
||||
public void setInnerClasses(Collection ics) {
|
||||
innerClasses = (ics == null) ? null : new ArrayList(ics);
|
||||
public void setInnerClasses(Collection<InnerClass> ics) {
|
||||
innerClasses = (ics == null) ? null : new ArrayList<InnerClass>(ics);
|
||||
// Edit the attribute list, if necessary.
|
||||
Attribute a = getAttribute(attrInnerClassesEmpty);
|
||||
if (innerClasses != null && a == null)
|
||||
@ -318,19 +319,18 @@ class Package implements Constants {
|
||||
* The order of the resulting list is consistent
|
||||
* with that of Package.this.allInnerClasses.
|
||||
*/
|
||||
public List computeGloballyImpliedICs() {
|
||||
HashSet cpRefs = new HashSet();
|
||||
public List<InnerClass> computeGloballyImpliedICs() {
|
||||
HashSet<Entry> cpRefs = new HashSet<>();
|
||||
{ // This block temporarily displaces this.innerClasses.
|
||||
ArrayList innerClassesSaved = innerClasses;
|
||||
ArrayList<InnerClass> innerClassesSaved = innerClasses;
|
||||
innerClasses = null; // ignore for the moment
|
||||
visitRefs(VRM_CLASSIC, cpRefs);
|
||||
innerClasses = innerClassesSaved;
|
||||
}
|
||||
ConstantPool.completeReferencesIn(cpRefs, true);
|
||||
|
||||
HashSet icRefs = new HashSet();
|
||||
for (Iterator i = cpRefs.iterator(); i.hasNext(); ) {
|
||||
Entry e = (Entry) i.next();
|
||||
HashSet<Entry> icRefs = new HashSet<>();
|
||||
for (Entry e : cpRefs) {
|
||||
// Restrict cpRefs to InnerClasses entries only.
|
||||
if (!(e instanceof ClassEntry)) continue;
|
||||
// For every IC reference, add its outers also.
|
||||
@ -345,9 +345,8 @@ class Package implements Constants {
|
||||
// This loop is structured this way so as to accumulate
|
||||
// entries into impliedICs in an order which reflects
|
||||
// the order of allInnerClasses.
|
||||
ArrayList impliedICs = new ArrayList();
|
||||
for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) {
|
||||
InnerClass ic = (InnerClass) i.next();
|
||||
ArrayList<InnerClass> impliedICs = new ArrayList<>();
|
||||
for (InnerClass ic : allInnerClasses) {
|
||||
// This one is locally relevant if it describes
|
||||
// a member of the current class, or if the current
|
||||
// class uses it somehow. In the particular case
|
||||
@ -366,10 +365,11 @@ class Package implements Constants {
|
||||
|
||||
// Helper for both minimizing and expanding.
|
||||
// Computes a symmetric difference.
|
||||
private List computeICdiff() {
|
||||
List impliedICs = computeGloballyImpliedICs();
|
||||
List actualICs = getInnerClasses();
|
||||
if (actualICs == null) actualICs = Collections.EMPTY_LIST;
|
||||
private List<InnerClass> computeICdiff() {
|
||||
List<InnerClass> impliedICs = computeGloballyImpliedICs();
|
||||
List<InnerClass> actualICs = getInnerClasses();
|
||||
if (actualICs == null)
|
||||
actualICs = Collections.EMPTY_LIST;
|
||||
|
||||
// Symmetric difference is calculated from I, A like this:
|
||||
// diff = (I+A) - (I*A)
|
||||
@ -388,8 +388,8 @@ class Package implements Constants {
|
||||
// Diff is A since I is empty.
|
||||
}
|
||||
// (I*A) is non-trivial
|
||||
HashSet center = new HashSet(actualICs);
|
||||
center.retainAll(new HashSet(impliedICs));
|
||||
HashSet<InnerClass> center = new HashSet<>(actualICs);
|
||||
center.retainAll(new HashSet<>(impliedICs));
|
||||
impliedICs.addAll(actualICs);
|
||||
impliedICs.removeAll(center);
|
||||
// Diff is now I^A = (I+A)-(I*A).
|
||||
@ -407,9 +407,9 @@ class Package implements Constants {
|
||||
* to use the globally implied ICs changed.
|
||||
*/
|
||||
void minimizeLocalICs() {
|
||||
List diff = computeICdiff();
|
||||
List actualICs = innerClasses;
|
||||
List localICs; // will be the diff, modulo edge cases
|
||||
List<InnerClass> diff = computeICdiff();
|
||||
List<InnerClass> actualICs = innerClasses;
|
||||
List<InnerClass> localICs; // will be the diff, modulo edge cases
|
||||
if (diff.isEmpty()) {
|
||||
// No diff, so transmit no attribute.
|
||||
localICs = null;
|
||||
@ -439,12 +439,12 @@ class Package implements Constants {
|
||||
* Otherwise, return positive if any IC tuples were added.
|
||||
*/
|
||||
int expandLocalICs() {
|
||||
List localICs = innerClasses;
|
||||
List actualICs;
|
||||
List<InnerClass> localICs = innerClasses;
|
||||
List<InnerClass> actualICs;
|
||||
int changed;
|
||||
if (localICs == null) {
|
||||
// Diff was empty. (Common case.)
|
||||
List impliedICs = computeGloballyImpliedICs();
|
||||
List<InnerClass> impliedICs = computeGloballyImpliedICs();
|
||||
if (impliedICs.isEmpty()) {
|
||||
actualICs = null;
|
||||
changed = 0;
|
||||
@ -490,7 +490,7 @@ class Package implements Constants {
|
||||
protected Entry[] getCPMap() {
|
||||
return cpMap;
|
||||
}
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
if (verbose > 2) Utils.log.fine("visitRefs "+this);
|
||||
// Careful: The descriptor is used by the package,
|
||||
// but the classfile breaks it into component refs.
|
||||
@ -518,7 +518,7 @@ class Package implements Constants {
|
||||
super(flags, descriptor);
|
||||
assert(!descriptor.isMethod());
|
||||
if (fields == null)
|
||||
fields = new ArrayList();
|
||||
fields = new ArrayList<>();
|
||||
boolean added = fields.add(this);
|
||||
assert(added);
|
||||
order = fields.size();
|
||||
@ -543,7 +543,7 @@ class Package implements Constants {
|
||||
super(flags, descriptor);
|
||||
assert(descriptor.isMethod());
|
||||
if (methods == null)
|
||||
methods = new ArrayList();
|
||||
methods = new ArrayList<>();
|
||||
boolean added = methods.add(this);
|
||||
assert(added);
|
||||
}
|
||||
@ -573,7 +573,7 @@ class Package implements Constants {
|
||||
code.strip(attrName);
|
||||
super.strip(attrName);
|
||||
}
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
super.visitRefs(mode, refs);
|
||||
if (code != null) {
|
||||
if (mode == VRM_CLASSIC) {
|
||||
@ -614,7 +614,7 @@ class Package implements Constants {
|
||||
super.strip(attrName);
|
||||
}
|
||||
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
if (verbose > 2) Utils.log.fine("visitRefs "+this);
|
||||
refs.add(thisClass);
|
||||
refs.add(superClass);
|
||||
@ -641,7 +641,7 @@ class Package implements Constants {
|
||||
super.visitRefs(mode, refs);
|
||||
}
|
||||
|
||||
protected void visitInnerClassRefs(int mode, Collection refs) {
|
||||
protected void visitInnerClassRefs(int mode, Collection<Entry> refs) {
|
||||
Package.visitInnerClassRefs(innerClasses, mode, refs);
|
||||
}
|
||||
|
||||
@ -713,16 +713,15 @@ class Package implements Constants {
|
||||
}
|
||||
|
||||
// What non-class files are in this unit?
|
||||
ArrayList files = new ArrayList();
|
||||
ArrayList<File> files = new ArrayList<>();
|
||||
|
||||
public List getFiles() {
|
||||
public List<File> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public List getClassStubs() {
|
||||
ArrayList classStubs = new ArrayList(classes.size());
|
||||
for (Iterator i = classes.iterator(); i.hasNext(); ) {
|
||||
Class cls = (Class) i.next();
|
||||
public List<File> getClassStubs() {
|
||||
ArrayList<File> classStubs = new ArrayList<>(classes.size());
|
||||
for (Class cls : classes) {
|
||||
assert(cls.file.isClassStub());
|
||||
classStubs.add(cls.file);
|
||||
}
|
||||
@ -840,7 +839,7 @@ class Package implements Constants {
|
||||
public InputStream getInputStream() {
|
||||
InputStream in = new ByteArrayInputStream(append.toByteArray());
|
||||
if (prepend.size() == 0) return in;
|
||||
ArrayList isa = new ArrayList(prepend.size()+1);
|
||||
ArrayList<InputStream> isa = new ArrayList<>(prepend.size()+1);
|
||||
for (Iterator i = prepend.iterator(); i.hasNext(); ) {
|
||||
byte[] bytes = (byte[]) i.next();
|
||||
isa.add(new ByteArrayInputStream(bytes));
|
||||
@ -849,7 +848,7 @@ class Package implements Constants {
|
||||
return new SequenceInputStream(Collections.enumeration(isa));
|
||||
}
|
||||
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
assert(name != null);
|
||||
refs.add(name);
|
||||
}
|
||||
@ -877,8 +876,8 @@ class Package implements Constants {
|
||||
}
|
||||
|
||||
// Is there a globally declared table of inner classes?
|
||||
ArrayList allInnerClasses = new ArrayList();
|
||||
HashMap allInnerClassesByThis;
|
||||
ArrayList<InnerClass> allInnerClasses = new ArrayList<>();
|
||||
HashMap<ClassEntry, InnerClass> allInnerClassesByThis;
|
||||
|
||||
public
|
||||
List getAllInnerClasses() {
|
||||
@ -886,15 +885,14 @@ class Package implements Constants {
|
||||
}
|
||||
|
||||
public
|
||||
void setAllInnerClasses(Collection ics) {
|
||||
void setAllInnerClasses(Collection<InnerClass> ics) {
|
||||
assert(ics != allInnerClasses);
|
||||
allInnerClasses.clear();
|
||||
allInnerClasses.addAll(ics);
|
||||
|
||||
// Make an index:
|
||||
allInnerClassesByThis = new HashMap(allInnerClasses.size());
|
||||
for (Iterator i = allInnerClasses.iterator(); i.hasNext(); ) {
|
||||
InnerClass ic = (InnerClass) i.next();
|
||||
allInnerClassesByThis = new HashMap<>(allInnerClasses.size());
|
||||
for (InnerClass ic : allInnerClasses) {
|
||||
Object pic = allInnerClassesByThis.put(ic.thisClass, ic);
|
||||
assert(pic == null); // caller must ensure key uniqueness!
|
||||
}
|
||||
@ -904,7 +902,7 @@ class Package implements Constants {
|
||||
public
|
||||
InnerClass getGlobalInnerClass(Entry thisClass) {
|
||||
assert(thisClass instanceof ClassEntry);
|
||||
return (InnerClass) allInnerClassesByThis.get(thisClass);
|
||||
return allInnerClassesByThis.get(thisClass);
|
||||
}
|
||||
|
||||
static
|
||||
@ -963,7 +961,7 @@ class Package implements Constants {
|
||||
return this.thisClass.compareTo(that.thisClass);
|
||||
}
|
||||
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
refs.add(thisClass);
|
||||
if (mode == VRM_CLASSIC || !predictable) {
|
||||
// If the name can be demangled, the package omits
|
||||
@ -980,7 +978,7 @@ class Package implements Constants {
|
||||
|
||||
// Helper for building InnerClasses attributes.
|
||||
static private
|
||||
void visitInnerClassRefs(Collection innerClasses, int mode, Collection refs) {
|
||||
void visitInnerClassRefs(Collection innerClasses, int mode, Collection<Entry> refs) {
|
||||
if (innerClasses == null) {
|
||||
return; // no attribute; nothing to do
|
||||
}
|
||||
@ -1165,9 +1163,8 @@ class Package implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
protected void visitRefs(int mode, Collection refs) {
|
||||
for (Iterator i = classes.iterator(); i.hasNext(); ) {
|
||||
Class c = (Class)i.next();
|
||||
protected void visitRefs(int mode, Collection<Entry> refs) {
|
||||
for ( Class c : classes) {
|
||||
c.visitRefs(mode, refs);
|
||||
}
|
||||
if (mode != VRM_CLASSIC) {
|
||||
@ -1259,7 +1256,7 @@ class Package implements Constants {
|
||||
}
|
||||
|
||||
// Use this before writing the package file.
|
||||
void buildGlobalConstantPool(Set requiredEntries) {
|
||||
void buildGlobalConstantPool(Set<Entry> requiredEntries) {
|
||||
if (verbose > 1)
|
||||
Utils.log.fine("Checking for unused CP entries");
|
||||
requiredEntries.add(getRefString("")); // uconditionally present
|
||||
@ -1291,9 +1288,8 @@ class Package implements Constants {
|
||||
|
||||
// Use this before writing the class files.
|
||||
void ensureAllClassFiles() {
|
||||
HashSet fileSet = new HashSet(files);
|
||||
for (Iterator i = classes.iterator(); i.hasNext(); ) {
|
||||
Class cls = (Class) i.next();
|
||||
HashSet<File> fileSet = new HashSet<>(files);
|
||||
for (Class cls : classes) {
|
||||
// Add to the end of ths list:
|
||||
if (!fileSet.contains(cls.file))
|
||||
files.add(cls.file);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,12 +25,11 @@
|
||||
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import com.sun.java.util.jar.pack.Attribute.Layout;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.zip.*;
|
||||
import java.io.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
||||
|
||||
/*
|
||||
@ -41,31 +40,22 @@ import java.beans.PropertyChangeEvent;
|
||||
*/
|
||||
|
||||
|
||||
public class PackerImpl implements Pack200.Packer {
|
||||
public class PackerImpl extends TLGlobals implements Pack200.Packer {
|
||||
|
||||
/**
|
||||
* Constructs a Packer object and sets the initial state of
|
||||
* the packer engines.
|
||||
*/
|
||||
public PackerImpl() {
|
||||
_props = new PropMap();
|
||||
//_props.getProperty() consults defaultProps invisibly.
|
||||
//_props.putAll(defaultProps);
|
||||
}
|
||||
|
||||
|
||||
// Private stuff.
|
||||
final PropMap _props;
|
||||
public PackerImpl() {}
|
||||
|
||||
/**
|
||||
* Get the set of options for the pack and unpack engines.
|
||||
* @return A sorted association of option key strings to option values.
|
||||
*/
|
||||
public SortedMap properties() {
|
||||
return _props;
|
||||
public SortedMap<String, String> properties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
//Driver routines
|
||||
|
||||
/**
|
||||
@ -78,21 +68,22 @@ public class PackerImpl implements Pack200.Packer {
|
||||
*/
|
||||
public void pack(JarFile in, OutputStream out) throws IOException {
|
||||
assert(Utils.currentInstance.get() == null);
|
||||
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
|
||||
TimeZone.getDefault();
|
||||
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
|
||||
? null
|
||||
: TimeZone.getDefault();
|
||||
try {
|
||||
Utils.currentInstance.set(this);
|
||||
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) {
|
||||
if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
|
||||
Utils.copyJarFile(in, out);
|
||||
} else {
|
||||
(new DoPack()).run(in, out);
|
||||
in.close();
|
||||
}
|
||||
} finally {
|
||||
Utils.currentInstance.set(null);
|
||||
if (tz != null) TimeZone.setDefault(tz);
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,21 +103,20 @@ public class PackerImpl implements Pack200.Packer {
|
||||
*/
|
||||
public void pack(JarInputStream in, OutputStream out) throws IOException {
|
||||
assert(Utils.currentInstance.get() == null);
|
||||
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
|
||||
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
|
||||
TimeZone.getDefault();
|
||||
try {
|
||||
Utils.currentInstance.set(this);
|
||||
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||
if ("0".equals(_props.getProperty(Pack200.Packer.EFFORT))) {
|
||||
if ("0".equals(props.getProperty(Pack200.Packer.EFFORT))) {
|
||||
Utils.copyJarFile(in, out);
|
||||
} else {
|
||||
(new DoPack()).run(in, out);
|
||||
in.close();
|
||||
}
|
||||
} finally {
|
||||
Utils.currentInstance.set(null);
|
||||
if (tz != null) TimeZone.setDefault(tz);
|
||||
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
/**
|
||||
@ -134,7 +124,7 @@ public class PackerImpl implements Pack200.Packer {
|
||||
* @param listener An object to be invoked when a property is changed.
|
||||
*/
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
_props.addListener(listener);
|
||||
props.addListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -142,7 +132,7 @@ public class PackerImpl implements Pack200.Packer {
|
||||
* @param listener The PropertyChange listener to be removed.
|
||||
*/
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
_props.removeListener(listener);
|
||||
props.removeListener(listener);
|
||||
}
|
||||
|
||||
|
||||
@ -151,11 +141,11 @@ public class PackerImpl implements Pack200.Packer {
|
||||
|
||||
// The packer worker.
|
||||
private class DoPack {
|
||||
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
|
||||
{
|
||||
_props.setInteger(Pack200.Packer.PROGRESS, 0);
|
||||
if (verbose > 0) Utils.log.info(_props.toString());
|
||||
props.setInteger(Pack200.Packer.PROGRESS, 0);
|
||||
if (verbose > 0) Utils.log.info(props.toString());
|
||||
}
|
||||
|
||||
// Here's where the bits are collected before getting packed:
|
||||
@ -163,7 +153,7 @@ public class PackerImpl implements Pack200.Packer {
|
||||
|
||||
final String unknownAttrCommand;
|
||||
{
|
||||
String uaMode = _props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
|
||||
String uaMode = props.getProperty(Pack200.Packer.UNKNOWN_ATTRIBUTE, Pack200.Packer.PASS);
|
||||
if (!(Pack200.Packer.STRIP.equals(uaMode) ||
|
||||
Pack200.Packer.PASS.equals(uaMode) ||
|
||||
Pack200.Packer.ERROR.equals(uaMode))) {
|
||||
@ -191,13 +181,12 @@ public class PackerImpl implements Pack200.Packer {
|
||||
};
|
||||
for (int i = 0; i < ctypes.length; i++) {
|
||||
String pfx = keys[i];
|
||||
Map map = _props.prefixMap(pfx);
|
||||
for (Iterator j = map.keySet().iterator(); j.hasNext(); ) {
|
||||
String key = (String) j.next();
|
||||
Map<String, String> map = props.prefixMap(pfx);
|
||||
for (String key : map.keySet()) {
|
||||
assert(key.startsWith(pfx));
|
||||
String name = key.substring(pfx.length());
|
||||
String layout = _props.getProperty(key);
|
||||
Object lkey = Attribute.keyForLookup(ctypes[i], name);
|
||||
String layout = props.getProperty(key);
|
||||
Layout lkey = Attribute.keyForLookup(ctypes[i], name);
|
||||
if (Pack200.Packer.STRIP.equals(layout) ||
|
||||
Pack200.Packer.PASS.equals(layout) ||
|
||||
Pack200.Packer.ERROR.equals(layout)) {
|
||||
@ -222,25 +211,25 @@ public class PackerImpl implements Pack200.Packer {
|
||||
}
|
||||
|
||||
final boolean keepFileOrder
|
||||
= _props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER);
|
||||
= props.getBoolean(Pack200.Packer.KEEP_FILE_ORDER);
|
||||
final boolean keepClassOrder
|
||||
= _props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER);
|
||||
= props.getBoolean(Utils.PACK_KEEP_CLASS_ORDER);
|
||||
|
||||
final boolean keepModtime
|
||||
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME));
|
||||
= Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
|
||||
final boolean latestModtime
|
||||
= Pack200.Packer.LATEST.equals(_props.getProperty(Pack200.Packer.MODIFICATION_TIME));
|
||||
= Pack200.Packer.LATEST.equals(props.getProperty(Pack200.Packer.MODIFICATION_TIME));
|
||||
final boolean keepDeflateHint
|
||||
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Packer.DEFLATE_HINT));
|
||||
= Pack200.Packer.KEEP.equals(props.getProperty(Pack200.Packer.DEFLATE_HINT));
|
||||
{
|
||||
if (!keepModtime && !latestModtime) {
|
||||
int modtime = _props.getTime(Pack200.Packer.MODIFICATION_TIME);
|
||||
int modtime = props.getTime(Pack200.Packer.MODIFICATION_TIME);
|
||||
if (modtime != Constants.NO_MODTIME) {
|
||||
pkg.default_modtime = modtime;
|
||||
}
|
||||
}
|
||||
if (!keepDeflateHint) {
|
||||
boolean deflate_hint = _props.getBoolean(Pack200.Packer.DEFLATE_HINT);
|
||||
boolean deflate_hint = props.getBoolean(Pack200.Packer.DEFLATE_HINT);
|
||||
if (deflate_hint) {
|
||||
pkg.default_options |= Constants.AO_DEFLATE_HINT;
|
||||
}
|
||||
@ -254,10 +243,10 @@ public class PackerImpl implements Pack200.Packer {
|
||||
final long segmentLimit;
|
||||
{
|
||||
long limit;
|
||||
if (_props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals(""))
|
||||
if (props.getProperty(Pack200.Packer.SEGMENT_LIMIT, "").equals(""))
|
||||
limit = -1;
|
||||
else
|
||||
limit = _props.getLong(Pack200.Packer.SEGMENT_LIMIT);
|
||||
limit = props.getLong(Pack200.Packer.SEGMENT_LIMIT);
|
||||
limit = Math.min(Integer.MAX_VALUE, limit);
|
||||
limit = Math.max(-1, limit);
|
||||
if (limit == -1)
|
||||
@ -265,10 +254,10 @@ public class PackerImpl implements Pack200.Packer {
|
||||
segmentLimit = limit;
|
||||
}
|
||||
|
||||
final List passFiles; // parsed pack.pass.file options
|
||||
final List<String> passFiles; // parsed pack.pass.file options
|
||||
{
|
||||
// Which class files will be passed through?
|
||||
passFiles = _props.getProperties(Pack200.Packer.PASS_FILE_PFX);
|
||||
passFiles = props.getProperties(Pack200.Packer.PASS_FILE_PFX);
|
||||
for (ListIterator i = passFiles.listIterator(); i.hasNext(); ) {
|
||||
String file = (String) i.next();
|
||||
if (file == null) { i.remove(); continue; }
|
||||
@ -283,28 +272,28 @@ public class PackerImpl implements Pack200.Packer {
|
||||
{
|
||||
// Fill in permitted range of major/minor version numbers.
|
||||
int ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.majver")) != 0)
|
||||
pkg.min_class_majver = (short) ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"min.class.minver")) != 0)
|
||||
pkg.min_class_minver = (short) ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.majver")) != 0)
|
||||
pkg.max_class_majver = (short) ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"max.class.minver")) != 0)
|
||||
pkg.max_class_minver = (short) ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"package.minver")) != 0)
|
||||
pkg.package_minver = (short) ver;
|
||||
if ((ver = _props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
|
||||
if ((ver = props.getInteger(Utils.COM_PREFIX+"package.majver")) != 0)
|
||||
pkg.package_majver = (short) ver;
|
||||
}
|
||||
|
||||
{
|
||||
// Hook for testing: Forces use of special archive modes.
|
||||
int opt = _props.getInteger(Utils.COM_PREFIX+"archive.options");
|
||||
int opt = props.getInteger(Utils.COM_PREFIX+"archive.options");
|
||||
if (opt != 0)
|
||||
pkg.default_options |= opt;
|
||||
}
|
||||
|
||||
// (Done collecting options from _props.)
|
||||
// (Done collecting options from props.)
|
||||
|
||||
boolean isClassFile(String name) {
|
||||
if (!name.endsWith(".class")) return false;
|
||||
@ -423,16 +412,18 @@ public class PackerImpl implements Pack200.Packer {
|
||||
Package.File file = null;
|
||||
// (5078608) : discount the resource files in META-INF
|
||||
// from segment computation.
|
||||
long inflen = (isMetaInfFile(name)) ? 0L :
|
||||
inFile.getInputLength();
|
||||
long inflen = (isMetaInfFile(name))
|
||||
? 0L
|
||||
: inFile.getInputLength();
|
||||
|
||||
if ((segmentSize += inflen) > segmentLimit) {
|
||||
segmentSize -= inflen;
|
||||
int nextCount = -1; // don't know; it's a stream
|
||||
flushPartial(out, nextCount);
|
||||
}
|
||||
if (verbose > 1)
|
||||
if (verbose > 1) {
|
||||
Utils.log.fine("Reading " + name);
|
||||
}
|
||||
|
||||
assert(je.isDirectory() == name.endsWith("/"));
|
||||
|
||||
@ -450,18 +441,18 @@ public class PackerImpl implements Pack200.Packer {
|
||||
}
|
||||
|
||||
void run(JarFile in, OutputStream out) throws IOException {
|
||||
List inFiles = scanJar(in);
|
||||
List<InFile> inFiles = scanJar(in);
|
||||
|
||||
if (verbose > 0)
|
||||
Utils.log.info("Reading " + inFiles.size() + " files...");
|
||||
|
||||
int numDone = 0;
|
||||
for (Iterator i = inFiles.iterator(); i.hasNext(); ) {
|
||||
InFile inFile = (InFile) i.next();
|
||||
for (InFile inFile : inFiles) {
|
||||
String name = inFile.name;
|
||||
// (5078608) : discount the resource files completely from segmenting
|
||||
long inflen = (isMetaInfFile(name)) ? 0L :
|
||||
inFile.getInputLength() ;
|
||||
long inflen = (isMetaInfFile(name))
|
||||
? 0L
|
||||
: inFile.getInputLength() ;
|
||||
if ((segmentSize += inflen) > segmentLimit) {
|
||||
segmentSize -= inflen;
|
||||
// Estimate number of remaining segments:
|
||||
@ -530,11 +521,11 @@ public class PackerImpl implements Pack200.Packer {
|
||||
}
|
||||
|
||||
void flushPartial(OutputStream out, int nextCount) throws IOException {
|
||||
if (pkg.files.size() == 0 && pkg.classes.size() == 0) {
|
||||
if (pkg.files.isEmpty() && pkg.classes.isEmpty()) {
|
||||
return; // do not flush an empty segment
|
||||
}
|
||||
flushPackage(out, Math.max(1, nextCount));
|
||||
_props.setInteger(Pack200.Packer.PROGRESS, 25);
|
||||
props.setInteger(Pack200.Packer.PROGRESS, 25);
|
||||
// In case there will be another segment:
|
||||
makeNextPackage();
|
||||
segmentCount += 1;
|
||||
@ -543,10 +534,10 @@ public class PackerImpl implements Pack200.Packer {
|
||||
}
|
||||
|
||||
void flushAll(OutputStream out) throws IOException {
|
||||
_props.setInteger(Pack200.Packer.PROGRESS, 50);
|
||||
props.setInteger(Pack200.Packer.PROGRESS, 50);
|
||||
flushPackage(out, 0);
|
||||
out.flush();
|
||||
_props.setInteger(Pack200.Packer.PROGRESS, 100);
|
||||
props.setInteger(Pack200.Packer.PROGRESS, 100);
|
||||
segmentCount += 1;
|
||||
segmentTotalSize += segmentSize;
|
||||
segmentSize = 0;
|
||||
@ -582,11 +573,11 @@ public class PackerImpl implements Pack200.Packer {
|
||||
pkg.trimStubs();
|
||||
|
||||
// Do some stripping, maybe.
|
||||
if (_props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug");
|
||||
if (_props.getBoolean(Utils.COM_PREFIX+"strip.compile")) pkg.stripAttributeKind("Compile");
|
||||
if (_props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant");
|
||||
if (_props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions");
|
||||
if (_props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
|
||||
if (props.getBoolean(Utils.COM_PREFIX+"strip.debug")) pkg.stripAttributeKind("Debug");
|
||||
if (props.getBoolean(Utils.COM_PREFIX+"strip.compile")) pkg.stripAttributeKind("Compile");
|
||||
if (props.getBoolean(Utils.COM_PREFIX+"strip.constants")) pkg.stripAttributeKind("Constant");
|
||||
if (props.getBoolean(Utils.COM_PREFIX+"strip.exceptions")) pkg.stripAttributeKind("Exceptions");
|
||||
if (props.getBoolean(Utils.COM_PREFIX+"strip.innerclasses")) pkg.stripAttributeKind("InnerClasses");
|
||||
|
||||
// Must choose an archive version; PackageWriter does not.
|
||||
if (pkg.package_majver <= 0) pkg.choosePackageVersion();
|
||||
@ -606,11 +597,10 @@ public class PackerImpl implements Pack200.Packer {
|
||||
}
|
||||
}
|
||||
|
||||
List scanJar(JarFile jf) throws IOException {
|
||||
List<InFile> scanJar(JarFile jf) throws IOException {
|
||||
// Collect jar entries, preserving order.
|
||||
List inFiles = new ArrayList();
|
||||
for (Enumeration e = jf.entries(); e.hasMoreElements(); ) {
|
||||
JarEntry je = (JarEntry) e.nextElement();
|
||||
List<InFile> inFiles = new ArrayList<>();
|
||||
for (JarEntry je : Collections.list(jf.entries())) {
|
||||
InFile inFile = new InFile(jf, je);
|
||||
assert(je.isDirectory() == inFile.name.endsWith("/"));
|
||||
inFiles.add(inFile);
|
||||
|
@ -91,7 +91,7 @@ class PropMap extends TreeMap {
|
||||
String.valueOf(Boolean.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)));
|
||||
|
||||
// The segment size is unlimited
|
||||
props.put(Pack200.Packer.SEGMENT_LIMIT, "");
|
||||
props.put(Pack200.Packer.SEGMENT_LIMIT, "-1");
|
||||
|
||||
// Preserve file ordering by default.
|
||||
props.put(Pack200.Packer.KEEP_FILE_ORDER, Pack200.Packer.TRUE);
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.SortedMap;
|
||||
|
||||
/*
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class provides a container to hold the global variables, for packer
|
||||
* and unpacker instances. This is typically stashed away in a ThreadLocal,
|
||||
* and the storage is destroyed upon completion. Therefore any local
|
||||
* references to these members must be eliminated appropriately to prevent a
|
||||
* memory leak.
|
||||
*/
|
||||
class TLGlobals {
|
||||
// Global environment
|
||||
final PropMap props;
|
||||
|
||||
// Needed by ConstantPool.java
|
||||
private final Map<String, Utf8Entry> utf8Entries;
|
||||
private final Map<String, ClassEntry> classEntries;
|
||||
private final Map<Object, LiteralEntry> literalEntries;
|
||||
private final Map<String, SignatureEntry> signatureEntries;
|
||||
private final Map<String, DescriptorEntry> descriptorEntries;
|
||||
private final Map<String, MemberEntry> memberEntries;
|
||||
|
||||
TLGlobals() {
|
||||
utf8Entries = new HashMap<>();
|
||||
classEntries = new HashMap<>();
|
||||
literalEntries = new HashMap<>();
|
||||
signatureEntries = new HashMap<>();
|
||||
descriptorEntries = new HashMap<>();
|
||||
memberEntries = new HashMap<>();
|
||||
props = new PropMap();
|
||||
}
|
||||
|
||||
SortedMap<Object, Object> getPropMap() {
|
||||
return props;
|
||||
}
|
||||
|
||||
Map<String, Utf8Entry> getUtf8Entries() {
|
||||
return utf8Entries;
|
||||
}
|
||||
|
||||
Map<String, ClassEntry> getClassEntries() {
|
||||
return classEntries;
|
||||
}
|
||||
|
||||
Map<Object, LiteralEntry> getLiteralEntries() {
|
||||
return literalEntries;
|
||||
}
|
||||
|
||||
Map<String, DescriptorEntry> getDescriptorEntries() {
|
||||
return descriptorEntries;
|
||||
}
|
||||
|
||||
Map<String, SignatureEntry> getSignatureEntries() {
|
||||
return signatureEntries;
|
||||
}
|
||||
|
||||
Map<String, MemberEntry> getMemberEntries() {
|
||||
return memberEntries;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,6 @@ import java.util.jar.*;
|
||||
import java.util.zip.*;
|
||||
import java.io.*;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
|
||||
/*
|
||||
* Implementation of the Pack provider.
|
||||
@ -40,7 +39,7 @@ import java.beans.PropertyChangeEvent;
|
||||
*/
|
||||
|
||||
|
||||
public class UnpackerImpl implements Pack200.Unpacker {
|
||||
public class UnpackerImpl extends TLGlobals implements Pack200.Unpacker {
|
||||
|
||||
|
||||
/**
|
||||
@ -48,7 +47,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
* @param listener An object to be invoked when a property is changed.
|
||||
*/
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
_props.addListener(listener);
|
||||
props.addListener(listener);
|
||||
}
|
||||
|
||||
|
||||
@ -57,25 +56,19 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
* @param listener The PropertyChange listener to be removed.
|
||||
*/
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
_props.removeListener(listener);
|
||||
props.removeListener(listener);
|
||||
}
|
||||
|
||||
public UnpackerImpl() {
|
||||
_props = new PropMap();
|
||||
//_props.getProperty() consults defaultProps invisibly.
|
||||
//_props.putAll(defaultProps);
|
||||
}
|
||||
public UnpackerImpl() {}
|
||||
|
||||
// Private stuff.
|
||||
final PropMap _props;
|
||||
|
||||
|
||||
/**
|
||||
* Get the set of options for the pack and unpack engines.
|
||||
* @return A sorted association of option key strings to option values.
|
||||
*/
|
||||
public SortedMap properties() {
|
||||
return _props;
|
||||
public SortedMap<String, String> properties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
// Back-pointer to NativeUnpacker, when active.
|
||||
@ -101,19 +94,20 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
*/
|
||||
public void unpack(InputStream in0, JarOutputStream out) throws IOException {
|
||||
assert(Utils.currentInstance.get() == null);
|
||||
TimeZone tz = (_props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE)) ? null :
|
||||
TimeZone.getDefault();
|
||||
TimeZone tz = (props.getBoolean(Utils.PACK_DEFAULT_TIMEZONE))
|
||||
? null
|
||||
: TimeZone.getDefault();
|
||||
|
||||
try {
|
||||
Utils.currentInstance.set(this);
|
||||
if (tz != null) TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
|
||||
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
BufferedInputStream in = new BufferedInputStream(in0);
|
||||
if (Utils.isJarMagic(Utils.readMagic(in))) {
|
||||
if (verbose > 0)
|
||||
Utils.log.info("Copying unpacked JAR file...");
|
||||
Utils.copyJarFile(new JarInputStream(in), out);
|
||||
} else if (_props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
|
||||
} else if (props.getBoolean(Utils.DEBUG_DISABLE_NATIVE)) {
|
||||
(new DoUnpack()).run(in, out);
|
||||
in.close();
|
||||
Utils.markJarFile(out);
|
||||
@ -142,36 +136,38 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
// %%% Reconsider if native unpacker learns to memory-map the file.
|
||||
FileInputStream instr = new FileInputStream(in);
|
||||
unpack(instr, out);
|
||||
if (_props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
|
||||
if (props.getBoolean(Utils.UNPACK_REMOVE_PACKFILE)) {
|
||||
in.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private class DoUnpack {
|
||||
final int verbose = _props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
final int verbose = props.getInteger(Utils.DEBUG_VERBOSE);
|
||||
|
||||
{
|
||||
_props.setInteger(Pack200.Unpacker.PROGRESS, 0);
|
||||
props.setInteger(Pack200.Unpacker.PROGRESS, 0);
|
||||
}
|
||||
|
||||
// Here's where the bits are read from disk:
|
||||
final Package pkg = new Package();
|
||||
|
||||
final boolean keepModtime
|
||||
= Pack200.Packer.KEEP.equals(_props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
|
||||
= Pack200.Packer.KEEP.equals(
|
||||
props.getProperty(Utils.UNPACK_MODIFICATION_TIME, Pack200.Packer.KEEP));
|
||||
final boolean keepDeflateHint
|
||||
= Pack200.Packer.KEEP.equals(_props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
|
||||
= Pack200.Packer.KEEP.equals(
|
||||
props.getProperty(Pack200.Unpacker.DEFLATE_HINT, Pack200.Packer.KEEP));
|
||||
final int modtime;
|
||||
final boolean deflateHint;
|
||||
{
|
||||
if (!keepModtime) {
|
||||
modtime = _props.getTime(Utils.UNPACK_MODIFICATION_TIME);
|
||||
modtime = props.getTime(Utils.UNPACK_MODIFICATION_TIME);
|
||||
} else {
|
||||
modtime = pkg.default_modtime;
|
||||
}
|
||||
|
||||
deflateHint = (keepDeflateHint) ? false :
|
||||
_props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
|
||||
props.getBoolean(java.util.jar.Pack200.Unpacker.DEFLATE_HINT);
|
||||
}
|
||||
|
||||
// Checksum apparatus.
|
||||
@ -181,7 +177,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
|
||||
public void run(BufferedInputStream in, JarOutputStream out) throws IOException {
|
||||
if (verbose > 0) {
|
||||
_props.list(System.out);
|
||||
props.list(System.out);
|
||||
}
|
||||
for (int seg = 1; ; seg++) {
|
||||
unpackSegment(in, out);
|
||||
@ -194,25 +190,26 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
}
|
||||
|
||||
private void unpackSegment(InputStream in, JarOutputStream out) throws IOException {
|
||||
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
|
||||
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"0");
|
||||
// Process the output directory or jar output.
|
||||
new PackageReader(pkg, in).read();
|
||||
|
||||
if (_props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug");
|
||||
if (_props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile");
|
||||
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
|
||||
if (props.getBoolean("unpack.strip.debug")) pkg.stripAttributeKind("Debug");
|
||||
if (props.getBoolean("unpack.strip.compile")) pkg.stripAttributeKind("Compile");
|
||||
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"50");
|
||||
pkg.ensureAllClassFiles();
|
||||
// Now write out the files.
|
||||
HashSet classesToWrite = new HashSet(pkg.getClasses());
|
||||
HashSet<Package.Class> classesToWrite = new HashSet<>(pkg.getClasses());
|
||||
for (Iterator i = pkg.getFiles().iterator(); i.hasNext(); ) {
|
||||
Package.File file = (Package.File) i.next();
|
||||
String name = file.nameString;
|
||||
JarEntry je = new JarEntry(Utils.getJarEntryName(name));
|
||||
boolean deflate;
|
||||
|
||||
deflate = (keepDeflateHint) ? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
|
||||
((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0)) :
|
||||
deflateHint;
|
||||
deflate = (keepDeflateHint)
|
||||
? (((file.options & Constants.FO_DEFLATE_HINT) != 0) ||
|
||||
((pkg.default_options & Constants.AO_DEFLATE_HINT) != 0))
|
||||
: deflateHint;
|
||||
|
||||
boolean needCRC = !deflate; // STORE mode requires CRC
|
||||
|
||||
@ -250,7 +247,7 @@ public class UnpackerImpl implements Pack200.Unpacker {
|
||||
Utils.log.info("Writing "+Utils.zeString((ZipEntry)je));
|
||||
}
|
||||
assert(classesToWrite.isEmpty());
|
||||
_props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
|
||||
props.setProperty(java.util.jar.Pack200.Unpacker.PROGRESS,"100");
|
||||
pkg.reset(); // reset for the next segment, if any
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,13 @@
|
||||
|
||||
package com.sun.java.util.jar.pack;
|
||||
|
||||
import com.sun.java.util.jar.pack.Attribute.Layout;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.ClassEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.DescriptorEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.LiteralEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.MemberEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.SignatureEntry;
|
||||
import com.sun.java.util.jar.pack.ConstantPool.Utf8Entry;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import java.util.zip.*;
|
||||
@ -113,17 +120,46 @@ class Utils {
|
||||
*/
|
||||
static final String PACK_ZIP_ARCHIVE_MARKER_COMMENT = "PACK200";
|
||||
|
||||
// Keep a TLS point to the current Packer or Unpacker.
|
||||
// This makes it simpler to supply environmental options
|
||||
// Keep a TLS point to the global data and environment.
|
||||
// This makes it simpler to supply environmental options
|
||||
// to the engine code, especially the native code.
|
||||
static final ThreadLocal currentInstance = new ThreadLocal();
|
||||
static final ThreadLocal<TLGlobals> currentInstance = new ThreadLocal<>();
|
||||
|
||||
// convenience methods to access the TL globals
|
||||
static TLGlobals getTLGlobals() {
|
||||
return currentInstance.get();
|
||||
}
|
||||
|
||||
static Map<String, Utf8Entry> getUtf8Entries() {
|
||||
return getTLGlobals().getUtf8Entries();
|
||||
}
|
||||
|
||||
static Map<String, ClassEntry> getClassEntries() {
|
||||
return getTLGlobals().getClassEntries();
|
||||
}
|
||||
|
||||
static Map<Object, LiteralEntry> getLiteralEntries() {
|
||||
return getTLGlobals().getLiteralEntries();
|
||||
}
|
||||
|
||||
static Map<String, DescriptorEntry> getDescriptorEntries() {
|
||||
return getTLGlobals().getDescriptorEntries();
|
||||
}
|
||||
|
||||
static Map<String, SignatureEntry> getSignatureEntries() {
|
||||
return getTLGlobals().getSignatureEntries();
|
||||
}
|
||||
|
||||
static Map<String, MemberEntry> getMemberEntries() {
|
||||
return getTLGlobals().getMemberEntries();
|
||||
}
|
||||
|
||||
static PropMap currentPropMap() {
|
||||
Object obj = currentInstance.get();
|
||||
if (obj instanceof PackerImpl)
|
||||
return ((PackerImpl)obj)._props;
|
||||
return ((PackerImpl)obj).props;
|
||||
if (obj instanceof UnpackerImpl)
|
||||
return ((UnpackerImpl)obj)._props;
|
||||
return ((UnpackerImpl)obj).props;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -813,7 +813,8 @@ public final class Connection implements Runnable {
|
||||
try {
|
||||
while (true) {
|
||||
try {
|
||||
inbuf = new byte[10];
|
||||
// type and length (at most 128 octets for long form)
|
||||
inbuf = new byte[129];
|
||||
|
||||
offset = 0;
|
||||
seqlen = 0;
|
||||
|
@ -470,7 +470,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
public AbstractStringBuilder append(CharSequence s, int start, int end) {
|
||||
if (s == null)
|
||||
s = "null";
|
||||
if ((start < 0) || (end < 0) || (start > end) || (end > s.length()))
|
||||
if ((start < 0) || (start > end) || (end > s.length()))
|
||||
throw new IndexOutOfBoundsException(
|
||||
"start " + start + ", end " + end + ", s.length() "
|
||||
+ s.length());
|
||||
@ -529,7 +529,8 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
* or {@code offset+len > str.length}
|
||||
*/
|
||||
public AbstractStringBuilder append(char str[], int offset, int len) {
|
||||
ensureCapacityInternal(count + len);
|
||||
if (len > 0) // let arraycopy report AIOOBE for len < 0
|
||||
ensureCapacityInternal(count + len);
|
||||
System.arraycopy(str, offset, value, count, len);
|
||||
count += len;
|
||||
return this;
|
||||
|
@ -413,6 +413,18 @@ class Thread implements Runnable {
|
||||
tid = nextThreadID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws CloneNotSupportedException as a Thread can not be meaningfully
|
||||
* cloned. Construct a new Thread instead.
|
||||
*
|
||||
* @throws CloneNotSupportedException
|
||||
* always
|
||||
*/
|
||||
@Override
|
||||
protected Object clone() throws CloneNotSupportedException {
|
||||
throw new CloneNotSupportedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a new {@code Thread} object. This constructor has the same
|
||||
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
|
||||
|
@ -200,7 +200,16 @@ public class Throwable implements Serializable {
|
||||
* @serial
|
||||
* @since 1.7
|
||||
*/
|
||||
private List<Throwable> suppressedExceptions = Collections.emptyList();
|
||||
private List<Throwable> suppressedExceptions = null;
|
||||
/*
|
||||
* This field is lazily initialized when the first suppressed
|
||||
* exception is added.
|
||||
*
|
||||
* OutOfMemoryError is preallocated in the VM for better OOM
|
||||
* diagnosability during VM initialization. Constructor can't
|
||||
* be not invoked. If a new field to be added in the future must
|
||||
* be initialized to non-null, it requires a synchronized VM change.
|
||||
*/
|
||||
|
||||
/** Message for trying to suppress a null exception. */
|
||||
private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception.";
|
||||
@ -329,7 +338,7 @@ public class Throwable implements Serializable {
|
||||
* cause is nonexistent or unknown.
|
||||
* @since 1.4
|
||||
*/
|
||||
public Throwable getCause() {
|
||||
public synchronized Throwable getCause() {
|
||||
return (cause==this ? null : cause);
|
||||
}
|
||||
|
||||
@ -563,7 +572,7 @@ public class Throwable implements Serializable {
|
||||
s.println("\tat " + traceElement);
|
||||
|
||||
// Print suppressed exceptions, if any
|
||||
for (Throwable se : suppressedExceptions)
|
||||
for (Throwable se : getSuppressedExceptions())
|
||||
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu);
|
||||
|
||||
// Print cause, if any
|
||||
@ -604,7 +613,7 @@ public class Throwable implements Serializable {
|
||||
s.println(prefix + "\t... " + framesInCommon + " more");
|
||||
|
||||
// Print suppressed exceptions, if any
|
||||
for (Throwable se : suppressedExceptions)
|
||||
for (Throwable se : getSuppressedExceptions())
|
||||
se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION,
|
||||
prefix +"\t", dejaVu);
|
||||
|
||||
@ -747,7 +756,9 @@ public class Throwable implements Serializable {
|
||||
if (defensiveCopy[i] == null)
|
||||
throw new NullPointerException("stackTrace[" + i + "]");
|
||||
|
||||
this.stackTrace = defensiveCopy;
|
||||
synchronized (this) {
|
||||
this.stackTrace = defensiveCopy;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -772,11 +783,11 @@ public class Throwable implements Serializable {
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException {
|
||||
s.defaultReadObject(); // read in all fields
|
||||
List<Throwable> suppressed = Collections.emptyList();
|
||||
List<Throwable> suppressed = null;
|
||||
if (suppressedExceptions != null &&
|
||||
!suppressedExceptions.isEmpty()) { // Copy Throwables to new list
|
||||
suppressed = new ArrayList<Throwable>();
|
||||
for(Throwable t : suppressedExceptions) {
|
||||
for (Throwable t : suppressedExceptions) {
|
||||
if (t == null)
|
||||
throw new NullPointerException(NULL_CAUSE_MESSAGE);
|
||||
suppressed.add(t);
|
||||
@ -819,7 +830,7 @@ public class Throwable implements Serializable {
|
||||
if (exception == this)
|
||||
throw new IllegalArgumentException("Self-suppression not permitted");
|
||||
|
||||
if (suppressedExceptions.size() == 0)
|
||||
if (suppressedExceptions == null)
|
||||
suppressedExceptions = new ArrayList<Throwable>();
|
||||
suppressedExceptions.add(exception);
|
||||
}
|
||||
@ -835,7 +846,10 @@ public class Throwable implements Serializable {
|
||||
* suppressed to deliver this exception.
|
||||
* @since 1.7
|
||||
*/
|
||||
public Throwable[] getSuppressedExceptions() {
|
||||
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
|
||||
public synchronized Throwable[] getSuppressedExceptions() {
|
||||
if (suppressedExceptions == null)
|
||||
return EMPTY_THROWABLE_ARRAY;
|
||||
else
|
||||
return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
|
||||
}
|
||||
}
|
||||
|
@ -1093,14 +1093,8 @@ public final class HttpCookie implements Cloneable {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static SimpleDateFormat[] cDateFormats = null;
|
||||
static {
|
||||
cDateFormats = new SimpleDateFormat[COOKIE_DATE_FORMATS.length];
|
||||
for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
|
||||
cDateFormats[i] = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
|
||||
cDateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
}
|
||||
static final TimeZone GMT = TimeZone.getTimeZone("GMT");
|
||||
|
||||
/*
|
||||
* @param dateString a date string in one of the formats
|
||||
* defined in Netscape cookie spec
|
||||
@ -1109,12 +1103,14 @@ public final class HttpCookie implements Cloneable {
|
||||
* time and the time specified by dateString
|
||||
*/
|
||||
private long expiryDate2DeltaSeconds(String dateString) {
|
||||
for (SimpleDateFormat df : cDateFormats) {
|
||||
for (int i = 0; i < COOKIE_DATE_FORMATS.length; i++) {
|
||||
SimpleDateFormat df = new SimpleDateFormat(COOKIE_DATE_FORMATS[i], Locale.US);
|
||||
df.setTimeZone(GMT);
|
||||
try {
|
||||
Date date = df.parse(dateString);
|
||||
return (date.getTime() - whenCreated) / 1000;
|
||||
} catch (Exception e) {
|
||||
|
||||
// Ignore, try the next date format
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -856,9 +856,7 @@ public final class URI
|
||||
try {
|
||||
return new URI(str);
|
||||
} catch (URISyntaxException x) {
|
||||
IllegalArgumentException y = new IllegalArgumentException();
|
||||
y.initCause(x);
|
||||
throw y;
|
||||
throw new IllegalArgumentException(x.getMessage(), x);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -131,17 +131,19 @@ import javax.security.auth.callback.*;
|
||||
* to read existing entries from the keystore, or to write new entries
|
||||
* into the keystore:
|
||||
* <pre>
|
||||
* KeyStore.ProtectionParameter protParam =
|
||||
* new KeyStore.PasswordProtection(password);
|
||||
*
|
||||
* // get my private key
|
||||
* KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
|
||||
* ks.getEntry("privateKeyAlias", password);
|
||||
* ks.getEntry("privateKeyAlias", protParam);
|
||||
* PrivateKey myPrivateKey = pkEntry.getPrivateKey();
|
||||
*
|
||||
* // save my secret key
|
||||
* javax.crypto.SecretKey mySecretKey;
|
||||
* KeyStore.SecretKeyEntry skEntry =
|
||||
* new KeyStore.SecretKeyEntry(mySecretKey);
|
||||
* ks.setEntry("secretKeyAlias", skEntry,
|
||||
* new KeyStore.PasswordProtection(password));
|
||||
* ks.setEntry("secretKeyAlias", skEntry, protParam);
|
||||
*
|
||||
* // store away the keystore
|
||||
* java.io.FileOutputStream fos = null;
|
||||
|
@ -103,27 +103,46 @@ public class Date extends java.util.Date {
|
||||
* JDBC date escape format (yyyy-mm-dd)
|
||||
*/
|
||||
public static Date valueOf(String s) {
|
||||
int year;
|
||||
int month;
|
||||
int day;
|
||||
final int YEAR_LENGTH = 4;
|
||||
final int MONTH_LENGTH = 2;
|
||||
final int DAY_LENGTH = 2;
|
||||
final int MAX_MONTH = 12;
|
||||
final int MAX_DAY = 31;
|
||||
int firstDash;
|
||||
int secondDash;
|
||||
Date d = null;
|
||||
|
||||
if (s == null) throw new java.lang.IllegalArgumentException();
|
||||
|
||||
firstDash = s.indexOf('-');
|
||||
secondDash = s.indexOf('-', firstDash+1);
|
||||
if ((firstDash > 0) & (secondDash > 0) & (secondDash < s.length()-1)) {
|
||||
year = Integer.parseInt(s.substring(0, firstDash)) - 1900;
|
||||
month = Integer.parseInt(s.substring(firstDash+1, secondDash)) - 1;
|
||||
day = Integer.parseInt(s.substring(secondDash+1));
|
||||
} else {
|
||||
if (s == null) {
|
||||
throw new java.lang.IllegalArgumentException();
|
||||
}
|
||||
|
||||
return new Date(year, month, day);
|
||||
firstDash = s.indexOf('-');
|
||||
secondDash = s.indexOf('-', firstDash + 1);
|
||||
|
||||
if ((firstDash > 0) && (secondDash > 0) && (secondDash < s.length() - 1)) {
|
||||
String yyyy = s.substring(0, firstDash);
|
||||
String mm = s.substring(firstDash + 1, secondDash);
|
||||
String dd = s.substring(secondDash + 1);
|
||||
if (yyyy.length() == YEAR_LENGTH && mm.length() == MONTH_LENGTH &&
|
||||
dd.length() == DAY_LENGTH) {
|
||||
int year = Integer.parseInt(yyyy);
|
||||
int month = Integer.parseInt(mm);
|
||||
int day = Integer.parseInt(dd);
|
||||
|
||||
if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) {
|
||||
d = new Date(year - 1900, month - 1, day);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (d == null) {
|
||||
throw new java.lang.IllegalArgumentException();
|
||||
}
|
||||
|
||||
return d;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Formats a date in the date escape format yyyy-mm-dd.
|
||||
* <P>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -946,7 +946,6 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
||||
|
||||
/**
|
||||
* Returns the height of a table row, in pixels.
|
||||
* The default row height is 16.0.
|
||||
*
|
||||
* @return the height in pixels of a table row
|
||||
* @see #setRowHeight
|
||||
|
@ -36,117 +36,71 @@ package sun.java2d.pisces;
|
||||
* semantics are unclear.
|
||||
*
|
||||
*/
|
||||
public class Dasher extends LineSink {
|
||||
public class Dasher implements LineSink {
|
||||
private final LineSink output;
|
||||
private final float[] dash;
|
||||
private final float startPhase;
|
||||
private final boolean startDashOn;
|
||||
private final int startIdx;
|
||||
|
||||
LineSink output;
|
||||
int[] dash;
|
||||
int startPhase;
|
||||
boolean startDashOn;
|
||||
int startIdx;
|
||||
private final float m00, m10, m01, m11;
|
||||
private final float det;
|
||||
|
||||
int idx;
|
||||
boolean dashOn;
|
||||
int phase;
|
||||
private boolean firstDashOn;
|
||||
private boolean starting;
|
||||
|
||||
int sx, sy;
|
||||
int x0, y0;
|
||||
private int idx;
|
||||
private boolean dashOn;
|
||||
private float phase;
|
||||
|
||||
int m00, m01;
|
||||
int m10, m11;
|
||||
private float sx, sy;
|
||||
private float x0, y0;
|
||||
private float sx1, sy1;
|
||||
|
||||
Transform4 transform;
|
||||
|
||||
boolean symmetric;
|
||||
long ldet;
|
||||
|
||||
boolean firstDashOn;
|
||||
boolean starting;
|
||||
int sx1, sy1;
|
||||
|
||||
/**
|
||||
* Empty constructor. <code>setOutput</code> and
|
||||
* <code>setParameters</code> must be called prior to calling any
|
||||
* other methods.
|
||||
*/
|
||||
public Dasher() {}
|
||||
|
||||
/**
|
||||
* Constructs a <code>Dasher</code>.
|
||||
*
|
||||
* @param output an output <code>LineSink</code>.
|
||||
* @param dash an array of <code>int</code>s containing the dash
|
||||
* pattern in S15.16 format.
|
||||
* @param phase an <code>int</code> containing the dash phase in
|
||||
* S15.16 format.
|
||||
* @param dash an array of <code>int</code>s containing the dash pattern
|
||||
* @param phase an <code>int</code> containing the dash phase
|
||||
* @param transform a <code>Transform4</code> object indicating
|
||||
* the transform that has been previously applied to all incoming
|
||||
* coordinates. This is required in order to compute dash lengths
|
||||
* properly.
|
||||
*/
|
||||
public Dasher(LineSink output,
|
||||
int[] dash, int phase,
|
||||
Transform4 transform) {
|
||||
setOutput(output);
|
||||
setParameters(dash, phase, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output <code>LineSink</code> of this
|
||||
* <code>Dasher</code>.
|
||||
*
|
||||
* @param output an output <code>LineSink</code>.
|
||||
*/
|
||||
public void setOutput(LineSink output) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameters of this <code>Dasher</code>.
|
||||
*
|
||||
* @param dash an array of <code>int</code>s containing the dash
|
||||
* pattern in S15.16 format.
|
||||
* @param phase an <code>int</code> containing the dash phase in
|
||||
* S15.16 format.
|
||||
* @param transform a <code>Transform4</code> object indicating
|
||||
* the transform that has been previously applied to all incoming
|
||||
* coordinates. This is required in order to compute dash lengths
|
||||
* properly.
|
||||
*/
|
||||
public void setParameters(int[] dash, int phase,
|
||||
Transform4 transform) {
|
||||
float[] dash, float phase,
|
||||
float a00, float a01, float a10, float a11) {
|
||||
if (phase < 0) {
|
||||
throw new IllegalArgumentException("phase < 0 !");
|
||||
}
|
||||
|
||||
this.output = output;
|
||||
|
||||
// Normalize so 0 <= phase < dash[0]
|
||||
int idx = 0;
|
||||
dashOn = true;
|
||||
int d;
|
||||
float d;
|
||||
while (phase >= (d = dash[idx])) {
|
||||
phase -= d;
|
||||
idx = (idx + 1) % dash.length;
|
||||
dashOn = !dashOn;
|
||||
}
|
||||
|
||||
this.dash = new int[dash.length];
|
||||
for (int i = 0; i < dash.length; i++) {
|
||||
this.dash[i] = dash[i];
|
||||
}
|
||||
this.dash = dash;
|
||||
this.startPhase = this.phase = phase;
|
||||
this.startDashOn = dashOn;
|
||||
this.startIdx = idx;
|
||||
|
||||
this.transform = transform;
|
||||
|
||||
this.m00 = transform.m00;
|
||||
this.m01 = transform.m01;
|
||||
this.m10 = transform.m10;
|
||||
this.m11 = transform.m11;
|
||||
this.ldet = ((long)m00*m11 - (long)m01*m10) >> 16;
|
||||
this.symmetric = (m00 == m11 && m10 == -m01);
|
||||
m00 = a00;
|
||||
m01 = a01;
|
||||
m10 = a10;
|
||||
m11 = a11;
|
||||
det = m00 * m11 - m01 * m10;
|
||||
}
|
||||
|
||||
public void moveTo(int x0, int y0) {
|
||||
public void moveTo(float x0, float y0) {
|
||||
output.moveTo(x0, y0);
|
||||
this.idx = startIdx;
|
||||
this.dashOn = this.startDashOn;
|
||||
@ -160,7 +114,7 @@ public class Dasher extends LineSink {
|
||||
output.lineJoin();
|
||||
}
|
||||
|
||||
private void goTo(int x1, int y1) {
|
||||
private void goTo(float x1, float y1) {
|
||||
if (dashOn) {
|
||||
if (starting) {
|
||||
this.sx1 = x1;
|
||||
@ -180,52 +134,64 @@ public class Dasher extends LineSink {
|
||||
this.y0 = y1;
|
||||
}
|
||||
|
||||
public void lineTo(int x1, int y1) {
|
||||
public void lineTo(float x1, float y1) {
|
||||
// The widened line is squished to a 0 width one, so no drawing is done
|
||||
if (det == 0) {
|
||||
goTo(x1, y1);
|
||||
return;
|
||||
}
|
||||
float dx = x1 - x0;
|
||||
float dy = y1 - y0;
|
||||
|
||||
|
||||
// Compute segment length in the untransformed
|
||||
// coordinate system
|
||||
|
||||
float la = (dy*m00 - dx*m10)/det;
|
||||
float lb = (dy*m01 - dx*m11)/det;
|
||||
float origLen = (float) Math.hypot(la, lb);
|
||||
|
||||
if (origLen == 0) {
|
||||
// Let the output LineSink deal with cases where dx, dy are 0.
|
||||
goTo(x1, y1);
|
||||
return;
|
||||
}
|
||||
|
||||
// The scaling factors needed to get the dx and dy of the
|
||||
// transformed dash segments.
|
||||
float cx = dx / origLen;
|
||||
float cy = dy / origLen;
|
||||
|
||||
while (true) {
|
||||
int d = dash[idx] - phase;
|
||||
int lx = x1 - x0;
|
||||
int ly = y1 - y0;
|
||||
|
||||
// Compute segment length in the untransformed
|
||||
// coordinate system
|
||||
// IMPL NOTE - use fixed point
|
||||
|
||||
int l;
|
||||
if (symmetric) {
|
||||
l = (int)((PiscesMath.hypot(lx, ly)*65536L)/ldet);
|
||||
} else{
|
||||
long la = ((long)ly*m00 - (long)lx*m10)/ldet;
|
||||
long lb = ((long)ly*m01 - (long)lx*m11)/ldet;
|
||||
l = (int)PiscesMath.hypot(la, lb);
|
||||
}
|
||||
|
||||
if (l < d) {
|
||||
float leftInThisDashSegment = dash[idx] - phase;
|
||||
if (origLen < leftInThisDashSegment) {
|
||||
goTo(x1, y1);
|
||||
// Advance phase within current dash segment
|
||||
phase += l;
|
||||
phase += origLen;
|
||||
return;
|
||||
} else if (origLen == leftInThisDashSegment) {
|
||||
goTo(x1, y1);
|
||||
phase = 0f;
|
||||
idx = (idx + 1) % dash.length;
|
||||
dashOn = !dashOn;
|
||||
return;
|
||||
}
|
||||
|
||||
long t;
|
||||
int xsplit, ysplit;
|
||||
// // For zero length dashses, SE appears to move 1/8 unit
|
||||
// // in device space
|
||||
// if (d == 0) {
|
||||
// double dlx = lx/65536.0;
|
||||
// double dly = ly/65536.0;
|
||||
// len = PiscesMath.hypot(dlx, dly);
|
||||
// double dt = 1.0/(8*len);
|
||||
// double dxsplit = (x0/65536.0) + dt*dlx;
|
||||
// double dysplit = (y0/65536.0) + dt*dly;
|
||||
// xsplit = (int)(dxsplit*65536.0);
|
||||
// ysplit = (int)(dysplit*65536.0);
|
||||
// } else {
|
||||
t = ((long)d << 16)/l;
|
||||
xsplit = x0 + (int)(t*(x1 - x0) >> 16);
|
||||
ysplit = y0 + (int)(t*(y1 - y0) >> 16);
|
||||
// }
|
||||
goTo(xsplit, ysplit);
|
||||
float dashx, dashy;
|
||||
float dashdx = dash[idx] * cx;
|
||||
float dashdy = dash[idx] * cy;
|
||||
if (phase == 0) {
|
||||
dashx = x0 + dashdx;
|
||||
dashy = y0 + dashdy;
|
||||
} else {
|
||||
float p = (leftInThisDashSegment) / dash[idx];
|
||||
dashx = x0 + p * dashdx;
|
||||
dashy = y0 + p * dashdy;
|
||||
}
|
||||
|
||||
goTo(dashx, dashy);
|
||||
|
||||
origLen -= (dash[idx] - phase);
|
||||
// Advance to next dash segment
|
||||
idx = (idx + 1) % dash.length;
|
||||
dashOn = !dashOn;
|
||||
@ -233,6 +199,7 @@ public class Dasher extends LineSink {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void close() {
|
||||
lineTo(sx, sy);
|
||||
if (firstDashOn) {
|
||||
|
@ -39,16 +39,16 @@ package sun.java2d.pisces;
|
||||
* <code>LineSink</code> interface.
|
||||
*
|
||||
*/
|
||||
public abstract class LineSink {
|
||||
public interface LineSink {
|
||||
|
||||
/**
|
||||
* Moves the current drawing position to the point <code>(x0,
|
||||
* y0)</code>.
|
||||
*
|
||||
* @param x0 the X coordinate in S15.16 format
|
||||
* @param y0 the Y coordinate in S15.16 format
|
||||
* @param x0 the X coordinate
|
||||
* @param y0 the Y coordinate
|
||||
*/
|
||||
public abstract void moveTo(int x0, int y0);
|
||||
public void moveTo(float x0, float y0);
|
||||
|
||||
/**
|
||||
* Provides a hint that the current segment should be joined to
|
||||
@ -65,29 +65,29 @@ public abstract class LineSink {
|
||||
* <p> Other <code>LineSink</code> classes should simply pass this
|
||||
* hint to their output sink as needed.
|
||||
*/
|
||||
public abstract void lineJoin();
|
||||
public void lineJoin();
|
||||
|
||||
/**
|
||||
* Draws a line from the current drawing position to the point
|
||||
* <code>(x1, y1)</code> and sets the current drawing position to
|
||||
* <code>(x1, y1)</code>.
|
||||
*
|
||||
* @param x1 the X coordinate in S15.16 format
|
||||
* @param y1 the Y coordinate in S15.16 format
|
||||
* @param x1 the X coordinate
|
||||
* @param y1 the Y coordinate
|
||||
*/
|
||||
public abstract void lineTo(int x1, int y1);
|
||||
public void lineTo(float x1, float y1);
|
||||
|
||||
/**
|
||||
* Closes the current path by drawing a line from the current
|
||||
* drawing position to the point specified by the moset recent
|
||||
* <code>moveTo</code> command.
|
||||
*/
|
||||
public abstract void close();
|
||||
public void close();
|
||||
|
||||
/**
|
||||
* Ends the current path. It may be necessary to end a path in
|
||||
* order to allow end caps to be drawn.
|
||||
*/
|
||||
public abstract void end();
|
||||
public void end();
|
||||
|
||||
}
|
||||
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.pisces;
|
||||
|
||||
public class PiscesMath {
|
||||
|
||||
private PiscesMath() {}
|
||||
|
||||
private static final int SINTAB_LG_ENTRIES = 10;
|
||||
private static final int SINTAB_ENTRIES = 1 << SINTAB_LG_ENTRIES;
|
||||
private static int[] sintab;
|
||||
|
||||
public static final int PI = (int)(Math.PI*65536.0);
|
||||
public static final int TWO_PI = (int)(2.0*Math.PI*65536.0);
|
||||
public static final int PI_OVER_TWO = (int)((Math.PI/2.0)*65536.0);
|
||||
public static final int SQRT_TWO = (int)(Math.sqrt(2.0)*65536.0);
|
||||
|
||||
static {
|
||||
sintab = new int[SINTAB_ENTRIES + 1];
|
||||
for (int i = 0; i < SINTAB_ENTRIES + 1; i++) {
|
||||
double theta = i*(Math.PI/2.0)/SINTAB_ENTRIES;
|
||||
sintab[i] = (int)(Math.sin(theta)*65536.0);
|
||||
}
|
||||
}
|
||||
|
||||
public static int sin(int theta) {
|
||||
int sign = 1;
|
||||
if (theta < 0) {
|
||||
theta = -theta;
|
||||
sign = -1;
|
||||
}
|
||||
// 0 <= theta
|
||||
while (theta >= TWO_PI) {
|
||||
theta -= TWO_PI;
|
||||
}
|
||||
// 0 <= theta < 2*PI
|
||||
if (theta >= PI) {
|
||||
theta = TWO_PI - theta;
|
||||
sign = -sign;
|
||||
}
|
||||
// 0 <= theta < PI
|
||||
if (theta > PI_OVER_TWO) {
|
||||
theta = PI - theta;
|
||||
}
|
||||
// 0 <= theta <= PI/2
|
||||
int itheta = (int)((long)theta*SINTAB_ENTRIES/(PI_OVER_TWO));
|
||||
return sign*sintab[itheta];
|
||||
}
|
||||
|
||||
public static int cos(int theta) {
|
||||
return sin(PI_OVER_TWO - theta);
|
||||
}
|
||||
|
||||
// public static double sqrt(double x) {
|
||||
// double dsqrt = Math.sqrt(x);
|
||||
// int ix = (int)(x*65536.0);
|
||||
// Int Isqrt = Isqrt(Ix);
|
||||
|
||||
// Long Lx = (Long)(X*65536.0);
|
||||
// Long Lsqrt = Lsqrt(Lx);
|
||||
|
||||
// System.Out.Println();
|
||||
// System.Out.Println("X = " + X);
|
||||
// System.Out.Println("Dsqrt = " + Dsqrt);
|
||||
|
||||
// System.Out.Println("Ix = " + Ix);
|
||||
// System.Out.Println("Isqrt = " + Isqrt/65536.0);
|
||||
|
||||
// System.Out.Println("Lx = " + Lx);
|
||||
// System.Out.Println("Lsqrt = " + Lsqrt/65536.0);
|
||||
|
||||
// Return Dsqrt;
|
||||
// }
|
||||
|
||||
// From Ken Turkowski, _Fixed-Point Square Root_, In Graphics Gems V
|
||||
public static int isqrt(int x) {
|
||||
int fracbits = 16;
|
||||
|
||||
int root = 0;
|
||||
int remHi = 0;
|
||||
int remLo = x;
|
||||
int count = 15 + fracbits/2;
|
||||
|
||||
do {
|
||||
remHi = (remHi << 2) | (remLo >>> 30); // N.B. - unsigned shift R
|
||||
remLo <<= 2;
|
||||
root <<= 1;
|
||||
int testdiv = (root << 1) + 1;
|
||||
if (remHi >= testdiv) {
|
||||
remHi -= testdiv;
|
||||
root++;
|
||||
}
|
||||
} while (count-- != 0);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static long lsqrt(long x) {
|
||||
int fracbits = 16;
|
||||
|
||||
long root = 0;
|
||||
long remHi = 0;
|
||||
long remLo = x;
|
||||
int count = 31 + fracbits/2;
|
||||
|
||||
do {
|
||||
remHi = (remHi << 2) | (remLo >>> 62); // N.B. - unsigned shift R
|
||||
remLo <<= 2;
|
||||
root <<= 1;
|
||||
long testDiv = (root << 1) + 1;
|
||||
if (remHi >= testDiv) {
|
||||
remHi -= testDiv;
|
||||
root++;
|
||||
}
|
||||
} while (count-- != 0);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
public static double hypot(double x, double y) {
|
||||
// new RuntimeException().printStackTrace();
|
||||
return Math.sqrt(x*x + y*y);
|
||||
}
|
||||
|
||||
public static int hypot(int x, int y) {
|
||||
return (int)((lsqrt((long)x*x + (long)y*y) + 128) >> 8);
|
||||
}
|
||||
|
||||
public static long hypot(long x, long y) {
|
||||
return (lsqrt(x*x + y*y) + 128) >> 8;
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ package sun.java2d.pisces;
|
||||
|
||||
import java.awt.Shape;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.geom.FlatteningPathIterator;
|
||||
import java.awt.geom.Path2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.PathIterator;
|
||||
@ -37,23 +38,9 @@ import sun.java2d.pipe.RenderingEngine;
|
||||
import sun.java2d.pipe.AATileGenerator;
|
||||
|
||||
public class PiscesRenderingEngine extends RenderingEngine {
|
||||
public static Transform4 IdentT4 = new Transform4();
|
||||
public static double defaultFlat = 0.1;
|
||||
|
||||
static int FloatToS15_16(float flt) {
|
||||
flt = flt * 65536f + 0.5f;
|
||||
if (flt <= -(65536f * 65536f)) {
|
||||
return Integer.MIN_VALUE;
|
||||
} else if (flt >= (65536f * 65536f)) {
|
||||
return Integer.MAX_VALUE;
|
||||
} else {
|
||||
return (int) Math.floor(flt);
|
||||
}
|
||||
}
|
||||
|
||||
static float S15_16ToFloat(int fix) {
|
||||
return (fix / 65536f);
|
||||
}
|
||||
private static enum NormMode {OFF, ON_NO_AA, ON_WITH_AA}
|
||||
|
||||
/**
|
||||
* Create a widened path as specified by the parameters.
|
||||
@ -85,18 +72,19 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
strokeTo(src,
|
||||
null,
|
||||
width,
|
||||
NormMode.OFF,
|
||||
caps,
|
||||
join,
|
||||
miterlimit,
|
||||
dashes,
|
||||
dashphase,
|
||||
new LineSink() {
|
||||
public void moveTo(int x0, int y0) {
|
||||
p2d.moveTo(S15_16ToFloat(x0), S15_16ToFloat(y0));
|
||||
public void moveTo(float x0, float y0) {
|
||||
p2d.moveTo(x0, y0);
|
||||
}
|
||||
public void lineJoin() {}
|
||||
public void lineTo(int x1, int y1) {
|
||||
p2d.lineTo(S15_16ToFloat(x1), S15_16ToFloat(y1));
|
||||
public void lineTo(float x1, float y1) {
|
||||
p2d.lineTo(x1, y1);
|
||||
}
|
||||
public void close() {
|
||||
p2d.closePath();
|
||||
@ -142,14 +130,17 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
boolean antialias,
|
||||
final PathConsumer2D consumer)
|
||||
{
|
||||
strokeTo(src, at, bs, thin, normalize, antialias,
|
||||
NormMode norm = (normalize) ?
|
||||
((antialias) ? NormMode.ON_WITH_AA : NormMode.ON_NO_AA)
|
||||
: NormMode.OFF;
|
||||
strokeTo(src, at, bs, thin, norm, antialias,
|
||||
new LineSink() {
|
||||
public void moveTo(int x0, int y0) {
|
||||
consumer.moveTo(S15_16ToFloat(x0), S15_16ToFloat(y0));
|
||||
public void moveTo(float x0, float y0) {
|
||||
consumer.moveTo(x0, y0);
|
||||
}
|
||||
public void lineJoin() {}
|
||||
public void lineTo(int x1, int y1) {
|
||||
consumer.lineTo(S15_16ToFloat(x1), S15_16ToFloat(y1));
|
||||
public void lineTo(float x1, float y1) {
|
||||
consumer.lineTo(x1, y1);
|
||||
}
|
||||
public void close() {
|
||||
consumer.closePath();
|
||||
@ -164,7 +155,7 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
AffineTransform at,
|
||||
BasicStroke bs,
|
||||
boolean thin,
|
||||
boolean normalize,
|
||||
NormMode normalize,
|
||||
boolean antialias,
|
||||
LineSink lsink)
|
||||
{
|
||||
@ -181,6 +172,7 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
strokeTo(src,
|
||||
at,
|
||||
lw,
|
||||
normalize,
|
||||
bs.getEndCap(),
|
||||
bs.getLineJoin(),
|
||||
bs.getMiterLimit(),
|
||||
@ -258,6 +250,7 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
void strokeTo(Shape src,
|
||||
AffineTransform at,
|
||||
float width,
|
||||
NormMode normalize,
|
||||
int caps,
|
||||
int join,
|
||||
float miterlimit,
|
||||
@ -265,36 +258,139 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
float dashphase,
|
||||
LineSink lsink)
|
||||
{
|
||||
Transform4 t4;
|
||||
|
||||
if (at == null || at.isIdentity()) {
|
||||
t4 = IdentT4;
|
||||
} else {
|
||||
t4 = new Transform4(FloatToS15_16((float) at.getScaleX()),
|
||||
FloatToS15_16((float) at.getShearX()),
|
||||
FloatToS15_16((float) at.getShearY()),
|
||||
FloatToS15_16((float) at.getScaleY()));
|
||||
float a00 = 1f, a01 = 0f, a10 = 0f, a11 = 1f;
|
||||
if (at != null && !at.isIdentity()) {
|
||||
a00 = (float)at.getScaleX();
|
||||
a01 = (float)at.getShearX();
|
||||
a10 = (float)at.getShearY();
|
||||
a11 = (float)at.getScaleY();
|
||||
}
|
||||
|
||||
lsink = new Stroker(lsink,
|
||||
FloatToS15_16(width),
|
||||
caps,
|
||||
join,
|
||||
FloatToS15_16(miterlimit),
|
||||
t4);
|
||||
lsink = new Stroker(lsink, width, caps, join, miterlimit, a00, a01, a10, a11);
|
||||
if (dashes != null) {
|
||||
int fdashes[] = new int[dashes.length];
|
||||
for (int i = 0; i < dashes.length; i++) {
|
||||
fdashes[i] = FloatToS15_16(dashes[i]);
|
||||
lsink = new Dasher(lsink, dashes, dashphase, a00, a01, a10, a11);
|
||||
}
|
||||
PathIterator pi;
|
||||
if (normalize != NormMode.OFF) {
|
||||
pi = new FlatteningPathIterator(
|
||||
new NormalizingPathIterator(src.getPathIterator(at), normalize),
|
||||
defaultFlat);
|
||||
} else {
|
||||
pi = src.getPathIterator(at, defaultFlat);
|
||||
}
|
||||
pathTo(pi, lsink);
|
||||
}
|
||||
|
||||
private static class NormalizingPathIterator implements PathIterator {
|
||||
|
||||
private final PathIterator src;
|
||||
|
||||
// the adjustment applied to the current position.
|
||||
private float curx_adjust, cury_adjust;
|
||||
// the adjustment applied to the last moveTo position.
|
||||
private float movx_adjust, movy_adjust;
|
||||
|
||||
// constants used in normalization computations
|
||||
private final float lval, rval;
|
||||
|
||||
NormalizingPathIterator(PathIterator src, NormMode mode) {
|
||||
this.src = src;
|
||||
switch (mode) {
|
||||
case ON_NO_AA:
|
||||
// round to nearest (0.25, 0.25) pixel
|
||||
lval = rval = 0.25f;
|
||||
break;
|
||||
case ON_WITH_AA:
|
||||
// round to nearest pixel center
|
||||
lval = 0f;
|
||||
rval = 0.5f;
|
||||
break;
|
||||
case OFF:
|
||||
throw new InternalError("A NormalizingPathIterator should " +
|
||||
"not be created if no normalization is being done");
|
||||
default:
|
||||
throw new InternalError("Unrecognized normalization mode");
|
||||
}
|
||||
lsink = new Dasher(lsink,
|
||||
fdashes,
|
||||
FloatToS15_16(dashphase),
|
||||
t4);
|
||||
}
|
||||
|
||||
PathIterator pi = src.getPathIterator(at, defaultFlat);
|
||||
pathTo(pi, lsink);
|
||||
public int currentSegment(float[] coords) {
|
||||
int type = src.currentSegment(coords);
|
||||
|
||||
int lastCoord;
|
||||
switch(type) {
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
lastCoord = 4;
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
lastCoord = 2;
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
case PathIterator.SEG_MOVETO:
|
||||
lastCoord = 0;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
// we don't want to deal with this case later. We just exit now
|
||||
curx_adjust = movx_adjust;
|
||||
cury_adjust = movy_adjust;
|
||||
return type;
|
||||
default:
|
||||
throw new InternalError("Unrecognized curve type");
|
||||
}
|
||||
|
||||
// normalize endpoint
|
||||
float x_adjust = (float)Math.floor(coords[lastCoord] + lval) + rval -
|
||||
coords[lastCoord];
|
||||
float y_adjust = (float)Math.floor(coords[lastCoord+1] + lval) + rval -
|
||||
coords[lastCoord + 1];
|
||||
|
||||
coords[lastCoord ] += x_adjust;
|
||||
coords[lastCoord + 1] += y_adjust;
|
||||
|
||||
// now that the end points are done, normalize the control points
|
||||
switch(type) {
|
||||
case PathIterator.SEG_CUBICTO:
|
||||
coords[0] += curx_adjust;
|
||||
coords[1] += cury_adjust;
|
||||
coords[2] += x_adjust;
|
||||
coords[3] += y_adjust;
|
||||
break;
|
||||
case PathIterator.SEG_QUADTO:
|
||||
coords[0] += (curx_adjust + x_adjust) / 2;
|
||||
coords[1] += (cury_adjust + y_adjust) / 2;
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
break;
|
||||
case PathIterator.SEG_MOVETO:
|
||||
movx_adjust = x_adjust;
|
||||
movy_adjust = y_adjust;
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
throw new InternalError("This should be handled earlier.");
|
||||
}
|
||||
curx_adjust = x_adjust;
|
||||
cury_adjust = y_adjust;
|
||||
return type;
|
||||
}
|
||||
|
||||
public int currentSegment(double[] coords) {
|
||||
float[] tmp = new float[6];
|
||||
int type = this.currentSegment(tmp);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
coords[i] = (float) tmp[i];
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getWindingRule() {
|
||||
return src.getWindingRule();
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
return src.isDone();
|
||||
}
|
||||
|
||||
public void next() {
|
||||
src.next();
|
||||
}
|
||||
}
|
||||
|
||||
void pathTo(PathIterator pi, LineSink lsink) {
|
||||
@ -302,13 +398,11 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
while (!pi.isDone()) {
|
||||
switch (pi.currentSegment(coords)) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
lsink.moveTo(FloatToS15_16(coords[0]),
|
||||
FloatToS15_16(coords[1]));
|
||||
lsink.moveTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_LINETO:
|
||||
lsink.lineJoin();
|
||||
lsink.lineTo(FloatToS15_16(coords[0]),
|
||||
FloatToS15_16(coords[1]));
|
||||
lsink.lineTo(coords[0], coords[1]);
|
||||
break;
|
||||
case PathIterator.SEG_CLOSE:
|
||||
lsink.lineJoin();
|
||||
@ -378,18 +472,28 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
int bbox[])
|
||||
{
|
||||
PiscesCache pc = PiscesCache.createInstance();
|
||||
Renderer r = new Renderer();
|
||||
r.setCache(pc);
|
||||
r.setAntialiasing(3, 3);
|
||||
r.beginRendering(clip.getLoX(), clip.getLoY(),
|
||||
clip.getWidth(), clip.getHeight());
|
||||
Renderer r;
|
||||
NormMode norm = (normalize) ? NormMode.ON_WITH_AA : NormMode.OFF;
|
||||
if (bs == null) {
|
||||
PathIterator pi = s.getPathIterator(at, defaultFlat);
|
||||
r.setWindingRule(pi.getWindingRule());
|
||||
PathIterator pi;
|
||||
if (normalize) {
|
||||
pi = new FlatteningPathIterator(
|
||||
new NormalizingPathIterator(s.getPathIterator(at), norm),
|
||||
defaultFlat);
|
||||
} else {
|
||||
pi = s.getPathIterator(at, defaultFlat);
|
||||
}
|
||||
r = new Renderer(3, 3,
|
||||
clip.getLoX(), clip.getLoY(),
|
||||
clip.getWidth(), clip.getHeight(),
|
||||
pi.getWindingRule(), pc);
|
||||
pathTo(pi, r);
|
||||
} else {
|
||||
r.setWindingRule(PathIterator.WIND_NON_ZERO);
|
||||
strokeTo(s, at, bs, thin, normalize, true, r);
|
||||
r = new Renderer(3, 3,
|
||||
clip.getLoX(), clip.getLoY(),
|
||||
clip.getWidth(), clip.getHeight(),
|
||||
PathIterator.WIND_NON_ZERO, pc);
|
||||
strokeTo(s, at, bs, thin, norm, true, r);
|
||||
}
|
||||
r.endRendering();
|
||||
PiscesTileGenerator ptg = new PiscesTileGenerator(pc, r.MAX_AA_ALPHA);
|
||||
@ -420,3 +524,4 @@ public class PiscesRenderingEngine extends RenderingEngine {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
|
||||
package sun.java2d.pisces;
|
||||
|
||||
public class Stroker extends LineSink {
|
||||
public class Stroker implements LineSink {
|
||||
|
||||
private static final int MOVE_TO = 0;
|
||||
private static final int LINE_TO = 1;
|
||||
@ -61,19 +61,15 @@ public class Stroker extends LineSink {
|
||||
*/
|
||||
public static final int CAP_SQUARE = 2;
|
||||
|
||||
LineSink output;
|
||||
private final LineSink output;
|
||||
|
||||
int lineWidth;
|
||||
int capStyle;
|
||||
int joinStyle;
|
||||
int miterLimit;
|
||||
private final int capStyle;
|
||||
private final int joinStyle;
|
||||
|
||||
Transform4 transform;
|
||||
int m00, m01;
|
||||
int m10, m11;
|
||||
private final float m00, m01, m10, m11, det;
|
||||
|
||||
int lineWidth2;
|
||||
long scaledLineWidth2;
|
||||
private final float lineWidth2;
|
||||
private final float scaledLineWidth2;
|
||||
|
||||
// For any pen offset (pen_dx, pen_dy) that does not depend on
|
||||
// the line orientation, the pen should be transformed so that:
|
||||
@ -88,143 +84,86 @@ public class Stroker extends LineSink {
|
||||
//
|
||||
// pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
|
||||
// pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
|
||||
int numPenSegments;
|
||||
int[] pen_dx;
|
||||
int[] pen_dy;
|
||||
boolean[] penIncluded;
|
||||
int[] join;
|
||||
private int numPenSegments;
|
||||
private final float[] pen_dx;
|
||||
private final float[] pen_dy;
|
||||
private boolean[] penIncluded;
|
||||
private final float[] join;
|
||||
|
||||
int[] offset = new int[2];
|
||||
int[] reverse = new int[100];
|
||||
int[] miter = new int[2];
|
||||
long miterLimitSq;
|
||||
private final float[] offset = new float[2];
|
||||
private float[] reverse = new float[100];
|
||||
private final float[] miter = new float[2];
|
||||
private final float miterLimitSq;
|
||||
|
||||
int prev;
|
||||
int rindex;
|
||||
boolean started;
|
||||
boolean lineToOrigin;
|
||||
boolean joinToOrigin;
|
||||
private int prev;
|
||||
private int rindex;
|
||||
private boolean started;
|
||||
private boolean lineToOrigin;
|
||||
private boolean joinToOrigin;
|
||||
|
||||
int sx0, sy0, sx1, sy1, x0, y0, x1, y1;
|
||||
int mx0, my0, mx1, my1, omx, omy;
|
||||
int lx0, ly0, lx1, ly1, lx0p, ly0p, px0, py0;
|
||||
private float sx0, sy0, sx1, sy1, x0, y0, px0, py0;
|
||||
private float mx0, my0, omx, omy;
|
||||
|
||||
double m00_2_m01_2;
|
||||
double m10_2_m11_2;
|
||||
double m00_m10_m01_m11;
|
||||
|
||||
/**
|
||||
* Empty constructor. <code>setOutput</code> and
|
||||
* <code>setParameters</code> must be called prior to calling any
|
||||
* other methods.
|
||||
*/
|
||||
public Stroker() {}
|
||||
private float m00_2_m01_2;
|
||||
private float m10_2_m11_2;
|
||||
private float m00_m10_m01_m11;
|
||||
|
||||
/**
|
||||
* Constructs a <code>Stroker</code>.
|
||||
*
|
||||
* @param output an output <code>LineSink</code>.
|
||||
* @param lineWidth the desired line width in pixels, in S15.16
|
||||
* format.
|
||||
* @param lineWidth the desired line width in pixels
|
||||
* @param capStyle the desired end cap style, one of
|
||||
* <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
|
||||
* <code>CAP_SQUARE</code>.
|
||||
* @param joinStyle the desired line join style, one of
|
||||
* <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
|
||||
* <code>JOIN_BEVEL</code>.
|
||||
* @param miterLimit the desired miter limit, in S15.16 format.
|
||||
* @param miterLimit the desired miter limit
|
||||
* @param transform a <code>Transform4</code> object indicating
|
||||
* the transform that has been previously applied to all incoming
|
||||
* coordinates. This is required in order to produce consistently
|
||||
* shaped end caps and joins.
|
||||
*/
|
||||
public Stroker(LineSink output,
|
||||
int lineWidth,
|
||||
float lineWidth,
|
||||
int capStyle,
|
||||
int joinStyle,
|
||||
int miterLimit,
|
||||
Transform4 transform) {
|
||||
setOutput(output);
|
||||
setParameters(lineWidth, capStyle, joinStyle, miterLimit, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output <code>LineSink</code> of this
|
||||
* <code>Stroker</code>.
|
||||
*
|
||||
* @param output an output <code>LineSink</code>.
|
||||
*/
|
||||
public void setOutput(LineSink output) {
|
||||
float miterLimit,
|
||||
float m00, float m01, float m10, float m11) {
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the parameters of this <code>Stroker</code>.
|
||||
* @param lineWidth the desired line width in pixels, in S15.16
|
||||
* format.
|
||||
* @param capStyle the desired end cap style, one of
|
||||
* <code>CAP_BUTT</code>, <code>CAP_ROUND</code> or
|
||||
* <code>CAP_SQUARE</code>.
|
||||
* @param joinStyle the desired line join style, one of
|
||||
* <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
|
||||
* <code>JOIN_BEVEL</code>.
|
||||
* @param miterLimit the desired miter limit, in S15.16 format.
|
||||
* @param transform a <code>Transform4</code> object indicating
|
||||
* the transform that has been previously applied to all incoming
|
||||
* coordinates. This is required in order to produce consistently
|
||||
* shaped end caps and joins.
|
||||
*/
|
||||
public void setParameters(int lineWidth,
|
||||
int capStyle,
|
||||
int joinStyle,
|
||||
int miterLimit,
|
||||
Transform4 transform) {
|
||||
this.lineWidth = lineWidth;
|
||||
this.lineWidth2 = lineWidth >> 1;
|
||||
this.scaledLineWidth2 = ((long)transform.m00*lineWidth2) >> 16;
|
||||
this.lineWidth2 = lineWidth / 2;
|
||||
this.scaledLineWidth2 = m00 * lineWidth2;
|
||||
this.capStyle = capStyle;
|
||||
this.joinStyle = joinStyle;
|
||||
this.miterLimit = miterLimit;
|
||||
|
||||
this.transform = transform;
|
||||
this.m00 = transform.m00;
|
||||
this.m01 = transform.m01;
|
||||
this.m10 = transform.m10;
|
||||
this.m11 = transform.m11;
|
||||
m00_2_m01_2 = m00*m00 + m01*m01;
|
||||
m10_2_m11_2 = m10*m10 + m11*m11;
|
||||
m00_m10_m01_m11 = m00*m10 + m01*m11;
|
||||
|
||||
this.m00_2_m01_2 = (double)m00*m00 + (double)m01*m01;
|
||||
this.m10_2_m11_2 = (double)m10*m10 + (double)m11*m11;
|
||||
this.m00_m10_m01_m11 = (double)m00*m10 + (double)m01*m11;
|
||||
this.m00 = m00;
|
||||
this.m01 = m01;
|
||||
this.m10 = m10;
|
||||
this.m11 = m11;
|
||||
det = m00*m11 - m01*m10;
|
||||
|
||||
double dm00 = m00/65536.0;
|
||||
double dm01 = m01/65536.0;
|
||||
double dm10 = m10/65536.0;
|
||||
double dm11 = m11/65536.0;
|
||||
double determinant = dm00*dm11 - dm01*dm10;
|
||||
float limit = miterLimit * lineWidth2 * det;
|
||||
this.miterLimitSq = limit*limit;
|
||||
|
||||
if (joinStyle == JOIN_MITER) {
|
||||
double limit =
|
||||
(miterLimit/65536.0)*(lineWidth2/65536.0)*determinant;
|
||||
double limitSq = limit*limit;
|
||||
this.miterLimitSq = (long)(limitSq*65536.0*65536.0);
|
||||
}
|
||||
|
||||
this.numPenSegments = (int)(3.14159f*lineWidth/65536.0f);
|
||||
if (pen_dx == null || pen_dx.length < numPenSegments) {
|
||||
this.pen_dx = new int[numPenSegments];
|
||||
this.pen_dy = new int[numPenSegments];
|
||||
this.penIncluded = new boolean[numPenSegments];
|
||||
this.join = new int[2*numPenSegments];
|
||||
}
|
||||
this.numPenSegments = (int)(3.14159f * lineWidth);
|
||||
this.pen_dx = new float[numPenSegments];
|
||||
this.pen_dy = new float[numPenSegments];
|
||||
this.penIncluded = new boolean[numPenSegments];
|
||||
this.join = new float[2*numPenSegments];
|
||||
|
||||
for (int i = 0; i < numPenSegments; i++) {
|
||||
double r = lineWidth/2.0;
|
||||
double theta = (double)i*2.0*Math.PI/numPenSegments;
|
||||
double theta = (i * 2.0 * Math.PI)/numPenSegments;
|
||||
|
||||
double cos = Math.cos(theta);
|
||||
double sin = Math.sin(theta);
|
||||
pen_dx[i] = (int)(r*(dm00*cos + dm01*sin));
|
||||
pen_dy[i] = (int)(r*(dm10*cos + dm11*sin));
|
||||
pen_dx[i] = (float)(lineWidth2 * (m00*cos + m01*sin));
|
||||
pen_dy[i] = (float)(lineWidth2 * (m10*cos + m11*sin));
|
||||
}
|
||||
|
||||
prev = CLOSE;
|
||||
@ -233,32 +172,31 @@ public class Stroker extends LineSink {
|
||||
lineToOrigin = false;
|
||||
}
|
||||
|
||||
private void computeOffset(int x0, int y0, int x1, int y1, int[] m) {
|
||||
long lx = (long)x1 - (long)x0;
|
||||
long ly = (long)y1 - (long)y0;
|
||||
private void computeOffset(float x0, float y0,
|
||||
float x1, float y1, float[] m) {
|
||||
float lx = x1 - x0;
|
||||
float ly = y1 - y0;
|
||||
|
||||
int dx, dy;
|
||||
float dx, dy;
|
||||
if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
|
||||
long ilen = PiscesMath.hypot(lx, ly);
|
||||
float ilen = (float)Math.hypot(lx, ly);
|
||||
if (ilen == 0) {
|
||||
dx = dy = 0;
|
||||
} else {
|
||||
dx = (int)( (ly*scaledLineWidth2)/ilen);
|
||||
dy = (int)(-(lx*scaledLineWidth2)/ilen);
|
||||
dx = (ly * scaledLineWidth2)/ilen;
|
||||
dy = -(lx * scaledLineWidth2)/ilen;
|
||||
}
|
||||
} else {
|
||||
double dlx = x1 - x0;
|
||||
double dly = y1 - y0;
|
||||
double det = (double)m00*m11 - (double)m01*m10;
|
||||
int sdet = (det > 0) ? 1 : -1;
|
||||
double a = dly*m00 - dlx*m10;
|
||||
double b = dly*m01 - dlx*m11;
|
||||
double dh = PiscesMath.hypot(a, b);
|
||||
double div = sdet*lineWidth2/(65536.0*dh);
|
||||
double ddx = dly*m00_2_m01_2 - dlx*m00_m10_m01_m11;
|
||||
double ddy = dly*m00_m10_m01_m11 - dlx*m10_2_m11_2;
|
||||
dx = (int)(ddx*div);
|
||||
dy = (int)(ddy*div);
|
||||
float a = ly * m00 - lx * m10;
|
||||
float b = ly * m01 - lx * m11;
|
||||
float dh = (float)Math.hypot(a, b);
|
||||
float div = sdet * lineWidth2/dh;
|
||||
|
||||
float ddx = ly * m00_2_m01_2 - lx * m00_m10_m01_m11;
|
||||
float ddy = ly * m00_m10_m01_m11 - lx * m10_2_m11_2;
|
||||
dx = ddx*div;
|
||||
dy = ddy*div;
|
||||
}
|
||||
|
||||
m[0] = dx;
|
||||
@ -267,58 +205,43 @@ public class Stroker extends LineSink {
|
||||
|
||||
private void ensureCapacity(int newrindex) {
|
||||
if (reverse.length < newrindex) {
|
||||
int[] tmp = new int[Math.max(newrindex, 6*reverse.length/5)];
|
||||
System.arraycopy(reverse, 0, tmp, 0, rindex);
|
||||
this.reverse = tmp;
|
||||
reverse = java.util.Arrays.copyOf(reverse, 6*reverse.length/5);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCCW(int x0, int y0,
|
||||
int x1, int y1,
|
||||
int x2, int y2) {
|
||||
int dx0 = x1 - x0;
|
||||
int dy0 = y1 - y0;
|
||||
int dx1 = x2 - x1;
|
||||
int dy1 = y2 - y1;
|
||||
return (long)dx0*dy1 < (long)dy0*dx1;
|
||||
private boolean isCCW(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2) {
|
||||
return (x1 - x0) * (y2 - y1) < (y1 - y0) * (x2 - x1);
|
||||
}
|
||||
|
||||
private boolean side(int x, int y, int x0, int y0, int x1, int y1) {
|
||||
long lx = x;
|
||||
long ly = y;
|
||||
long lx0 = x0;
|
||||
long ly0 = y0;
|
||||
long lx1 = x1;
|
||||
long ly1 = y1;
|
||||
|
||||
return (ly0 - ly1)*lx + (lx1 - lx0)*ly + (lx0*ly1 - lx1*ly0) > 0;
|
||||
private boolean side(float x, float y,
|
||||
float x0, float y0,
|
||||
float x1, float y1) {
|
||||
return (y0 - y1)*x + (x1 - x0)*y + (x0*y1 - x1*y0) > 0;
|
||||
}
|
||||
|
||||
private int computeRoundJoin(int cx, int cy,
|
||||
int xa, int ya,
|
||||
int xb, int yb,
|
||||
private int computeRoundJoin(float cx, float cy,
|
||||
float xa, float ya,
|
||||
float xb, float yb,
|
||||
int side,
|
||||
boolean flip,
|
||||
int[] join) {
|
||||
int px, py;
|
||||
float[] join) {
|
||||
float px, py;
|
||||
int ncoords = 0;
|
||||
|
||||
boolean centerSide;
|
||||
if (side == 0) {
|
||||
centerSide = side(cx, cy, xa, ya, xb, yb);
|
||||
} else {
|
||||
centerSide = (side == 1) ? true : false;
|
||||
centerSide = (side == 1);
|
||||
}
|
||||
for (int i = 0; i < numPenSegments; i++) {
|
||||
px = cx + pen_dx[i];
|
||||
py = cy + pen_dy[i];
|
||||
|
||||
boolean penSide = side(px, py, xa, ya, xb, yb);
|
||||
if (penSide != centerSide) {
|
||||
penIncluded[i] = true;
|
||||
} else {
|
||||
penIncluded[i] = false;
|
||||
}
|
||||
penIncluded[i] = (penSide != centerSide);
|
||||
}
|
||||
|
||||
int start = -1, end = -1;
|
||||
@ -338,10 +261,10 @@ public class Stroker extends LineSink {
|
||||
}
|
||||
|
||||
if (start != -1 && end != -1) {
|
||||
long dxa = cx + pen_dx[start] - xa;
|
||||
long dya = cy + pen_dy[start] - ya;
|
||||
long dxb = cx + pen_dx[start] - xb;
|
||||
long dyb = cy + pen_dy[start] - yb;
|
||||
float dxa = cx + pen_dx[start] - xa;
|
||||
float dya = cy + pen_dy[start] - ya;
|
||||
float dxb = cx + pen_dx[start] - xb;
|
||||
float dyb = cy + pen_dy[start] - yb;
|
||||
|
||||
boolean rev = (dxa*dxa + dya*dya > dxb*dxb + dyb*dyb);
|
||||
int i = rev ? end : start;
|
||||
@ -362,22 +285,25 @@ public class Stroker extends LineSink {
|
||||
return ncoords/2;
|
||||
}
|
||||
|
||||
private static final long ROUND_JOIN_THRESHOLD = 1000L;
|
||||
private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
|
||||
// pisces used to use fixed point arithmetic with 16 decimal digits. I
|
||||
// didn't want to change the values of the constants below when I converted
|
||||
// it to floating point, so that's why the divisions by 2^16 are there.
|
||||
private static final float ROUND_JOIN_THRESHOLD = 1000/65536f;
|
||||
private static final float ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000/65536f;
|
||||
|
||||
private void drawRoundJoin(int x, int y,
|
||||
int omx, int omy, int mx, int my,
|
||||
private void drawRoundJoin(float x, float y,
|
||||
float omx, float omy, float mx, float my,
|
||||
int side,
|
||||
boolean flip,
|
||||
boolean rev,
|
||||
long threshold) {
|
||||
float threshold) {
|
||||
if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
long domx = (long)omx - mx;
|
||||
long domy = (long)omy - my;
|
||||
long len = domx*domx + domy*domy;
|
||||
float domx = omx - mx;
|
||||
float domy = omy - my;
|
||||
float len = domx*domx + domy*domy;
|
||||
if (len < threshold) {
|
||||
return;
|
||||
}
|
||||
@ -389,10 +315,10 @@ public class Stroker extends LineSink {
|
||||
my = -my;
|
||||
}
|
||||
|
||||
int bx0 = x + omx;
|
||||
int by0 = y + omy;
|
||||
int bx1 = x + mx;
|
||||
int by1 = y + my;
|
||||
float bx0 = x + omx;
|
||||
float by0 = y + omy;
|
||||
float bx1 = x + mx;
|
||||
float by1 = y + my;
|
||||
|
||||
int npoints = computeRoundJoin(x, y,
|
||||
bx0, by0, bx1, by1, side, flip,
|
||||
@ -404,40 +330,30 @@ public class Stroker extends LineSink {
|
||||
|
||||
// Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
|
||||
// and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
|
||||
private void computeMiter(int ix0, int iy0, int ix1, int iy1,
|
||||
int ix0p, int iy0p, int ix1p, int iy1p,
|
||||
int[] m) {
|
||||
long x0 = ix0;
|
||||
long y0 = iy0;
|
||||
long x1 = ix1;
|
||||
long y1 = iy1;
|
||||
private void computeMiter(float x0, float y0, float x1, float y1,
|
||||
float x0p, float y0p, float x1p, float y1p,
|
||||
float[] m) {
|
||||
float x10 = x1 - x0;
|
||||
float y10 = y1 - y0;
|
||||
float x10p = x1p - x0p;
|
||||
float y10p = y1p - y0p;
|
||||
|
||||
long x0p = ix0p;
|
||||
long y0p = iy0p;
|
||||
long x1p = ix1p;
|
||||
long y1p = iy1p;
|
||||
|
||||
long x10 = x1 - x0;
|
||||
long y10 = y1 - y0;
|
||||
long x10p = x1p - x0p;
|
||||
long y10p = y1p - y0p;
|
||||
|
||||
long den = (x10*y10p - x10p*y10) >> 16;
|
||||
float den = x10*y10p - x10p*y10;
|
||||
if (den == 0) {
|
||||
m[0] = ix0;
|
||||
m[1] = iy0;
|
||||
m[0] = x0;
|
||||
m[1] = y0;
|
||||
return;
|
||||
}
|
||||
|
||||
long t = (x1p*(y0 - y0p) - x0*y10p + x0p*(y1p - y0)) >> 16;
|
||||
m[0] = (int)(x0 + (t*x10)/den);
|
||||
m[1] = (int)(y0 + (t*y10)/den);
|
||||
float t = x1p*(y0 - y0p) - x0*y10p + x0p*(y1p - y0);
|
||||
m[0] = x0 + (t*x10)/den;
|
||||
m[1] = y0 + (t*y10)/den;
|
||||
}
|
||||
|
||||
private void drawMiter(int px0, int py0,
|
||||
int x0, int y0,
|
||||
int x1, int y1,
|
||||
int omx, int omy, int mx, int my,
|
||||
private void drawMiter(float px0, float py0,
|
||||
float x0, float y0,
|
||||
float x1, float y1,
|
||||
float omx, float omy, float mx, float my,
|
||||
boolean rev) {
|
||||
if (mx == omx && my == omy) {
|
||||
return;
|
||||
@ -461,11 +377,11 @@ public class Stroker extends LineSink {
|
||||
miter);
|
||||
|
||||
// Compute miter length in untransformed coordinates
|
||||
long dx = (long)miter[0] - x0;
|
||||
long dy = (long)miter[1] - y0;
|
||||
long a = (dy*m00 - dx*m10) >> 16;
|
||||
long b = (dy*m01 - dx*m11) >> 16;
|
||||
long lenSq = a*a + b*b;
|
||||
float dx = miter[0] - x0;
|
||||
float dy = miter[1] - y0;
|
||||
float a = dy*m00 - dx*m10;
|
||||
float b = dy*m01 - dx*m11;
|
||||
float lenSq = a*a + b*b;
|
||||
|
||||
if (lenSq < miterLimitSq) {
|
||||
emitLineTo(miter[0], miter[1], rev);
|
||||
@ -473,7 +389,7 @@ public class Stroker extends LineSink {
|
||||
}
|
||||
|
||||
|
||||
public void moveTo(int x0, int y0) {
|
||||
public void moveTo(float x0, float y0) {
|
||||
// System.out.println("Stroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
|
||||
|
||||
if (lineToOrigin) {
|
||||
@ -501,7 +417,7 @@ public class Stroker extends LineSink {
|
||||
this.joinSegment = true;
|
||||
}
|
||||
|
||||
public void lineTo(int x1, int y1) {
|
||||
public void lineTo(float x1, float y1) {
|
||||
// System.out.println("Stroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
|
||||
|
||||
if (lineToOrigin) {
|
||||
@ -526,10 +442,10 @@ public class Stroker extends LineSink {
|
||||
joinSegment = false;
|
||||
}
|
||||
|
||||
private void lineToImpl(int x1, int y1, boolean joinSegment) {
|
||||
private void lineToImpl(float x1, float y1, boolean joinSegment) {
|
||||
computeOffset(x0, y0, x1, y1, offset);
|
||||
int mx = offset[0];
|
||||
int my = offset[1];
|
||||
float mx = offset[0];
|
||||
float my = offset[1];
|
||||
|
||||
if (!started) {
|
||||
emitMoveTo(x0 + mx, y0 + my);
|
||||
@ -567,10 +483,6 @@ public class Stroker extends LineSink {
|
||||
emitLineTo(x0 - mx, y0 - my, true);
|
||||
emitLineTo(x1 - mx, y1 - my, true);
|
||||
|
||||
lx0 = x1 + mx; ly0 = y1 + my;
|
||||
lx0p = x1 - mx; ly0p = y1 - my;
|
||||
lx1 = x1; ly1 = y1;
|
||||
|
||||
this.omx = mx;
|
||||
this.omy = my;
|
||||
this.px0 = x0;
|
||||
@ -594,8 +506,8 @@ public class Stroker extends LineSink {
|
||||
}
|
||||
|
||||
computeOffset(x0, y0, sx0, sy0, offset);
|
||||
int mx = offset[0];
|
||||
int my = offset[1];
|
||||
float mx = offset[0];
|
||||
float my = offset[1];
|
||||
|
||||
// Draw penultimate join
|
||||
boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
|
||||
@ -678,12 +590,10 @@ public class Stroker extends LineSink {
|
||||
this.prev = MOVE_TO;
|
||||
}
|
||||
|
||||
long lineLength(long ldx, long ldy) {
|
||||
long ldet = ((long)m00*m11 - (long)m01*m10) >> 16;
|
||||
long la = ((long)ldy*m00 - (long)ldx*m10)/ldet;
|
||||
long lb = ((long)ldy*m01 - (long)ldx*m11)/ldet;
|
||||
long llen = (int)PiscesMath.hypot(la, lb);
|
||||
return llen;
|
||||
double userSpaceLineLength(double dx, double dy) {
|
||||
double a = (dy*m00 - dx*m10)/det;
|
||||
double b = (dy*m01 - dx*m11)/det;
|
||||
return Math.hypot(a, b);
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
@ -692,13 +602,13 @@ public class Stroker extends LineSink {
|
||||
omx, omy, -omx, -omy, 1, false, false,
|
||||
ROUND_JOIN_THRESHOLD);
|
||||
} else if (capStyle == CAP_SQUARE) {
|
||||
long ldx = (long)(px0 - x0);
|
||||
long ldy = (long)(py0 - y0);
|
||||
long llen = lineLength(ldx, ldy);
|
||||
long s = (long)lineWidth2*65536/llen;
|
||||
float dx = px0 - x0;
|
||||
float dy = py0 - y0;
|
||||
float len = (float)userSpaceLineLength(dx, dy);
|
||||
float s = lineWidth2/len;
|
||||
|
||||
int capx = x0 - (int)(ldx*s >> 16);
|
||||
int capy = y0 - (int)(ldy*s >> 16);
|
||||
float capx = x0 - dx*s;
|
||||
float capy = y0 - dy*s;
|
||||
|
||||
emitLineTo(capx + omx, capy + omy);
|
||||
emitLineTo(capx - omx, capy - omy);
|
||||
@ -714,13 +624,13 @@ public class Stroker extends LineSink {
|
||||
-mx0, -my0, mx0, my0, 1, false, false,
|
||||
ROUND_JOIN_THRESHOLD);
|
||||
} else if (capStyle == CAP_SQUARE) {
|
||||
long ldx = (long)(sx1 - sx0);
|
||||
long ldy = (long)(sy1 - sy0);
|
||||
long llen = lineLength(ldx, ldy);
|
||||
long s = (long)lineWidth2*65536/llen;
|
||||
float dx = sx1 - sx0;
|
||||
float dy = sy1 - sy0;
|
||||
float len = (float)userSpaceLineLength(dx, dy);
|
||||
float s = lineWidth2/len;
|
||||
|
||||
int capx = sx0 - (int)(ldx*s >> 16);
|
||||
int capy = sy0 - (int)(ldy*s >> 16);
|
||||
float capx = sx0 - dx*s;
|
||||
float capy = sy0 - dy*s;
|
||||
|
||||
emitLineTo(capx - mx0, capy - my0);
|
||||
emitLineTo(capx + mx0, capy + my0);
|
||||
@ -730,17 +640,17 @@ public class Stroker extends LineSink {
|
||||
this.joinSegment = false;
|
||||
}
|
||||
|
||||
private void emitMoveTo(int x0, int y0) {
|
||||
private void emitMoveTo(float x0, float y0) {
|
||||
// System.out.println("Stroker.emitMoveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
|
||||
output.moveTo(x0, y0);
|
||||
}
|
||||
|
||||
private void emitLineTo(int x1, int y1) {
|
||||
private void emitLineTo(float x1, float y1) {
|
||||
// System.out.println("Stroker.emitLineTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
|
||||
output.lineTo(x1, y1);
|
||||
}
|
||||
|
||||
private void emitLineTo(int x1, int y1, boolean rev) {
|
||||
private void emitLineTo(float x1, float y1, boolean rev) {
|
||||
if (rev) {
|
||||
ensureCapacity(rindex + 2);
|
||||
reverse[rindex++] = x1;
|
||||
@ -755,3 +665,4 @@ public class Stroker extends LineSink {
|
||||
output.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.java2d.pisces;
|
||||
|
||||
public class Transform4 {
|
||||
|
||||
public int m00, m01, m10, m11;
|
||||
// double det; // det*65536
|
||||
|
||||
public Transform4() {
|
||||
this(1 << 16, 0, 0, 1 << 16);
|
||||
}
|
||||
|
||||
public Transform4(int m00, int m01,
|
||||
int m10, int m11) {
|
||||
this.m00 = m00;
|
||||
this.m01 = m01;
|
||||
this.m10 = m10;
|
||||
this.m11 = m11;
|
||||
|
||||
// this.det = (double)m00*m11 - (double)m01*m10;
|
||||
}
|
||||
|
||||
// public Transform4 createInverse() {
|
||||
// double dm00 = m00/65536.0;
|
||||
// double dm01 = m01/65536.0;
|
||||
// double dm10 = m10/65536.0;
|
||||
// double dm11 = m11/65536.0;
|
||||
|
||||
// double invdet = 65536.0/(dm00*dm11 - dm01*dm10);
|
||||
|
||||
// int im00 = (int)( dm11*invdet);
|
||||
// int im01 = (int)(-dm01*invdet);
|
||||
// int im10 = (int)(-dm10*invdet);
|
||||
// int im11 = (int)( dm00*invdet);
|
||||
|
||||
// return new Transform4(im00, im01, im10, im11);
|
||||
// }
|
||||
|
||||
// public void transform(int[] point) {
|
||||
// }
|
||||
|
||||
// /**
|
||||
// * Returns the length of the line segment obtained by inverse
|
||||
// * transforming the points <code>(x0, y0)</code> and <code>(x1,
|
||||
// * y1)</code>.
|
||||
// */
|
||||
// public int getTransformedLength(int x0, int x1, int y0, int y1) {
|
||||
// int lx = x1 - x0;
|
||||
// int ly = y1 - y0;
|
||||
|
||||
// double a = (double)m00*ly - (double)m10*lx;
|
||||
// double b = (double)m01*ly - (double)m11*lx;
|
||||
// double len = PiscesMath.sqrt((a*a + b*b)/(det*det));
|
||||
// return (int)(len*65536.0);
|
||||
// }
|
||||
|
||||
// public int getType() {
|
||||
// }
|
||||
|
||||
}
|
@ -59,7 +59,7 @@ public class FileURLConnection extends URLConnection {
|
||||
String filename;
|
||||
boolean isDirectory = false;
|
||||
boolean exists = false;
|
||||
List files;
|
||||
List<String> files;
|
||||
|
||||
long length = -1;
|
||||
long lastModified = 0;
|
||||
@ -81,7 +81,10 @@ public class FileURLConnection extends URLConnection {
|
||||
filename = file.toString();
|
||||
isDirectory = file.isDirectory();
|
||||
if (isDirectory) {
|
||||
files = (List) Arrays.asList(file.list());
|
||||
String[] fileList = file.list();
|
||||
if (fileList == null)
|
||||
throw new FileNotFoundException(filename + " exists, but is not accessible");
|
||||
files = Arrays.<String>asList(fileList);
|
||||
} else {
|
||||
|
||||
is = new BufferedInputStream(new FileInputStream(filename));
|
||||
@ -197,7 +200,7 @@ public class FileURLConnection extends URLConnection {
|
||||
Collections.sort(files, Collator.getInstance());
|
||||
|
||||
for (int i = 0 ; i < files.size() ; i++) {
|
||||
String fileName = (String)files.get(i);
|
||||
String fileName = files.get(i);
|
||||
buf.append(fileName);
|
||||
buf.append("\n");
|
||||
}
|
||||
|
@ -1768,6 +1768,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
|
||||
// Not really necessary for a tunnel, but can't hurt
|
||||
requests.setIfNotSet("Accept", acceptString);
|
||||
|
||||
if (http.getHttpKeepAliveSet()) {
|
||||
requests.setIfNotSet("Proxy-Connection", "keep-alive");
|
||||
}
|
||||
|
||||
setPreemptiveProxyAuthentication(requests);
|
||||
|
||||
/* Log the CONNECT request */
|
||||
|
@ -536,9 +536,11 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long read0(ByteBuffer[] bufs) throws IOException {
|
||||
if (bufs == null)
|
||||
throw new NullPointerException();
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
@ -552,7 +554,7 @@ class DatagramChannelImpl
|
||||
return 0;
|
||||
readerThread = NativeThread.current();
|
||||
do {
|
||||
n = IOUtil.read(fd, bufs, nd);
|
||||
n = IOUtil.read(fd, dsts, offset, length, nd);
|
||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||
return IOStatus.normalize(n);
|
||||
} finally {
|
||||
@ -563,15 +565,6 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return read0(Util.subsequence(dsts, offset, length));
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
@ -599,9 +592,11 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long write0(ByteBuffer[] bufs) throws IOException {
|
||||
if (bufs == null)
|
||||
throw new NullPointerException();
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
@ -615,7 +610,7 @@ class DatagramChannelImpl
|
||||
return 0;
|
||||
writerThread = NativeThread.current();
|
||||
do {
|
||||
n = IOUtil.write(fd, bufs, nd);
|
||||
n = IOUtil.write(fd, srcs, offset, length, nd);
|
||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||
return IOStatus.normalize(n);
|
||||
} finally {
|
||||
@ -626,15 +621,6 @@ class DatagramChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return write0(Util.subsequence(srcs, offset, length));
|
||||
}
|
||||
|
||||
protected void implConfigureBlocking(boolean block) throws IOException {
|
||||
IOUtil.configureBlocking(fd, block);
|
||||
}
|
||||
|
@ -143,7 +143,11 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long read0(ByteBuffer[] dsts) throws IOException {
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
ensureOpen();
|
||||
if (!readable)
|
||||
throw new NonReadableChannelException();
|
||||
@ -156,7 +160,7 @@ public class FileChannelImpl
|
||||
if (!isOpen())
|
||||
return 0;
|
||||
do {
|
||||
n = IOUtil.read(fd, dsts, nd);
|
||||
n = IOUtil.read(fd, dsts, offset, length, nd);
|
||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||
return IOStatus.normalize(n);
|
||||
} finally {
|
||||
@ -167,15 +171,6 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return read0(Util.subsequence(dsts, offset, length));
|
||||
}
|
||||
|
||||
public int write(ByteBuffer src) throws IOException {
|
||||
ensureOpen();
|
||||
if (!writable)
|
||||
@ -200,7 +195,11 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long write0(ByteBuffer[] srcs) throws IOException {
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
ensureOpen();
|
||||
if (!writable)
|
||||
throw new NonWritableChannelException();
|
||||
@ -213,7 +212,7 @@ public class FileChannelImpl
|
||||
if (!isOpen())
|
||||
return 0;
|
||||
do {
|
||||
n = IOUtil.write(fd, srcs, nd);
|
||||
n = IOUtil.write(fd, srcs, offset, length, nd);
|
||||
} while ((n == IOStatus.INTERRUPTED) && isOpen());
|
||||
return IOStatus.normalize(n);
|
||||
} finally {
|
||||
@ -224,16 +223,6 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return write0(Util.subsequence(srcs, offset, length));
|
||||
}
|
||||
|
||||
|
||||
// -- Other operations --
|
||||
|
||||
public long position() throws IOException {
|
||||
@ -440,24 +429,45 @@ public class FileChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long transferToTrustedChannel(long position, int icount,
|
||||
// Maximum size to map when using a mapped buffer
|
||||
private static final long MAPPED_TRANSFER_SIZE = 8L*1024L*1024L;
|
||||
|
||||
private long transferToTrustedChannel(long position, long count,
|
||||
WritableByteChannel target)
|
||||
throws IOException
|
||||
{
|
||||
if ( !((target instanceof FileChannelImpl)
|
||||
|| (target instanceof SelChImpl)))
|
||||
boolean isSelChImpl = (target instanceof SelChImpl);
|
||||
if (!((target instanceof FileChannelImpl) || isSelChImpl))
|
||||
return IOStatus.UNSUPPORTED;
|
||||
|
||||
// Trusted target: Use a mapped buffer
|
||||
MappedByteBuffer dbb = null;
|
||||
try {
|
||||
dbb = map(MapMode.READ_ONLY, position, icount);
|
||||
// ## Bug: Closing this channel will not terminate the write
|
||||
return target.write(dbb);
|
||||
} finally {
|
||||
if (dbb != null)
|
||||
unmap(dbb);
|
||||
long remaining = count;
|
||||
while (remaining > 0L) {
|
||||
long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
|
||||
try {
|
||||
MappedByteBuffer dbb = map(MapMode.READ_ONLY, position, size);
|
||||
try {
|
||||
// ## Bug: Closing this channel will not terminate the write
|
||||
int n = target.write(dbb);
|
||||
assert n >= 0;
|
||||
remaining -= n;
|
||||
if (isSelChImpl) {
|
||||
// one attempt to write to selectable channel
|
||||
break;
|
||||
}
|
||||
assert n > 0;
|
||||
position += n;
|
||||
} finally {
|
||||
unmap(dbb);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
// Only throw exception if no bytes have been written
|
||||
if (remaining == count)
|
||||
throw ioe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return count - remaining;
|
||||
}
|
||||
|
||||
private long transferToArbitraryChannel(long position, int icount,
|
||||
@ -535,20 +545,34 @@ public class FileChannelImpl
|
||||
long position, long count)
|
||||
throws IOException
|
||||
{
|
||||
// Note we could loop here to accumulate more at once
|
||||
synchronized (src.positionLock) {
|
||||
long p = src.position();
|
||||
int icount = (int)Math.min(Math.min(count, Integer.MAX_VALUE),
|
||||
src.size() - p);
|
||||
// ## Bug: Closing this channel will not terminate the write
|
||||
MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, icount);
|
||||
try {
|
||||
long n = write(bb, position);
|
||||
src.position(p + n);
|
||||
return n;
|
||||
} finally {
|
||||
unmap(bb);
|
||||
long pos = src.position();
|
||||
long max = Math.min(count, src.size() - pos);
|
||||
|
||||
long remaining = max;
|
||||
long p = pos;
|
||||
while (remaining > 0L) {
|
||||
long size = Math.min(remaining, MAPPED_TRANSFER_SIZE);
|
||||
// ## Bug: Closing this channel will not terminate the write
|
||||
MappedByteBuffer bb = src.map(MapMode.READ_ONLY, p, size);
|
||||
try {
|
||||
long n = write(bb, position);
|
||||
assert n > 0;
|
||||
p += n;
|
||||
position += n;
|
||||
remaining -= n;
|
||||
} catch (IOException ioe) {
|
||||
// Only throw exception if no bytes have been written
|
||||
if (remaining == max)
|
||||
throw ioe;
|
||||
break;
|
||||
} finally {
|
||||
unmap(bb);
|
||||
}
|
||||
}
|
||||
long nwritten = max - remaining;
|
||||
src.position(pos + nwritten);
|
||||
return nwritten;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,34 +38,6 @@ class IOUtil {
|
||||
|
||||
private IOUtil() { } // No instantiation
|
||||
|
||||
/*
|
||||
* Returns the index of first buffer in bufs with remaining,
|
||||
* or -1 if there is nothing left
|
||||
*/
|
||||
private static int remaining(ByteBuffer[] bufs) {
|
||||
int numBufs = bufs.length;
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (bufs[i].hasRemaining()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a new ByteBuffer array with only unfinished buffers in it
|
||||
*/
|
||||
private static ByteBuffer[] skipBufs(ByteBuffer[] bufs,
|
||||
int nextWithRemaining)
|
||||
{
|
||||
int newSize = bufs.length - nextWithRemaining;
|
||||
ByteBuffer[] temp = new ByteBuffer[newSize];
|
||||
for (int i=0; i<newSize; i++) {
|
||||
temp[i] = bufs[i + nextWithRemaining];
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
static int write(FileDescriptor fd, ByteBuffer src, long position,
|
||||
NativeDispatcher nd, Object lock)
|
||||
throws IOException
|
||||
@ -93,7 +65,7 @@ class IOUtil {
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
Util.releaseTemporaryDirectBuffer(bb);
|
||||
Util.offerFirstTemporaryDirectBuffer(bb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,88 +97,81 @@ class IOUtil {
|
||||
static long write(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
|
||||
throws IOException
|
||||
{
|
||||
int nextWithRemaining = remaining(bufs);
|
||||
// if all bufs are empty we should return immediately
|
||||
if (nextWithRemaining < 0)
|
||||
return 0;
|
||||
// If some bufs are empty we should skip them
|
||||
if (nextWithRemaining > 0)
|
||||
bufs = skipBufs(bufs, nextWithRemaining);
|
||||
return write(fd, bufs, 0, bufs.length, nd);
|
||||
}
|
||||
|
||||
int numBufs = bufs.length;
|
||||
static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
|
||||
NativeDispatcher nd)
|
||||
throws IOException
|
||||
{
|
||||
IOVecWrapper vec = IOVecWrapper.get(length);
|
||||
|
||||
// Create shadow to ensure DirectByteBuffers are used
|
||||
ByteBuffer[] shadow = new ByteBuffer[numBufs];
|
||||
boolean completed = false;
|
||||
int iov_len = 0;
|
||||
try {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
int pos = bufs[i].position();
|
||||
int lim = bufs[i].limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
ByteBuffer bb = Util.getTemporaryDirectBuffer(rem);
|
||||
shadow[i] = bb;
|
||||
// Leave slow buffer position untouched; it will be updated
|
||||
// after we see how many bytes were really written out
|
||||
bb.put(bufs[i]);
|
||||
bufs[i].position(pos);
|
||||
bb.flip();
|
||||
} else {
|
||||
shadow[i] = bufs[i];
|
||||
// Iterate over buffers to populate native iovec array.
|
||||
int count = offset + length;
|
||||
for (int i=offset; i<count; i++) {
|
||||
ByteBuffer buf = bufs[i];
|
||||
int pos = buf.position();
|
||||
int lim = buf.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
if (rem > 0) {
|
||||
vec.setBuffer(iov_len, buf, pos, rem);
|
||||
|
||||
// allocate shadow buffer to ensure I/O is done with direct buffer
|
||||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
shadow.put(buf);
|
||||
shadow.flip();
|
||||
vec.setShadow(iov_len, shadow);
|
||||
buf.position(pos); // temporarily restore position in user buffer
|
||||
buf = shadow;
|
||||
pos = shadow.position();
|
||||
}
|
||||
|
||||
vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
|
||||
vec.putLen(iov_len, rem);
|
||||
iov_len++;
|
||||
}
|
||||
}
|
||||
if (iov_len == 0)
|
||||
return 0L;
|
||||
|
||||
IOVecWrapper vec = null;
|
||||
long bytesWritten = 0;
|
||||
try {
|
||||
// Create a native iovec array
|
||||
vec= new IOVecWrapper(numBufs);
|
||||
|
||||
// Fill in the iovec array with appropriate data
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer nextBuffer = shadow[i];
|
||||
// put in the buffer addresses
|
||||
long pos = nextBuffer.position();
|
||||
long len = nextBuffer.limit() - pos;
|
||||
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
|
||||
vec.putLen(i, len);
|
||||
}
|
||||
|
||||
// Invoke native call to fill the buffers
|
||||
bytesWritten = nd.writev(fd, vec.address, numBufs);
|
||||
} finally {
|
||||
vec.free();
|
||||
}
|
||||
long returnVal = bytesWritten;
|
||||
long bytesWritten = nd.writev(fd, vec.address, iov_len);
|
||||
|
||||
// Notify the buffers how many bytes were taken
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer nextBuffer = bufs[i];
|
||||
int pos = nextBuffer.position();
|
||||
int lim = nextBuffer.limit();
|
||||
assert (pos <= lim);
|
||||
int len = (pos <= lim ? lim - pos : lim);
|
||||
if (bytesWritten >= len) {
|
||||
bytesWritten -= len;
|
||||
int newPosition = pos + len;
|
||||
nextBuffer.position(newPosition);
|
||||
} else { // Buffers not completely filled
|
||||
if (bytesWritten > 0) {
|
||||
assert(pos + bytesWritten < (long)Integer.MAX_VALUE);
|
||||
int newPosition = (int)(pos + bytesWritten);
|
||||
nextBuffer.position(newPosition);
|
||||
}
|
||||
break;
|
||||
long left = bytesWritten;
|
||||
for (int j=0; j<iov_len; j++) {
|
||||
if (left > 0) {
|
||||
ByteBuffer buf = vec.getBuffer(j);
|
||||
int pos = vec.getPosition(j);
|
||||
int rem = vec.getRemaining(j);
|
||||
int n = (left > rem) ? rem : (int)left;
|
||||
buf.position(pos + n);
|
||||
left -= n;
|
||||
}
|
||||
// return shadow buffers to buffer pool
|
||||
ByteBuffer shadow = vec.getShadow(j);
|
||||
if (shadow != null)
|
||||
Util.offerLastTemporaryDirectBuffer(shadow);
|
||||
vec.clearRefs(j);
|
||||
}
|
||||
return returnVal;
|
||||
|
||||
completed = true;
|
||||
return bytesWritten;
|
||||
|
||||
} finally {
|
||||
// return any substituted buffers to cache
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer bb = shadow[i];
|
||||
if (bb != null && bb != bufs[i]) {
|
||||
Util.releaseTemporaryDirectBuffer(bb);
|
||||
// if an error occurred then clear refs to buffers and return any shadow
|
||||
// buffers to cache
|
||||
if (!completed) {
|
||||
for (int j=0; j<iov_len; j++) {
|
||||
ByteBuffer shadow = vec.getShadow(j);
|
||||
if (shadow != null)
|
||||
Util.offerLastTemporaryDirectBuffer(shadow);
|
||||
vec.clearRefs(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +196,7 @@ class IOUtil {
|
||||
dst.put(bb);
|
||||
return n;
|
||||
} finally {
|
||||
Util.releaseTemporaryDirectBuffer(bb);
|
||||
Util.offerFirstTemporaryDirectBuffer(bb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,92 +227,85 @@ class IOUtil {
|
||||
static long read(FileDescriptor fd, ByteBuffer[] bufs, NativeDispatcher nd)
|
||||
throws IOException
|
||||
{
|
||||
int nextWithRemaining = remaining(bufs);
|
||||
// if all bufs are empty we should return immediately
|
||||
if (nextWithRemaining < 0)
|
||||
return 0;
|
||||
// If some bufs are empty we should skip them
|
||||
if (nextWithRemaining > 0)
|
||||
bufs = skipBufs(bufs, nextWithRemaining);
|
||||
return read(fd, bufs, 0, bufs.length, nd);
|
||||
}
|
||||
|
||||
int numBufs = bufs.length;
|
||||
static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length,
|
||||
NativeDispatcher nd)
|
||||
throws IOException
|
||||
{
|
||||
IOVecWrapper vec = IOVecWrapper.get(length);
|
||||
|
||||
// Read into the shadow to ensure DirectByteBuffers are used
|
||||
ByteBuffer[] shadow = new ByteBuffer[numBufs];
|
||||
boolean usingSlowBuffers = false;
|
||||
boolean completed = false;
|
||||
int iov_len = 0;
|
||||
try {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (bufs[i].isReadOnly())
|
||||
|
||||
// Iterate over buffers to populate native iovec array.
|
||||
int count = offset + length;
|
||||
for (int i=offset; i<count; i++) {
|
||||
ByteBuffer buf = bufs[i];
|
||||
if (buf.isReadOnly())
|
||||
throw new IllegalArgumentException("Read-only buffer");
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
shadow[i] = Util.getTemporaryDirectBuffer(bufs[i].remaining());
|
||||
usingSlowBuffers = true;
|
||||
} else {
|
||||
shadow[i] = bufs[i];
|
||||
int pos = buf.position();
|
||||
int lim = buf.limit();
|
||||
assert (pos <= lim);
|
||||
int rem = (pos <= lim ? lim - pos : 0);
|
||||
|
||||
if (rem > 0) {
|
||||
vec.setBuffer(iov_len, buf, pos, rem);
|
||||
|
||||
// allocate shadow buffer to ensure I/O is done with direct buffer
|
||||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
vec.setShadow(iov_len, shadow);
|
||||
buf = shadow;
|
||||
pos = shadow.position();
|
||||
}
|
||||
|
||||
vec.putBase(iov_len, ((DirectBuffer)buf).address() + pos);
|
||||
vec.putLen(iov_len, rem);
|
||||
iov_len++;
|
||||
}
|
||||
}
|
||||
if (iov_len == 0)
|
||||
return 0L;
|
||||
|
||||
IOVecWrapper vec = null;
|
||||
long bytesRead = 0;
|
||||
try {
|
||||
// Create a native iovec array
|
||||
vec = new IOVecWrapper(numBufs);
|
||||
|
||||
// Fill in the iovec array with appropriate data
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer nextBuffer = shadow[i];
|
||||
// put in the buffer addresses
|
||||
long pos = nextBuffer.position();
|
||||
long len = nextBuffer.remaining();
|
||||
vec.putBase(i, ((DirectBuffer)nextBuffer).address() + pos);
|
||||
vec.putLen(i, len);
|
||||
}
|
||||
|
||||
// Invoke native call to fill the buffers
|
||||
bytesRead = nd.readv(fd, vec.address, numBufs);
|
||||
} finally {
|
||||
vec.free();
|
||||
}
|
||||
long returnVal = bytesRead;
|
||||
long bytesRead = nd.readv(fd, vec.address, iov_len);
|
||||
|
||||
// Notify the buffers how many bytes were read
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer nextBuffer = shadow[i];
|
||||
// Note: should this have been cached from above?
|
||||
int pos = nextBuffer.position();
|
||||
int len = nextBuffer.remaining();
|
||||
if (bytesRead >= len) {
|
||||
bytesRead -= len;
|
||||
int newPosition = pos + len;
|
||||
nextBuffer.position(newPosition);
|
||||
} else { // Buffers not completely filled
|
||||
if (bytesRead > 0) {
|
||||
assert(pos + bytesRead < (long)Integer.MAX_VALUE);
|
||||
int newPosition = (int)(pos + bytesRead);
|
||||
nextBuffer.position(newPosition);
|
||||
long left = bytesRead;
|
||||
for (int j=0; j<iov_len; j++) {
|
||||
ByteBuffer shadow = vec.getShadow(j);
|
||||
if (left > 0) {
|
||||
ByteBuffer buf = vec.getBuffer(j);
|
||||
int rem = vec.getRemaining(j);
|
||||
int n = (left > rem) ? rem : (int)left;
|
||||
if (shadow == null) {
|
||||
int pos = vec.getPosition(j);
|
||||
buf.position(pos + n);
|
||||
} else {
|
||||
shadow.limit(shadow.position() + n);
|
||||
buf.put(shadow);
|
||||
}
|
||||
break;
|
||||
left -= n;
|
||||
}
|
||||
if (shadow != null)
|
||||
Util.offerLastTemporaryDirectBuffer(shadow);
|
||||
vec.clearRefs(j);
|
||||
}
|
||||
|
||||
// Put results from shadow into the slow buffers
|
||||
if (usingSlowBuffers) {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
if (!(bufs[i] instanceof DirectBuffer)) {
|
||||
shadow[i].flip();
|
||||
bufs[i].put(shadow[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnVal;
|
||||
completed = true;
|
||||
return bytesRead;
|
||||
|
||||
} finally {
|
||||
// return any substituted buffers to cache
|
||||
if (usingSlowBuffers) {
|
||||
for (int i=0; i<numBufs; i++) {
|
||||
ByteBuffer bb = shadow[i];
|
||||
if (bb != null && bb != bufs[i]) {
|
||||
Util.releaseTemporaryDirectBuffer(bb);
|
||||
}
|
||||
// if an error occurred then clear refs to buffers and return any shadow
|
||||
// buffers to cache
|
||||
if (!completed) {
|
||||
for (int j=0; j<iov_len; j++) {
|
||||
ByteBuffer shadow = vec.getShadow(j);
|
||||
if (shadow != null)
|
||||
Util.offerLastTemporaryDirectBuffer(shadow);
|
||||
vec.clearRefs(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package sun.nio.ch;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import sun.misc.*;
|
||||
|
||||
|
||||
@ -43,23 +44,98 @@ import sun.misc.*;
|
||||
class IOVecWrapper {
|
||||
|
||||
// Miscellaneous constants
|
||||
static int BASE_OFFSET = 0;
|
||||
static int LEN_OFFSET;
|
||||
static int SIZE_IOVEC;
|
||||
private static final int BASE_OFFSET = 0;
|
||||
private static final int LEN_OFFSET;
|
||||
private static final int SIZE_IOVEC;
|
||||
|
||||
// The iovec array
|
||||
private AllocatedNativeObject vecArray;
|
||||
private final AllocatedNativeObject vecArray;
|
||||
|
||||
// Number of elements in iovec array
|
||||
private final int size;
|
||||
|
||||
// Buffers and position/remaining corresponding to elements in iovec array
|
||||
private final ByteBuffer[] buf;
|
||||
private final int[] position;
|
||||
private final int[] remaining;
|
||||
|
||||
// Shadow buffers for cases when original buffer is substituted
|
||||
private final ByteBuffer[] shadow;
|
||||
|
||||
// Base address of this array
|
||||
long address;
|
||||
final long address;
|
||||
|
||||
// Address size in bytes
|
||||
static int addressSize;
|
||||
|
||||
IOVecWrapper(int newSize) {
|
||||
newSize = (newSize + 1) * SIZE_IOVEC;
|
||||
vecArray = new AllocatedNativeObject(newSize, false);
|
||||
address = vecArray.address();
|
||||
private static class Deallocator implements Runnable {
|
||||
private final AllocatedNativeObject obj;
|
||||
Deallocator(AllocatedNativeObject obj) {
|
||||
this.obj = obj;
|
||||
}
|
||||
public void run() {
|
||||
obj.free();
|
||||
}
|
||||
}
|
||||
|
||||
// per thread IOVecWrapper
|
||||
private static final ThreadLocal<IOVecWrapper> cached =
|
||||
new ThreadLocal<IOVecWrapper>();
|
||||
|
||||
private IOVecWrapper(int size) {
|
||||
this.size = size;
|
||||
this.buf = new ByteBuffer[size];
|
||||
this.position = new int[size];
|
||||
this.remaining = new int[size];
|
||||
this.shadow = new ByteBuffer[size];
|
||||
this.vecArray = new AllocatedNativeObject(size * SIZE_IOVEC, false);
|
||||
this.address = vecArray.address();
|
||||
}
|
||||
|
||||
static IOVecWrapper get(int size) {
|
||||
IOVecWrapper wrapper = cached.get();
|
||||
if (wrapper != null && wrapper.size < size) {
|
||||
// not big enough; eagerly release memory
|
||||
wrapper.vecArray.free();
|
||||
wrapper = null;
|
||||
}
|
||||
if (wrapper == null) {
|
||||
wrapper = new IOVecWrapper(size);
|
||||
Cleaner.create(wrapper, new Deallocator(wrapper.vecArray));
|
||||
cached.set(wrapper);
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
void setBuffer(int i, ByteBuffer buf, int pos, int rem) {
|
||||
this.buf[i] = buf;
|
||||
this.position[i] = pos;
|
||||
this.remaining[i] = rem;
|
||||
}
|
||||
|
||||
void setShadow(int i, ByteBuffer buf) {
|
||||
shadow[i] = buf;
|
||||
}
|
||||
|
||||
ByteBuffer getBuffer(int i) {
|
||||
return buf[i];
|
||||
}
|
||||
|
||||
int getPosition(int i) {
|
||||
return position[i];
|
||||
}
|
||||
|
||||
int getRemaining(int i) {
|
||||
return remaining[i];
|
||||
}
|
||||
|
||||
ByteBuffer getShadow(int i) {
|
||||
return shadow[i];
|
||||
}
|
||||
|
||||
void clearRefs(int i) {
|
||||
buf[i] = null;
|
||||
shadow[i] = null;
|
||||
}
|
||||
|
||||
void putBase(int i, long base) {
|
||||
@ -78,10 +154,6 @@ class IOVecWrapper {
|
||||
vecArray.putLong(offset, len);
|
||||
}
|
||||
|
||||
void free() {
|
||||
vecArray.free();
|
||||
}
|
||||
|
||||
static {
|
||||
addressSize = Util.unsafe().addressSize();
|
||||
LEN_OFFSET = addressSize;
|
||||
|
@ -385,9 +385,11 @@ class SocketChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
private long read0(ByteBuffer[] bufs) throws IOException {
|
||||
if (bufs == null)
|
||||
throw new NullPointerException();
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
if (!ensureReadOpen())
|
||||
return -1;
|
||||
@ -401,7 +403,7 @@ class SocketChannelImpl
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
n = IOUtil.read(fd, bufs, nd);
|
||||
n = IOUtil.read(fd, dsts, offset, length, nd);
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
return IOStatus.normalize(n);
|
||||
@ -418,15 +420,6 @@ class SocketChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long read(ByteBuffer[] dsts, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return read0(Util.subsequence(dsts, offset, length));
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
@ -458,9 +451,11 @@ class SocketChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long write0(ByteBuffer[] bufs) throws IOException {
|
||||
if (bufs == null)
|
||||
throw new NullPointerException();
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
ensureWriteOpen();
|
||||
long n = 0;
|
||||
@ -472,7 +467,7 @@ class SocketChannelImpl
|
||||
writerThread = NativeThread.current();
|
||||
}
|
||||
for (;;) {
|
||||
n = IOUtil.write(fd, bufs, nd);
|
||||
n = IOUtil.write(fd, srcs, offset, length, nd);
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
return IOStatus.normalize(n);
|
||||
@ -489,15 +484,6 @@ class SocketChannelImpl
|
||||
}
|
||||
}
|
||||
|
||||
public long write(ByteBuffer[] srcs, int offset, int length)
|
||||
throws IOException
|
||||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
// ## Fix IOUtil.write so that we can avoid this array copy
|
||||
return write0(Util.subsequence(srcs, offset, length));
|
||||
}
|
||||
|
||||
// package-private
|
||||
int sendOutOfBandData(byte b) throws IOException {
|
||||
synchronized (writeLock) {
|
||||
|
@ -41,67 +41,180 @@ import sun.security.action.GetPropertyAction;
|
||||
|
||||
class Util {
|
||||
|
||||
|
||||
// -- Caches --
|
||||
|
||||
// The number of temp buffers in our pool
|
||||
private static final int TEMP_BUF_POOL_SIZE = 3;
|
||||
private static final int TEMP_BUF_POOL_SIZE = 8;
|
||||
|
||||
// Per-thread soft cache of the last temporary direct buffer
|
||||
private static ThreadLocal<SoftReference<ByteBuffer>>[] bufferPool;
|
||||
// Per-thread cache of temporary direct buffers
|
||||
private static ThreadLocal<BufferCache> bufferCache =
|
||||
new ThreadLocal<BufferCache>()
|
||||
{
|
||||
@Override
|
||||
protected BufferCache initialValue() {
|
||||
return new BufferCache();
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static ThreadLocal<SoftReference<ByteBuffer>>[] createThreadLocalBufferPool() {
|
||||
return new ThreadLocal[TEMP_BUF_POOL_SIZE];
|
||||
}
|
||||
|
||||
static {
|
||||
bufferPool = createThreadLocalBufferPool();
|
||||
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++)
|
||||
bufferPool[i] = new ThreadLocal<SoftReference<ByteBuffer>>();
|
||||
/**
|
||||
* A simple cache of direct buffers.
|
||||
*/
|
||||
private static class BufferCache {
|
||||
// the array of buffers
|
||||
private ByteBuffer[] buffers;
|
||||
|
||||
// the number of buffers in the cache
|
||||
private int count;
|
||||
|
||||
// the index of the first valid buffer (undefined if count == 0)
|
||||
private int start;
|
||||
|
||||
private int next(int i) {
|
||||
return (i + 1) % TEMP_BUF_POOL_SIZE;
|
||||
}
|
||||
|
||||
BufferCache() {
|
||||
buffers = new ByteBuffer[TEMP_BUF_POOL_SIZE];
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes and returns a buffer from the cache of at least the given
|
||||
* size (or null if no suitable buffer is found).
|
||||
*/
|
||||
ByteBuffer get(int size) {
|
||||
if (count == 0)
|
||||
return null; // cache is empty
|
||||
|
||||
ByteBuffer[] buffers = this.buffers;
|
||||
|
||||
// search for suitable buffer (often the first buffer will do)
|
||||
ByteBuffer buf = buffers[start];
|
||||
if (buf.capacity() < size) {
|
||||
buf = null;
|
||||
int i = start;
|
||||
while ((i = next(i)) != start) {
|
||||
ByteBuffer bb = buffers[i];
|
||||
if (bb == null)
|
||||
break;
|
||||
if (bb.capacity() >= size) {
|
||||
buf = bb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (buf == null)
|
||||
return null;
|
||||
// move first element to here to avoid re-packing
|
||||
buffers[i] = buffers[start];
|
||||
}
|
||||
|
||||
// remove first element
|
||||
buffers[start] = null;
|
||||
start = next(start);
|
||||
count--;
|
||||
|
||||
// prepare the buffer and return it
|
||||
buf.rewind();
|
||||
buf.limit(size);
|
||||
return buf;
|
||||
}
|
||||
|
||||
boolean offerFirst(ByteBuffer buf) {
|
||||
if (count >= TEMP_BUF_POOL_SIZE) {
|
||||
return false;
|
||||
} else {
|
||||
start = (start + TEMP_BUF_POOL_SIZE - 1) % TEMP_BUF_POOL_SIZE;
|
||||
buffers[start] = buf;
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean offerLast(ByteBuffer buf) {
|
||||
if (count >= TEMP_BUF_POOL_SIZE) {
|
||||
return false;
|
||||
} else {
|
||||
int next = (start + count) % TEMP_BUF_POOL_SIZE;
|
||||
buffers[next] = buf;
|
||||
count++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return count == 0;
|
||||
}
|
||||
|
||||
ByteBuffer removeFirst() {
|
||||
assert count > 0;
|
||||
ByteBuffer buf = buffers[start];
|
||||
buffers[start] = null;
|
||||
start = next(start);
|
||||
count--;
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a temporary buffer of at least the given size
|
||||
*/
|
||||
static ByteBuffer getTemporaryDirectBuffer(int size) {
|
||||
ByteBuffer buf = null;
|
||||
// Grab a buffer if available
|
||||
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
|
||||
SoftReference<ByteBuffer> ref = bufferPool[i].get();
|
||||
if ((ref != null) && ((buf = ref.get()) != null) &&
|
||||
(buf.capacity() >= size)) {
|
||||
buf.rewind();
|
||||
buf.limit(size);
|
||||
bufferPool[i].set(null);
|
||||
return buf;
|
||||
BufferCache cache = bufferCache.get();
|
||||
ByteBuffer buf = cache.get(size);
|
||||
if (buf != null) {
|
||||
return buf;
|
||||
} else {
|
||||
// No suitable buffer in the cache so we need to allocate a new
|
||||
// one. To avoid the cache growing then we remove the first
|
||||
// buffer from the cache and free it.
|
||||
if (!cache.isEmpty()) {
|
||||
buf = cache.removeFirst();
|
||||
free(buf);
|
||||
}
|
||||
return ByteBuffer.allocateDirect(size);
|
||||
}
|
||||
|
||||
// Make a new one
|
||||
return ByteBuffer.allocateDirect(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a temporary buffer by returning to the cache or freeing it.
|
||||
*/
|
||||
static void releaseTemporaryDirectBuffer(ByteBuffer buf) {
|
||||
if (buf == null)
|
||||
return;
|
||||
// Put it in an empty slot if such exists
|
||||
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
|
||||
SoftReference<ByteBuffer> ref = bufferPool[i].get();
|
||||
if ((ref == null) || (ref.get() == null)) {
|
||||
bufferPool[i].set(new SoftReference<ByteBuffer>(buf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Otherwise replace a smaller one in the cache if such exists
|
||||
for (int i=0; i<TEMP_BUF_POOL_SIZE; i++) {
|
||||
SoftReference<ByteBuffer> ref = bufferPool[i].get();
|
||||
ByteBuffer inCacheBuf = ref.get();
|
||||
if ((inCacheBuf == null) || (buf.capacity() > inCacheBuf.capacity())) {
|
||||
bufferPool[i].set(new SoftReference<ByteBuffer>(buf));
|
||||
return;
|
||||
}
|
||||
}
|
||||
offerFirstTemporaryDirectBuffer(buf);
|
||||
}
|
||||
|
||||
// release memory
|
||||
((DirectBuffer)buf).cleaner().clean();
|
||||
/**
|
||||
* Releases a temporary buffer by returning to the cache or freeing it. If
|
||||
* returning to the cache then insert it at the start so that it is
|
||||
* likely to be returned by a subsequent call to getTemporaryDirectBuffer.
|
||||
*/
|
||||
static void offerFirstTemporaryDirectBuffer(ByteBuffer buf) {
|
||||
assert buf != null;
|
||||
BufferCache cache = bufferCache.get();
|
||||
if (!cache.offerFirst(buf)) {
|
||||
// cache is full
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a temporary buffer by returning to the cache or freeing it. If
|
||||
* returning to the cache then insert it at the end. This makes it
|
||||
* suitable for scatter/gather operations where the buffers are returned to
|
||||
* cache in same order that they were obtained.
|
||||
*/
|
||||
static void offerLastTemporaryDirectBuffer(ByteBuffer buf) {
|
||||
assert buf != null;
|
||||
BufferCache cache = bufferCache.get();
|
||||
if (!cache.offerLast(buf)) {
|
||||
// cache is full
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the memory for the given direct buffer
|
||||
*/
|
||||
private static void free(ByteBuffer buf) {
|
||||
((DirectBuffer)buf).cleaner().clean();
|
||||
}
|
||||
|
||||
private static class SelectorWrapper {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
"Central European Summer Time", "CEST"};
|
||||
String CHAST[] = new String[] {"Chatham Standard Time", "CHAST",
|
||||
"Chatham Daylight Time", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Central Indonesia Time", "CIT",
|
||||
"Central Indonesia Summer Time", "CIST"};
|
||||
String CLT[] = new String[] {"Chile Time", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
"Pitcairn Daylight Time", "PDT"};
|
||||
String PKT[] = new String[] {"Pakistan Time", "PKT",
|
||||
"Pakistan Summer Time", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Pacific Standard Time", "PST",
|
||||
"Pacific Daylight Time", "PDT"};
|
||||
String RST[] = new String[] {"Eastern Standard Time", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
"Eastern Summer Time (Tasmania)", "EST"};
|
||||
String TMT[] = new String[] {"Turkmenistan Time", "TMT",
|
||||
"Turkmenistan Summer Time", "TMST"};
|
||||
String TRUT[] = new String[] {"Truk Time", "TRUT",
|
||||
"Truk Summer Time", "TRUST"};
|
||||
String ULAT[]= new String[] {"Ulaanbaatar Time", "ULAT",
|
||||
"Ulaanbaatar Summer Time", "ULAST"};
|
||||
String WART[] = new String[] {"Western Argentine Time", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -755,6 +758,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Vanuatu Time", "VUT",
|
||||
"Vanuatu Summer Time", "VUST"}},
|
||||
@ -793,8 +797,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Palau Time", "PWT",
|
||||
"Palau Summer Time", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ponape Time", "PONT",
|
||||
"Ponape Summer Time", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Papua New Guinea Time", "PGT",
|
||||
"Papua New Guinea Summer Time", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Cook Is. Time", "CKT",
|
||||
@ -807,12 +811,12 @@ public final class TimeZoneNames extends TimeZoneNamesBundle {
|
||||
"Gilbert Is. Summer Time", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Tonga Time", "TOT",
|
||||
"Tonga Summer Time", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Wake Time", "WAKT",
|
||||
"Wake Summer Time", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Wallis & Futuna Time", "WFT",
|
||||
"Wallis & Futuna Summer Time", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
"Mitteleurop\u00e4ische Sommerzeit", "MESZ"};
|
||||
String CHAST[] = new String[] {"Chatham Normalzeit", "CHAST",
|
||||
"Chatham Sommerzeit", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Zentralindonesische Zeit", "CIT",
|
||||
"Zentralindonesische Sommerzeit", "CIST"};
|
||||
String CLT[] = new String[] {"Chilenische Zeit", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
"Pitcairn Sommerzeit", "PDT"};
|
||||
String PKT[] = new String[] {"Pakistanische Zeit", "PKT",
|
||||
"Pakistanische Sommerzeit", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Pazifische Normalzeit", "PST",
|
||||
"Pazifische Sommerzeit", "PDT"};
|
||||
String RST[] = new String[] {"\u00d6stliche Normalzeit", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
"\u00d6stliche Sommerzeit (Tasmanien)", "EST"};
|
||||
String TMT[] = new String[] {"Turkmenische Zeit", "TMT",
|
||||
"Turkmenische Sommerzeit", "TMST"};
|
||||
String TRUT[] = new String[] {"Truk Zeit", "TRUT",
|
||||
"Truk Sommerzeit", "TRUST"};
|
||||
String ULAT[]= new String[] {"Ulaanbaatar Zeit", "ULAT",
|
||||
"Ulaanbaatar Sommerzeit", "ULAST"};
|
||||
String WART[] = new String[] {"Westargentinische Zeit", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Dumont-d'Urville Sommerzeit", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"Mawson Zeit", "MAWT",
|
||||
"Mawson Sommerzeit", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Vanuatu Zeit", "VUT",
|
||||
"Vanuatu Sommerzeit", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Palau Zeit", "PWT",
|
||||
"Palau Sommerzeit", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ponape Zeit", "PONT",
|
||||
"Ponape Sommerzeit", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Papua-Neuguinea Zeit", "PGT",
|
||||
"Papua-Neuguinea Sommerzeit", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Cook-Inseln Zeit", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_de extends TimeZoneNamesBundle {
|
||||
"Gilbert-Inseln Sommerzeit", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Tonga Zeit", "TOT",
|
||||
"Tonga Sommerzeit", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Wake Zeit", "WAKT",
|
||||
"Wake Sommerzeit", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Wallis u. Futuna Zeit", "WFT",
|
||||
"Wallis u. Futuna Sommerzeit", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
"Hora de verano de Europa Central", "CEST"};
|
||||
String CHAST[] = new String[] {"Hora est\u00e1ndar de Chatham", "CHAST",
|
||||
"Hora de verano de Chatham", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Hora de Indonesia Central", "CIT",
|
||||
"Hora de verano de Indonesia Central", "CIST"};
|
||||
String CLT[] = new String[] {"Hora de Chile", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
"Hora de verano de Pitcairn", "PDT"};
|
||||
String PKT[] = new String[] {"Hora de Pakist\u00e1n", "PKT",
|
||||
"Hora de verano de Pakist\u00e1n", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Hora est\u00e1ndar del Pac\u00edfico", "PST",
|
||||
"Hora de verano del Pac\u00edfico", "PDT"};
|
||||
String RST[] = new String[] {"Hora est\u00e1ndar Oriental", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
"Hora de verano del Este (Tasmania)", "EST"};
|
||||
String TMT[] = new String[] {"Hora de Turkmenist\u00e1n", "TMT",
|
||||
"Hora de verano de Turkmenist\u00e1n", "TMST"};
|
||||
String TRUT[] =new String[] {"Hora de Truk", "TRUT",
|
||||
"Hora de verano de Truk", "TRUST"};
|
||||
String ULAT[]= new String[] {"Hora de Ulan Bator", "ULAT",
|
||||
"Hora de verano de Ulan Bator", "ULAST"};
|
||||
String WART[] = new String[] {"Hora de Argentina Occidental", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Hora de verano de Dumont-d'Urville", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"Hora de Mawson", "MAWT",
|
||||
"Hora de verano de Mawson", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -533,7 +539,6 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
"Hora de verano de Filipinas", "PHST"}},
|
||||
{"Asia/Muscat", GST},
|
||||
{"Asia/Nicosia", EET},
|
||||
|
||||
{"Asia/Novokuznetsk", NOVT},
|
||||
{"Asia/Novosibirsk", NOVT},
|
||||
{"Asia/Oral", new String[] {"Hora de Uralsk", "ORAT",
|
||||
@ -753,6 +758,7 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Hora de Vanuatu", "VUT",
|
||||
"Hora de verano de Vanuatu", "VUST"}},
|
||||
@ -791,8 +797,8 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Hora de Palau", "PWT",
|
||||
"Hora de verano de Palau", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Hora de Ponape", "PONT",
|
||||
"Hora de verano de Ponape", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Hora de Pap\u00faa-Nueva Guinea", "PGT",
|
||||
"Hora de verano de Pap\u00faa-Nueva Guinea", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Hora de las islas Cook", "CKT",
|
||||
@ -805,12 +811,12 @@ public final class TimeZoneNames_es extends TimeZoneNamesBundle {
|
||||
"Hora de verano de las islas Gilbert", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Hora de Tonga", "TOT",
|
||||
"Hora de verano de Tonga", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Hora de Wake", "WAKT",
|
||||
"Hora de verano de Wake", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Hora de Wallis y Futuna", "WFT",
|
||||
"Hora de verano de Wallis y Futuna", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
"Heure d'\u00e9t\u00e9 d'Europe centrale", "CEST"} ;
|
||||
String CHAST[] = new String[] {"Heure standard de Chatham", "CHAST",
|
||||
"Heure avanc\u00e9e de Chatham", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Heure d'Indon\u00e9sie centrale", "CIT",
|
||||
"Heure d'\u00e9t\u00e9 d'Indon\u00e9sie centrale", "CIST"};
|
||||
String CLT[] = new String[] {"Heure du Chili", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
"heure avanc\u00e9e des Pitcairn", "PDT"};
|
||||
String PKT[] = new String[] {"Heure du Pakistan", "PKT",
|
||||
"Heure d'\u00e9t\u00e9 du Pakistan", "PKST"} ;
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Heure normale du Pacifique", "PST",
|
||||
"Heure avanc\u00e9e du Pacifique", "PDT"} ;
|
||||
String RST[] = new String[] {"Heure normale de l'Est", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
"Heure d'\u00e9t\u00e9 d'Australie orientale (Tasmanie)", "EST"};
|
||||
String TMT[] = new String[] {"Heure du Turkm\u00e9nistan", "TMT",
|
||||
"Heure d'\u00e9t\u00e9 du Turkm\u00e9nistan", "TMST"} ;
|
||||
String TRUT[] = new String[] {"Heure de Truk", "TRUT",
|
||||
"Heure d'\u00e9t\u00e9 de Truk", "TRUST"};
|
||||
String ULAT[]= new String[] {"Heure de l'Ulaanbaatar", "ULAT",
|
||||
"Heure d'\u00e9t\u00e9 de l'Ulaanbaatar", "ULAST"} ;
|
||||
String WART[] = new String[] {"Heure D'Argentine de l'Ouest", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Heure d'\u00e9t\u00e9 de Dumont-d'Urville", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"Heure de Mawson", "MAWT",
|
||||
"Heure d'\u00e9t\u00e9 de Mawson", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Heure du Vanuatu", "VUT",
|
||||
"Heure d'\u00e9t\u00e9 du Vanuatu", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Heure de Palaos", "PWT",
|
||||
"Heure d'\u00e9t\u00e9 de Palaos", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Heure de Ponap\u00e9", "PONT",
|
||||
"Heure d'\u00e9t\u00e9 de Ponap\u00e9", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Heure de Papouasie-Nouvelle-Guin\u00e9e", "PGT",
|
||||
"Heure d'\u00e9t\u00e9 de de Papouasie-Nouvelle-Guin\u00e9e", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Heure des \u00celes Cook", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_fr extends TimeZoneNamesBundle {
|
||||
"Heure d'\u00e9t\u00e9 de Kiribati", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Heure de Tonga", "TOT",
|
||||
"Heure d'\u00e9t\u00e9 de Tonga", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Heure de Wake", "WAKT",
|
||||
"Heure d'\u00e9t\u00e9 de Wake", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Heure de Wallis et Futuna", "WFT",
|
||||
"Heure d'\u00e9t\u00e9 de Wallis et Futuna", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
"Ora estiva dell'Europa centrale", "CEST"};
|
||||
String CHAST[] = new String[] {"Ora di Chatham standard", "CHAST",
|
||||
"Ora legale di Chatham", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Ora dell'Indonesia centrale", "CIT",
|
||||
"Ora estiva dell'Indonesia centrale", "CIST"};
|
||||
String CLT[] = new String[] {"Ora del Cile", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
"Ora legale di Pitcairn", "PDT"};
|
||||
String PKT[] = new String[] {"Ora del Pakistan", "PKT",
|
||||
"Ora estiva del Pakistan", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Ora solare della costa occidentale USA", "PST",
|
||||
"Ora legale della costa occidentale USA", "PDT"};
|
||||
String RST[] = new String[] {"Ora solare USA orientale", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
"Ora estiva orientale (Tasmania)", "EST"};
|
||||
String TMT[] = new String[] {"Ora del Turkmenistan", "TMT",
|
||||
"Ora estiva del Turkmenistan", "TMST"};
|
||||
String TRUT[] = new String[] {"Ora di Truk", "TRUT",
|
||||
"Ora estiva di Truk", "TRUST"};
|
||||
String ULAT[]= new String[] {"Ora di Ulaanbaatar", "ULAT",
|
||||
"Ora estiva di Ulaanbaatar", "ULAST"};
|
||||
String WART[] = new String[] {"Ora dell'Argentina occidentale", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Ora estiva di Dumont-d'Urville", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"Ora di Mawson", "MAWT",
|
||||
"Ora estiva di Mawson", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Ora di Vanuatu", "VUT",
|
||||
"Ora estiva di Vanuatu", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Ora di Palau", "PWT",
|
||||
"Ora estiva di Palau", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ora di Ponape", "PONT",
|
||||
"Ora estiva di Ponape", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Ora di Papua Nuova Guinea", "PGT",
|
||||
"Ora estiva di Papua Nuova Guinea", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Ora delle Isole Cook", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_it extends TimeZoneNamesBundle {
|
||||
"Ora estiva delle Isole Gilbert", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Ora di Tonga", "TOT",
|
||||
"Ora estiva di Tonga", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Ora di Wake", "WAKT",
|
||||
"Ora estiva di Wake", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Ora di Wallis e Futuna", "WFT",
|
||||
"Ora estiva di Wallis e Futuna", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
"\u4e2d\u90e8\u30e8\u30fc\u30ed\u30c3\u30d1\u590f\u6642\u9593", "CEST"};
|
||||
String CHAST[] = new String[] {"\u30c1\u30e3\u30bf\u30e0\u6a19\u6e96\u6642", "CHAST",
|
||||
"\u30c1\u30e3\u30bf\u30e0\u590f\u6642\u9593", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"\u4e2d\u592e\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u6642\u9593", "CIT",
|
||||
"\u4e2d\u592e\u30a4\u30f3\u30c9\u30cd\u30b7\u30a2\u590f\u6642\u9593", "CIST"};
|
||||
String CLT[] = new String[] {"\u30c1\u30ea\u6642\u9593", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
"\u30d4\u30c8\u30b1\u30eb\u30f3\u5cf6\u590f\u6642\u9593", "PDT"};
|
||||
String PKT[] = new String[] {"\u30d1\u30ad\u30b9\u30bf\u30f3\u6642\u9593", "PKT",
|
||||
"\u30d1\u30ad\u30b9\u30bf\u30f3\u590f\u6642\u9593", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642", "PST",
|
||||
"\u592a\u5e73\u6d0b\u590f\u6642\u9593", "PDT"};
|
||||
String RST[] = new String[] {"\u6771\u90e8\u6a19\u6e96\u6642", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
"\u6771\u90e8\u590f\u6642\u9593 (\u30bf\u30b9\u30de\u30cb\u30a2)", "EST"};
|
||||
String TMT[] = new String[] {"\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u6642\u9593", "TMT",
|
||||
"\u30c8\u30eb\u30af\u30e1\u30cb\u30b9\u30bf\u30f3\u590f\u6642\u9593", "TMST"};
|
||||
String TRUT[] = new String[] {"\u30c8\u30e9\u30c3\u30af\u6642\u9593", "TRUT",
|
||||
"\u30c8\u30e9\u30c3\u30af\u590f\u6642\u9593", "TRUST"};
|
||||
String ULAT[]= new String[] {"\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u6642\u9593", "ULAT",
|
||||
"\u30a6\u30e9\u30fc\u30f3\u30d0\u30fc\u30c8\u30eb\u590f\u6642\u9593", "ULAST"};
|
||||
String WART[] = new String[] {"\u897f\u30a2\u30eb\u30bc\u30f3\u30c1\u30f3\u6642\u9593", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"\u30c7\u30e5\u30e2\u30f3\u30c7\u30e5\u30eb\u30f4\u30a3\u30eb\u590f\u6642\u9593", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"\u30e2\u30fc\u30bd\u30f3\u6642\u9593", "MAWT",
|
||||
"\u30e2\u30fc\u30bd\u30f3\u590f\u6642\u9593", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"\u30d0\u30cc\u30a2\u30c4\u6642\u9593", "VUT",
|
||||
"\u30d0\u30cc\u30a2\u30c4\u590f\u6642\u9593", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"\u30d1\u30e9\u30aa\u6642\u9593", "PWT",
|
||||
"\u30d1\u30e9\u30aa\u590f\u6642\u9593", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"\u30dd\u30ca\u30da\u6642\u9593", "PONT",
|
||||
"\u30dd\u30ca\u30da\u590f\u6642\u9593", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"\u30d1\u30d7\u30a2\u30cb\u30e5\u30fc\u30ae\u30cb\u30a2\u6642\u9593", "PGT",
|
||||
"\u30d1\u30d7\u30a2\u30cb\u30e5\u30fc\u30ae\u30cb\u30a2\u590f\u6642\u9593", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"\u30af\u30c3\u30af\u8af8\u5cf6\u6642\u9593", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_ja extends TimeZoneNamesBundle {
|
||||
"\u30ae\u30eb\u30d0\u30fc\u30c8\u8af8\u5cf6\u590f\u6642\u9593", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"\u30c8\u30f3\u30ac\u6642\u9593", "TOT",
|
||||
"\u30c8\u30f3\u30ac\u590f\u6642\u9593", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"\u30a6\u30a7\u30fc\u30af\u6642\u9593", "WAKT",
|
||||
"\u30a6\u30a7\u30fc\u30af\u590f\u6642\u9593", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"\u30ef\u30ea\u30b9\u53ca\u3073\u30d5\u30c4\u30ca\u6642\u9593", "WFT",
|
||||
"\u30ef\u30ea\u30b9\u53ca\u3073\u30d5\u30c4\u30ca\u590f\u6642\u9593", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
"\uc911\uc559 \uc720\ub7fd \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CEST"};
|
||||
String CHAST[] = new String[] {"Chatham \ud45c\uc900\uc2dc", "CHAST",
|
||||
"Chatham \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"\uc911\uc559 \uc778\ub3c4\ub124\uc2dc\uc544 \uc2dc\uac04", "CIT",
|
||||
"\uc911\uc559 \uc778\ub3c4\ub124\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "CIST"};
|
||||
String CLT[] = new String[] {"\uce60\ub808 \uc2dc\uac04", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
"Pitcairn \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PDT"};
|
||||
String PKT[] = new String[] {"\ud30c\ud0a4\uc2a4\ud0c4 \uc2dc\uac04", "PKT",
|
||||
"\ud30c\ud0a4\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"\ud0dc\ud3c9\uc591 \ud45c\uc900\uc2dc", "PST",
|
||||
"\ud0dc\ud3c9\uc591 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PDT"};
|
||||
String RST[] = new String[] {"\ub3d9\ubd80 \ud45c\uc900\uc2dc", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
"\ub3d9\ubd80 \uc77c\uad11\uc808\uc57d\uc2dc\uac04(\ud0dc\uc988\uba54\uc774\ub2c8\uc544)", "EST"};
|
||||
String TMT[] = new String[] {"\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc2dc\uac04", "TMT",
|
||||
"\ud22c\ub974\ud06c\uba54\ub2c8\uc2a4\ud0c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TMST"};
|
||||
String TRUT[] = new String[] {"\ud2b8\ub8e8\ud06c \uc2dc\uac04", "TRUT",
|
||||
"\ud2b8\ub8e8\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TRUST"};
|
||||
String ULAT[]= new String[] {"\uc6b8\ub780\ubc14\ud0c0\ub974 \uc2dc\uac04", "ULAT",
|
||||
"\uc6b8\ub780\ubc14\ud0c0\ub974 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ULAST"};
|
||||
String WART[] = new String[] {"\uc11c\ubd80 \uc544\ub974\ud5e8\ud2f0\ub098 \uc2dc\uac04", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"\ub4a4\ubabd \ub4a4\ub974\ube4c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"\ubaa8\uc2a8 \uc2dc\uac04", "MAWT",
|
||||
"\ubaa8\uc2a8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"\ube44\ub204\uc544\ud22c \uc2dc\uac04", "VUT",
|
||||
"\ubc14\ub204\uc544\ud22c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"\ud314\ub77c\uc6b0 \uc2dc\uac04", "PWT",
|
||||
"\ud314\ub77c\uc6b0 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"\ud3ec\ub098\ud504 \uc2dc\uac04", "PONT",
|
||||
"\ud3ec\ub098\ud504 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"\ud30c\ud478\uc544\ub274\uae30\ub2c8 \uc2dc\uac04", "PGT",
|
||||
"\ud30c\ud478\uc544\ub274\uae30\ub2c8 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"\ucfe0\ud06c \uad70\ub3c4 \uc2dc\uac04", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_ko extends TimeZoneNamesBundle {
|
||||
"\uae38\ubc84\ud2b8 \uad70\ub3c4 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"\ud1b5\uac00 \uc2dc\uac04", "TOT",
|
||||
"\ud1b5\uac00 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"\uc6e8\uc774\ud06c \uc2dc\uac04", "WAKT",
|
||||
"\uc6e8\uc774\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"\uc6d4\ub9ac\uc2a4 \ud6c4\ud22c\ub098 \uc2dc\uac04", "WFT",
|
||||
"\uc6d4\ub9ac\uc2a4 \ud6c4\ud2b8\ub098 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
"Centraleuropeisk sommartid", "CEST"};
|
||||
String CHAST[] = new String[] {"Chatham, normaltid", "CHAST",
|
||||
"Chatham, sommartid", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"Centralindonesisk tid", "CIT",
|
||||
"Centralindonesisk sommartid", "CIST"};
|
||||
String CLT[] = new String[] {"Chile, normaltid", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
"Pitcairn, sommartid", "PDT"};
|
||||
String PKT[] = new String[] {"Pakistan, normaltid", "PKT",
|
||||
"Pakistan, sommartid", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"Stilla havet, normaltid", "PST",
|
||||
"Stilla havet, sommartid", "PDT"};
|
||||
String RST[] = new String[] {"Eastern, normaltid", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
"Eastern, sommartid (Tasmanien)", "EST"};
|
||||
String TMT[] = new String[] {"Turkmenistan, normaltid", "TMT",
|
||||
"Turkmenistan, sommartid", "TMST"};
|
||||
String TRUT[] = new String[] {"Truk, normaltid", "TRUT",
|
||||
"Truk, sommartid", "TRUST"};
|
||||
String ULAT[]= new String[] {"Ulaanbaatar, normaltid", "ULAT",
|
||||
"Ulaanbaatar, sommartid", "ULAST"};
|
||||
String WART[] = new String[] {"V\u00e4stargentina, normaltid", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Dumont-d'Urville, sommartid", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"Mawson, normaltid", "MAWT",
|
||||
"Mawson, sommartid", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"Vanuatu, normaltid", "VUT",
|
||||
"Vanuatu, sommartid", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"Palau, normaltid", "PWT",
|
||||
"Palau, sommartid", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ponape, normaltid", "PONT",
|
||||
"Ponape, sommartid", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"Papua Nya Guinea, normaltid", "PGT",
|
||||
"Papua Nya Guinea, sommartid", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"Cook\u00f6arna, normaltid", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_sv extends TimeZoneNamesBundle {
|
||||
"Gilbert\u00f6arna, sommartid", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"Tonga, normaltid", "TOT",
|
||||
"Tonga, sommartid", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"Wake, normaltid", "WAKT",
|
||||
"Wake, sommartid", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"Wallis & Futuna, normaltid", "WFT",
|
||||
"Wallis & Futuna, sommartid", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
"\u4e2d\u6b27\u590f\u4ee4\u65f6", "CEST"};
|
||||
String CHAST[] = new String[] {"\u67e5\u8428\u59c6\u6807\u51c6\u65f6\u95f4", "CHAST",
|
||||
"\u67e5\u8428\u59c6\u590f\u4ee4\u65f6", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"\u4e2d\u90e8\u5370\u5ea6\u5c3c\u897f\u4e9a\u65f6\u95f4", "CIT",
|
||||
"\u4e2d\u90e8\u5370\u5ea6\u5c3c\u897f\u4e9a\u590f\u4ee4\u65f6", "CIST"};
|
||||
String CLT[] = new String[] {"\u667a\u5229\u65f6\u95f4", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
"\u76ae\u7279\u5eb7\u5c9b\u590f\u4ee4\u65f6", "PDT"};
|
||||
String PKT[] = new String[] {"\u5df4\u57fa\u65af\u5766\u65f6\u95f4", "PKT",
|
||||
"\u5df4\u57fa\u65af\u5766\u590f\u4ee4\u65f6", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4", "PST",
|
||||
"\u592a\u5e73\u6d0b\u590f\u4ee4\u65f6", "PDT"};
|
||||
String RST[] = new String[] {"\u4e1c\u90e8\u6807\u51c6\u65f6\u95f4", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
"\u4e1c\u90e8\u590f\u4ee4\u65f6\uff08\u5854\u65af\u9a6c\u5c3c\u4e9a\uff09", "EST"};
|
||||
String TMT[] = new String[] {"\u571f\u5e93\u66fc\u65f6\u95f4", "TMT",
|
||||
"\u571f\u5e93\u66fc\u590f\u4ee4\u65f6", "TMST"};
|
||||
String TRUT[] = new String[] {"\u7279\u9c81\u514b\u65f6\u95f4", "TRUT",
|
||||
"\u7279\u9c81\u514b\u590f\u4ee4\u65f6", "TRUST"};
|
||||
String ULAT[]= new String[] {"\u5e93\u4f26\u65f6\u95f4", "ULAT",
|
||||
"\u5e93\u4f26\u590f\u4ee4\u65f6", "ULAST"};
|
||||
String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u65f6\u95f4", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Dumont-d'Urville \u590f\u4ee4\u65f6", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"\u83ab\u68ee\u65f6\u95f4", "MAWT",
|
||||
"\u83ab\u68ee\u590f\u4ee4\u65f6", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -752,6 +758,7 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"\u74e6\u5974\u963f\u56fe\u65f6\u95f4", "VUT",
|
||||
"\u74e6\u5974\u963f\u56fe\u590f\u4ee4\u65f6", "VUST"}},
|
||||
@ -790,8 +797,8 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"\u5e1b\u7409\u65f6\u95f4", "PWT",
|
||||
"\u5e1b\u7409\u590f\u4ee4\u65f6", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ponape \u65f6\u95f4", "PONT",
|
||||
"Ponape \u590f\u4ee4\u65f6", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"\u5df4\u5e03\u4e9a\u65b0\u51e0\u5185\u4e9a\u65f6\u95f4", "PGT",
|
||||
"\u5df4\u5e03\u4e9a\u65b0\u51e0\u5185\u4e9a\u590f\u4ee4\u65f6", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"\u5e93\u514b\u7fa4\u5c9b\u65f6\u95f4", "CKT",
|
||||
@ -804,12 +811,12 @@ public final class TimeZoneNames_zh_CN extends TimeZoneNamesBundle {
|
||||
"\u5409\u4f2f\u7279\u7fa4\u5c9b\u590f\u4ee4\u65f6", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"\u4e1c\u52a0\u65f6\u95f4", "TOT",
|
||||
"\u4e1c\u52a0\u590f\u4ee4\u65f6", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"\u5a01\u514b\u65f6\u95f4", "WAKT",
|
||||
"\u5a01\u514b\u590f\u4ee4\u65f6", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"\u74e6\u5229\u65af\u53ca\u798f\u675c\u7eb3\u7fa4\u5c9b\u65f6\u95f4", "WFT",
|
||||
"\u74e6\u5229\u65af\u53ca\u798f\u675c\u7eb3\u7fa4\u5c9b\u590f\u4ee4\u65f6", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -75,6 +75,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
"\u4e2d\u6b50\u590f\u4ee4\u6642\u9593", "CEST"};
|
||||
String CHAST[] = new String[] {"\u67e5\u5766\u6a19\u6e96\u6642\u9593", "CHAST",
|
||||
"\u67e5\u5766\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "CHADT"};
|
||||
String CHUT[] = new String[] {"Chuuk Time", "CHUT",
|
||||
"Chuuk Summer Time", "CHUST"};
|
||||
String CIT[] = new String[] {"\u4e2d\u5370\u5ea6\u5c3c\u897f\u4e9e\u6642\u9593", "CIT",
|
||||
"\u4e2d\u5370\u5ea6\u5c3c\u897f\u4e9e\u590f\u4ee4\u6642\u9593", "CIST"};
|
||||
String CLT[] = new String[] {"\u667a\u5229\u6642\u9593", "CLT",
|
||||
@ -153,6 +155,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
"\u76ae\u7279\u5eb7\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PDT"};
|
||||
String PKT[] = new String[] {"\u5df4\u57fa\u65af\u5766\u6642\u9593", "PKT",
|
||||
"\u5df4\u57fa\u65af\u5766\u590f\u4ee4\u6642\u9593", "PKST"};
|
||||
String PONT[] = new String[] {"Pohnpei Time", "PONT",
|
||||
"Pohnpei Summer Time", "PONST"};
|
||||
String PST[] = new String[] {"\u592a\u5e73\u6d0b\u6a19\u6e96\u6642\u9593", "PST",
|
||||
"\u592a\u5e73\u6d0b\u65e5\u5149\u7bc0\u7d04\u6642\u9593", "PDT"};
|
||||
String RST[] = new String[] {"\u6771\u65b9\u6a19\u6e96\u6642\u9593", "EST",
|
||||
@ -169,8 +173,6 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
"\u6771\u90e8\u590f\u4ee4\u6642\u9593 (\u5854\u65af\u6885\u5c3c\u4e9e\u5cf6)", "EST"};
|
||||
String TMT[] = new String[] {"\u571f\u5eab\u66fc\u6642\u9593", "TMT",
|
||||
"\u571f\u5eab\u66fc\u590f\u4ee4\u6642\u9593", "TMST"};
|
||||
String TRUT[] = new String[] {"\u7279\u9b6f\u514b\u6642\u9593", "TRUT",
|
||||
"\u7279\u9b6f\u514b\u590f\u4ee4\u6642\u9593", "TRUST"};
|
||||
String ULAT[]= new String[] {"\u5eab\u502b\u6642\u9593", "ULAT",
|
||||
"\u5eab\u502b\u590f\u4ee4\u6642\u9593", "ULAST"};
|
||||
String WART[] = new String[] {"\u897f\u963f\u6839\u5ef7\u6642\u9593", "WART",
|
||||
@ -309,6 +311,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
{"America/Atikokan", EST},
|
||||
{"America/Atka", HAST},
|
||||
{"America/Bahia", BRT},
|
||||
{"America/Bahia_Banderas", CST},
|
||||
{"America/Barbados", AST},
|
||||
{"America/Belem", BRT},
|
||||
{"America/Belize", CST},
|
||||
@ -446,10 +449,13 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
{"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",
|
||||
"Dumont-d'Urville \u590f\u4ee4\u6642\u9593", "DDUST"}},
|
||||
{"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST",
|
||||
"Macquarie Island Summer Time", "MIST"}},
|
||||
{"Antarctica/Mawson", new String[] {"\u83ab\u68ee\u6642\u9593", "MAWT",
|
||||
"\u83ab\u68ee\u590f\u4ee4\u6642\u9593", "MAWST"}},
|
||||
{"Antarctica/McMurdo", NZST},
|
||||
@ -753,6 +759,7 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
{"Pacific/Apia", WST_SAMOA},
|
||||
{"Pacific/Auckland", NZST},
|
||||
{"Pacific/Chatham", CHAST},
|
||||
{"Pacific/Chuuk", CHUT},
|
||||
{"Pacific/Easter", EASTER},
|
||||
{"Pacific/Efate", new String[] {"\u74e6\u5974\u963f\u5716\u6642\u9593", "VUT",
|
||||
"\u74e6\u5974\u963f\u5716\u590f\u4ee4\u6642\u9593", "VUST"}},
|
||||
@ -791,8 +798,8 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
{"Pacific/Palau", new String[] {"\u5e1b\u7409\u6642\u9593", "PWT",
|
||||
"\u5e1b\u7409\u590f\u4ee4\u6642\u9593", "PWST"}},
|
||||
{"Pacific/Pitcairn", PITCAIRN},
|
||||
{"Pacific/Ponape", new String[] {"Ponape \u6642\u9593", "PONT",
|
||||
"Ponape \u590f\u4ee4\u6642\u9593", "PONST"}},
|
||||
{"Pacific/Pohnpei", PONT},
|
||||
{"Pacific/Ponape", PONT},
|
||||
{"Pacific/Port_Moresby", new String[] {"\u5df4\u5e03\u4e9e\u65b0\u5e7e\u5167\u4e9e\u6642\u9593", "PGT",
|
||||
"\u5df4\u5e03\u4e9e\u65b0\u5e7e\u5167\u4e9e\u590f\u4ee4\u6642\u9593", "PGST"}},
|
||||
{"Pacific/Rarotonga", new String[] {"\u5eab\u514b\u7fa4\u5cf6\u6642\u9593", "CKT",
|
||||
@ -805,12 +812,12 @@ public final class TimeZoneNames_zh_TW extends TimeZoneNamesBundle {
|
||||
"\u5409\u4f2f\u7279\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "GILST"}},
|
||||
{"Pacific/Tongatapu", new String[] {"\u6771\u52a0\u6642\u9593", "TOT",
|
||||
"\u6771\u52a0\u590f\u4ee4\u6642\u9593", "TOST"}},
|
||||
{"Pacific/Truk", TRUT},
|
||||
{"Pacific/Truk", CHUT},
|
||||
{"Pacific/Wake", new String[] {"\u5a01\u514b\u6642\u9593", "WAKT",
|
||||
"\u5a01\u514b\u590f\u4ee4\u6642\u9593", "WAKST"}},
|
||||
{"Pacific/Wallis", new String[] {"\u74e6\u5229\u65af\u53ca\u798f\u675c\u7d0d\u7fa4\u5cf6\u6642\u9593", "WFT",
|
||||
"\u74e6\u5229\u65af\u53ca\u798f\u675c\u7d0d\u7fa4\u5cf6\u590f\u4ee4\u6642\u9593", "WFST"}},
|
||||
{"Pacific/Yap", TRUT},
|
||||
{"Pacific/Yap", CHUT},
|
||||
{"Poland", CET},
|
||||
{"PRC", CTT},
|
||||
{"PST8PDT", PST},
|
||||
|
@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10
|
||||
# Example,
|
||||
# ocsp.responderCertSerialNumber=2A:FF:00
|
||||
|
||||
#
|
||||
# Policy for failed Kerberos KDC lookups:
|
||||
#
|
||||
# When a KDC is unavailable (network error, service failure, etc), it is
|
||||
# put inside a blacklist and accessed less often for future requests. The
|
||||
# value (case-insensitive) for this policy can be:
|
||||
#
|
||||
# tryLast
|
||||
# KDCs in the blacklist are always tried after those not on the list.
|
||||
#
|
||||
# tryLess[:max_retries,timeout]
|
||||
# KDCs in the blacklist are still tried by their order in the configuration,
|
||||
# but with smaller max_retries and timeout values. max_retries and timeout
|
||||
# are optional numerical parameters (default 1 and 5000, which means once
|
||||
# and 5 seconds). Please notes that if any of the values defined here is
|
||||
# more than what is defined in krb5.conf, it will be ignored.
|
||||
#
|
||||
# Whenever a KDC is detected as available, it is removed from the blacklist.
|
||||
# The blacklist is reset when krb5.conf is reloaded. You can add
|
||||
# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
|
||||
# reloaded whenever a JAAS authentication is attempted.
|
||||
#
|
||||
# Example,
|
||||
# krb5.kdc.bad.policy = tryLast
|
||||
# krb5.kdc.bad.policy = tryLess:2,2000
|
||||
krb5.kdc.bad.policy = tryLast
|
||||
|
||||
|
@ -260,3 +260,30 @@ networkaddress.cache.negative.ttl=10
|
||||
# Example,
|
||||
# ocsp.responderCertSerialNumber=2A:FF:00
|
||||
|
||||
#
|
||||
# Policy for failed Kerberos KDC lookups:
|
||||
#
|
||||
# When a KDC is unavailable (network error, service failure, etc), it is
|
||||
# put inside a blacklist and accessed less often for future requests. The
|
||||
# value (case-insensitive) for this policy can be:
|
||||
#
|
||||
# tryLast
|
||||
# KDCs in the blacklist are always tried after those not on the list.
|
||||
#
|
||||
# tryLess[:max_retries,timeout]
|
||||
# KDCs in the blacklist are still tried by their order in the configuration,
|
||||
# but with smaller max_retries and timeout values. max_retries and timeout
|
||||
# are optional numerical parameters (default 1 and 5000, which means once
|
||||
# and 5 seconds). Please notes that if any of the values defined here is
|
||||
# more than what is defined in krb5.conf, it will be ignored.
|
||||
#
|
||||
# Whenever a KDC is detected as available, it is removed from the blacklist.
|
||||
# The blacklist is reset when krb5.conf is reloaded. You can add
|
||||
# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is
|
||||
# reloaded whenever a JAAS authentication is attempted.
|
||||
#
|
||||
# Example,
|
||||
# krb5.kdc.bad.policy = tryLast
|
||||
# krb5.kdc.bad.policy = tryLess:2,2000
|
||||
krb5.kdc.bad.policy = tryLast
|
||||
|
||||
|
@ -2730,7 +2730,10 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta
|
||||
operand);
|
||||
const char *result_signature;
|
||||
check_and_push(context, signature, VM_STRING_UTF);
|
||||
result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC) + 1;
|
||||
result_signature = strchr(signature, JVM_SIGNATURE_ENDFUNC);
|
||||
if (result_signature++ == NULL) {
|
||||
CCerror(context, "Illegal signature %s", signature);
|
||||
}
|
||||
if (result_signature[0] == JVM_SIGNATURE_VOID) {
|
||||
stack_results = "";
|
||||
} else {
|
||||
@ -3654,14 +3657,13 @@ signature_to_fieldtype(context_type *context,
|
||||
const char **signature_p, fullinfo_type *full_info_p)
|
||||
{
|
||||
const char *p = *signature_p;
|
||||
fullinfo_type full_info = MAKE_FULLINFO(0, 0, 0);
|
||||
fullinfo_type full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
|
||||
char result;
|
||||
int array_depth = 0;
|
||||
|
||||
for (;;) {
|
||||
switch(*p++) {
|
||||
default:
|
||||
full_info = MAKE_FULLINFO(ITEM_Bogus, 0, 0);
|
||||
result = 0;
|
||||
break;
|
||||
|
||||
@ -3714,7 +3716,14 @@ signature_to_fieldtype(context_type *context,
|
||||
char buffer_space[256];
|
||||
char *buffer = buffer_space;
|
||||
char *finish = strchr(p, JVM_SIGNATURE_ENDCLASS);
|
||||
int length = finish - p;
|
||||
int length;
|
||||
if (finish == NULL) {
|
||||
/* Signature must have ';' after the class name.
|
||||
* If it does not, return 0 and ITEM_Bogus in full_info. */
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
length = finish - p;
|
||||
if (length + 1 > (int)sizeof(buffer_space)) {
|
||||
buffer = malloc(length + 1);
|
||||
check_and_push(context, buffer, VM_MALLOC_BLK);
|
||||
|
@ -187,7 +187,6 @@ class UnixFileSystem extends FileSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
assert canonicalize0(path).equals(res) || path.startsWith(javaHome);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -1141,6 +1141,13 @@ class UnixPath
|
||||
}
|
||||
result = result.resolve(element);
|
||||
}
|
||||
|
||||
// check file exists (without following links)
|
||||
try {
|
||||
UnixFileAttributes.get(result, false);
|
||||
} catch (UnixException x) {
|
||||
x.rethrowAsIOException(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1052,30 +1052,38 @@ JNIEXPORT void JNICALL
|
||||
Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
||||
jobject this) {
|
||||
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
|
||||
int fd;
|
||||
|
||||
int t = 1;
|
||||
int fd, t = 1;
|
||||
#ifdef AF_INET6
|
||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||
#else
|
||||
int domain = AF_INET;
|
||||
#endif
|
||||
|
||||
if (IS_NULL(fdObj)) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
|
||||
"Socket closed");
|
||||
return;
|
||||
} else {
|
||||
#ifdef AF_INET6
|
||||
if (ipv6_available()) {
|
||||
fd = JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
|
||||
} else
|
||||
#endif /* AF_INET6 */
|
||||
{
|
||||
fd = JVM_Socket(AF_INET, SOCK_DGRAM, 0);
|
||||
}
|
||||
}
|
||||
if (fd == JVM_IO_ERR) {
|
||||
|
||||
if ((fd = JVM_Socket(domain, SOCK_DGRAM, 0)) == JVM_IO_ERR) {
|
||||
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
|
||||
"Error creating socket");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef AF_INET6
|
||||
/* Disable IPV6_V6ONLY to ensure dual-socket support */
|
||||
if (domain == AF_INET6) {
|
||||
int arg = 0;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
|
||||
sizeof(int)) < 0) {
|
||||
NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
|
||||
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
|
||||
|
||||
#ifdef __linux__
|
||||
@ -1088,7 +1096,7 @@ Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
|
||||
* On Linux for IPv6 sockets we must set the hop limit
|
||||
* to 1 to be compatible with default ttl of 1 for IPv4 sockets.
|
||||
*/
|
||||
if (ipv6_available()) {
|
||||
if (domain == AF_INET6) {
|
||||
int ttl = 1;
|
||||
setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
|
||||
sizeof(ttl));
|
||||
|
@ -181,6 +181,12 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
|
||||
jboolean stream) {
|
||||
jobject fdObj, ssObj;
|
||||
int fd;
|
||||
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
|
||||
#ifdef AF_INET6
|
||||
int domain = ipv6_available() ? AF_INET6 : AF_INET;
|
||||
#else
|
||||
int domain = AF_INET;
|
||||
#endif
|
||||
|
||||
if (socketExceptionCls == NULL) {
|
||||
jclass c = (*env)->FindClass(env, "java/net/SocketException");
|
||||
@ -194,25 +200,29 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
|
||||
(*env)->ThrowNew(env, socketExceptionCls, "null fd object");
|
||||
return;
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
if (ipv6_available()) {
|
||||
fd = JVM_Socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
|
||||
} else
|
||||
#endif /* AF_INET6 */
|
||||
{
|
||||
fd = JVM_Socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
|
||||
}
|
||||
if (fd == JVM_IO_ERR) {
|
||||
|
||||
if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
|
||||
/* note: if you run out of fds, you may not be able to load
|
||||
* the exception class, and get a NoClassDefFoundError
|
||||
* instead.
|
||||
*/
|
||||
NET_ThrowNew(env, errno, "can't create socket");
|
||||
return;
|
||||
} else {
|
||||
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
|
||||
}
|
||||
|
||||
#ifdef AF_INET6
|
||||
/* Disable IPV6_V6ONLY to ensure dual-socket support */
|
||||
if (domain == AF_INET6) {
|
||||
int arg = 0;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
|
||||
sizeof(int)) < 0) {
|
||||
NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* AF_INET6 */
|
||||
|
||||
/*
|
||||
* If this is a server socket then enable SO_REUSEADDR
|
||||
* automatically and set to non blocking.
|
||||
@ -221,9 +231,15 @@ Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
|
||||
if (ssObj != NULL) {
|
||||
int arg = 1;
|
||||
SET_NONBLOCKING(fd);
|
||||
JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
|
||||
sizeof(arg));
|
||||
if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
|
||||
sizeof(arg)) < 0) {
|
||||
NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
(*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -170,6 +170,22 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
if (fd < 0) {
|
||||
return handleSocketError(env, errno);
|
||||
}
|
||||
|
||||
#ifdef AF_INET6
|
||||
/* Disable IPV6_V6ONLY to ensure dual-socket support */
|
||||
if (domain == AF_INET6) {
|
||||
int arg = 0;
|
||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
|
||||
sizeof(int)) < 0) {
|
||||
JNU_ThrowByNameWithLastError(env,
|
||||
JNU_JAVANETPKG "SocketException",
|
||||
"sun.nio.ch.Net.setIntOption");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (reuse) {
|
||||
int arg = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
|
||||
|
@ -424,7 +424,6 @@ class Win32FileSystem extends FileSystem {
|
||||
}
|
||||
}
|
||||
}
|
||||
assert canonicalize0(path).equalsIgnoreCase(res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ case "$OS" in
|
||||
Linux )
|
||||
FS="/"
|
||||
;;
|
||||
Windows* )
|
||||
Windows* | CYGWIN* )
|
||||
FS="\\"
|
||||
;;
|
||||
esac
|
||||
|
@ -1536,6 +1536,7 @@ public class Test {
|
||||
serial();
|
||||
urls();
|
||||
npes();
|
||||
bugs();
|
||||
}
|
||||
|
||||
|
||||
@ -1572,6 +1573,19 @@ public class Test {
|
||||
}
|
||||
|
||||
|
||||
// miscellaneous bugs/rfes that don't fit in with the test framework
|
||||
|
||||
static void bugs() {
|
||||
// 6339649 - include detail message from nested exception
|
||||
try {
|
||||
URI uri = URI.create("http://nowhere.net/should not be permitted");
|
||||
} catch (IllegalArgumentException e) {
|
||||
if ("".equals(e.getMessage()) || e.getMessage() == null) {
|
||||
throw new RuntimeException ("No detail message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
switch (args.length) {
|
||||
|
||||
|
@ -260,6 +260,21 @@ public class Misc {
|
||||
*/
|
||||
assertTrue(file.toRealPath(true).isSameFile(file.toRealPath(false)));
|
||||
|
||||
/**
|
||||
* Test: toRealPath should fail if file does not exist
|
||||
*/
|
||||
Path doesNotExist = dir.resolve("DoesNotExist");
|
||||
try {
|
||||
doesNotExist.toRealPath(true);
|
||||
throw new RuntimeException("IOException expected");
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
try {
|
||||
doesNotExist.toRealPath(false);
|
||||
throw new RuntimeException("IOException expected");
|
||||
} catch (IOException expected) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test: toRealPath(true) should resolve links
|
||||
*/
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#
|
||||
# @test
|
||||
# @ignore until 6543856 is fixed
|
||||
# @bug 4990825
|
||||
# @summary attach to external but local JVM processes
|
||||
# @library ../../testlibrary
|
||||
|
59
jdk/test/sun/net/www/protocol/file/DirPermissionDenied.java
Normal file
59
jdk/test/sun/net/www/protocol/file/DirPermissionDenied.java
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DirPermissionDenied {
|
||||
public static void main(String[] args) throws Exception {
|
||||
URL url = new URL("file:" + args[0]);
|
||||
|
||||
try {
|
||||
URLConnection uc = url.openConnection();
|
||||
uc.connect();
|
||||
} catch (IOException e) {
|
||||
// OK
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
URLConnection uc = url.openConnection();
|
||||
uc.getInputStream();
|
||||
} catch (IOException e) {
|
||||
// OK
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed " + e);
|
||||
}
|
||||
|
||||
try {
|
||||
URLConnection uc = url.openConnection();
|
||||
uc.getContentLengthLong();
|
||||
} catch (IOException e) {
|
||||
// OK
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed " + e);
|
||||
}
|
||||
}
|
||||
}
|
41
jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh
Normal file
41
jdk/test/sun/net/www/protocol/file/DirPermissionDenied.sh
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#
|
||||
# @test
|
||||
# @bug 6977851
|
||||
# @summary NPE from FileURLConnection.connect
|
||||
# @build DirPermissionDenied
|
||||
# @run shell DirPermissionDenied.sh
|
||||
|
||||
TESTDIR="${TESTCLASSES}/DirPermissionDeniedDirectory"
|
||||
echo ${TESTDIR}
|
||||
|
||||
rm -rf ${TESTDIR}
|
||||
mkdir -p ${TESTDIR}
|
||||
chmod 333 ${TESTDIR}
|
||||
|
||||
$TESTJAVA/bin/java -classpath $TESTCLASSES DirPermissionDenied ${TESTDIR}
|
||||
result=$?
|
||||
rm -rf ${TESTDIR}
|
||||
exit $result
|
40
jdk/test/sun/security/krb5/BadKdcDefaultValue.java
Normal file
40
jdk/test/sun/security/krb5/BadKdcDefaultValue.java
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6976536
|
||||
* @summary Solaris JREs do not have the krb5.kdc.bad.policy configured by default.
|
||||
* @run main/othervm BadKdcDefaultValue
|
||||
*/
|
||||
|
||||
import java.security.Security;
|
||||
|
||||
public class BadKdcDefaultValue {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (!"tryLast".equalsIgnoreCase(
|
||||
Security.getProperty("krb5.kdc.bad.policy"))) {
|
||||
throw new Exception("Default value not correct");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6226610
|
||||
* @bug 6226610 6973030
|
||||
* @run main/othervm B6226610
|
||||
* @summary HTTP tunnel connections send user headers to proxy
|
||||
*/
|
||||
@ -36,45 +36,23 @@
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import javax.net.ssl.*;
|
||||
import javax.net.ServerSocketFactory;
|
||||
import sun.net.www.*;
|
||||
import java.util.Enumeration;
|
||||
import sun.net.www.MessageHeader;
|
||||
|
||||
public class B6226610 {
|
||||
static HeaderCheckerProxyTunnelServer proxy;
|
||||
|
||||
// it seems there's no proxy ever if a url points to 'localhost',
|
||||
// even if proxy related properties are set. so we need to bind
|
||||
// our simple http proxy and http server to a non-loopback address
|
||||
static InetAddress firstNonLoAddress = null;
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
try {
|
||||
proxy = new HeaderCheckerProxyTunnelServer();
|
||||
proxy.start();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Cannot create proxy: " + e);
|
||||
}
|
||||
proxy = new HeaderCheckerProxyTunnelServer();
|
||||
proxy.start();
|
||||
|
||||
try {
|
||||
firstNonLoAddress = getNonLoAddress();
|
||||
|
||||
if (firstNonLoAddress == null) {
|
||||
System.out.println("The test needs at least one non-loopback address to run. Quit now.");
|
||||
System.exit(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.setProperty( "https.proxyHost", firstNonLoAddress.getHostAddress());
|
||||
System.setProperty( "https.proxyPort", (new Integer(proxy.getLocalPort())).toString() );
|
||||
String hostname = InetAddress.getLocalHost().getHostName();
|
||||
|
||||
try {
|
||||
URL u = new URL("https://" + firstNonLoAddress.getHostAddress());
|
||||
java.net.URLConnection c = u.openConnection();
|
||||
URL u = new URL("https://" + hostname + "/");
|
||||
System.out.println("Connecting to " + u);
|
||||
InetSocketAddress proxyAddr = new InetSocketAddress(hostname, proxy.getLocalPort());
|
||||
java.net.URLConnection c = u.openConnection(new Proxy(Proxy.Type.HTTP, proxyAddr));
|
||||
|
||||
/* I want this header to go to the destination server only, protected
|
||||
* by SSL
|
||||
@ -89,33 +67,15 @@ public class B6226610 {
|
||||
}
|
||||
else
|
||||
System.out.println(e);
|
||||
|
||||
} finally {
|
||||
if (proxy != null) proxy.shutdown();
|
||||
}
|
||||
|
||||
if (HeaderCheckerProxyTunnelServer.failed)
|
||||
throw new RuntimeException("Test failed: Proxy should not receive user defined headers for tunneled requests");
|
||||
throw new RuntimeException("Test failed; see output");
|
||||
}
|
||||
|
||||
public static InetAddress getNonLoAddress() throws Exception {
|
||||
NetworkInterface loNIC = NetworkInterface.getByInetAddress(InetAddress.getByName("localhost"));
|
||||
Enumeration<NetworkInterface> nics = NetworkInterface.getNetworkInterfaces();
|
||||
while (nics.hasMoreElements()) {
|
||||
NetworkInterface nic = nics.nextElement();
|
||||
if (!nic.getName().equalsIgnoreCase(loNIC.getName())) {
|
||||
Enumeration<InetAddress> addrs = nic.getInetAddresses();
|
||||
while (addrs.hasMoreElements()) {
|
||||
InetAddress addr = addrs.nextElement();
|
||||
if (!addr.isLoopbackAddress())
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class HeaderCheckerProxyTunnelServer extends Thread
|
||||
{
|
||||
public static boolean failed = false;
|
||||
@ -139,6 +99,10 @@ class HeaderCheckerProxyTunnelServer extends Thread
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
try { ss.close(); } catch (IOException e) {}
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
try {
|
||||
@ -178,6 +142,15 @@ class HeaderCheckerProxyTunnelServer extends Thread
|
||||
retrieveConnectInfo(statusLine);
|
||||
|
||||
if (mheader.findValue("X-TestHeader") != null) {
|
||||
System.out.println("Proxy should not receive user defined headers for tunneled requests");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
// 6973030
|
||||
String value;
|
||||
if ((value = mheader.findValue("Proxy-Connection")) == null ||
|
||||
!value.equals("keep-alive")) {
|
||||
System.out.println("Proxy-Connection:keep-alive not being sent");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4225317
|
||||
* @bug 4225317 6969651
|
||||
* @summary Check extracted files have date as per those in the .jar file
|
||||
*/
|
||||
|
||||
@ -68,17 +68,9 @@ public class JarEntryTime {
|
||||
}
|
||||
|
||||
public static void realMain(String[] args) throws Throwable {
|
||||
final long now = System.currentTimeMillis();
|
||||
final long earlier = now - (60L * 60L * 6L * 1000L);
|
||||
final long yesterday = now - (60L * 60L * 24L * 1000L);
|
||||
|
||||
// ZipEntry's mod date has 2 seconds precision: give extra time to
|
||||
// allow for e.g. rounding/truncation and networked/samba drives.
|
||||
final long PRECISION = 10000L;
|
||||
|
||||
File dirOuter = new File("outer");
|
||||
File dirInner = new File(dirOuter, "inner");
|
||||
|
||||
File jarFile = new File("JarEntryTime.jar");
|
||||
|
||||
// Remove any leftovers from prior run
|
||||
@ -99,6 +91,17 @@ public class JarEntryTime {
|
||||
PrintWriter pw = new PrintWriter(fileInner);
|
||||
pw.println("hello, world");
|
||||
pw.close();
|
||||
|
||||
// Get the "now" from the "last-modified-time" of the last file we
|
||||
// just created, instead of the "System.currentTimeMillis()", to
|
||||
// workaround the possible "time difference" due to nfs.
|
||||
final long now = fileInner.lastModified();
|
||||
final long earlier = now - (60L * 60L * 6L * 1000L);
|
||||
final long yesterday = now - (60L * 60L * 24L * 1000L);
|
||||
// ZipEntry's mod date has 2 seconds precision: give extra time to
|
||||
// allow for e.g. rounding/truncation and networked/samba drives.
|
||||
final long PRECISION = 10000L;
|
||||
|
||||
dirOuter.setLastModified(now);
|
||||
dirInner.setLastModified(yesterday);
|
||||
fileInner.setLastModified(earlier);
|
||||
|
179
jdk/test/tools/pack200/CommandLineTests.java
Normal file
179
jdk/test/tools/pack200/CommandLineTests.java
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test CommandLineTests.sh
|
||||
* @bug 6521334 6965836 6965836
|
||||
* @compile -XDignore.symbol.file CommandLineTests.java Pack200Test.java
|
||||
* @run main/timeout=1200 CommandLineTests
|
||||
* @summary An ad hoc test to verify the behavior of pack200/unpack200 CLIs,
|
||||
* and a simulation of pack/unpacking in the install repo.
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
/*
|
||||
* We try a potpouri of things ie. we have pack.conf to setup some
|
||||
* options as well as a couple of command line options. We also test
|
||||
* the packing and unpacking mechanism using the Java APIs. This also
|
||||
* simulates pack200 the install workspace, noting that this is a simulation
|
||||
* and can only test jars that are guaranteed to be available, also the
|
||||
* configuration may not be in sync with the installer workspace.
|
||||
*/
|
||||
|
||||
public class CommandLineTests {
|
||||
private static final File CWD = new File(".");
|
||||
private static final File EXP_SDK = new File(CWD, "exp-sdk-image");
|
||||
private static final File EXP_SDK_LIB_DIR = new File(EXP_SDK, "lib");
|
||||
private static final File EXP_SDK_BIN_DIR = new File(EXP_SDK, "bin");
|
||||
private static final File EXP_JRE_DIR = new File(EXP_SDK, "jre");
|
||||
private static final File EXP_JRE_LIB_DIR = new File(EXP_JRE_DIR, "lib");
|
||||
private static final File RtJar = new File(EXP_JRE_LIB_DIR, "rt.jar");
|
||||
private static final File CharsetsJar = new File(EXP_JRE_LIB_DIR, "charsets.jar");
|
||||
private static final File JsseJar = new File(EXP_JRE_LIB_DIR, "jsse.jar");
|
||||
private static final File ToolsJar = new File(EXP_SDK_LIB_DIR, "tools.jar");
|
||||
private static final File javaCmd;
|
||||
private static final File javacCmd;
|
||||
private static final File ConfigFile = new File("pack.conf");
|
||||
private static final List<File> jarList;
|
||||
|
||||
static {
|
||||
javaCmd = Utils.IsWindows
|
||||
? new File(EXP_SDK_BIN_DIR, "java.exe")
|
||||
: new File(EXP_SDK_BIN_DIR, "java");
|
||||
|
||||
javacCmd = Utils.IsWindows
|
||||
? new File(EXP_SDK_BIN_DIR, "javac.exe")
|
||||
: new File(EXP_SDK_BIN_DIR, "javac");
|
||||
|
||||
jarList = new ArrayList<File>();
|
||||
jarList.add(RtJar);
|
||||
jarList.add(CharsetsJar);
|
||||
jarList.add(JsseJar);
|
||||
jarList.add(ToolsJar);
|
||||
}
|
||||
|
||||
// init test area with a copy of the sdk
|
||||
static void init() throws IOException {
|
||||
Utils.recursiveCopy(Utils.JavaSDK, EXP_SDK);
|
||||
creatConfigFile();
|
||||
}
|
||||
|
||||
// Hopefully, this should be kept in sync with what the installer does.
|
||||
static void creatConfigFile() throws IOException {
|
||||
FileOutputStream fos = null;
|
||||
PrintStream ps = null;
|
||||
try {
|
||||
fos = new FileOutputStream(ConfigFile);
|
||||
ps = new PrintStream(fos);
|
||||
ps.println("com.sun.java.util.jar.pack.debug.verbose=0");
|
||||
ps.println("pack.modification.time=keep");
|
||||
ps.println("pack.keep.class.order=true");
|
||||
ps.println("pack.deflate.hint=false");
|
||||
// Fail the build, if new or unknown attributes are introduced.
|
||||
ps.println("pack.unknown.attribute=error");
|
||||
ps.println("pack.segment.limit=-1");
|
||||
// BugId: 6328502, These files will be passed-through as-is.
|
||||
ps.println("pack.pass.file.0=java/lang/Error.class");
|
||||
ps.println("pack.pass.file.1=java/lang/LinkageError.class");
|
||||
ps.println("pack.pass.file.2=java/lang/Object.class");
|
||||
ps.println("pack.pass.file.3=java/lang/Throwable.class");
|
||||
ps.println("pack.pass.file.4=java/lang/VerifyError.class");
|
||||
ps.println("pack.pass.file.5=com/sun/demo/jvmti/hprof/Tracker.class");
|
||||
} finally {
|
||||
Utils.close(ps);
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
static void runPack200(boolean jre) throws IOException {
|
||||
List<String> cmdsList = new ArrayList<String>();
|
||||
for (File f : jarList) {
|
||||
if (jre && f.getName().equals("tools.jar")) {
|
||||
continue; // need not worry about tools.jar for JRE
|
||||
}
|
||||
// make a backup copy for re-use
|
||||
File bakFile = new File(f.getName() + ".bak");
|
||||
if (!bakFile.exists()) { // backup
|
||||
Utils.copyFile(f.getAbsoluteFile(), bakFile.getAbsoluteFile());
|
||||
} else { // restore
|
||||
Utils.copyFile(bakFile.getAbsoluteFile(), f.getAbsoluteFile());
|
||||
}
|
||||
cmdsList.clear();
|
||||
cmdsList.add(Utils.getPack200Cmd());
|
||||
cmdsList.add("-J-esa");
|
||||
cmdsList.add("-J-ea");
|
||||
cmdsList.add(Utils.Is64Bit ? "-J-Xmx1g" : "-J-Xmx512m");
|
||||
cmdsList.add("--repack");
|
||||
cmdsList.add("--config-file=" + ConfigFile.getAbsolutePath());
|
||||
if (jre) {
|
||||
cmdsList.add("--strip-debug");
|
||||
}
|
||||
// NOTE: commented until 6965836 is fixed
|
||||
// cmdsList.add("--code-attribute=StackMapTable=strip");
|
||||
cmdsList.add(f.getAbsolutePath());
|
||||
Utils.runExec(cmdsList);
|
||||
}
|
||||
}
|
||||
|
||||
static void testJRE() throws IOException {
|
||||
runPack200(true);
|
||||
// the speciment JRE
|
||||
List<String> cmdsList = new ArrayList<String>();
|
||||
cmdsList.add(javaCmd.getAbsolutePath());
|
||||
cmdsList.add("-verify");
|
||||
cmdsList.add("-version");
|
||||
Utils.runExec(cmdsList);
|
||||
}
|
||||
|
||||
static void testJDK() throws IOException {
|
||||
runPack200(false);
|
||||
// test the specimen JDK
|
||||
List<String> cmdsList = new ArrayList<String>();
|
||||
cmdsList.add(javaCmd.getAbsolutePath());
|
||||
cmdsList.add("-verify");
|
||||
cmdsList.add("-version");
|
||||
Utils.runExec(cmdsList);
|
||||
|
||||
// invoke javac to test the tools.jar
|
||||
cmdsList.clear();
|
||||
cmdsList.add(javacCmd.getAbsolutePath());
|
||||
cmdsList.add("-J-verify");
|
||||
cmdsList.add("-help");
|
||||
Utils.runExec(cmdsList);
|
||||
}
|
||||
public static void main(String... args) {
|
||||
try {
|
||||
init();
|
||||
testJRE();
|
||||
testJDK();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
128
jdk/test/tools/pack200/Pack200Props.java
Normal file
128
jdk/test/tools/pack200/Pack200Props.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6575373 6969063
|
||||
* @summary verify default properties of the packer/unpacker and segment limit
|
||||
* @compile -XDignore.symbol.file Utils.java Pack200Props.java
|
||||
* @run main Pack200Props
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.Pack200;
|
||||
import java.util.jar.Pack200.Packer;
|
||||
|
||||
/*
|
||||
* Run this against a large jar file, by default the packer should generate only
|
||||
* one segment, parse the output of the packer to verify if this is indeed true.
|
||||
*/
|
||||
|
||||
public class Pack200Props {
|
||||
|
||||
public static void main(String... args) {
|
||||
verifyDefaults();
|
||||
File out = new File("test" + Utils.PACK_FILE_EXT);
|
||||
out.delete();
|
||||
verifySegmentLimit(out);
|
||||
}
|
||||
|
||||
static void verifySegmentLimit(File outFile) {
|
||||
File sdkHome = Utils.JavaSDK;
|
||||
File testJar = new File(new File(sdkHome, "lib"), "tools.jar");
|
||||
|
||||
System.out.println("using pack200: " + Utils.getPack200Cmd());
|
||||
|
||||
List<String> cmdsList = new ArrayList<>();
|
||||
cmdsList.add(Utils.getPack200Cmd());
|
||||
cmdsList.add("--effort=1");
|
||||
cmdsList.add("--verbose");
|
||||
cmdsList.add("--no-gzip");
|
||||
cmdsList.add(outFile.getName());
|
||||
cmdsList.add(testJar.getAbsolutePath());
|
||||
List<String> outList = Utils.runExec(cmdsList);
|
||||
|
||||
int count = 0;
|
||||
for (String line : outList) {
|
||||
System.out.println(line);
|
||||
if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) {
|
||||
throw new RuntimeException("no segments or no output ????");
|
||||
} else if (count > 1) {
|
||||
throw new RuntimeException("multiple segments detected, expected 1");
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyDefaults() {
|
||||
Map<String, String> expectedDefaults = new HashMap<>();
|
||||
Packer p = Pack200.newPacker();
|
||||
expectedDefaults.put("com.sun.java.util.jar.pack.default.timezone",
|
||||
p.FALSE);
|
||||
expectedDefaults.put("com.sun.java.util.jar.pack.disable.native",
|
||||
p.FALSE);
|
||||
expectedDefaults.put("com.sun.java.util.jar.pack.verbose", "0");
|
||||
expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "CompilationID", "RUH");
|
||||
expectedDefaults.put(p.CLASS_ATTRIBUTE_PFX + "SourceID", "RUH");
|
||||
expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CharacterRangeTable",
|
||||
"NH[PHPOHIIH]");
|
||||
expectedDefaults.put(p.CODE_ATTRIBUTE_PFX + "CoverageTable",
|
||||
"NH[PHHII]");
|
||||
expectedDefaults.put(p.DEFLATE_HINT, p.KEEP);
|
||||
expectedDefaults.put(p.EFFORT, "5");
|
||||
expectedDefaults.put(p.KEEP_FILE_ORDER, p.TRUE);
|
||||
expectedDefaults.put(p.MODIFICATION_TIME, p.KEEP);
|
||||
expectedDefaults.put(p.SEGMENT_LIMIT, "-1");
|
||||
expectedDefaults.put(p.UNKNOWN_ATTRIBUTE, p.PASS);
|
||||
|
||||
Map<String, String> props = p.properties();
|
||||
int errors = 0;
|
||||
for (String key : expectedDefaults.keySet()) {
|
||||
String def = expectedDefaults.get(key);
|
||||
String x = props.get(key);
|
||||
if (x == null) {
|
||||
System.out.println("Error: key not found:" + key);
|
||||
errors++;
|
||||
} else {
|
||||
if (!def.equals(x)) {
|
||||
System.out.println("Error: key " + key
|
||||
+ "\n value expected: " + def
|
||||
+ "\n value obtained: " + x);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException(errors +
|
||||
" error(s) encountered in default properties verification");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,197 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
# @test Pack200Simple.sh
|
||||
# @bug 6521334
|
||||
# @build Pack200Test
|
||||
# @run shell/timeout=1200 Pack200Simple.sh
|
||||
# @summary An ad hoc test to verify class-file format.
|
||||
# @author Kumar Srinivasan
|
||||
|
||||
# The goal of this test is to assist javac or other developers
|
||||
# who modify class file formats, to quickly test those modifications
|
||||
# without having to build the install workspace. However it must
|
||||
# be noted that building the install workspace is the only know
|
||||
# way to prevent build breakages.
|
||||
|
||||
# Pack200 developers could use this as a basic smoke-test, however
|
||||
# please note, there are other more elaborate and thorough tests for
|
||||
# this very purpose.
|
||||
|
||||
# We try a potpouri of things ie. we have pack.conf to setup some
|
||||
# options as well as a couple of command line options. We also test
|
||||
# the packing and unpacking mechanism using the Java APIs.
|
||||
|
||||
# print error and exit with a message
|
||||
errorOut() {
|
||||
if [ "x$1" = "x" ]; then
|
||||
printf "Error: Unknown error\n"
|
||||
else
|
||||
printf "Error: %s\n" "$1"
|
||||
fi
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Verify directory context variables are set
|
||||
if [ "${TESTJAVA}" = "" ]; then
|
||||
errorOut "TESTJAVA not set. Test cannot execute. Failed."
|
||||
fi
|
||||
|
||||
if [ "${TESTSRC}" = "" ]; then
|
||||
errorOut "TESTSRC not set. Test cannot execute. Failed."
|
||||
fi
|
||||
|
||||
|
||||
if [ "${TESTCLASSES}" = "" ]; then
|
||||
errorOut "TESTCLASSES not set. Test cannot execute. Failed."
|
||||
fi
|
||||
|
||||
# The common java utils we need
|
||||
PACK200=${TESTJAVA}/bin/pack200
|
||||
UNPACK200=${TESTJAVA}/bin/unpack200
|
||||
JAR=${TESTJAVA}/bin/jar
|
||||
|
||||
# For Windows and Linux needs the heap to be set, for others ergonomics
|
||||
# will do the rest. It is important to use ea, which can expose class
|
||||
# format errors much earlier than later.
|
||||
|
||||
OS=`uname -s`
|
||||
|
||||
|
||||
case "$OS" in
|
||||
Windows*|CYGWIN* )
|
||||
PackOptions="-J-Xmx512m -J-ea"
|
||||
break
|
||||
;;
|
||||
|
||||
Linux )
|
||||
PackOptions="-J-Xmx512m -J-ea"
|
||||
break
|
||||
;;
|
||||
|
||||
* )
|
||||
PackOptions="-J-ea"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Creates a packfile of choice expects 1 argument the filename
|
||||
createConfigFile() {
|
||||
# optimize for speed
|
||||
printf "pack.effort=1\n" > $1
|
||||
# we DO want to know about new attributes
|
||||
printf "pack.unknown.attribute=error\n" >> $1
|
||||
# optimize for speed
|
||||
printf "pack.deflate.hint=false\n" >> $1
|
||||
# keep the ordering for easy compare
|
||||
printf "pack.keep.class.order=true\n" >> $1
|
||||
}
|
||||
|
||||
|
||||
# Tests a given jar, expects 1 argument the fully qualified
|
||||
# name to a test jar, it writes all output to the current
|
||||
# directory which is a scratch area.
|
||||
testAJar() {
|
||||
PackConf="pack.conf"
|
||||
createConfigFile $PackConf
|
||||
|
||||
# Try some command line options
|
||||
CLIPackOptions="$PackOptions -v --no-gzip --segment-limit=10000 --config-file=$PackConf"
|
||||
|
||||
jfName=`basename $1`
|
||||
|
||||
${PACK200} $CLIPackOptions ${jfName}.pack $1 > ${jfName}.pack.log 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
errorOut "$jfName packing failed"
|
||||
fi
|
||||
|
||||
# We want to test unpack200, therefore we dont use -r with pack
|
||||
${UNPACK200} -v ${jfName}.pack $jfName > ${jfName}.unpack.log 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
errorOut "$jfName unpacking failed"
|
||||
fi
|
||||
|
||||
# A quick crc compare test to ensure a well formed zip
|
||||
# archive, this is a critical unpack200 behaviour.
|
||||
|
||||
unzip -t $jfName > ${jfName}.unzip.log 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
errorOut "$jfName unzip -t test failed"
|
||||
fi
|
||||
|
||||
# The PACK200 signature should be at the top of the log
|
||||
# this tag is critical for deployment related tools.
|
||||
|
||||
head -5 ${jfName}.unzip.log | grep PACK200 > /dev/null 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
errorOut "$jfName PACK200 signature missing"
|
||||
fi
|
||||
|
||||
|
||||
# we know the size fields don't match, strip 'em out, its
|
||||
# extremely important to ensure that the date stamps match up.
|
||||
# Don't EVER sort the output we are checking for correct ordering.
|
||||
|
||||
${JAR} -tvf $1 | sed -e 's/^ *[0-9]* //g'> ${jfName}.ref.txt
|
||||
${JAR} -tvf $jfName | sed -e 's/^ *[0-9]* //g'> ${jfName}.cmp.txt
|
||||
|
||||
diff ${jfName}.ref.txt ${jfName}.cmp.txt > ${jfName}.diff.log 2>&1
|
||||
if [ $? != 0 ]; then
|
||||
errorOut "$jfName files missing"
|
||||
fi
|
||||
}
|
||||
|
||||
# These JARs are the largest and also the most likely specimens to
|
||||
# expose class format issues and stress the packer as well.
|
||||
|
||||
JLIST="${TESTJAVA}/lib/tools.jar ${TESTJAVA}/jre/lib/rt.jar"
|
||||
|
||||
|
||||
# Test the Command Line Interfaces (CLI).
|
||||
mkdir cliTestDir
|
||||
_pwd=`pwd`
|
||||
cd cliTestDir
|
||||
|
||||
for jarfile in $JLIST ; do
|
||||
if [ -f $jarfile ]; then
|
||||
testAJar $jarfile
|
||||
else
|
||||
errorOut "Error: '$jarFile' does not exist\nTest requires a j2sdk-image\n"
|
||||
fi
|
||||
done
|
||||
cd $_pwd
|
||||
|
||||
# Test the Java APIs.
|
||||
mkdir apiTestDir
|
||||
_pwd=`pwd`
|
||||
cd apiTestDir
|
||||
|
||||
# Strip out the -J prefixes.
|
||||
JavaPackOptions=`printf %s "$PackOptions" | sed -e 's/-J//g'`
|
||||
|
||||
# Test the Java APIs now.
|
||||
$TESTJAVA/bin/java $JavaPackOptions -cp $TESTCLASSES Pack200Test $JLIST || exit 1
|
||||
|
||||
cd $_pwd
|
||||
|
||||
exit 0
|
@ -24,111 +24,97 @@
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryMXBean;
|
||||
import java.util.jar.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
/*
|
||||
* Pack200Test.java
|
||||
*
|
||||
* @author ksrini
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6521334 6712743
|
||||
* @summary check for memory leaks, test general packer/unpacker functionality\
|
||||
* using native and java unpackers
|
||||
* @compile -XDignore.symbol.file Utils.java Pack200Test.java
|
||||
* @run main/othervm/timeout=1200 -Xmx512m Pack200Test
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
/**
|
||||
* These tests are very rudimentary smoke tests to ensure that the packing
|
||||
* unpacking process works on a select set of JARs.
|
||||
* Tests the packing/unpacking via the APIs.
|
||||
*/
|
||||
public class Pack200Test {
|
||||
|
||||
private static ArrayList <File> jarList = new ArrayList<File>();
|
||||
static final String PACKEXT = ".pack";
|
||||
static final MemoryMXBean mmxbean = ManagementFactory.getMemoryMXBean();
|
||||
static final long m0 = getUsedMemory();
|
||||
static final int LEAK_TOLERANCE = 20000; // OS and GC related variations.
|
||||
|
||||
/** Creates a new instance of Pack200Test */
|
||||
private Pack200Test() {}
|
||||
|
||||
static long getUsedMemory() {
|
||||
mmxbean.gc();
|
||||
mmxbean.gc();
|
||||
mmxbean.gc();
|
||||
return mmxbean.getHeapMemoryUsage().getUsed()/1024;
|
||||
}
|
||||
|
||||
private static void leakCheck() throws Exception {
|
||||
long diff = getUsedMemory() - m0;
|
||||
System.out.println(" Info: memory diff = " + diff + "K");
|
||||
if ( diff > LEAK_TOLERANCE) {
|
||||
throw new Exception("memory leak detected " + diff);
|
||||
}
|
||||
}
|
||||
|
||||
private static void doPackUnpack() {
|
||||
for (File in : jarList) {
|
||||
Pack200.Packer packer = Pack200.newPacker();
|
||||
Map<String, String> p = packer.properties();
|
||||
// Take the time optimization vs. space
|
||||
p.put(packer.EFFORT, "1"); // CAUTION: do not use 0.
|
||||
// Make the memory consumption as effective as possible
|
||||
p.put(packer.SEGMENT_LIMIT,"10000");
|
||||
// throw an error if an attribute is unrecognized
|
||||
p.put(packer.UNKNOWN_ATTRIBUTE, packer.ERROR);
|
||||
// ignore all JAR deflation requests to save time
|
||||
p.put(packer.DEFLATE_HINT, packer.FALSE);
|
||||
// save the file ordering of the original JAR
|
||||
p.put(packer.KEEP_FILE_ORDER, packer.TRUE);
|
||||
|
||||
JarOutputStream javaUnpackerStream = null;
|
||||
JarOutputStream nativeUnpackerStream = null;
|
||||
JarFile jarFile = null;
|
||||
try {
|
||||
JarFile jarFile = new JarFile(in);
|
||||
jarFile = new JarFile(in);
|
||||
|
||||
// Write out to a jtreg scratch area
|
||||
FileOutputStream fos = new FileOutputStream(in.getName() + PACKEXT);
|
||||
File packFile = new File(in.getName() + Utils.PACK_FILE_EXT);
|
||||
|
||||
System.out.print("Packing [" + in.toString() + "]...");
|
||||
System.out.println("Packing [" + in.toString() + "]");
|
||||
// Call the packer
|
||||
packer.pack(jarFile, fos);
|
||||
Utils.pack(jarFile, packFile);
|
||||
jarFile.close();
|
||||
fos.close();
|
||||
|
||||
System.out.print("Unpacking...");
|
||||
File f = new File(in.getName() + PACKEXT);
|
||||
leakCheck();
|
||||
|
||||
System.out.println(" Unpacking using java unpacker");
|
||||
File javaUnpackedJar = new File("java-" + in.getName());
|
||||
// Write out to current directory, jtreg will setup a scratch area
|
||||
JarOutputStream jostream = new JarOutputStream(new FileOutputStream(in.getName()));
|
||||
|
||||
// Unpack the files
|
||||
Pack200.Unpacker unpacker = Pack200.newUnpacker();
|
||||
// Call the unpacker
|
||||
unpacker.unpack(f, jostream);
|
||||
// Must explicitly close the output.
|
||||
jostream.close();
|
||||
System.out.print("Testing...");
|
||||
javaUnpackerStream = new JarOutputStream(
|
||||
new FileOutputStream(javaUnpackedJar));
|
||||
Utils.unpackj(packFile, javaUnpackerStream);
|
||||
javaUnpackerStream.close();
|
||||
System.out.println(" Testing...java unpacker");
|
||||
leakCheck();
|
||||
// Ok we have unpacked the file, lets test it.
|
||||
doTest(in);
|
||||
Utils.doCompareVerify(in.getAbsoluteFile(), javaUnpackedJar);
|
||||
|
||||
System.out.println(" Unpacking using native unpacker");
|
||||
// Write out to current directory
|
||||
File nativeUnpackedJar = new File("native-" + in.getName());
|
||||
nativeUnpackerStream = new JarOutputStream(
|
||||
new FileOutputStream(nativeUnpackedJar));
|
||||
Utils.unpackn(packFile, nativeUnpackerStream);
|
||||
nativeUnpackerStream.close();
|
||||
System.out.println(" Testing...native unpacker");
|
||||
leakCheck();
|
||||
// the unpackers (native and java) should produce identical bits
|
||||
// so we use use bit wise compare, the verification compare is
|
||||
// very expensive wrt. time.
|
||||
Utils.doCompareBitWise(javaUnpackedJar, nativeUnpackedJar);
|
||||
System.out.println("Done.");
|
||||
} catch (Exception e) {
|
||||
System.out.println("ERROR: " + e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList <String> getZipFileEntryNames(ZipFile z) {
|
||||
ArrayList <String> out = new ArrayList<String>();
|
||||
for (ZipEntry ze : Collections.list(z.entries())) {
|
||||
out.add(ze.getName());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static void doTest(File in) throws Exception {
|
||||
// make sure all the files in the original jar exists in the other
|
||||
ArrayList <String> refList = getZipFileEntryNames(new ZipFile(in));
|
||||
ArrayList <String> cmpList = getZipFileEntryNames(new ZipFile(in.getName()));
|
||||
|
||||
System.out.print(refList.size() + "/" + cmpList.size() + " entries...");
|
||||
|
||||
if (refList.size() != cmpList.size()) {
|
||||
throw new Exception("Missing: files ?, entries don't match");
|
||||
}
|
||||
|
||||
for (String ename: refList) {
|
||||
if (!cmpList.contains(ename)) {
|
||||
throw new Exception("Does not contain : " + ename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void doSanity(String[] args) {
|
||||
for (String s: args) {
|
||||
File f = new File(s);
|
||||
if (f.exists()) {
|
||||
jarList.add(f);
|
||||
} else {
|
||||
System.out.println("Warning: The JAR file " + f.toString() + " does not exist,");
|
||||
System.out.println(" this test requires a JDK image, this file will be skipped.");
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
Utils.close(nativeUnpackerStream);
|
||||
Utils.close(javaUnpackerStream);
|
||||
Utils.close((Closeable) jarFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,11 +123,12 @@ public class Pack200Test {
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length < 1) {
|
||||
System.out.println("Usage: jar1 jar2 jar3 .....");
|
||||
System.exit(1);
|
||||
}
|
||||
doSanity(args);
|
||||
// select the jars carefully, adding more jars will increase the
|
||||
// testing time, especially for jprt.
|
||||
jarList.add(Utils.locateJar("tools.jar"));
|
||||
jarList.add(Utils.locateJar("rt.jar"));
|
||||
jarList.add(Utils.locateJar("golden.jar"));
|
||||
System.out.println(jarList);
|
||||
doPackUnpack();
|
||||
}
|
||||
}
|
||||
|
@ -22,13 +22,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6712743
|
||||
* @summary verify package versioning
|
||||
* @compile -XDignore.symbol.file PackageVersionTest.java
|
||||
* @run main PackageVersionTest
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6712743
|
||||
* @summary verify package versions
|
||||
* @compile -XDignore.symbol.file Utils.java PackageVersionTest.java
|
||||
* @run main PackageVersionTest
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
@ -74,14 +75,6 @@ public class PackageVersionTest {
|
||||
JAVA5_PACKAGE_MINOR_VERSION);
|
||||
}
|
||||
|
||||
static void close(Closeable c) {
|
||||
if (c == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException ignore) {}
|
||||
}
|
||||
|
||||
static void createClassFile(String name) {
|
||||
createJavaFile(name);
|
||||
@ -93,7 +86,7 @@ public class PackageVersionTest {
|
||||
name.substring(name.length() - 1),
|
||||
name + ".java"
|
||||
};
|
||||
compileJava(javacCmds);
|
||||
Utils.compiler(javacCmds);
|
||||
}
|
||||
|
||||
static void createJavaFile(String name) {
|
||||
@ -108,22 +101,8 @@ public class PackageVersionTest {
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("creation of test file failed");
|
||||
} finally {
|
||||
close(ps);
|
||||
close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
static void compileJava(String... javacCmds) {
|
||||
if (com.sun.tools.javac.Main.compile(javacCmds) != 0) {
|
||||
throw new RuntimeException("compilation failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void makeJar(String... jargs) {
|
||||
sun.tools.jar.Main jarTool =
|
||||
new sun.tools.jar.Main(System.out, System.err, "jartool");
|
||||
if (!jarTool.run(jargs)) {
|
||||
throw new RuntimeException("jar command failed");
|
||||
Utils.close(ps);
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +115,7 @@ public class PackageVersionTest {
|
||||
jarFileName.getName(),
|
||||
filename
|
||||
};
|
||||
makeJar(jargs);
|
||||
Utils.jar(jargs);
|
||||
JarFile jfin = null;
|
||||
|
||||
try {
|
||||
@ -163,7 +142,7 @@ public class PackageVersionTest {
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe.getMessage());
|
||||
} finally {
|
||||
close(jfin);
|
||||
Utils.close((Closeable) jfin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 6575373
|
||||
* @summary verify default segment limit
|
||||
* @compile SegmentLimit.java
|
||||
* @run main SegmentLimit
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
|
||||
/*
|
||||
* Run this against a large jar file, by default the packer should generate only
|
||||
* one segment, parse the output of the packer to verify if this is indeed true.
|
||||
*/
|
||||
|
||||
public class SegmentLimit {
|
||||
|
||||
private static final File javaHome = new File(System.getProperty("java.home"));
|
||||
|
||||
public static void main(String... args) {
|
||||
if (!javaHome.getName().endsWith("jre")) {
|
||||
throw new RuntimeException("Error: requires an SDK to run");
|
||||
}
|
||||
|
||||
File out = new File("test" + Pack200Test.PACKEXT);
|
||||
out.delete();
|
||||
runPack200(out);
|
||||
}
|
||||
|
||||
static void close(Closeable c) {
|
||||
if (c == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException ignore) {}
|
||||
}
|
||||
|
||||
static void runPack200(File outFile) {
|
||||
File binDir = new File(javaHome, "bin");
|
||||
File pack200Exe = System.getProperty("os.name").startsWith("Windows")
|
||||
? new File(binDir, "pack200.exe")
|
||||
: new File(binDir, "pack200");
|
||||
File sdkHome = javaHome.getParentFile();
|
||||
File testJar = new File(new File(sdkHome, "lib"), "tools.jar");
|
||||
|
||||
System.out.println("using pack200: " + pack200Exe.getAbsolutePath());
|
||||
|
||||
String[] cmds = { pack200Exe.getAbsolutePath(),
|
||||
"--effort=1",
|
||||
"--verbose",
|
||||
"--no-gzip",
|
||||
outFile.getName(),
|
||||
testJar.getAbsolutePath()
|
||||
};
|
||||
InputStream is = null;
|
||||
BufferedReader br = null;
|
||||
InputStreamReader ir = null;
|
||||
|
||||
FileOutputStream fos = null;
|
||||
PrintStream ps = null;
|
||||
|
||||
try {
|
||||
ProcessBuilder pb = new ProcessBuilder(cmds);
|
||||
pb.redirectErrorStream(true);
|
||||
Process p = pb.start();
|
||||
is = p.getInputStream();
|
||||
ir = new InputStreamReader(is);
|
||||
br = new BufferedReader(ir);
|
||||
|
||||
File logFile = new File("pack200.log");
|
||||
fos = new FileOutputStream(logFile);
|
||||
ps = new PrintStream(fos);
|
||||
|
||||
String line = br.readLine();
|
||||
int count = 0;
|
||||
while (line != null) {
|
||||
line = line.trim();
|
||||
if (line.matches(".*Transmitted.*files of.*input bytes in a segment of.*bytes")) {
|
||||
count++;
|
||||
}
|
||||
ps.println(line);
|
||||
line=br.readLine();
|
||||
}
|
||||
p.waitFor();
|
||||
if (p.exitValue() != 0) {
|
||||
throw new RuntimeException("pack200 failed");
|
||||
}
|
||||
p.destroy();
|
||||
if (count > 1) {
|
||||
throw new Error("test fails: check for multiple segments(" +
|
||||
count + ") in: " + logFile.getAbsolutePath());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
} catch (InterruptedException ignore){
|
||||
} finally {
|
||||
close(is);
|
||||
close(ps);
|
||||
close(fos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
156
jdk/test/tools/pack200/TimeStamp.java
Normal file
156
jdk/test/tools/pack200/TimeStamp.java
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6966740
|
||||
* @summary verify identical timestamps, unpacked in any timezone
|
||||
* @compile -XDignore.symbol.file Utils.java TimeStamp.java
|
||||
* @run main/othervm TimeStamp
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
/**
|
||||
* First we pack the file in some time zone say India, then we unpack the file
|
||||
* in the current time zone, and ensure the timestamp recorded in the unpacked
|
||||
* jar are the same.
|
||||
*/
|
||||
public class TimeStamp {
|
||||
static final TimeZone tz = TimeZone.getDefault();
|
||||
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
|
||||
// make a local copy of our test file
|
||||
File srcFile = Utils.locateJar("golden.jar");
|
||||
File goldenFile = new File("golden.jar");
|
||||
Utils.copyFile(srcFile, goldenFile.getAbsoluteFile());
|
||||
|
||||
JarFile goldenJarFile = new JarFile(goldenFile);
|
||||
File packFile = new File("golden.pack");
|
||||
|
||||
// set the test timezone and pack the file
|
||||
TimeZone.setDefault(TimeZone.getTimeZone("IST"));
|
||||
Utils.pack(goldenJarFile, packFile);
|
||||
TimeZone.setDefault(tz); // reset the timezone
|
||||
|
||||
// unpack in the test timezone
|
||||
File istFile = new File("golden.jar.java.IST");
|
||||
unpackJava(packFile, istFile);
|
||||
verifyJar(goldenFile, istFile);
|
||||
istFile.delete();
|
||||
|
||||
// unpack in some other timezone
|
||||
File pstFile = new File("golden.jar.java.PST");
|
||||
unpackJava(packFile, pstFile);
|
||||
verifyJar(goldenFile, pstFile);
|
||||
pstFile.delete();
|
||||
|
||||
// repeat the test for unpack200 tool.
|
||||
istFile = new File("golden.jar.native.IST");
|
||||
unpackNative(packFile, istFile);
|
||||
verifyJar(goldenFile, istFile);
|
||||
istFile.delete();
|
||||
|
||||
pstFile = new File("golden.jar.native.PST");
|
||||
unpackNative(packFile, pstFile);
|
||||
verifyJar(goldenFile, pstFile);
|
||||
pstFile.delete();
|
||||
}
|
||||
|
||||
static void unpackNative(File packFile, File outFile) {
|
||||
String name = outFile.getName();
|
||||
String tzname = name.substring(name.lastIndexOf(".") + 1);
|
||||
HashMap<String, String> env = new HashMap<>();
|
||||
switch(tzname) {
|
||||
case "PST":
|
||||
env.put("TZ", "US/Pacific");
|
||||
break;
|
||||
case "IST":
|
||||
env.put("TZ", "Asia/Calcutta");
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("not implemented: " + tzname);
|
||||
}
|
||||
List<String> cmdsList = new ArrayList<>();
|
||||
cmdsList.add(Utils.getUnpack200Cmd());
|
||||
cmdsList.add(packFile.getName());
|
||||
cmdsList.add(outFile.getName());
|
||||
Utils.runExec(cmdsList, env);
|
||||
}
|
||||
|
||||
static void unpackJava(File packFile, File outFile) throws IOException {
|
||||
String name = outFile.getName();
|
||||
String tzname = name.substring(name.lastIndexOf(".") + 1);
|
||||
JarOutputStream jos = null;
|
||||
try {
|
||||
TimeZone.setDefault(TimeZone.getTimeZone(tzname));
|
||||
jos = new JarOutputStream(new FileOutputStream(outFile));
|
||||
System.out.println("Using timezone: " + TimeZone.getDefault());
|
||||
Utils.unpackj(packFile, jos);
|
||||
} finally {
|
||||
Utils.close(jos);
|
||||
TimeZone.setDefault(tz); // always reset
|
||||
}
|
||||
}
|
||||
|
||||
static void verifyJar(File f1, File f2) throws IOException {
|
||||
int errors = 0;
|
||||
JarFile jf1 = null;
|
||||
JarFile jf2 = null;
|
||||
try {
|
||||
jf1 = new JarFile(f1);
|
||||
jf2 = new JarFile(f2);
|
||||
System.out.println("Verifying: " + f1 + " and " + f2);
|
||||
for (JarEntry je1 : Collections.list(jf1.entries())) {
|
||||
JarEntry je2 = jf2.getJarEntry(je1.getName());
|
||||
if (je1.getTime() != je2.getTime()) {
|
||||
System.out.println("Error:");
|
||||
System.out.println(" expected:" + jf1.getName() + ":"
|
||||
+ je1.getName() + ":" + je1.getTime());
|
||||
System.out.println(" obtained:" + jf2.getName() + ":"
|
||||
+ je2.getName() + ":" + je2.getTime());
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Utils.close(jf1);
|
||||
Utils.close(jf2);
|
||||
}
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException("FAIL:" + errors + " error(s) encounted");
|
||||
}
|
||||
}
|
||||
}
|
86
jdk/test/tools/pack200/UnpackerMemoryTest.java
Normal file
86
jdk/test/tools/pack200/UnpackerMemoryTest.java
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6531345
|
||||
* @summary check for unpacker memory leaks
|
||||
* @compile -XDignore.symbol.file Utils.java UnpackerMemoryTest.java
|
||||
* @run main/othervm/timeout=1200 -Xmx32m UnpackerMemoryTest
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.io.IOException;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
|
||||
public class UnpackerMemoryTest {
|
||||
|
||||
private static void createPackFile(File packFile) throws IOException {
|
||||
File tFile = new File("test.dat");
|
||||
FileOutputStream fos = null;
|
||||
PrintStream ps = null;
|
||||
String jarFileName = Utils.baseName(packFile, Utils.PACK_FILE_EXT)
|
||||
+ Utils.JAR_FILE_EXT;
|
||||
JarFile jarFile = null;
|
||||
try {
|
||||
fos = new FileOutputStream(tFile);
|
||||
ps = new PrintStream(fos);
|
||||
ps.println("A quick brown fox");
|
||||
Utils.jar("cvf", jarFileName, tFile.getName());
|
||||
jarFile = new JarFile(jarFileName);
|
||||
Utils.pack(jarFile, packFile);
|
||||
} finally {
|
||||
Utils.close(ps);
|
||||
tFile.delete();
|
||||
Utils.close(jarFile);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String name = "foo";
|
||||
File packFile = new File(name + Utils.PACK_FILE_EXT);
|
||||
createPackFile(packFile);
|
||||
if (!packFile.exists()) {
|
||||
throw new RuntimeException(packFile + " not found");
|
||||
}
|
||||
File jarOut = new File(name + ".out");
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
JarOutputStream jarOS = null;
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(jarOut);
|
||||
jarOS = new JarOutputStream(fos);
|
||||
System.out.println("Unpacking[" + i + "]" + packFile);
|
||||
Utils.unpackn(packFile, jarOS);
|
||||
} finally {
|
||||
Utils.close(jarOS);
|
||||
Utils.close(fos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
516
jdk/test/tools/pack200/Utils.java
Normal file
516
jdk/test/tools/pack200/Utils.java
Normal file
@ -0,0 +1,516 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2010 Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Pack200;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
/*
|
||||
* This class contains all the commonly used utilities used by various tests
|
||||
* in this directory.
|
||||
*/
|
||||
class Utils {
|
||||
static final String JavaHome = System.getProperty("test.java",
|
||||
System.getProperty("java.home"));
|
||||
static final boolean IsWindows =
|
||||
System.getProperty("os.name").startsWith("Windows");
|
||||
static final boolean Is64Bit =
|
||||
System.getProperty("sun.arch.data.model", "32").equals("64");
|
||||
static final File JavaSDK = new File(JavaHome).getParentFile();
|
||||
|
||||
static final String PACK_FILE_EXT = ".pack";
|
||||
static final String JAVA_FILE_EXT = ".java";
|
||||
static final String CLASS_FILE_EXT = ".class";
|
||||
static final String JAR_FILE_EXT = ".jar";
|
||||
|
||||
static final File TEST_SRC_DIR = new File(System.getProperty("test.src"));
|
||||
static final String VERIFIER_DIR_NAME = "pack200-verifier";
|
||||
static final File VerifierJar = new File(VERIFIER_DIR_NAME + JAR_FILE_EXT);
|
||||
|
||||
private Utils() {} // all static
|
||||
|
||||
static {
|
||||
if (!JavaHome.endsWith("jre")) {
|
||||
throw new RuntimeException("Error: requires an SDK to run");
|
||||
}
|
||||
}
|
||||
|
||||
private static void init() throws IOException {
|
||||
if (VerifierJar.exists()) {
|
||||
return;
|
||||
}
|
||||
File srcDir = new File(TEST_SRC_DIR, VERIFIER_DIR_NAME);
|
||||
List<File> javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT));
|
||||
File tmpFile = File.createTempFile("javac", ".tmp");
|
||||
File classesDir = new File("xclasses");
|
||||
classesDir.mkdirs();
|
||||
FileOutputStream fos = null;
|
||||
PrintStream ps = null;
|
||||
try {
|
||||
fos = new FileOutputStream(tmpFile);
|
||||
ps = new PrintStream(fos);
|
||||
for (File f : javaFileList) {
|
||||
ps.println(f.getAbsolutePath());
|
||||
}
|
||||
} finally {
|
||||
close(ps);
|
||||
close(fos);
|
||||
}
|
||||
|
||||
compiler("-d",
|
||||
"xclasses",
|
||||
"@" + tmpFile.getAbsolutePath());
|
||||
|
||||
jar("cvfe",
|
||||
VerifierJar.getName(),
|
||||
"sun.tools.pack.verify.Main",
|
||||
"-C",
|
||||
"xclasses",
|
||||
".");
|
||||
}
|
||||
|
||||
static void dirlist(File dir) {
|
||||
File[] files = dir.listFiles();
|
||||
System.out.println("--listing " + dir.getAbsolutePath() + "---");
|
||||
for (File f : files) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append(f.isDirectory() ? "d " : "- ");
|
||||
sb.append(f.getName());
|
||||
System.out.println(sb);
|
||||
}
|
||||
}
|
||||
static void doCompareVerify(File reference, File specimen) throws IOException {
|
||||
init();
|
||||
List<String> cmds = new ArrayList<String>();
|
||||
cmds.add(getJavaCmd());
|
||||
cmds.add("-jar");
|
||||
cmds.add(VerifierJar.getName());
|
||||
cmds.add(reference.getAbsolutePath());
|
||||
cmds.add(specimen.getAbsolutePath());
|
||||
cmds.add("-O");
|
||||
runExec(cmds);
|
||||
}
|
||||
|
||||
static void doCompareBitWise(File reference, File specimen)
|
||||
throws IOException {
|
||||
init();
|
||||
List<String> cmds = new ArrayList<String>();
|
||||
cmds.add(getJavaCmd());
|
||||
cmds.add("-jar");
|
||||
cmds.add(VerifierJar.getName());
|
||||
cmds.add(reference.getName());
|
||||
cmds.add(specimen.getName());
|
||||
cmds.add("-O");
|
||||
cmds.add("-b");
|
||||
runExec(cmds);
|
||||
}
|
||||
|
||||
static FileFilter createFilter(final String extension) {
|
||||
return new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File pathname) {
|
||||
String name = pathname.getName();
|
||||
if (name.endsWith(extension)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static final FileFilter DIR_FILTER = new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
if (pathname.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
static final FileFilter FILE_FILTER = new FileFilter() {
|
||||
public boolean accept(File pathname) {
|
||||
if (pathname.isFile()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
private static void setFileAttributes(File src, File dst) throws IOException {
|
||||
dst.setExecutable(src.canExecute());
|
||||
dst.setReadable(src.canRead());
|
||||
dst.setWritable(src.canWrite());
|
||||
dst.setLastModified(src.lastModified());
|
||||
}
|
||||
|
||||
static void copyFile(File src, File dst) throws IOException {
|
||||
if (src.isDirectory()) {
|
||||
dst.mkdirs();
|
||||
setFileAttributes(src, dst);
|
||||
return;
|
||||
} else {
|
||||
File baseDirFile = dst.getParentFile();
|
||||
if (!baseDirFile.exists()) {
|
||||
baseDirFile.mkdirs();
|
||||
}
|
||||
}
|
||||
FileInputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
FileChannel srcChannel = null;
|
||||
FileChannel dstChannel = null;
|
||||
try {
|
||||
in = new FileInputStream(src);
|
||||
out = new FileOutputStream(dst);
|
||||
srcChannel = in.getChannel();
|
||||
dstChannel = out.getChannel();
|
||||
|
||||
long retval = srcChannel.transferTo(0, src.length(), dstChannel);
|
||||
if (src.length() != dst.length()) {
|
||||
throw new IOException("file copy failed for " + src);
|
||||
}
|
||||
} finally {
|
||||
close(srcChannel);
|
||||
close(dstChannel);
|
||||
close(in);
|
||||
close(out);
|
||||
}
|
||||
setFileAttributes(src, dst);
|
||||
}
|
||||
|
||||
static String baseName(File file, String extension) {
|
||||
return baseName(file.getAbsolutePath(), extension);
|
||||
}
|
||||
|
||||
static String baseName(String name, String extension) {
|
||||
int cut = name.length() - extension.length();
|
||||
return name.lastIndexOf(extension) == cut
|
||||
? name.substring(0, cut)
|
||||
: name;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Suppose a path is provided which consists of a full path
|
||||
* this method returns the sub path for a full path ex: /foo/bar/baz/foobar.z
|
||||
* and the base path is /foo/bar it will will return baz/foobar.z.
|
||||
*/
|
||||
private static String getEntryPath(String basePath, String fullPath) {
|
||||
if (!fullPath.startsWith(basePath)) {
|
||||
return null;
|
||||
}
|
||||
return fullPath.substring(basePath.length());
|
||||
}
|
||||
|
||||
static String getEntryPath(File basePathFile, File fullPathFile) {
|
||||
return getEntryPath(basePathFile.toString(), fullPathFile.toString());
|
||||
}
|
||||
|
||||
public static void recursiveCopy(File src, File dest) throws IOException {
|
||||
if (!src.exists() || !src.canRead()) {
|
||||
throw new IOException("file not found or readable: " + src);
|
||||
}
|
||||
if (dest.exists() && !dest.isDirectory() && !dest.canWrite()) {
|
||||
throw new IOException("file not found or writeable: " + dest);
|
||||
}
|
||||
if (!dest.exists()) {
|
||||
dest.mkdirs();
|
||||
}
|
||||
List<File> a = directoryList(src);
|
||||
for (File f : a) {
|
||||
copyFile(f, new File(dest, getEntryPath(src, f)));
|
||||
}
|
||||
}
|
||||
|
||||
static List<File> directoryList(File dirname) {
|
||||
List<File> dirList = new ArrayList<File>();
|
||||
return directoryList(dirname, dirList, null);
|
||||
}
|
||||
|
||||
private static List<File> directoryList(File dirname, List<File> dirList,
|
||||
File[] dirs) {
|
||||
dirList.addAll(Arrays.asList(dirname.listFiles(FILE_FILTER)));
|
||||
dirs = dirname.listFiles(DIR_FILTER);
|
||||
for (File f : dirs) {
|
||||
if (f.isDirectory() && !f.equals(dirname)) {
|
||||
dirList.add(f);
|
||||
directoryList(f, dirList, dirs);
|
||||
}
|
||||
}
|
||||
return dirList;
|
||||
}
|
||||
|
||||
static void recursiveDelete(File dir) throws IOException {
|
||||
if (dir.isFile()) {
|
||||
dir.delete();
|
||||
} else if (dir.isDirectory()) {
|
||||
File[] entries = dir.listFiles();
|
||||
for (int i = 0; i < entries.length; i++) {
|
||||
if (entries[i].isDirectory()) {
|
||||
recursiveDelete(entries[i]);
|
||||
}
|
||||
entries[i].delete();
|
||||
}
|
||||
dir.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static List<File> findFiles(File startDir, FileFilter filter)
|
||||
throws IOException {
|
||||
List<File> list = new ArrayList<File>();
|
||||
findFiles0(startDir, list, filter);
|
||||
return list;
|
||||
}
|
||||
/*
|
||||
* finds files in the start directory using the the filter, appends
|
||||
* the files to the dirList.
|
||||
*/
|
||||
private static void findFiles0(File startDir, List<File> list,
|
||||
FileFilter filter) throws IOException {
|
||||
File[] foundFiles = startDir.listFiles(filter);
|
||||
list.addAll(Arrays.asList(foundFiles));
|
||||
File[] dirs = startDir.listFiles(DIR_FILTER);
|
||||
for (File dir : dirs) {
|
||||
findFiles0(dir, list, filter);
|
||||
}
|
||||
}
|
||||
|
||||
static void close(Closeable c) {
|
||||
if (c == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
c.close();
|
||||
} catch (IOException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
static void compiler(String... javacCmds) {
|
||||
if (com.sun.tools.javac.Main.compile(javacCmds) != 0) {
|
||||
throw new RuntimeException("compilation failed");
|
||||
}
|
||||
}
|
||||
|
||||
static void jar(String... jargs) {
|
||||
sun.tools.jar.Main jarTool =
|
||||
new sun.tools.jar.Main(System.out, System.err, "jartool");
|
||||
if (!jarTool.run(jargs)) {
|
||||
throw new RuntimeException("jar command failed");
|
||||
}
|
||||
}
|
||||
|
||||
// given a jar file foo.jar will write to foo.pack
|
||||
static void pack(JarFile jarFile, File packFile) throws IOException {
|
||||
Pack200.Packer packer = Pack200.newPacker();
|
||||
Map<String, String> p = packer.properties();
|
||||
// Take the time optimization vs. space
|
||||
p.put(packer.EFFORT, "1"); // CAUTION: do not use 0.
|
||||
// Make the memory consumption as effective as possible
|
||||
p.put(packer.SEGMENT_LIMIT, "10000");
|
||||
// ignore all JAR deflation requests to save time
|
||||
p.put(packer.DEFLATE_HINT, packer.FALSE);
|
||||
// save the file ordering of the original JAR
|
||||
p.put(packer.KEEP_FILE_ORDER, packer.TRUE);
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
// Write out to a jtreg scratch area
|
||||
fos = new FileOutputStream(packFile);
|
||||
// Call the packer
|
||||
packer.pack(jarFile, fos);
|
||||
} finally {
|
||||
close(fos);
|
||||
}
|
||||
}
|
||||
|
||||
// uses java unpacker, slow but useful to discover issues with the packer
|
||||
static void unpackj(File inFile, JarOutputStream jarStream)
|
||||
throws IOException {
|
||||
unpack0(inFile, jarStream, true);
|
||||
|
||||
}
|
||||
|
||||
// uses native unpacker using the java APIs
|
||||
static void unpackn(File inFile, JarOutputStream jarStream)
|
||||
throws IOException {
|
||||
unpack0(inFile, jarStream, false);
|
||||
}
|
||||
|
||||
// given a packed file, create the jar file in the current directory.
|
||||
private static void unpack0(File inFile, JarOutputStream jarStream,
|
||||
boolean useJavaUnpack) throws IOException {
|
||||
// Unpack the files
|
||||
Pack200.Unpacker unpacker = Pack200.newUnpacker();
|
||||
Map<String, String> props = unpacker.properties();
|
||||
if (useJavaUnpack) {
|
||||
props.put("com.sun.java.util.jar.pack.disable.native", "true");
|
||||
}
|
||||
// Call the unpacker
|
||||
unpacker.unpack(inFile, jarStream);
|
||||
}
|
||||
|
||||
static byte[] getBuffer(ZipFile zf, ZipEntry ze) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte buf[] = new byte[8192];
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = zf.getInputStream(ze);
|
||||
int n = is.read(buf);
|
||||
while (n > 0) {
|
||||
baos.write(buf, 0, n);
|
||||
n = is.read(buf);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
} finally {
|
||||
close(is);
|
||||
}
|
||||
}
|
||||
|
||||
static ArrayList<String> getZipFileEntryNames(ZipFile z) {
|
||||
ArrayList<String> out = new ArrayList<String>();
|
||||
for (ZipEntry ze : Collections.list(z.entries())) {
|
||||
out.add(ze.getName());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
static List<String> runExec(List<String> cmdsList) {
|
||||
return runExec(cmdsList, null);
|
||||
}
|
||||
static List<String> runExec(List<String> cmdsList, Map<String, String> penv) {
|
||||
ArrayList<String> alist = new ArrayList<String>();
|
||||
ProcessBuilder pb =
|
||||
new ProcessBuilder(cmdsList);
|
||||
Map<String, String> env = pb.environment();
|
||||
if (penv != null && !penv.isEmpty()) {
|
||||
env.putAll(penv);
|
||||
}
|
||||
pb.directory(new File("."));
|
||||
dirlist(new File("."));
|
||||
for (String x : cmdsList) {
|
||||
System.out.print(x + " ");
|
||||
}
|
||||
System.out.println("");
|
||||
int retval = 0;
|
||||
Process p = null;
|
||||
InputStreamReader ir = null;
|
||||
BufferedReader rd = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
pb.redirectErrorStream(true);
|
||||
p = pb.start();
|
||||
is = p.getInputStream();
|
||||
ir = new InputStreamReader(is);
|
||||
rd = new BufferedReader(ir, 8192);
|
||||
|
||||
String in = rd.readLine();
|
||||
while (in != null) {
|
||||
alist.add(in);
|
||||
System.out.println(in);
|
||||
in = rd.readLine();
|
||||
}
|
||||
retval = p.waitFor();
|
||||
if (retval != 0) {
|
||||
throw new RuntimeException("process failed with non-zero exit");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
} finally {
|
||||
close(rd);
|
||||
close(ir);
|
||||
close(is);
|
||||
if (p != null) {
|
||||
p.destroy();
|
||||
}
|
||||
}
|
||||
return alist;
|
||||
}
|
||||
|
||||
static String getUnpack200Cmd() {
|
||||
return getAjavaCmd("unpack200");
|
||||
}
|
||||
|
||||
static String getPack200Cmd() {
|
||||
return getAjavaCmd("pack200");
|
||||
}
|
||||
|
||||
static String getJavaCmd() {
|
||||
return getAjavaCmd("java");
|
||||
}
|
||||
|
||||
static String getAjavaCmd(String cmdStr) {
|
||||
File binDir = new File(JavaHome, "bin");
|
||||
File unpack200File = IsWindows
|
||||
? new File(binDir, cmdStr + ".exe")
|
||||
: new File(binDir, cmdStr);
|
||||
|
||||
String cmd = unpack200File.getAbsolutePath();
|
||||
if (!unpack200File.canExecute()) {
|
||||
throw new RuntimeException("please check" +
|
||||
cmd + " exists and is executable");
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
private static List<File> locaterCache = null;
|
||||
// search the source dir and jdk dir for requested file and returns
|
||||
// the first location it finds.
|
||||
static File locateJar(String name) {
|
||||
try {
|
||||
if (locaterCache == null) {
|
||||
locaterCache = new ArrayList<File>();
|
||||
locaterCache.addAll(findFiles(TEST_SRC_DIR, createFilter(JAR_FILE_EXT)));
|
||||
locaterCache.addAll(findFiles(JavaSDK, createFilter(JAR_FILE_EXT)));
|
||||
}
|
||||
for (File f : locaterCache) {
|
||||
if (f.getName().equals(name)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
throw new IOException("file not found: " + name);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
45
jdk/test/tools/pack200/pack200-verifier/data/README
Normal file
45
jdk/test/tools/pack200/pack200-verifier/data/README
Normal file
@ -0,0 +1,45 @@
|
||||
The files contained in the golden.jar have been harvested from many
|
||||
different sources, some are hand-crafted invalid class files (odds directory),
|
||||
or from random JDK builds.
|
||||
|
||||
Generally these files serve to ensure the integrity of the packer and unpacker
|
||||
by,
|
||||
1. maximizing the test coverage.
|
||||
2. exercising all the Bands in the pack200 specification.
|
||||
2. testing the behavior of the packer with invalid classes.
|
||||
3. testing the archive integrity, ordering and description (date, sizes,
|
||||
CRC etc.)
|
||||
|
||||
Build:
|
||||
To rebuild this JAR follow these steps:
|
||||
1. unzip the golden.jar to some directory lets call it "example"
|
||||
2. now we can add any directories with files into example.
|
||||
2. run the script BUILDME.sh as
|
||||
% sh BUILDME.sh example
|
||||
|
||||
Note: the BUILDME.sh is known to work on all Unix platforms as well as Windows
|
||||
using Cygwin.
|
||||
|
||||
The above will create two JAR files in the current directory,
|
||||
example.jar and example-cls.jar, now the example.jar can be used as the
|
||||
golden.jar.
|
||||
|
||||
To ensure the JAR has been built correctly use jar -tvf and compare the
|
||||
results of the old jar and the newly built one, note that the compressed sizes
|
||||
may differ, however the timestamps etc. should be consistent.
|
||||
|
||||
Test:
|
||||
Basic:
|
||||
% pack200 --repack test.jar golden.jar
|
||||
|
||||
Advanced:
|
||||
Create a pack.conf as follows:
|
||||
% cat pack.conf
|
||||
com.sun.java.util.jar.pack.dump.bands=true
|
||||
|
||||
% pack200 --no-gzip --config-file=pack.conf \
|
||||
--verbose golden.jar.pack golden.jar
|
||||
|
||||
This command will dump the Bands in a unique directory BD_XXXXXX,
|
||||
one can inspect the directory to ensure all of the bands are being
|
||||
generated. Familiarity of the Pack200 specification is suggested.
|
BIN
jdk/test/tools/pack200/pack200-verifier/data/golden.jar
Normal file
BIN
jdk/test/tools/pack200/pack200-verifier/data/golden.jar
Normal file
Binary file not shown.
59
jdk/test/tools/pack200/pack200-verifier/make/build.xml
Normal file
59
jdk/test/tools/pack200/pack200-verifier/make/build.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<project name="PackageVerify" default="dist" basedir="..">
|
||||
<!-- Requires ant 1.6.1+ and JDK 1.6+-->
|
||||
|
||||
<!-- set global properties for this build -->
|
||||
<property name="src" value="${basedir}/src"/>
|
||||
<property name="build" value="${basedir}/build"/>
|
||||
<property name="dist" value="${basedir}/dist"/>
|
||||
<property name="make" value="${basedir}/make"/>
|
||||
<property name="classes" value="${build}/classes"/>
|
||||
<property name="api" value="${build}/api"/>
|
||||
|
||||
<target name="init">
|
||||
<!-- Create the time stamp -->
|
||||
<tstamp/>
|
||||
<!-- Create the build directory structure used by compile -->
|
||||
<mkdir dir="${build}"/>
|
||||
<mkdir dir="${dist}"/>
|
||||
<mkdir dir="${classes}"/>
|
||||
<mkdir dir="${api}"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="init">
|
||||
<!-- Compile the java code from ${src} into ${build} -->
|
||||
<javac
|
||||
source="1.6"
|
||||
srcdir="${src}"
|
||||
destdir="${build}/classes"
|
||||
verbose="no"
|
||||
debug="on"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<target name="doc" depends="init, compile">
|
||||
<javadoc
|
||||
source="1.6"
|
||||
sourcepath="${src}"
|
||||
destdir="${api}"
|
||||
/>
|
||||
</target>
|
||||
<target name="dist" depends="compile, doc">
|
||||
<!-- Put everything in jar file -->
|
||||
<jar destfile="${dist}/pack200-verifier.jar">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="sun.tools.pack.verify.Main"/>
|
||||
</manifest>
|
||||
<fileset dir="${classes}"/>
|
||||
</jar>
|
||||
<zip destfile="dist/pack200-verifier-doc.zip">
|
||||
<fileset dir="${api}"/>
|
||||
</zip>
|
||||
</target>
|
||||
|
||||
<target name="clean">
|
||||
<!-- Delete the ${build} and ${dist} directory trees -->
|
||||
<delete dir="${build}"/>
|
||||
<delete dir="${dist}"/>
|
||||
</target>
|
||||
|
||||
</project>
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.tools.pack.verify;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
import xmlkit.*;
|
||||
|
||||
public class ClassCompare {
|
||||
|
||||
/*
|
||||
* @author ksrini
|
||||
*/
|
||||
private static XMLKit.Element getXMLelement(InputStream is,
|
||||
boolean ignoreUnkAttrs,
|
||||
List<String> ignoreElements) throws IOException {
|
||||
|
||||
ClassReader cr = new ClassReader();
|
||||
cr.keepOrder = false;
|
||||
XMLKit.Element e = cr.readFrom(is);
|
||||
|
||||
if (ignoreElements != null) {
|
||||
XMLKit.Filter filter = XMLKit.elementFilter(ignoreElements);
|
||||
e.removeAllInTree(filter);
|
||||
}
|
||||
|
||||
if (ignoreUnkAttrs == true) {
|
||||
// This removes any unknown attributes
|
||||
e.removeAllInTree(XMLKit.elementFilter("Attribute"));
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static String getXMLPrettyString(XMLKit.Element e) throws IOException {
|
||||
StringWriter out = new StringWriter();
|
||||
e.writePrettyTo(out);
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
private static boolean compareClass0(JarFile jf1, JarFile jf2,
|
||||
JarEntry je, boolean ignoreUnkAttrs,
|
||||
List<String> ignoreElements)
|
||||
throws IOException {
|
||||
|
||||
InputStream is1 = jf1.getInputStream(je);
|
||||
InputStream is2 = jf2.getInputStream(je);
|
||||
|
||||
// First we try to compare the bits if they are the same
|
||||
boolean bCompare = JarFileCompare.compareStreams(is1, is2);
|
||||
|
||||
// If they are the same there is nothing more to do.
|
||||
if (bCompare) {
|
||||
Globals.println("+++" + je.getName() + "+++\t"
|
||||
+ "b/b:PASS");
|
||||
return bCompare;
|
||||
}
|
||||
is1.close();
|
||||
is2.close();
|
||||
|
||||
is1 = jf1.getInputStream(je);
|
||||
is2 = jf2.getInputStream(je);
|
||||
|
||||
|
||||
XMLKit.Element e1 = getXMLelement(is1, ignoreUnkAttrs, ignoreElements);
|
||||
XMLKit.Element e2 = getXMLelement(is2, ignoreUnkAttrs, ignoreElements);
|
||||
|
||||
Globals.print("+++" + je.getName() + "+++\t"
|
||||
+ e1.size() + "/" + e1.size() + ":");
|
||||
|
||||
boolean result = true;
|
||||
|
||||
if (e1.equals(e2)) {
|
||||
Globals.println("PASS");
|
||||
} else {
|
||||
Globals.println("FAIL");
|
||||
Globals.log("Strings differs");
|
||||
Globals.log(getXMLPrettyString(e1));
|
||||
Globals.log("----------");
|
||||
Globals.log(getXMLPrettyString(e2));
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given two Class Paths could be jars the first being a reference
|
||||
* will execute a series of comparisons on the classname specified
|
||||
* The className could be null in which case it will iterate through
|
||||
* all the classes, otherwise it will compare one class and exit.
|
||||
*/
|
||||
public static boolean compareClass(String jar1, String jar2,
|
||||
String className, boolean ignoreUnkAttrs,
|
||||
List<String> ignoreElements)
|
||||
throws IOException {
|
||||
|
||||
Globals.println("Unknown attributes ignored:" + ignoreUnkAttrs);
|
||||
if (ignoreElements != null) {
|
||||
Globals.println(ignoreElements.toString());
|
||||
}
|
||||
|
||||
JarFile jf1 = new JarFile(jar1);
|
||||
JarFile jf2 = new JarFile(jar2);
|
||||
|
||||
boolean result = true;
|
||||
|
||||
if (className == null) {
|
||||
for (JarEntry je1 : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
|
||||
if (je1.getName().endsWith(".class")) {
|
||||
JarEntry je2 = jf2.getJarEntry(je1.getName());
|
||||
boolean pf = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
|
||||
if (result == true) {
|
||||
result = pf;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JarEntry je1 = jf1.getJarEntry(className);
|
||||
result = compareClass0(jf1, jf2, je1, ignoreUnkAttrs, ignoreElements);
|
||||
}
|
||||
if (result == false) {
|
||||
throw new RuntimeException("Class structural comparison failure");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static boolean compareClass(String jar1, String jar2,
|
||||
String className) throws IOException {
|
||||
|
||||
Stack<String> s = new Stack();
|
||||
if (Globals.ignoreDebugAttributes()) {
|
||||
s = new Stack();
|
||||
s.push("LocalVariable");
|
||||
s.push("LocalVariableType");
|
||||
s.push("LineNumber");
|
||||
s.push("SourceFile");
|
||||
}
|
||||
return compareClass(jar1, jar2, className, Globals.ignoreUnknownAttributes(), s);
|
||||
}
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* A collection of useful global utilities commonly used.
|
||||
*/
|
||||
package sun.tools.pack.verify;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
/*
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
class Globals {
|
||||
|
||||
private static int errors = 0;
|
||||
private static PrintWriter _pw = null;
|
||||
private static String _logFileName = null;
|
||||
private static final String DEFAULT_LOG_FILE = "verifier.log";
|
||||
private static boolean _verbose = true;
|
||||
private static boolean _ignoreJarDirectories = false;
|
||||
private static boolean _checkJarClassOrdering = true;
|
||||
private static boolean _bitWiseClassCompare = false;
|
||||
// Ignore Deprecated, SourceFile and Synthetic
|
||||
private static boolean _ignoreCompileAttributes = false;
|
||||
// Ignore Debug Attributes LocalVariableTable, LocalVariableType,LineNumberTable
|
||||
private static boolean _ignoreDebugAttributes = false;
|
||||
private static boolean _ignoreUnknownAttributes = false;
|
||||
private static boolean _validateClass = true;
|
||||
private static Globals _instance = null;
|
||||
|
||||
static Globals getInstance() {
|
||||
if (_instance == null) {
|
||||
_instance = new Globals();
|
||||
_verbose = (System.getProperty("sun.tools.pack.verify.verbose") == null)
|
||||
? false : true;
|
||||
_ignoreJarDirectories = (System.getProperty("ignoreJarDirectories") == null)
|
||||
? false : true;
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
static boolean ignoreCompileAttributes() {
|
||||
return _ignoreCompileAttributes;
|
||||
}
|
||||
|
||||
static boolean ignoreDebugAttributes() {
|
||||
return _ignoreDebugAttributes;
|
||||
}
|
||||
|
||||
static boolean ignoreUnknownAttributes() {
|
||||
return _ignoreUnknownAttributes;
|
||||
}
|
||||
|
||||
static boolean ignoreJarDirectories() {
|
||||
return _ignoreJarDirectories;
|
||||
}
|
||||
|
||||
static boolean validateClass() {
|
||||
return _validateClass;
|
||||
}
|
||||
|
||||
static void setCheckJarClassOrdering(boolean flag) {
|
||||
_checkJarClassOrdering = flag;
|
||||
}
|
||||
|
||||
static boolean checkJarClassOrdering() {
|
||||
return _checkJarClassOrdering;
|
||||
}
|
||||
|
||||
static boolean bitWiseClassCompare() {
|
||||
return _bitWiseClassCompare;
|
||||
}
|
||||
|
||||
static boolean setBitWiseClassCompare(boolean flag) {
|
||||
return _bitWiseClassCompare = flag;
|
||||
}
|
||||
|
||||
public static boolean setIgnoreCompileAttributes(boolean flag) {
|
||||
return _ignoreCompileAttributes = flag;
|
||||
}
|
||||
|
||||
static boolean setIgnoreDebugAttributes(boolean flag) {
|
||||
return _ignoreDebugAttributes = flag;
|
||||
}
|
||||
|
||||
static boolean setIgnoreUnknownAttributes(boolean flag) {
|
||||
return _ignoreUnknownAttributes = flag;
|
||||
}
|
||||
|
||||
static boolean setValidateClass(boolean flag) {
|
||||
return _validateClass = flag;
|
||||
}
|
||||
|
||||
static int getErrors() {
|
||||
return errors;
|
||||
}
|
||||
|
||||
static void trace(String s) {
|
||||
if (_verbose) {
|
||||
println(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void print(String s) {
|
||||
_pw.print(s);
|
||||
}
|
||||
|
||||
static void println(String s) {
|
||||
_pw.println(s);
|
||||
}
|
||||
|
||||
static void log(String s) {
|
||||
errors++;
|
||||
_pw.println("ERROR:" + s);
|
||||
}
|
||||
|
||||
static void lognoln(String s) {
|
||||
errors++;
|
||||
_pw.print(s);
|
||||
}
|
||||
|
||||
private static PrintWriter openFile(String fileName) {
|
||||
//Lets create the directory if it does not exist.
|
||||
File f = new File(fileName);
|
||||
File baseDir = f.getParentFile();
|
||||
if (baseDir != null && baseDir.exists() == false) {
|
||||
baseDir.mkdirs();
|
||||
}
|
||||
try {
|
||||
return new PrintWriter(new FileWriter(f), true);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static void closeFile() {
|
||||
_pw.flush();
|
||||
_pw.close();
|
||||
}
|
||||
|
||||
static void printPropsToLog() {
|
||||
println("Log started " + new Date(System.currentTimeMillis()));
|
||||
print(System.getProperty("java.vm.version"));
|
||||
println("\t" + System.getProperty("java.vm.name"));
|
||||
|
||||
println("System properties");
|
||||
println("\tjava.home=" + System.getProperty("java.home"));
|
||||
println("\tjava.class.version=" + System.getProperty("java.class.version"));
|
||||
println("\tjava.class.path=" + System.getProperty("java.class.path"));
|
||||
println("\tjava.ext.dirs=" + System.getProperty("java.ext.dirs"));
|
||||
println("\tos.name=" + System.getProperty("os.name"));
|
||||
println("\tos.arch=" + System.getProperty("os.arch"));
|
||||
println("\tos.version=" + System.getProperty("os.version"));
|
||||
println("\tuser.name=" + System.getProperty("user.name"));
|
||||
println("\tuser.home=" + System.getProperty("user.home"));
|
||||
println("\tuser.dir=" + System.getProperty("user.dir"));
|
||||
println("\tLocale.getDefault=" + Locale.getDefault());
|
||||
println("System properties end");
|
||||
}
|
||||
|
||||
static void openLog(String s) {
|
||||
_logFileName = (s != null) ? s : "." + File.separator + DEFAULT_LOG_FILE;
|
||||
_logFileName = (new File(_logFileName).isDirectory())
|
||||
? _logFileName + File.separator + DEFAULT_LOG_FILE : _logFileName;
|
||||
_pw = openFile(_logFileName);
|
||||
printPropsToLog();
|
||||
}
|
||||
|
||||
static void closeLog() {
|
||||
closeFile();
|
||||
}
|
||||
|
||||
static String getLogFileName() {
|
||||
return _logFileName;
|
||||
}
|
||||
|
||||
static void diffCharData(String s1, String s2) {
|
||||
boolean diff = false;
|
||||
char[] c1 = s1.toCharArray();
|
||||
char[] c2 = s2.toCharArray();
|
||||
if (c1.length != c2.length) {
|
||||
diff = true;
|
||||
Globals.log("Length differs: " + (c1.length - c2.length));
|
||||
}
|
||||
// Take the smaller of the two arrays to prevent Array...Exception
|
||||
int minlen = (c1.length < c2.length) ? c1.length : c2.length;
|
||||
for (int i = 0; i < c1.length; i++) {
|
||||
if (c1[i] != c2[i]) {
|
||||
diff = true;
|
||||
Globals.lognoln("\t idx[" + i + "] 0x" + Integer.toHexString(c1[i]) + "<>" + "0x" + Integer.toHexString(c2[i]));
|
||||
Globals.log(" -> " + c1[i] + "<>" + c2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void diffByteData(String s1, String s2) {
|
||||
boolean diff = false;
|
||||
byte[] b1 = s1.getBytes();
|
||||
byte[] b2 = s2.getBytes();
|
||||
|
||||
if (b1.length != b2.length) {
|
||||
diff = true;
|
||||
//(+) b1 is greater, (-) b2 is greater
|
||||
Globals.log("Length differs diff: " + (b1.length - b2.length));
|
||||
}
|
||||
// Take the smaller of the two array to prevent Array...Exception
|
||||
int minlen = (b1.length < b2.length) ? b1.length : b2.length;
|
||||
for (int i = 0; i < b1.length; i++) {
|
||||
if (b1[i] != b2[i]) {
|
||||
diff = true;
|
||||
Globals.log("\t" + "idx[" + i + "] 0x" + Integer.toHexString(b1[i]) + "<>" + "0x" + Integer.toHexString(b2[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dumpToHex(String s) {
|
||||
try {
|
||||
dumpToHex(s.getBytes("UTF-8"));
|
||||
} catch (UnsupportedEncodingException uce) {
|
||||
throw new RuntimeException(uce);
|
||||
}
|
||||
}
|
||||
|
||||
static void dumpToHex(byte[] buffer) {
|
||||
int linecount = 0;
|
||||
byte[] b = new byte[16];
|
||||
for (int i = 0; i < buffer.length; i += 16) {
|
||||
if (buffer.length - i > 16) {
|
||||
System.arraycopy(buffer, i, b, 0, 16);
|
||||
print16Bytes(b, linecount);
|
||||
linecount += 16;
|
||||
} else {
|
||||
System.arraycopy(buffer, i, b, 0, buffer.length - i);
|
||||
for (int n = buffer.length - (i + 1); n < 16; n++) {
|
||||
b[n] = 0;
|
||||
}
|
||||
print16Bytes(b, linecount);
|
||||
linecount += 16;
|
||||
}
|
||||
}
|
||||
Globals.log("-----------------------------------------------------------------");
|
||||
}
|
||||
|
||||
static void print16Bytes(byte[] buffer, int linecount) {
|
||||
final int MAX = 4;
|
||||
Globals.lognoln(paddedHexString(linecount, 4) + " ");
|
||||
|
||||
for (int i = 0; i < buffer.length; i += 2) {
|
||||
int iOut = pack2Bytes2Int(buffer[i], buffer[i + 1]);
|
||||
Globals.lognoln(paddedHexString(iOut, 4) + " ");
|
||||
}
|
||||
|
||||
Globals.lognoln("| ");
|
||||
|
||||
StringBuilder sb = new StringBuilder(new String(buffer));
|
||||
|
||||
for (int i = 0; i < buffer.length; i++) {
|
||||
if (Character.isISOControl(sb.charAt(i))) {
|
||||
sb.setCharAt(i, '.');
|
||||
}
|
||||
}
|
||||
Globals.log(sb.toString());
|
||||
}
|
||||
|
||||
static int pack2Bytes2Int(byte b1, byte b2) {
|
||||
int out = 0x0;
|
||||
out += b1;
|
||||
out <<= 8;
|
||||
out &= 0x0000ffff;
|
||||
out |= 0x000000ff & b2;
|
||||
return out;
|
||||
}
|
||||
|
||||
static String paddedHexString(int n, int max) {
|
||||
char[] c = Integer.toHexString(n).toCharArray();
|
||||
char[] out = new char[max];
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
out[i] = '0';
|
||||
}
|
||||
int offset = (max - c.length < 0) ? 0 : max - c.length;
|
||||
for (int i = 0; i < c.length; i++) {
|
||||
out[offset + i] = c[i];
|
||||
}
|
||||
return new String(out);
|
||||
}
|
||||
}
|
@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.tools.pack.verify;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.jar.*;
|
||||
|
||||
class JarFileCompare {
|
||||
/*
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
private static VerifyTreeSet getVerifyTreeSet(String jarPath) {
|
||||
VerifyTreeSet vts = new VerifyTreeSet();
|
||||
try {
|
||||
JarFile j = new JarFile(jarPath);
|
||||
for (JarEntry je : Collections.list((Enumeration<JarEntry>) j.entries())) {
|
||||
if (!je.isDirectory()) { // totally ignore directories
|
||||
vts.add(je.getName());
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
return vts;
|
||||
}
|
||||
|
||||
private static LinkedList getListOfClasses(String jarPath) {
|
||||
LinkedList l = new LinkedList();
|
||||
try {
|
||||
JarFile j = new JarFile(jarPath);
|
||||
for (JarEntry je : Collections.list((Enumeration<JarEntry>) j.entries())) {
|
||||
if (!je.isDirectory() && je.getName().endsWith(".class")) {
|
||||
l.add(je.getName());
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
private static void jarDirectoryCompare(String jarPath1, String jarPath2) {
|
||||
VerifyTreeSet vts1 = getVerifyTreeSet(jarPath1);
|
||||
VerifyTreeSet vts2 = getVerifyTreeSet(jarPath2);
|
||||
|
||||
TreeSet diff1 = vts1.diff(vts2);
|
||||
if (diff1.size() > 0) {
|
||||
Globals.log("Left has the following entries that right does not have");
|
||||
Globals.log(diff1.toString());
|
||||
}
|
||||
TreeSet diff2 = vts2.diff(vts1);
|
||||
if (diff2.size() > 0) {
|
||||
Globals.log("Right has the following entries that left does not have");
|
||||
Globals.log(diff2.toString());
|
||||
}
|
||||
if (Globals.checkJarClassOrdering()) {
|
||||
boolean error = false;
|
||||
Globals.println("Checking Class Ordering");
|
||||
LinkedList l1 = getListOfClasses(jarPath1);
|
||||
LinkedList l2 = getListOfClasses(jarPath2);
|
||||
if (l1.size() != l2.size()) {
|
||||
error = true;
|
||||
Globals.log("The number of classes differs");
|
||||
Globals.log("\t" + l1.size() + "<>" + l2.size());
|
||||
}
|
||||
for (int i = 0; i < l1.size(); i++) {
|
||||
String s1 = (String) l1.get(i);
|
||||
String s2 = (String) l2.get(i);
|
||||
if (s1.compareTo(s2) != 0) {
|
||||
error = true;
|
||||
Globals.log("Ordering differs at[" + i + "] = " + s1);
|
||||
Globals.log("\t" + s2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the two Streams are bit identical, and false if they
|
||||
* are not, no further diagnostics
|
||||
*/
|
||||
static boolean compareStreams(InputStream is1, InputStream is2) {
|
||||
|
||||
BufferedInputStream bis1 = new BufferedInputStream(is1, 8192);
|
||||
BufferedInputStream bis2 = new BufferedInputStream(is2, 8192);
|
||||
try {
|
||||
int i1, i2;
|
||||
int count = 0;
|
||||
while ((i1 = bis1.read()) == (i2 = bis2.read())) {
|
||||
count++;
|
||||
if (i1 < 0) {
|
||||
// System.out.println("bytes read " + count);
|
||||
return true; // got all the way to EOF
|
||||
}
|
||||
}
|
||||
return false; // reads returned dif
|
||||
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkEntry(JarFile jf1, JarFile jf2, JarEntry je) throws IOException {
|
||||
InputStream is1 = jf1.getInputStream(je);
|
||||
InputStream is2 = jf2.getInputStream(je);
|
||||
if (is1 != null && is2 != null) {
|
||||
if (!compareStreams(jf1.getInputStream(je), jf2.getInputStream(je))) {
|
||||
Globals.println("+++" + je.getName() + "+++");
|
||||
Globals.log("Error: File:" + je.getName()
|
||||
+ " differs, use a diff util for further diagnostics");
|
||||
}
|
||||
} else {
|
||||
Globals.println("+++" + je.getName() + "+++");
|
||||
Globals.log("Error: File:" + je.getName() + " not found in " + jf2.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Given two jar files we compare and see if the jarfiles have all the
|
||||
* entries. The property ignoreJarDirectories is set to true by default
|
||||
* which means that Directory entries in a jar may be ignore.
|
||||
*/
|
||||
static void jarCompare(String jarPath1, String jarPath2) {
|
||||
jarDirectoryCompare(jarPath1, jarPath2);
|
||||
|
||||
try {
|
||||
JarFile jf1 = new JarFile(jarPath1);
|
||||
JarFile jf2 = new JarFile(jarPath2);
|
||||
|
||||
int nclasses = 0;
|
||||
int nentries = 0;
|
||||
int entries_checked = 0;
|
||||
int classes_checked = 0;
|
||||
|
||||
for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
|
||||
if (!je.isDirectory() && !je.getName().endsWith(".class")) {
|
||||
nentries++;
|
||||
} else if (je.getName().endsWith(".class")) {
|
||||
nclasses++;
|
||||
}
|
||||
}
|
||||
|
||||
for (JarEntry je : Collections.list((Enumeration<JarEntry>) jf1.entries())) {
|
||||
if (je.isDirectory()) {
|
||||
continue; // Ignore directories
|
||||
}
|
||||
if (!je.getName().endsWith(".class")) {
|
||||
entries_checked++;
|
||||
if (je.getName().compareTo("META-INF/MANIFEST.MF") == 0) {
|
||||
Manifest mf1 = new Manifest(jf1.getInputStream(je));
|
||||
Manifest mf2 = new Manifest(jf2.getInputStream(je));
|
||||
if (!mf1.equals(mf2)) {
|
||||
Globals.log("Error: Manifests differ");
|
||||
Globals.log("Manifest1");
|
||||
Globals.log(mf1.getMainAttributes().entrySet().toString());
|
||||
Globals.log("Manifest2");
|
||||
Globals.log(mf2.getMainAttributes().entrySet().toString());
|
||||
}
|
||||
} else {
|
||||
checkEntry(jf1, jf2, je);
|
||||
}
|
||||
} else if (Globals.bitWiseClassCompare() == true) {
|
||||
checkEntry(jf1, jf2, je);
|
||||
classes_checked++;
|
||||
}
|
||||
}
|
||||
if (Globals.bitWiseClassCompare()) {
|
||||
Globals.println("Class entries checked (byte wise)/Total Class entries = "
|
||||
+ classes_checked + "/" + nclasses);
|
||||
}
|
||||
Globals.println("Non-class entries checked/Total non-class entries = "
|
||||
+ entries_checked + "/" + nentries);
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
// The Main Entry point
|
||||
package sun.tools.pack.verify;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* This class provides a convenient entry point to the pack200 verifier. This
|
||||
* compares two classes, either in path or in an archive.
|
||||
* @see xmlkit.XMLKit
|
||||
* @author ksrini
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
private static void syntax() {
|
||||
System.out.println("Usage: ");
|
||||
System.out.println("\tREFERENCE_CLASSPATH COMPARED_CLASSPATH [Options]");
|
||||
System.out.println("\tOptions:");
|
||||
System.out.println("\t\t-O check jar ordering");
|
||||
System.out.println("\t\t-C ignore compile attributes (Deprecated, SourceFile, Synthetic, )");
|
||||
System.out.println("\t\t-D ignore debug attributes (LocalVariable, LineNumber)");
|
||||
System.out.println("\t\t-u ignore unknown attributes");
|
||||
System.out.println("\t\t-V turn off class validation");
|
||||
System.out.println("\t\t-c CLASS, compare CLASS only");
|
||||
System.out.println("\t\t-b Compares all entries bitwise only");
|
||||
System.out.println("\t\t-l Directory or Log File Name");
|
||||
}
|
||||
|
||||
/**
|
||||
* main entry point to the class file comparator, which compares semantically
|
||||
* class files in a classpath or an archive.
|
||||
* @param args String array as described below
|
||||
* @throws RuntimeException
|
||||
* <pre>
|
||||
* Usage:
|
||||
* ReferenceClasspath SpecimenClaspath [Options]
|
||||
* Options:
|
||||
* -O check jar ordering
|
||||
* -C do not compare compile attributes (Deprecated, SourceFile, Synthetic)
|
||||
* -D do not compare debug attribute (LocalVariableTable, LineNumberTable)
|
||||
* -u ignore unknown attributes
|
||||
* -V turn off class validation
|
||||
* -c class, compare a single class
|
||||
* -b compares all entries bitwise (fastest)
|
||||
* -l directory or log file name
|
||||
* </pre>
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
Globals.getInstance();
|
||||
if (args == null || args.length < 2) {
|
||||
syntax();
|
||||
System.exit(1);
|
||||
}
|
||||
String refJarFileName = null;
|
||||
String cmpJarFileName = null;
|
||||
String specificClass = null;
|
||||
String logDirFileName = null;
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (i == 0) {
|
||||
refJarFileName = args[0];
|
||||
continue;
|
||||
}
|
||||
if (i == 1) {
|
||||
cmpJarFileName = args[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-O")) {
|
||||
Globals.setCheckJarClassOrdering(true);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-b")) {
|
||||
Globals.setBitWiseClassCompare(true);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-C")) {
|
||||
Globals.setIgnoreCompileAttributes(true);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-D")) {
|
||||
Globals.setIgnoreDebugAttributes(true);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-V")) {
|
||||
Globals.setValidateClass(false);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-c")) {
|
||||
i++;
|
||||
specificClass = args[i].trim();
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-u")) {
|
||||
i++;
|
||||
Globals.setIgnoreUnknownAttributes(true);
|
||||
}
|
||||
|
||||
if (args[i].startsWith("-l")) {
|
||||
i++;
|
||||
logDirFileName = args[i].trim();
|
||||
}
|
||||
}
|
||||
|
||||
Globals.openLog(logDirFileName);
|
||||
|
||||
File refJarFile = new File(refJarFileName);
|
||||
File cmpJarFile = new File(cmpJarFileName);
|
||||
|
||||
String f1 = refJarFile.getAbsoluteFile().toString();
|
||||
String f2 = cmpJarFile.getAbsoluteFile().toString();
|
||||
|
||||
System.out.println("LogFile:" + Globals.getLogFileName());
|
||||
System.out.println("Reference JAR:" + f1);
|
||||
System.out.println("Compared JAR:" + f2);
|
||||
|
||||
Globals.println("LogFile:" + Globals.getLogFileName());
|
||||
Globals.println("Reference JAR:" + f1);
|
||||
Globals.println("Compared JAR:" + f2);
|
||||
|
||||
Globals.println("Ignore Compile Attributes:" + Globals.ignoreCompileAttributes());
|
||||
Globals.println("Ignore Debug Attributes:" + Globals.ignoreDebugAttributes());
|
||||
Globals.println("Ignore Unknown Attributes:" + Globals.ignoreUnknownAttributes());
|
||||
Globals.println("Class ordering check:" + Globals.checkJarClassOrdering());
|
||||
Globals.println("Class validation check:" + Globals.validateClass());
|
||||
Globals.println("Bit-wise compare:" + Globals.bitWiseClassCompare());
|
||||
Globals.println("ClassName:" + ((specificClass == null) ? "ALL" : specificClass));
|
||||
|
||||
if (specificClass == null && Globals.bitWiseClassCompare() == true) {
|
||||
JarFileCompare.jarCompare(refJarFileName, cmpJarFileName);
|
||||
} else {
|
||||
try {
|
||||
ClassCompare.compareClass(refJarFileName, cmpJarFileName, specificClass);
|
||||
} catch (Exception e) {
|
||||
Globals.log("Exception " + e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (Globals.getErrors() > 0) {
|
||||
System.out.println("FAIL");
|
||||
Globals.println("FAIL");
|
||||
System.exit(Globals.getErrors());
|
||||
}
|
||||
|
||||
System.out.println("PASS");
|
||||
Globals.println("PASS");
|
||||
System.exit(Globals.getErrors());
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.tools.pack.verify;
|
||||
|
||||
import java.util.*;
|
||||
/*
|
||||
* @author ksrini
|
||||
*/
|
||||
|
||||
class VerifyTreeSet<K> extends java.util.TreeSet {
|
||||
|
||||
VerifyTreeSet() {
|
||||
super();
|
||||
}
|
||||
|
||||
public VerifyTreeSet(Comparator c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public TreeSet<K> diff(TreeSet in) {
|
||||
TreeSet<K> delta = (TreeSet<K>) this.clone();
|
||||
delta.removeAll(in);
|
||||
return delta;
|
||||
}
|
||||
}
|
1003
jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
Normal file
1003
jdk/test/tools/pack200/pack200-verifier/src/xmlkit/ClassReader.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,518 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
import xmlkit.XMLKit.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.nio.ByteBuffer;
|
||||
import xmlkit.XMLKit.Element;
|
||||
/*
|
||||
* @author jrose
|
||||
*/
|
||||
public abstract class ClassSyntax {
|
||||
|
||||
public interface GetCPIndex {
|
||||
|
||||
int getCPIndex(int tag, String name); // cp finder
|
||||
}
|
||||
public static final int CONSTANT_Utf8 = 1,
|
||||
CONSTANT_Integer = 3,
|
||||
CONSTANT_Float = 4,
|
||||
CONSTANT_Long = 5,
|
||||
CONSTANT_Double = 6,
|
||||
CONSTANT_Class = 7,
|
||||
CONSTANT_String = 8,
|
||||
CONSTANT_Fieldref = 9,
|
||||
CONSTANT_Methodref = 10,
|
||||
CONSTANT_InterfaceMethodref = 11,
|
||||
CONSTANT_NameAndType = 12;
|
||||
private static final String[] cpTagName = {
|
||||
/* 0: */null,
|
||||
/* 1: */ "Utf8",
|
||||
/* 2: */ null,
|
||||
/* 3: */ "Integer",
|
||||
/* 4: */ "Float",
|
||||
/* 5: */ "Long",
|
||||
/* 6: */ "Double",
|
||||
/* 7: */ "Class",
|
||||
/* 8: */ "String",
|
||||
/* 9: */ "Fieldref",
|
||||
/* 10: */ "Methodref",
|
||||
/* 11: */ "InterfaceMethodref",
|
||||
/* 12: */ "NameAndType",
|
||||
null
|
||||
};
|
||||
private static final Set<String> cpTagNames;
|
||||
|
||||
static {
|
||||
Set<String> set = new HashSet<String>(Arrays.asList(cpTagName));
|
||||
set.remove(null);
|
||||
cpTagNames = Collections.unmodifiableSet(set);
|
||||
}
|
||||
public static final int ITEM_Top = 0, // replicates by [1..4,1..4]
|
||||
ITEM_Integer = 1, // (ditto)
|
||||
ITEM_Float = 2,
|
||||
ITEM_Double = 3,
|
||||
ITEM_Long = 4,
|
||||
ITEM_Null = 5,
|
||||
ITEM_UninitializedThis = 6,
|
||||
ITEM_Object = 7,
|
||||
ITEM_Uninitialized = 8,
|
||||
ITEM_ReturnAddress = 9,
|
||||
ITEM_LIMIT = 10;
|
||||
private static final String[] itemTagName = {
|
||||
"Top",
|
||||
"Integer",
|
||||
"Float",
|
||||
"Double",
|
||||
"Long",
|
||||
"Null",
|
||||
"UninitializedThis",
|
||||
"Object",
|
||||
"Uninitialized",
|
||||
"ReturnAddress",};
|
||||
private static final Set<String> itemTagNames;
|
||||
|
||||
static {
|
||||
Set<String> set = new HashSet<String>(Arrays.asList(itemTagName));
|
||||
set.remove(null);
|
||||
itemTagNames = Collections.unmodifiableSet(set);
|
||||
}
|
||||
protected static final HashMap<String, String> attrTypesBacking;
|
||||
protected static final Map<String, String> attrTypesInit;
|
||||
|
||||
static {
|
||||
HashMap<String, String> at = new HashMap<String, String>();
|
||||
|
||||
//at.put("*.Deprecated", "<deprecated=true>");
|
||||
//at.put("*.Synthetic", "<synthetic=true>");
|
||||
////at.put("Field.ConstantValue", "<constantValue=>KQH");
|
||||
//at.put("Class.SourceFile", "<sourceFile=>RUH");
|
||||
at.put("Method.Bridge", "<Bridge>");
|
||||
at.put("Method.Varargs", "<Varargs>");
|
||||
at.put("Class.Enum", "<Enum>");
|
||||
at.put("*.Signature", "<Signature>RSH");
|
||||
//at.put("*.Deprecated", "<Deprecated>");
|
||||
//at.put("*.Synthetic", "<Synthetic>");
|
||||
at.put("Field.ConstantValue", "<ConstantValue>KQH");
|
||||
at.put("Class.SourceFile", "<SourceFile>RUH");
|
||||
at.put("Class.InnerClasses", "NH[<InnerClass><class=>RCH<outer=>RCH<name=>RUH<flags=>FH]");
|
||||
at.put("Code.LineNumberTable", "NH[<LineNumber><bci=>PH<line=>H]");
|
||||
at.put("Code.LocalVariableTable", "NH[<LocalVariable><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
|
||||
at.put("Code.LocalVariableTypeTable", "NH[<LocalVariableType><bci=>PH<span=>H<name=>RUH<type=>RSH<slot=>H]");
|
||||
at.put("Method.Exceptions", "NH[<Exception><name=>RCH]");
|
||||
at.put("Method.Code", "<Code>...");
|
||||
at.put("Code.StackMapTable", "<Frame>...");
|
||||
//at.put("Code.StkMapX", "<FrameX>...");
|
||||
if (true) {
|
||||
at.put("Code.StackMapTable",
|
||||
"[NH[<Frame>(1)]]"
|
||||
+ "[TB"
|
||||
+ "(64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79"
|
||||
+ ",80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95"
|
||||
+ ",96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111"
|
||||
+ ",112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127"
|
||||
+ ")[<SameLocals1StackItemFrame>(4)]"
|
||||
+ "(247)[<SameLocals1StackItemExtended>H(4)]"
|
||||
+ "(248)[<Chop3>H]"
|
||||
+ "(249)[<Chop2>H]"
|
||||
+ "(250)[<Chop1>H]"
|
||||
+ "(251)[<SameFrameExtended>H]"
|
||||
+ "(252)[<Append1>H(4)]"
|
||||
+ "(253)[<Append2>H(4)(4)]"
|
||||
+ "(254)[<Append3>H(4)(4)(4)]"
|
||||
+ "(255)[<FullFrame>H(2)(3)]"
|
||||
+ "()[<SameFrame>]]"
|
||||
+ "[NH[<Local>(4)]]"
|
||||
+ "[NH[<Stack>(4)]]"
|
||||
+ "[TB"
|
||||
+ ("(0)[<Top>]"
|
||||
+ "(1)[<ItemInteger>](2)[<ItemFloat>](3)[<ItemDouble>](4)[<ItemLong>]"
|
||||
+ "(5)[<ItemNull>](6)[<ItemUninitializedThis>]"
|
||||
+ "(7)[<ItemObject><class=>RCH]"
|
||||
+ "(8)[<ItemUninitialized><bci=>PH]"
|
||||
+ "()[<ItemUnknown>]]"));
|
||||
}
|
||||
|
||||
at.put("Class.EnclosingMethod", "<EnclosingMethod><class=>RCH<desc=>RDH");//RDNH
|
||||
|
||||
// Layouts of metadata attrs:
|
||||
String vpf = "[<RuntimeVisibleAnnotation>";
|
||||
String ipf = "[<RuntimeInvisibleAnnotation>";
|
||||
String apf = "[<Annotation>";
|
||||
String mdanno2 = ""
|
||||
+ "<type=>RSHNH[<Member><name=>RUH(3)]]"
|
||||
+ ("[TB"
|
||||
+ "(\\B,\\C,\\I,\\S,\\Z)[<value=>KIH]"
|
||||
+ "(\\D)[<value=>KDH]"
|
||||
+ "(\\F)[<value=>KFH]"
|
||||
+ "(\\J)[<value=>KJH]"
|
||||
+ "(\\c)[<class=>RSH]"
|
||||
+ "(\\e)[<type=>RSH<name=>RUH]"
|
||||
+ "(\\s)[<String>RUH]"
|
||||
+ "(\\@)[(2)]"
|
||||
+ "(\\[)[NH[<Element>(3)]]"
|
||||
+ "()[]"
|
||||
+ "]");
|
||||
String visanno = "[NH[(2)]][(1)]" + vpf + mdanno2;
|
||||
String invanno = "[NH[(2)]][(1)]" + ipf + mdanno2;
|
||||
String vparamanno = ""
|
||||
+ "[NB[<RuntimeVisibleParameterAnnotation>(1)]][NH[(2)]]"
|
||||
+ apf + mdanno2;
|
||||
String iparamanno = ""
|
||||
+ "[NB[<RuntimeInvisibleParameterAnnotation>(1)]][NH[(2)]]"
|
||||
+ apf + mdanno2;
|
||||
String mdannodef = "[<AnnotationDefault>(3)][(1)]" + apf + mdanno2;
|
||||
String[] mdplaces = {"Class", "Field", "Method"};
|
||||
for (String place : mdplaces) {
|
||||
at.put(place + ".RuntimeVisibleAnnotations", visanno);
|
||||
at.put(place + ".RuntimeInvisibleAnnotations", invanno);
|
||||
}
|
||||
at.put("Method.RuntimeVisibleParameterAnnotations", vparamanno);
|
||||
at.put("Method.RuntimeInvisibleParameterAnnotations", iparamanno);
|
||||
at.put("Method.AnnotationDefault", mdannodef);
|
||||
|
||||
attrTypesBacking = at;
|
||||
attrTypesInit = Collections.unmodifiableMap(at);
|
||||
}
|
||||
|
||||
;
|
||||
private static final String[] jcovAttrTypes = {
|
||||
"Code.CoverageTable=NH[<Coverage><bci=>PH<type=>H<line=>I<pos=>I]",
|
||||
"Code.CharacterRangeTable=NH[<CharacterRange><bci=>PH<endbci=>POH<from=>I<to=>I<flag=>H]",
|
||||
"Class.SourceID=<SourceID><id=>RUH",
|
||||
"Class.CompilationID=<CompilationID><id=>RUH"
|
||||
};
|
||||
protected static final String[][] modifierNames = {
|
||||
{"public"},
|
||||
{"private"},
|
||||
{"protected"},
|
||||
{"static"},
|
||||
{"final"},
|
||||
{"synchronized"},
|
||||
{null, "volatile", "bridge"},
|
||||
{null, "transient", "varargs"},
|
||||
{null, null, "native"},
|
||||
{"interface"},
|
||||
{"abstract"},
|
||||
{"strictfp"},
|
||||
{"synthetic"},
|
||||
{"annotation"},
|
||||
{"enum"},};
|
||||
protected static final String EIGHT_BIT_CHAR_ENCODING = "ISO8859_1";
|
||||
protected static final String UTF8_ENCODING = "UTF8";
|
||||
// What XML tags are used by this syntax, apart from attributes?
|
||||
protected static final Set<String> nonAttrTags;
|
||||
|
||||
static {
|
||||
HashSet<String> tagSet = new HashSet<String>();
|
||||
Collections.addAll(tagSet, new String[]{
|
||||
"ConstantPool",// the CP
|
||||
"Class", // the class
|
||||
"Interface", // implemented interfaces
|
||||
"Method", // methods
|
||||
"Field", // fields
|
||||
"Handler", // exception handler pseudo-attribute
|
||||
"Attribute", // unparsed attribute
|
||||
"Bytes", // bytecodes
|
||||
"Instructions" // bytecodes, parsed
|
||||
});
|
||||
nonAttrTags = Collections.unmodifiableSet(tagSet);
|
||||
}
|
||||
|
||||
// Accessors.
|
||||
public static Set<String> nonAttrTags() {
|
||||
return nonAttrTags;
|
||||
}
|
||||
|
||||
public static String cpTagName(int t) {
|
||||
t &= 0xFF;
|
||||
String ts = null;
|
||||
if (t < cpTagName.length) {
|
||||
ts = cpTagName[t];
|
||||
}
|
||||
if (ts != null) {
|
||||
return ts;
|
||||
}
|
||||
return ("UnknownTag" + (int) t).intern();
|
||||
}
|
||||
|
||||
public static int cpTagValue(String name) {
|
||||
for (int t = 0; t < cpTagName.length; t++) {
|
||||
if (name.equals(cpTagName[t])) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static String itemTagName(int t) {
|
||||
t &= 0xFF;
|
||||
String ts = null;
|
||||
if (t < itemTagName.length) {
|
||||
ts = itemTagName[t];
|
||||
}
|
||||
if (ts != null) {
|
||||
return ts;
|
||||
}
|
||||
return ("UnknownItem" + (int) t).intern();
|
||||
}
|
||||
|
||||
public static int itemTagValue(String name) {
|
||||
for (int t = 0; t < itemTagName.length; t++) {
|
||||
if (name.equals(itemTagName[t])) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void addJcovAttrTypes() {
|
||||
addAttrTypes(jcovAttrTypes);
|
||||
}
|
||||
// Public methods for declaring attribute types.
|
||||
protected Map<String, String> attrTypes = attrTypesInit;
|
||||
|
||||
public void addAttrType(String opt) {
|
||||
int eqpos = opt.indexOf('=');
|
||||
addAttrType(opt.substring(0, eqpos), opt.substring(eqpos + 1));
|
||||
}
|
||||
|
||||
public void addAttrTypes(String[] opts) {
|
||||
for (String opt : opts) {
|
||||
addAttrType(opt);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAttr(String attr) {
|
||||
if (!attr.startsWith("Class.")
|
||||
&& !attr.startsWith("Field.")
|
||||
&& !attr.startsWith("Method.")
|
||||
&& !attr.startsWith("Code.")
|
||||
&& !attr.startsWith("*.")) {
|
||||
throw new IllegalArgumentException("attr name must start with 'Class.', etc.");
|
||||
}
|
||||
String uattr = attr.substring(attr.indexOf('.') + 1);
|
||||
if (nonAttrTags.contains(uattr)) {
|
||||
throw new IllegalArgumentException("attr name must not be one of " + nonAttrTags);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAttrs(Map<String, String> at) {
|
||||
for (String attr : at.keySet()) {
|
||||
checkAttr(attr);
|
||||
}
|
||||
}
|
||||
|
||||
private void modAttrs() {
|
||||
if (attrTypes == attrTypesInit) {
|
||||
// Make modifiable.
|
||||
attrTypes = new HashMap<String, String>(attrTypesBacking);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAttrType(String attr, String fmt) {
|
||||
checkAttr(attr);
|
||||
modAttrs();
|
||||
attrTypes.put(attr, fmt);
|
||||
}
|
||||
|
||||
public void addAttrTypes(Map<String, String> at) {
|
||||
checkAttrs(at);
|
||||
modAttrs();
|
||||
attrTypes.putAll(at);
|
||||
}
|
||||
|
||||
public Map<String, String> getAttrTypes() {
|
||||
if (attrTypes == attrTypesInit) {
|
||||
return attrTypes;
|
||||
}
|
||||
return Collections.unmodifiableMap(attrTypes);
|
||||
}
|
||||
|
||||
public void setAttrTypes(Map<String, String> at) {
|
||||
checkAttrs(at);
|
||||
modAttrs();
|
||||
attrTypes.keySet().retainAll(at.keySet());
|
||||
attrTypes.putAll(at);
|
||||
}
|
||||
|
||||
// attr format helpers
|
||||
protected static boolean matchTag(int tagValue, String caseStr) {
|
||||
//System.out.println("matchTag "+tagValue+" in "+caseStr);
|
||||
for (int pos = 0, max = caseStr.length(), comma;
|
||||
pos < max;
|
||||
pos = comma + 1) {
|
||||
int caseValue;
|
||||
if (caseStr.charAt(pos) == '\\') {
|
||||
caseValue = caseStr.charAt(pos + 1);
|
||||
comma = pos + 2;
|
||||
assert (comma == max || caseStr.charAt(comma) == ',');
|
||||
} else {
|
||||
comma = caseStr.indexOf(',', pos);
|
||||
if (comma < 0) {
|
||||
comma = max;
|
||||
}
|
||||
caseValue = Integer.parseInt(caseStr.substring(pos, comma));
|
||||
}
|
||||
if (tagValue == caseValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static String[] getBodies(String type) {
|
||||
ArrayList<String> bodies = new ArrayList<String>();
|
||||
for (int i = 0; i < type.length();) {
|
||||
String body = getBody(type, i);
|
||||
bodies.add(body);
|
||||
i += body.length() + 2; // skip body and brackets
|
||||
}
|
||||
return bodies.toArray(new String[bodies.size()]);
|
||||
}
|
||||
|
||||
protected static String getBody(String type, int i) {
|
||||
assert (type.charAt(i) == '[');
|
||||
int next = ++i; // skip bracket
|
||||
for (int depth = 1; depth > 0; next++) {
|
||||
switch (type.charAt(next)) {
|
||||
case '[':
|
||||
depth++;
|
||||
break;
|
||||
case ']':
|
||||
depth--;
|
||||
break;
|
||||
case '(':
|
||||
next = type.indexOf(')', next);
|
||||
break;
|
||||
case '<':
|
||||
next = type.indexOf('>', next);
|
||||
break;
|
||||
}
|
||||
assert (next > 0);
|
||||
}
|
||||
--next; // get before bracket
|
||||
assert (type.charAt(next) == ']');
|
||||
return type.substring(i, next);
|
||||
}
|
||||
|
||||
public Element makeCPDigest(int length) {
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("MD5");
|
||||
} catch (java.security.NoSuchAlgorithmException ee) {
|
||||
throw new Error(ee);
|
||||
}
|
||||
int items = 0;
|
||||
for (Element e : cpool.elements()) {
|
||||
if (items == length) {
|
||||
break;
|
||||
}
|
||||
if (cpTagNames.contains(e.getName())) {
|
||||
items += 1;
|
||||
md.update((byte) cpTagValue(e.getName()));
|
||||
try {
|
||||
md.update(e.getText().toString().getBytes(UTF8_ENCODING));
|
||||
} catch (java.io.UnsupportedEncodingException ee) {
|
||||
throw new Error(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
ByteBuffer bb = ByteBuffer.wrap(md.digest());
|
||||
String l0 = Long.toHexString(bb.getLong(0));
|
||||
String l1 = Long.toHexString(bb.getLong(8));
|
||||
while (l0.length() < 16) {
|
||||
l0 = "0" + l0;
|
||||
}
|
||||
while (l1.length() < 16) {
|
||||
l1 = "0" + l1;
|
||||
}
|
||||
return new Element("Digest",
|
||||
"length", "" + items,
|
||||
"bytes", l0 + l1);
|
||||
}
|
||||
|
||||
public Element getCPDigest(int length) {
|
||||
if (length == -1) {
|
||||
length = cpool.countAll(XMLKit.elementFilter(cpTagNames));
|
||||
}
|
||||
for (Element md : cpool.findAllElements("Digest").elements()) {
|
||||
if (md.getAttrLong("length") == length) {
|
||||
return md;
|
||||
}
|
||||
}
|
||||
Element md = makeCPDigest(length);
|
||||
cpool.add(md);
|
||||
return md;
|
||||
}
|
||||
|
||||
public Element getCPDigest() {
|
||||
return getCPDigest(-1);
|
||||
}
|
||||
|
||||
public boolean checkCPDigest(Element md) {
|
||||
return md.equals(getCPDigest((int) md.getAttrLong("length")));
|
||||
}
|
||||
|
||||
public static int computeInterfaceNum(String intMethRef) {
|
||||
intMethRef = intMethRef.substring(1 + intMethRef.lastIndexOf(' '));
|
||||
if (!intMethRef.startsWith("(")) {
|
||||
return -1;
|
||||
}
|
||||
int signum = 1; // start with one for "this"
|
||||
scanSig:
|
||||
for (int i = 1; i < intMethRef.length(); i++) {
|
||||
char ch = intMethRef.charAt(i);
|
||||
signum++;
|
||||
switch (ch) {
|
||||
case ')':
|
||||
--signum;
|
||||
break scanSig;
|
||||
case 'L':
|
||||
i = intMethRef.indexOf(';', i);
|
||||
break;
|
||||
case '[':
|
||||
while (ch == '[') {
|
||||
ch = intMethRef.charAt(++i);
|
||||
}
|
||||
if (ch == 'L') {
|
||||
i = intMethRef.indexOf(';', i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
int num = (signum << 8) | 0;
|
||||
//System.out.println("computeInterfaceNum "+intMethRef+" => "+num);
|
||||
return num;
|
||||
}
|
||||
// Protected state for representing the class file.
|
||||
protected Element cfile; // <ClassFile ...>
|
||||
protected Element cpool; // <ConstantPool ...>
|
||||
protected Element klass; // <Class ...>
|
||||
protected Element currentMember; // varies during scans
|
||||
protected Element currentCode; // varies during scans
|
||||
}
|
@ -0,0 +1,818 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
|
||||
import java.util.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.io.*;
|
||||
import xmlkit.XMLKit.Element;
|
||||
/*
|
||||
* @author jrose
|
||||
*/
|
||||
public class ClassWriter extends ClassSyntax implements ClassSyntax.GetCPIndex {
|
||||
|
||||
private static final CommandLineParser CLP = new CommandLineParser(""
|
||||
+ "-source: +> = \n"
|
||||
+ "-dest: +> = \n"
|
||||
+ "-encoding: +> = \n"
|
||||
+ "-parseBytes $ \n"
|
||||
+ "- *? \n"
|
||||
+ "\n");
|
||||
|
||||
public static void main(String[] ava) throws IOException {
|
||||
ArrayList<String> av = new ArrayList<String>(Arrays.asList(ava));
|
||||
HashMap<String, String> props = new HashMap<String, String>();
|
||||
props.put("-encoding:", "UTF8"); // default
|
||||
CLP.parse(av, props);
|
||||
File source = asFile(props.get("-source:"));
|
||||
File dest = asFile(props.get("-dest:"));
|
||||
String encoding = props.get("-encoding:");
|
||||
boolean parseBytes = props.containsKey("-parseBytes");
|
||||
boolean destMade = false;
|
||||
|
||||
for (String a : av) {
|
||||
File f;
|
||||
File inf = new File(source, a);
|
||||
System.out.println("Reading " + inf);
|
||||
Element e;
|
||||
if (inf.getName().endsWith(".class")) {
|
||||
ClassReader cr = new ClassReader();
|
||||
cr.parseBytes = parseBytes;
|
||||
e = cr.readFrom(inf);
|
||||
f = new File(a);
|
||||
} else if (inf.getName().endsWith(".xml")) {
|
||||
InputStream in = new FileInputStream(inf);
|
||||
Reader inw = ClassReader.makeReader(in, encoding);
|
||||
e = XMLKit.readFrom(inw);
|
||||
e.findAllInTree(XMLKit.and(XMLKit.elementFilter(nonAttrTags()),
|
||||
XMLKit.methodFilter(Element.method("trimText"))));
|
||||
//System.out.println(e);
|
||||
inw.close();
|
||||
f = new File(a.substring(0, a.length() - ".xml".length()) + ".class");
|
||||
} else {
|
||||
System.out.println("Warning: unknown input " + a);
|
||||
continue;
|
||||
}
|
||||
// Now write it:
|
||||
if (!destMade) {
|
||||
destMade = true;
|
||||
if (dest == null) {
|
||||
dest = File.createTempFile("TestOut", ".dir", new File("."));
|
||||
dest.delete();
|
||||
System.out.println("Writing results to " + dest);
|
||||
}
|
||||
if (!(dest.isDirectory() || dest.mkdir())) {
|
||||
throw new RuntimeException("Cannot create " + dest);
|
||||
}
|
||||
}
|
||||
File outf = new File(dest, f.isAbsolute() ? f.getName() : f.getPath());
|
||||
outf.getParentFile().mkdirs();
|
||||
new ClassWriter(e).writeTo(outf);
|
||||
}
|
||||
}
|
||||
|
||||
private static File asFile(String str) {
|
||||
return (str == null) ? null : new File(str);
|
||||
}
|
||||
|
||||
public void writeTo(File file) throws IOException {
|
||||
OutputStream out = null;
|
||||
try {
|
||||
out = new BufferedOutputStream(new FileOutputStream(file));
|
||||
writeTo(out);
|
||||
} finally {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
protected String[] callables; // varies
|
||||
protected int cpoolSize = 0;
|
||||
protected HashMap<String, String> attrTypesByTag;
|
||||
protected OutputStream out;
|
||||
protected HashMap<String, int[]> cpMap = new HashMap<String, int[]>();
|
||||
protected ArrayList<ByteArrayOutputStream> attrBufs = new ArrayList<ByteArrayOutputStream>();
|
||||
|
||||
private void setupAttrTypes() {
|
||||
attrTypesByTag = new HashMap<String, String>();
|
||||
for (String key : attrTypes.keySet()) {
|
||||
String pfx = key.substring(0, key.indexOf('.') + 1);
|
||||
String val = attrTypes.get(key);
|
||||
int pos = val.indexOf('<');
|
||||
if (pos >= 0) {
|
||||
String tag = val.substring(pos + 1, val.indexOf('>', pos));
|
||||
attrTypesByTag.put(pfx + tag, key);
|
||||
}
|
||||
}
|
||||
//System.out.println("attrTypesByTag: "+attrTypesByTag);
|
||||
}
|
||||
|
||||
protected ByteArrayOutputStream getAttrBuf() {
|
||||
int nab = attrBufs.size();
|
||||
if (nab == 0) {
|
||||
return new ByteArrayOutputStream(1024);
|
||||
}
|
||||
ByteArrayOutputStream ab = attrBufs.get(nab - 1);
|
||||
attrBufs.remove(nab - 1);
|
||||
return ab;
|
||||
}
|
||||
|
||||
protected void putAttrBuf(ByteArrayOutputStream ab) {
|
||||
ab.reset();
|
||||
attrBufs.add(ab);
|
||||
}
|
||||
|
||||
public ClassWriter(Element root) {
|
||||
this(root, null);
|
||||
}
|
||||
|
||||
public ClassWriter(Element root, ClassSyntax cr) {
|
||||
if (cr != null) {
|
||||
attrTypes = cr.attrTypes;
|
||||
}
|
||||
setupAttrTypes();
|
||||
if (root.getName() == "ClassFile") {
|
||||
cfile = root;
|
||||
cpool = root.findElement("ConstantPool");
|
||||
klass = root.findElement("Class");
|
||||
} else if (root.getName() == "Class") {
|
||||
cfile = new Element("ClassFile",
|
||||
new String[]{
|
||||
"magic", String.valueOf(0xCAFEBABE),
|
||||
"minver", "0", "majver", "46",});
|
||||
cpool = new Element("ConstantPool");
|
||||
klass = root;
|
||||
} else {
|
||||
throw new IllegalArgumentException("bad element type " + root.getName());
|
||||
}
|
||||
if (cpool == null) {
|
||||
cpool = new Element("ConstantPool");
|
||||
}
|
||||
|
||||
int cpLen = 1 + cpool.size();
|
||||
for (Element c : cpool.elements()) {
|
||||
int id = (int) c.getAttrLong("id");
|
||||
int tag = cpTagValue(c.getName());
|
||||
setCPIndex(tag, c.getText().toString(), id);
|
||||
switch (tag) {
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
cpLen += 1;
|
||||
}
|
||||
}
|
||||
cpoolSize = cpLen;
|
||||
}
|
||||
|
||||
public int findCPIndex(int tag, String name) {
|
||||
if (name == null) {
|
||||
return 0;
|
||||
}
|
||||
int[] ids = cpMap.get(name.toString());
|
||||
return (ids == null) ? 0 : ids[tag];
|
||||
}
|
||||
|
||||
public int getCPIndex(int tag, String name) {
|
||||
//System.out.println("getCPIndex "+cpTagName(tag)+" "+name);
|
||||
if (name == null) {
|
||||
return 0;
|
||||
}
|
||||
int id = findCPIndex(tag, name);
|
||||
if (id == 0) {
|
||||
id = cpoolSize;
|
||||
cpoolSize += 1;
|
||||
setCPIndex(tag, name, id);
|
||||
cpool.add(new Element(cpTagName(tag),
|
||||
new String[]{"id", "" + id},
|
||||
new Object[]{name}));
|
||||
int pos;
|
||||
switch (tag) {
|
||||
case CONSTANT_Long:
|
||||
case CONSTANT_Double:
|
||||
cpoolSize += 1;
|
||||
break;
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
getCPIndex(CONSTANT_Utf8, name);
|
||||
break;
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
pos = name.indexOf(' ');
|
||||
getCPIndex(CONSTANT_Class, name.substring(0, pos));
|
||||
getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1));
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
pos = name.indexOf(' ');
|
||||
getCPIndex(CONSTANT_Utf8, name.substring(0, pos));
|
||||
getCPIndex(CONSTANT_Utf8, name.substring(pos + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setCPIndex(int tag, String name, int id) {
|
||||
//System.out.println("setCPIndex id="+id+" tag="+tag+" name="+name);
|
||||
int[] ids = cpMap.get(name);
|
||||
if (ids == null) {
|
||||
cpMap.put(name, ids = new int[13]);
|
||||
}
|
||||
if (ids[tag] != 0 && ids[tag] != id) {
|
||||
System.out.println("Warning: Duplicate CP entries for " + ids[tag] + " and " + id);
|
||||
}
|
||||
//assert(ids[tag] == 0 || ids[tag] == id);
|
||||
ids[tag] = id;
|
||||
}
|
||||
|
||||
public int parseFlags(String flagString) {
|
||||
int flags = 0;
|
||||
int i = -1;
|
||||
for (String[] names : modifierNames) {
|
||||
++i;
|
||||
for (String name : names) {
|
||||
if (name == null) {
|
||||
continue;
|
||||
}
|
||||
int pos = flagString.indexOf(name);
|
||||
if (pos >= 0) {
|
||||
flags |= (1 << i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream realOut) throws IOException {
|
||||
OutputStream headOut = realOut;
|
||||
ByteArrayOutputStream tailOut = new ByteArrayOutputStream();
|
||||
|
||||
// write the body of the class file first
|
||||
this.out = tailOut;
|
||||
writeClass();
|
||||
|
||||
// write the file header last
|
||||
this.out = headOut;
|
||||
u4((int) cfile.getAttrLong("magic"));
|
||||
u2((int) cfile.getAttrLong("minver"));
|
||||
u2((int) cfile.getAttrLong("majver"));
|
||||
writeCP();
|
||||
|
||||
// recopy the file tail
|
||||
this.out = null;
|
||||
tailOut.writeTo(realOut);
|
||||
}
|
||||
|
||||
void writeClass() throws IOException {
|
||||
int flags = parseFlags(klass.getAttr("flags"));
|
||||
flags ^= Modifier.SYNCHRONIZED;
|
||||
u2(flags);
|
||||
cpRef(CONSTANT_Class, klass.getAttr("name"));
|
||||
cpRef(CONSTANT_Class, klass.getAttr("super"));
|
||||
Element interfaces = klass.findAllElements("Interface");
|
||||
u2(interfaces.size());
|
||||
for (Element e : interfaces.elements()) {
|
||||
cpRef(CONSTANT_Class, e.getAttr("name"));
|
||||
}
|
||||
for (int isMethod = 0; isMethod <= 1; isMethod++) {
|
||||
Element members = klass.findAllElements(isMethod != 0 ? "Method" : "Field");
|
||||
u2(members.size());
|
||||
for (Element m : members.elements()) {
|
||||
writeMember(m, isMethod != 0);
|
||||
}
|
||||
}
|
||||
writeAttributesFor(klass);
|
||||
}
|
||||
|
||||
private void writeMember(Element member, boolean isMethod) throws IOException {
|
||||
//System.out.println("writeMember "+member);
|
||||
u2(parseFlags(member.getAttr("flags")));
|
||||
cpRef(CONSTANT_Utf8, member.getAttr("name"));
|
||||
cpRef(CONSTANT_Utf8, member.getAttr("type"));
|
||||
writeAttributesFor(member);
|
||||
}
|
||||
|
||||
protected void writeAttributesFor(Element x) throws IOException {
|
||||
LinkedHashSet<String> attrNames = new LinkedHashSet<String>();
|
||||
for (Element e : x.elements()) {
|
||||
attrNames.add(e.getName()); // uniquifying
|
||||
}
|
||||
attrNames.removeAll(nonAttrTags());
|
||||
u2(attrNames.size());
|
||||
if (attrNames.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Element prevCurrent;
|
||||
if (x.getName() == "Code") {
|
||||
prevCurrent = currentCode;
|
||||
currentCode = x;
|
||||
} else {
|
||||
prevCurrent = currentMember;
|
||||
currentMember = x;
|
||||
}
|
||||
OutputStream realOut = this.out;
|
||||
for (String utag : attrNames) {
|
||||
String qtag = x.getName() + "." + utag;
|
||||
String wtag = "*." + utag;
|
||||
String key = attrTypesByTag.get(qtag);
|
||||
if (key == null) {
|
||||
key = attrTypesByTag.get(wtag);
|
||||
}
|
||||
String type = attrTypes.get(key);
|
||||
//System.out.println("tag "+qtag+" => key "+key+"; type "+type);
|
||||
Element attrs = x.findAllElements(utag);
|
||||
ByteArrayOutputStream attrBuf = getAttrBuf();
|
||||
if (type == null) {
|
||||
if (attrs.size() != 1 || !attrs.get(0).equals(new Element(utag))) {
|
||||
System.out.println("Warning: No attribute type description: " + qtag);
|
||||
}
|
||||
key = wtag;
|
||||
} else {
|
||||
try {
|
||||
this.out = attrBuf;
|
||||
// unparse according to type desc.
|
||||
if (type.equals("<Code>...")) {
|
||||
writeCode((Element) attrs.get(0)); // assume only 1
|
||||
} else if (type.equals("<Frame>...")) {
|
||||
writeStackMap(attrs, false);
|
||||
} else if (type.equals("<FrameX>...")) {
|
||||
writeStackMap(attrs, true);
|
||||
} else if (type.startsWith("[")) {
|
||||
writeAttributeRecursive(attrs, type);
|
||||
} else {
|
||||
writeAttribute(attrs, type);
|
||||
}
|
||||
} finally {
|
||||
//System.out.println("Attr Bytes = \""+attrBuf.toString(EIGHT_BIT_CHAR_ENCODING).replace('"', (char)('"'|0x80))+"\"");
|
||||
this.out = realOut;
|
||||
}
|
||||
}
|
||||
cpRef(CONSTANT_Utf8, key.substring(key.indexOf('.') + 1));
|
||||
u4(attrBuf.size());
|
||||
attrBuf.writeTo(out);
|
||||
putAttrBuf(attrBuf);
|
||||
}
|
||||
if (x.getName() == "Code") {
|
||||
currentCode = prevCurrent;
|
||||
} else {
|
||||
currentMember = prevCurrent;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeAttributeRecursive(Element aval, String type) throws IOException {
|
||||
assert (callables == null);
|
||||
callables = getBodies(type);
|
||||
writeAttribute(aval, callables[0]);
|
||||
callables = null;
|
||||
}
|
||||
|
||||
private void writeAttribute(Element aval, String type) throws IOException {
|
||||
//System.out.println("writeAttribute "+aval+" using "+type);
|
||||
String nextAttrName = null;
|
||||
boolean afterElemHead = false;
|
||||
for (int len = type.length(), next, i = 0; i < len; i = next) {
|
||||
int value;
|
||||
char intKind;
|
||||
int tag;
|
||||
int sigChar;
|
||||
String attrValue;
|
||||
switch (type.charAt(i)) {
|
||||
case '<':
|
||||
assert (nextAttrName == null);
|
||||
next = type.indexOf('>', i);
|
||||
String form = type.substring(i + 1, next++);
|
||||
if (form.indexOf('=') < 0) {
|
||||
// elem_placement = '<' elemname '>'
|
||||
if (aval.isAnonymous()) {
|
||||
assert (aval.size() == 1);
|
||||
aval = (Element) aval.get(0);
|
||||
}
|
||||
assert (aval.getName().equals(form)) : aval + " // " + form;
|
||||
afterElemHead = true;
|
||||
} else {
|
||||
// attr_placement = '(' attrname '=' (value)? ')'
|
||||
int eqPos = form.indexOf('=');
|
||||
assert (eqPos >= 0);
|
||||
nextAttrName = form.substring(0, eqPos).intern();
|
||||
if (eqPos != form.length() - 1) {
|
||||
// value is implicit, not placed in file
|
||||
nextAttrName = null;
|
||||
}
|
||||
afterElemHead = false;
|
||||
}
|
||||
continue;
|
||||
case '(':
|
||||
next = type.indexOf(')', ++i);
|
||||
int callee = Integer.parseInt(type.substring(i, next++));
|
||||
writeAttribute(aval, callables[callee]);
|
||||
continue;
|
||||
case 'N': // replication = 'N' int '[' type ... ']'
|
||||
{
|
||||
assert (nextAttrName == null);
|
||||
afterElemHead = false;
|
||||
char countType = type.charAt(i + 1);
|
||||
next = i + 2;
|
||||
String type1 = getBody(type, next);
|
||||
Element elems = aval;
|
||||
if (type1.startsWith("<")) {
|
||||
// Select only matching members of aval.
|
||||
String elemName = type1.substring(1, type1.indexOf('>'));
|
||||
elems = aval.findAllElements(elemName);
|
||||
}
|
||||
putInt(elems.size(), countType);
|
||||
next += type1.length() + 2; // skip body and brackets
|
||||
for (Element elem : elems.elements()) {
|
||||
writeAttribute(elem, type1);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
case 'T': // union = 'T' any_int union_case* '(' ')' '[' body ']'
|
||||
// write the value
|
||||
value = (int) aval.getAttrLong("tag");
|
||||
assert (aval.getAttr("tag") != null) : aval;
|
||||
intKind = type.charAt(++i);
|
||||
if (intKind == 'S') {
|
||||
intKind = type.charAt(++i);
|
||||
}
|
||||
putInt(value, intKind);
|
||||
nextAttrName = null;
|
||||
afterElemHead = false;
|
||||
++i; // skip the int type char
|
||||
// union_case = '(' ('-')? digit+ ')' '[' body ']'
|
||||
for (boolean foundCase = false;;) {
|
||||
assert (type.charAt(i) == '(');
|
||||
next = type.indexOf(')', ++i);
|
||||
assert (next >= i);
|
||||
String caseStr = type.substring(i, next++);
|
||||
String type1 = getBody(type, next);
|
||||
next += type1.length() + 2; // skip body and brackets
|
||||
boolean lastCase = (caseStr.length() == 0);
|
||||
if (!foundCase
|
||||
&& (lastCase || matchTag(value, caseStr))) {
|
||||
foundCase = true;
|
||||
// Execute this body.
|
||||
writeAttribute(aval, type1);
|
||||
}
|
||||
if (lastCase) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
case 'B':
|
||||
case 'H':
|
||||
case 'I': // int = oneof "BHI"
|
||||
value = (int) aval.getAttrLong(nextAttrName);
|
||||
intKind = type.charAt(i);
|
||||
next = i + 1;
|
||||
break;
|
||||
case 'K':
|
||||
sigChar = type.charAt(i + 1);
|
||||
if (sigChar == 'Q') {
|
||||
assert (currentMember.getName() == "Field");
|
||||
assert (aval.getName() == "ConstantValue");
|
||||
String sig = currentMember.getAttr("type");
|
||||
sigChar = sig.charAt(0);
|
||||
switch (sigChar) {
|
||||
case 'Z':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'S':
|
||||
sigChar = 'I';
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (sigChar) {
|
||||
case 'I':
|
||||
tag = CONSTANT_Integer;
|
||||
break;
|
||||
case 'J':
|
||||
tag = CONSTANT_Long;
|
||||
break;
|
||||
case 'F':
|
||||
tag = CONSTANT_Float;
|
||||
break;
|
||||
case 'D':
|
||||
tag = CONSTANT_Double;
|
||||
break;
|
||||
case 'L':
|
||||
tag = CONSTANT_String;
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
tag = 0;
|
||||
}
|
||||
assert (type.charAt(i + 2) == 'H'); // only H works for now
|
||||
next = i + 3;
|
||||
assert (afterElemHead || nextAttrName != null);
|
||||
//System.out.println("get attr "+nextAttrName+" in "+aval);
|
||||
if (nextAttrName != null) {
|
||||
attrValue = aval.getAttr(nextAttrName);
|
||||
assert (attrValue != null);
|
||||
} else {
|
||||
assert (aval.isText()) : aval;
|
||||
attrValue = aval.getText().toString();
|
||||
}
|
||||
value = getCPIndex(tag, attrValue);
|
||||
intKind = 'H'; //type.charAt(i+2);
|
||||
break;
|
||||
case 'R':
|
||||
sigChar = type.charAt(i + 1);
|
||||
switch (sigChar) {
|
||||
case 'C':
|
||||
tag = CONSTANT_Class;
|
||||
break;
|
||||
case 'S':
|
||||
tag = CONSTANT_Utf8;
|
||||
break;
|
||||
case 'D':
|
||||
tag = CONSTANT_Class;
|
||||
break;
|
||||
case 'F':
|
||||
tag = CONSTANT_Fieldref;
|
||||
break;
|
||||
case 'M':
|
||||
tag = CONSTANT_Methodref;
|
||||
break;
|
||||
case 'I':
|
||||
tag = CONSTANT_InterfaceMethodref;
|
||||
break;
|
||||
case 'U':
|
||||
tag = CONSTANT_Utf8;
|
||||
break;
|
||||
//case 'Q': tag = CONSTANT_Class; break;
|
||||
default:
|
||||
assert (false);
|
||||
tag = 0;
|
||||
}
|
||||
assert (type.charAt(i + 2) == 'H'); // only H works for now
|
||||
next = i + 3;
|
||||
assert (afterElemHead || nextAttrName != null);
|
||||
//System.out.println("get attr "+nextAttrName+" in "+aval);
|
||||
if (nextAttrName != null) {
|
||||
attrValue = aval.getAttr(nextAttrName);
|
||||
} else if (aval.hasText()) {
|
||||
attrValue = aval.getText().toString();
|
||||
} else {
|
||||
attrValue = null;
|
||||
}
|
||||
value = getCPIndex(tag, attrValue);
|
||||
intKind = 'H'; //type.charAt(i+2);
|
||||
break;
|
||||
case 'P': // bci = 'P' int
|
||||
case 'S': // signed_int = 'S' int
|
||||
next = i + 2;
|
||||
value = (int) aval.getAttrLong(nextAttrName);
|
||||
intKind = type.charAt(i + 1);
|
||||
break;
|
||||
case 'F':
|
||||
next = i + 2;
|
||||
value = parseFlags(aval.getAttr(nextAttrName));
|
||||
intKind = type.charAt(i + 1);
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("bad attr format '" + type.charAt(i) + "': " + type);
|
||||
}
|
||||
// write the value
|
||||
putInt(value, intKind);
|
||||
nextAttrName = null;
|
||||
afterElemHead = false;
|
||||
}
|
||||
assert (nextAttrName == null);
|
||||
}
|
||||
|
||||
private void putInt(int x, char ch) throws IOException {
|
||||
switch (ch) {
|
||||
case 'B':
|
||||
u1(x);
|
||||
break;
|
||||
case 'H':
|
||||
u2(x);
|
||||
break;
|
||||
case 'I':
|
||||
u4(x);
|
||||
break;
|
||||
}
|
||||
assert ("BHI".indexOf(ch) >= 0);
|
||||
}
|
||||
|
||||
private void writeCode(Element code) throws IOException {
|
||||
//System.out.println("writeCode "+code);
|
||||
//Element m = new Element(currentMember); m.remove(code);
|
||||
//System.out.println(" in "+m);
|
||||
int stack = (int) code.getAttrLong("stack");
|
||||
int local = (int) code.getAttrLong("local");
|
||||
Element bytes = code.findElement("Bytes");
|
||||
Element insns = code.findElement("Instructions");
|
||||
String bytecodes;
|
||||
if (insns == null) {
|
||||
bytecodes = bytes.getText().toString();
|
||||
} else {
|
||||
bytecodes = InstructionSyntax.assemble(insns, this);
|
||||
// Cache the assembled bytecodes:
|
||||
bytes = new Element("Bytes", (String[]) null, bytecodes);
|
||||
code.add(0, bytes);
|
||||
}
|
||||
u2(stack);
|
||||
u2(local);
|
||||
int length = bytecodes.length();
|
||||
u4(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
u1((byte) bytecodes.charAt(i));
|
||||
}
|
||||
Element handlers = code.findAllElements("Handler");
|
||||
u2(handlers.size());
|
||||
for (Element handler : handlers.elements()) {
|
||||
int start = (int) handler.getAttrLong("start");
|
||||
int end = (int) handler.getAttrLong("end");
|
||||
int catsh = (int) handler.getAttrLong("catch");
|
||||
u2(start);
|
||||
u2(end);
|
||||
u2(catsh);
|
||||
cpRef(CONSTANT_Class, handler.getAttr("class"));
|
||||
}
|
||||
writeAttributesFor(code);
|
||||
}
|
||||
|
||||
protected void writeStackMap(Element attrs, boolean hasXOption) throws IOException {
|
||||
Element bytes = currentCode.findElement("Bytes");
|
||||
assert (bytes != null && bytes.size() == 1);
|
||||
int byteLength = ((String) bytes.get(0)).length();
|
||||
boolean uoffsetIsU4 = (byteLength >= (1 << 16));
|
||||
boolean ulocalvarIsU4 = currentCode.getAttrLong("local") >= (1 << 16);
|
||||
boolean ustackIsU4 = currentCode.getAttrLong("stack") >= (1 << 16);
|
||||
if (uoffsetIsU4) {
|
||||
u4(attrs.size());
|
||||
} else {
|
||||
u2(attrs.size());
|
||||
}
|
||||
for (Element frame : attrs.elements()) {
|
||||
int bci = (int) frame.getAttrLong("bci");
|
||||
if (uoffsetIsU4) {
|
||||
u4(bci);
|
||||
} else {
|
||||
u2(bci);
|
||||
}
|
||||
if (hasXOption) {
|
||||
u1((int) frame.getAttrLong("flags"));
|
||||
}
|
||||
// Scan local and stack types in this frame:
|
||||
final int LOCALS = 0, STACK = 1;
|
||||
for (int j = LOCALS; j <= STACK; j++) {
|
||||
Element types = frame.findElement(j == LOCALS ? "Local" : "Stack");
|
||||
int typeSize = (types == null) ? 0 : types.size();
|
||||
if (j == LOCALS) {
|
||||
if (ulocalvarIsU4) {
|
||||
u4(typeSize);
|
||||
} else {
|
||||
u2(typeSize);
|
||||
}
|
||||
} else { // STACK
|
||||
if (ustackIsU4) {
|
||||
u4(typeSize);
|
||||
} else {
|
||||
u2(typeSize);
|
||||
}
|
||||
}
|
||||
if (types == null) {
|
||||
continue;
|
||||
}
|
||||
for (Element type : types.elements()) {
|
||||
int tag = itemTagValue(type.getName());
|
||||
u1(tag);
|
||||
switch (tag) {
|
||||
case ITEM_Object:
|
||||
cpRef(CONSTANT_Class, type.getAttr("class"));
|
||||
break;
|
||||
case ITEM_Uninitialized:
|
||||
case ITEM_ReturnAddress: {
|
||||
int offset = (int) type.getAttrLong("bci");
|
||||
if (uoffsetIsU4) {
|
||||
u4(offset);
|
||||
} else {
|
||||
u2(offset);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeCP() throws IOException {
|
||||
int cpLen = cpoolSize;
|
||||
u2(cpLen);
|
||||
ByteArrayOutputStream buf = getAttrBuf();
|
||||
for (Element c : cpool.elements()) {
|
||||
if (!c.isText()) {
|
||||
System.out.println("## !isText " + c);
|
||||
}
|
||||
int id = (int) c.getAttrLong("id");
|
||||
int tag = cpTagValue(c.getName());
|
||||
String name = c.getText().toString();
|
||||
int pos;
|
||||
u1(tag);
|
||||
switch (tag) {
|
||||
case CONSTANT_Utf8: {
|
||||
int done = 0;
|
||||
buf.reset();
|
||||
int nameLen = name.length();
|
||||
while (done < nameLen) {
|
||||
int next = name.indexOf((char) 0, done);
|
||||
if (next < 0) {
|
||||
next = nameLen;
|
||||
}
|
||||
if (done < next) {
|
||||
buf.write(name.substring(done, next).getBytes(UTF8_ENCODING));
|
||||
}
|
||||
if (next < nameLen) {
|
||||
buf.write(0300);
|
||||
buf.write(0200);
|
||||
next++;
|
||||
}
|
||||
done = next;
|
||||
}
|
||||
u2(buf.size());
|
||||
buf.writeTo(out);
|
||||
}
|
||||
break;
|
||||
case CONSTANT_Integer:
|
||||
u4(Integer.parseInt(name));
|
||||
break;
|
||||
case CONSTANT_Float:
|
||||
u4(Float.floatToIntBits(Float.parseFloat(name)));
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
u8(Long.parseLong(name));
|
||||
//i += 1; // no need: extra cp slot is implicit
|
||||
break;
|
||||
case CONSTANT_Double:
|
||||
u8(Double.doubleToLongBits(Double.parseDouble(name)));
|
||||
//i += 1; // no need: extra cp slot is implicit
|
||||
break;
|
||||
case CONSTANT_Class:
|
||||
case CONSTANT_String:
|
||||
u2(getCPIndex(CONSTANT_Utf8, name));
|
||||
break;
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
pos = name.indexOf(' ');
|
||||
u2(getCPIndex(CONSTANT_Class, name.substring(0, pos)));
|
||||
u2(getCPIndex(CONSTANT_NameAndType, name.substring(pos + 1)));
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
pos = name.indexOf(' ');
|
||||
u2(getCPIndex(CONSTANT_Utf8, name.substring(0, pos)));
|
||||
u2(getCPIndex(CONSTANT_Utf8, name.substring(pos + 1)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
putAttrBuf(buf);
|
||||
}
|
||||
|
||||
public void cpRef(int tag, String name) throws IOException {
|
||||
u2(getCPIndex(tag, name));
|
||||
}
|
||||
|
||||
public void u8(long x) throws IOException {
|
||||
u4((int) (x >>> 32));
|
||||
u4((int) (x >>> 0));
|
||||
}
|
||||
|
||||
public void u4(int x) throws IOException {
|
||||
u2(x >>> 16);
|
||||
u2(x >>> 0);
|
||||
}
|
||||
|
||||
public void u2(int x) throws IOException {
|
||||
u1(x >>> 8);
|
||||
u1(x >>> 0);
|
||||
}
|
||||
|
||||
public void u1(int x) throws IOException {
|
||||
out.write(x & 0xFF);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
|
||||
import java.util.*;
|
||||
/*
|
||||
* @author jrose
|
||||
*/
|
||||
public class CommandLineParser {
|
||||
|
||||
public CommandLineParser(String optionString) {
|
||||
setOptionMap(optionString);
|
||||
}
|
||||
TreeMap<String, String[]> optionMap;
|
||||
|
||||
public void setOptionMap(String options) {
|
||||
// Convert options string into optLines dictionary.
|
||||
TreeMap<String, String[]> optmap = new TreeMap<String, String[]>();
|
||||
loadOptmap:
|
||||
for (String optline : options.split("\n")) {
|
||||
String[] words = optline.split("\\p{Space}+");
|
||||
if (words.length == 0) {
|
||||
continue loadOptmap;
|
||||
}
|
||||
String opt = words[0];
|
||||
words[0] = ""; // initial word is not a spec
|
||||
if (opt.length() == 0 && words.length >= 1) {
|
||||
opt = words[1]; // initial "word" is empty due to leading ' '
|
||||
words[1] = "";
|
||||
}
|
||||
if (opt.length() == 0) {
|
||||
continue loadOptmap;
|
||||
}
|
||||
String[] prevWords = optmap.put(opt, words);
|
||||
if (prevWords != null) {
|
||||
throw new RuntimeException("duplicate option: "
|
||||
+ optline.trim());
|
||||
}
|
||||
}
|
||||
optionMap = optmap;
|
||||
}
|
||||
|
||||
public String getOptionMap() {
|
||||
TreeMap<String, String[]> optmap = optionMap;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (String opt : optmap.keySet()) {
|
||||
sb.append(opt);
|
||||
for (String spec : optmap.get(opt)) {
|
||||
sb.append(' ').append(spec);
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a set of command-line options from args,
|
||||
* storing them in the properties map in a canonicalized form.
|
||||
*/
|
||||
public String parse(List<String> args, Map<String, String> properties) {
|
||||
//System.out.println(args+" // "+properties);
|
||||
|
||||
String resultString = null;
|
||||
TreeMap<String, String[]> optmap = optionMap;
|
||||
|
||||
// State machine for parsing a command line.
|
||||
ListIterator<String> argp = args.listIterator();
|
||||
ListIterator<String> pbp = new ArrayList<String>().listIterator();
|
||||
doArgs:
|
||||
for (;;) {
|
||||
// One trip through this loop per argument.
|
||||
// Multiple trips per option only if several options per argument.
|
||||
String arg;
|
||||
if (pbp.hasPrevious()) {
|
||||
arg = pbp.previous();
|
||||
pbp.remove();
|
||||
} else if (argp.hasNext()) {
|
||||
arg = argp.next();
|
||||
} else {
|
||||
// No more arguments at all.
|
||||
break doArgs;
|
||||
}
|
||||
tryOpt:
|
||||
for (int optlen = arg.length();; optlen--) {
|
||||
// One time through this loop for each matching arg prefix.
|
||||
String opt;
|
||||
// Match some prefix of the argument to a key in optmap.
|
||||
findOpt:
|
||||
for (;;) {
|
||||
opt = arg.substring(0, optlen);
|
||||
if (optmap.containsKey(opt)) {
|
||||
break findOpt;
|
||||
}
|
||||
if (optlen == 0) {
|
||||
break tryOpt;
|
||||
}
|
||||
// Decide on a smaller prefix to search for.
|
||||
SortedMap<String, String[]> pfxmap = optmap.headMap(opt);
|
||||
// pfxmap.lastKey is no shorter than any prefix in optmap.
|
||||
int len = pfxmap.isEmpty() ? 0 : pfxmap.lastKey().length();
|
||||
optlen = Math.min(len, optlen - 1);
|
||||
opt = arg.substring(0, optlen);
|
||||
// (Note: We could cut opt down to its common prefix with
|
||||
// pfxmap.lastKey, but that wouldn't save many cycles.)
|
||||
}
|
||||
opt = opt.intern();
|
||||
assert (arg.startsWith(opt));
|
||||
assert (opt.length() == optlen);
|
||||
String val = arg.substring(optlen); // arg == opt+val
|
||||
|
||||
// Execute the option processing specs for this opt.
|
||||
// If no actions are taken, then look for a shorter prefix.
|
||||
boolean didAction = false;
|
||||
boolean isError = false;
|
||||
|
||||
int pbpMark = pbp.nextIndex(); // in case of backtracking
|
||||
String[] specs = optmap.get(opt);
|
||||
eachSpec:
|
||||
for (String spec : specs) {
|
||||
if (spec.length() == 0) {
|
||||
continue eachSpec;
|
||||
}
|
||||
if (spec.startsWith("#")) {
|
||||
break eachSpec;
|
||||
}
|
||||
int sidx = 0;
|
||||
char specop = spec.charAt(sidx++);
|
||||
|
||||
// Deal with '+'/'*' prefixes (spec conditions).
|
||||
boolean ok;
|
||||
switch (specop) {
|
||||
case '+':
|
||||
// + means we want an non-empty val suffix.
|
||||
ok = (val.length() != 0);
|
||||
specop = spec.charAt(sidx++);
|
||||
break;
|
||||
case '*':
|
||||
// * means we accept empty or non-empty
|
||||
ok = true;
|
||||
specop = spec.charAt(sidx++);
|
||||
break;
|
||||
default:
|
||||
// No condition prefix means we require an exact
|
||||
// match, as indicated by an empty val suffix.
|
||||
ok = (val.length() == 0);
|
||||
break;
|
||||
}
|
||||
if (!ok) {
|
||||
continue eachSpec;
|
||||
}
|
||||
|
||||
String specarg = spec.substring(sidx);
|
||||
switch (specop) {
|
||||
case '.': // terminate the option sequence
|
||||
resultString = (specarg.length() != 0) ? specarg.intern() : opt;
|
||||
break doArgs;
|
||||
case '?': // abort the option sequence
|
||||
resultString = (specarg.length() != 0) ? specarg.intern() : arg;
|
||||
isError = true;
|
||||
break eachSpec;
|
||||
case '@': // change the effective opt name
|
||||
opt = specarg.intern();
|
||||
break;
|
||||
case '>': // shift remaining arg val to next arg
|
||||
pbp.add(specarg + val); // push a new argument
|
||||
val = "";
|
||||
break;
|
||||
case '!': // negation option
|
||||
String negopt = (specarg.length() != 0) ? specarg.intern() : opt;
|
||||
properties.remove(negopt);
|
||||
properties.put(negopt, null); // leave placeholder
|
||||
didAction = true;
|
||||
break;
|
||||
case '$': // normal "boolean" option
|
||||
String boolval;
|
||||
if (specarg.length() != 0) {
|
||||
// If there is a given spec token, store it.
|
||||
boolval = specarg;
|
||||
} else {
|
||||
String old = properties.get(opt);
|
||||
if (old == null || old.length() == 0) {
|
||||
boolval = "1";
|
||||
} else {
|
||||
// Increment any previous value as a numeral.
|
||||
boolval = "" + (1 + Integer.parseInt(old));
|
||||
}
|
||||
}
|
||||
properties.put(opt, boolval);
|
||||
didAction = true;
|
||||
break;
|
||||
case '=': // "string" option
|
||||
case '&': // "collection" option
|
||||
// Read an option.
|
||||
boolean append = (specop == '&');
|
||||
String strval;
|
||||
if (pbp.hasPrevious()) {
|
||||
strval = pbp.previous();
|
||||
pbp.remove();
|
||||
} else if (argp.hasNext()) {
|
||||
strval = argp.next();
|
||||
} else {
|
||||
resultString = arg + " ?";
|
||||
isError = true;
|
||||
break eachSpec;
|
||||
}
|
||||
if (append) {
|
||||
String old = properties.get(opt);
|
||||
if (old != null) {
|
||||
// Append new val to old with embedded delim.
|
||||
String delim = specarg;
|
||||
if (delim.length() == 0) {
|
||||
delim = " ";
|
||||
}
|
||||
strval = old + specarg + strval;
|
||||
}
|
||||
}
|
||||
properties.put(opt, strval);
|
||||
didAction = true;
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("bad spec for "
|
||||
+ opt + ": " + spec);
|
||||
}
|
||||
}
|
||||
|
||||
// Done processing specs.
|
||||
if (didAction && !isError) {
|
||||
continue doArgs;
|
||||
}
|
||||
|
||||
// The specs should have done something, but did not.
|
||||
while (pbp.nextIndex() > pbpMark) {
|
||||
// Remove anything pushed during these specs.
|
||||
pbp.previous();
|
||||
pbp.remove();
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
throw new IllegalArgumentException(resultString);
|
||||
}
|
||||
|
||||
if (optlen == 0) {
|
||||
// We cannot try a shorter matching option.
|
||||
break tryOpt;
|
||||
}
|
||||
}
|
||||
|
||||
// If we come here, there was no matching option.
|
||||
// So, push back the argument, and return to caller.
|
||||
pbp.add(arg);
|
||||
break doArgs;
|
||||
}
|
||||
// Report number of arguments consumed.
|
||||
args.subList(0, argp.nextIndex()).clear();
|
||||
// Report any unconsumed partial argument.
|
||||
while (pbp.hasPrevious()) {
|
||||
args.add(0, pbp.previous());
|
||||
}
|
||||
//System.out.println(args+" // "+properties+" -> "+resultString);
|
||||
return resultString;
|
||||
}
|
||||
}
|
@ -0,0 +1,464 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
|
||||
import xmlkit.XMLKit.Element;
|
||||
import java.util.HashMap;
|
||||
/*
|
||||
* @author jrose
|
||||
*/
|
||||
abstract class InstructionAssembler extends InstructionSyntax {
|
||||
|
||||
InstructionAssembler() {
|
||||
}
|
||||
|
||||
public static String assemble(Element instructions, String pcAttrName,
|
||||
ClassSyntax.GetCPIndex getCPI) {
|
||||
int insCount = instructions.size();
|
||||
Element[] insElems = new Element[insCount];
|
||||
int[] elemToIndexMap;
|
||||
int[] insLocs;
|
||||
byte[] ops = new byte[insCount];
|
||||
int[] operands = new int[insCount];
|
||||
boolean[] isWide = new boolean[insCount];
|
||||
int[] branches;
|
||||
int[] branchInsLocs;
|
||||
HashMap<String, String> labels = new HashMap<String, String>();
|
||||
|
||||
final int WIDE = 0xc4;
|
||||
final int GOTO = 0xa7;
|
||||
final int GOTO_W = 0xc8;
|
||||
final int GOTO_LEN = 3;
|
||||
final int GOTO_W_LEN = 5;
|
||||
assert ("wide".equals(bcNames[WIDE]));
|
||||
assert ("goto".equals(bcNames[GOTO]));
|
||||
assert ("goto_w".equals(bcNames[GOTO_W]));
|
||||
assert (bcFormats[GOTO].length() == GOTO_LEN);
|
||||
assert (bcFormats[GOTO_W].length() == GOTO_W_LEN);
|
||||
|
||||
// Unpack instructions into temp. arrays, and find branches and labels.
|
||||
{
|
||||
elemToIndexMap = (pcAttrName != null) ? new int[insCount] : null;
|
||||
int[] buffer = operands;
|
||||
int id = 0;
|
||||
int branchCount = 0;
|
||||
for (int i = 0; i < insCount; i++) {
|
||||
Element ins = (Element) instructions.get(i);
|
||||
if (elemToIndexMap != null) {
|
||||
elemToIndexMap[i] = (ins.getAttr(pcAttrName) != null ? id : -1);
|
||||
}
|
||||
String lab = ins.getAttr("pc");
|
||||
if (lab != null) {
|
||||
labels.put(lab, String.valueOf(id));
|
||||
}
|
||||
int op = opCode(ins.getName());
|
||||
if (op < 0) {
|
||||
assert (ins.getAttr(pcAttrName) != null
|
||||
|| ins.getName().equals("label"));
|
||||
continue; // delete PC holder element
|
||||
}
|
||||
if (op == WIDE) { //0xc4
|
||||
isWide[id] = true; // force wide format
|
||||
continue;
|
||||
}
|
||||
if (bcFormats[op].indexOf('o') >= 0) {
|
||||
buffer[branchCount++] = id;
|
||||
}
|
||||
if (bcFormats[op] == bcWideFormats[op]) {
|
||||
isWide[id] = false;
|
||||
}
|
||||
insElems[id] = ins;
|
||||
ops[id] = (byte) op;
|
||||
id++;
|
||||
}
|
||||
insCount = id; // maybe we deleted some wide prefixes, etc.
|
||||
branches = new int[branchCount + 1];
|
||||
System.arraycopy(buffer, 0, branches, 0, branchCount);
|
||||
branches[branchCount] = -1; // sentinel
|
||||
}
|
||||
|
||||
// Compute instruction sizes. These sizes are final,
|
||||
// except for branch instructions, which may need lengthening.
|
||||
// Some instructions (ldc, bipush, iload, iinc) are automagically widened.
|
||||
insLocs = new int[insCount + 1];
|
||||
int loc = 0;
|
||||
for (int bn = 0, id = 0; id < insCount; id++) {
|
||||
insLocs[id] = loc;
|
||||
Element ins = insElems[id];
|
||||
int op = ops[id] & 0xFF;
|
||||
String format = opFormat(op, isWide[id]);
|
||||
// Make sure operands fit within the given format.
|
||||
for (int j = 1, jlimit = format.length(); j < jlimit; j++) {
|
||||
char fc = format.charAt(j);
|
||||
int x = 0;
|
||||
switch (fc) {
|
||||
case 'l':
|
||||
x = (int) ins.getAttrLong("loc");
|
||||
assert (x >= 0);
|
||||
if (x > 0xFF && !isWide[id]) {
|
||||
isWide[id] = true;
|
||||
format = opFormat(op, isWide[id]);
|
||||
}
|
||||
assert (x <= 0xFFFF);
|
||||
break;
|
||||
case 'k':
|
||||
char fc2 = format.charAt(Math.min(j + 1, format.length() - 1));
|
||||
x = getCPIndex(ins, fc2, getCPI);
|
||||
if (x > 0xFF && j == jlimit - 1) {
|
||||
assert (op == 0x12); //ldc
|
||||
ops[id] = (byte) (op = 0x13); //ldc_w
|
||||
format = opFormat(op);
|
||||
}
|
||||
assert (x <= 0xFFFF);
|
||||
j++; // skip type-of-constant marker
|
||||
break;
|
||||
case 'x':
|
||||
x = (int) ins.getAttrLong("num");
|
||||
assert (x >= 0 && x <= ((j == jlimit - 1) ? 0xFF : 0xFFFF));
|
||||
break;
|
||||
case 's':
|
||||
x = (int) ins.getAttrLong("num");
|
||||
if (x != (byte) x && j == jlimit - 1) {
|
||||
switch (op) {
|
||||
case 0x10: //bipush
|
||||
ops[id] = (byte) (op = 0x11); //sipush
|
||||
break;
|
||||
case 0x84: //iinc
|
||||
isWide[id] = true;
|
||||
format = opFormat(op, isWide[id]);
|
||||
break;
|
||||
default:
|
||||
assert (false); // cannot lengthen
|
||||
}
|
||||
}
|
||||
// unsign the value now, to make later steps clearer
|
||||
if (j == jlimit - 1) {
|
||||
assert (x == (byte) x);
|
||||
x = x & 0xFF;
|
||||
} else {
|
||||
assert (x == (short) x);
|
||||
x = x & 0xFFFF;
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
assert (branches[bn] == id);
|
||||
bn++;
|
||||
// make local copies of the branches, and fix up labels
|
||||
insElems[id] = ins = new Element(ins);
|
||||
String newLab = labels.get(ins.getAttr("lab"));
|
||||
assert (newLab != null);
|
||||
ins.setAttr("lab", newLab);
|
||||
int prevCas = 0;
|
||||
int k = 0;
|
||||
for (Element cas : ins.elements()) {
|
||||
assert (cas.getName().equals("Case"));
|
||||
ins.set(k++, cas = new Element(cas));
|
||||
newLab = labels.get(cas.getAttr("lab"));
|
||||
assert (newLab != null);
|
||||
cas.setAttr("lab", newLab);
|
||||
int thisCas = (int) cas.getAttrLong("num");
|
||||
assert (op == 0xab
|
||||
|| op == 0xaa && (k == 0 || thisCas == prevCas + 1));
|
||||
prevCas = thisCas;
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
// switch table is represented as Switch.Case sub-elements
|
||||
break;
|
||||
default:
|
||||
assert (false);
|
||||
}
|
||||
operands[id] = x; // record operand (last if there are 2)
|
||||
// skip redundant chars
|
||||
while (j + 1 < jlimit && format.charAt(j + 1) == fc) {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case 0xaa: //tableswitch
|
||||
loc = switchBase(loc);
|
||||
loc += 4 * (3 + ins.size());
|
||||
break;
|
||||
case 0xab: //lookupswitch
|
||||
loc = switchBase(loc);
|
||||
loc += 4 * (2 + 2 * ins.size());
|
||||
break;
|
||||
default:
|
||||
if (isWide[id]) {
|
||||
loc++; // 'wide' opcode prefix
|
||||
}
|
||||
loc += format.length();
|
||||
break;
|
||||
}
|
||||
}
|
||||
insLocs[insCount] = loc;
|
||||
|
||||
// compute branch offsets, and see if any branches need expansion
|
||||
for (int maxTries = 9, tries = 0;; ++tries) {
|
||||
boolean overflowing = false;
|
||||
boolean[] branchExpansions = null;
|
||||
for (int bn = 0; bn < branches.length - 1; bn++) {
|
||||
int id = branches[bn];
|
||||
Element ins = insElems[id];
|
||||
int insSize = insLocs[id + 1] - insLocs[id];
|
||||
int origin = insLocs[id];
|
||||
int target = insLocs[(int) ins.getAttrLong("lab")];
|
||||
int offset = target - origin;
|
||||
operands[id] = offset;
|
||||
//System.out.println("branch id="+id+" len="+insSize+" to="+target+" offset="+offset);
|
||||
assert (insSize == GOTO_LEN || insSize == GOTO_W_LEN || ins.getName().indexOf("switch") > 0);
|
||||
boolean thisOverflow = (insSize == GOTO_LEN && (offset != (short) offset));
|
||||
if (thisOverflow && !overflowing) {
|
||||
overflowing = true;
|
||||
branchExpansions = new boolean[branches.length];
|
||||
}
|
||||
if (thisOverflow || tries == maxTries - 1) {
|
||||
// lengthen the branch
|
||||
assert (!(thisOverflow && isWide[id]));
|
||||
isWide[id] = true;
|
||||
branchExpansions[bn] = true;
|
||||
}
|
||||
}
|
||||
if (!overflowing) {
|
||||
break; // done, usually on first try
|
||||
}
|
||||
assert (tries <= maxTries);
|
||||
|
||||
// Walk over all instructions, expanding branches and updating locations.
|
||||
int fixup = 0;
|
||||
for (int bn = 0, id = 0; id < insCount; id++) {
|
||||
insLocs[id] += fixup;
|
||||
if (branches[bn] == id) {
|
||||
int op = ops[id] & 0xFF;
|
||||
int wop;
|
||||
boolean invert;
|
||||
if (branchExpansions[bn]) {
|
||||
switch (op) {
|
||||
case GOTO: //0xa7
|
||||
wop = GOTO_W; //0xc8
|
||||
invert = false;
|
||||
break;
|
||||
case 0xa8: //jsr
|
||||
wop = 0xc9; //jsr_w
|
||||
invert = false;
|
||||
break;
|
||||
default:
|
||||
wop = invertBranchOp(op);
|
||||
invert = true;
|
||||
break;
|
||||
}
|
||||
assert (op != wop);
|
||||
ops[id] = (byte) wop;
|
||||
isWide[id] = invert;
|
||||
if (invert) {
|
||||
fixup += GOTO_W_LEN; //branch around a wide goto
|
||||
} else {
|
||||
fixup += (GOTO_W_LEN - GOTO_LEN);
|
||||
}
|
||||
// done expanding: ops and isWide reflect the decision
|
||||
}
|
||||
bn++;
|
||||
}
|
||||
}
|
||||
insLocs[insCount] += fixup;
|
||||
}
|
||||
// we know the layout now
|
||||
|
||||
// notify the caller of offsets, if requested
|
||||
if (elemToIndexMap != null) {
|
||||
for (int i = 0; i < elemToIndexMap.length; i++) {
|
||||
int id = elemToIndexMap[i];
|
||||
if (id >= 0) {
|
||||
Element ins = (Element) instructions.get(i);
|
||||
ins.setAttr(pcAttrName, "" + insLocs[id]);
|
||||
}
|
||||
}
|
||||
elemToIndexMap = null; // release the pointer
|
||||
}
|
||||
|
||||
// output the bytes
|
||||
StringBuffer sbuf = new StringBuffer(insLocs[insCount]);
|
||||
for (int bn = 0, id = 0; id < insCount; id++) {
|
||||
//System.out.println("output id="+id+" loc="+insLocs[id]+" len="+(insLocs[id+1]-insLocs[id])+" #sbuf="+sbuf.length());
|
||||
assert (sbuf.length() == insLocs[id]);
|
||||
Element ins;
|
||||
int pc = insLocs[id];
|
||||
int nextpc = insLocs[id + 1];
|
||||
int op = ops[id] & 0xFF;
|
||||
int opnd = operands[id];
|
||||
String format;
|
||||
if (branches[bn] == id) {
|
||||
bn++;
|
||||
sbuf.append((char) op);
|
||||
if (isWide[id]) {
|
||||
// emit <ifop lab=1f> <goto_w target> <label pc=1f>
|
||||
int target = pc + opnd;
|
||||
putInt(sbuf, nextpc - pc, -2);
|
||||
assert (sbuf.length() == pc + GOTO_LEN);
|
||||
sbuf.append((char) GOTO_W);
|
||||
putInt(sbuf, target - (pc + GOTO_LEN), 4);
|
||||
} else if (op == 0xaa || //tableswitch
|
||||
op == 0xab) { //lookupswitch
|
||||
ins = insElems[id];
|
||||
for (int pad = switchBase(pc) - (pc + 1); pad > 0; pad--) {
|
||||
sbuf.append((char) 0);
|
||||
}
|
||||
assert (pc + opnd == insLocs[(int) ins.getAttrLong("lab")]);
|
||||
putInt(sbuf, opnd, 4); // default label
|
||||
if (op == 0xaa) { //tableswitch
|
||||
Element cas0 = (Element) ins.get(0);
|
||||
int lowCase = (int) cas0.getAttrLong("num");
|
||||
Element casN = (Element) ins.get(ins.size() - 1);
|
||||
int highCase = (int) casN.getAttrLong("num");
|
||||
assert (highCase - lowCase + 1 == ins.size());
|
||||
putInt(sbuf, lowCase, 4);
|
||||
putInt(sbuf, highCase, 4);
|
||||
int caseForAssert = lowCase;
|
||||
for (Element cas : ins.elements()) {
|
||||
int target = insLocs[(int) cas.getAttrLong("lab")];
|
||||
assert (cas.getAttrLong("num") == caseForAssert++);
|
||||
putInt(sbuf, target - pc, 4);
|
||||
}
|
||||
} else { //lookupswitch
|
||||
int caseCount = ins.size();
|
||||
putInt(sbuf, caseCount, 4);
|
||||
for (Element cas : ins.elements()) {
|
||||
int target = insLocs[(int) cas.getAttrLong("lab")];
|
||||
putInt(sbuf, (int) cas.getAttrLong("num"), 4);
|
||||
putInt(sbuf, target - pc, 4);
|
||||
}
|
||||
}
|
||||
assert (nextpc == sbuf.length());
|
||||
} else {
|
||||
putInt(sbuf, opnd, -(nextpc - (pc + 1)));
|
||||
}
|
||||
} else if (nextpc == pc + 1) {
|
||||
// a single-byte instruction
|
||||
sbuf.append((char) op);
|
||||
} else {
|
||||
// picky stuff
|
||||
boolean wide = isWide[id];
|
||||
if (wide) {
|
||||
sbuf.append((char) WIDE);
|
||||
pc++;
|
||||
}
|
||||
sbuf.append((char) op);
|
||||
int opnd1;
|
||||
int opnd2 = opnd;
|
||||
switch (op) {
|
||||
case 0x84: //iinc
|
||||
ins = insElems[id];
|
||||
opnd1 = (int) ins.getAttrLong("loc");
|
||||
if (isWide[id]) {
|
||||
putInt(sbuf, opnd1, 2);
|
||||
putInt(sbuf, opnd2, 2);
|
||||
} else {
|
||||
putInt(sbuf, opnd1, 1);
|
||||
putInt(sbuf, opnd2, 1);
|
||||
}
|
||||
break;
|
||||
case 0xc5: //multianewarray
|
||||
ins = insElems[id];
|
||||
opnd1 = getCPIndex(ins, 'c', getCPI);
|
||||
putInt(sbuf, opnd1, 2);
|
||||
putInt(sbuf, opnd2, 1);
|
||||
break;
|
||||
case 0xb9: //invokeinterface
|
||||
ins = insElems[id];
|
||||
opnd1 = getCPIndex(ins, 'n', getCPI);
|
||||
putInt(sbuf, opnd1, 2);
|
||||
opnd2 = (int) ins.getAttrLong("num");
|
||||
if (opnd2 == 0) {
|
||||
opnd2 = ClassSyntax.computeInterfaceNum(ins.getAttr("val"));
|
||||
}
|
||||
putInt(sbuf, opnd2, 2);
|
||||
break;
|
||||
default:
|
||||
// put the single operand and be done
|
||||
putInt(sbuf, opnd, nextpc - (pc + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert (sbuf.length() == insLocs[insCount]);
|
||||
|
||||
return sbuf.toString();
|
||||
}
|
||||
|
||||
static int getCPIndex(Element ins, char ctype,
|
||||
ClassSyntax.GetCPIndex getCPI) {
|
||||
int x = (int) ins.getAttrLong("ref");
|
||||
if (x == 0 && getCPI != null) {
|
||||
String val = ins.getAttr("val");
|
||||
if (val == null || val.equals("")) {
|
||||
val = ins.getText().toString();
|
||||
}
|
||||
byte tag;
|
||||
switch (ctype) {
|
||||
case 'k':
|
||||
tag = (byte) ins.getAttrLong("tag");
|
||||
break;
|
||||
case 'c':
|
||||
tag = ClassSyntax.CONSTANT_Class;
|
||||
break;
|
||||
case 'f':
|
||||
tag = ClassSyntax.CONSTANT_Fieldref;
|
||||
break;
|
||||
case 'm':
|
||||
tag = ClassSyntax.CONSTANT_Methodref;
|
||||
break;
|
||||
case 'n':
|
||||
tag = ClassSyntax.CONSTANT_InterfaceMethodref;
|
||||
break;
|
||||
default:
|
||||
throw new Error("bad ctype " + ctype + " in " + ins);
|
||||
}
|
||||
x = getCPI.getCPIndex(tag, val);
|
||||
//System.out.println("getCPIndex "+ins+" => "+tag+"/"+val+" => "+x);
|
||||
} else {
|
||||
assert (x > 0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static void putInt(StringBuffer sbuf, int x, int len) {
|
||||
//System.out.println("putInt x="+x+" len="+len);
|
||||
boolean isSigned = false;
|
||||
if (len < 0) {
|
||||
len = -len;
|
||||
isSigned = true;
|
||||
}
|
||||
assert (len == 1 || len == 2 || len == 4);
|
||||
int insig = ((4 - len) * 8); // how many insignificant bits?
|
||||
int sx = x << insig;
|
||||
;
|
||||
assert (x == (isSigned ? (sx >> insig) : (sx >>> insig)));
|
||||
for (int i = 0; i < len; i++) {
|
||||
sbuf.append((char) (sx >>> 24));
|
||||
sx <<= 8;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
|
||||
import xmlkit.XMLKit.Element;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
/*
|
||||
* @author jrose
|
||||
*/
|
||||
public abstract class InstructionSyntax {
|
||||
|
||||
InstructionSyntax() {
|
||||
}
|
||||
static final String[] bcNames;
|
||||
static final String[] bcFormats;
|
||||
static final String[] bcWideFormats;
|
||||
static final HashMap<String, Integer> bcCodes;
|
||||
static final HashMap<String, Element> abbrevs;
|
||||
static final HashMap<Element, String> rabbrevs;
|
||||
|
||||
static {
|
||||
TokenList tl = new TokenList(
|
||||
" nop aconst_null iconst_m1 iconst_0 iconst_1 iconst_2 iconst_3"
|
||||
+ " iconst_4 iconst_5 lconst_0 lconst_1 fconst_0 fconst_1 fconst_2"
|
||||
+ " dconst_0 dconst_1 bipush/s sipush/ss ldc/k ldc_w/kk ldc2_w/kk"
|
||||
+ " iload/wl lload/wl fload/wl dload/wl aload/wl iload_0 iload_1"
|
||||
+ " iload_2 iload_3 lload_0 lload_1 lload_2 lload_3 fload_0 fload_1"
|
||||
+ " fload_2 fload_3 dload_0 dload_1 dload_2 dload_3 aload_0 aload_1"
|
||||
+ " aload_2 aload_3 iaload laload faload daload aaload baload caload"
|
||||
+ " saload istore/wl lstore/wl fstore/wl dstore/wl astore/wl"
|
||||
+ " istore_0 istore_1 istore_2 istore_3 lstore_0 lstore_1 lstore_2"
|
||||
+ " lstore_3 fstore_0 fstore_1 fstore_2 fstore_3 dstore_0 dstore_1"
|
||||
+ " dstore_2 dstore_3 astore_0 astore_1 astore_2 astore_3 iastore"
|
||||
+ " lastore fastore dastore aastore bastore castore sastore pop pop2"
|
||||
+ " dup dup_x1 dup_x2 dup2 dup2_x1 dup2_x2 swap iadd ladd fadd dadd"
|
||||
+ " isub lsub fsub dsub imul lmul fmul dmul idiv ldiv fdiv ddiv irem"
|
||||
+ " lrem frem drem ineg lneg fneg dneg ishl lshl ishr lshr iushr"
|
||||
+ " lushr iand land ior lor ixor lxor iinc/wls i2l i2f i2d l2i l2f"
|
||||
+ " l2d f2i f2l f2d d2i d2l d2f i2b i2c i2s lcmp fcmpl fcmpg dcmpl"
|
||||
+ " dcmpg ifeq/oo ifne/oo iflt/oo ifge/oo ifgt/oo ifle/oo"
|
||||
+ " if_icmpeq/oo if_icmpne/oo if_icmplt/oo if_icmpge/oo if_icmpgt/oo"
|
||||
+ " if_icmple/oo if_acmpeq/oo if_acmpne/oo goto/oo jsr/oo ret/wl"
|
||||
+ " tableswitch/oooot lookupswitch/oooot ireturn lreturn freturn dreturn areturn"
|
||||
+ " return getstatic/kf putstatic/kf getfield/kf putfield/kf"
|
||||
+ " invokevirtual/km invokespecial/km invokestatic/km"
|
||||
+ " invokeinterface/knxx xxxunusedxxx new/kc newarray/x anewarray/kc"
|
||||
+ " arraylength athrow checkcast/kc instanceof/kc monitorenter"
|
||||
+ " monitorexit wide multianewarray/kcx ifnull/oo ifnonnull/oo"
|
||||
+ " goto_w/oooo jsr_w/oooo");
|
||||
assert (tl.size() == 202); // this many instructions!
|
||||
HashMap<String, Integer> map = new HashMap<String, Integer>(tl.size());
|
||||
String[] names = tl.toArray(new String[tl.size()]);
|
||||
String[] formats = new String[names.length];
|
||||
String[] wideFormats = new String[names.length];
|
||||
StringBuilder sbuf = new StringBuilder();
|
||||
sbuf.append('i'); // all op formats begin with "i"
|
||||
int i = 0;
|
||||
for (String ins : names) {
|
||||
assert (ins == ins.trim()); // no whitespace
|
||||
int sfx = ins.indexOf('/');
|
||||
String format = "i";
|
||||
String wideFormat = null;
|
||||
if (sfx >= 0) {
|
||||
format = ins.substring(sfx + 1);
|
||||
ins = ins.substring(0, sfx);
|
||||
if (format.charAt(0) == 'w') {
|
||||
format = format.substring(1);
|
||||
sbuf.setLength(1);
|
||||
for (int j = 0; j < format.length(); j++) {
|
||||
// double everything except the initial 'i'
|
||||
sbuf.append(format.charAt(j));
|
||||
sbuf.append(format.charAt(j));
|
||||
}
|
||||
wideFormat = sbuf.toString().intern();
|
||||
}
|
||||
sbuf.setLength(1);
|
||||
sbuf.append(format);
|
||||
format = sbuf.toString().intern();
|
||||
}
|
||||
ins = ins.intern();
|
||||
names[i] = ins;
|
||||
formats[i] = format;
|
||||
wideFormats[i] = (wideFormat != null) ? wideFormat : format;
|
||||
//System.out.println(ins+" "+format+" "+wideFormat);
|
||||
map.put(ins, i++);
|
||||
}
|
||||
//map = Collections.unmodifiableMap(map);
|
||||
|
||||
HashMap<String, Element> abb = new HashMap<String, Element>(tl.size() / 2);
|
||||
abb.put("iconst_m1", new Element("bipush", "num", "-1"));
|
||||
for (String ins : names) {
|
||||
int sfx = ins.indexOf('_');
|
||||
if (sfx >= 0 && Character.isDigit(ins.charAt(sfx + 1))) {
|
||||
String pfx = ins.substring(0, sfx).intern();
|
||||
String num = ins.substring(sfx + 1);
|
||||
String att = pfx.endsWith("const") ? "num" : "loc";
|
||||
Element exp = new Element(pfx, att, num).deepFreeze();
|
||||
abb.put(ins, exp);
|
||||
}
|
||||
}
|
||||
//abb = Collections.unmodifiableMap(abb);
|
||||
HashMap<Element, String> rabb = new HashMap<Element, String>(tl.size() / 2);
|
||||
for (Map.Entry<String, Element> e : abb.entrySet()) {
|
||||
rabb.put(e.getValue(), e.getKey());
|
||||
}
|
||||
//rabb = Collections.unmodifiableMap(rabb);
|
||||
|
||||
|
||||
bcNames = names;
|
||||
bcFormats = formats;
|
||||
bcWideFormats = wideFormats;
|
||||
bcCodes = map;
|
||||
abbrevs = abb;
|
||||
rabbrevs = rabb;
|
||||
}
|
||||
|
||||
public static String opName(int op) {
|
||||
if (op >= 0 && op < bcNames.length) {
|
||||
return bcNames[op];
|
||||
}
|
||||
return "unknown#" + op;
|
||||
}
|
||||
|
||||
public static String opFormat(int op) {
|
||||
return opFormat(op, false);
|
||||
}
|
||||
|
||||
public static String opFormat(int op, boolean isWide) {
|
||||
if (op >= 0 && op < bcFormats.length) {
|
||||
return (isWide ? bcWideFormats[op] : bcFormats[op]);
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
public static int opCode(String opName) {
|
||||
Integer op = (Integer) bcCodes.get(opName);
|
||||
if (op != null) {
|
||||
return op.intValue();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static Element expandAbbrev(String opName) {
|
||||
return abbrevs.get(opName);
|
||||
}
|
||||
|
||||
public static String findAbbrev(Element op) {
|
||||
return rabbrevs.get(op);
|
||||
}
|
||||
|
||||
public static int invertBranchOp(int op) {
|
||||
assert (opFormat(op).indexOf('o') >= 0);
|
||||
final int IFMIN = 0x99;
|
||||
final int IFMAX = 0xa6;
|
||||
final int IFMIN2 = 0xc6;
|
||||
final int IFMAX2 = 0xc7;
|
||||
assert (bcNames[IFMIN] == "ifeq");
|
||||
assert (bcNames[IFMAX] == "if_acmpne");
|
||||
assert (bcNames[IFMIN2] == "ifnonnull");
|
||||
assert (bcNames[IFMAX2] == "ifnull");
|
||||
int rop;
|
||||
if (op >= IFMIN && op <= IFMAX) {
|
||||
rop = IFMIN + ((op - IFMIN) ^ 1);
|
||||
} else if (op >= IFMIN2 && op <= IFMAX2) {
|
||||
rop = IFMIN2 + ((op - IFMIN2) ^ 1);
|
||||
} else {
|
||||
assert (false);
|
||||
rop = op;
|
||||
}
|
||||
assert (opFormat(rop).indexOf('o') >= 0);
|
||||
return rop;
|
||||
}
|
||||
|
||||
public static Element parse(String bytes) {
|
||||
Element e = new Element("Instructions", bytes.length());
|
||||
boolean willBeWide;
|
||||
boolean isWide = false;
|
||||
Element[] tempMap = new Element[bytes.length()];
|
||||
for (int pc = 0, nextpc; pc < bytes.length(); pc = nextpc) {
|
||||
int op = bytes.charAt(pc);
|
||||
Element i = new Element(opName(op));
|
||||
|
||||
nextpc = pc + 1;
|
||||
int locarg = 0;
|
||||
int cparg = 0;
|
||||
int intarg = 0;
|
||||
int labelarg = 0;
|
||||
|
||||
willBeWide = false;
|
||||
switch (op) {
|
||||
case 0xc4: //wide
|
||||
willBeWide = true;
|
||||
break;
|
||||
case 0x10: //bipush
|
||||
intarg = nextpc++;
|
||||
intarg *= -1; //mark signed
|
||||
break;
|
||||
case 0x11: //sipush
|
||||
intarg = nextpc;
|
||||
nextpc += 2;
|
||||
intarg *= -1; //mark signed
|
||||
break;
|
||||
case 0x12: //ldc
|
||||
cparg = nextpc++;
|
||||
break;
|
||||
case 0x13: //ldc_w
|
||||
case 0x14: //ldc2_w
|
||||
case 0xb2: //getstatic
|
||||
case 0xb3: //putstatic
|
||||
case 0xb4: //getfield
|
||||
case 0xb5: //putfield
|
||||
case 0xb6: //invokevirtual
|
||||
case 0xb7: //invokespecial
|
||||
case 0xb8: //invokestatic
|
||||
case 0xbb: //new
|
||||
case 0xbd: //anewarray
|
||||
case 0xc0: //checkcast
|
||||
case 0xc1: //instanceof
|
||||
cparg = nextpc;
|
||||
nextpc += 2;
|
||||
break;
|
||||
case 0xb9: //invokeinterface
|
||||
cparg = nextpc;
|
||||
nextpc += 2;
|
||||
intarg = nextpc;
|
||||
nextpc += 2;
|
||||
break;
|
||||
case 0xc5: //multianewarray
|
||||
cparg = nextpc;
|
||||
nextpc += 2;
|
||||
intarg = nextpc++;
|
||||
break;
|
||||
case 0x15: //iload
|
||||
case 0x16: //lload
|
||||
case 0x17: //fload
|
||||
case 0x18: //dload
|
||||
case 0x19: //aload
|
||||
case 0x36: //istore
|
||||
case 0x37: //lstore
|
||||
case 0x38: //fstore
|
||||
case 0x39: //dstore
|
||||
case 0x3a: //astore
|
||||
case 0xa9: //ret
|
||||
locarg = nextpc++;
|
||||
if (isWide) {
|
||||
nextpc++;
|
||||
}
|
||||
break;
|
||||
case 0x84: //iinc
|
||||
locarg = nextpc++;
|
||||
if (isWide) {
|
||||
nextpc++;
|
||||
}
|
||||
intarg = nextpc++;
|
||||
if (isWide) {
|
||||
nextpc++;
|
||||
}
|
||||
intarg *= -1; //mark signed
|
||||
break;
|
||||
case 0x99: //ifeq
|
||||
case 0x9a: //ifne
|
||||
case 0x9b: //iflt
|
||||
case 0x9c: //ifge
|
||||
case 0x9d: //ifgt
|
||||
case 0x9e: //ifle
|
||||
case 0x9f: //if_icmpeq
|
||||
case 0xa0: //if_icmpne
|
||||
case 0xa1: //if_icmplt
|
||||
case 0xa2: //if_icmpge
|
||||
case 0xa3: //if_icmpgt
|
||||
case 0xa4: //if_icmple
|
||||
case 0xa5: //if_acmpeq
|
||||
case 0xa6: //if_acmpne
|
||||
case 0xa7: //goto
|
||||
case 0xa8: //jsr
|
||||
labelarg = nextpc;
|
||||
nextpc += 2;
|
||||
break;
|
||||
case 0xbc: //newarray
|
||||
intarg = nextpc++;
|
||||
break;
|
||||
case 0xc6: //ifnull
|
||||
case 0xc7: //ifnonnull
|
||||
labelarg = nextpc;
|
||||
nextpc += 2;
|
||||
break;
|
||||
case 0xc8: //goto_w
|
||||
case 0xc9: //jsr_w
|
||||
labelarg = nextpc;
|
||||
nextpc += 4;
|
||||
break;
|
||||
|
||||
// save the best for last:
|
||||
case 0xaa: //tableswitch
|
||||
nextpc = parseSwitch(bytes, pc, true, i);
|
||||
break;
|
||||
case 0xab: //lookupswitch
|
||||
nextpc = parseSwitch(bytes, pc, false, i);
|
||||
break;
|
||||
}
|
||||
|
||||
String format = null;
|
||||
assert ((format = opFormat(op, isWide)) != null);
|
||||
//System.out.println("pc="+pc+" len="+(nextpc - pc)+" w="+isWide+" op="+op+" name="+opName(op)+" format="+format);
|
||||
assert ((nextpc - pc) == format.length() || format.indexOf('t') >= 0);
|
||||
|
||||
// Parse out instruction fields.
|
||||
if (locarg != 0) {
|
||||
int len = nextpc - locarg;
|
||||
if (intarg != 0) {
|
||||
len /= 2; // split
|
||||
}
|
||||
i.setAttr("loc", "" + getInt(bytes, locarg, len));
|
||||
assert ('l' == format.charAt(locarg - pc + 0));
|
||||
assert ('l' == format.charAt(locarg - pc + len - 1));
|
||||
}
|
||||
if (cparg != 0) {
|
||||
int len = nextpc - cparg;
|
||||
if (len > 2) {
|
||||
len = 2;
|
||||
}
|
||||
i.setAttr("ref", "" + getInt(bytes, cparg, len));
|
||||
assert ('k' == format.charAt(cparg - pc + 0));
|
||||
}
|
||||
if (intarg != 0) {
|
||||
boolean isSigned = (intarg < 0);
|
||||
if (isSigned) {
|
||||
intarg *= -1;
|
||||
}
|
||||
int len = nextpc - intarg;
|
||||
i.setAttr("num", "" + getInt(bytes, intarg, isSigned ? -len : len));
|
||||
assert ((isSigned ? 's' : 'x') == format.charAt(intarg - pc + 0));
|
||||
assert ((isSigned ? 's' : 'x') == format.charAt(intarg - pc + len - 1));
|
||||
}
|
||||
if (labelarg != 0) {
|
||||
int len = nextpc - labelarg;
|
||||
int offset = getInt(bytes, labelarg, -len);
|
||||
int target = pc + offset;
|
||||
i.setAttr("lab", "" + target);
|
||||
assert ('o' == format.charAt(labelarg - pc + 0));
|
||||
assert ('o' == format.charAt(labelarg - pc + len - 1));
|
||||
}
|
||||
|
||||
e.add(i);
|
||||
tempMap[pc] = i;
|
||||
isWide = willBeWide;
|
||||
}
|
||||
|
||||
// Mark targets of branches.
|
||||
for (Element i : e.elements()) {
|
||||
for (int j = -1; j < i.size(); j++) {
|
||||
Element c = (j < 0) ? i : (Element) i.get(j);
|
||||
Number targetNum = c.getAttrNumber("lab");
|
||||
if (targetNum != null) {
|
||||
int target = targetNum.intValue();
|
||||
Element ti = null;
|
||||
if (target >= 0 && target < tempMap.length) {
|
||||
ti = tempMap[target];
|
||||
}
|
||||
if (ti != null) {
|
||||
ti.setAttr("pc", "" + target);
|
||||
} else {
|
||||
c.setAttr("lab.error", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shrink to fit:
|
||||
for (Element i : e.elements()) {
|
||||
i.trimToSize();
|
||||
}
|
||||
e.trimToSize();
|
||||
|
||||
/*
|
||||
String assem = assemble(e);
|
||||
if (!assem.equals(bytes)) {
|
||||
System.out.println("Bytes: "+bytes);
|
||||
System.out.println("Insns: "+e);
|
||||
System.out.println("Assem: "+parse(assem));
|
||||
}
|
||||
*/
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static int switchBase(int pc) {
|
||||
int apc = pc + 1;
|
||||
apc += (-apc) & 3;
|
||||
return apc;
|
||||
}
|
||||
|
||||
static int parseSwitch(String s, int pc, boolean isTable, Element i) {
|
||||
int apc = switchBase(pc);
|
||||
int defLabel = pc + getInt(s, apc + 4 * 0, 4);
|
||||
i.setAttr("lab", "" + defLabel);
|
||||
if (isTable) {
|
||||
int lowCase = getInt(s, apc + 4 * 1, 4);
|
||||
int highCase = getInt(s, apc + 4 * 2, 4);
|
||||
int caseCount = highCase - lowCase + 1;
|
||||
for (int n = 0; n < caseCount; n++) {
|
||||
Element c = new Element("Case", 4);
|
||||
int caseVal = lowCase + n;
|
||||
int caseLab = getInt(s, apc + 4 * (3 + n), 4) + pc;
|
||||
c.setAttr("num", "" + caseVal);
|
||||
c.setAttr("lab", "" + caseLab);
|
||||
assert (c.getExtraCapacity() == 0);
|
||||
i.add(c);
|
||||
}
|
||||
return apc + 4 * (3 + caseCount);
|
||||
} else {
|
||||
int caseCount = getInt(s, apc + 4 * 1, 4);
|
||||
for (int n = 0; n < caseCount; n++) {
|
||||
Element c = new Element("Case", 4);
|
||||
int caseVal = getInt(s, apc + 4 * (2 + (2 * n) + 0), 4);
|
||||
int caseLab = getInt(s, apc + 4 * (2 + (2 * n) + 1), 4) + pc;
|
||||
c.setAttr("num", "" + caseVal);
|
||||
c.setAttr("lab", "" + caseLab);
|
||||
assert (c.getExtraCapacity() == 0);
|
||||
i.add(c);
|
||||
}
|
||||
return apc + 4 * (2 + 2 * caseCount);
|
||||
}
|
||||
}
|
||||
|
||||
static int getInt(String s, int pc, int len) {
|
||||
//System.out.println("getInt s["+s.length()+"] pc="+pc+" len="+len);
|
||||
int result = s.charAt(pc);
|
||||
if (len < 0) {
|
||||
len = -len;
|
||||
result = (byte) result;
|
||||
}
|
||||
if (!(len == 1 || len == 2 || len == 4)) {
|
||||
System.out.println("len=" + len);
|
||||
}
|
||||
assert (len == 1 || len == 2 || len == 4);
|
||||
for (int i = 1; i < len; i++) {
|
||||
result <<= 8;
|
||||
result += s.charAt(pc + i) & 0xFF;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String assemble(Element instructions) {
|
||||
return InstructionAssembler.assemble(instructions, null, null);
|
||||
}
|
||||
|
||||
public static String assemble(Element instructions, String pcAttrName) {
|
||||
return InstructionAssembler.assemble(instructions, pcAttrName, null);
|
||||
}
|
||||
|
||||
public static String assemble(Element instructions, ClassSyntax.GetCPIndex getCPI) {
|
||||
return InstructionAssembler.assemble(instructions, null, getCPI);
|
||||
}
|
||||
|
||||
public static String assemble(Element instructions, String pcAttrName,
|
||||
ClassSyntax.GetCPIndex getCPI) {
|
||||
return InstructionAssembler.assemble(instructions, pcAttrName, getCPI);
|
||||
}
|
||||
}
|
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package xmlkit; // -*- mode: java; indent-tabs-mode: nil -*-
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A List of Strings each representing a word or token.
|
||||
* This object itself is a CharSequence whose characters consist
|
||||
* of all the tokens, separated by blanks.
|
||||
*
|
||||
* @author jrose
|
||||
*/
|
||||
public class TokenList extends ArrayList<String> implements CharSequence {
|
||||
|
||||
protected String separator;
|
||||
protected boolean frozen;
|
||||
|
||||
public TokenList() {
|
||||
this.separator = " ";
|
||||
}
|
||||
|
||||
public TokenList(Collection<? extends Object> tokens) {
|
||||
super(tokens.size());
|
||||
this.separator = " ";
|
||||
addTokens(tokens);
|
||||
}
|
||||
|
||||
public TokenList(Collection<? extends Object> tokens, String separator) {
|
||||
super(tokens.size());
|
||||
this.separator = separator;
|
||||
addTokens(tokens);
|
||||
}
|
||||
|
||||
public TokenList(Object[] tokens) {
|
||||
super(tokens.length);
|
||||
this.separator = " ";
|
||||
addTokens(tokens, 0, tokens.length);
|
||||
}
|
||||
|
||||
public TokenList(Object[] tokens, int beg, int end) {
|
||||
super(end - beg); // capacity
|
||||
this.separator = " ";
|
||||
addTokens(tokens, beg, end);
|
||||
}
|
||||
|
||||
public TokenList(Object[] tokens, int beg, int end, String separator) {
|
||||
super(end - beg); // capacity
|
||||
this.separator = separator;
|
||||
addTokens(tokens, beg, end);
|
||||
}
|
||||
|
||||
public TokenList(String tokenStr) {
|
||||
this(tokenStr, " ", false);
|
||||
}
|
||||
|
||||
public TokenList(String tokenStr, String separator) {
|
||||
this(tokenStr, separator, true);
|
||||
}
|
||||
|
||||
public TokenList(String tokenStr, String separator, boolean allowNulls) {
|
||||
super(tokenStr.length() / 5);
|
||||
this.separator = separator;
|
||||
addTokens(tokenStr, allowNulls);
|
||||
}
|
||||
static public final TokenList EMPTY;
|
||||
|
||||
static {
|
||||
TokenList tl = new TokenList(new Object[0]);
|
||||
tl.freeze();
|
||||
EMPTY = tl;
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
if (!frozen) {
|
||||
for (ListIterator<String> i = listIterator(); i.hasNext();) {
|
||||
i.set(i.next().toString());
|
||||
}
|
||||
trimToSize();
|
||||
frozen = true;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isFrozen() {
|
||||
return frozen;
|
||||
}
|
||||
|
||||
void checkNotFrozen() {
|
||||
if (isFrozen()) {
|
||||
throw new UnsupportedOperationException("cannot modify frozen TokenList");
|
||||
}
|
||||
}
|
||||
|
||||
public String getSeparator() {
|
||||
return separator;
|
||||
}
|
||||
|
||||
public void setSeparator(String separator) {
|
||||
checkNotFrozen();
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
/// All normal List mutators must check the frozen bit:
|
||||
public String set(int index, String o) {
|
||||
checkNotFrozen();
|
||||
return super.set(index, o);
|
||||
}
|
||||
|
||||
public boolean add(String o) {
|
||||
checkNotFrozen();
|
||||
return super.add(o);
|
||||
}
|
||||
|
||||
public void add(int index, String o) {
|
||||
checkNotFrozen();
|
||||
super.add(index, o);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends String> c) {
|
||||
checkNotFrozen();
|
||||
return super.addAll(c);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends String> c) {
|
||||
checkNotFrozen();
|
||||
return super.addAll(index, c);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
checkNotFrozen();
|
||||
return super.remove(o);
|
||||
}
|
||||
|
||||
public String remove(int index) {
|
||||
checkNotFrozen();
|
||||
return super.remove(index);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
checkNotFrozen();
|
||||
super.clear();
|
||||
}
|
||||
|
||||
/** Add a collection of tokens to the list, applying toString to each. */
|
||||
public boolean addTokens(Collection<? extends Object> tokens) {
|
||||
// Note that if this sequence is empty, no tokens are added.
|
||||
// This is different from adding a null string, which is
|
||||
// a single token.
|
||||
boolean added = false;
|
||||
for (Object token : tokens) {
|
||||
add(token.toString());
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean addTokens(Object[] tokens, int beg, int end) {
|
||||
boolean added = false;
|
||||
for (int i = beg; i < end; i++) {
|
||||
add(tokens[i].toString());
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean addTokens(String tokenStr) {
|
||||
return addTokens(tokenStr, false);
|
||||
}
|
||||
|
||||
public boolean addTokens(String tokenStr, boolean allowNulls) {
|
||||
boolean added = false;
|
||||
int pos = 0, limit = tokenStr.length(), sep = limit;
|
||||
while (pos < limit) {
|
||||
sep = tokenStr.indexOf(separator, pos);
|
||||
if (sep < 0) {
|
||||
sep = limit;
|
||||
}
|
||||
if (sep == pos) {
|
||||
if (allowNulls) {
|
||||
add("");
|
||||
added = true;
|
||||
}
|
||||
pos += separator.length();
|
||||
} else {
|
||||
add(tokenStr.substring(pos, sep));
|
||||
added = true;
|
||||
pos = sep + separator.length();
|
||||
}
|
||||
}
|
||||
if (allowNulls && sep < limit) {
|
||||
// Input was something like "tok1 tok2 ".
|
||||
add("");
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean addToken(Object token) {
|
||||
return add(token.toString());
|
||||
}
|
||||
|
||||
/** Format the token string, using quotes and escapes.
|
||||
* Quotes must contain an odd number of 3 or more elements,
|
||||
* a sequence of begin/end quote pairs, plus a superquote.
|
||||
* For each token, the first begin/end pair is used for
|
||||
* which the end quote does not occur in the token.
|
||||
* If the token contains all end quotes, the last pair
|
||||
* is used, with all occurrences of the end quote replaced
|
||||
* by the superquote. If an end quote is the empty string,
|
||||
* the separator is used instead.
|
||||
*/
|
||||
public String format(String separator, String[] quotes) {
|
||||
return ""; //@@
|
||||
}
|
||||
protected int[] lengths;
|
||||
protected static final int MODC = 0, HINT = 1, BEG0 = 2, END0 = 3;
|
||||
|
||||
// Layout of lengths:
|
||||
// { modCount, hint, -1==beg[0], end[0]==beg[1], ..., length }
|
||||
// Note that each beg[i]..end[i] span includes a leading separator,
|
||||
// which is not part of the corresponding token.
|
||||
protected final CharSequence getCS(int i) {
|
||||
return (CharSequence) get(i);
|
||||
}
|
||||
|
||||
// Produce (and cache) an table of indexes for each token.
|
||||
protected int[] getLengths() {
|
||||
int[] lengths = this.lengths;
|
||||
;
|
||||
int sepLength = separator.length();
|
||||
if (lengths == null || lengths[MODC] != modCount) {
|
||||
int size = this.size();
|
||||
lengths = new int[END0 + size + (size == 0 ? 1 : 0)];
|
||||
lengths[MODC] = modCount;
|
||||
int end = -sepLength; // cancels leading separator
|
||||
lengths[BEG0] = end;
|
||||
for (int i = 0; i < size; i++) {
|
||||
end += sepLength; // count leading separator
|
||||
end += getCS(i).length();
|
||||
lengths[END0 + i] = end;
|
||||
}
|
||||
this.lengths = lengths;
|
||||
}
|
||||
return lengths;
|
||||
}
|
||||
|
||||
public int length() {
|
||||
int[] lengths = getLengths();
|
||||
return lengths[lengths.length - 1];
|
||||
}
|
||||
|
||||
// Which token does the given index belong to?
|
||||
protected int which(int i) {
|
||||
if (i < 0) {
|
||||
return -1;
|
||||
}
|
||||
int[] lengths = getLengths();
|
||||
for (int hint = lengths[HINT];; hint = 0) {
|
||||
for (int wh = hint; wh < lengths.length - END0; wh++) {
|
||||
int beg = lengths[BEG0 + wh];
|
||||
int end = lengths[END0 + wh];
|
||||
if (i >= beg && i < end) {
|
||||
lengths[HINT] = wh;
|
||||
return wh;
|
||||
}
|
||||
}
|
||||
if (hint == 0) {
|
||||
return size(); // end of the line
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public char charAt(int i) {
|
||||
if (i < 0) {
|
||||
return "".charAt(i);
|
||||
}
|
||||
int wh = which(i);
|
||||
int beg = lengths[BEG0 + wh];
|
||||
int j = i - beg;
|
||||
int sepLength = separator.length();
|
||||
if (j < sepLength) {
|
||||
return separator.charAt(j);
|
||||
}
|
||||
return getCS(wh).charAt(j - sepLength);
|
||||
}
|
||||
|
||||
public CharSequence subSequence(int beg, int end) {
|
||||
//System.out.println("i: "+beg+".."+end);
|
||||
if (beg == end) {
|
||||
return "";
|
||||
}
|
||||
if (beg < 0) {
|
||||
charAt(beg); // raise exception
|
||||
}
|
||||
if (beg > end) {
|
||||
charAt(-1); // raise exception
|
||||
}
|
||||
int begWh = which(beg);
|
||||
int endWh = which(end);
|
||||
if (endWh == size() || end == lengths[BEG0 + endWh]) {
|
||||
--endWh;
|
||||
}
|
||||
//System.out.println("wh: "+begWh+".."+endWh);
|
||||
int begBase = lengths[BEG0 + begWh];
|
||||
int endBase = lengths[BEG0 + endWh];
|
||||
int sepLength = separator.length();
|
||||
int begFrag = 0;
|
||||
if ((beg - begBase) < sepLength) {
|
||||
begFrag = sepLength - (beg - begBase);
|
||||
beg += begFrag;
|
||||
}
|
||||
int endFrag = 0;
|
||||
if ((end - endBase) < sepLength) {
|
||||
endFrag = (end - endBase);
|
||||
end = endBase;
|
||||
endBase = lengths[BEG0 + --endWh];
|
||||
}
|
||||
if (false) {
|
||||
System.out.print("beg[wbf]end[wbf]");
|
||||
int pr[] = {begWh, begBase, begFrag, beg, endWh, endBase, endFrag, end};
|
||||
for (int k = 0; k < pr.length; k++) {
|
||||
System.out.print((k == 4 ? " " : " ") + (pr[k]));
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
if (begFrag > 0 && (end + endFrag) - begBase <= sepLength) {
|
||||
// Special case: Slice the separator.
|
||||
beg -= begFrag;
|
||||
end += endFrag;
|
||||
return separator.substring(beg - begBase, end - begBase);
|
||||
}
|
||||
if (begWh == endWh && (begFrag + endFrag) == 0) {
|
||||
// Special case: Slice a single token.
|
||||
return getCS(begWh).subSequence(beg - begBase - sepLength,
|
||||
end - endBase - sepLength);
|
||||
}
|
||||
Object[] subTokens = new Object[1 + (endWh - begWh) + 1];
|
||||
int fillp = 0;
|
||||
if (begFrag == sepLength) {
|
||||
// Insert a leading null token to force an initial separator.
|
||||
subTokens[fillp++] = "";
|
||||
begFrag = 0;
|
||||
}
|
||||
for (int wh = begWh; wh <= endWh; wh++) {
|
||||
CharSequence cs = getCS(wh);
|
||||
if (wh == begWh || wh == endWh) {
|
||||
// Slice it.
|
||||
int csBeg = (wh == begWh) ? (beg - begBase) - sepLength : 0;
|
||||
int csEnd = (wh == endWh) ? (end - endBase) - sepLength : cs.length();
|
||||
cs = cs.subSequence(csBeg, csEnd);
|
||||
if (begFrag > 0 && wh == begWh) {
|
||||
cs = separator.substring(sepLength - begFrag) + cs;
|
||||
}
|
||||
if (endFrag > 0 && wh == endWh) {
|
||||
cs = cs.toString() + separator.substring(0, endFrag);
|
||||
}
|
||||
}
|
||||
subTokens[fillp++] = cs;
|
||||
}
|
||||
return new TokenList(subTokens, 0, fillp, separator);
|
||||
}
|
||||
|
||||
/** Returns the concatenation of all tokens,
|
||||
* with intervening separator characters.
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder buf = new StringBuilder(length());
|
||||
int size = this.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i > 0) {
|
||||
buf.append(separator);
|
||||
}
|
||||
buf.append(get(i));
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/*---- TESTING CODE ----
|
||||
public static void main(String[] av) {
|
||||
if (av.length == 0) av = new String[]{"one", "2", "", "four"};
|
||||
TokenList ts = new TokenList();
|
||||
final String SEP = ", ";
|
||||
ts.setSeparator(SEP);
|
||||
for (int i = -1; i < av.length; i++) {
|
||||
if (i >= 0) ts.addToken(av[i]);
|
||||
{
|
||||
TokenList tsCopy = new TokenList(ts.toString(), SEP);
|
||||
if (!tsCopy.equals(ts)) {
|
||||
tsCopy.setSeparator(")(");
|
||||
System.out.println("!= ("+tsCopy+")");
|
||||
}
|
||||
}
|
||||
{
|
||||
TokenList tsBar = new TokenList(ts, "|");
|
||||
tsBar.add(0, "[");
|
||||
tsBar.add("]");
|
||||
System.out.println(tsBar);
|
||||
}
|
||||
if (false) {
|
||||
int[] ls = ts.getLengths();
|
||||
System.out.println("ts: "+ts);
|
||||
System.out.print("ls: {");
|
||||
for (int j = 0; j < ls.length; j++) System.out.print(" "+ls[j]);
|
||||
System.out.println(" }");
|
||||
}
|
||||
assert0(ts.size() == i+1);
|
||||
assert0(i < 0 || ts.get(i) == av[i]);
|
||||
String tss = ts.toString();
|
||||
int tslen = tss.length();
|
||||
assert0(ts.length() == tss.length());
|
||||
for (int n = 0; n < tslen; n++) {
|
||||
assert0(ts.charAt(n) == tss.charAt(n));
|
||||
}
|
||||
for (int j = 0; j < tslen; j++) {
|
||||
for (int k = tslen; k >= j; k--) {
|
||||
CharSequence sub = ts.subSequence(j, k);
|
||||
//System.out.println("|"+sub+"|");
|
||||
assert0(sub.toString().equals(tss.substring(j, k)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static void assert0(boolean z) {
|
||||
if (!z) throw new RuntimeException("assert failed");
|
||||
}
|
||||
// ---- TESTING CODE ----*/
|
||||
}
|
4330
jdk/test/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java
Normal file
4330
jdk/test/tools/pack200/pack200-verifier/src/xmlkit/XMLKit.java
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user