aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.2.1/libjava/java/util
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.2.1/libjava/java/util')
-rw-r--r--gcc-4.2.1/libjava/java/util/Calendar.java1277
-rw-r--r--gcc-4.2.1/libjava/java/util/Currency.java355
-rw-r--r--gcc-4.2.1/libjava/java/util/GregorianCalendar.java1358
-rw-r--r--gcc-4.2.1/libjava/java/util/Locale.java864
-rw-r--r--gcc-4.2.1/libjava/java/util/ResourceBundle.java580
-rw-r--r--gcc-4.2.1/libjava/java/util/VMTimeZone.java345
-rw-r--r--gcc-4.2.1/libjava/java/util/logging/LogManager.java981
-rw-r--r--gcc-4.2.1/libjava/java/util/logging/Logger.java1206
-rw-r--r--gcc-4.2.1/libjava/java/util/logging/natLogger.cc49
-rw-r--r--gcc-4.2.1/libjava/java/util/natResourceBundle.cc29
-rw-r--r--gcc-4.2.1/libjava/java/util/natVMTimeZone.cc145
-rw-r--r--gcc-4.2.1/libjava/java/util/zip/Deflater.java334
-rw-r--r--gcc-4.2.1/libjava/java/util/zip/Inflater.java269
-rw-r--r--gcc-4.2.1/libjava/java/util/zip/natDeflater.cc216
-rw-r--r--gcc-4.2.1/libjava/java/util/zip/natInflater.cc214
15 files changed, 8222 insertions, 0 deletions
diff --git a/gcc-4.2.1/libjava/java/util/Calendar.java b/gcc-4.2.1/libjava/java/util/Calendar.java
new file mode 100644
index 000000000..5559d8c53
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/Calendar.java
@@ -0,0 +1,1277 @@
+/* Calendar.java --
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * This class is an abstract base class for Calendars, which can be
+ * used to convert between <code>Date</code> objects and a set of
+ * integer fields which represent <code>YEAR</code>,
+ * <code>MONTH</code>, <code>DAY</code>, etc. The <code>Date</code>
+ * object represents a time in milliseconds since the Epoch. <br>
+ *
+ * This class is locale sensitive. To get the Object matching the
+ * current locale you can use <code>getInstance</code>. You can even provide
+ * a locale or a timezone. <code>getInstance</code> returns currently
+ * a <code>GregorianCalendar</code> for the current date. <br>
+ *
+ * If you want to convert a date from the Year, Month, Day, DayOfWeek,
+ * etc. Representation to a <code>Date</code>-Object, you can create
+ * a new Calendar with <code>getInstance()</code>,
+ * <code>clear()</code> all fields, <code>set(int,int)</code> the
+ * fields you need and convert it with <code>getTime()</code>. <br>
+ *
+ * If you want to convert a <code>Date</code>-object to the Calendar
+ * representation, create a new Calendar, assign the
+ * <code>Date</code>-Object with <code>setTime()</code>, and read the
+ * fields with <code>get(int)</code>. <br>
+ *
+ * When computing the date from time fields, it may happen, that there
+ * are either two few fields set, or some fields are inconsistent. This
+ * cases will handled in a calendar specific way. Missing fields are
+ * replaced by the fields of the epoch: 1970 January 1 00:00. <br>
+ *
+ * To understand, how the day of year is computed out of the fields
+ * look at the following table. It is traversed from top to bottom,
+ * and for the first line all fields are set, that line is used to
+ * compute the day. <br>
+ *
+ *
+<pre>month + day_of_month
+month + week_of_month + day_of_week
+month + day_of_week_of_month + day_of_week
+day_of_year
+day_of_week + week_of_year</pre>
+ *
+ * The hour_of_day-field takes precedence over the ampm and
+ * hour_of_ampm fields. <br>
+ *
+ * <STRONG>Note:</STRONG> This can differ for non-Gregorian calendar. <br>
+ *
+ * To convert a calendar to a human readable form and vice versa, use
+ * the <code>java.text.DateFormat</code> class. <br>
+ *
+ * Other useful things you can do with an calendar, is
+ * <code>roll</code>ing fields (that means increase/decrease a
+ * specific field by one, propagating overflows), or
+ * <code>add</code>ing/substracting a fixed amount to a field.
+ *
+ * @see Date
+ * @see GregorianCalendar
+ * @see TimeZone
+ * @see java.text.DateFormat
+ */
+public abstract class Calendar implements Serializable, Cloneable
+{
+ /**
+ * Constant representing the era time field.
+ */
+ public static final int ERA = 0;
+
+ /**
+ * Constant representing the year time field.
+ */
+ public static final int YEAR = 1;
+
+ /**
+ * Constant representing the month time field. This field
+ * should contain one of the JANUARY,...,DECEMBER constants below.
+ */
+ public static final int MONTH = 2;
+
+ /**
+ * Constant representing the week of the year field.
+ * @see #setFirstDayOfWeek(int)
+ */
+ public static final int WEEK_OF_YEAR = 3;
+
+ /**
+ * Constant representing the week of the month time field.
+ * @see #setFirstDayOfWeek(int)
+ */
+ public static final int WEEK_OF_MONTH = 4;
+
+ /**
+ * Constant representing the day time field, synonym for DAY_OF_MONTH.
+ */
+ public static final int DATE = 5;
+
+ /**
+ * Constant representing the day time field.
+ */
+ public static final int DAY_OF_MONTH = 5;
+
+ /**
+ * Constant representing the day of year time field. This is
+ * 1 for the first day in month.
+ */
+ public static final int DAY_OF_YEAR = 6;
+
+ /**
+ * Constant representing the day of week time field. This field
+ * should contain one of the SUNDAY,...,SATURDAY constants below.
+ */
+ public static final int DAY_OF_WEEK = 7;
+
+ /**
+ * Constant representing the day-of-week-in-month field. For
+ * instance this field contains 2 for the second thursday in a
+ * month. If you give a negative number here, the day will count
+ * from the end of the month.
+ */
+ public static final int DAY_OF_WEEK_IN_MONTH = 8;
+
+ /**
+ * Constant representing the part of the day for 12-hour clock. This
+ * should be one of AM or PM.
+ */
+ public static final int AM_PM = 9;
+
+ /**
+ * Constant representing the hour time field for 12-hour clock.
+ */
+ public static final int HOUR = 10;
+
+ /**
+ * Constant representing the hour of day time field for 24-hour clock.
+ */
+ public static final int HOUR_OF_DAY = 11;
+
+ /**
+ * Constant representing the minute of hour time field.
+ */
+ public static final int MINUTE = 12;
+
+ /**
+ * Constant representing the second time field.
+ */
+ public static final int SECOND = 13;
+
+ /**
+ * Constant representing the millisecond time field.
+ */
+ public static final int MILLISECOND = 14;
+
+ /**
+ * Constant representing the time zone offset time field for the
+ * time given in the other fields. It is measured in
+ * milliseconds. The default is the offset of the time zone.
+ */
+ public static final int ZONE_OFFSET = 15;
+
+ /**
+ * Constant representing the daylight saving time offset in
+ * milliseconds. The default is the value given by the time zone.
+ */
+ public static final int DST_OFFSET = 16;
+
+ /**
+ * Number of time fields.
+ */
+ public static final int FIELD_COUNT = 17;
+
+ /**
+ * Constant representing Sunday.
+ */
+ public static final int SUNDAY = 1;
+
+ /**
+ * Constant representing Monday.
+ */
+ public static final int MONDAY = 2;
+
+ /**
+ * Constant representing Tuesday.
+ */
+ public static final int TUESDAY = 3;
+
+ /**
+ * Constant representing Wednesday.
+ */
+ public static final int WEDNESDAY = 4;
+
+ /**
+ * Constant representing Thursday.
+ */
+ public static final int THURSDAY = 5;
+
+ /**
+ * Constant representing Friday.
+ */
+ public static final int FRIDAY = 6;
+
+ /**
+ * Constant representing Saturday.
+ */
+ public static final int SATURDAY = 7;
+
+ /**
+ * Constant representing January.
+ */
+ public static final int JANUARY = 0;
+
+ /**
+ * Constant representing February.
+ */
+ public static final int FEBRUARY = 1;
+
+ /**
+ * Constant representing March.
+ */
+ public static final int MARCH = 2;
+
+ /**
+ * Constant representing April.
+ */
+ public static final int APRIL = 3;
+
+ /**
+ * Constant representing May.
+ */
+ public static final int MAY = 4;
+
+ /**
+ * Constant representing June.
+ */
+ public static final int JUNE = 5;
+
+ /**
+ * Constant representing July.
+ */
+ public static final int JULY = 6;
+
+ /**
+ * Constant representing August.
+ */
+ public static final int AUGUST = 7;
+
+ /**
+ * Constant representing September.
+ */
+ public static final int SEPTEMBER = 8;
+
+ /**
+ * Constant representing October.
+ */
+ public static final int OCTOBER = 9;
+
+ /**
+ * Constant representing November.
+ */
+ public static final int NOVEMBER = 10;
+
+ /**
+ * Constant representing December.
+ */
+ public static final int DECEMBER = 11;
+
+ /**
+ * Constant representing Undecimber. This is an artificial name useful
+ * for lunar calendars.
+ */
+ public static final int UNDECIMBER = 12;
+
+ /**
+ * Useful constant for 12-hour clock.
+ */
+ public static final int AM = 0;
+
+ /**
+ * Useful constant for 12-hour clock.
+ */
+ public static final int PM = 1;
+
+ /**
+ * The time fields. The array is indexed by the constants YEAR to
+ * DST_OFFSET.
+ * @serial
+ */
+ protected int[] fields = new int[FIELD_COUNT];
+
+ /**
+ * The flags which tell if the fields above have a value.
+ * @serial
+ */
+ protected boolean[] isSet = new boolean[FIELD_COUNT];
+
+ /**
+ * The time in milliseconds since the epoch.
+ * @serial
+ */
+ protected long time;
+
+ /**
+ * Tells if the above field has a valid value.
+ * @serial
+ */
+ protected boolean isTimeSet;
+
+ /**
+ * Tells if the fields have a valid value. This superseeds the isSet
+ * array.
+ * @serial
+ */
+ protected boolean areFieldsSet;
+
+ /**
+ * The time zone of this calendar. Used by sub classes to do UTC / local
+ * time conversion. Sub classes can access this field with getTimeZone().
+ * @serial
+ */
+ private TimeZone zone;
+
+ /**
+ * Specifies if the date/time interpretation should be lenient.
+ * If the flag is set, a date such as "February 30, 1996" will be
+ * treated as the 29th day after the February 1. If this flag
+ * is false, such dates will cause an exception.
+ * @serial
+ */
+ private boolean lenient;
+
+ /**
+ * Sets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @serial
+ */
+ private int firstDayOfWeek;
+
+ /**
+ * Sets how many days are required in the first week of the year.
+ * If the first day of the year should be the first week you should
+ * set this value to 1. If the first week must be a full week, set
+ * it to 7.
+ * @serial
+ */
+ private int minimalDaysInFirstWeek;
+
+ /**
+ * Is set to true if DST_OFFSET is explicitly set. In that case
+ * it's value overrides the value computed from the current
+ * time and the timezone.
+ */
+ private boolean explicitDSTOffset = false;
+
+ /**
+ * The version of the serialized data on the stream.
+ * <dl><dt>0 or not present</dt>
+ * <dd> JDK 1.1.5 or later.</dd>
+ * <dt>1</dt>
+ * <dd>JDK 1.1.6 or later. This always writes a correct `time' value
+ * on the stream, as well as the other fields, to be compatible with
+ * earlier versions</dd></dl>
+ * @since JDK1.1.6
+ * @serial
+ */
+ private int serialVersionOnStream = 1;
+
+ /**
+ * XXX - I have not checked the compatibility. The documentation of
+ * the serialized-form is quite hairy...
+ */
+ static final long serialVersionUID = -1807547505821590642L;
+
+ /**
+ * The name of the resource bundle. Used only by getBundle()
+ */
+ private static final String bundleName = "gnu.java.locale.Calendar";
+
+ /**
+ * get resource bundle:
+ * The resources should be loaded via this method only. Iff an application
+ * uses this method, the resourcebundle is required.
+ */
+ private static ResourceBundle getBundle(Locale locale)
+ {
+ return ResourceBundle.getBundle(bundleName, locale,
+ ClassLoader.getSystemClassLoader());
+ }
+
+ /**
+ * Constructs a new Calendar with the default time zone and the default
+ * locale.
+ */
+ protected Calendar()
+ {
+ this(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new Calendar with the given time zone and the given
+ * locale.
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ protected Calendar(TimeZone zone, Locale locale)
+ {
+ this.zone = zone;
+ lenient = true;
+
+ ResourceBundle rb = getBundle(locale);
+
+ firstDayOfWeek = ((Integer) rb.getObject("firstDayOfWeek")).intValue();
+ minimalDaysInFirstWeek = ((Integer) rb.getObject("minimalDaysInFirstWeek"))
+ .intValue();
+ clear();
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the default
+ * time zone and locale.
+ */
+ public static synchronized Calendar getInstance()
+ {
+ return getInstance(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the given
+ * time zone and the default locale.
+ * @param zone a time zone.
+ */
+ public static synchronized Calendar getInstance(TimeZone zone)
+ {
+ return getInstance(zone, Locale.getDefault());
+ }
+
+ /**
+ * Creates a calendar representing the actual time, using the default
+ * time zone and the given locale.
+ * @param locale a locale.
+ */
+ public static synchronized Calendar getInstance(Locale locale)
+ {
+ return getInstance(TimeZone.getDefault(), locale);
+ }
+
+ /**
+ * Cache of locale->calendar-class mappings. This avoids having to do a ResourceBundle
+ * lookup for every getInstance call.
+ */
+ private static HashMap cache = new HashMap();
+
+ /** Preset argument types for calendar-class constructor lookup. */
+ private static Class[] ctorArgTypes = new Class[]
+ {
+ TimeZone.class, Locale.class
+ };
+
+ /**
+ * Creates a calendar representing the actual time, using the given
+ * time zone and locale.
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ public static synchronized Calendar getInstance(TimeZone zone, Locale locale)
+ {
+ Class calendarClass = (Class) cache.get(locale);
+ Throwable exception = null;
+
+ try
+ {
+ if (calendarClass == null)
+ {
+ ResourceBundle rb = getBundle(locale);
+ String calendarClassName = rb.getString("calendarClass");
+
+ if (calendarClassName != null)
+ {
+ calendarClass = Class.forName(calendarClassName);
+ if (Calendar.class.isAssignableFrom(calendarClass))
+ cache.put(locale, calendarClass);
+ }
+ }
+
+ // GregorianCalendar is by far the most common case. Optimize by
+ // avoiding reflection.
+ if (calendarClass == GregorianCalendar.class)
+ return new GregorianCalendar(zone, locale);
+
+ if (Calendar.class.isAssignableFrom(calendarClass))
+ {
+ Constructor ctor = calendarClass.getConstructor(ctorArgTypes);
+ return (Calendar) ctor.newInstance(new Object[] { zone, locale });
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ exception = ex;
+ }
+ catch (IllegalAccessException ex)
+ {
+ exception = ex;
+ }
+ catch (NoSuchMethodException ex)
+ {
+ exception = ex;
+ }
+ catch (InstantiationException ex)
+ {
+ exception = ex;
+ }
+ catch (InvocationTargetException ex)
+ {
+ exception = ex;
+ }
+
+ throw new RuntimeException("Error instantiating calendar for locale "
+ + locale, exception);
+ }
+
+ /**
+ * Gets the set of locales for which a Calendar is available.
+ * @exception MissingResourceException if locale data couldn't be found.
+ * @return the set of locales.
+ */
+ public static synchronized Locale[] getAvailableLocales()
+ {
+ ResourceBundle rb = getBundle(new Locale("", ""));
+ return (Locale[]) rb.getObject("availableLocales");
+ }
+
+ /**
+ * Converts the time field values (<code>fields</code>) to
+ * milliseconds since the epoch UTC (<code>time</code>). Override
+ * this method if you write your own Calendar. */
+ protected abstract void computeTime();
+
+ /**
+ * Converts the milliseconds since the epoch UTC
+ * (<code>time</code>) to time fields
+ * (<code>fields</code>). Override this method if you write your
+ * own Calendar.
+ */
+ protected abstract void computeFields();
+
+ /**
+ * Converts the time represented by this object to a
+ * <code>Date</code>-Object.
+ * @return the Date.
+ */
+ public final Date getTime()
+ {
+ if (! isTimeSet)
+ computeTime();
+ return new Date(time);
+ }
+
+ /**
+ * Sets this Calendar's time to the given Date. All time fields
+ * are invalidated by this method.
+ */
+ public final void setTime(Date date)
+ {
+ setTimeInMillis(date.getTime());
+ }
+
+ /**
+ * Returns the time represented by this Calendar.
+ * @return the time in milliseconds since the epoch.
+ * @specnote This was made public in 1.4.
+ */
+ public long getTimeInMillis()
+ {
+ if (! isTimeSet)
+ computeTime();
+ return time;
+ }
+
+ /**
+ * Sets this Calendar's time to the given Time. All time fields
+ * are invalidated by this method.
+ * @param time the time in milliseconds since the epoch
+ * @specnote This was made public in 1.4.
+ */
+ public void setTimeInMillis(long time)
+ {
+ clear();
+ this.time = time;
+ isTimeSet = true;
+ computeFields();
+ }
+
+ /**
+ * Gets the value of the specified field. They are recomputed
+ * if they are invalid.
+ * @param field the time field. One of the time field constants.
+ * @return the value of the specified field
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @specnote Not final since JDK 1.4
+ */
+ public int get(int field)
+ {
+ // If the requested field is invalid, force all fields to be recomputed.
+ if (! isSet[field])
+ areFieldsSet = false;
+ complete();
+ return fields[field];
+ }
+
+ /**
+ * Gets the value of the specified field. This method doesn't
+ * recompute the fields, if they are invalid.
+ * @param field the time field. One of the time field constants.
+ * @return the value of the specified field, undefined if
+ * <code>areFieldsSet</code> or <code>isSet[field]</code> is false.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ protected final int internalGet(int field)
+ {
+ return fields[field];
+ }
+
+ /**
+ * Sets the time field with the given value. This does invalidate
+ * the time in milliseconds.
+ * @param field the time field. One of the time field constants
+ * @param value the value to be set.
+ * @throws ArrayIndexOutOfBoundsException if field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @specnote Not final since JDK 1.4
+ */
+ public void set(int field, int value)
+ {
+ if (isTimeSet)
+ for (int i = 0; i < FIELD_COUNT; i++)
+ isSet[i] = false;
+ isTimeSet = false;
+ fields[field] = value;
+ isSet[field] = true;
+
+ // The five valid date patterns, in order of priority
+ // 1 YEAR + MONTH + DAY_OF_MONTH
+ // 2 YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ // 3 YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ // 4 YEAR + DAY_OF_YEAR
+ // 5 YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
+ switch (field)
+ {
+ case MONTH: // pattern 1,2 or 3
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_MONTH: // pattern 1
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[WEEK_OF_MONTH] = true;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case WEEK_OF_MONTH: // pattern 2
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_WEEK_IN_MONTH: // pattern 3
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[MONTH] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_YEAR: // pattern 4
+ isSet[YEAR] = true;
+ isSet[MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ break;
+ case WEEK_OF_YEAR: // pattern 5
+ if (! isSet[DAY_OF_WEEK])
+ fields[DAY_OF_WEEK] = getFirstDayOfWeek();
+ isSet[YEAR] = true;
+ isSet[DAY_OF_WEEK] = true;
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ break;
+ case AM_PM:
+ isSet[HOUR] = true;
+ isSet[HOUR_OF_DAY] = false;
+ break;
+ case HOUR_OF_DAY:
+ isSet[AM_PM] = false;
+ isSet[HOUR] = false;
+ break;
+ case HOUR:
+ isSet[AM_PM] = true;
+ isSet[HOUR_OF_DAY] = false;
+ break;
+ case DST_OFFSET:
+ explicitDSTOffset = true;
+ }
+
+ // May have crossed over a DST boundary.
+ if (! explicitDSTOffset && (field != DST_OFFSET && field != ZONE_OFFSET))
+ isSet[DST_OFFSET] = false;
+ }
+
+ /**
+ * Sets the fields for year, month, and date
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ */
+ public final void set(int year, int month, int date)
+ {
+ isTimeSet = false;
+ fields[YEAR] = year;
+ fields[MONTH] = month;
+ fields[DATE] = date;
+ isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
+ isSet[WEEK_OF_YEAR] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[ERA] = false;
+
+ if (! explicitDSTOffset)
+ isSet[DST_OFFSET] = false; // May have crossed a DST boundary.
+ }
+
+ /**
+ * Sets the fields for year, month, date, hour, and minute
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ * @param hour the hour of day.
+ * @param minute the minute.
+ */
+ public final void set(int year, int month, int date, int hour, int minute)
+ {
+ set(year, month, date);
+ fields[HOUR_OF_DAY] = hour;
+ fields[MINUTE] = minute;
+ isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
+ isSet[AM_PM] = false;
+ isSet[HOUR] = false;
+ }
+
+ /**
+ * Sets the fields for year, month, date, hour, and minute
+ * @param year the year.
+ * @param month the month, one of the constants JANUARY..UNDICEMBER.
+ * @param date the day of the month
+ * @param hour the hour of day.
+ * @param minute the minute.
+ * @param second the second.
+ */
+ public final void set(int year, int month, int date, int hour, int minute,
+ int second)
+ {
+ set(year, month, date, hour, minute);
+ fields[SECOND] = second;
+ isSet[SECOND] = true;
+ }
+
+ /**
+ * Clears the values of all the time fields.
+ */
+ public final void clear()
+ {
+ isTimeSet = false;
+ areFieldsSet = false;
+ int zoneOffs = zone.getRawOffset();
+ int[] tempFields =
+ {
+ 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
+ 0, 0, zoneOffs, 0
+ };
+ fields = tempFields;
+ for (int i = 0; i < FIELD_COUNT; i++)
+ isSet[i] = false;
+ }
+
+ /**
+ * Clears the values of the specified time field.
+ * @param field the time field. One of the time field constants.
+ * @throws ArrayIndexOutOfBoundsException if field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public final void clear(int field)
+ {
+ int[] tempFields =
+ {
+ 1, 1970, JANUARY, 1, 1, 1, 1, THURSDAY, 1, AM, 0, 0, 0,
+ 0, 0, zone.getRawOffset(), 0
+ };
+ isTimeSet = false;
+ areFieldsSet = false;
+ isSet[field] = false;
+ fields[field] = tempFields[field];
+ }
+
+ /**
+ * Determines if the specified field has a valid value.
+ * @return true if the specified field has a value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public final boolean isSet(int field)
+ {
+ return isSet[field];
+ }
+
+ /**
+ * Fills any unset fields in the time field list
+ */
+ protected void complete()
+ {
+ if (! isTimeSet)
+ computeTime();
+ if (! areFieldsSet)
+ computeFields();
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, that represents
+ * the same time (but doesn't necessary have the same fields).
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof Calendar))
+ return false;
+ Calendar cal = (Calendar) o;
+ if (getTimeInMillis() == ((Calendar) o).getTimeInMillis()
+ && cal.getFirstDayOfWeek() == getFirstDayOfWeek()
+ && cal.isLenient() == isLenient()
+ && cal.getMinimalDaysInFirstWeek() == getMinimalDaysInFirstWeek())
+ {
+ TimeZone self = getTimeZone();
+ TimeZone oth = cal.getTimeZone();
+ return self == null ? oth == null : self.equals(oth);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code for this calendar.
+ * @return a hash code, which fullfits the general contract of
+ * <code>hashCode()</code>
+ */
+ public int hashCode()
+ {
+ long time = getTimeInMillis();
+ int val = (int) ((time & 0xffffffffL) ^ (time >> 32));
+ val += (getFirstDayOfWeek() + (isLenient() ? 1230 : 1237)
+ + getMinimalDaysInFirstWeek());
+ TimeZone self = getTimeZone();
+ if (self != null)
+ val ^= self.hashCode();
+ return val;
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, and this calendar
+ * represents a smaller time than the calendar o.
+ * @exception ClassCastException if o is not an calendar.
+ * @since JDK1.2 you don't need to override this method
+ */
+ public boolean before(Object o)
+ {
+ return getTimeInMillis() < ((Calendar) o).getTimeInMillis();
+ }
+
+ /**
+ * Compares the given calendar with this.
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, and this calendar
+ * represents a bigger time than the calendar o.
+ * @exception ClassCastException if o is not an calendar.
+ * @since JDK1.2 you don't need to override this method
+ */
+ public boolean after(Object o)
+ {
+ return getTimeInMillis() > ((Calendar) o).getTimeInMillis();
+ }
+
+ /**
+ * Adds the specified amount of time to the given time field. The
+ * amount may be negative to subtract the time. If the field overflows
+ * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount of time.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public abstract void add(int field, int amount);
+
+ /**
+ * Rolls the specified time field up or down. This means add one
+ * to the specified field, but don't change the other fields. If
+ * the maximum for this field is reached, start over with the
+ * minimum value. <br>
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically converted to July, 1.
+ * @param field the time field. One of the time field constants.
+ * @param up the direction, true for up, false for down.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ */
+ public abstract void roll(int field, boolean up);
+
+ /**
+ * Rolls up or down the specified time field by the given amount.
+ * A negative amount rolls down. The default implementation is
+ * call <code>roll(int, boolean)</code> for the specified amount.
+ *
+ * Subclasses should override this method to do more intuitiv things.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount to roll by, positive for rolling up,
+ * negative for rolling down.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since JDK1.2
+ */
+ public void roll(int field, int amount)
+ {
+ while (amount > 0)
+ {
+ roll(field, true);
+ amount--;
+ }
+ while (amount < 0)
+ {
+ roll(field, false);
+ amount++;
+ }
+ }
+
+ /**
+ * Sets the time zone to the specified value.
+ * @param zone the new time zone
+ */
+ public void setTimeZone(TimeZone zone)
+ {
+ this.zone = zone;
+ }
+
+ /**
+ * Gets the time zone of this calendar
+ * @return the current time zone.
+ */
+ public TimeZone getTimeZone()
+ {
+ return zone;
+ }
+
+ /**
+ * Specifies if the date/time interpretation should be lenient.
+ * If the flag is set, a date such as "February 30, 1996" will be
+ * treated as the 29th day after the February 1. If this flag
+ * is false, such dates will cause an exception.
+ * @param lenient true, if the date should be interpreted linient,
+ * false if it should be interpreted strict.
+ */
+ public void setLenient(boolean lenient)
+ {
+ this.lenient = lenient;
+ }
+
+ /**
+ * Tells if the date/time interpretation is lenient.
+ * @return true, if the date should be interpreted linient,
+ * false if it should be interpreted strict.
+ */
+ public boolean isLenient()
+ {
+ return lenient;
+ }
+
+ /**
+ * Sets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @param value the first day of week. One of SUNDAY to SATURDAY.
+ */
+ public void setFirstDayOfWeek(int value)
+ {
+ firstDayOfWeek = value;
+ }
+
+ /**
+ * Gets what the first day of week is. This is used for
+ * WEEK_OF_MONTH and WEEK_OF_YEAR fields.
+ * @return the first day of week. One of SUNDAY to SATURDAY.
+ */
+ public int getFirstDayOfWeek()
+ {
+ return firstDayOfWeek;
+ }
+
+ /**
+ * Sets how many days are required in the first week of the year.
+ * If the first day of the year should be the first week you should
+ * set this value to 1. If the first week must be a full week, set
+ * it to 7.
+ * @param value the minimal days required in the first week.
+ */
+ public void setMinimalDaysInFirstWeek(int value)
+ {
+ minimalDaysInFirstWeek = value;
+ }
+
+ /**
+ * Gets how many days are required in the first week of the year.
+ * @return the minimal days required in the first week.
+ * @see #setMinimalDaysInFirstWeek
+ */
+ public int getMinimalDaysInFirstWeek()
+ {
+ return minimalDaysInFirstWeek;
+ }
+
+ /**
+ * Gets the smallest value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the smallest value.
+ */
+ public abstract int getMinimum(int field);
+
+ /**
+ * Gets the biggest value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the biggest value.
+ */
+ public abstract int getMaximum(int field);
+
+ /**
+ * Gets the greatest minimum value that is allowed for the specified field.
+ * @param field the time field. One of the time field constants.
+ * @return the greatest minimum value.
+ */
+ public abstract int getGreatestMinimum(int field);
+
+ /**
+ * Gets the smallest maximum value that is allowed for the
+ * specified field. For example this is 28 for DAY_OF_MONTH.
+ * @param field the time field. One of the time field constants.
+ * @return the least maximum value.
+ */
+ public abstract int getLeastMaximum(int field);
+
+ /**
+ * Gets the actual minimum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields.
+ * @param field the time field. One of the time field constants.
+ * @return the actual minimum value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since jdk1.2
+ */
+ public int getActualMinimum(int field)
+ {
+ Calendar tmp = (Calendar) clone(); // To avoid restoring state
+ int min = tmp.getGreatestMinimum(field);
+ int end = tmp.getMinimum(field);
+ tmp.set(field, min);
+ for (; min > end; min--)
+ {
+ tmp.add(field, -1); // Try to get smaller
+ if (tmp.get(field) != min - 1)
+ break; // Done if not successful
+ }
+ return min;
+ }
+
+ /**
+ * Gets the actual maximum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields.
+ * @param field the time field. One of the time field constants.
+ * @return the actual maximum value.
+ * @throws ArrayIndexOutOfBoundsException if the field is outside
+ * the valid range. The value of field must be >= 0 and
+ * <= <code>FIELD_COUNT</code>.
+ * @since jdk1.2
+ */
+ public int getActualMaximum(int field)
+ {
+ Calendar tmp = (Calendar) clone(); // To avoid restoring state
+ int max = tmp.getLeastMaximum(field);
+ int end = tmp.getMaximum(field);
+ tmp.set(field, max);
+ for (; max < end; max++)
+ {
+ tmp.add(field, 1);
+ if (tmp.get(field) != max + 1)
+ break;
+ }
+ return max;
+ }
+
+ /**
+ * Return a clone of this object.
+ */
+ public Object clone()
+ {
+ try
+ {
+ Calendar cal = (Calendar) super.clone();
+ cal.fields = (int[]) fields.clone();
+ cal.isSet = (boolean[]) isSet.clone();
+ return cal;
+ }
+ catch (CloneNotSupportedException ex)
+ {
+ return null;
+ }
+ }
+
+ private static final String[] fieldNames =
+ {
+ ",ERA=", ",YEAR=", ",MONTH=",
+ ",WEEK_OF_YEAR=",
+ ",WEEK_OF_MONTH=",
+ ",DAY_OF_MONTH=",
+ ",DAY_OF_YEAR=", ",DAY_OF_WEEK=",
+ ",DAY_OF_WEEK_IN_MONTH=",
+ ",AM_PM=", ",HOUR=",
+ ",HOUR_OF_DAY=", ",MINUTE=",
+ ",SECOND=", ",MILLISECOND=",
+ ",ZONE_OFFSET=", ",DST_OFFSET="
+ };
+
+ /**
+ * Returns a string representation of this object. It is mainly
+ * for debugging purposes and its content is implementation
+ * specific.
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append(getClass().getName()).append('[');
+ sb.append("time=");
+ if (isTimeSet)
+ sb.append(time);
+ else
+ sb.append("?");
+ sb.append(",zone=" + zone);
+ sb.append(",areFieldsSet=" + areFieldsSet);
+ for (int i = 0; i < FIELD_COUNT; i++)
+ {
+ sb.append(fieldNames[i]);
+ if (isSet[i])
+ sb.append(fields[i]);
+ else
+ sb.append("?");
+ }
+ sb.append(",lenient=").append(lenient);
+ sb.append(",firstDayOfWeek=").append(firstDayOfWeek);
+ sb.append(",minimalDaysInFirstWeek=").append(minimalDaysInFirstWeek);
+ sb.append("]");
+ return sb.toString();
+ }
+
+ /**
+ * Saves the state of the object to the stream. Ideally we would
+ * only write the time field, but we need to be compatible with
+ * earlier versions. <br>
+ *
+ * This doesn't write the JDK1.1 field nextStamp to the stream, as
+ * I don't know what it is good for, and because the documentation
+ * says, that it could be omitted. */
+ private void writeObject(ObjectOutputStream stream) throws IOException
+ {
+ if (! isTimeSet)
+ computeTime();
+ stream.defaultWriteObject();
+ }
+
+ /**
+ * Reads the object back from stream (deserialization).
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException
+ {
+ stream.defaultReadObject();
+ if (! isTimeSet)
+ computeTime();
+
+ if (serialVersionOnStream > 1)
+ {
+ // This is my interpretation of the serial number:
+ // Sun wants to remove all fields from the stream someday
+ // and will then increase the serialVersion number again.
+ // We prepare to be compatible.
+ fields = new int[FIELD_COUNT];
+ isSet = new boolean[FIELD_COUNT];
+ areFieldsSet = false;
+ }
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/Currency.java b/gcc-4.2.1/libjava/java/util/Currency.java
new file mode 100644
index 000000000..e1a28e0b8
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/Currency.java
@@ -0,0 +1,355 @@
+/* Currency.java -- Representation of a currency
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util;
+
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.text.NumberFormat;
+
+/**
+ * Representation of a currency for a particular locale. Each currency
+ * is identified by its ISO 4217 code, and only one instance of this
+ * class exists per currency. As a result, instances are created
+ * via the <code>getInstance()</code> methods rather than by using
+ * a constructor.
+ *
+ * @see java.util.Locale
+ * @author Guilhem Lavaux (guilhem.lavaux@free.fr)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ * @author Bryce McKinlay (mckinlay@redhat.com)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.4
+ */
+public final class Currency
+ implements Serializable
+{
+ /**
+ * For compatability with Sun's JDK
+ */
+ static final long serialVersionUID = -158308464356906721L;
+
+ /**
+ * The locale associated with this currency.
+ *
+ * @see #Currency(java.util.Locale)
+ * @see #getInstance(java.util.Locale)
+ * @see #getSymbol(java.util.Locale)
+ * @serial ignored.
+ */
+ private transient Locale locale;
+
+ /**
+ * The resource bundle which maps the currency to
+ * a ISO 4217 currency code.
+ *
+ * @see #getCurrencyCode()
+ * @serial ignored.
+ */
+ private transient ResourceBundle res;
+
+ /**
+ * The ISO 4217 currency code associated with this
+ * particular instance.
+ *
+ * @see #getCurrencyCode()
+ * @serial the ISO 4217 currency code
+ */
+ private String currencyCode;
+
+ /**
+ * A cache of <code>Currency</code> instances to
+ * ensure the singleton nature of this class. The key
+ * is the locale of the currency.
+ *
+ * @see #getInstance(java.util.Locale)
+ * @see #readResolve()
+ * @serial ignored.
+ */
+ private static transient Map cache;
+
+ /**
+ * Instantiates the cache.
+ */
+ static
+ {
+ cache = new HashMap();
+ }
+
+ /**
+ * Default constructor for deserialization
+ */
+ private Currency ()
+ {
+ }
+
+ /**
+ * Constructor to create a <code>Currency</code> object
+ * for a particular <code>Locale</code>.
+ * All components of the given locale, other than the
+ * country code, are ignored. The results of calling this
+ * method may vary over time, as the currency associated with
+ * a particular country changes. For countries without
+ * a given currency (e.g. Antarctica), the result is null.
+ *
+ * @param loc the locale for the new currency.
+ */
+ private Currency (Locale loc)
+ {
+ this.locale = loc;
+ this.res = ResourceBundle.getBundle ("gnu.java.locale.LocaleInformation",
+ locale, ClassLoader.getSystemClassLoader());
+ /* Retrieve the ISO4217 currency code */
+ try
+ {
+ currencyCode = res.getString ("intlCurrencySymbol");
+ }
+ catch (Exception _)
+ {
+ currencyCode = null;
+ }
+ }
+
+ /**
+ * Returns the ISO4217 currency code of this currency.
+ *
+ * @return a <code>String</code> containing currency code.
+ */
+ public String getCurrencyCode ()
+ {
+ return currencyCode;
+ }
+
+ /**
+ * Returns the number of digits which occur after the decimal point
+ * for this particular currency. For example, currencies such
+ * as the U.S. dollar, the Euro and the Great British pound have two
+ * digits following the decimal point to indicate the value which exists
+ * in the associated lower-valued coinage (cents in the case of the first
+ * two, pennies in the latter). Some currencies such as the Japanese
+ * Yen have no digits after the decimal point. In the case of pseudo
+ * currencies, such as IMF Special Drawing Rights, -1 is returned.
+ *
+ * @return the number of digits after the decimal separator for this currency.
+ */
+ public int getDefaultFractionDigits ()
+ {
+ NumberFormat currency = NumberFormat.getCurrencyInstance (locale);
+
+ return currency.getMaximumFractionDigits();
+ }
+
+ /**
+ * Builds a new currency instance for this locale.
+ * All components of the given locale, other than the
+ * country code, are ignored. The results of calling this
+ * method may vary over time, as the currency associated with
+ * a particular country changes. For countries without
+ * a given currency (e.g. Antarctica), the result is null.
+ *
+ * @param locale a <code>Locale</code> instance.
+ * @return a new <code>Currency</code> instance.
+ * @throws NullPointerException if the locale or its
+ * country code is null.
+ * @throws IllegalArgumentException if the country of
+ * the given locale is not a supported ISO3166 code.
+ */
+ public static Currency getInstance (Locale locale)
+ {
+ /**
+ * The new instance must be the only available instance
+ * for the currency it supports. We ensure this happens,
+ * while maintaining a suitable performance level, by
+ * creating the appropriate object on the first call to
+ * this method, and returning the cached instance on
+ * later calls.
+ */
+ Currency newCurrency;
+
+ /* Attempt to get the currency from the cache */
+ newCurrency = (Currency) cache.get(locale);
+ if (newCurrency == null)
+ {
+ /* Create the currency for this locale */
+ newCurrency = new Currency (locale);
+ /* Cache it */
+ cache.put(locale, newCurrency);
+ }
+ /* Return the instance */
+ return newCurrency;
+ }
+
+ /**
+ * Builds the currency corresponding to the specified currency code.
+ *
+ * @param currencyCode a string representing a currency code.
+ * @return a new <code>Currency</code> instance.
+ * @throws NullPointerException if currencyCode is null.
+ * @throws IllegalArgumentException if the supplied currency code
+ * is not a supported ISO 4217 code.
+ */
+ public static Currency getInstance (String currencyCode)
+ {
+ Locale[] allLocales = Locale.getAvailableLocales ();
+
+ for (int i = 0;i < allLocales.length; i++)
+ {
+ Currency testCurrency = getInstance (allLocales[i]);
+
+ if (testCurrency.getCurrencyCode() != null &&
+ testCurrency.getCurrencyCode().equals(currencyCode))
+ return testCurrency;
+ }
+ /*
+ * If we get this far, the code is not supported by any of
+ * our locales.
+ */
+ throw new IllegalArgumentException("The currency code, " + currencyCode +
+ ", is not supported.");
+ }
+
+ /**
+ * This method returns the symbol which precedes or follows a
+ * value in this particular currency. In cases where there is no
+ * such symbol for the currency, the ISO 4217 currency
+ * code is returned.
+ *
+ * @return the currency symbol, or the ISO 4217 currency code if
+ * one doesn't exist.
+ */
+ public String getSymbol()
+ {
+ try
+ {
+ /* What does this return if there is no mapping? */
+ return res.getString ("currencySymbol");
+ }
+ catch (Exception _)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * <p>
+ * This method returns the symbol which precedes or follows a
+ * value in this particular currency. The returned value is
+ * the symbol used to denote the currency in the specified locale.
+ * </p>
+ * <p>
+ * For example, a supplied locale may specify a different symbol
+ * for the currency, due to conflicts with its own currency.
+ * This would be the case with the American currency, the dollar.
+ * Locales that also use a dollar-based currency (e.g. Canada, Australia)
+ * need to differentiate the American dollar using 'US$' rather than '$'.
+ * So, supplying one of these locales to <code>getSymbol()</code> would
+ * return this value, rather than the standard '$'.
+ * </p>
+ * <p>
+ * In cases where there is no such symbol for a particular currency,
+ * the ISO 4217 currency code is returned.
+ * </p>
+ *
+ * @param locale the locale to express the symbol in.
+ * @return the currency symbol, or the ISO 4217 currency code if
+ * one doesn't exist.
+ * @throws NullPointerException if the locale is null.
+ */
+ public String getSymbol(Locale locale)
+ {
+ // TODO. The behaviour is unclear if locale != this.locale.
+ // First we need to implement fully LocaleInformation*.java
+
+ /*
+ * FIXME: My reading of how this method works has this implementation
+ * as wrong. It should return a value relating to how the specified
+ * locale handles the symbol for this currency. This implementation
+ * seems to just do a variation of getInstance(locale).
+ */
+ try
+ {
+ ResourceBundle localeResource =
+ ResourceBundle.getBundle ("gnu.java.locale.LocaleInformation",
+ locale, Currency.class.getClassLoader());
+
+ if (localeResource.equals(res))
+ return localeResource.getString ("currencySymbol");
+ else
+ return localeResource.getString ("intlCurrencySymbol");
+ }
+ catch (Exception e1)
+ {
+ try
+ {
+ return res.getString ("intlCurrencySymbol");
+ }
+ catch (Exception e2)
+ {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * Returns the international ISO4217 currency code of this currency.
+ *
+ * @return a <code>String</code> containing the ISO4217 currency code.
+ */
+ public String toString()
+ {
+ return getCurrencyCode();
+ }
+
+ /**
+ * Resolves the deserialized object to the singleton instance for its
+ * particular currency. The currency code of the deserialized instance
+ * is used to return the correct instance.
+ *
+ * @return the singleton instance for the currency specified by the
+ * currency code of the deserialized object. This replaces
+ * the deserialized object as the returned object from
+ * deserialization.
+ * @throws ObjectStreamException if a problem occurs with deserializing
+ * the object.
+ */
+ private Object readResolve()
+ throws ObjectStreamException
+ {
+ return getInstance(currencyCode);
+ }
+
+}
diff --git a/gcc-4.2.1/libjava/java/util/GregorianCalendar.java b/gcc-4.2.1/libjava/java/util/GregorianCalendar.java
new file mode 100644
index 000000000..dc77c2f50
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/GregorianCalendar.java
@@ -0,0 +1,1358 @@
+/* java.util.GregorianCalendar
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+
+/**
+ * <p>
+ * This class represents the Gregorian calendar, that is used in most
+ * countries all over the world. It does also handle the Julian calendar
+ * for dates smaller than the date of the change to the Gregorian calendar.
+ * The Gregorian calendar differs from the Julian calendar by a different
+ * leap year rule (no leap year every 100 years, except if year is divisible
+ * by 400).
+ * </p>
+ * <p>
+ * This change date is different from country to country, and can be changed with
+ * <code>setGregorianChange</code>. The first countries to adopt the Gregorian
+ * calendar did so on the 15th of October, 1582. This date followed October
+ * the 4th, 1582 in the Julian calendar system. The non-existant days that were
+ * omitted when the change took place are interpreted as Gregorian dates.
+ * </p>
+ * <p>
+ * Prior to the changeover date, New Year's Day occurred on the 25th of March.
+ * However, this class always takes New Year's Day as being the 1st of January.
+ * Client code should manually adapt the year value, if required, for dates
+ * between January the 1st and March the 24th in years prior to the changeover.
+ * </p>
+ * <p>
+ * Any date infinitely forwards or backwards in time can be represented by
+ * this class. A <em>proleptic</em> calendar system is used, which allows
+ * future dates to be created via the existing rules. This allows meaningful
+ * and consistent dates to be produced for all years. However, dates are only
+ * historically accurate following March the 1st, 4AD when the Julian calendar
+ * system was adopted. Prior to this, leap year rules were applied erraticly.
+ * </p>
+ * <p>
+ * There are two eras available for the Gregorian calendar, namely BC and AD.
+ * </p>
+ * <p>
+ * Weeks are defined as a period of seven days, beginning on the first day
+ * of the week, as returned by <code>getFirstDayOfWeek()</code>, and ending
+ * on the day prior to this.
+ * </p>
+ * <p>
+ * The weeks of the year are numbered from 1 to a possible 53. The first week
+ * of the year is defined as the first week that contains at least the minimum
+ * number of days of the first week in the new year (retrieved via
+ * <code>getMinimalDaysInFirstWeek()</code>). All weeks after this are numbered
+ * from 2 onwards.
+ * </p>
+ * <p>
+ * For example, take the year 2004. It began on a Thursday. The first week
+ * of 2004 depends both on where a week begins and how long it must minimally
+ * last. Let's say that the week begins on a Monday and must have a minimum
+ * of 5 days. In this case, the first week begins on Monday, the 5th of January.
+ * The first 4 days (Thursday to Sunday) are not eligible, as they are too few
+ * to make up the minimum number of days of the first week which must be in
+ * the new year. If the minimum was lowered to 4 days, then the first week
+ * would instead begin on Monday, the 29th of December, 2003. This first week
+ * has 4 of its days in the new year, and is now eligible.
+ * </p>
+ * <p>
+ * The weeks of the month are numbered from 0 to a possible 6. The first week
+ * of the month (numbered 1) is a set of days, prior to the first day of the week,
+ * which number at least the minimum number of days in a week. Unlike the first
+ * week of the year, the first week of the month only uses days from that particular
+ * month. As a consequence, it may have a variable number of days (from the minimum
+ * number required up to a full week of 7) and it need not start on the first day of
+ * the week. It must, however, be following by the first day of the week, as this
+ * marks the beginning of week 2. Any days of the month which occur prior to the
+ * first week (because the first day of the week occurs before the minimum number
+ * of days is met) are seen as week 0.
+ * </p>
+ * <p>
+ * Again, we will take the example of the year 2004 to demonstrate this. September
+ * 2004 begins on a Wednesday. Taking our first day of the week as Monday, and the
+ * minimum length of the first week as 6, we find that week 1 runs from Monday,
+ * the 6th of September to Sunday the 12th. Prior to the 6th, there are only
+ * 5 days (Wednesday through to Sunday). This is too small a number to meet the
+ * minimum, so these are classed as being days in week 0. Week 2 begins on the
+ * 13th, and so on. This changes if we reduce the minimum to 5. In this case,
+ * week 1 is a truncated week from Wednesday the 1st to Sunday the 5th, and week
+ * 0 doesn't exist. The first seven day week is week 2, starting on the 6th.
+ * </p>
+ * <p>
+ * On using the <code>clear()</code> method, the Gregorian calendar returns
+ * to its default value of the 1st of January, 1970 AD 00:00:00 (the epoch).
+ * The day of the week is set to the correct day for that particular time.
+ * The day is also the first of the month, and the date is in week 0.
+ * </p>
+ *
+ * @see Calendar
+ * @see TimeZone
+ * @see Calendar#getFirstDayOfWeek()
+ * @see Calendar#getMinimalDaysInFirstWeek()
+ */
+public class GregorianCalendar extends Calendar
+{
+ /**
+ * Constant representing the era BC (Before Christ).
+ */
+ public static final int BC = 0;
+
+ /**
+ * Constant representing the era AD (Anno Domini).
+ */
+ public static final int AD = 1;
+
+ /**
+ * The point at which the Gregorian calendar rules were used.
+ * This is locale dependent; the default for most catholic
+ * countries is midnight (UTC) on October 5, 1582 (Julian),
+ * or October 15, 1582 (Gregorian).
+ *
+ * @serial the changeover point from the Julian calendar
+ * system to the Gregorian.
+ */
+ private long gregorianCutover;
+
+ /**
+ * For compatability with Sun's JDK.
+ */
+ static final long serialVersionUID = -8125100834729963327L;
+
+ /**
+ * The name of the resource bundle. Used only by getBundle()
+ */
+ private static final String bundleName = "gnu.java.locale.Calendar";
+
+ /**
+ * Days in the epoch. Relative Jan 1, year '0' which is not a leap year.
+ * (although there is no year zero, this does not matter.)
+ * This is consistent with the formula:
+ * = (year-1)*365L + ((year-1) >> 2)
+ *
+ * Plus the gregorian correction:
+ * Math.floor((year-1) / 400.) - Math.floor((year-1) / 100.);
+ * For a correct julian date, the correction is -2 instead.
+ *
+ * The gregorian cutover in 1582 was 10 days, so by calculating the
+ * correction from year zero, we have 15 non-leap days (even centuries)
+ * minus 3 leap days (year 400,800,1200) = 12. Subtracting two corrects
+ * this to the correct number 10.
+ */
+ private static final int EPOCH_DAYS = 719162;
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the default time zone and the default locale.
+ */
+ public GregorianCalendar()
+ {
+ this(TimeZone.getDefault(), Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the specified time zone and the default locale.
+ *
+ * @param zone a time zone.
+ */
+ public GregorianCalendar(TimeZone zone)
+ {
+ this(zone, Locale.getDefault());
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time, using the default time zone and the specified locale.
+ *
+ * @param locale a locale.
+ */
+ public GregorianCalendar(Locale locale)
+ {
+ this(TimeZone.getDefault(), locale);
+ }
+
+ /**
+ * Constructs a new GregorianCalender representing the current
+ * time with the given time zone and the given locale.
+ *
+ * @param zone a time zone.
+ * @param locale a locale.
+ */
+ public GregorianCalendar(TimeZone zone, Locale locale)
+ {
+ this(zone, locale, false);
+ setTimeInMillis(System.currentTimeMillis());
+ complete();
+ }
+
+ /**
+ * Common constructor that all constructors should call.
+ * @param zone a time zone.
+ * @param locale a locale.
+ * @param unused unused parameter to make the signature differ from
+ * the public constructor (TimeZone, Locale).
+ */
+ private GregorianCalendar(TimeZone zone, Locale locale, boolean unused)
+ {
+ super(zone, locale);
+ ResourceBundle rb = ResourceBundle.getBundle(bundleName, locale,
+ ClassLoader
+ .getSystemClassLoader());
+ gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime();
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ */
+ public GregorianCalendar(int year, int month, int day)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day);
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ *
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ * @param hour corresponds to the HOUR_OF_DAY time field.
+ * @param minute corresponds to the MINUTE time field.
+ */
+ public GregorianCalendar(int year, int month, int day, int hour, int minute)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day, hour, minute);
+ }
+
+ /**
+ * Constructs a new GregorianCalendar representing midnight on the
+ * given date with the default time zone and locale.
+ *
+ * @param year corresponds to the YEAR time field.
+ * @param month corresponds to the MONTH time field.
+ * @param day corresponds to the DAY time field.
+ * @param hour corresponds to the HOUR_OF_DAY time field.
+ * @param minute corresponds to the MINUTE time field.
+ * @param second corresponds to the SECOND time field.
+ */
+ public GregorianCalendar(int year, int month, int day, int hour, int minute,
+ int second)
+ {
+ this(TimeZone.getDefault(), Locale.getDefault(), false);
+ set(year, month, day, hour, minute, second);
+ }
+
+ /**
+ * Sets the date of the switch from Julian dates to Gregorian dates.
+ * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure
+ * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian
+ * calendar.
+ *
+ * @param date the date of the change.
+ */
+ public void setGregorianChange(Date date)
+ {
+ gregorianCutover = date.getTime();
+ }
+
+ /**
+ * Gets the date of the switch from Julian dates to Gregorian dates.
+ *
+ * @return the date of the change.
+ */
+ public final Date getGregorianChange()
+ {
+ return new Date(gregorianCutover);
+ }
+
+ /**
+ * <p>
+ * Determines if the given year is a leap year. The result is
+ * undefined if the Gregorian change took place in 1800, so that
+ * the end of February is skipped, and that year is specified.
+ * (well...).
+ * </p>
+ * <p>
+ * To specify a year in the BC era, use a negative value calculated
+ * as 1 - y, where y is the required year in BC. So, 1 BC is 0,
+ * 2 BC is -1, 3 BC is -2, etc.
+ * </p>
+ *
+ * @param year a year (use a negative value for BC).
+ * @return true, if the given year is a leap year, false otherwise.
+ */
+ public boolean isLeapYear(int year)
+ {
+ // Only years divisible by 4 can be leap years
+ if ((year & 3) != 0)
+ return false;
+
+ // Is the leap-day a Julian date? Then it's a leap year
+ if (! isGregorian(year, 31 + 29 - 1))
+ return true;
+
+ // Apply gregorian rules otherwise
+ return ((year % 100) != 0 || (year % 400) == 0);
+ }
+
+ /**
+ * Retrieves the day of the week corresponding to the specified
+ * day of the specified year.
+ *
+ * @param year the year in which the dayOfYear occurs.
+ * @param dayOfYear the day of the year (an integer between 0 and
+ * and 366)
+ */
+ private int getWeekDay(int year, int dayOfYear)
+ {
+ boolean greg = isGregorian(year, dayOfYear);
+ int day = (int) getLinearDay(year, dayOfYear, greg);
+
+ // The epoch was a thursday.
+ int weekday = (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ return weekday;
+ }
+
+ /**
+ * Returns the day of the week for the first day of a given month (0..11)
+ */
+ private int getFirstDayOfMonth(int year, int month)
+ {
+ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ if (month > 11)
+ {
+ year += (month / 12);
+ month = month % 12;
+ }
+
+ if (month < 0)
+ {
+ year += (int) month / 12;
+ month = month % 12;
+ if (month < 0)
+ {
+ month += 12;
+ year--;
+ }
+ }
+
+ int dayOfYear = dayCount[month] + 1;
+ if (month > 1)
+ if (isLeapYear(year))
+ dayOfYear++;
+
+ boolean greg = isGregorian(year, dayOfYear);
+ int day = (int) getLinearDay(year, dayOfYear, greg);
+
+ // The epoch was a thursday.
+ int weekday = (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ return weekday;
+ }
+
+ /**
+ * Takes a year, and a (zero based) day of year and determines
+ * if it is gregorian or not.
+ */
+ private boolean isGregorian(int year, int dayOfYear)
+ {
+ int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+ int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ return ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover);
+ }
+
+ /**
+ * Check set fields for validity, without leniency.
+ *
+ * @throws IllegalArgumentException if a field is invalid
+ */
+ private void nonLeniencyCheck() throws IllegalArgumentException
+ {
+ int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int year = fields[YEAR];
+ int month = fields[MONTH];
+ int leap = isLeapYear(year) ? 1 : 0;
+
+ if (isSet[ERA] && fields[ERA] != AD && fields[ERA] != BC)
+ throw new IllegalArgumentException("Illegal ERA.");
+ if (isSet[YEAR] && fields[YEAR] < 1)
+ throw new IllegalArgumentException("Illegal YEAR.");
+ if (isSet[MONTH] && (month < 0 || month > 11))
+ throw new IllegalArgumentException("Illegal MONTH.");
+ if (isSet[WEEK_OF_YEAR])
+ {
+ int daysInYear = 365 + leap;
+ daysInYear += (getFirstDayOfMonth(year, 0) - 1); // pad first week
+ int last = getFirstDayOfMonth(year, 11) + 4;
+ if (last > 7)
+ last -= 7;
+ daysInYear += 7 - last;
+ int weeks = daysInYear / 7;
+ if (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > weeks)
+ throw new IllegalArgumentException("Illegal WEEK_OF_YEAR.");
+ }
+
+ if (isSet[WEEK_OF_MONTH])
+ {
+ int weeks = (month == 1 && leap == 0) ? 4 : 5;
+ if (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > weeks)
+ throw new IllegalArgumentException("Illegal WEEK_OF_MONTH.");
+ }
+
+ if (isSet[DAY_OF_MONTH])
+ if (fields[DAY_OF_MONTH] < 1
+ || fields[DAY_OF_MONTH] > month_days[month]
+ + ((month == 1) ? leap : 0))
+ throw new IllegalArgumentException("Illegal DAY_OF_MONTH.");
+
+ if (isSet[DAY_OF_YEAR]
+ && (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > 365 + leap))
+ throw new IllegalArgumentException("Illegal DAY_OF_YEAR.");
+
+ if (isSet[DAY_OF_WEEK]
+ && (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7))
+ throw new IllegalArgumentException("Illegal DAY_OF_WEEK.");
+
+ if (isSet[DAY_OF_WEEK_IN_MONTH])
+ {
+ int weeks = (month == 1 && leap == 0) ? 4 : 5;
+ if (fields[DAY_OF_WEEK_IN_MONTH] < -weeks
+ || fields[DAY_OF_WEEK_IN_MONTH] > weeks)
+ throw new IllegalArgumentException("Illegal DAY_OF_WEEK_IN_MONTH.");
+ }
+
+ if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM)
+ throw new IllegalArgumentException("Illegal AM_PM.");
+ if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
+ throw new IllegalArgumentException("Illegal HOUR.");
+ if (isSet[HOUR_OF_DAY]
+ && (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23))
+ throw new IllegalArgumentException("Illegal HOUR_OF_DAY.");
+ if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59))
+ throw new IllegalArgumentException("Illegal MINUTE.");
+ if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59))
+ throw new IllegalArgumentException("Illegal SECOND.");
+ if (isSet[MILLISECOND]
+ && (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999))
+ throw new IllegalArgumentException("Illegal MILLISECOND.");
+ if (isSet[ZONE_OFFSET]
+ && (fields[ZONE_OFFSET] < -12 * 60 * 60 * 1000L
+ || fields[ZONE_OFFSET] > 12 * 60 * 60 * 1000L))
+ throw new IllegalArgumentException("Illegal ZONE_OFFSET.");
+ if (isSet[DST_OFFSET]
+ && (fields[DST_OFFSET] < -12 * 60 * 60 * 1000L
+ || fields[DST_OFFSET] > 12 * 60 * 60 * 1000L))
+ throw new IllegalArgumentException("Illegal DST_OFFSET.");
+ }
+
+ /**
+ * Converts the time field values (<code>fields</code>) to
+ * milliseconds since the epoch UTC (<code>time</code>).
+ *
+ * @throws IllegalArgumentException if any calendar fields
+ * are invalid.
+ */
+ protected synchronized void computeTime()
+ {
+ int millisInDay = 0;
+ int era = fields[ERA];
+ int year = fields[YEAR];
+ int month = fields[MONTH];
+ int day = fields[DAY_OF_MONTH];
+
+ int minute = fields[MINUTE];
+ int second = fields[SECOND];
+ int millis = fields[MILLISECOND];
+ int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ int hour = 0;
+
+ if (! isLenient())
+ nonLeniencyCheck();
+
+ if (! isSet[MONTH] && (! isSet[DAY_OF_WEEK] || isSet[WEEK_OF_YEAR]))
+ {
+ // 5: YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
+ if (isSet[WEEK_OF_YEAR])
+ {
+ int first = getFirstDayOfMonth(year, 0);
+ int offs = 1;
+ int daysInFirstWeek = getFirstDayOfWeek() - first;
+ if (daysInFirstWeek <= 0)
+ daysInFirstWeek += 7;
+
+ if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+ offs += daysInFirstWeek;
+ else
+ offs -= 7 - daysInFirstWeek;
+ month = 0;
+ day = offs + 7 * (fields[WEEK_OF_YEAR] - 1);
+ offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+
+ if (offs < 0)
+ offs += 7;
+ day += offs;
+ }
+ else
+ {
+ // 4: YEAR + DAY_OF_YEAR
+ month = 0;
+ day = fields[DAY_OF_YEAR];
+ }
+ }
+ else
+ {
+ if (isSet[DAY_OF_WEEK])
+ {
+ int first = getFirstDayOfMonth(year, month);
+
+ // 3: YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
+ if (isSet[DAY_OF_WEEK_IN_MONTH])
+ {
+ if (fields[DAY_OF_WEEK_IN_MONTH] < 0)
+ {
+ month++;
+ first = getFirstDayOfMonth(year, month);
+ day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH]);
+ }
+ else
+ day = 1 + 7 * (fields[DAY_OF_WEEK_IN_MONTH] - 1);
+
+ int offs = fields[DAY_OF_WEEK] - first;
+ if (offs < 0)
+ offs += 7;
+ day += offs;
+ }
+ else
+ { // 2: YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
+ int offs = 1;
+ int daysInFirstWeek = getFirstDayOfWeek() - first;
+ if (daysInFirstWeek <= 0)
+ daysInFirstWeek += 7;
+
+ if (daysInFirstWeek < getMinimalDaysInFirstWeek())
+ offs += daysInFirstWeek;
+ else
+ offs -= 7 - daysInFirstWeek;
+
+ day = offs + 7 * (fields[WEEK_OF_MONTH] - 1);
+ offs = fields[DAY_OF_WEEK] - getFirstDayOfWeek();
+ if (offs <= 0)
+ offs += 7;
+ day += offs;
+ }
+ }
+
+ // 1: YEAR + MONTH + DAY_OF_MONTH
+ }
+ if (era == BC && year > 0)
+ year = 1 - year;
+
+ // rest of code assumes day/month/year set
+ // should negative BC years be AD?
+ // get the hour (but no check for validity)
+ if (isSet[HOUR])
+ {
+ hour = fields[HOUR];
+ if (fields[AM_PM] == PM)
+ hour += 12;
+ }
+ else
+ hour = fields[HOUR_OF_DAY];
+
+ // Read the era,year,month,day fields and convert as appropriate.
+ // Calculate number of milliseconds into the day
+ // This takes care of both h, m, s, ms over/underflows.
+ long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L + millis;
+ day += allMillis / (24 * 60 * 60 * 1000L);
+ millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
+
+ if (month < 0)
+ {
+ year += (int) month / 12;
+ month = month % 12;
+ if (month < 0)
+ {
+ month += 12;
+ year--;
+ }
+ }
+ if (month > 11)
+ {
+ year += (month / 12);
+ month = month % 12;
+ }
+
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+
+ while (day <= 0)
+ {
+ if (month == 0)
+ {
+ year--;
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+ }
+ month = (month + 11) % 12;
+ day += month_days[month];
+ }
+ while (day > month_days[month])
+ {
+ day -= (month_days[month]);
+ month = (month + 1) % 12;
+ if (month == 0)
+ {
+ year++;
+ month_days[1] = isLeapYear(year) ? 29 : 28;
+ }
+ }
+
+ // ok, by here we have valid day,month,year,era and millisinday
+ int dayOfYear = dayCount[month] + day - 1; // (day starts on 1)
+ if (isLeapYear(year) && month > 1)
+ dayOfYear++;
+
+ int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+ int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover)
+ relativeDay += gregFactor;
+ else
+ relativeDay -= 2;
+
+ time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay;
+
+ // the epoch was a Thursday.
+ int weekday = (int) (relativeDay + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ fields[DAY_OF_WEEK] = weekday;
+
+ // Time zone corrections.
+ TimeZone zone = getTimeZone();
+ int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET]
+ : zone.getRawOffset();
+
+ int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET]
+ : (zone.getOffset((year < 0) ? BC : AD,
+ (year < 0) ? 1 - year
+ : year,
+ month, day, weekday,
+ millisInDay)
+ - zone.getRawOffset());
+
+ time -= rawOffset + dstOffset;
+
+ isTimeSet = true;
+ }
+
+ /**
+ * Get the linear day in days since the epoch, using the
+ * Julian or Gregorian calendar as specified. If you specify a
+ * nonpositive year it is interpreted as BC as following: 0 is 1
+ * BC, -1 is 2 BC and so on.
+ *
+ * @param year the year of the date.
+ * @param dayOfYear the day of year of the date; 1 based.
+ * @param gregorian <code>true</code>, if we should use the Gregorian rules.
+ * @return the days since the epoch, may be negative.
+ */
+ private long getLinearDay(int year, int dayOfYear, boolean gregorian)
+ {
+ // The 13 is the number of days, that were omitted in the Gregorian
+ // Calender until the epoch.
+ // We shift right by 2 instead of dividing by 4, to get correct
+ // results for negative years (and this is even more efficient).
+ long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
+ - EPOCH_DAYS; // gregorian days from 1 to epoch.
+
+ if (gregorian)
+ {
+ // subtract the days that are missing in gregorian calendar
+ // with respect to julian calendar.
+ //
+ // Okay, here we rely on the fact that the gregorian
+ // calendar was introduced in the AD era. This doesn't work
+ // with negative years.
+ //
+ // The additional leap year factor accounts for the fact that
+ // a leap day is not seen on Jan 1 of the leap year.
+ int gregOffset = (int) Math.floor((double) (year - 1) / 400.)
+ - (int) Math.floor((double) (year - 1) / 100.);
+
+ return julianDay + gregOffset;
+ }
+ else
+ julianDay -= 2;
+ return julianDay;
+ }
+
+ /**
+ * Converts the given linear day into era, year, month,
+ * day_of_year, day_of_month, day_of_week, and writes the result
+ * into the fields array.
+ *
+ * @param day the linear day.
+ * @param gregorian true, if we should use Gregorian rules.
+ */
+ private void calculateDay(int[] fields, long day, boolean gregorian)
+ {
+ // the epoch was a Thursday.
+ int weekday = (int) (day + THURSDAY) % 7;
+ if (weekday <= 0)
+ weekday += 7;
+ fields[DAY_OF_WEEK] = weekday;
+
+ // get a first approximation of the year. This may be one
+ // year too big.
+ int year = 1970
+ + (int) (gregorian
+ ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L
+ + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L));
+ if (day >= 0)
+ year++;
+
+ long firstDayOfYear = getLinearDay(year, 1, gregorian);
+
+ // Now look in which year day really lies.
+ if (day < firstDayOfYear)
+ {
+ year--;
+ firstDayOfYear = getLinearDay(year, 1, gregorian);
+ }
+
+ day -= firstDayOfYear - 1; // day of year, one based.
+
+ fields[DAY_OF_YEAR] = (int) day;
+ if (year <= 0)
+ {
+ fields[ERA] = BC;
+ fields[YEAR] = 1 - year;
+ }
+ else
+ {
+ fields[ERA] = AD;
+ fields[YEAR] = year;
+ }
+
+ int leapday = isLeapYear(year) ? 1 : 0;
+ if (day <= 31 + 28 + leapday)
+ {
+ fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY
+ fields[DAY_OF_MONTH] = (int) day - 31 * fields[MONTH];
+ }
+ else
+ {
+ // A few more magic formulas
+ int scaledDay = ((int) day - leapday) * 5 + 8;
+ fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
+ fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
+ }
+ }
+
+ /**
+ * Converts the milliseconds since the epoch UTC
+ * (<code>time</code>) to time fields
+ * (<code>fields</code>).
+ */
+ protected synchronized void computeFields()
+ {
+ boolean gregorian = (time >= gregorianCutover);
+
+ TimeZone zone = getTimeZone();
+ fields[ZONE_OFFSET] = zone.getRawOffset();
+ long localTime = time + fields[ZONE_OFFSET];
+
+ long day = localTime / (24 * 60 * 60 * 1000L);
+ int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
+
+ if (millisInDay < 0)
+ {
+ millisInDay += (24 * 60 * 60 * 1000);
+ day--;
+ }
+
+ calculateDay(fields, day, gregorian);
+ fields[DST_OFFSET] = zone.getOffset(fields[ERA], fields[YEAR],
+ fields[MONTH], fields[DAY_OF_MONTH],
+ fields[DAY_OF_WEEK], millisInDay)
+ - fields[ZONE_OFFSET];
+
+ millisInDay += fields[DST_OFFSET];
+ if (millisInDay >= 24 * 60 * 60 * 1000)
+ {
+ millisInDay -= 24 * 60 * 60 * 1000;
+ calculateDay(fields, ++day, gregorian);
+ }
+
+ fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
+
+ // which day of the week are we (0..6), relative to getFirstDayOfWeek
+ int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
+
+ fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7;
+
+ int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
+
+ // Do the Correction: getMinimalDaysInFirstWeek() is always in the
+ // first week.
+ int minDays = getMinimalDaysInFirstWeek();
+ int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays)
+ - getFirstDayOfWeek()) % 7;
+ if (minDays - firstWeekday < 1)
+ weekOfYear++;
+ fields[WEEK_OF_YEAR] = weekOfYear;
+
+ int hourOfDay = millisInDay / (60 * 60 * 1000);
+ fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
+ int hour = hourOfDay % 12;
+ fields[HOUR] = hour;
+ fields[HOUR_OF_DAY] = hourOfDay;
+ millisInDay %= (60 * 60 * 1000);
+ fields[MINUTE] = millisInDay / (60 * 1000);
+ millisInDay %= (60 * 1000);
+ fields[SECOND] = millisInDay / (1000);
+ fields[MILLISECOND] = millisInDay % 1000;
+
+ areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true;
+ }
+
+ /**
+ * Return a hash code for this object, following the general contract
+ * specified by {@link Object#hashCode()}.
+ * @return the hash code
+ */
+ public int hashCode()
+ {
+ int val = (int) ((gregorianCutover >>> 32) ^ (gregorianCutover & 0xffffffff));
+ return super.hashCode() ^ val;
+ }
+
+ /**
+ * Compares the given calendar with this. An object, o, is
+ * equivalent to this if it is also a <code>GregorianCalendar</code>
+ * with the same time since the epoch under the same conditions
+ * (same change date and same time zone).
+ *
+ * @param o the object to that we should compare.
+ * @return true, if the given object is a calendar, that represents
+ * the same time (but doesn't necessarily have the same fields).
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof GregorianCalendar))
+ return false;
+
+ GregorianCalendar cal = (GregorianCalendar) o;
+ return (cal.gregorianCutover == gregorianCutover
+ && super.equals(o));
+ }
+
+ /**
+ * Adds the specified amount of time to the given time field. The
+ * amount may be negative to subtract the time. If the field overflows
+ * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+ * @param field one of the time field constants.
+ * @param amount the amount of time to add.
+ * @exception IllegalArgumentException if <code>field</code> is
+ * <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or
+ * if <code>amount</code> contains an out-of-range value and the calendar
+ * is not in lenient mode.
+ */
+ public void add(int field, int amount)
+ {
+ switch (field)
+ {
+ case YEAR:
+ complete();
+ fields[YEAR] += amount;
+ isTimeSet = false;
+ break;
+ case MONTH:
+ complete();
+ int months = fields[MONTH] + amount;
+ fields[YEAR] += months / 12;
+ fields[MONTH] = months % 12;
+ if (fields[MONTH] < 0)
+ {
+ fields[MONTH] += 12;
+ fields[YEAR]--;
+ }
+ int maxDay = getActualMaximum(DAY_OF_MONTH);
+ if (fields[DAY_OF_MONTH] > maxDay)
+ fields[DAY_OF_MONTH] = maxDay;
+ set(YEAR, fields[YEAR]);
+ set(MONTH, fields[MONTH]);
+ break;
+ case DAY_OF_MONTH:
+ case DAY_OF_YEAR:
+ case DAY_OF_WEEK:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (24 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case WEEK_OF_YEAR:
+ case WEEK_OF_MONTH:
+ case DAY_OF_WEEK_IN_MONTH:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (7 * 24 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case AM_PM:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (12 * 60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case HOUR:
+ case HOUR_OF_DAY:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (60 * 60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case MINUTE:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (60 * 1000L);
+ areFieldsSet = false;
+ break;
+ case SECOND:
+ if (! isTimeSet)
+ computeTime();
+ time += amount * (1000L);
+ areFieldsSet = false;
+ break;
+ case MILLISECOND:
+ if (! isTimeSet)
+ computeTime();
+ time += amount;
+ areFieldsSet = false;
+ break;
+ case ZONE_OFFSET:
+ case DST_OFFSET:default:
+ throw new IllegalArgumentException("Invalid or unknown field");
+ }
+ }
+
+ /**
+ * Rolls the specified time field up or down. This means add one
+ * to the specified field, but don't change the other fields. If
+ * the maximum for this field is reached, start over with the
+ * minimum value.
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically converted to July, 1.
+ * This requires lenient settings.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param up the direction, true for up, false for down.
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public void roll(int field, boolean up)
+ {
+ roll(field, up ? 1 : -1);
+ }
+
+ /**
+ * Checks that the fields are still within their legal bounds,
+ * following use of the <code>roll()</code> method.
+ *
+ * @param field the field to check.
+ * @param delta multipler for alterations to the <code>time</code>.
+ * @see #roll(int, boolean)
+ * @see #roll(int, int)
+ */
+ private void cleanUpAfterRoll(int field, int delta)
+ {
+ switch (field)
+ {
+ case ERA:
+ case YEAR:
+ case MONTH:
+ // check that day of month is still in correct range
+ if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH))
+ fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH);
+ isTimeSet = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ break;
+ case DAY_OF_MONTH:
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (24 * 60 * 60 * 1000L);
+ break;
+ case WEEK_OF_MONTH:
+ isSet[DAY_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case DAY_OF_WEEK_IN_MONTH:
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case DAY_OF_YEAR:
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_WEEK] = false;
+ isSet[WEEK_OF_YEAR] = false;
+ time += delta * (24 * 60 * 60 * 1000L);
+ break;
+ case WEEK_OF_YEAR:
+ isSet[MONTH] = false;
+ isSet[DAY_OF_MONTH] = false;
+ isSet[WEEK_OF_MONTH] = false;
+ isSet[DAY_OF_WEEK_IN_MONTH] = false;
+ isSet[DAY_OF_YEAR] = false;
+ time += delta * (7 * 24 * 60 * 60 * 1000L);
+ break;
+ case AM_PM:
+ isSet[HOUR_OF_DAY] = false;
+ time += delta * (12 * 60 * 60 * 1000L);
+ break;
+ case HOUR:
+ isSet[HOUR_OF_DAY] = false;
+ time += delta * (60 * 60 * 1000L);
+ break;
+ case HOUR_OF_DAY:
+ isSet[HOUR] = false;
+ isSet[AM_PM] = false;
+ time += delta * (60 * 60 * 1000L);
+ break;
+ case MINUTE:
+ time += delta * (60 * 1000L);
+ break;
+ case SECOND:
+ time += delta * (1000L);
+ break;
+ case MILLISECOND:
+ time += delta;
+ break;
+ }
+ }
+
+ /**
+ * Rolls the specified time field by the given amount. This means
+ * add amount to the specified field, but don't change the other
+ * fields. If the maximum for this field is reached, start over
+ * with the minimum value and vice versa for negative amounts.
+ *
+ * <strong>Note:</strong> There may be situation, where the other
+ * fields must be changed, e.g rolling the month on May, 31.
+ * The date June, 31 is automatically corrected to June, 30.
+ *
+ * @param field the time field. One of the time field constants.
+ * @param amount the amount by which we should roll.
+ * @throws IllegalArgumentException if one of the fields
+ * <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
+ * specified, if an unknown field is specified or if one
+ * of the calendar fields receives an illegal value when
+ * leniancy is not enabled.
+ */
+ public void roll(int field, int amount)
+ {
+ switch (field)
+ {
+ case DAY_OF_WEEK:
+ // day of week is special: it rolls automatically
+ add(field, amount);
+ return;
+ case ZONE_OFFSET:
+ case DST_OFFSET:
+ throw new IllegalArgumentException("Can't roll time zone");
+ }
+ complete();
+ int min = getActualMinimum(field);
+ int range = getActualMaximum(field) - min + 1;
+ int oldval = fields[field];
+ int newval = (oldval - min + range + amount) % range + min;
+ if (newval < min)
+ newval += range;
+ fields[field] = newval;
+ cleanUpAfterRoll(field, newval - oldval);
+ }
+
+ /**
+ * The minimum values for the calendar fields.
+ */
+ private static final int[] minimums =
+ {
+ BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, AM,
+ 1, 0, 0, 0, 0, -(12 * 60 * 60 * 1000),
+ 0
+ };
+
+ /**
+ * The maximum values for the calendar fields.
+ */
+ private static final int[] maximums =
+ {
+ AD, 5000000, 11, 53, 5, 31, 366,
+ SATURDAY, 5, PM, 12, 23, 59, 59, 999,
+ +(12 * 60 * 60 * 1000),
+ (12 * 60 * 60 * 1000)
+ };
+
+ /**
+ * Gets the smallest value that is allowed for the specified field.
+ *
+ * @param field one of the time field constants.
+ * @return the smallest value for the specified field.
+ */
+ public int getMinimum(int field)
+ {
+ return minimums[field];
+ }
+
+ /**
+ * Gets the biggest value that is allowed for the specified field.
+ *
+ * @param field one of the time field constants.
+ * @return the biggest value.
+ */
+ public int getMaximum(int field)
+ {
+ return maximums[field];
+ }
+
+ /**
+ * Gets the greatest minimum value that is allowed for the specified field.
+ * This is the largest value returned by the <code>getActualMinimum(int)</code>
+ * method.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the greatest minimum value.
+ * @see #getActualMinimum(int)
+ */
+ public int getGreatestMinimum(int field)
+ {
+ if (field == WEEK_OF_YEAR)
+ return 1;
+ return minimums[field];
+ }
+
+ /**
+ * Gets the smallest maximum value that is allowed for the
+ * specified field. This is the smallest value returned
+ * by the <code>getActualMaximum(int)</code>. For example,
+ * this is 28 for DAY_OF_MONTH (as all months have at least
+ * 28 days).
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the least maximum value.
+ * @see #getActualMaximum(int)
+ * @since 1.2
+ */
+ public int getLeastMaximum(int field)
+ {
+ switch (field)
+ {
+ case WEEK_OF_YEAR:
+ return 52;
+ case DAY_OF_MONTH:
+ return 28;
+ case DAY_OF_YEAR:
+ return 365;
+ case DAY_OF_WEEK_IN_MONTH:
+ case WEEK_OF_MONTH:
+ return 4;
+ default:
+ return maximums[field];
+ }
+ }
+
+ /**
+ * Gets the actual minimum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields. Note that
+ * this calls <code>complete()</code> if not enough fields are set. This
+ * can have ugly side effects. The value given depends on the current
+ * time used by this instance.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the actual minimum value.
+ * @since 1.2
+ */
+ public int getActualMinimum(int field)
+ {
+ if (field == WEEK_OF_YEAR)
+ {
+ int min = getMinimalDaysInFirstWeek();
+ if (min == 0)
+ return 1;
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ int weekday = getWeekDay(year, min);
+ if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1)
+ return 1;
+ return 0;
+ }
+ return minimums[field];
+ }
+
+ /**
+ * Gets the actual maximum value that is allowed for the specified field.
+ * This value is dependent on the values of the other fields. Note that
+ * this calls <code>complete()</code> if not enough fields are set. This
+ * can have ugly side effects. The value given depends on the current time
+ * used by this instance; thus, leap years have a maximum day of month value of
+ * 29, rather than 28.
+ *
+ * @param field the time field. One of the time field constants.
+ * @return the actual maximum value.
+ */
+ public int getActualMaximum(int field)
+ {
+ switch (field)
+ {
+ case WEEK_OF_YEAR:
+ {
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+
+ // This is wrong for the year that contains the gregorian change.
+ // I.e it gives the weeks in the julian year or in the gregorian
+ // year in that case.
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ int lastDay = isLeapYear(year) ? 366 : 365;
+ int weekday = getWeekDay(year, lastDay);
+ int week = (lastDay + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+
+ int minimalDays = getMinimalDaysInFirstWeek();
+ int firstWeekday = getWeekDay(year, minimalDays);
+ /*
+ * Is there a set of days at the beginning of the year, before the
+ * first day of the week, equal to or greater than the minimum number
+ * of days required in the first week?
+ */
+ if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1)
+ return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */
+ }
+ case DAY_OF_MONTH:
+ {
+ if (! areFieldsSet || ! isSet[MONTH])
+ complete();
+ int month = fields[MONTH];
+
+ // If you change this, you should also change
+ // SimpleTimeZone.getDaysInMonth();
+ if (month == FEBRUARY)
+ {
+ if (! isSet[YEAR] || ! isSet[ERA])
+ complete();
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ return isLeapYear(year) ? 29 : 28;
+ }
+ else if (month < AUGUST)
+ return 31 - (month & 1);
+ else
+ return 30 + (month & 1);
+ }
+ case DAY_OF_YEAR:
+ {
+ if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR])
+ complete();
+ int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+ return isLeapYear(year) ? 366 : 365;
+ }
+ case DAY_OF_WEEK_IN_MONTH:
+ {
+ // This is wrong for the month that contains the gregorian change.
+ int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+
+ // That's black magic, I know
+ return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7;
+ }
+ case WEEK_OF_MONTH:
+ {
+ int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+ int weekday = (daysInMonth - fields[DAY_OF_MONTH]
+ + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY;
+ return (daysInMonth + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+ }
+ default:
+ return maximums[field];
+ }
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/Locale.java b/gcc-4.2.1/libjava/java/util/Locale.java
new file mode 100644
index 000000000..03689aa7a
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/Locale.java
@@ -0,0 +1,864 @@
+/* Locale.java -- i18n locales
+ Copyright (C) 1998, 1999, 2001, 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.SystemProperties;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Locales represent a specific country and culture. Classes which can be
+ * passed a Locale object tailor their information for a given locale. For
+ * instance, currency number formatting is handled differently for the USA
+ * and France.
+ *
+ * <p>Locales are made up of a language code, a country code, and an optional
+ * set of variant strings. Language codes are represented by
+ * <a href="http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt">
+ * ISO 639:1988</a> w/ additions from ISO 639/RA Newsletter No. 1/1989
+ * and a decision of the Advisory Committee of ISO/TC39 on August 8, 1997.
+ *
+ * <p>Country codes are represented by
+ * <a href="http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html">
+ * ISO 3166</a>. Variant strings are vendor and browser specific. Standard
+ * variant strings include "POSIX" for POSIX, "WIN" for MS-Windows, and
+ * "MAC" for Macintosh. When there is more than one variant string, they must
+ * be separated by an underscore (U+005F).
+ *
+ * <p>The default locale is determined by the values of the system properties
+ * user.language, user.region, and user.variant, defaulting to "en". Note that
+ * the locale does NOT contain the conversion and formatting capabilities (for
+ * that, use ResourceBundle and java.text). Rather, it is an immutable tag
+ * object for identifying a given locale, which is referenced by these other
+ * classes when they must make locale-dependent decisions.
+ *
+ * @see ResourceBundle
+ * @see java.text.Format
+ * @see java.text.NumberFormat
+ * @see java.text.Collator
+ * @author Jochen Hoenicke
+ * @author Paul Fisher
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Locale implements Serializable, Cloneable
+{
+ /** Locale which represents the English language. */
+ public static final Locale ENGLISH = getLocale("en");
+
+ /** Locale which represents the French language. */
+ public static final Locale FRENCH = getLocale("fr");
+
+ /** Locale which represents the German language. */
+ public static final Locale GERMAN = getLocale("de");
+
+ /** Locale which represents the Italian language. */
+ public static final Locale ITALIAN = getLocale("it");
+
+ /** Locale which represents the Japanese language. */
+ public static final Locale JAPANESE = getLocale("ja");
+
+ /** Locale which represents the Korean language. */
+ public static final Locale KOREAN = getLocale("ko");
+
+ /** Locale which represents the Chinese language. */
+ public static final Locale CHINESE = getLocale("zh");
+
+ /** Locale which represents the Chinese language as used in China. */
+ public static final Locale SIMPLIFIED_CHINESE = getLocale("zh", "CN");
+
+ /**
+ * Locale which represents the Chinese language as used in Taiwan.
+ * Same as TAIWAN Locale.
+ */
+ public static final Locale TRADITIONAL_CHINESE = getLocale("zh", "TW");
+
+ /** Locale which represents France. */
+ public static final Locale FRANCE = getLocale("fr", "FR");
+
+ /** Locale which represents Germany. */
+ public static final Locale GERMANY = getLocale("de", "DE");
+
+ /** Locale which represents Italy. */
+ public static final Locale ITALY = getLocale("it", "IT");
+
+ /** Locale which represents Japan. */
+ public static final Locale JAPAN = getLocale("ja", "JP");
+
+ /** Locale which represents Korea. */
+ public static final Locale KOREA = getLocale("ko", "KR");
+
+ /**
+ * Locale which represents China.
+ * Same as SIMPLIFIED_CHINESE Locale.
+ */
+ public static final Locale CHINA = SIMPLIFIED_CHINESE;
+
+ /**
+ * Locale which represents the People's Republic of China.
+ * Same as CHINA Locale.
+ */
+ public static final Locale PRC = CHINA;
+
+ /**
+ * Locale which represents Taiwan.
+ * Same as TRADITIONAL_CHINESE Locale.
+ */
+ public static final Locale TAIWAN = TRADITIONAL_CHINESE;
+
+ /** Locale which represents the United Kingdom. */
+ public static final Locale UK = getLocale("en", "GB");
+
+ /** Locale which represents the United States. */
+ public static final Locale US = getLocale("en", "US");
+
+ /** Locale which represents the English speaking portion of Canada. */
+ public static final Locale CANADA = getLocale("en", "CA");
+
+ /** Locale which represents the French speaking portion of Canada. */
+ public static final Locale CANADA_FRENCH = getLocale("fr", "CA");
+
+ /**
+ * Compatible with JDK 1.1+.
+ */
+ private static final long serialVersionUID = 9149081749638150636L;
+
+ /**
+ * The language code, as returned by getLanguage().
+ *
+ * @serial the languange, possibly ""
+ */
+ private String language;
+
+ /**
+ * The country code, as returned by getCountry().
+ *
+ * @serial the country, possibly ""
+ */
+ private String country;
+
+ /**
+ * The variant code, as returned by getVariant().
+ *
+ * @serial the variant, possibly ""
+ */
+ private String variant;
+
+ /**
+ * This is the cached hashcode. When writing to stream, we write -1.
+ *
+ * @serial should be -1 in serial streams
+ */
+ private int hashcode;
+
+ /**
+ * The default locale. Except for during bootstrapping, this should never be
+ * null. Note the logic in the main constructor, to detect when
+ * bootstrapping has completed.
+ */
+ private static Locale defaultLocale =
+ getLocale(SystemProperties.getProperty("user.language", "en"),
+ SystemProperties.getProperty("user.region", ""),
+ SystemProperties.getProperty("user.variant", ""));
+
+ /**
+ * Retrieves the locale with the specified language from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language)
+ {
+ return getLocale(language, "", "");
+ }
+
+ /**
+ * Retrieves the locale with the specified language and region
+ * from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @param region the region of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language, String region)
+ {
+ return getLocale(language, region, "");
+ }
+
+ /**
+ * Retrieves the locale with the specified language, region
+ * and variant from the cache.
+ *
+ * @param language the language of the locale to retrieve.
+ * @param region the region of the locale to retrieve.
+ * @param variant the variant of the locale to retrieve.
+ * @return the locale.
+ */
+ private static Locale getLocale(String language, String region, String variant)
+ {
+ return new Locale(language, region, variant);
+ }
+
+ /**
+ * Convert new iso639 codes to the old ones.
+ *
+ * @param language the language to check
+ * @return the appropriate code
+ */
+ private String convertLanguage(String language)
+ {
+ if (language.equals(""))
+ return language;
+ language = language.toLowerCase();
+ int index = "he,id,yi".indexOf(language);
+ if (index != -1)
+ return "iw,in,ji".substring(index, index + 2);
+ return language;
+ }
+
+ /**
+ * Creates a new locale for the given language and country.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @param country uppercase two-letter ISO-3166 A2 contry code
+ * @param variant vendor and browser specific
+ * @throws NullPointerException if any argument is null
+ */
+ public Locale(String language, String country, String variant)
+ {
+ // During bootstrap, we already know the strings being passed in are
+ // the correct capitalization, and not null. We can't call
+ // String.toUpperCase during this time, since that depends on the
+ // default locale.
+ if (defaultLocale != null)
+ {
+ language = convertLanguage(language).intern();
+ country = country.toUpperCase().intern();
+ variant = variant.intern();
+ }
+ this.language = language;
+ this.country = country;
+ this.variant = variant;
+ hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+ }
+
+ /**
+ * Creates a new locale for the given language and country.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @param country uppercase two-letter ISO-3166 A2 country code
+ * @throws NullPointerException if either argument is null
+ */
+ public Locale(String language, String country)
+ {
+ this(language, country, "");
+ }
+
+ /**
+ * Creates a new locale for a language.
+ *
+ * @param language lowercase two-letter ISO-639 A2 language code
+ * @throws NullPointerException if either argument is null
+ * @since 1.4
+ */
+ public Locale(String language)
+ {
+ this(language, "", "");
+ }
+
+ /**
+ * Returns the default Locale. The default locale is generally once set
+ * on start up and then never changed. Normally you should use this locale
+ * for everywhere you need a locale. The initial setting matches the
+ * default locale, the user has chosen.
+ *
+ * @return the default locale for this virtual machine
+ */
+ public static Locale getDefault()
+ {
+ return defaultLocale;
+ }
+
+ /**
+ * Changes the default locale. Normally only called on program start up.
+ * Note that this doesn't change the locale for other programs. This has
+ * a security check,
+ * <code>PropertyPermission("user.language", "write")</code>, because of
+ * its potential impact to running code.
+ *
+ * @param newLocale the new default locale
+ * @throws NullPointerException if newLocale is null
+ * @throws SecurityException if permission is denied
+ */
+ public static void setDefault(Locale newLocale)
+ {
+ if (newLocale == null)
+ throw new NullPointerException();
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(new PropertyPermission("user.language", "write"));
+ defaultLocale = newLocale;
+ }
+
+ /**
+ * Returns the list of available locales.
+ *
+ * @return the installed locales
+ */
+ public static Locale[] getAvailableLocales()
+ {
+ /* I only return those for which localized language
+ * or country information exists.
+ * XXX - remove hard coded list, and implement more locales (Sun's JDK 1.4
+ * has 148 installed locales!).
+ */
+ return new Locale[]
+ {
+ ENGLISH, FRENCH, GERMAN, new Locale("ga", "")
+ };
+ }
+
+ /**
+ * Returns a list of all 2-letter uppercase country codes as defined
+ * in ISO 3166.
+ *
+ * @return a list of acceptable country codes
+ */
+ public static String[] getISOCountries()
+ {
+ return new String[]
+ {
+ "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS",
+ "AT", "AU", "AW", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI",
+ "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ", "CA",
+ "CC", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU",
+ "CV", "CX", "CY", "CZ", "DE", "DJ", "DK", "DM", "DO", "DZ", "EC", "EE",
+ "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FR", "FX",
+ "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ",
+ "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU",
+ "ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP",
+ "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA",
+ "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC",
+ "MD", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS",
+ "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG",
+ "NI", "NL", "NO", "NP", "NR", "NU", "NZ", "OM", "PA", "PE", "PF", "PG",
+ "PH", "PK", "PL", "PM", "PN", "PR", "PT", "PW", "PY", "QA", "RE", "RO",
+ "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK",
+ "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ", "TC", "TD", "TF",
+ "TG", "TH", "TJ", "TK", "TM", "TN", "TO", "TP", "TR", "TT", "TV", "TW",
+ "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VE", "VG", "VI",
+ "VN", "VU", "WF", "WS", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW"
+ };
+ }
+
+ /**
+ * Returns a list of all 2-letter lowercase language codes as defined
+ * in ISO 639 (both old and new variant).
+ *
+ * @return a list of acceptable language codes
+ */
+ public static String[] getISOLanguages()
+ {
+ return new String[]
+ {
+ "aa", "ab", "af", "am", "ar", "as", "ay", "az", "ba", "be", "bg", "bh",
+ "bi", "bn", "bo", "br", "ca", "co", "cs", "cy", "da", "de", "dz", "el",
+ "en", "eo", "es", "et", "eu", "fa", "fi", "fj", "fo", "fr", "fy", "ga",
+ "gd", "gl", "gn", "gu", "ha", "he", "hi", "hr", "hu", "hy", "ia", "id",
+ "ie", "ik", "in", "is", "it", "iu", "iw", "ja", "ji", "jw", "ka", "kk",
+ "kl", "km", "kn", "ko", "ks", "ku", "ky", "la", "ln", "lo", "lt", "lv",
+ "mg", "mi", "mk", "ml", "mn", "mo", "mr", "ms", "mt", "my", "na", "ne",
+ "nl", "no", "oc", "om", "or", "pa", "pl", "ps", "pt", "qu", "rm", "rn",
+ "ro", "ru", "rw", "sa", "sd", "sg", "sh", "si", "sk", "sl", "sm", "sn",
+ "so", "sq", "sr", "ss", "st", "su", "sv", "sw", "ta", "te", "tg", "th",
+ "ti", "tk", "tl", "tn", "to", "tr", "ts", "tt", "tw", "ug", "uk", "ur",
+ "uz", "vi", "vo", "wo", "xh", "yi", "yo", "za", "zh", "zu"
+ };
+ }
+
+ /**
+ * Returns the language code of this locale. Some language codes have changed
+ * as ISO 639 has evolved; this returns the old name, even if you built
+ * the locale with the new one.
+ *
+ * @return language code portion of this locale, or an empty String
+ */
+ public String getLanguage()
+ {
+ return language;
+ }
+
+ /**
+ * Returns the country code of this locale.
+ *
+ * @return country code portion of this locale, or an empty String
+ */
+ public String getCountry()
+ {
+ return country;
+ }
+
+ /**
+ * Returns the variant code of this locale.
+ *
+ * @return the variant code portion of this locale, or an empty String
+ */
+ public String getVariant()
+ {
+ return variant;
+ }
+
+ /**
+ * Gets the string representation of the current locale. This consists of
+ * the language, the country, and the variant, separated by an underscore.
+ * The variant is listed only if there is a language or country. Examples:
+ * "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr__MAC".
+ *
+ * @return the string representation of this Locale
+ * @see #getDisplayName()
+ */
+ public String toString()
+ {
+ if (language.length() == 0 && country.length() == 0)
+ return "";
+ else if (country.length() == 0 && variant.length() == 0)
+ return language;
+ StringBuffer result = new StringBuffer(language);
+ result.append('_').append(country);
+ if (variant.length() != 0)
+ result.append('_').append(variant);
+ return result.toString();
+ }
+
+ /**
+ * Returns the three-letter ISO language abbrevation of this locale.
+ *
+ * @throws MissingResourceException if the three-letter code is not known
+ */
+ public String getISO3Language()
+ {
+ // We know all strings are interned so we can use '==' for better performance.
+ if (language == "")
+ return "";
+ int index
+ = ("aa,ab,af,am,ar,as,ay,az,ba,be,bg,bh,bi,bn,bo,br,ca,co,cs,cy,da,"
+ + "de,dz,el,en,eo,es,et,eu,fa,fi,fj,fo,fr,fy,ga,gd,gl,gn,gu,ha,iw,"
+ + "hi,hr,hu,hy,ia,in,ie,ik,in,is,it,iu,iw,ja,ji,jw,ka,kk,kl,km,kn,"
+ + "ko,ks,ku,ky,la,ln,lo,lt,lv,mg,mi,mk,ml,mn,mo,mr,ms,mt,my,na,ne,"
+ + "nl,no,oc,om,or,pa,pl,ps,pt,qu,rm,rn,ro,ru,rw,sa,sd,sg,sh,si,sk,"
+ + "sl,sm,sn,so,sq,sr,ss,st,su,sv,sw,ta,te,tg,th,ti,tk,tl,tn,to,tr,"
+ + "ts,tt,tw,ug,uk,ur,uz,vi,vo,wo,xh,ji,yo,za,zh,zu")
+ .indexOf(language);
+
+ if (index % 3 != 0 || language.length() != 2)
+ throw new MissingResourceException
+ ("Can't find ISO3 language for " + language,
+ "java.util.Locale", language);
+
+ // Don't read this aloud. These are the three letter language codes.
+ return
+ ("aarabkaframharaasmaymazebakbelbulbihbisbenbodbrecatcoscescymdandeu"
+ + "dzoellengepospaesteusfasfinfijfaofrafrygaigdhglggrngujhauhebhinhrv"
+ + "hunhyeinaindileipkindislitaikuhebjpnyidjawkatkazkalkhmkankorkaskur"
+ + "kirlatlinlaolitlavmlgmrimkdmalmonmolmarmsamltmyanaunepnldnorociorm"
+ + "oripanpolpusporquerohrunronruskinsansndsagsrpsinslkslvsmosnasomsqi"
+ + "srpsswsotsunsweswatamteltgkthatirtuktgltsntonturtsotattwiuigukrurd"
+ + "uzbvievolwolxhoyidyorzhazhozul")
+ .substring(index, index + 3);
+ }
+
+ /**
+ * Returns the three-letter ISO country abbrevation of the locale.
+ *
+ * @throws MissingResourceException if the three-letter code is not known
+ */
+ public String getISO3Country()
+ {
+ // We know all strings are interned so we can use '==' for better performance.
+ if (country == "")
+ return "";
+ int index
+ = ("AD,AE,AF,AG,AI,AL,AM,AN,AO,AQ,AR,AS,AT,AU,AW,AZ,BA,BB,BD,BE,BF,"
+ + "BG,BH,BI,BJ,BM,BN,BO,BR,BS,BT,BV,BW,BY,BZ,CA,CC,CF,CG,CH,CI,CK,"
+ + "CL,CM,CN,CO,CR,CU,CV,CX,CY,CZ,DE,DJ,DK,DM,DO,DZ,EC,EE,EG,EH,ER,"
+ + "ES,ET,FI,FJ,FK,FM,FO,FR,FX,GA,GB,GD,GE,GF,GH,GI,GL,GM,GN,GP,GQ,"
+ + "GR,GS,GT,GU,GW,GY,HK,HM,HN,HR,HT,HU,ID,IE,IL,IN,IO,IQ,IR,IS,IT,"
+ + "JM,JO,JP,KE,KG,KH,KI,KM,KN,KP,KR,KW,KY,KZ,LA,LB,LC,LI,LK,LR,LS,"
+ + "LT,LU,LV,LY,MA,MC,MD,MG,MH,MK,ML,MM,MN,MO,MP,MQ,MR,MS,MT,MU,MV,"
+ + "MW,MX,MY,MZ,NA,NC,NE,NF,NG,NI,NL,NO,NP,NR,NU,NZ,OM,PA,PE,PF,PG,"
+ + "PH,PK,PL,PM,PN,PR,PT,PW,PY,QA,RE,RO,RU,RW,SA,SB,SC,SD,SE,SG,SH,"
+ + "SI,SJ,SK,SL,SM,SN,SO,SR,ST,SV,SY,SZ,TC,TD,TF,TG,TH,TJ,TK,TM,TN,"
+ + "TO,TP,TR,TT,TV,TW,TZ,UA,UG,UM,US,UY,UZ,VA,VC,VE,VG,VI,VN,VU,WF,"
+ + "WS,YE,YT,YU,ZA,ZM,ZR,ZW")
+ .indexOf(country);
+
+ if (index % 3 != 0 || country.length() != 2)
+ throw new MissingResourceException
+ ("Can't find ISO3 country for " + country,
+ "java.util.Locale", country);
+
+ // Don't read this aloud. These are the three letter country codes.
+ return
+ ("ANDAREAFGATGAIAALBARMANTAGOATAARGASMAUTAUSABWAZEBIHBRBBGDBELBFABGR"
+ + "BHRBDIBENBMUBRNBOLBRABHSBTNBVTBWABLRBLZCANCCKCAFCOGCHECIVCOKCHLCMR"
+ + "CHNCOLCRICUBCPVCXRCYPCZEDEUDJIDNKDMADOMDZAECUESTEGYESHERIESPETHFIN"
+ + "FJIFLKFSMFROFRAFXXGABGBRGRDGEOGUFGHAGIBGRLGMBGINGLPGNQGRCSGSGTMGUM"
+ + "GNBGUYHKGHMDHNDHRVHTIHUNIDNIRLISRINDIOTIRQIRNISLITAJAMJORJPNKENKGZ"
+ + "KHMKIRCOMKNAPRKKORKWTCYMKAZLAOLBNLCALIELKALBRLSOLTULUXLVALBYMARMCO"
+ + "MDAMDGMHLMKDMLIMMRMNGMACMNPMTQMRTMSRMLTMUSMDVMWIMEXMYSMOZNAMNCLNER"
+ + "NFKNGANICNLDNORNPLNRUNIUNZLOMNPANPERPYFPNGPHLPAKPOLSPMPCNPRIPRTPLW"
+ + "PRYQATREUROMRUSRWASAUSLBSYCSDNSWESGPSHNSVNSJMSVKSLESMRSENSOMSURSTP"
+ + "SLVSYRSWZTCATCDATFTGOTHATJKTKLTKMTUNTONTMPTURTTOTUVTWNTZAUKRUGAUMI"
+ + "USAURYUZBVATVCTVENVGBVIRVNMVUTWLFWSMYEMMYTYUGZAFZMBZARZWE")
+ .substring(index, index + 3);
+ }
+
+ /**
+ * Gets the country name suitable for display to the user, formatted
+ * for the default locale. This has the same effect as
+ * <pre>
+ * getDisplayLanguage(Locale.getDefault());
+ * </pre>
+ *
+ * @return the language name of this locale localized to the default locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayLanguage()
+ {
+ return getDisplayLanguage(defaultLocale);
+ }
+
+ /**
+ * <p>
+ * Gets the name of the language specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is
+ * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+ * the result would be 'German'. Using the German locale would instead give
+ * 'Deutsch'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the language is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the language name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayLanguage(Locale inLocale)
+ {
+ try
+ {
+ ResourceBundle bundle
+ = ResourceBundle.getBundle("gnu.java.locale.iso639", inLocale);
+ return bundle.getString(language);
+ }
+ catch (MissingResourceException ex)
+ {
+ return language;
+ }
+ }
+
+ /**
+ * Returns the country name of this locale localized to the
+ * default locale. If the localized is not found, the ISO code
+ * is returned. This has the same effect as
+ * <pre>
+ * getDisplayCountry(Locale.getDefault());
+ * </pre>
+ *
+ * @return the country name of this locale localized to the given locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayCountry()
+ {
+ return getDisplayCountry(defaultLocale);
+ }
+
+ /**
+ * <p>
+ * Gets the name of the country specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is
+ * <code>Locale.GERMANY</code>, and the specified locale is <code>Locale.UK</code>,
+ * the result would be 'Germany'. Using the German locale would instead give
+ * 'Deutschland'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the country is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the country name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayCountry(Locale inLocale)
+ {
+ try
+ {
+ ResourceBundle bundle =
+ ResourceBundle.getBundle("gnu.java.locale.iso3166", inLocale);
+ return bundle.getString(country);
+ }
+ catch (MissingResourceException ex)
+ {
+ return country;
+ }
+ }
+
+ /**
+ * Returns the variant name of this locale localized to the
+ * default locale. If the localized is not found, the variant code
+ * itself is returned. This has the same effect as
+ * <pre>
+ * getDisplayVariant(Locale.getDefault());
+ * </pre>
+ *
+ * @return the variant code of this locale localized to the given locale,
+ * with the ISO code as backup
+ */
+ public String getDisplayVariant()
+ {
+ return getDisplayVariant(defaultLocale);
+ }
+
+ /**
+ * <p>
+ * Gets the name of the variant specified by this locale, in a form suitable
+ * for display to the user. If possible, the display name will be localized
+ * to the specified locale. For example, if the locale instance is a revised
+ * variant, and the specified locale is <code>Locale.UK</code>, the result
+ * would be 'REVISED'. Using the German locale would instead give
+ * 'Revidiert'. If the display name can not be localized to the supplied
+ * locale, it will fall back on other output in the following order:
+ * </p>
+ * <ul>
+ * <li>the display name in the default locale</li>
+ * <li>the display name in English</li>
+ * <li>the ISO code</li>
+ * </ul>
+ * <p>
+ * If the variant is unspecified by this locale, then the empty string is
+ * returned.
+ * </p>
+ *
+ * @param inLocale the locale to use for formatting the display string.
+ * @return the variant name of this locale localized to the given locale,
+ * with the default locale, English and the ISO code as backups.
+ * @throws NullPointerException if the supplied locale is null.
+ */
+ public String getDisplayVariant(Locale inLocale)
+ {
+ // XXX - load a bundle?
+ return variant;
+ }
+
+ /**
+ * Gets all local components suitable for display to the user, formatted
+ * for the default locale. For the language component, getDisplayLanguage
+ * is called. For the country component, getDisplayCountry is called.
+ * For the variant set component, getDisplayVariant is called.
+ *
+ * <p>The returned String will be one of the following forms:<br>
+ * <pre>
+ * language (country, variant)
+ * language (country)
+ * language (variant)
+ * country (variant)
+ * language
+ * country
+ * variant
+ * </pre>
+ *
+ * @return String version of this locale, suitable for display to the user
+ */
+ public String getDisplayName()
+ {
+ return getDisplayName(defaultLocale);
+ }
+
+ /**
+ * Gets all local components suitable for display to the user, formatted
+ * for a specified locale. For the language component,
+ * getDisplayLanguage(Locale) is called. For the country component,
+ * getDisplayCountry(Locale) is called. For the variant set component,
+ * getDisplayVariant(Locale) is called.
+ *
+ * <p>The returned String will be one of the following forms:<br>
+ * <pre>
+ * language (country, variant)
+ * language (country)
+ * language (variant)
+ * country (variant)
+ * language
+ * country
+ * variant
+ * </pre>
+ *
+ * @param locale locale to use for formatting
+ * @return String version of this locale, suitable for display to the user
+ */
+ public String getDisplayName(Locale locale)
+ {
+ StringBuffer result = new StringBuffer();
+ int count = 0;
+ String[] delimiters = {"", " (", ","};
+ if (language.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayLanguage(locale));
+ }
+ if (country.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayCountry(locale));
+ }
+ if (variant.length() != 0)
+ {
+ result.append(delimiters[count++]);
+ result.append(getDisplayVariant(locale));
+ }
+ if (count > 1)
+ result.append(")");
+ return result.toString();
+ }
+
+ /**
+ * Does the same as <code>Object.clone()</code> but does not throw
+ * a <code>CloneNotSupportedException</code>. Why anyone would
+ * use this method is a secret to me, since this class is immutable.
+ *
+ * @return the clone
+ */
+ public Object clone()
+ {
+ // This class is final, so no need to use native super.clone().
+ return new Locale(language, country, variant);
+ }
+
+ /**
+ * Return the hash code for this locale. The hashcode is the logical
+ * xor of the hash codes of the language, the country and the variant.
+ * The hash code is precomputed, since <code>Locale</code>s are often
+ * used in hash tables.
+ *
+ * @return the hashcode
+ */
+ public int hashCode()
+ {
+ return hashcode;
+ }
+
+ /**
+ * Compares two locales. To be equal, obj must be a Locale with the same
+ * language, country, and variant code.
+ *
+ * @param obj the other locale
+ * @return true if obj is equal to this
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (! (obj instanceof Locale))
+ return false;
+ Locale l = (Locale) obj;
+
+ return (language == l.language
+ && country == l.country
+ && variant == l.variant);
+ }
+
+ /**
+ * Write the locale to an object stream.
+ *
+ * @param output the stream to write to
+ * @throws IOException if the write fails
+ * @serialData The first three fields are Strings representing language,
+ * country, and variant. The fourth field is a placeholder for
+ * the cached hashcode, but this is always written as -1, and
+ * recomputed when reading it back.
+ */
+ private void writeObject(ObjectOutputStream s)
+ throws IOException
+ {
+ ObjectOutputStream.PutField fields = s.putFields();
+ fields.put("hashcode", -1);
+ s.defaultWriteObject();
+ }
+
+ /**
+ * Reads a locale from the input stream.
+ *
+ * @param input the stream to read from
+ * @throws IOException if reading fails
+ * @throws ClassNotFoundException if reading fails
+ * @serialData the hashCode is always invalid and must be recomputed
+ */
+ private void readObject(ObjectInputStream s)
+ throws IOException, ClassNotFoundException
+ {
+ s.defaultReadObject();
+ language = language.intern();
+ country = country.intern();
+ variant = variant.intern();
+ hashcode = language.hashCode() ^ country.hashCode() ^ variant.hashCode();
+ }
+} // class Locale
diff --git a/gcc-4.2.1/libjava/java/util/ResourceBundle.java b/gcc-4.2.1/libjava/java/util/ResourceBundle.java
new file mode 100644
index 000000000..19dd3cdf1
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/ResourceBundle.java
@@ -0,0 +1,580 @@
+/* ResourceBundle -- aids in loading resource bundles
+ Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A resource bundle contains locale-specific data. If you need localized
+ * data, you can load a resource bundle that matches the locale with
+ * <code>getBundle</code>. Now you can get your object by calling
+ * <code>getObject</code> or <code>getString</code> on that bundle.
+ *
+ * <p>When a bundle is demanded for a specific locale, the ResourceBundle
+ * is searched in following order (<i>def. language</i> stands for the
+ * two letter ISO language code of the default locale (see
+ * <code>Locale.getDefault()</code>).
+ *
+<pre>baseName_<i>language code</i>_<i>country code</i>_<i>variant</i>
+baseName_<i>language code</i>_<i>country code</i>
+baseName_<i>language code</i>
+baseName_<i>def. language</i>_<i>def. country</i>_<i>def. variant</i>
+baseName_<i>def. language</i>_<i>def. country</i>
+baseName_<i>def. language</i>
+baseName</pre>
+ *
+ * <p>A bundle is backed up by less specific bundles (omitting variant, country
+ * or language). But it is not backed up by the default language locale.
+ *
+ * <p>If you provide a bundle for a given locale, say
+ * <code>Bundle_en_UK_POSIX</code>, you must also provide a bundle for
+ * all sub locales, ie. <code>Bundle_en_UK</code>, <code>Bundle_en</code>, and
+ * <code>Bundle</code>.
+ *
+ * <p>When a bundle is searched, we look first for a class with the given
+ * name, then for a file with <code>.properties</code> extension in the
+ * classpath. The name must be a fully qualified classname (with dots as
+ * path separators).
+ *
+ * <p>(Note: This implementation always backs up the class with a properties
+ * file if that is existing, but you shouldn't rely on this, if you want to
+ * be compatible to the standard JDK.)
+ *
+ * @author Jochen Hoenicke
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Locale
+ * @see ListResourceBundle
+ * @see PropertyResourceBundle
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public abstract class ResourceBundle
+{
+ /**
+ * The parent bundle. This is consulted when you call getObject and there
+ * is no such resource in the current bundle. This field may be null.
+ */
+ protected ResourceBundle parent;
+
+ /**
+ * The locale of this resource bundle. You can read this with
+ * <code>getLocale</code> and it is automatically set in
+ * <code>getBundle</code>.
+ */
+ private Locale locale;
+
+ private static native ClassLoader getCallingClassLoader();
+
+ /**
+ * The resource bundle cache.
+ */
+ private static Map bundleCache;
+
+ /**
+ * The last default Locale we saw. If this ever changes then we have to
+ * reset our caches.
+ */
+ private static Locale lastDefaultLocale;
+
+ /**
+ * The `empty' locale is created once in order to optimize
+ * tryBundle().
+ */
+ private static final Locale emptyLocale = new Locale("");
+
+ /**
+ * The constructor. It does nothing special.
+ */
+ public ResourceBundle()
+ {
+ }
+
+ /**
+ * Get a String from this resource bundle. Since most localized Objects
+ * are Strings, this method provides a convenient way to get them without
+ * casting.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ * @throws ClassCastException if resource is not a string
+ */
+ public final String getString(String key)
+ {
+ return (String) getObject(key);
+ }
+
+ /**
+ * Get an array of Strings from this resource bundle. This method
+ * provides a convenient way to get it without casting.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ * @throws ClassCastException if resource is not a string
+ */
+ public final String[] getStringArray(String key)
+ {
+ return (String[]) getObject(key);
+ }
+
+ /**
+ * Get an object from this resource bundle. This will call
+ * <code>handleGetObject</code> for this resource and all of its parents,
+ * until it finds a non-null resource.
+ *
+ * @param key the name of the resource
+ * @throws MissingResourceException if the resource can't be found
+ * @throws NullPointerException if key is null
+ */
+ public final Object getObject(String key)
+ {
+ for (ResourceBundle bundle = this; bundle != null; bundle = bundle.parent)
+ {
+ Object o = bundle.handleGetObject(key);
+ if (o != null)
+ return o;
+ }
+
+ String className = getClass().getName();
+ throw new MissingResourceException("Key '" + key
+ + "'not found in Bundle: "
+ + className, className, key);
+ }
+
+ /**
+ * Return the actual locale of this bundle. You can use it after calling
+ * getBundle, to know if the bundle for the desired locale was loaded or
+ * if the fall back was used.
+ *
+ * @return the bundle's locale
+ */
+ public Locale getLocale()
+ {
+ return locale;
+ }
+
+ /**
+ * Set the parent of this bundle. The parent is consulted when you call
+ * getObject and there is no such resource in the current bundle.
+ *
+ * @param parent the parent of this bundle
+ */
+ protected void setParent(ResourceBundle parent)
+ {
+ this.parent = parent;
+ }
+
+ /**
+ * Get the appropriate ResourceBundle for the default locale. This is like
+ * calling <code>getBundle(baseName, Locale.getDefault(),
+ * getClass().getClassLoader()</code>, except that any security check of
+ * getClassLoader won't fail.
+ *
+ * @param baseName the name of the ResourceBundle
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if baseName is null
+ */
+ public static ResourceBundle getBundle(String baseName)
+ {
+ ClassLoader cl = getCallingClassLoader();
+ if (cl == null)
+ cl = ClassLoader.getSystemClassLoader();
+ return getBundle(baseName, Locale.getDefault(), cl);
+ }
+
+ /**
+ * Get the appropriate ResourceBundle for the given locale. This is like
+ * calling <code>getBundle(baseName, locale,
+ * getClass().getClassLoader()</code>, except that any security check of
+ * getClassLoader won't fail.
+ *
+ * @param baseName the name of the ResourceBundle
+ * @param locale A locale
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if baseName or locale is null
+ */
+ public static ResourceBundle getBundle(String baseName, Locale locale)
+ {
+ ClassLoader cl = getCallingClassLoader();
+ if (cl == null)
+ cl = ClassLoader.getSystemClassLoader();
+ return getBundle(baseName, locale, cl);
+ }
+
+ /** Cache key for the ResourceBundle cache. Resource bundles are keyed
+ by the combination of bundle name, locale, and class loader. */
+ private static class BundleKey
+ {
+ String baseName;
+ Locale locale;
+ ClassLoader classLoader;
+ int hashcode;
+
+ BundleKey() {}
+
+ BundleKey(String s, Locale l, ClassLoader cl)
+ {
+ set(s, l, cl);
+ }
+
+ void set(String s, Locale l, ClassLoader cl)
+ {
+ baseName = s;
+ locale = l;
+ classLoader = cl;
+ hashcode = baseName.hashCode() ^ locale.hashCode() ^
+ classLoader.hashCode();
+ }
+
+ public int hashCode()
+ {
+ return hashcode;
+ }
+
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof BundleKey))
+ return false;
+ BundleKey key = (BundleKey) o;
+ return hashcode == key.hashcode &&
+ baseName.equals(key.baseName) &&
+ locale.equals(key.locale) &&
+ classLoader.equals(key.classLoader);
+ }
+ }
+
+ /** A cache lookup key. This avoids having to a new one for every
+ * getBundle() call. */
+ private static BundleKey lookupKey = new BundleKey();
+
+ /** Singleton cache entry to represent previous failed lookups. */
+ private static Object nullEntry = new Object();
+
+ /**
+ * Get the appropriate ResourceBundle for the given locale. The following
+ * strategy is used:
+ *
+ * <p>A sequence of candidate bundle names are generated, and tested in
+ * this order, where the suffix 1 means the string from the specified
+ * locale, and the suffix 2 means the string from the default locale:</p>
+ *
+ * <ul>
+ * <li>baseName + "_" + language1 + "_" + country1 + "_" + variant1</li>
+ * <li>baseName + "_" + language1 + "_" + country1</li>
+ * <li>baseName + "_" + language1</li>
+ * <li>baseName + "_" + language2 + "_" + country2 + "_" + variant2</li>
+ * <li>baseName + "_" + language2 + "_" + country2</li>
+ * <li>baseName + "_" + language2</li>
+ * <li>baseName</li>
+ * </ul>
+ *
+ * <p>In the sequence, entries with an empty string are ignored. Next,
+ * <code>getBundle</code> tries to instantiate the resource bundle:</p>
+ *
+ * <ul>
+ * <li>First, an attempt is made to load a class in the specified classloader
+ * which is a subclass of ResourceBundle, and which has a public constructor
+ * with no arguments, via reflection.</li>
+ * <li>Next, a search is made for a property resource file, by replacing
+ * '.' with '/' and appending ".properties", and using
+ * ClassLoader.getResource(). If a file is found, then a
+ * PropertyResourceBundle is created from the file's contents.</li>
+ * </ul>
+ * If no resource bundle was found, a MissingResourceException is thrown.
+ *
+ * <p>Next, the parent chain is implemented. The remaining candidate names
+ * in the above sequence are tested in a similar manner, and if any results
+ * in a resource bundle, it is assigned as the parent of the first bundle
+ * using the <code>setParent</code> method (unless the first bundle already
+ * has a parent).</p>
+ *
+ * <p>For example, suppose the following class and property files are
+ * provided: MyResources.class, MyResources_fr_CH.properties,
+ * MyResources_fr_CH.class, MyResources_fr.properties,
+ * MyResources_en.properties, and MyResources_es_ES.class. The contents of
+ * all files are valid (that is, public non-abstract subclasses of
+ * ResourceBundle with public nullary constructors for the ".class" files,
+ * syntactically correct ".properties" files). The default locale is
+ * Locale("en", "UK").</p>
+ *
+ * <p>Calling getBundle with the shown locale argument values instantiates
+ * resource bundles from the following sources:</p>
+ *
+ * <ul>
+ * <li>Locale("fr", "CH"): result MyResources_fr_CH.class, parent
+ * MyResources_fr.properties, parent MyResources.class</li>
+ * <li>Locale("fr", "FR"): result MyResources_fr.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("de", "DE"): result MyResources_en.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("en", "US"): result MyResources_en.properties, parent
+ * MyResources.class</li>
+ * <li>Locale("es", "ES"): result MyResources_es_ES.class, parent
+ * MyResources.class</li>
+ * </ul>
+ *
+ * <p>The file MyResources_fr_CH.properties is never used because it is hidden
+ * by MyResources_fr_CH.class.</p>
+ *
+ * @param baseName the name of the ResourceBundle
+ * @param locale A locale
+ * @param classLoader a ClassLoader
+ * @return the desired resource bundle
+ * @throws MissingResourceException if the resource bundle can't be found
+ * @throws NullPointerException if any argument is null
+ * @since 1.2
+ */
+ // This method is synchronized so that the cache is properly
+ // handled.
+ public static synchronized ResourceBundle getBundle
+ (String baseName, Locale locale, ClassLoader classLoader)
+ {
+ // If the default locale changed since the last time we were called,
+ // all cache entries are invalidated.
+ Locale defaultLocale = Locale.getDefault();
+ if (defaultLocale != lastDefaultLocale)
+ {
+ bundleCache = new HashMap();
+ lastDefaultLocale = defaultLocale;
+ }
+
+ // This will throw NullPointerException if any arguments are null.
+ lookupKey.set(baseName, locale, classLoader);
+
+ Object obj = bundleCache.get(lookupKey);
+ ResourceBundle rb = null;
+
+ if (obj instanceof ResourceBundle)
+ {
+ return (ResourceBundle) obj;
+ }
+ else if (obj == nullEntry)
+ {
+ // Lookup has failed previously. Fall through.
+ }
+ else
+ {
+ // First, look for a bundle for the specified locale. We don't want
+ // the base bundle this time.
+ boolean wantBase = locale.equals(defaultLocale);
+ ResourceBundle bundle = tryBundle(baseName, locale, classLoader,
+ wantBase);
+
+ // Try the default locale if neccessary.
+ if (bundle == null && !locale.equals(defaultLocale))
+ bundle = tryBundle(baseName, defaultLocale, classLoader, true);
+
+ BundleKey key = new BundleKey(baseName, locale, classLoader);
+ if (bundle == null)
+ {
+ // Cache the fact that this lookup has previously failed.
+ bundleCache.put(key, nullEntry);
+ }
+ else
+ {
+ // Cache the result and return it.
+ bundleCache.put(key, bundle);
+ return bundle;
+ }
+ }
+
+ throw new MissingResourceException("Bundle " + baseName + " not found",
+ baseName, "");
+ }
+
+ /**
+ * Override this method to provide the resource for a keys. This gets
+ * called by <code>getObject</code>. If you don't have a resource
+ * for the given key, you should return null instead throwing a
+ * MissingResourceException. You don't have to ask the parent, getObject()
+ * already does this; nor should you throw a MissingResourceException.
+ *
+ * @param key the key of the resource
+ * @return the resource for the key, or null if not in bundle
+ * @throws NullPointerException if key is null
+ */
+ protected abstract Object handleGetObject(String key);
+
+ /**
+ * This method should return all keys for which a resource exists; you
+ * should include the enumeration of any parent's keys, after filtering out
+ * duplicates.
+ *
+ * @return an enumeration of the keys
+ */
+ public abstract Enumeration getKeys();
+
+ /**
+ * Tries to load a class or a property file with the specified name.
+ *
+ * @param localizedName the name
+ * @param classloader the classloader
+ * @return the resource bundle if it was loaded, otherwise the backup
+ */
+ private static ResourceBundle tryBundle(String localizedName,
+ ClassLoader classloader)
+ {
+ ResourceBundle bundle = null;
+ try
+ {
+ Class rbClass;
+ if (classloader == null)
+ rbClass = Class.forName(localizedName);
+ else
+ rbClass = classloader.loadClass(localizedName);
+ // Note that we do the check up front instead of catching
+ // ClassCastException. The reason for this is that some crazy
+ // programs (Eclipse) have classes that do not extend
+ // ResourceBundle but that have the same name as a property
+ // bundle; in fact Eclipse relies on ResourceBundle not
+ // instantiating these classes.
+ if (ResourceBundle.class.isAssignableFrom(rbClass))
+ bundle = (ResourceBundle) rbClass.newInstance();
+ }
+ catch (IllegalAccessException ex) {}
+ catch (InstantiationException ex) {}
+ catch (ClassNotFoundException ex) {}
+
+ if (bundle == null)
+ {
+ try
+ {
+ InputStream is;
+ String resourceName
+ = localizedName.replace('.', '/') + ".properties";
+ if (classloader == null)
+ is = ClassLoader.getSystemResourceAsStream(resourceName);
+ else
+ is = classloader.getResourceAsStream(resourceName);
+ if (is != null)
+ bundle = new PropertyResourceBundle(is);
+ }
+ catch (IOException ex)
+ {
+ MissingResourceException mre = new MissingResourceException
+ ("Failed to load bundle: " + localizedName, localizedName, "");
+ mre.initCause(ex);
+ throw mre;
+ }
+ }
+
+ return bundle;
+ }
+
+ /**
+ * Tries to load a the bundle for a given locale, also loads the backup
+ * locales with the same language.
+ *
+ * @param baseName the raw bundle name, without locale qualifiers
+ * @param locale the locale
+ * @param classloader the classloader
+ * @param bundle the backup (parent) bundle
+ * @param wantBase whether a resource bundle made only from the base name
+ * (with no locale information attached) should be returned.
+ * @return the resource bundle if it was loaded, otherwise the backup
+ */
+ private static ResourceBundle tryBundle(String baseName, Locale locale,
+ ClassLoader classLoader,
+ boolean wantBase)
+ {
+ String language = locale.getLanguage();
+ String country = locale.getCountry();
+ String variant = locale.getVariant();
+
+ int baseLen = baseName.length();
+
+ // Build up a StringBuffer containing the complete bundle name, fully
+ // qualified by locale.
+ StringBuffer sb = new StringBuffer(baseLen + variant.length() + 7);
+
+ sb.append(baseName);
+
+ if (language.length() > 0)
+ {
+ sb.append('_');
+ sb.append(language);
+
+ if (country.length() > 0)
+ {
+ sb.append('_');
+ sb.append(country);
+
+ if (variant.length() > 0)
+ {
+ sb.append('_');
+ sb.append(variant);
+ }
+ }
+ }
+
+ // Now try to load bundles, starting with the most specialized name.
+ // Build up the parent chain as we go.
+ String bundleName = sb.toString();
+ ResourceBundle first = null; // The most specialized bundle.
+ ResourceBundle last = null; // The least specialized bundle.
+
+ while (true)
+ {
+ ResourceBundle foundBundle = tryBundle(bundleName, classLoader);
+ if (foundBundle != null)
+ {
+ if (first == null)
+ first = foundBundle;
+ if (last != null)
+ last.parent = foundBundle;
+ foundBundle.locale = locale;
+ last = foundBundle;
+ }
+ int idx = bundleName.lastIndexOf('_');
+ // Try the non-localized base name only if we already have a
+ // localized child bundle, or wantBase is true.
+ if (idx > baseLen || (idx == baseLen && (first != null || wantBase)))
+ bundleName = bundleName.substring(0, idx);
+ else
+ break;
+ }
+
+ return first;
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/VMTimeZone.java b/gcc-4.2.1/libjava/java/util/VMTimeZone.java
new file mode 100644
index 000000000..86b625843
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/VMTimeZone.java
@@ -0,0 +1,345 @@
+/* java.util.VMTimeZone
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util;
+
+import gnu.classpath.Configuration;
+
+import java.io.*;
+
+/**
+ *
+ */
+final class VMTimeZone
+{
+ static
+ {
+ if (Configuration.INIT_LOAD_LIBRARY)
+ {
+ System.loadLibrary("javautil");
+ }
+ }
+
+ /**
+ * This method returns a time zone id string which is in the form
+ * (standard zone name) or (standard zone name)(GMT offset) or
+ * (standard zone name)(GMT offset)(daylight time zone name). The
+ * GMT offset can be in seconds, or where it is evenly divisible by
+ * 3600, then it can be in hours. The offset must be the time to
+ * add to the local time to get GMT. If a offset is given and the
+ * time zone observes daylight saving then the (daylight time zone
+ * name) must also be given (otherwise it is assumed the time zone
+ * does not observe any daylight savings).
+ * <p>
+ * The result of this method is given to the method
+ * TimeZone.getDefaultTimeZone(String) which tries to map the time
+ * zone id to a known TimeZone. See that method on how the returned
+ * String is mapped to a real TimeZone object.
+ * <p>
+ * The reference implementation which is made for GNU/Posix like
+ * systems calls <code>System.getenv("TZ")</code>,
+ * <code>readTimeZoneFile("/etc/timezone")</code>,
+ * <code>readtzFile("/etc/localtime")</code> and finally
+ * <code>getSystemTimeZoneId()</code> till a supported TimeZone is
+ * found through <code>TimeZone.getDefaultTimeZone(String)</code>.
+ * If every method fails <code>null</code> is returned (which means
+ * the TimeZone code will fall back on GMT as default time zone).
+ * <p>
+ * Note that this method is called inside a
+ * <code>AccessController.doPrivileged()</code> block and runs with
+ * the priviliges of the java.util system classes. It will only be
+ * called when the default time zone is not yet set, the system
+ * property user.timezone isn't set and it is requested for the
+ * first time.
+ */
+ static TimeZone getDefaultTimeZoneId()
+ {
+ TimeZone zone = null;
+
+ // See if TZ environment variable is set and accessible.
+ String tzid = System.getenv("TZ");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+
+ // Try to parse /etc/timezone.
+ if (zone == null)
+ {
+ tzid = readTimeZoneFile("/etc/timezone");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ // Try to parse /etc/localtime
+ if (zone == null)
+ {
+ tzid = readtzFile("/etc/localtime");
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ // Try some system specific way
+ if (zone == null)
+ {
+ tzid = getSystemTimeZoneId();
+ if (tzid != null && !tzid.equals(""))
+ zone = TimeZone.getDefaultTimeZone(tzid);
+ }
+
+ return zone;
+ }
+
+ /**
+ * Tries to read the time zone name from a file. Only the first
+ * consecutive letters, digits, slashes, dashes and underscores are
+ * read from the file. If the file cannot be read or an IOException
+ * occurs null is returned.
+ * <p>
+ * The /etc/timezone file is not standard, but a lot of systems have
+ * it. If it exist the first line always contains a string
+ * describing the timezone of the host of domain. Some systems
+ * contain a /etc/TIMEZONE file which is used to set the TZ
+ * environment variable (which is checked before /etc/timezone is
+ * read).
+ */
+ private static String readTimeZoneFile(String file)
+ {
+ File f = new File(file);
+ if (!f.exists())
+ return null;
+
+ InputStreamReader isr = null;
+ try
+ {
+ FileInputStream fis = new FileInputStream(f);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ isr = new InputStreamReader(bis);
+
+ StringBuffer sb = new StringBuffer();
+ int i = isr.read();
+ while (i != -1)
+ {
+ char c = (char) i;
+ if (Character.isLetter(c) || Character.isDigit(c)
+ || c == '/' || c == '-' || c == '_')
+ {
+ sb.append(c);
+ i = isr.read();
+ }
+ else
+ break;
+ }
+ return sb.toString();
+ }
+ catch (IOException ioe)
+ {
+ // Parse error, not a proper tzfile.
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ if (isr != null)
+ isr.close();
+ }
+ catch (IOException ioe)
+ {
+ // Error while close, nothing we can do.
+ }
+ }
+ }
+
+ /**
+ * Tries to read a file as a "standard" tzfile and return a time
+ * zone id string as expected by <code>getDefaultTimeZone(String)</code>.
+ * If the file doesn't exist, an IOException occurs or it isn't a tzfile
+ * that can be parsed null is returned.
+ * <p>
+ * The tzfile structure (as also used by glibc) is described in the Olson
+ * tz database archive as can be found at
+ * <code>ftp://elsie.nci.nih.gov/pub/</code>.
+ * <p>
+ * At least the following platforms support the tzdata file format
+ * and /etc/localtime (GNU/Linux, Darwin, Solaris and FreeBSD at
+ * least). Some systems (like Darwin) don't start the file with the
+ * required magic bytes 'TZif', this implementation can handle
+ * that).
+ */
+ private static String readtzFile(String file)
+ {
+ File f = new File(file);
+ if (!f.exists())
+ return null;
+
+ DataInputStream dis = null;
+ try
+ {
+ FileInputStream fis = new FileInputStream(f);
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ dis = new DataInputStream(bis);
+
+ // Make sure we are reading a tzfile.
+ byte[] tzif = new byte[4];
+ dis.readFully(tzif);
+ if (tzif[0] == 'T' && tzif[1] == 'Z'
+ && tzif[2] == 'i' && tzif[3] == 'f')
+ // Reserved bytes, ttisgmtcnt, ttisstdcnt and leapcnt
+ skipFully(dis, 16 + 3 * 4);
+ else
+ // Darwin has tzdata files that don't start with the TZif marker
+ skipFully(dis, 16 + 3 * 4 - 4);
+
+ int timecnt = dis.readInt();
+ int typecnt = dis.readInt();
+ if (typecnt > 0)
+ {
+ int charcnt = dis.readInt();
+ // Transition times plus indexed transition times.
+ skipFully(dis, timecnt * (4 + 1));
+
+ // Get last gmt_offset and dst/non-dst time zone names.
+ int abbrind = -1;
+ int dst_abbrind = -1;
+ int gmt_offset = 0;
+ while (typecnt-- > 0)
+ {
+ // gmtoff
+ int offset = dis.readInt();
+ int dst = dis.readByte();
+ if (dst == 0)
+ {
+ abbrind = dis.readByte();
+ gmt_offset = offset;
+ }
+ else
+ dst_abbrind = dis.readByte();
+ }
+
+ // gmt_offset is the offset you must add to UTC/GMT to
+ // get the local time, we need the offset to add to
+ // the local time to get UTC/GMT.
+ gmt_offset *= -1;
+
+ // Turn into hours if possible.
+ if (gmt_offset % 3600 == 0)
+ gmt_offset /= 3600;
+
+ if (abbrind >= 0)
+ {
+ byte[] names = new byte[charcnt];
+ dis.readFully(names);
+ int j = abbrind;
+ while (j < charcnt && names[j] != 0)
+ j++;
+
+ String zonename = new String(names, abbrind, j - abbrind,
+ "ASCII");
+
+ String dst_zonename;
+ if (dst_abbrind >= 0)
+ {
+ j = dst_abbrind;
+ while (j < charcnt && names[j] != 0)
+ j++;
+ dst_zonename = new String(names, dst_abbrind,
+ j - dst_abbrind, "ASCII");
+ }
+ else
+ dst_zonename = "";
+
+ // Only use gmt offset when necessary.
+ // Also special case GMT+/- timezones.
+ String offset_string;
+ if ("".equals(dst_zonename)
+ && (gmt_offset == 0
+ || zonename.startsWith("GMT+")
+ || zonename.startsWith("GMT-")))
+ offset_string = "";
+ else
+ offset_string = Integer.toString(gmt_offset);
+
+ String id = zonename + offset_string + dst_zonename;
+
+ return id;
+ }
+ }
+
+ // Something didn't match while reading the file.
+ return null;
+ }
+ catch (IOException ioe)
+ {
+ // Parse error, not a proper tzfile.
+ return null;
+ }
+ finally
+ {
+ try
+ {
+ if (dis != null)
+ dis.close();
+ }
+ catch(IOException ioe)
+ {
+ // Error while close, nothing we can do.
+ }
+ }
+ }
+
+ /**
+ * Skips the requested number of bytes in the given InputStream.
+ * Throws EOFException if not enough bytes could be skipped.
+ * Negative numbers of bytes to skip are ignored.
+ */
+ private static void skipFully(InputStream is, long l) throws IOException
+ {
+ while (l > 0)
+ {
+ long k = is.skip(l);
+ if (k <= 0)
+ throw new EOFException();
+ l -= k;
+ }
+ }
+
+ /**
+ * Tries to get the system time zone id through native code.
+ */
+ private static native String getSystemTimeZoneId();
+}
diff --git a/gcc-4.2.1/libjava/java/util/logging/LogManager.java b/gcc-4.2.1/libjava/java/util/logging/LogManager.java
new file mode 100644
index 000000000..b8b31c43c
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/logging/LogManager.java
@@ -0,0 +1,981 @@
+/* LogManager.java -- a class for maintaining Loggers and managing
+ configuration properties
+ Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import gnu.classpath.SystemProperties;
+
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * The <code>LogManager</code> maintains a hierarchical namespace
+ * of Logger objects and manages properties for configuring the logging
+ * framework. There exists only one single <code>LogManager</code>
+ * per virtual machine. This instance can be retrieved using the
+ * static method {@link #getLogManager()}.
+ *
+ * <p><strong>Configuration Process:</strong> The global LogManager
+ * object is created and configured when the class
+ * <code>java.util.logging.LogManager</code> is initialized.
+ * The configuration process includes the subsequent steps:
+ *
+ * <ul>
+ * <li>If the system property <code>java.util.logging.manager</code>
+ * is set to the name of a subclass of
+ * <code>java.util.logging.LogManager</code>, an instance of
+ * that subclass is created and becomes the global LogManager.
+ * Otherwise, a new instance of LogManager is created.</li>
+ * <li>The <code>LogManager</code> constructor tries to create
+ * a new instance of the class specified by the system
+ * property <code>java.util.logging.config.class</code>.
+ * Typically, the constructor of this class will call
+ * <code>LogManager.getLogManager().readConfiguration(java.io.InputStream)</code>
+ * for configuring the logging framework.
+ * The configuration process stops at this point if
+ * the system property <code>java.util.logging.config.class</code>
+ * is set (irrespective of whether the class constructor
+ * could be called or an exception was thrown).</li>
+ *
+ * <li>If the system property <code>java.util.logging.config.class</code>
+ * is <em>not</em> set, the configuration parameters are read in from
+ * a file and passed to
+ * {@link #readConfiguration(java.io.InputStream)}.
+ * The name and location of this file are specified by the system
+ * property <code>java.util.logging.config.file</code>.</li>
+ * <li>If the system property <code>java.util.logging.config.file</code>
+ * is not set, however, the contents of the URL
+ * "{gnu.classpath.home.url}/logging.properties" are passed to
+ * {@link #readConfiguration(java.io.InputStream)}.
+ * Here, "{gnu.classpath.home.url}" stands for the value of
+ * the system property <code>gnu.classpath.home.url</code>.</li>
+ * </ul>
+ *
+ * <p>The <code>LogManager</code> has a level of <code>INFO</code> by
+ * default, and this will be inherited by <code>Logger</code>s unless they
+ * override it either by properties or programmatically.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class LogManager
+{
+ /**
+ * The object name for the logging management bean.
+ * @since 1.5
+ */
+ public static final String LOGGING_MXBEAN_NAME
+ = "java.util.logging:type=Logging";
+
+ /**
+ * The singleton LogManager instance.
+ */
+ private static LogManager logManager;
+
+ /**
+ * The singleton logging bean.
+ */
+ private static LoggingMXBean loggingBean;
+
+ /**
+ * The registered named loggers; maps the name of a Logger to
+ * a WeakReference to it.
+ */
+ private Map loggers;
+
+ /**
+ * The properties for the logging framework which have been
+ * read in last.
+ */
+ private Properties properties;
+
+ /**
+ * A delegate object that provides support for handling
+ * PropertyChangeEvents. The API specification does not
+ * mention which bean should be the source in the distributed
+ * PropertyChangeEvents, but Mauve test code has determined that
+ * the Sun J2SE 1.4 reference implementation uses the LogManager
+ * class object. This is somewhat strange, as the class object
+ * is not the bean with which listeners have to register, but
+ * there is no reason for the GNU Classpath implementation to
+ * behave differently from the reference implementation in
+ * this case.
+ */
+ private final PropertyChangeSupport pcs = new PropertyChangeSupport( /* source bean */
+ LogManager.class);
+
+ protected LogManager()
+ {
+ loggers = new HashMap();
+ }
+
+ /**
+ * Returns the globally shared LogManager instance.
+ */
+ public static synchronized LogManager getLogManager()
+ {
+ if (logManager == null)
+ {
+ logManager = makeLogManager();
+ initLogManager();
+ }
+ return logManager;
+ }
+
+ private static final String MANAGER_PROPERTY = "java.util.logging.manager";
+
+ private static LogManager makeLogManager()
+ {
+ String managerClassName = SystemProperties.getProperty(MANAGER_PROPERTY);
+ LogManager manager = (LogManager) createInstance
+ (managerClassName, LogManager.class, MANAGER_PROPERTY);
+ if (manager == null)
+ manager = new LogManager();
+ return manager;
+ }
+
+ private static final String CONFIG_PROPERTY = "java.util.logging.config.class";
+
+ private static void initLogManager()
+ {
+ LogManager manager = getLogManager();
+ Logger.root.setLevel(Level.INFO);
+ manager.addLogger(Logger.root);
+
+ /* The Javadoc description of the class explains
+ * what is going on here.
+ */
+ Object configurator = createInstance(System.getProperty(CONFIG_PROPERTY),
+ /* must be instance of */ Object.class,
+ CONFIG_PROPERTY);
+
+ try
+ {
+ if (configurator == null)
+ manager.readConfiguration();
+ }
+ catch (IOException ex)
+ {
+ /* FIXME: Is it ok to ignore exceptions here? */
+ }
+ }
+
+ /**
+ * Registers a listener which will be notified when the
+ * logging properties are re-read.
+ */
+ public synchronized void addPropertyChangeListener(PropertyChangeListener listener)
+ {
+ /* do not register null. */
+ listener.getClass();
+
+ pcs.addPropertyChangeListener(listener);
+ }
+
+ /**
+ * Unregisters a listener.
+ *
+ * If <code>listener</code> has not been registered previously,
+ * nothing happens. Also, no exception is thrown if
+ * <code>listener</code> is <code>null</code>.
+ */
+ public synchronized void removePropertyChangeListener(PropertyChangeListener listener)
+ {
+ if (listener != null)
+ pcs.removePropertyChangeListener(listener);
+ }
+
+ /**
+ * Adds a named logger. If a logger with the same name has
+ * already been registered, the method returns <code>false</code>
+ * without adding the logger.
+ *
+ * <p>The <code>LogManager</code> only keeps weak references
+ * to registered loggers. Therefore, names can become available
+ * after automatic garbage collection.
+ *
+ * @param logger the logger to be added.
+ *
+ * @return <code>true</code>if <code>logger</code> was added,
+ * <code>false</code> otherwise.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ */
+ public synchronized boolean addLogger(Logger logger)
+ {
+ /* To developers thinking about to remove the 'synchronized'
+ * declaration from this method: Please read the comment
+ * in java.util.logging.Logger.getLogger(String, String)
+ * and make sure that whatever you change wrt. synchronization
+ * does not endanger thread-safety of Logger.getLogger.
+ * The current implementation of Logger.getLogger assumes
+ * that LogManager does its synchronization on the globally
+ * shared instance of LogManager.
+ */
+ String name;
+ WeakReference ref;
+
+ /* This will throw a NullPointerException if logger is null,
+ * as required by the API specification.
+ */
+ name = logger.getName();
+
+ ref = (WeakReference) loggers.get(name);
+ if (ref != null)
+ {
+ if (ref.get() != null)
+ return false;
+
+ /* There has been a logger under this name in the past,
+ * but it has been garbage collected.
+ */
+ loggers.remove(ref);
+ }
+
+ /* Adding a named logger requires a security permission. */
+ if ((name != null) && ! name.equals(""))
+ checkAccess();
+
+ Logger parent = findAncestor(logger);
+ loggers.put(name, new WeakReference(logger));
+ if (parent != logger.getParent())
+ logger.setParent(parent);
+
+ // The level of the newly added logger must be specified.
+ // The easiest case is if there is a level for exactly this logger
+ // in the properties. If no such level exists the level needs to be
+ // searched along the hirachy. So if there is a new logger 'foo.blah.blub'
+ // and an existing parent logger 'foo' the properties 'foo.blah.blub.level'
+ // and 'foo.blah.level' need to be checked. If both do not exist in the
+ // properties the level of the new logger is set to 'null' (i.e. it uses the
+ // level of its parent 'foo').
+ Level logLevel = logger.getLevel();
+ String searchName = name;
+ String parentName = parent != null ? parent.getName() : "";
+ while (logLevel == null && ! searchName.equals(parentName))
+ {
+ logLevel = getLevelProperty(searchName + ".level", logLevel);
+ int index = searchName.lastIndexOf('.');
+ if(index > -1)
+ searchName = searchName.substring(0,index);
+ else
+ searchName = "";
+ }
+ logger.setLevel(logLevel);
+
+ /* It can happen that existing loggers should be children of
+ * the newly added logger. For example, assume that there
+ * already exist loggers under the names "", "foo", and "foo.bar.baz".
+ * When adding "foo.bar", the logger "foo.bar.baz" should change
+ * its parent to "foo.bar".
+ */
+ for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
+ {
+ Logger possChild = (Logger) ((WeakReference) loggers.get(iter.next()))
+ .get();
+ if ((possChild == null) || (possChild == logger)
+ || (possChild.getParent() != parent))
+ continue;
+
+ if (! possChild.getName().startsWith(name))
+ continue;
+
+ if (possChild.getName().charAt(name.length()) != '.')
+ continue;
+
+ possChild.setParent(logger);
+ }
+
+ return true;
+ }
+
+ /**
+ * Finds the closest ancestor for a logger among the currently
+ * registered ones. For example, if the currently registered
+ * loggers have the names "", "foo", and "foo.bar", the result for
+ * "foo.bar.baz" will be the logger whose name is "foo.bar".
+ *
+ * @param child a logger for whose name no logger has been
+ * registered.
+ *
+ * @return the closest ancestor for <code>child</code>,
+ * or <code>null</code> if <code>child</code>
+ * is the root logger.
+ *
+ * @throws NullPointerException if <code>child</code>
+ * is <code>null</code>.
+ */
+ private synchronized Logger findAncestor(Logger child)
+ {
+ String childName = child.getName();
+ int childNameLength = childName.length();
+ Logger best = Logger.root;
+ int bestNameLength = 0;
+
+ Logger cand;
+ String candName;
+ int candNameLength;
+
+ if (child == Logger.root)
+ return null;
+
+ for (Iterator iter = loggers.keySet().iterator(); iter.hasNext();)
+ {
+ candName = (String) iter.next();
+ candNameLength = candName.length();
+
+ if (candNameLength > bestNameLength
+ && childNameLength > candNameLength
+ && childName.startsWith(candName)
+ && childName.charAt(candNameLength) == '.')
+ {
+ cand = (Logger) ((WeakReference) loggers.get(candName)).get();
+ if ((cand == null) || (cand == child))
+ continue;
+
+ bestNameLength = candName.length();
+ best = cand;
+ }
+ }
+
+ return best;
+ }
+
+ /**
+ * Returns a Logger given its name.
+ *
+ * @param name the name of the logger.
+ *
+ * @return a named Logger, or <code>null</code> if there is no
+ * logger with that name.
+ *
+ * @throw java.lang.NullPointerException if <code>name</code>
+ * is <code>null</code>.
+ */
+ public synchronized Logger getLogger(String name)
+ {
+ WeakReference ref;
+
+ /* Throw a NullPointerException if name is null. */
+ name.getClass();
+
+ ref = (WeakReference) loggers.get(name);
+ if (ref != null)
+ return (Logger) ref.get();
+ else
+ return null;
+ }
+
+ /**
+ * Returns an Enumeration of currently registered Logger names.
+ * Since other threads can register loggers at any time, the
+ * result could be different any time this method is called.
+ *
+ * @return an Enumeration with the names of the currently
+ * registered Loggers.
+ */
+ public synchronized Enumeration getLoggerNames()
+ {
+ return Collections.enumeration(loggers.keySet());
+ }
+
+ /**
+ * Resets the logging configuration by removing all handlers for
+ * registered named loggers and setting their level to <code>null</code>.
+ * The level of the root logger will be set to <code>Level.INFO</code>.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public synchronized void reset() throws SecurityException
+ {
+ /* Throw a SecurityException if the caller does not have the
+ * permission to control the logging infrastructure.
+ */
+ checkAccess();
+
+ properties = new Properties();
+
+ Iterator iter = loggers.values().iterator();
+ while (iter.hasNext())
+ {
+ WeakReference ref;
+ Logger logger;
+
+ ref = (WeakReference) iter.next();
+ if (ref != null)
+ {
+ logger = (Logger) ref.get();
+
+ if (logger == null)
+ iter.remove();
+ else if (logger != Logger.root)
+ {
+ logger.resetLogger();
+ logger.setLevel(null);
+ }
+ }
+ }
+
+ Logger.root.setLevel(Level.INFO);
+ Logger.root.resetLogger();
+ }
+
+ /**
+ * Configures the logging framework by reading a configuration file.
+ * The name and location of this file are specified by the system
+ * property <code>java.util.logging.config.file</code>. If this
+ * property is not set, the URL
+ * "{gnu.classpath.home.url}/logging.properties" is taken, where
+ * "{gnu.classpath.home.url}" stands for the value of the system
+ * property <code>gnu.classpath.home.url</code>.
+ *
+ * <p>The task of configuring the framework is then delegated to
+ * {@link #readConfiguration(java.io.InputStream)}, which will
+ * notify registered listeners after having read the properties.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure, or if the caller is
+ * not granted the permission to read the configuration
+ * file.
+ *
+ * @throws IOException if there is a problem reading in the
+ * configuration file.
+ */
+ public synchronized void readConfiguration()
+ throws IOException, SecurityException
+ {
+ String path;
+ InputStream inputStream;
+
+ path = System.getProperty("java.util.logging.config.file");
+ if ((path == null) || (path.length() == 0))
+ {
+ String url = (System.getProperty("gnu.classpath.home.url")
+ + "/logging.properties");
+ try
+ {
+ inputStream = new URL(url).openStream();
+ }
+ catch (Exception e)
+ {
+ inputStream=null;
+ }
+
+ // If no config file could be found use a default configuration.
+ if(inputStream == null)
+ {
+ String defaultConfig = "handlers = java.util.logging.ConsoleHandler \n"
+ + ".level=INFO \n";
+ inputStream = new ByteArrayInputStream(defaultConfig.getBytes());
+ }
+ }
+ else
+ inputStream = new java.io.FileInputStream(path);
+
+ try
+ {
+ readConfiguration(inputStream);
+ }
+ finally
+ {
+ // Close the stream in order to save
+ // resources such as file descriptors.
+ inputStream.close();
+ }
+ }
+
+ public synchronized void readConfiguration(InputStream inputStream)
+ throws IOException, SecurityException
+ {
+ Properties newProperties;
+ Enumeration keys;
+
+ checkAccess();
+ newProperties = new Properties();
+ newProperties.load(inputStream);
+ reset();
+ this.properties = newProperties;
+ keys = newProperties.propertyNames();
+
+ while (keys.hasMoreElements())
+ {
+ String key = ((String) keys.nextElement()).trim();
+ String value = newProperties.getProperty(key);
+
+ if (value == null)
+ continue;
+
+ value = value.trim();
+
+ if ("handlers".equals(key))
+ {
+ StringTokenizer tokenizer = new StringTokenizer(value);
+ while (tokenizer.hasMoreTokens())
+ {
+ String handlerName = tokenizer.nextToken();
+ Handler handler = (Handler)
+ createInstance(handlerName, Handler.class, key);
+ Logger.root.addHandler(handler);
+ }
+ }
+
+ if (key.endsWith(".level"))
+ {
+ String loggerName = key.substring(0, key.length() - 6);
+ Logger logger = getLogger(loggerName);
+
+ if (logger == null)
+ {
+ logger = Logger.getLogger(loggerName);
+ addLogger(logger);
+ }
+ Level level = null;
+ try
+ {
+ level = Level.parse(value);
+ }
+ catch (IllegalArgumentException e)
+ {
+ warn("bad level \'" + value + "\'", e);
+ }
+ if (level != null)
+ {
+ logger.setLevel(level);
+ }
+ continue;
+ }
+ }
+
+ /* The API specification does not talk about the
+ * property name that is distributed with the
+ * PropertyChangeEvent. With test code, it could
+ * be determined that the Sun J2SE 1.4 reference
+ * implementation uses null for the property name.
+ */
+ pcs.firePropertyChange(null, null, null);
+ }
+
+ /**
+ * Returns the value of a configuration property as a String.
+ */
+ public synchronized String getProperty(String name)
+ {
+ if (properties != null)
+ return properties.getProperty(name);
+ else
+ return null;
+ }
+
+ /**
+ * Returns the value of a configuration property as an integer.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is not an integer
+ * number.
+ */
+ static int getIntProperty(String name, int defaultValue)
+ {
+ try
+ {
+ return Integer.parseInt(getLogManager().getProperty(name));
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as an integer,
+ * provided it is inside the acceptable range.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param minValue the lowest acceptable value.
+ *
+ * @param maxValue the highest acceptable value.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is not an integer
+ * number, or if it is less than the minimum value,
+ * or if it is greater than the maximum value.
+ */
+ static int getIntPropertyClamped(String name, int defaultValue,
+ int minValue, int maxValue)
+ {
+ int val = getIntProperty(name, defaultValue);
+ if ((val < minValue) || (val > maxValue))
+ val = defaultValue;
+ return val;
+ }
+
+ /**
+ * Returns the value of a configuration property as a boolean.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param name the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if its value is neither
+ * <code>"true"</code> nor <code>"false"</code>.
+ */
+ static boolean getBooleanProperty(String name, boolean defaultValue)
+ {
+ try
+ {
+ return (Boolean.valueOf(getLogManager().getProperty(name))).booleanValue();
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as a Level.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param propertyName the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if
+ * {@link Level#parse(java.lang.String)} does not like
+ * the property value.
+ */
+ static Level getLevelProperty(String propertyName, Level defaultValue)
+ {
+ try
+ {
+ return Level.parse(getLogManager().getProperty(propertyName));
+ }
+ catch (Exception ex)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Returns the value of a configuration property as a Class.
+ * This function is a helper used by the Classpath implementation
+ * of java.util.logging, it is <em>not</em> specified in the
+ * logging API.
+ *
+ * @param propertyName the name of the configuration property.
+ *
+ * @param defaultValue the value that will be returned if the
+ * property is not defined, or if it does not specify
+ * the name of a loadable class.
+ */
+ static final Class getClassProperty(String propertyName, Class defaultValue)
+ {
+ String propertyValue = logManager.getProperty(propertyName);
+
+ if (propertyValue != null)
+ try
+ {
+ return locateClass(propertyValue);
+ }
+ catch (ClassNotFoundException e)
+ {
+ warn(propertyName + " = " + propertyValue, e);
+ }
+
+ return defaultValue;
+ }
+
+ static final Object getInstanceProperty(String propertyName, Class ofClass,
+ Class defaultClass)
+ {
+ Class klass = getClassProperty(propertyName, defaultClass);
+ if (klass == null)
+ return null;
+
+ try
+ {
+ Object obj = klass.newInstance();
+ if (ofClass.isInstance(obj))
+ return obj;
+ }
+ catch (InstantiationException e)
+ {
+ warn(propertyName + " = " + klass.getName(), e);
+ }
+ catch (IllegalAccessException e)
+ {
+ warn(propertyName + " = " + klass.getName(), e);
+ }
+
+ if (defaultClass == null)
+ return null;
+
+ try
+ {
+ return defaultClass.newInstance();
+ }
+ catch (java.lang.InstantiationException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ catch (java.lang.IllegalAccessException ex)
+ {
+ throw new RuntimeException(ex.getMessage());
+ }
+ }
+
+ /**
+ * An instance of <code>LoggingPermission("control")</code>
+ * that is shared between calls to <code>checkAccess()</code>.
+ */
+ private static final LoggingPermission controlPermission = new LoggingPermission("control",
+ null);
+
+ /**
+ * Checks whether the current security context allows changing
+ * the configuration of the logging framework. For the security
+ * context to be trusted, it has to be granted
+ * a LoggingPermission("control").
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not granted the permission to control
+ * the logging infrastructure.
+ */
+ public void checkAccess() throws SecurityException
+ {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ sm.checkPermission(controlPermission);
+ }
+
+ /**
+ * Creates a new instance of a class specified by name and verifies
+ * that it is an instance (or subclass of) a given type.
+ *
+ * @param className the name of the class of which a new instance
+ * should be created.
+ *
+ * @param type the object created must be an instance of
+ * <code>type</code> or any subclass of <code>type</code>
+ *
+ * @param property the system property to reference in error
+ * messages
+ *
+ * @return the new instance, or <code>null</code> if
+ * <code>className</code> is <code>null</code>, if no class
+ * with that name could be found, if there was an error
+ * loading that class, or if the constructor of the class
+ * has thrown an exception.
+ */
+ private static final Object createInstance(String className, Class type,
+ String property)
+ {
+ Class klass = null;
+
+ if ((className == null) || (className.length() == 0))
+ return null;
+
+ try
+ {
+ klass = locateClass(className);
+ if (type.isAssignableFrom(klass))
+ return klass.newInstance();
+ warn(property, className, "not an instance of " + type.getName());
+ }
+ catch (ClassNotFoundException e)
+ {
+ warn(property, className, "class not found", e);
+ }
+ catch (IllegalAccessException e)
+ {
+ warn(property, className, "illegal access", e);
+ }
+ catch (InstantiationException e)
+ {
+ warn(property, className, e);
+ }
+ catch (java.lang.LinkageError e)
+ {
+ warn(property, className, "linkage error", e);
+ }
+
+ return null;
+ }
+
+ private static final void warn(String property, String klass, Throwable t)
+ {
+ warn(property, klass, null, t);
+ }
+
+ private static final void warn(String property, String klass, String msg)
+ {
+ warn(property, klass, msg, null);
+ }
+
+ private static final void warn(String property, String klass, String msg,
+ Throwable t)
+ {
+ warn("error instantiating '" + klass + "' referenced by " + property +
+ (msg == null ? "" : ", " + msg), t);
+ }
+
+ /**
+ * All debug warnings go through this method.
+ */
+
+ private static final void warn(String msg, Throwable t)
+ {
+ System.err.println("WARNING: " + msg);
+ if (t != null)
+ t.printStackTrace(System.err);
+ }
+
+ /**
+ * Locates a class by first checking the system class loader and
+ * then checking the context class loader.
+ *
+ * @param name the fully qualified name of the Class to locate
+ * @return Class the located Class
+ */
+
+ private static Class locateClass(String name) throws ClassNotFoundException
+ {
+ // GCJ LOCAL
+ // Unfortunately this can be called during bootstrap when
+ // Thread.currentThread() will return null.
+ // See bug #27658
+ Thread t = Thread.currentThread();
+ ClassLoader loader = (t == null) ? null : t.getContextClassLoader();
+ try
+ {
+ return Class.forName(name, true, loader);
+ }
+ catch (ClassNotFoundException e)
+ {
+ loader = ClassLoader.getSystemClassLoader();
+ return Class.forName(name, true, loader);
+ }
+ }
+
+ /**
+ * Return the logging bean. There is a single logging bean per
+ * VM instance.
+ * @since 1.5
+ */
+ public static synchronized LoggingMXBean getLoggingMXBean()
+ {
+ if (loggingBean == null)
+ {
+ loggingBean = new LoggingMXBean()
+ {
+ public String getLoggerLevel(String logger)
+ {
+ LogManager mgr = getLogManager();
+ Logger l = mgr.getLogger(logger);
+ if (l == null)
+ return null;
+ Level lev = l.getLevel();
+ if (lev == null)
+ return "";
+ return lev.getName();
+ }
+
+ public List getLoggerNames()
+ {
+ LogManager mgr = getLogManager();
+ // This is inefficient, but perhaps better for maintenance.
+ return Collections.list(mgr.getLoggerNames());
+ }
+
+ public String getParentLoggerName(String logger)
+ {
+ LogManager mgr = getLogManager();
+ Logger l = mgr.getLogger(logger);
+ if (l == null)
+ return null;
+ l = l.getParent();
+ if (l == null)
+ return "";
+ return l.getName();
+ }
+
+ public void setLoggerLevel(String logger, String level)
+ {
+ LogManager mgr = getLogManager();
+ Logger l = mgr.getLogger(logger);
+ if (l == null)
+ throw new IllegalArgumentException("no logger named " + logger);
+ Level newLevel;
+ if (level == null)
+ newLevel = null;
+ else
+ newLevel = Level.parse(level);
+ l.setLevel(newLevel);
+ }
+ };
+ }
+ return loggingBean;
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/logging/Logger.java b/gcc-4.2.1/libjava/java/util/logging/Logger.java
new file mode 100644
index 000000000..adb07ecf6
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/logging/Logger.java
@@ -0,0 +1,1206 @@
+/* Logger.java -- a class for logging messages
+ Copyright (C) 2002, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.util.logging;
+
+import java.util.List;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * A Logger is used for logging information about events. Usually, there
+ * is a seprate logger for each subsystem or component, although there
+ * is a shared instance for components that make only occasional use of
+ * the logging framework.
+ *
+ * <p>It is common to name a logger after the name of a corresponding
+ * Java package. Loggers are organized into a hierarchical namespace;
+ * for example, the logger <code>"org.gnu.foo"</code> is the
+ * <em>parent</em> of logger <code>"org.gnu.foo.bar"</code>.
+ *
+ * <p>A logger for a named subsystem can be obtained through {@link
+ * java.util.logging.Logger#getLogger(java.lang.String)}. However,
+ * only code which has been granted the permission to control the
+ * logging infrastructure will be allowed to customize that logger.
+ * Untrusted code can obtain a private, anonymous logger through
+ * {@link #getAnonymousLogger()} if it wants to perform any
+ * modifications to the logger.
+ *
+ * <p>FIXME: Write more documentation.
+ *
+ * @author Sascha Brawer (brawer@acm.org)
+ */
+public class Logger
+{
+
+ static final Logger root = new Logger("", null);
+
+ /**
+ * A logger provided to applications that make only occasional use
+ * of the logging framework, typically early prototypes. Serious
+ * products are supposed to create and use their own Loggers, so
+ * they can be controlled individually.
+ */
+ public static final Logger global;
+
+ static
+ {
+ // Our class might be initialized from an unprivileged context
+ global = (Logger) AccessController.doPrivileged
+ (new PrivilegedAction()
+ {
+ public Object run()
+ {
+ return getLogger("global");
+ }
+ });
+ }
+
+
+ /**
+ * The name of the Logger, or <code>null</code> if the logger is
+ * anonymous.
+ *
+ * <p>A previous version of the GNU Classpath implementation granted
+ * untrusted code the permission to control any logger whose name
+ * was null. However, test code revealed that the Sun J2SE 1.4
+ * reference implementation enforces the security control for any
+ * logger that was not created through getAnonymousLogger, even if
+ * it has a null name. Therefore, a separate flag {@link
+ * Logger#anonymous} was introduced.
+ */
+ private final String name;
+
+
+ /**
+ * The name of the resource bundle used for localization.
+ *
+ * <p>This variable cannot be declared as <code>final</code>
+ * because its value can change as a result of calling
+ * getLogger(String,String).
+ */
+ private String resourceBundleName;
+
+
+ /**
+ * The resource bundle used for localization.
+ *
+ * <p>This variable cannot be declared as <code>final</code>
+ * because its value can change as a result of calling
+ * getLogger(String,String).
+ */
+ private ResourceBundle resourceBundle;
+
+ private Filter filter;
+
+ private final List handlerList = new java.util.ArrayList(4);
+ private Handler[] handlers = new Handler[0];
+
+ /**
+ * Indicates whether or not this logger is anonymous. While
+ * a LoggingPermission is required for any modifications to
+ * a normal logger, untrusted code can obtain an anonymous logger
+ * and modify it according to its needs.
+ *
+ * <p>A previous version of the GNU Classpath implementation
+ * granted access to every logger whose name was null.
+ * However, test code revealed that the Sun J2SE 1.4 reference
+ * implementation enforces the security control for any logger
+ * that was not created through getAnonymousLogger, even
+ * if it has a null name.
+ */
+ private boolean anonymous;
+
+
+ private boolean useParentHandlers;
+
+ private Level level;
+
+ private Logger parent;
+
+ /**
+ * Constructs a Logger for a subsystem. Most applications do not
+ * need to create new Loggers explicitly; instead, they should call
+ * the static factory methods
+ * {@link #getLogger(java.lang.String,java.lang.String) getLogger}
+ * (with ResourceBundle for localization) or
+ * {@link #getLogger(java.lang.String) getLogger} (without
+ * ResourceBundle), respectively.
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "com.foo.bar". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ */
+ protected Logger(String name, String resourceBundleName)
+ throws MissingResourceException
+ {
+ this.name = name;
+ this.resourceBundleName = resourceBundleName;
+
+ if (resourceBundleName == null)
+ resourceBundle = null;
+ else
+ resourceBundle = ResourceBundle.getBundle(resourceBundleName);
+
+ level = null;
+
+ /* This is null when the root logger is being constructed,
+ * and the root logger afterwards.
+ */
+ parent = root;
+
+ useParentHandlers = (parent != null);
+ }
+
+
+
+ /**
+ * Finds a registered logger for a subsystem, or creates one in
+ * case no logger has been registered yet.
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "com.foo.bar". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @throws IllegalArgumentException if a logger for the subsystem
+ * identified by <code>name</code> has already been created,
+ * but uses a a resource bundle for localizing messages.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ *
+ * @return a logger for the subsystem specified by <code>name</code>
+ * that does not localize messages.
+ */
+ public static Logger getLogger(String name)
+ {
+ return getLogger(name, null);
+ }
+
+
+ /**
+ * Finds a registered logger for a subsystem, or creates one in case
+ * no logger has been registered yet.
+ *
+ * <p>If a logger with the specified name has already been
+ * registered, the behavior depends on the resource bundle that is
+ * currently associated with the existing logger.
+ *
+ * <ul><li>If the existing logger uses the same resource bundle as
+ * specified by <code>resourceBundleName</code>, the existing logger
+ * is returned.</li>
+ *
+ * <li>If the existing logger currently does not localize messages,
+ * the existing logger is modified to use the bundle specified by
+ * <code>resourceBundleName</code>. The existing logger is then
+ * returned. Therefore, all subsystems currently using this logger
+ * will produce localized messages from now on.</li>
+ *
+ * <li>If the existing logger already has an associated resource
+ * bundle, but a different one than specified by
+ * <code>resourceBundleName</code>, an
+ * <code>IllegalArgumentException</code> is thrown.</li></ul>
+ *
+ * @param name the name for the logger, for example "java.awt"
+ * or "org.gnu.foo". The name should be based on
+ * the name of the package issuing log records
+ * and consist of dot-separated Java identifiers.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @return a logger for the subsystem specified by <code>name</code>.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ *
+ * @throws IllegalArgumentException if a logger for the subsystem
+ * identified by <code>name</code> has already been created,
+ * but uses a different resource bundle for localizing
+ * messages.
+ *
+ * @throws NullPointerException if <code>name</code> is
+ * <code>null</code>.
+ */
+ public static Logger getLogger(String name, String resourceBundleName)
+ {
+ LogManager lm = LogManager.getLogManager();
+ Logger result;
+
+ /* Throw NullPointerException if name is null. */
+ name.getClass();
+
+ /* Without synchronized(lm), it could happen that another thread
+ * would create a logger between our calls to getLogger and
+ * addLogger. While addLogger would indicate this by returning
+ * false, we could not be sure that this other logger was still
+ * existing when we called getLogger a second time in order
+ * to retrieve it -- note that LogManager is only allowed to
+ * keep weak references to registered loggers, so Loggers
+ * can be garbage collected at any time in general, and between
+ * our call to addLogger and our second call go getLogger
+ * in particular.
+ *
+ * Of course, we assume here that LogManager.addLogger etc.
+ * are synchronizing on the global LogManager object. There
+ * is a comment in the implementation of LogManager.addLogger
+ * referring to this comment here, so that any change in
+ * the synchronization of LogManager will be reflected here.
+ */
+ synchronized (lm)
+ {
+ result = lm.getLogger(name);
+ if (result == null)
+ {
+ boolean couldBeAdded;
+
+ result = new Logger(name, resourceBundleName);
+ couldBeAdded = lm.addLogger(result);
+ if (!couldBeAdded)
+ throw new IllegalStateException("cannot register new logger");
+ }
+ else
+ {
+ /* The logger already exists. Make sure it uses
+ * the same resource bundle for localizing messages.
+ */
+ String existingBundleName = result.getResourceBundleName();
+
+ /* The Sun J2SE 1.4 reference implementation will return the
+ * registered logger object, even if it does not have a resource
+ * bundle associated with it. However, it seems to change the
+ * resourceBundle of the registered logger to the bundle
+ * whose name was passed to getLogger.
+ */
+ if ((existingBundleName == null) && (resourceBundleName != null))
+ {
+ /* If ResourceBundle.getBundle throws an exception, the
+ * existing logger will be unchanged. This would be
+ * different if the assignment to resourceBundleName
+ * came first.
+ */
+ result.resourceBundle = ResourceBundle.getBundle(resourceBundleName);
+ result.resourceBundleName = resourceBundleName;
+ return result;
+ }
+
+ if ((existingBundleName != resourceBundleName)
+ && ((existingBundleName == null)
+ || !existingBundleName.equals(resourceBundleName)))
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ /**
+ * Creates a new, unnamed logger. Unnamed loggers are not
+ * registered in the namespace of the LogManager, and no special
+ * security permission is required for changing their state.
+ * Therefore, untrusted applets are able to modify their private
+ * logger instance obtained through this method.
+ *
+ * <p>The parent of the newly created logger will the the root
+ * logger, from which the level threshold and the handlers are
+ * inherited.
+ */
+ public static Logger getAnonymousLogger()
+ {
+ return getAnonymousLogger(null);
+ }
+
+
+ /**
+ * Creates a new, unnamed logger. Unnamed loggers are not
+ * registered in the namespace of the LogManager, and no special
+ * security permission is required for changing their state.
+ * Therefore, untrusted applets are able to modify their private
+ * logger instance obtained through this method.
+ *
+ * <p>The parent of the newly created logger will the the root
+ * logger, from which the level threshold and the handlers are
+ * inherited.
+ *
+ * @param resourceBundleName the name of a resource bundle
+ * for localizing messages, or <code>null</code>
+ * to indicate that messages do not need to be localized.
+ *
+ * @throws java.util.MissingResourceException if
+ * <code>resourceBundleName</code> is not <code>null</code>
+ * and no such bundle could be located.
+ */
+ public static Logger getAnonymousLogger(String resourceBundleName)
+ throws MissingResourceException
+ {
+ Logger result;
+
+ result = new Logger(null, resourceBundleName);
+ result.anonymous = true;
+ return result;
+ }
+
+
+ /**
+ * Returns the name of the resource bundle that is being used for
+ * localizing messages.
+ *
+ * @return the name of the resource bundle used for localizing messages,
+ * or <code>null</code> if the parent's resource bundle
+ * is used for this purpose.
+ */
+ public synchronized String getResourceBundleName()
+ {
+ return resourceBundleName;
+ }
+
+
+ /**
+ * Returns the resource bundle that is being used for localizing
+ * messages.
+ *
+ * @return the resource bundle used for localizing messages,
+ * or <code>null</code> if the parent's resource bundle
+ * is used for this purpose.
+ */
+ public synchronized ResourceBundle getResourceBundle()
+ {
+ return resourceBundle;
+ }
+
+
+ /**
+ * Returns the severity level threshold for this <code>Handler</code>.
+ * All log records with a lower severity level will be discarded;
+ * a log record of the same or a higher level will be published
+ * unless an installed <code>Filter</code> decides to discard it.
+ *
+ * @return the severity level below which all log messages will be
+ * discarded, or <code>null</code> if the logger inherits
+ * the threshold from its parent.
+ */
+ public synchronized Level getLevel()
+ {
+ return level;
+ }
+
+
+ /**
+ * Returns whether or not a message of the specified level
+ * would be logged by this logger.
+ *
+ * @throws NullPointerException if <code>level</code>
+ * is <code>null</code>.
+ */
+ public synchronized boolean isLoggable(Level level)
+ {
+ if (this.level != null)
+ return this.level.intValue() <= level.intValue();
+
+ if (parent != null)
+ return parent.isLoggable(level);
+ else
+ return false;
+ }
+
+
+ /**
+ * Sets the severity level threshold for this <code>Handler</code>.
+ * All log records with a lower severity level will be discarded
+ * immediately. A log record of the same or a higher level will be
+ * published unless an installed <code>Filter</code> decides to
+ * discard it.
+ *
+ * @param level the severity level below which all log messages
+ * will be discarded, or <code>null</code> to
+ * indicate that the logger should inherit the
+ * threshold from its parent.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setLevel(Level level)
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.level = level;
+ }
+
+
+ public synchronized Filter getFilter()
+ {
+ return filter;
+ }
+
+
+ /**
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setFilter(Filter filter)
+ throws SecurityException
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.filter = filter;
+ }
+
+
+
+
+ /**
+ * Returns the name of this logger.
+ *
+ * @return the name of this logger, or <code>null</code> if
+ * the logger is anonymous.
+ */
+ public String getName()
+ {
+ /* Note that the name of a logger cannot be changed during
+ * its lifetime, so no synchronization is needed.
+ */
+ return name;
+ }
+
+
+ /**
+ * Passes a record to registered handlers, provided the record
+ * is considered as loggable both by {@link #isLoggable(Level)}
+ * and a possibly installed custom {@link #setFilter(Filter) filter}.
+ *
+ * <p>If the logger has been configured to use parent handlers,
+ * the record will be forwarded to the parent of this logger
+ * in addition to being processed by the handlers registered with
+ * this logger.
+ *
+ * <p>The other logging methods in this class are convenience methods
+ * that merely create a new LogRecord and pass it to this method.
+ * Therefore, subclasses usually just need to override this single
+ * method for customizing the logging behavior.
+ *
+ * @param record the log record to be inspected and possibly forwarded.
+ */
+ public synchronized void log(LogRecord record)
+ {
+ if (!isLoggable(record.getLevel()))
+ return;
+
+ if ((filter != null) && !filter.isLoggable(record))
+ return;
+
+ /* If no logger name has been set for the log record,
+ * use the name of this logger.
+ */
+ if (record.getLoggerName() == null)
+ record.setLoggerName(name);
+
+ /* Avoid that some other thread is changing the logger hierarchy
+ * while we are traversing it.
+ */
+ synchronized (LogManager.getLogManager())
+ {
+ Logger curLogger = this;
+
+ do
+ {
+ /* The Sun J2SE 1.4 reference implementation seems to call the
+ * filter only for the logger whose log method is called,
+ * never for any of its parents. Also, parent loggers publish
+ * log record whatever their level might be. This is pretty
+ * weird, but GNU Classpath tries to be as compatible as
+ * possible to the reference implementation.
+ */
+ for (int i = 0; i < curLogger.handlers.length; i++)
+ curLogger.handlers[i].publish(record);
+
+ if (curLogger.getUseParentHandlers() == false)
+ break;
+
+ curLogger = curLogger.getParent();
+ }
+ while (parent != null);
+ }
+ }
+
+
+ public void log(Level level, String message)
+ {
+ if (isLoggable(level))
+ log(level, message, (Object[]) null);
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Object param)
+ {
+ if (isLoggable(level))
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ param);
+ }
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Object[] params)
+ {
+ if (isLoggable(level))
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ params);
+ }
+ }
+
+
+ public synchronized void log(Level level,
+ String message,
+ Throwable thrown)
+ {
+ if (isLoggable(level))
+ {
+ StackTraceElement caller = getCallerStackFrame();
+ logp(level,
+ caller != null ? caller.getClassName() : "<unknown>",
+ caller != null ? caller.getMethodName() : "<unknown>",
+ message,
+ thrown);
+ }
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message)
+ {
+ logp(level, sourceClass, sourceMethod, message,
+ (Object[]) null);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object param)
+ {
+ logp(level, sourceClass, sourceMethod, message,
+ new Object[] { param });
+ }
+
+
+ private synchronized ResourceBundle findResourceBundle()
+ {
+ if (resourceBundle != null)
+ return resourceBundle;
+
+ if (parent != null)
+ return parent.findResourceBundle();
+
+ return null;
+ }
+
+
+ private synchronized void logImpl(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object[] params)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundle(findResourceBundle());
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setParameters(params);
+
+ log(rec);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Object[] params)
+ {
+ logImpl(level, sourceClass, sourceMethod, message, params);
+ }
+
+
+ public synchronized void logp(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String message,
+ Throwable thrown)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundle(resourceBundle);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setThrown(thrown);
+
+ log(rec);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message)
+ {
+ logrb(level, sourceClass, sourceMethod, bundleName,
+ message, (Object[]) null);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Object param)
+ {
+ logrb(level, sourceClass, sourceMethod, bundleName,
+ message, new Object[] { param });
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Object[] params)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundleName(bundleName);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setParameters(params);
+
+ log(rec);
+ }
+
+
+ public synchronized void logrb(Level level,
+ String sourceClass,
+ String sourceMethod,
+ String bundleName,
+ String message,
+ Throwable thrown)
+ {
+ LogRecord rec = new LogRecord(level, message);
+
+ rec.setResourceBundleName(bundleName);
+ rec.setSourceClassName(sourceClass);
+ rec.setSourceMethodName(sourceMethod);
+ rec.setThrown(thrown);
+
+ log(rec);
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod,
+ Object param)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param);
+ }
+
+
+ public synchronized void entering(String sourceClass,
+ String sourceMethod,
+ Object[] params)
+ {
+ if (isLoggable(Level.FINER))
+ {
+ StringBuffer buf = new StringBuffer(80);
+ buf.append("ENTRY");
+ for (int i = 0; i < params.length; i++)
+ {
+ buf.append(" {");
+ buf.append(i);
+ buf.append('}');
+ }
+
+ logp(Level.FINER, sourceClass, sourceMethod, buf.toString(), params);
+ }
+ }
+
+
+ public synchronized void exiting(String sourceClass,
+ String sourceMethod)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
+ }
+
+
+ public synchronized void exiting(String sourceClass,
+ String sourceMethod,
+ Object result)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
+ }
+
+
+ public synchronized void throwing(String sourceClass,
+ String sourceMethod,
+ Throwable thrown)
+ {
+ if (isLoggable(Level.FINER))
+ logp(Level.FINER, sourceClass, sourceMethod, "THROW", thrown);
+ }
+
+
+ /**
+ * Logs a message with severity level SEVERE, indicating a serious
+ * failure that prevents normal program execution. Messages at this
+ * level should be understandable to an inexperienced, non-technical
+ * end user. Ideally, they explain in simple words what actions the
+ * user can take in order to resolve the problem.
+ *
+ * @see Level#SEVERE
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void severe(String message)
+ {
+ if (isLoggable(Level.SEVERE))
+ log(Level.SEVERE, message);
+ }
+
+
+ /**
+ * Logs a message with severity level WARNING, indicating a
+ * potential problem that does not prevent normal program execution.
+ * Messages at this level should be understandable to an
+ * inexperienced, non-technical end user. Ideally, they explain in
+ * simple words what actions the user can take in order to resolve
+ * the problem.
+ *
+ * @see Level#WARNING
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void warning(String message)
+ {
+ if (isLoggable(Level.WARNING))
+ log(Level.WARNING, message);
+ }
+
+
+ /**
+ * Logs a message with severity level INFO. {@link Level#INFO} is
+ * intended for purely informational messages that do not indicate
+ * error or warning situations. In the default logging
+ * configuration, INFO messages will be written to the system
+ * console. For this reason, the INFO level should be used only for
+ * messages that are important to end users and system
+ * administrators. Messages at this level should be understandable
+ * to an inexperienced, non-technical user.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void info(String message)
+ {
+ if (isLoggable(Level.INFO))
+ log(Level.INFO, message);
+ }
+
+
+ /**
+ * Logs a message with severity level CONFIG. {@link Level#CONFIG} is
+ * intended for static configuration messages, for example about the
+ * windowing environment, the operating system version, etc.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource bundle. While
+ * it is possible to pass <code>null</code>, this is not
+ * recommended, since a logging message without text is unlikely
+ * to be helpful.
+ */
+ public synchronized void config(String message)
+ {
+ if (isLoggable(Level.CONFIG))
+ log(Level.CONFIG, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINE. {@link Level#FINE} is
+ * intended for messages that are relevant for developers using
+ * the component generating log messages. Examples include minor,
+ * recoverable failures, or possible inefficiencies.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void fine(String message)
+ {
+ if (isLoggable(Level.FINE))
+ log(Level.FINE, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINER. {@link Level#FINER} is
+ * intended for rather detailed tracing, for example entering a
+ * method, returning from a method, or throwing an exception.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void finer(String message)
+ {
+ if (isLoggable(Level.FINER))
+ log(Level.FINER, message);
+ }
+
+
+ /**
+ * Logs a message with severity level FINEST. {@link Level#FINEST}
+ * is intended for highly detailed tracing, for example reaching a
+ * certain point inside the body of a method.
+ *
+ * @param message the message text, also used as look-up key if the
+ * logger is localizing messages with a resource
+ * bundle. While it is possible to pass
+ * <code>null</code>, this is not recommended, since
+ * a logging message without text is unlikely to be
+ * helpful.
+ */
+ public synchronized void finest(String message)
+ {
+ if (isLoggable(Level.FINEST))
+ log(Level.FINEST, message);
+ }
+
+
+ /**
+ * Adds a handler to the set of handlers that get notified
+ * when a log record is to be published.
+ *
+ * @param handler the handler to be added.
+ *
+ * @throws NullPointerException if <code>handler</code>
+ * is <code>null</code>.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void addHandler(Handler handler)
+ throws SecurityException
+ {
+ /* Throw a new NullPointerException if handler is null. */
+ handler.getClass();
+
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ if (!handlerList.contains(handler))
+ {
+ handlerList.add(handler);
+ handlers = getHandlers();
+ }
+ }
+
+
+ /**
+ * Removes a handler from the set of handlers that get notified
+ * when a log record is to be published.
+ *
+ * @param handler the handler to be removed.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted the
+ * permission to control the logging infrastructure by having
+ * LoggingPermission("control"). Untrusted code can obtain an
+ * anonymous logger through the static factory method {@link
+ * #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ *
+ * @throws NullPointerException if <code>handler</code>
+ * is <code>null</code>.
+ */
+ public synchronized void removeHandler(Handler handler)
+ throws SecurityException
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ /* Throw a new NullPointerException if handler is null. */
+ handler.getClass();
+
+ handlerList.remove(handler);
+ handlers = getHandlers();
+ }
+
+
+ /**
+ * Returns the handlers currently registered for this Logger.
+ * When a log record has been deemed as being loggable,
+ * it will be passed to all registered handlers for
+ * publication. In addition, if the logger uses parent handlers
+ * (see {@link #getUseParentHandlers() getUseParentHandlers}
+ * and {@link #setUseParentHandlers(boolean) setUseParentHandlers},
+ * the log record will be passed to the parent's handlers.
+ */
+ public synchronized Handler[] getHandlers()
+ {
+ /* We cannot return our internal handlers array
+ * because we do not have any guarantee that the
+ * caller would not change the array entries.
+ */
+ return (Handler[]) handlerList.toArray(new Handler[handlerList.size()]);
+ }
+
+
+ /**
+ * Returns whether or not this Logger forwards log records to
+ * handlers registered for its parent loggers.
+ *
+ * @return <code>false</code> if this Logger sends log records
+ * merely to Handlers registered with itself;
+ * <code>true</code> if this Logger sends log records
+ * not only to Handlers registered with itself, but also
+ * to those Handlers registered with parent loggers.
+ */
+ public synchronized boolean getUseParentHandlers()
+ {
+ return useParentHandlers;
+ }
+
+
+ /**
+ * Sets whether or not this Logger forwards log records to
+ * handlers registered for its parent loggers.
+ *
+ * @param useParentHandlers <code>false</code> to let this
+ * Logger send log records merely to Handlers registered
+ * with itself; <code>true</code> to let this Logger
+ * send log records not only to Handlers registered
+ * with itself, but also to those Handlers registered with
+ * parent loggers.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ *
+ */
+ public synchronized void setUseParentHandlers(boolean useParentHandlers)
+ {
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.useParentHandlers = useParentHandlers;
+ }
+
+
+ /**
+ * Returns the parent of this logger. By default, the parent is
+ * assigned by the LogManager by inspecting the logger's name.
+ *
+ * @return the parent of this logger (as detemined by the LogManager
+ * by inspecting logger names), the root logger if no other
+ * logger has a name which is a prefix of this logger's name, or
+ * <code>null</code> for the root logger.
+ */
+ public synchronized Logger getParent()
+ {
+ return parent;
+ }
+
+
+ /**
+ * Sets the parent of this logger. Usually, applications do not
+ * call this method directly. Instead, the LogManager will ensure
+ * that the tree of loggers reflects the hierarchical logger
+ * namespace. Basically, this method should not be public at all,
+ * but the GNU implementation follows the API specification.
+ *
+ * @throws NullPointerException if <code>parent</code> is
+ * <code>null</code>.
+ *
+ * @throws SecurityException if this logger is not anonymous, a
+ * security manager exists, and the caller is not granted
+ * the permission to control the logging infrastructure by
+ * having LoggingPermission("control"). Untrusted code can
+ * obtain an anonymous logger through the static factory method
+ * {@link #getAnonymousLogger(java.lang.String) getAnonymousLogger}.
+ */
+ public synchronized void setParent(Logger parent)
+ {
+ /* Throw a new NullPointerException if parent is null. */
+ parent.getClass();
+
+ if (this == root)
+ throw new IllegalArgumentException(
+ "the root logger can only have a null parent");
+
+ /* An application is allowed to control an anonymous logger
+ * without having the permission to control the logging
+ * infrastructure.
+ */
+ if (!anonymous)
+ LogManager.getLogManager().checkAccess();
+
+ this.parent = parent;
+ }
+
+ /**
+ * Gets the StackTraceElement of the first class that is not this class.
+ * That should be the initial caller of a logging method.
+ * @return caller of the initial logging method or null if unknown.
+ */
+ private native StackTraceElement getCallerStackFrame();
+
+ /**
+ * Reset and close handlers attached to this logger. This function is package
+ * private because it must only be avaiable to the LogManager.
+ */
+ void resetLogger()
+ {
+ for (int i = 0; i < handlers.length; i++)
+ {
+ handlers[i].close();
+ handlerList.remove(handlers[i]);
+ }
+ handlers = getHandlers();
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/logging/natLogger.cc b/gcc-4.2.1/libjava/java/util/logging/natLogger.cc
new file mode 100644
index 000000000..5c68b1722
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/logging/natLogger.cc
@@ -0,0 +1,49 @@
+// natLogger.cc - Native part of Logger class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation
+
+ This Logger is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the Logger "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+#include <platform.h>
+
+#include <string.h>
+
+#pragma implementation "Logger.h"
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java-stack.h>
+
+#include <java/lang/Object.h>
+#include <java/lang/Class.h>
+#include <java/util/logging/Logger.h>
+#include <java/lang/StackTraceElement.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+
+using namespace java::util::logging;
+
+java::lang::StackTraceElement*
+java::util::logging::Logger::getCallerStackFrame ()
+{
+ jclass klass = NULL;
+ _Jv_Method *meth = NULL;
+ _Jv_StackTrace::GetCallerInfo (&Logger::class$, &klass, &meth);
+
+ jstring meth_name = NULL;
+ jstring klass_name = NULL;
+ if (klass != NULL)
+ klass_name = klass->getName();
+ if (meth != NULL)
+ meth_name = _Jv_NewStringUtf8Const (meth->name);
+
+ java::lang::StackTraceElement *e
+ = new java::lang::StackTraceElement
+ (JvNewStringUTF (""), 0, klass_name, meth_name, false);
+
+ return e;
+}
diff --git a/gcc-4.2.1/libjava/java/util/natResourceBundle.cc b/gcc-4.2.1/libjava/java/util/natResourceBundle.cc
new file mode 100644
index 000000000..e8d4fb4fd
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/natResourceBundle.cc
@@ -0,0 +1,29 @@
+/* Copyright (C) 2002, 2003, 2005 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// Written by Tom Tromey <tromey@redhat.com>
+
+#include <config.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java-stack.h>
+#include <java/util/ResourceBundle.h>
+#include <java/lang/ClassLoader.h>
+#include <java/lang/Class.h>
+
+using namespace java::lang;
+
+java::lang::ClassLoader *
+java::util::ResourceBundle::getCallingClassLoader ()
+{
+ jclass caller = _Jv_StackTrace::GetCallingClass (&ResourceBundle::class$);
+ if (caller)
+ return caller->getClassLoaderInternal();
+ return NULL;
+}
diff --git a/gcc-4.2.1/libjava/java/util/natVMTimeZone.cc b/gcc-4.2.1/libjava/java/util/natVMTimeZone.cc
new file mode 100644
index 000000000..d45ebf978
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/natVMTimeZone.cc
@@ -0,0 +1,145 @@
+// natVMTimeZone.cc -- Native side of VMTimeZone class.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+#include <platform.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/util/VMTimeZone.h>
+#include <java/lang/Character.h>
+#include <java/lang/Integer.h>
+
+#include <stdio.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#include <string.h>
+
+/**
+ * This method returns a time zone id string which is in the form
+ * (standard zone name) or (standard zone name)(GMT offset) or
+ * (standard zone name)(GMT offset)(daylight time zone name). The
+ * GMT offset can be in seconds, or where it is evenly divisible by
+ * 3600, then it can be in hours. The offset must be the time to
+ * add to the local time to get GMT. If a offset is given and the
+ * time zone observes daylight saving then the (daylight time zone
+ * name) must also be given (otherwise it is assumed the time zone
+ * does not observe any daylight savings).
+ * <p>
+ * The result of this method is given to getDefaultTimeZone(String)
+ * which tries to map the time zone id to a known TimeZone. See
+ * that method on how the returned String is mapped to a real
+ * TimeZone object.
+ */
+jstring
+java::util::VMTimeZone::getSystemTimeZoneId()
+{
+ struct tm tim;
+#if !defined(HAVE_LOCALTIME_R) || !defined(_POSIX_PTHREAD_SEMANTICS)
+ struct tm *lt_tim;
+#endif
+#ifdef HAVE_TM_ZONE
+ int month;
+#endif
+ time_t current_time;
+ long tzoffset;
+ const char *tz1, *tz2;
+ char *tzid;
+
+ time(&current_time);
+#if defined(HAVE_LOCALTIME_R) && defined(_POSIX_PTHREAD_SEMANTICS)
+ localtime_r(&current_time, &tim);
+#else
+ /* Fall back on non-thread safe localtime. */
+ lt_tim = localtime(&current_time);
+ memcpy(&tim, lt_tim, sizeof (struct tm));
+#endif
+ mktime(&tim);
+
+#ifdef HAVE_TM_ZONE
+ /* We will cycle through the months to make sure we hit dst. */
+ month = tim.tm_mon;
+ tz1 = tz2 = NULL;
+ while (tz1 == NULL || tz2 == NULL)
+ {
+ if (tim.tm_isdst > 0)
+ tz2 = tim.tm_zone;
+ else if (tz1 == NULL)
+ {
+ tz1 = tim.tm_zone;
+ month = tim.tm_mon;
+ }
+
+ if (tz1 == NULL || tz2 == NULL)
+ {
+ tim.tm_mon++;
+ tim.tm_mon %= 12;
+ }
+
+ if (tim.tm_mon == month && tz2 == NULL)
+ tz2 = "";
+ else
+ mktime(&tim);
+ }
+ /* We want to make sure the tm struct we use later on is not dst. */
+ tim.tm_mon = month;
+ mktime(&tim);
+#elif defined (HAVE_TZNAME)
+ /* If dst is never used, tzname[1] is the empty string. */
+ tzset();
+ tz1 = tzname[0];
+ tz2 = tzname[1];
+#else
+ /* Some targets have no concept of timezones. Assume GMT without dst. */
+ tz1 = "GMT";
+ tz2 = "";
+#endif
+
+#ifdef STRUCT_TM_HAS_GMTOFF
+ /* tm_gmtoff is the number of seconds that you must add to GMT to get
+ local time, we need the number of seconds to add to the local time
+ to get GMT. */
+ tzoffset = -1L * tim.tm_gmtoff;
+#elif HAVE_UNDERSCORE_TIMEZONE
+ tzoffset = _timezone;
+#elif HAVE_TIMEZONE
+ /* timezone is secs WEST of UTC. */
+ tzoffset = timezone;
+#else
+ /* FIXME: there must be another global if neither tm_gmtoff nor timezone
+ is available, esp. if tzname is valid.
+ Richard Earnshaw <rearnsha@arm.com> has suggested using difftime to
+ calculate between gmtime and localtime (and accounting for possible
+ daylight savings time) as an alternative. */
+ tzoffset = 0L;
+#endif
+
+ if ((tzoffset % 3600) == 0)
+ tzoffset = tzoffset / 3600;
+
+ tzid = (char*) _Jv_Malloc (strlen(tz1) + strlen(tz2) + 6);
+ sprintf(tzid, "%s%ld%s", tz1, tzoffset, tz2);
+ jstring retval = JvNewStringUTF (tzid);
+ _Jv_Free (tzid);
+
+ return retval;
+}
diff --git a/gcc-4.2.1/libjava/java/util/zip/Deflater.java b/gcc-4.2.1/libjava/java/util/zip/Deflater.java
new file mode 100644
index 000000000..8ac8a34a6
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/zip/Deflater.java
@@ -0,0 +1,334 @@
+/* Deflater.java - Compress a data stream
+ Copyright (C) 1999, 2000, 2001, 2004, 2006 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+import gnu.gcj.RawData;
+
+/**
+ * This is the Deflater class. The deflater class compresses input
+ * with the deflate algorithm described in RFC 1951. It has several
+ * compression levels and three different strategies described below.
+ *
+ * This class is <i>not</i> thread safe. This is inherent in the API, due
+ * to the split of deflate and setInput.
+ *
+ * @author Jochen Hoenicke
+ * @author Tom Tromey
+ */
+public class Deflater
+{
+ /**
+ * The best and slowest compression level. This tries to find very
+ * long and distant string repetitions.
+ */
+ public static final int BEST_COMPRESSION = 9;
+ /**
+ * The worst but fastest compression level.
+ */
+ public static final int BEST_SPEED = 1;
+ /**
+ * The default compression level.
+ */
+ public static final int DEFAULT_COMPRESSION = -1;
+ /**
+ * This level won't compress at all but output uncompressed blocks.
+ */
+ public static final int NO_COMPRESSION = 0;
+
+ /**
+ * The default strategy.
+ */
+ public static final int DEFAULT_STRATEGY = 0;
+ /**
+ * This strategy will only allow longer string repetitions. It is
+ * useful for random data with a small character set.
+ */
+ public static final int FILTERED = 1;
+
+ /**
+ * This strategy will not look for string repetitions at all. It
+ * only encodes with Huffman trees (which means, that more common
+ * characters get a smaller encoding.
+ */
+ public static final int HUFFMAN_ONLY = 2;
+
+ /**
+ * The compression method. This is the only method supported so far.
+ * There is no need to use this constant at all.
+ */
+ public static final int DEFLATED = 8;
+
+ /** Compression level. */
+ private int level;
+
+ /** Compression strategy. */
+ private int strategy;
+
+ /** The zlib stream. */
+ private RawData zstream;
+
+ /** True if finished. */
+ private boolean is_finished;
+
+ /** `Flush' flag to pass to next call to deflate. */
+ private int flush_flag;
+
+ /**
+ * Creates a new deflater with default compression level.
+ */
+ public Deflater()
+ {
+ this(DEFAULT_COMPRESSION, false);
+ }
+
+ /**
+ * Creates a new deflater with given compression level.
+ * @param lvl the compression level, a value between NO_COMPRESSION
+ * and BEST_COMPRESSION, or DEFAULT_COMPRESSION.
+ * @exception IllegalArgumentException if lvl is out of range.
+ */
+ public Deflater(int lvl)
+ {
+ this(lvl, false);
+ }
+
+ /**
+ * Creates a new deflater with given compression level.
+ * @param lvl the compression level, a value between NO_COMPRESSION
+ * and BEST_COMPRESSION.
+ * @param nowrap true, iff we should suppress the deflate header at the
+ * beginning and the adler checksum at the end of the output. This is
+ * useful for the GZIP format.
+ * @exception IllegalArgumentException if lvl is out of range.
+ */
+ public Deflater(int lvl, boolean noHeader)
+ {
+ this.strategy = DEFAULT_STRATEGY;
+ init(lvl, noHeader);
+ setLevel(lvl);
+ }
+
+ private native void init(int level, boolean noHeader);
+
+ private native void update();
+
+ /**
+ * Resets the deflater. The deflater acts afterwards as if it was
+ * just created with the same compression level and strategy as it
+ * had before.
+ */
+ public native void reset();
+
+ /**
+ * Frees all objects allocated by the compressor. There's no
+ * reason to call this, since you can just rely on garbage
+ * collection. Exists only for compatibility against Sun's JDK,
+ * where the compressor allocates native memory.
+ * If you call any method (even reset) afterwards the behaviour is
+ * <i>undefined</i>.
+ * @deprecated Just clear all references to deflater instead.
+ */
+ public native void end();
+
+ /**
+ * Gets the current adler checksum of the data that was processed so
+ * far.
+ */
+ public native int getAdler();
+
+ /**
+ * Gets the number of input bytes processed so far.
+ */
+ public native int getTotalIn();
+
+ /**
+ * Gets the number of output bytes so far.
+ */
+ public native int getTotalOut();
+
+ /**
+ * Finalizes this object.
+ */
+ protected void finalize()
+ {
+ end();
+ }
+
+ /**
+ * Finishes the deflater with the current input block. It is an error
+ * to give more input after this method was called. This method must
+ * be called to force all bytes to be flushed.
+ */
+ public native void finish();
+
+ /**
+ * Returns true iff the stream was finished and no more output bytes
+ * are available.
+ */
+ public synchronized boolean finished()
+ {
+ return is_finished;
+ }
+
+ /**
+ * Returns true, if the input buffer is empty.
+ * You should then call setInput(). <br>
+ *
+ * <em>NOTE</em>: This method can also return true when the stream
+ * was finished.
+ */
+ public native boolean needsInput();
+
+ /**
+ * Sets the data which should be compressed next. This should be only
+ * called when needsInput indicates that more input is needed.
+ * If you call setInput when needsInput() returns false, the
+ * previous input that is still pending will be thrown away.
+ * The given byte array should not be changed, before needsInput() returns
+ * true again.
+ * This call is equivalent to <code>setInput(input, 0, input.length)</code>.
+ * @param input the buffer containing the input data.
+ * @exception IllegalStateException if the buffer was finished() or ended().
+ */
+ public void setInput(byte[] input)
+ {
+ setInput(input, 0, input.length);
+ }
+
+ /**
+ * Sets the data which should be compressed next. This should be
+ * only called when needsInput indicates that more input is needed.
+ * The given byte array should not be changed, before needsInput() returns
+ * true again.
+ * @param input the buffer containing the input data.
+ * @param off the start of the data.
+ * @param len the length of the data.
+ * @exception IllegalStateException if the buffer was finished() or ended()
+ * or if previous input is still pending.
+ */
+ public native void setInput(byte[] input, int off, int len);
+
+ /**
+ * Sets the compression level. There is no guarantee of the exact
+ * position of the change, but if you call this when needsInput is
+ * true the change of compression level will occur somewhere near
+ * before the end of the so far given input.
+ * @param lvl the new compression level.
+ */
+ public synchronized void setLevel(int lvl)
+ {
+ if (lvl != -1 && (lvl < 0 || lvl > 9))
+ throw new IllegalArgumentException();
+ level = (lvl == -1) ? 6 : lvl;
+ update();
+ }
+
+ /**
+ * Sets the compression strategy. Strategy is one of
+ * DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact
+ * position where the strategy is changed, the same as for
+ * setLevel() applies.
+ * @param stgy the new compression strategy.
+ */
+ public synchronized void setStrategy(int stgy)
+ {
+ if (stgy != DEFAULT_STRATEGY && stgy != FILTERED
+ && stgy != HUFFMAN_ONLY)
+ throw new IllegalArgumentException();
+ strategy = stgy;
+ update();
+ }
+
+ /**
+ * Deflates the current input block to the given array. It returns
+ * the number of bytes compressed, or 0 if either
+ * needsInput() or finished() returns true or length is zero.
+ * @param output the buffer where to write the compressed data.
+ */
+ public int deflate(byte[] output)
+ {
+ return deflate(output, 0, output.length);
+ }
+
+ /**
+ * Deflates the current input block to the given array. It returns
+ * the number of bytes compressed, or 0 if either
+ * needsInput() or finished() returns true or length is zero.
+ * @param output the buffer where to write the compressed data.
+ * @param offset the offset into the output array.
+ * @param length the maximum number of bytes that may be written.
+ * @exception IllegalStateException if end() was called.
+ * @exception IndexOutOfBoundsException if offset and/or length
+ * don't match the array length.
+ */
+ public native int deflate(byte[] output, int off, int len);
+
+ /**
+ * Sets the dictionary which should be used in the deflate process.
+ * This call is equivalent to <code>setDictionary(dict, 0,
+ * dict.length)</code>.
+ * @param dict the dictionary.
+ * @exception IllegalStateException if setInput () or deflate ()
+ * were already called or another dictionary was already set.
+ */
+ public void setDictionary(byte[] dict)
+ {
+ setDictionary(dict, 0, dict.length);
+ }
+
+ /**
+ * Sets the dictionary which should be used in the deflate process.
+ * The dictionary should be a byte array containing strings that are
+ * likely to occur in the data which should be compressed. The
+ * dictionary is not stored in the compressed output, only a
+ * checksum. To decompress the output you need to supply the same
+ * dictionary again.
+ * @param dict the dictionary.
+ * @param offset an offset into the dictionary.
+ * @param length the length of the dictionary.
+ * @exception IllegalStateException if setInput () or deflate () were
+ * already called or another dictionary was already set.
+ */
+ public native void setDictionary(byte[] buf, int off, int len);
+
+ // Classpath's compression library supports flushing, but we
+ // don't. So this is a no-op here.
+ void flush()
+ {
+ }
+}
diff --git a/gcc-4.2.1/libjava/java/util/zip/Inflater.java b/gcc-4.2.1/libjava/java/util/zip/Inflater.java
new file mode 100644
index 000000000..c51cde802
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/zip/Inflater.java
@@ -0,0 +1,269 @@
+/* Inflater.java - Decompress a data stream
+ Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.util.zip;
+
+import gnu.gcj.RawData;
+
+/* Written using on-line Java Platform 1.2 API Specification
+ * and JCL book.
+ * Believed complete and correct.
+ */
+
+/**
+ * Inflater is used to decompress data that has been compressed according
+ * to the "deflate" standard described in rfc1950.
+ *
+ * The usage is as following. First you have to set some input with
+ * <code>setInput()</code>, then inflate() it. If inflate doesn't
+ * inflate any bytes there may be three reasons:
+ * <ul>
+ * <li>needsInput() returns true because the input buffer is empty.
+ * You have to provide more input with <code>setInput()</code>.
+ * NOTE: needsInput() also returns true when, the stream is finished.
+ * </li>
+ * <li>needsDictionary() returns true, you have to provide a preset
+ * dictionary with <code>setDictionary()</code>.</li>
+ * <li>finished() returns true, the inflater has finished.</li>
+ * </ul>
+ * Once the first output byte is produced, a dictionary will not be
+ * needed at a later stage.
+ *
+ * @author John Leuner, Jochen Hoenicke
+ * @author Tom Tromey
+ * @date May 17, 1999
+ * @since JDK 1.1
+ */
+public class Inflater
+{
+ // The zlib stream.
+ private RawData zstream;
+
+ // True if finished.
+ private boolean is_finished;
+
+ // True if dictionary needed.
+ private boolean dict_needed;
+
+ /**
+ * Creates a new inflater.
+ */
+ public Inflater ()
+ {
+ this (false);
+ }
+
+ /**
+ * Creates a new inflater.
+ * @param nowrap true if no header and checksum field appears in the
+ * stream. This is used for GZIPed input. For compatibility with
+ * Sun JDK you should provide one byte of input more than needed in
+ * this case.
+ */
+ public Inflater (boolean noHeader)
+ {
+ init (noHeader);
+ }
+
+ /**
+ * Finalizes this object.
+ */
+ protected void finalize ()
+ {
+ end ();
+ }
+
+ /**
+ * Frees all objects allocated by the inflater. There's no reason
+ * to call this, since you can just rely on garbage collection (even
+ * for the Sun implementation). Exists only for compatibility
+ * with Sun's JDK, where the compressor allocates native memory.
+ * If you call any method (even reset) afterwards the behaviour is
+ * <i>undefined</i>.
+ * @deprecated Just clear all references to inflater instead.
+ */
+ public native void end ();
+
+ /**
+ * Returns true, if the inflater has finished. This means, that no
+ * input is needed and no output can be produced.
+ */
+ public synchronized boolean finished ()
+ {
+ return is_finished;
+ }
+
+ /**
+ * Gets the adler checksum. This is either the checksum of all
+ * uncompressed bytes returned by inflate(), or if needsDictionary()
+ * returns true (and thus no output was yet produced) this is the
+ * adler checksum of the expected dictionary.
+ * @returns the adler checksum.
+ */
+ public native int getAdler ();
+
+ /**
+ * Gets the number of unprocessed input. Useful, if the end of the
+ * stream is reached and you want to further process the bytes after
+ * the deflate stream.
+ * @return the number of bytes of the input which were not processed.
+ */
+ public native int getRemaining ();
+
+ /**
+ * Gets the total number of processed compressed input bytes.
+ * @return the total number of bytes of processed input bytes.
+ */
+ public native int getTotalIn ();
+
+ /**
+ * Gets the total number of output bytes returned by inflate().
+ * @return the total number of output bytes.
+ */
+ public native int getTotalOut ();
+
+ /**
+ * Inflates the compressed stream to the output buffer. If this
+ * returns 0, you should check, whether needsDictionary(),
+ * needsInput() or finished() returns true, to determine why no
+ * further output is produced.
+ * @param buffer the output buffer.
+ * @return the number of bytes written to the buffer, 0 if no further
+ * output can be produced.
+ * @exception DataFormatException if deflated stream is invalid.
+ * @exception IllegalArgumentException if buf has length 0.
+ */
+ public int inflate (byte[] buf) throws DataFormatException
+ {
+ return inflate (buf, 0, buf.length);
+ }
+
+ /**
+ * Inflates the compressed stream to the output buffer. If this
+ * returns 0, you should check, whether needsDictionary(),
+ * needsInput() or finished() returns true, to determine why no
+ * further output is produced.
+ * @param buffer the output buffer.
+ * @param off the offset into buffer where the output should start.
+ * @param len the maximum length of the output.
+ * @return the number of bytes written to the buffer, 0 if no further
+ * output can be produced.
+ * @exception DataFormatException if deflated stream is invalid.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public native int inflate (byte[] buf, int off, int len)
+ throws DataFormatException;
+
+ private native void init (boolean noHeader);
+
+ /**
+ * Returns true, if a preset dictionary is needed to inflate the input.
+ */
+ public synchronized boolean needsDictionary ()
+ {
+ return dict_needed;
+ }
+
+ /**
+ * Returns true, if the input buffer is empty.
+ * You should then call setInput(). <br>
+ *
+ * <em>NOTE</em>: This method also returns true when the stream is finished.
+ */
+ public synchronized boolean needsInput ()
+ {
+ return getRemaining () == 0;
+ }
+
+ /**
+ * Resets the inflater so that a new stream can be decompressed. All
+ * pending input and output will be discarded.
+ */
+ public native void reset ();
+
+ /**
+ * Sets the preset dictionary. This should only be called, if
+ * needsDictionary() returns true and it should set the same
+ * dictionary, that was used for deflating. The getAdler()
+ * function returns the checksum of the dictionary needed.
+ * @param buffer the dictionary.
+ * @exception IllegalStateException if no dictionary is needed.
+ * @exception IllegalArgumentException if the dictionary checksum is
+ * wrong.
+ */
+ public void setDictionary (byte[] buf)
+ {
+ setDictionary (buf, 0, buf.length);
+ }
+
+ /**
+ * Sets the preset dictionary. This should only be called, if
+ * needsDictionary() returns true and it should set the same
+ * dictionary, that was used for deflating. The getAdler()
+ * function returns the checksum of the dictionary needed.
+ * @param buffer the dictionary.
+ * @param off the offset into buffer where the dictionary starts.
+ * @param len the length of the dictionary.
+ * @exception IllegalStateException if no dictionary is needed.
+ * @exception IllegalArgumentException if the dictionary checksum is
+ * wrong.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public native void setDictionary (byte[] buf, int off, int len);
+
+ /**
+ * Sets the input. This should only be called, if needsInput()
+ * returns true.
+ * @param buffer the input.
+ * @exception IllegalStateException if no input is needed.
+ */
+ public void setInput (byte[] buf)
+ {
+ setInput (buf, 0, buf.length);
+ }
+
+ /**
+ * Sets the input. This should only be called, if needsInput()
+ * returns true.
+ * @param buffer the input.
+ * @param off the offset into buffer where the input starts.
+ * @param len the length of the input.
+ * @exception IllegalStateException if no input is needed.
+ * @exception IndexOutOfBoundsException if the off and/or len are wrong.
+ */
+ public native void setInput (byte[] buf, int off, int len);
+}
diff --git a/gcc-4.2.1/libjava/java/util/zip/natDeflater.cc b/gcc-4.2.1/libjava/java/util/zip/natDeflater.cc
new file mode 100644
index 000000000..23e1201b5
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/zip/natDeflater.cc
@@ -0,0 +1,216 @@
+// natDeflater.cc - Implementation of Deflater native methods.
+
+/* Copyright (C) 1999, 2002 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// Written by Tom Tromey <tromey@cygnus.com>
+
+#include <config.h>
+
+#include <zlib.h>
+#include <stdlib.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/util/zip/Deflater.h>
+#include <java/util/zip/DataFormatException.h>
+
+#include <java/lang/InternalError.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+
+extern void *_Jv_ZMalloc (void *, uInt nitems, uInt size);
+extern void _Jv_ZFree (void *, void *addr);
+
+
+
+jint
+java::util::zip::Deflater::deflate (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ if (len == 0)
+ return 0;
+
+ s->next_out = (Bytef *) (elements (buf) + off);
+ s->avail_out = len;
+
+ switch (::deflate (s, flush_flag))
+ {
+ case Z_STREAM_END:
+ is_finished = true;
+ if (s->avail_out == (unsigned int) len)
+ return -1;
+ break;
+
+ case Z_STREAM_ERROR:
+ case Z_BUF_ERROR:
+ // FIXME?
+ throw new java::lang::InternalError;
+ break;
+
+ case Z_OK:
+ break;
+ }
+
+ return len - s->avail_out;
+}
+
+void
+java::util::zip::Deflater::end ()
+{
+ JvSynchronize sync (this);
+ // Just ignore errors.
+ deflateEnd ((z_streamp) zstream);
+ _Jv_Free (zstream);
+ zstream = NULL;
+}
+
+void
+java::util::zip::Deflater::finish ()
+{
+ JvSynchronize sync (this);
+ flush_flag = Z_FINISH;
+}
+
+jint
+java::util::zip::Deflater::getAdler ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->adler;
+}
+
+jint
+java::util::zip::Deflater::getTotalIn ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_in;
+}
+
+jint
+java::util::zip::Deflater::getTotalOut ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_out;
+}
+
+jboolean
+java::util::zip::Deflater::needsInput ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->avail_in == 0;
+}
+
+void
+java::util::zip::Deflater::reset ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ // Just ignore errors.
+ deflateReset (s);
+ s->avail_in = 0;
+ flush_flag = 0;
+ is_finished = false;
+}
+
+void
+java::util::zip::Deflater::setDictionary (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ // Ignore errors.
+ deflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
+}
+
+void
+java::util::zip::Deflater::setInput (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ s->next_in = (Bytef *) (elements (buf) + off);
+ s->avail_in = len;
+}
+
+void
+java::util::zip::Deflater::update ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ int strat = Z_DEFAULT_STRATEGY;
+ switch (strategy)
+ {
+ case DEFAULT_STRATEGY:
+ strat = Z_DEFAULT_STRATEGY;
+ break;
+ case FILTERED:
+ strat = Z_FILTERED;
+ break;
+ case HUFFMAN_ONLY:
+ strat = Z_HUFFMAN_ONLY;
+ break;
+ default:
+ JvFail ("unexpected strategy");
+ }
+
+ // Ignore errors.
+ deflateParams (s, level, strat);
+}
+
+void
+java::util::zip::Deflater::init (jint level, jboolean no_header)
+{
+ z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
+ stream->next_in = Z_NULL;
+ stream->avail_in = 0;
+ stream->zalloc = _Jv_ZMalloc;
+ stream->zfree = _Jv_ZFree;
+ stream->opaque = NULL;
+
+ // Handle NO_HEADER using undocumented zlib feature.
+ int wbits = MAX_WBITS;
+ if (no_header)
+ wbits = - wbits;
+
+#define DEFAULT_MEM_LEVEL 8
+ if (deflateInit2 (stream, level, Z_DEFLATED, wbits,
+ DEFAULT_MEM_LEVEL, Z_DEFAULT_STRATEGY) != Z_OK)
+ {
+ jstring msg = NULL;
+ if (stream->msg != NULL)
+ msg = JvNewStringLatin1 (stream->msg);
+ throw new java::lang::InternalError (msg);
+ }
+
+ zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
+ is_finished = false;
+ flush_flag = 0;
+}
diff --git a/gcc-4.2.1/libjava/java/util/zip/natInflater.cc b/gcc-4.2.1/libjava/java/util/zip/natInflater.cc
new file mode 100644
index 000000000..69de6c335
--- /dev/null
+++ b/gcc-4.2.1/libjava/java/util/zip/natInflater.cc
@@ -0,0 +1,214 @@
+// natInflater.cc - Implementation of Inflater native methods.
+
+/* Copyright (C) 1999, 2002 Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+// Written by Tom Tromey <tromey@cygnus.com>
+
+#include <config.h>
+
+#include <zlib.h>
+#include <stdlib.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+
+#include <java/util/zip/Inflater.h>
+#include <java/util/zip/DataFormatException.h>
+
+#include <java/lang/InternalError.h>
+#include <java/lang/NullPointerException.h>
+#include <java/lang/ArrayIndexOutOfBoundsException.h>
+#include <java/lang/OutOfMemoryError.h>
+
+
+
+// A couple of helper functions used to interface with zlib's
+// allocation.
+
+void *
+_Jv_ZMalloc (void *, uInt nitems, uInt size)
+{
+ return _Jv_Malloc (nitems * size);
+}
+
+void
+_Jv_ZFree (void *, void *addr)
+{
+ _Jv_Free (addr);
+}
+
+
+
+void
+java::util::zip::Inflater::end ()
+{
+ JvSynchronize sync (this);
+ // Just ignore errors.
+ inflateEnd ((z_streamp) zstream);
+ _Jv_Free (zstream);
+ zstream = NULL;
+}
+
+jint
+java::util::zip::Inflater::getAdler ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->adler;
+}
+
+jint
+java::util::zip::Inflater::getRemaining ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->avail_in;
+}
+
+jint
+java::util::zip::Inflater::getTotalIn ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_in;
+}
+
+jint
+java::util::zip::Inflater::getTotalOut ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ return s->total_out;
+}
+
+jint
+java::util::zip::Inflater::inflate (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ if (len == 0)
+ return 0;
+
+ s->next_out = (Bytef *) (elements (buf) + off);
+ s->avail_out = len;
+
+ switch (::inflate (s, Z_SYNC_FLUSH))
+ {
+ case Z_BUF_ERROR:
+ /* Using the no_header option, zlib requires an extra padding byte at the
+ end of the stream in order to successfully complete decompression (see
+ zlib/contrib/minizip/unzip.c). We don't do this, so can end up with a
+ Z_BUF_ERROR at the end of a stream when zlib has completed inflation
+ and there's no more input. Thats not a problem. */
+ if (s->avail_in != 0)
+ throw new java::lang::InternalError;
+ // Fall through.
+
+ case Z_STREAM_END:
+ is_finished = true;
+ if (s->avail_out == (unsigned int) len)
+ return -1;
+ break;
+
+ case Z_NEED_DICT:
+ dict_needed = true;
+ break;
+
+ case Z_DATA_ERROR:
+ throw new java::util::zip::DataFormatException
+ (s->msg == NULL ? NULL : JvNewStringLatin1 (s->msg));
+ break;
+
+ case Z_MEM_ERROR:
+ throw new java::lang::OutOfMemoryError;
+ break;
+
+ case Z_OK:
+ break;
+ }
+
+ return len - s->avail_out;
+}
+
+void
+java::util::zip::Inflater::reset ()
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+ // Just ignore errors.
+ inflateReset (s);
+ s->avail_in = 0;
+ is_finished = false;
+ dict_needed = false;
+}
+
+void
+java::util::zip::Inflater::setDictionary (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ // Ignore errors.
+ inflateSetDictionary (s, (Bytef *) (elements (buf) + off), len);
+ dict_needed = false;
+}
+
+void
+java::util::zip::Inflater::setInput (jbyteArray buf, jint off, jint len)
+{
+ JvSynchronize sync (this);
+ z_streamp s = (z_streamp) zstream;
+
+ if (! buf)
+ throw new java::lang::NullPointerException;
+ if (off < 0 || len < 0 || off + len > buf->length)
+ throw new java::lang::ArrayIndexOutOfBoundsException;
+
+ s->next_in = (Bytef *) (elements (buf) + off);
+ s->avail_in = len;
+}
+
+void
+java::util::zip::Inflater::init (jboolean no_header)
+{
+ z_stream_s *stream = (z_stream_s *) _Jv_Malloc (sizeof (z_stream_s));
+ stream->next_in = Z_NULL;
+ stream->avail_in = 0;
+ stream->zalloc = _Jv_ZMalloc;
+ stream->zfree = _Jv_ZFree;
+ stream->opaque = NULL;
+
+ // Handle NO_HEADER using undocumented zlib feature.
+ int wbits = MAX_WBITS;
+ if (no_header)
+ wbits = - wbits;
+
+ if (inflateInit2 (stream, wbits) != Z_OK)
+ {
+ jstring msg = NULL;
+ if (stream->msg != NULL)
+ msg = JvNewStringLatin1 (stream->msg);
+ throw new java::lang::InternalError (msg);
+ }
+
+ zstream = reinterpret_cast<gnu::gcj::RawData *> (stream);
+ is_finished = false;
+ dict_needed = false;
+}