This commit is contained in:
Lana Steuck 2010-08-29 22:41:28 -07:00
commit ae1cce3a74
99 changed files with 13031 additions and 2711 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
tzdata2010i
tzdata2010l

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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&iacute;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&iacute;a de Banderas homologa su horario al del centro del
# pa&iacute;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&iacute;a de Banderas homologa su horario con el del Centro del
# Pa&iacute;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&iacute;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&iacute;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

View File

@ -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

View 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
@ -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));
}

View File

@ -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());

View 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,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;
}

View File

@ -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;

View File

@ -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);

View 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);

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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
}
}

View 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,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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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

View File

@ -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) {

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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() {
// }
}

View File

@ -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");
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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) {

View File

@ -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 {

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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},

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -187,7 +187,6 @@ class UnixFileSystem extends FileSystem {
}
}
}
assert canonicalize0(path).equals(res) || path.startsWith(javaHome);
return res;
}
}

View File

@ -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;
}

View File

@ -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));

View File

@ -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);
}
/*

View File

@ -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,

View File

@ -424,7 +424,6 @@ class Win32FileSystem extends FileSystem {
}
}
}
assert canonicalize0(path).equalsIgnoreCase(res);
return res;
}
}

View File

@ -55,7 +55,7 @@ case "$OS" in
Linux )
FS="/"
;;
Windows* )
Windows* | CYGWIN* )
FS="\\"
;;
esac

View File

@ -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) {

View File

@ -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
*/

View File

@ -23,6 +23,7 @@
#
# @test
# @ignore until 6543856 is fixed
# @bug 4990825
# @summary attach to external but local JVM processes
# @library ../../testlibrary

View 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);
}
}
}

View 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

View 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");
}
}
}

View File

@ -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;
}

View File

@ -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);

View 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);
}
}
}

View 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");
}
}
}

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View 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");
}
}
}

View 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);
}
}
}
}

View 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);
}
}
}

View 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.

View 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>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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 ----*/
}

File diff suppressed because it is too large Load Diff