Imported GNU Classpath 0.20

Imported GNU Classpath 0.20
       * Makefile.am (AM_CPPFLAGS): Add classpath/include.
       * java/nio/charset/spi/CharsetProvider.java: New override file.
       * java/security/Security.java: Likewise.
       * sources.am: Regenerated.
       * Makefile.in: Likewise.

From-SVN: r109831
This commit is contained in:
Mark Wielaard
2006-01-17 18:09:40 +00:00
parent bcb36c3e02
commit 2127637945
444 changed files with 75778 additions and 30731 deletions
+1 -1
View File
@@ -415,7 +415,7 @@ public class BorderLayout implements LayoutManager2, java.io.Serializable
*/
public Dimension maximumLayoutSize(Container target)
{
return calcSize(target, MAX);
return new Dimension (Integer.MAX_VALUE, Integer.MAX_VALUE);
}
/**
+27 -15
View File
@@ -1038,14 +1038,10 @@ public abstract class Component
if ((c != null) && c.equals(background))
return;
// If c is null, inherit from closest ancestor whose bg is set.
if (c == null && parent != null)
c = parent.getBackground();
if (peer != null && c != null)
peer.setBackground(c);
Color previous = background;
background = c;
if (peer != null && c != null)
peer.setBackground(c);
firePropertyChange("background", previous, c);
}
@@ -2642,7 +2638,7 @@ public abstract class Component
{
mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
if (mouseMotionListener != null)
enableEvents(AWTEvent.MOUSE_EVENT_MASK);
enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
}
/**
@@ -2775,10 +2771,19 @@ public abstract class Component
}
/**
* Returns all registered EventListers of the given listenerType.
* Returns all registered {@link EventListener}s of the given
* <code>listenerType</code>.
*
* @param listenerType the class of listeners to filter
* @return an array of registered listeners
* @param listenerType the class of listeners to filter (<code>null</code>
* not permitted).
*
* @return An array of registered listeners.
*
* @throws ClassCastException if <code>listenerType</code> does not implement
* the {@link EventListener} interface.
* @throws NullPointerException if <code>listenerType</code> is
* <code>null</code>.
*
* @see #getComponentListeners()
* @see #getFocusListeners()
* @see #getHierarchyListeners()
@@ -4786,7 +4791,12 @@ p * <li>the set of backward traversal keys
void dispatchEventImpl(AWTEvent e)
{
Event oldEvent = translateEvent (e);
// This boolean tells us not to process focus events when the focus
// opposite component is the same as the focus component.
boolean ignoreFocus =
(e instanceof FocusEvent &&
((FocusEvent)e).getComponent() == ((FocusEvent)e).getOppositeComponent());
if (oldEvent != null)
postEvent (oldEvent);
@@ -4817,7 +4827,8 @@ p * <li>the set of backward traversal keys
break;
}
}
if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE)
if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE
&& !ignoreFocus)
processEvent(e);
}
@@ -4853,11 +4864,12 @@ p * <li>the set of backward traversal keys
case MouseEvent.MOUSE_EXITED:
case MouseEvent.MOUSE_PRESSED:
case MouseEvent.MOUSE_RELEASED:
return (mouseListener != null
|| (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
case MouseEvent.MOUSE_MOVED:
case MouseEvent.MOUSE_DRAGGED:
return (mouseListener != null
|| mouseMotionListener != null
|| (eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0);
return (mouseMotionListener != null
|| (eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0);
case FocusEvent.FOCUS_GAINED:
case FocusEvent.FOCUS_LOST:
+30 -29
View File
@@ -449,9 +449,6 @@ public class Container extends Component
ContainerEvent.COMPONENT_REMOVED,
r);
getToolkit().getSystemEventQueue().postEvent(ce);
// Repaint this container.
repaint();
}
}
}
@@ -896,13 +893,21 @@ public class Container extends Component
}
/**
* Returns an array of all the objects currently registered as FooListeners
* upon this Container. FooListeners are registered using the addFooListener
* method.
*
* @exception ClassCastException If listenerType doesn't specify a class or
* interface that implements @see java.util.EventListener.
* Returns all registered {@link EventListener}s of the given
* <code>listenerType</code>.
*
* @param listenerType the class of listeners to filter (<code>null</code>
* not permitted).
*
* @return An array of registered listeners.
*
* @throws ClassCastException if <code>listenerType</code> does not implement
* the {@link EventListener} interface.
* @throws NullPointerException if <code>listenerType</code> is
* <code>null</code>.
*
* @see #getContainerListeners()
*
* @since 1.3
*/
public EventListener[] getListeners(Class listenerType)
@@ -1094,7 +1099,7 @@ public class Container extends Component
{
if (!contains(x, y))
return null;
for (int i = 0; i < ncomponents; ++i)
{
// Ignore invisible children...
@@ -1117,7 +1122,8 @@ public class Container extends Component
}
//don't return transparent components with no MouseListeners
if (this.getMouseListeners().length == 0)
if (getMouseListeners().length == 0
&& getMouseMotionListeners().length == 0)
return null;
return this;
}
@@ -1625,30 +1631,19 @@ public class Container extends Component
Component comp)
{
Rectangle bounds = comp.getBounds();
Rectangle oldClip = gfx.getClipBounds();
if (oldClip == null)
oldClip = bounds;
Rectangle clip = oldClip.intersection(bounds);
if(!gfx.hitClip(bounds.x,bounds.y, bounds.width, bounds.height))
return;
if (clip.isEmpty()) return;
boolean clipped = false;
boolean translated = false;
Graphics g2 = gfx.create(bounds.x, bounds.y, bounds.width,
bounds.height);
try
{
gfx.setClip(clip.x, clip.y, clip.width, clip.height);
clipped = true;
gfx.translate(bounds.x, bounds.y);
translated = true;
visitor.visit(comp, gfx);
visitor.visit(comp, g2);
}
finally
{
if (translated)
gfx.translate (-bounds.x, -bounds.y);
if (clipped)
gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height);
g2.dispose();
}
}
@@ -2148,12 +2143,18 @@ class LightweightDispatcher implements Serializable
break;
}
if (me.getID() == MouseEvent.MOUSE_PRESSED && modifiers > 0
if (me.getID() == MouseEvent.MOUSE_RELEASED
|| me.getID() == MouseEvent.MOUSE_PRESSED && modifiers > 0
|| me.getID() == MouseEvent.MOUSE_DRAGGED)
{
// If any of the following events occur while a button is held down,
// they should be dispatched to the same component to which the
// original MOUSE_PRESSED event was dispatched:
// - MOUSE_RELEASED: This is important for correct dragging
// behaviour, otherwise the release goes to an arbitrary component
// outside of the dragged component. OTOH, if there is no mouse
// drag while the mouse is pressed, the component under the mouse
// is the same as the previously pressed component anyway.
// - MOUSE_PRESSED: another button pressed while the first is held
// down
// - MOUSE_DRAGGED
+15 -9
View File
@@ -341,11 +341,14 @@ public class GridBagLayout
GridBagLayoutInfo info = getLayoutInfo (parent, PREFERREDSIZE);
if (info.cols == 0 && info.rows == 0)
return;
layoutInfo = info;
// DEBUG
//dumpLayoutInfo (layoutInfo);
//dumpLayoutInfo (info);
// Calling setBounds on these components causes this layout to
// be invalidated, clearing the layout information cache,
// layoutInfo. So we wait until after this for loop to set
// layoutInfo.
for(int i = 0; i < components.length; i++)
{
Component component = components [i];
@@ -357,11 +360,11 @@ public class GridBagLayout
GridBagConstraints constraints =
lookupInternalConstraints(component);
int cellx = sumIntArray(layoutInfo.colWidths, constraints.gridx);
int celly = sumIntArray(layoutInfo.rowHeights, constraints.gridy);
int cellw = sumIntArray(layoutInfo.colWidths,
int cellx = sumIntArray(info.colWidths, constraints.gridx);
int celly = sumIntArray(info.rowHeights, constraints.gridy);
int cellw = sumIntArray(info.colWidths,
constraints.gridx + constraints.gridwidth) - cellx;
int cellh = sumIntArray(layoutInfo.rowHeights,
int cellh = sumIntArray(info.rowHeights,
constraints.gridy + constraints.gridheight) - celly;
Insets insets = constraints.insets;
@@ -438,11 +441,14 @@ public class GridBagLayout
break;
}
component.setBounds(layoutInfo.pos_x + x, layoutInfo.pos_y + y, dim.width, dim.height);
component.setBounds(info.pos_x + x, info.pos_y + y, dim.width, dim.height);
}
// DEBUG
//dumpLayoutInfo (layoutInfo);
//dumpLayoutInfo (info);
// Cache layout information.
layoutInfo = getLayoutInfo (parent, PREFERREDSIZE);
}
/**
File diff suppressed because it is too large Load Diff
@@ -38,9 +38,11 @@ exception statement from your version. */
package java.awt.datatransfer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
/**
* This class maps between native platform type names and DataFlavors.
@@ -54,10 +56,28 @@ import java.util.Map;
public final class SystemFlavorMap implements FlavorMap, FlavorTable
{
/**
* The default (instance) flavor map.
* The map which maps the thread's <code>ClassLoaders</code> to
* <code>SystemFlavorMaps</code>.
*/
private static FlavorMap defaultFlavorMap;
private static final Map systemFlavorMaps = new WeakHashMap();
/**
* Constant which is used to prefix encode Java MIME types.
*/
private static final String GNU_JAVA_MIME_PREFIX = "gnu.java:";
/**
* This map maps native <code>String</code>s to lists of
* <code>DataFlavor</code>s
*/
private HashMap nativeToFlavorMap = new HashMap();
/**
* This map maps <code>DataFlavor</code>s to lists of native
* <code>String</code>s
*/
private HashMap flavorToNativeMap = new HashMap();
/**
* Private constructor.
*/
@@ -98,47 +118,118 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
}
/**
* Returns the default (instance) (System)FlavorMap.
* Returns the (System)FlavorMap for the current thread's
* ClassLoader.
*/
public static FlavorMap getDefaultFlavorMap ()
{
if (defaultFlavorMap == null)
defaultFlavorMap = new SystemFlavorMap ();
return defaultFlavorMap;
ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
//if ContextClassLoader not set, use system default
if (classLoader == null)
{
classLoader = ClassLoader.getSystemClassLoader();
}
synchronized(systemFlavorMaps)
{
FlavorMap map = (FlavorMap)
systemFlavorMaps.get(classLoader);
if (map == null)
{
map = new SystemFlavorMap();
systemFlavorMaps.put(classLoader, map);
}
return map;
}
}
/**
* Returns the native type name for the given java mime type.
* Encodes a MIME type for use as a <code>String</code> native. The format
* of an encoded representation of a MIME type is implementation-dependent.
* The only restrictions are:
* <ul>
* <li>The encoded representation is <code>null</code> if and only if the
* MIME type <code>String</code> is <code>null</code>.</li>
* <li>The encoded representations for two non-<code>null</code> MIME type
* <code>String</code>s are equal if and only if these <code>String</code>s
* are equal according to <code>String.equals(Object)</code>.</li>
* </ul>
* <p>
* The present implementation of this method returns the specified MIME
* type <code>String</code> prefixed with <code>gnu.java:</code>.
*
* @param mime the MIME type to encode
* @return the encoded <code>String</code>, or <code>null</code> if
* mimeType is <code>null</code>
*/
public static String encodeJavaMIMEType (String mime)
{
return null;
if (mime != null)
return GNU_JAVA_MIME_PREFIX + mime;
else
return null;
}
/**
* Returns the native type name for the given data flavor.
* Encodes a <code>DataFlavor</code> for use as a <code>String</code>
* native. The format of an encoded <code>DataFlavor</code> is
* implementation-dependent. The only restrictions are:
* <ul>
* <li>The encoded representation is <code>null</code> if and only if the
* specified <code>DataFlavor</code> is <code>null</code> or its MIME type
* <code>String</code> is <code>null</code>.</li>
* <li>The encoded representations for two non-<code>null</code>
* <code>DataFlavor</code>s with non-<code>null</code> MIME type
* <code>String</code>s are equal if and only if the MIME type
* <code>String</code>s of these <code>DataFlavor</code>s are equal
* according to <code>String.equals(Object)</code>.</li>
* </ul>
* <p>
* The present implementation of this method returns the MIME type
* <code>String</code> of the specified <code>DataFlavor</code> prefixed
* with <code>gnu.java:</code>.
*
* @param df the <code>DataFlavor</code> to encode
* @return the encoded <code>String</code>, or <code>null</code> if
* flav is <code>null</code> or has a <code>null</code> MIME type
*/
public static String encodeDataFlavor (DataFlavor df)
{
return null;
if (df != null)
{
return encodeJavaMIMEType(df.getMimeType());
}
else
return null;
}
/**
* Returns true if the native type name can be represented as
* a java mime type.
* a java mime type. Returns <code>false</code> if parameter is
* <code>null</code>.
*/
public static boolean isJavaMIMEType (String name)
{
return false;
return (name != null && name.startsWith(GNU_JAVA_MIME_PREFIX));
}
/**
* Returns the java mime type for the given the native type name.
* Decodes a <code>String</code> native for use as a Java MIME type.
*
* @param name the <code>String</code> to decode
* @return the decoded Java MIME type, or <code>null</code> if nat
* is not an encoded <code>String</code> native
*/
public static String decodeJavaMIMEType (String name)
{
return null;
if (isJavaMIMEType(name))
{
return name.substring(GNU_JAVA_MIME_PREFIX.length());
}
else
return null;
}
/**
@@ -156,6 +247,20 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
return null;
}
/**
* Returns a List of <code>DataFlavors</code> to which the specified
* <code>String</code> native can be translated by the data transfer
* subsystem. The <code>List</code> will be sorted from best
* <code>DataFlavor</code> to worst. That is, the first <code>DataFlavor
* </code> will best reflect data in the specified native to a Java
* application.
* <p>
* If the specified native is previously unknown to the data transfer
* subsystem, and that native has been properly encoded, then invoking
* this method will establish a mapping in both directions between the
* specified native and a DataFlavor whose MIME type is a decoded
* version of the native.
*/
public List getFlavorsForNative (String nat)
{
throw new Error ("Not implemented");
@@ -165,5 +270,160 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable
{
throw new Error ("Not implemented");
}
/**
* Adds a mapping from a single <code>String</code> native to a single
* <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the
* mapping will only be established in one direction, and the native will
* not be encoded. To establish a two-way mapping, call
* <code>addUnencodedNativeForFlavor</code> as well. The new mapping will
* be of lower priority than any existing mapping.
* This method has no effect if a mapping from the specified
* <code>String</code> native to the specified or equal
* <code>DataFlavor</code> already exists.
*
* @param nativeStr the <code>String</code> native key for the mapping
* @param flavor the <code>DataFlavor</code> value for the mapping
* @throws NullPointerException if nat or flav is <code>null</code>
*
* @see #addUnencodedNativeForFlavor
* @since 1.4
*/
public synchronized void addFlavorForUnencodedNative(String nativeStr,
DataFlavor flavor)
{
if ((nativeStr == null) || (flavor == null))
throw new NullPointerException();
List flavors = (List) nativeToFlavorMap.get(nativeStr);
if (flavors == null)
{
flavors = new ArrayList();
nativeToFlavorMap.put(nativeStr, flavors);
}
else
{
if (! flavors.contains(flavor))
flavors.add(flavor);
}
}
/**
* Adds a mapping from the specified <code>DataFlavor</code> (and all
* <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>)
* to the specified <code>String</code> native.
* Unlike <code>getNativesForFlavor</code>, the mapping will only be
* established in one direction, and the native will not be encoded. To
* establish a two-way mapping, call
* <code>addFlavorForUnencodedNative</code> as well. The new mapping will
* be of lower priority than any existing mapping.
* This method has no effect if a mapping from the specified or equal
* <code>DataFlavor</code> to the specified <code>String</code> native
* already exists.
*
* @param flavor the <code>DataFlavor</code> key for the mapping
* @param nativeStr the <code>String</code> native value for the mapping
* @throws NullPointerException if flav or nat is <code>null</code>
*
* @see #addFlavorForUnencodedNative
* @since 1.4
*/
public synchronized void addUnencodedNativeForFlavor(DataFlavor flavor,
String nativeStr)
{
if ((nativeStr == null) || (flavor == null))
throw new NullPointerException();
List natives = (List) flavorToNativeMap.get(flavor);
if (natives == null)
{
natives = new ArrayList();
flavorToNativeMap.put(flavor, natives);
}
else
{
if (! natives.contains(nativeStr))
natives.add(nativeStr);
}
}
/**
* Discards the current mappings for the specified <code>DataFlavor</code>
* and all <code>DataFlavor</code>s equal to the specified
* <code>DataFlavor</code>, and creates new mappings to the
* specified <code>String</code> natives.
* Unlike <code>getNativesForFlavor</code>, the mappings will only be
* established in one direction, and the natives will not be encoded. To
* establish two-way mappings, call <code>setFlavorsForNative</code>
* as well. The first native in the array will represent the highest
* priority mapping. Subsequent natives will represent mappings of
* decreasing priority.
* <p>
* If the array contains several elements that reference equal
* <code>String</code> natives, this method will establish new mappings
* for the first of those elements and ignore the rest of them.
* <p>
* It is recommended that client code not reset mappings established by the
* data transfer subsystem. This method should only be used for
* application-level mappings.
*
* @param flavor the <code>DataFlavor</code> key for the mappings
* @param natives the <code>String</code> native values for the mappings
* @throws NullPointerException if flav or natives is <code>null</code>
* or if natives contains <code>null</code> elements
*
* @see #setFlavorsForNative
* @since 1.4
*/
public synchronized void setNativesForFlavor(DataFlavor flavor,
String[] natives)
{
if ((natives == null) || (flavor == null))
throw new NullPointerException();
flavorToNativeMap.remove(flavor);
for (int i = 0; i < natives.length; i++)
{
addUnencodedNativeForFlavor(flavor, natives[i]);
}
}
/**
* Discards the current mappings for the specified <code>String</code>
* native, and creates new mappings to the specified
* <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the
* mappings will only be established in one direction, and the natives need
* not be encoded. To establish two-way mappings, call
* <code>setNativesForFlavor</code> as well. The first
* <code>DataFlavor</code> in the array will represent the highest priority
* mapping. Subsequent <code>DataFlavor</code>s will represent mappings of
* decreasing priority.
* <p>
* If the array contains several elements that reference equal
* <code>DataFlavor</code>s, this method will establish new mappings
* for the first of those elements and ignore the rest of them.
* <p>
* It is recommended that client code not reset mappings established by the
* data transfer subsystem. This method should only be used for
* application-level mappings.
*
* @param nativeStr the <code>String</code> native key for the mappings
* @param flavors the <code>DataFlavor</code> values for the mappings
* @throws NullPointerException if nat or flavors is <code>null</code>
* or if flavors contains <code>null</code> elements
*
* @see #setNativesForFlavor
* @since 1.4
*/
public synchronized void setFlavorsForNative(String nativeStr,
DataFlavor[] flavors)
{
if ((nativeStr == null) || (flavors == null))
throw new NullPointerException();
nativeToFlavorMap.remove(nativeStr);
for (int i = 0; i < flavors.length; i++)
{
addFlavorForUnencodedNative(nativeStr, flavors[i]);
}
}
} // class SystemFlavorMap
@@ -0,0 +1,194 @@
/* DefaultPersistenceDelegate.java
Copyright (C) 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.beans;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/** <p><code>DefaultPersistenceDelegate</code> is a {@link PersistenceDelegate}
* implementation that can be used to serialize objects which adhere to the
* Java Beans naming convention.</p>
*
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public class DefaultPersistenceDelegate extends PersistenceDelegate
{
private String[] constructorPropertyNames;
/** Using this constructor the object to be serialized will be instantiated
* with the default non-argument constructor.
*/
public DefaultPersistenceDelegate()
{
}
/** This constructor allows to specify which Bean properties appear
* in the constructor.
*
* <p>The implementation reads the mentioned properties from the Bean
* instance and applies it in the given order to a corresponding
* constructor.</p>
*
* @param constructorPropertyNames The properties the Bean's constructor
* should be given to.
*/
public DefaultPersistenceDelegate(String[] constructorPropertyNames)
{
this.constructorPropertyNames = constructorPropertyNames;
}
protected boolean mutatesTo(Object oldInstance, Object newInstance)
{
try
{
return (constructorPropertyNames != null
&& constructorPropertyNames.length > 0
&& oldInstance.getClass()
.getDeclaredMethod("equals",
new Class[] { Object.class }) != null)
? oldInstance.equals(newInstance)
: super.mutatesTo(oldInstance, newInstance);
}
catch (NoSuchMethodException nsme)
{
return super.mutatesTo(oldInstance, newInstance);
}
}
protected Expression instantiate(Object oldInstance, Encoder out)
{
Object[] args = null;
try
{
// If there are property names in the array, then we create
// a corresponding argument array and store every
// argument in it. To retrieve an argument object we have
// dig up the right property in the bean class' BeanInfo
// object.
// This is so costly in terms of execution time I better
// not think twice about it ...
if (constructorPropertyNames != null)
{
args = new Object[constructorPropertyNames.length];
// Look up the properties of oldInstance's class to find matches for
// the
// names given in the constructor.
PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
oldInstance.getClass()).getPropertyDescriptors();
for (int i = 0; i < constructorPropertyNames.length; i++)
{
// Scan the property descriptions for a matching name.
for (int j = 0; j < propertyDescs.length; j++)
{
if (propertyDescs[i].getName().equals(
constructorPropertyNames[i]))
{
Method readMethod = propertyDescs[i].getReadMethod();
args[i] = readMethod.invoke(oldInstance, null);
}
}
}
}
}
catch (IllegalAccessException iae)
{
out.getExceptionListener().exceptionThrown(iae);
}
catch (IllegalArgumentException iarge)
{
out.getExceptionListener().exceptionThrown(iarge);
}
catch (InvocationTargetException ite)
{
out.getExceptionListener().exceptionThrown(ite);
}
catch (IntrospectionException ie)
{
out.getExceptionListener().exceptionThrown(ie);
}
return new Expression(oldInstance, oldInstance.getClass(), "new", args);
}
protected void initialize(Class type, Object oldInstance, Object newInstance,
Encoder out)
{
try
{
PropertyDescriptor[] propertyDescs = Introspector.getBeanInfo(
oldInstance.getClass()).getPropertyDescriptors();
for (int i = 0; i < propertyDescs.length; i++)
{
Method readMethod = propertyDescs[i].getReadMethod();
Method writeMethod = propertyDescs[i].getWriteMethod();
if (readMethod != null && writeMethod != null)
{
Object oldValue = readMethod.invoke(oldInstance, null);
if (oldValue != null)
out.writeStatement(new Statement(oldInstance,
writeMethod.getName(),
new Object[] { oldValue }));
}
}
}
catch (IntrospectionException ie)
{
out.getExceptionListener().exceptionThrown(ie);
}
catch (IllegalAccessException iae)
{
out.getExceptionListener().exceptionThrown(iae);
}
catch (InvocationTargetException ite)
{
out.getExceptionListener().exceptionThrown(ite);
}
}
}
+463
View File
@@ -0,0 +1,463 @@
/* Encoder.java
Copyright (C) 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.beans;
import gnu.java.beans.encoder.ArrayPersistenceDelegate;
import gnu.java.beans.encoder.ClassPersistenceDelegate;
import gnu.java.beans.encoder.CollectionPersistenceDelegate;
import gnu.java.beans.encoder.MapPersistenceDelegate;
import gnu.java.beans.encoder.PrimitivePersistenceDelegate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;
/**
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public class Encoder
{
/**
* An internal DefaultPersistenceDelegate instance that is used for every
* class that does not a have a special special PersistenceDelegate.
*/
private static PersistenceDelegate defaultPersistenceDelegate;
private static PersistenceDelegate fakePersistenceDelegate;
/**
* Stores the relation Class->PersistenceDelegate.
*/
private static HashMap delegates = new HashMap();
/**
* Stores the relation oldInstance->newInstance
*/
private IdentityHashMap candidates = new IdentityHashMap();
private ExceptionListener exceptionListener;
/**
* A simple number that is used to restrict the access to writeExpression and
* writeStatement. The rule is that both methods should only be used when an
* object is written to the stream (= writeObject). Therefore accessCounter is
* incremented just before the call to writeObject and decremented afterwards.
* Then writeStatement and writeExpression allow execution only if
* accessCounter is bigger than zero.
*/
private int accessCounter = 0;
public Encoder()
{
setupDefaultPersistenceDelegates();
setExceptionListener(null);
}
/**
* Sets up a bunch of {@link PersistenceDelegate} instances which are needed
* for the basic working of a {@link Encoder}s.
*/
private static void setupDefaultPersistenceDelegates()
{
synchronized (delegates)
{
if (defaultPersistenceDelegate != null)
return;
delegates.put(Class.class, new ClassPersistenceDelegate());
PersistenceDelegate pd = new PrimitivePersistenceDelegate();
delegates.put(Boolean.class, pd);
delegates.put(Byte.class, pd);
delegates.put(Short.class, pd);
delegates.put(Integer.class, pd);
delegates.put(Long.class, pd);
delegates.put(Float.class, pd);
delegates.put(Double.class, pd);
delegates.put(Object[].class, new ArrayPersistenceDelegate());
pd = new CollectionPersistenceDelegate();
delegates.put(ArrayList.class, pd);
delegates.put(LinkedList.class, pd);
delegates.put(Vector.class, pd);
delegates.put(HashSet.class, pd);
delegates.put(LinkedHashSet.class, pd);
delegates.put(TreeSet.class, pd);
pd = new MapPersistenceDelegate();
delegates.put(HashMap.class, pd);
delegates.put(TreeMap.class, pd);
delegates.put(java.util.Hashtable.class, pd);
delegates.put(java.util.IdentityHashMap.class, pd);
delegates.put(java.util.LinkedHashMap.class, pd);
delegates.put(java.util.Properties.class, pd);
delegates.put(java.awt.RenderingHints.class, pd);
delegates.put(java.util.WeakHashMap.class, pd);
delegates.put(javax.swing.UIDefaults.class, pd);
// TODO: These classes need to be implemented first
//delegates.put(java.security.AuthProvider.class, pd);
//delegates.put(java.util.concurrent.ConcurrentHashMap.class, pd);
//delegates.put(java.util.EnumMap.class, pd);
//delegates.put(javax.management.openmbean.TabularDataSupport.class, pd);
defaultPersistenceDelegate = new DefaultPersistenceDelegate();
delegates.put(Object.class, defaultPersistenceDelegate);
// Creates a PersistenceDelegate implementation which is
// returned for 'null'. In practice this instance is
// not used in any way and is just here to be compatible
// with the reference implementation which returns a
// similar instance when calling getPersistenceDelegate(null) .
fakePersistenceDelegate = new PersistenceDelegate()
{
protected Expression instantiate(Object o, Encoder e)
{
return null;
}
};
}
}
protected void writeObject(Object o)
{
// 'null' has no PersistenceDelegate and will not
// create an Expression which has to be cloned.
// However subclasses should be aware that writeObject
// may be called with a 'null' argument and should
// write the proper representation of it.
if (o == null)
return;
PersistenceDelegate pd = getPersistenceDelegate(o.getClass());
accessCounter++;
pd.writeObject(o, this);
accessCounter--;
}
/**
* Sets the {@link ExceptionListener} instance to be used for reporting
* recorable exceptions in the instantiation and initialization sequence. If
* the argument is <code>null</code> a default instance will be used that
* prints the thrown exception to <code>System.err</code>.
*/
public void setExceptionListener(ExceptionListener listener)
{
exceptionListener = (listener != null) ? listener : new ExceptionListener()
{
public void exceptionThrown(Exception e)
{
System.err.println("exception thrown: " + e);
e.printStackTrace();
}
};
}
/**
* Returns the currently active {@link ExceptionListener} instance.
*/
public ExceptionListener getExceptionListener()
{
return exceptionListener;
}
public PersistenceDelegate getPersistenceDelegate(Class type)
{
// This is not specified but the JDK behaves like this.
if (type == null)
return fakePersistenceDelegate;
// Treats all array classes in the same way and assigns
// them a shared PersistenceDelegate implementation tailored
// for array instantation and initialization.
if (type.isArray())
return (PersistenceDelegate) delegates.get(Object[].class);
PersistenceDelegate pd = (PersistenceDelegate) delegates.get(type);
return (pd != null) ? pd : (PersistenceDelegate) defaultPersistenceDelegate;
}
/**
* Sets the {@link PersistenceDelegate} instance for the given class.
* <p>
* Note: Throws a <code>NullPointerException</code> if the argument is
* <code>null</code>.
* </p>
* <p>
* Note: Silently ignores PersistenceDelegates for Array types and primitive
* wrapper classes.
* </p>
* <p>
* Note: Although this method is not declared <code>static</code> changes to
* the {@link PersistenceDelegate}s affect <strong>all</strong>
* {@link Encoder} instances. <strong>In this implementation</strong> the
* access is thread safe.
* </p>
*/
public void setPersistenceDelegate(Class type, PersistenceDelegate delegate)
{
// If the argument is null this will cause a NullPointerException
// which is expected behavior.
// This makes custom PDs for array, primitive types and their wrappers
// impossible but this is how the JDK behaves.
if (type.isArray() || type.isPrimitive() || type == Boolean.class
|| type == Byte.class || type == Short.class || type == Integer.class
|| type == Long.class || type == Float.class || type == Double.class)
return;
synchronized (delegates)
{
delegates.put(type, delegate);
}
}
public Object remove(Object oldInstance)
{
return candidates.remove(oldInstance);
}
/**
* Returns the replacement object which has been created by the encoder during
* the instantiation sequence or <code>null</code> if the object has not
* been processed yet.
* <p>
* Note: The <code>String</code> class acts as an endpoint for the
* inherently recursive algorithm of the {@link Encoder}. Therefore instances
* of <code>String</code> will always be returned by this method. In other
* words the assertion: <code>
* assert (anyEncoder.get(anyString) == anyString)
* </code<
* will always hold.</p>
*
* <p>Note: If <code>null</code> is requested, the result will
* always be <code>null</code>.</p>
*/
public Object get(Object oldInstance)
{
// String instances are handled in a special way.
// No one knows why this is not officially specified
// because this is a rather important design decision.
return (oldInstance == null) ? null :
(oldInstance.getClass() == String.class) ?
oldInstance : candidates.get(oldInstance);
}
/**
* <p>
* Note: If you call this method not from within an object instantiation and
* initialization sequence it will be silently ignored.
* </p>
*/
public void writeStatement(Statement stmt)
{
// Silently ignore out of bounds calls.
if (accessCounter <= 0)
return;
Object target = stmt.getTarget();
Object newTarget = get(target);
if (newTarget == null)
{
writeObject(target);
newTarget = get(target);
}
Object[] args = stmt.getArguments();
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++)
{
newArgs[i] = get(args[i]);
if (newArgs[i] == null || isImmutableType(args[i].getClass()))
{
writeObject(args[i]);
newArgs[i] = get(args[i]);
}
}
Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
try
{
newStmt.execute();
}
catch (Exception e)
{
exceptionListener.exceptionThrown(e);
}
}
/**
* <p>
* Note: If you call this method not from within an object instantiation and
* initialization sequence it will be silently ignored.
* </p>
*/
public void writeExpression(Expression expr)
{
// Silently ignore out of bounds calls.
if (accessCounter <= 0)
return;
Object target = expr.getTarget();
Object value = null;
Object newValue = null;
try
{
value = expr.getValue();
}
catch (Exception e)
{
exceptionListener.exceptionThrown(e);
return;
}
newValue = get(value);
if (newValue == null)
{
Object newTarget = get(target);
if (newTarget == null)
{
writeObject(target);
newTarget = get(target);
// May happen if exception was thrown.
if (newTarget == null)
{
return;
}
}
Object[] args = expr.getArguments();
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++)
{
newArgs[i] = get(args[i]);
if (newArgs[i] == null || isImmutableType(args[i].getClass()))
{
writeObject(args[i]);
newArgs[i] = get(args[i]);
}
}
Expression newExpr = new Expression(newTarget, expr.getMethodName(),
newArgs);
// Fakes the result of Class.forName(<primitiveType>) to make it possible
// to hand such a type to the encoding process.
if (value instanceof Class && ((Class) value).isPrimitive())
newExpr.setValue(value);
// Instantiates the new object.
try
{
newValue = newExpr.getValue();
candidates.put(value, newValue);
}
catch (Exception e)
{
exceptionListener.exceptionThrown(e);
return;
}
writeObject(value);
}
else if(value.getClass() == String.class || value.getClass() == Class.class)
{
writeObject(value);
}
}
/** Returns whether the given class is an immutable
* type which has to be handled differently when serializing it.
*
* <p>Immutable objects always have to be instantiated instead of
* modifying an existing instance.</p>
*
* @param type The class to test.
* @return Whether the first argument is an immutable type.
*/
boolean isImmutableType(Class type)
{
return type == String.class || type == Class.class
|| type == Integer.class || type == Boolean.class
|| type == Byte.class || type == Short.class
|| type == Long.class || type == Float.class
|| type == Double.class;
}
/** Sets the stream candidate for a given object.
*
* @param oldObject The object given to the encoder.
* @param newObject The object the encoder generated.
*/
void putCandidate(Object oldObject, Object newObject)
{
candidates.put(oldObject, newObject);
}
}
File diff suppressed because it is too large Load Diff
+43 -38
View File
@@ -35,16 +35,19 @@ 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.beans;
/**
* class Expression
*
* An Expression captures the execution of an object method that
* returns a value. It stores an object, the method to call, and the
* arguments to pass to the method.
*
* <p>An Expression captures the execution of an object method
* that returns a value.</p>
*
* <p>It stores an object, the method to call, and the arguments to pass to
* the method.</p>
*
* <p>While this class can generally be used to describe method calls it is
* part of the XML serialization API.</p>
*
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public class Expression extends Statement
@@ -53,38 +56,40 @@ public class Expression extends Statement
// yet;
private static final Object UNSET = new Object();
// The value to return. This is equal to unset until getValue is called.
// The value to return. This is equal to unset until getValue is called.
private Object value;
/**
* Constructor
*
* Constructs an Expression representing the invocation of
* object.methodName(arg[0], arg[1], ...); However, it will never
* be executed. Instead, value will always be returned.
*
* @param value The value to return.
* @param target The object to invoke the method on.
* @param methodName The object method to invoke.
* @param arguments An array of arguments to pass to the method.
* Constructor Constructs an Expression representing the invocation of
* object.methodName(arg[0], arg[1], ...); However, it will never be executed.
* Instead, value will always be returned.
*
* @param value
* The value to return.
* @param target
* The object to invoke the method on.
* @param methodName
* The object method to invoke.
* @param arguments
* An array of arguments to pass to the method.
*/
public Expression(Object value, Object target, String methodName,
Object[] arguments)
Object[] arguments)
{
super(target, methodName, arguments);
this.value = value;
}
/**
* Constructor
*
* Constructs an Expression representing the invocation of
* Constructor Constructs an Expression representing the invocation of
* object.methodName(arg[0], arg[1], ...);
*
* @param target The object to invoke the method on.
* @param methodName The object method to invoke.
* @param arguments An array of arguments to pass to the method.
*
* @param target
* The object to invoke the method on.
* @param methodName
* The object method to invoke.
* @param arguments
* An array of arguments to pass to the method.
*/
public Expression(Object target, String methodName, Object[] arguments)
{
@@ -93,15 +98,14 @@ public class Expression extends Statement
}
/**
* Return the result of executing the method.
*
* If the cached value has not yet been set, the method is
* executed in the same way as Statement.execute(), except that
* the value is cached, and then returned. If the value has been
* Return the result of executing the method. If the cached value has not yet
* been set, the method is executed in the same way as Statement.execute(),
* except that the value is cached, and then returned. If the value has been
* set, it is returned without executing the method again.
*
*
* @return the result of executing the method.
* @exception Exception if an error occurs
* @exception Exception
* if an error occurs
*/
public Object getValue() throws Exception
{
@@ -112,14 +116,15 @@ public class Expression extends Statement
/**
* Set the cached value to be returned by getValue()
*
* @param value the value to cache and return.
*
* @param value
* the value to cache and return.
*/
public void setValue(Object value)
{
this.value = value;
}
/**
* Return a string representation of this expression.
*/
@@ -127,7 +132,7 @@ public class Expression extends Statement
{
String result = super.toString();
if (value != UNSET)
return value.getClass().getName() + " " + result;
return value.getClass().getName() + "=" + result;
return result;
}
}
@@ -0,0 +1,81 @@
/* Indexed property change event
Copyright (C) 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.beans;
/**
* This is like a PropertyChangeEvent, but also carries with it the
* index of the property which changed.
* @author Tom Tromey (tromey@redhat.com)
* @since 1.5
*/
public class IndexedPropertyChangeEvent extends PropertyChangeEvent
{
private static final long serialVersionUID = -320227448495806870L;
/**
* Index of the item that was changed.
*/
private int index;
/**
* Create a new IndexedPropertyChangeEvent.
* @param source the Bean containing the property
* @param name the property's name
* @param oldValue the old value of the property
* @param newValue the new value of the property
* @param index the index of the element in the property which changed
* @throws IllegalArgumentException if source is null
*/
public IndexedPropertyChangeEvent(Object source, String name,
Object oldValue, Object newValue,
int index)
{
super(source, name, oldValue, newValue);
this.index = index;
}
/**
* Return the index of the changed property.
* @return the index
*/
public int getIndex()
{
return index;
}
}
+150 -54
View File
@@ -211,6 +211,82 @@ public class Introspector {
return cachedInfo;
}
}
/**
* Returns a {@BeanInfo} instance for the given Bean class where a flag
* controls the usage of explicit BeanInfo class to retrieve that
* information.
*
* <p>You have three options:</p>
* <p>With {@link #USE_ALL_BEANINFO} the result is the same as
* {@link #getBeanInfo(Class)}.</p>
*
* <p>Calling the method with <code>flag</code> set to
* {@link #IGNORE_IMMEDIATE_BEANINFO} will let it use all
* explicit BeanInfo classes for the beans superclasses
* but not for the bean class itself. Furthermore eventset,
* property and method information is retrieved by introspection
* if the explicit <code>BeanInfos</code> did not provide such data
* (ie. return <code>null</code> on {@link BeanInfo.getMethodDescriptors},
* {@link BeanInfo.getEventSetDescriptors} and
* {@link BeanInfo.getPropertyDescriptors}.)
* </p>
*
* <p>When the method is called with <code>flag</code< set to
* {@link #IGNORE_ALL_BEANINFO} all the bean data is retrieved
* by inspecting the class.</p>
*
* <p>Note: Any unknown value for <code>flag</code> is interpreted
* as {@link #IGNORE_ALL_BEANINFO}</p>.
*
* @param beanClass The class whose BeanInfo should be returned.
* @param flag Controls the usage of explicit <code>BeanInfo</code> classes.
* @return A BeanInfo object describing the class.
* @throws IntrospectionException If something goes wrong while retrieving
* the bean data.
*/
public static BeanInfo getBeanInfo(Class beanClass, int flag)
throws IntrospectionException
{
IntrospectionIncubator ii;
BeanInfoEmbryo infoEmbryo;
switch(flag)
{
case USE_ALL_BEANINFO:
return getBeanInfo(beanClass);
case IGNORE_IMMEDIATE_BEANINFO:
Class superclass = beanClass.getSuperclass();
ExplicitInfo explicit = new ExplicitInfo(superclass, null);
ii = new IntrospectionIncubator();
if (explicit.explicitEventSetDescriptors != null)
ii.setEventStopClass(superclass);
if (explicit.explicitMethodDescriptors != null)
ii.setMethodStopClass(superclass);
if (explicit.explicitPropertyDescriptors != null)
ii.setPropertyStopClass(superclass);
ii.addMethods(beanClass.getMethods());
infoEmbryo = ii.getBeanInfoEmbryo();
merge(infoEmbryo, explicit);
infoEmbryo.setBeanDescriptor(new BeanDescriptor(beanClass, null));
return infoEmbryo.getBeanInfo();
case IGNORE_ALL_BEANINFO:
default:
ii = new IntrospectionIncubator();
ii.addMethods(beanClass.getMethods());
infoEmbryo = ii.getBeanInfoEmbryo();
infoEmbryo.setBeanDescriptor(new BeanDescriptor(beanClass, null));
return infoEmbryo.getBeanInfo();
}
}
/**
* Flush all of the Introspector's internal caches.
@@ -244,6 +320,69 @@ public class Introspector {
}
}
/** Adds all explicity given bean info data to the introspected
* data.
*
* @param infoEmbryo Bean info data retrieved by introspection.
* @param explicit Bean info data retrieved by BeanInfo classes.
*/
private static void merge(BeanInfoEmbryo infoEmbryo, ExplicitInfo explicit)
{
PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
if(p!=null)
{
for(int i=0;i<p.length;i++)
{
if(!infoEmbryo.hasProperty(p[i]))
{
infoEmbryo.addProperty(p[i]);
}
}
// -1 should be used to denote a missing default property but
// for robustness reasons any value below zero is discarded.
// Not doing so would let Classpath fail where the JDK succeeds.
if(explicit.defaultProperty > -1)
{
infoEmbryo.setDefaultPropertyName(p[explicit.defaultProperty].getName());
}
}
EventSetDescriptor[] e = explicit.explicitEventSetDescriptors;
if(e!=null)
{
for(int i=0;i<e.length;i++)
{
if(!infoEmbryo.hasEvent(e[i]))
{
infoEmbryo.addEvent(e[i]);
}
}
// -1 should be used to denote a missing default event but
// for robustness reasons any value below zero is discarded.
// Not doing so would let Classpath fail where the JDK succeeds.
if(explicit.defaultEvent > -1)
{
infoEmbryo.setDefaultEventName(e[explicit.defaultEvent].getName());
}
}
MethodDescriptor[] m = explicit.explicitMethodDescriptors;
if(m!=null)
{
for(int i=0;i<m.length;i++)
{
if(!infoEmbryo.hasMethod(m[i]))
{
infoEmbryo.addMethod(m[i]);
}
}
}
infoEmbryo.setAdditionalBeanInfo(explicit.explicitBeanInfo);
infoEmbryo.setIcons(explicit.im);
}
/**
* Get the BeanInfo for class <CODE>beanClass</CODE>,
* first by looking for explicit information, next by
@@ -267,62 +406,19 @@ public class Introspector {
ii.addMethods(beanClass.getMethods());
BeanInfoEmbryo currentInfo = ii.getBeanInfoEmbryo();
PropertyDescriptor[] p = explicit.explicitPropertyDescriptors;
if(p!=null)
{
for(int i=0;i<p.length;i++)
{
if(!currentInfo.hasProperty(p[i]))
{
currentInfo.addProperty(p[i]);
}
}
if(explicit.defaultProperty != -1)
{
currentInfo.setDefaultPropertyName(p[explicit.defaultProperty].getName());
}
}
EventSetDescriptor[] e = explicit.explicitEventSetDescriptors;
if(e!=null)
{
for(int i=0;i<e.length;i++)
{
if(!currentInfo.hasEvent(e[i]))
{
currentInfo.addEvent(e[i]);
}
}
if(explicit.defaultEvent != -1)
{
currentInfo.setDefaultEventName(e[explicit.defaultEvent].getName());
}
}
MethodDescriptor[] m = explicit.explicitMethodDescriptors;
if(m!=null)
{
for(int i=0;i<m.length;i++)
{
if(!currentInfo.hasMethod(m[i]))
{
currentInfo.addMethod(m[i]);
}
}
}
// Sets the info's BeanDescriptor to the one we extracted from the
// explicit BeanInfo instance(s) if they contained one. Otherwise we
// create the BeanDescriptor from scratch.
// Note: We do not create a copy the retrieved BeanDescriptor which will allow
// the user to modify the instance while it is cached. However this is how
// the RI does it.
currentInfo.setBeanDescriptor(
(explicit.explicitBeanDescriptor == null ?
new BeanDescriptor(beanClass, null) :
explicit.explicitBeanDescriptor));
currentInfo.setAdditionalBeanInfo(explicit.explicitBeanInfo);
currentInfo.setIcons(explicit.im);
merge(currentInfo, explicit);
// Sets the info's BeanDescriptor to the one we extracted from the
// explicit BeanInfo instance(s) if they contained one. Otherwise we
// create the BeanDescriptor from scratch.
// Note: We do not create a copy the retrieved BeanDescriptor which will allow
// the user to modify the instance while it is cached. However this is how
// the RI does it.
currentInfo.setBeanDescriptor(
(explicit.explicitBeanDescriptor == null ?
new BeanDescriptor(beanClass, null) :
explicit.explicitBeanDescriptor));
return currentInfo.getBeanInfo();
}
@@ -0,0 +1,91 @@
/* java.beans.PersistenceDelegate
Copyright (C) 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.beans;
/** <p>A <code>PersistenceDelegate</code> describes how a another object
* has to constructed and transformed in order to create a complete
* replicate.</p>
*
* <p>For custom classes you will need to implement
* <code>PersistenceDelegate</code> in a way that is suitable for them.
* To make use of the implementation you have to register it with an
* {@link Encoder} using the {Encoder#setPersistenceDelegate} method.</p>
*
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public abstract class PersistenceDelegate
{
protected void initialize(Class type, Object oldInstance, Object newInstance,
Encoder out)
{
if (type != Object.class)
{
type = type.getSuperclass();
PersistenceDelegate pd = out.getPersistenceDelegate(
oldInstance.getClass().getSuperclass());
pd.initialize(type, oldInstance, newInstance, out);
}
}
public void writeObject(Object oldInstance, Encoder out)
{
Object streamCandidate = out.get(oldInstance);
if (mutatesTo(oldInstance, streamCandidate))
{
initialize(oldInstance.getClass(), oldInstance, streamCandidate, out);
}
else
{
out.remove(oldInstance);
out.writeExpression(instantiate(oldInstance, out));
}
}
protected boolean mutatesTo(Object oldInstance, Object newInstance)
{
return (newInstance != null)
&& oldInstance.getClass() == newInstance.getClass();
}
protected abstract Expression instantiate(Object oldInstance, Encoder out);
}
@@ -396,6 +396,58 @@ public class PropertyChangeSupport implements Serializable
}
}
/**
* Fire an indexed property change event. This will only fire
* an event if the old and new values are not equal and not null.
* @param name the name of the property which changed
* @param index the index of the property which changed
* @param oldValue the old value of the property
* @param newValue the new value of the property
* @since 1.5
*/
public void fireIndexedPropertyChange(String name, int index,
Object oldValue, Object newValue)
{
// Argument checking is done in firePropertyChange(PropertyChangeEvent) .
firePropertyChange(new IndexedPropertyChangeEvent(source, name,
oldValue, newValue,
index));
}
/**
* Fire an indexed property change event. This will only fire
* an event if the old and new values are not equal.
* @param name the name of the property which changed
* @param index the index of the property which changed
* @param oldValue the old value of the property
* @param newValue the new value of the property
* @since 1.5
*/
public void fireIndexedPropertyChange(String name, int index,
int oldValue, int newValue)
{
if (oldValue != newValue)
fireIndexedPropertyChange(name, index, Integer.valueOf(oldValue),
Integer.valueOf(newValue));
}
/**
* Fire an indexed property change event. This will only fire
* an event if the old and new values are not equal.
* @param name the name of the property which changed
* @param index the index of the property which changed
* @param oldValue the old value of the property
* @param newValue the new value of the property
* @since 1.5
*/
public void fireIndexedPropertyChange(String name, int index,
boolean oldValue, boolean newValue)
{
if (oldValue != newValue)
fireIndexedPropertyChange(name, index, Boolean.valueOf(oldValue),
Boolean.valueOf(newValue));
}
/**
* Tell whether the specified property is being listened on or not. This
* will only return <code>true</code> if there are listeners on all
+86 -79
View File
@@ -1,4 +1,4 @@
/* java.beans.Statement
/* Statement.java
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -42,32 +42,26 @@ import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.WeakHashMap;
/**
* class Statement
*
* A Statement captures the execution of an object method. It stores
* <p>A Statement captures the execution of an object method. It stores
* the object, the method to call, and the arguments to the method and
* provides the ability to execute the method on the object, using the
* provided arguments.
* provided arguments.</p>
*
* @author Jerry Quinn (jlquinn@optonline.net)
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public class Statement
{
/** Nested map for the relation between a class, its instances and their
* names.
*/
private static HashMap classMaps = new HashMap();
private Object target;
private String methodName;
private Object[] arguments;
// One or the other of these will get a value after execute is
// called once, but not both.
/**
* One or the other of these will get a value after execute is
* called once, but not both.
*/
private transient Method method;
private transient Constructor ctor;
@@ -87,76 +81,44 @@ public class Statement
this.target = target;
this.methodName = methodName;
this.arguments = (arguments != null) ? arguments : new Object[0];
storeTargetName(target);
}
/** Creates a name for the target instance or does nothing if the object's
* name is already known. This makes sure that there *is* a name for every
* target instance.
*/
private static synchronized void storeTargetName(Object obj)
{
Class klass = obj.getClass();
WeakHashMap names = (WeakHashMap) classMaps.get(klass);
if ( names == null )
{
names = new WeakHashMap();
names.put(obj,
( klass == String.class ? ("\"" + obj + "\"") :
(klass.getName() + names.size()) ));
classMaps.put(klass, names);
return;
}
String targetName = (String) names.get(obj);
if ( targetName == null )
{
names.put(obj,
( klass == String.class ? ("\"" + obj + "\"") :
(klass.getName() + names.size()) ));
}
// Nothing to do. The given object was already stored.
}
/**
* Execute the statement.
*
* Finds the specified method in the target object and calls it with
* the arguments given in the constructor.
* <p>Finds the specified method in the target object and calls it with
* the arguments given in the constructor.</p>
*
* The most specific method according to the JLS(15.11) is used when
* there are multiple methods with the same name.
* <p>The most specific method according to the JLS(15.11) is used when
* there are multiple methods with the same name.</p>
*
* Execute performs some special handling for methods and
* <p>Execute performs some special handling for methods and
* parameters:
* <ul>
* <li>Static methods can be executed by providing the class as a
* target.</li>
*
* Static methods can be executed by providing the class as a
* target.
*
* The method name new is reserved to call the constructor
* <li>The method name new is reserved to call the constructor
* new() will construct an object and return it. Not useful unless
* an expression :-)
* an expression :-)</li>
*
* If the target is an array, get and set as defined in
* <li>If the target is an array, get and set as defined in
* java.util.List are recognized as valid methods and mapped to the
* methods of the same name in java.lang.reflect.Array.
* methods of the same name in java.lang.reflect.Array.</li>
*
* The native datatype wrappers Boolean, Byte, Character, Double,
* <li>The native datatype wrappers Boolean, Byte, Character, Double,
* Float, Integer, Long, and Short will map to methods that have
* native datatypes as parameters, in the same way as Method.invoke.
* However, these wrappers also select methods that actually take
* the wrapper type as an argument.
* the wrapper type as an argument.</li>
* </ul>
* </p>
*
* The Sun spec doesn't deal with overloading between int and
* <p>The Sun spec doesn't deal with overloading between int and
* Integer carefully. If there are two methods, one that takes an
* Integer and the other taking an int, the method chosen is not
* specified, and can depend on the order in which the methods are
* declared in the source file.
* declared in the source file.</p>
*
* @throws Exception if an exception occurs while locating or
* invoking the method.
@@ -178,8 +140,10 @@ public class Statement
Integer.TYPE, Long.TYPE, Short.TYPE
};
// Given a wrapper class, return the native class for it. For
// example, if c is Integer, Integer.TYPE is returned.
/** Given a wrapper class, return the native class for it.
* <p>For example, if <code>c</code> is <code>Integer</code>,
* <code>Integer.TYPE</code> is returned.</p>
*/
private Class unwrap(Class c)
{
for (int i = 0; i < wrappers.length; i++)
@@ -188,13 +152,22 @@ public class Statement
return null;
}
// Return true if all args can be assigned to params, false
// otherwise. Arrays are guaranteed to be the same length.
/** Returns <code>true</code> if all args can be assigned to
* <code>params</code>, <code>false</code> otherwise.
*
* <p>Arrays are guaranteed to be the same length.</p>
*/
private boolean compatible(Class[] params, Class[] args)
{
for (int i = 0; i < params.length; i++)
{
// Treat Integer like int if appropriate
// Argument types are derived from argument values. If one of them was
// null then we cannot deduce its type. However null can be assigned to
// any type.
if (args[i] == null)
continue;
// Treat Integer like int if appropriate
Class nativeType = unwrap(args[i]);
if (nativeType != null && params[i].isPrimitive()
&& params[i].isAssignableFrom(nativeType))
@@ -208,14 +181,15 @@ public class Statement
}
/**
* Return true if the method arguments in first are more specific
* than the method arguments in second, i.e. all args in first can
* be assigned to those in second.
* Returns <code>true</code> if the method arguments in first are
* more specific than the method arguments in second, i.e. all
* arguments in <code>first</code> can be assigned to those in
* <code>second</code>.
*
* A method is more specific if all parameters can also be fed to
* <p>A method is more specific if all parameters can also be fed to
* the less specific method, because, e.g. the less specific method
* accepts a base class of the equivalent argument for the more
* specific one.
* specific one.</p>
*
* @param first a <code>Class[]</code> value
* @param second a <code>Class[]</code> value
@@ -238,8 +212,11 @@ public class Statement
? (Class) target : target.getClass();
Object args[] = (arguments == null) ? new Object[0] : arguments;
Class argTypes[] = new Class[args.length];
// Retrieve type or use null if the argument is null. The null argument
// type is later used in compatible().
for (int i = 0; i < args.length; i++)
argTypes[i] = args[i].getClass();
argTypes[i] = (args[i] != null) ? args[i].getClass() : null;
if (target.getClass().isArray())
{
@@ -333,7 +310,29 @@ public class Statement
}
if (method == null)
throw new NoSuchMethodException("No matching method for statement " + toString());
// If we were calling Class.forName(String) we intercept and call the
// forName-variant that allows a ClassLoader argument. We take the
// system classloader (aka application classloader) here to make sure
// that application defined classes can be resolved. If we would not
// do that the Class.forName implementation would use the class loader
// of java.beans.Statement which is <null> and cannot resolve application
// defined classes.
if (method.equals(
Class.class.getMethod("forName", new Class[] { String.class })))
return Class.forName(
(String) args[0], true, ClassLoader.getSystemClassLoader());
try {
return method.invoke(target, args);
} catch(IllegalArgumentException iae){
System.err.println("method: " + method);
for(int i=0;i<args.length;i++){
System.err.println("args[" + i + "]: " + args[i]);
}
throw iae;
}
}
@@ -352,9 +351,13 @@ public class Statement
{
StringBuffer result = new StringBuffer();
Class klass = target.getClass();
String targetName = target.getClass().getName();
if ( targetName.startsWith("java"))
{
targetName = targetName.substring(targetName.lastIndexOf('.') + 1);
}
result.append( ((WeakHashMap) classMaps.get(klass)).get(target));
result.append(targetName);
result.append(".");
result.append(methodName);
result.append("(");
@@ -363,11 +366,15 @@ public class Statement
for (int i = 0; i < arguments.length; i++)
{
result.append(sep);
result.append(arguments[i].getClass().getName());
result.append(
( arguments[i] == null ) ? "null" :
( arguments[i] instanceof String ) ? "\"" + arguments[i] + "\"" :
arguments[i].getClass().getName());
sep = ", ";
}
result.append(")");
return result.toString();
}
}
@@ -0,0 +1,265 @@
/* XMLEncoder.java
Copyright (C) 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.beans;
import gnu.java.beans.encoder.ScanEngine;
import java.io.OutputStream;
/**
* This class uses the {@link PersistenceDelegate} and {@link Encoder}
* infrastructure to generate an XML representation of the objects it
* serializes.
*
* @author Robert Schuster (robertschuster@fsfe.org)
* @since 1.4
*/
public class XMLEncoder extends Encoder
{
Object owner;
Exception exception;
ScanEngine scanEngine;
private int accessCounter = 0;
public XMLEncoder(OutputStream os)
{
scanEngine = new ScanEngine(os);
}
public void close()
{
if (scanEngine != null)
{
scanEngine.close();
scanEngine = null;
}
}
public void flush()
{
scanEngine.flush();
}
public void writeExpression(Expression expr)
{
// Implementation note: Why is this method overwritten and nearly exactly
// reimplemented as in Encoder?
// The Encoder class can (and should be) subclassed by users outside of the
// java.beans package. While I have doubts that this is possible from an
// API design point of view I tried to replicate the Encoder's behavior
// in the JDK as exactly as possible. This strictness however made it
// extremely complicated to implement the XMLEncoder's backend. Therefore
// I decided to copy the Encoder's implementation and make all changes
// I needed for a succesfull operation of XMLEncoder.
//
// The same is true for the writeStatement method.
// Silently ignore out of bounds calls.
if (accessCounter <= 0)
return;
scanEngine.writeExpression(expr);
Object target = expr.getTarget();
Object value = null;
Object newValue = null;
try
{
value = expr.getValue();
}
catch (Exception e)
{
getExceptionListener().exceptionThrown(e);
return;
}
newValue = get(value);
if (newValue == null)
{
Object newTarget = get(target);
if (newTarget == null)
{
writeObject(target);
newTarget = get(target);
// May happen if exception was thrown.
if (newTarget == null)
{
return;
}
}
Object[] args = expr.getArguments();
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++)
{
newArgs[i] = get(args[i]);
if (newArgs[i] == null || isImmutableType(args[i].getClass()))
{
writeObject(args[i]);
newArgs[i] = get(args[i]);
}
}
Expression newExpr = new Expression(newTarget, expr.getMethodName(),
newArgs);
// Fakes the result of Class.forName(<primitiveType>) to make it possible
// to hand such a type to the encoding process.
if (value instanceof Class && ((Class) value).isPrimitive())
newExpr.setValue(value);
// Instantiates the new object.
try
{
newValue = newExpr.getValue();
putCandidate(value, newValue);
}
catch (Exception e)
{
getExceptionListener().exceptionThrown(e);
// In Statement.writeExpression we had no possibility to flags
// an erroneous state to the ScanEngine without behaving different
// to the JDK.
scanEngine.revoke();
}
writeObject(value);
}
else if(value.getClass() == String.class || value.getClass() == Class.class)
{
writeObject(value);
}
scanEngine.end();
}
public void writeStatement(Statement stmt)
{
// In case of questions have a at the implementation note in
// writeExpression.
scanEngine.writeStatement(stmt);
// Silently ignore out of bounds calls.
if (accessCounter <= 0)
return;
Object target = stmt.getTarget();
Object newTarget = get(target);
if (newTarget == null)
{
writeObject(target);
newTarget = get(target);
}
Object[] args = stmt.getArguments();
Object[] newArgs = new Object[args.length];
for (int i = 0; i < args.length; i++)
{
// Here is the difference to the original writeStatement
// method in Encoder. In case that the object is known or
// not an immutable we put it directly into the ScanEngine
// which will then generate an object reference for it.
newArgs[i] = get(args[i]);
if (newArgs[i] == null || isImmutableType(args[i].getClass()))
{
writeObject(args[i]);
newArgs[i] = get(args[i]);
}
else
scanEngine.writeObject(args[i]);
}
Statement newStmt = new Statement(newTarget, stmt.getMethodName(), newArgs);
try
{
newStmt.execute();
}
catch (Exception e)
{
getExceptionListener().exceptionThrown(e);
// In Statement.writeStatement we had no possibility to flags
// an erroneous state to the ScanEngine without behaving different
// to the JDK.
scanEngine.revoke();
return;
}
scanEngine.end();
}
public void writeObject(Object o)
{
accessCounter++;
scanEngine.writeObject(o);
if (get(o) == null);
super.writeObject(o);
accessCounter--;
}
public void setOwner(Object o)
{
owner = o;
}
public Object getOwner()
{
return owner;
}
}
+7 -2
View File
@@ -396,7 +396,8 @@ public class File implements Serializable, Comparable
* This method initializes a new <code>File</code> object to represent
* a file corresponding to the specified <code>file:</code> protocol URI.
*
* @param uri The uri.
* @param uri The URI
* @throws IllegalArgumentException if the URI is not hierarchical
*/
public File(URI uri)
{
@@ -406,7 +407,11 @@ public class File implements Serializable, Comparable
if (!uri.getScheme().equals("file"))
throw new IllegalArgumentException("invalid uri protocol");
path = normalizePath(uri.getPath());
String name = uri.getPath();
if (name == null)
throw new IllegalArgumentException("URI \"" + uri
+ "\" is not hierarchical");
path = normalizePath(name);
}
/**
@@ -230,6 +230,8 @@ public class InputStreamReader extends Reader
* Creates an InputStreamReader that uses a decoder of the given
* charset to decode the bytes in the InputStream into
* characters.
*
* @since 1.5
*/
public InputStreamReader(InputStream in, Charset charset) {
this.in = in;
@@ -244,6 +246,8 @@ public class InputStreamReader extends Reader
/**
* Creates an InputStreamReader that uses the given charset decoder
* to decode the bytes in the InputStream into characters.
*
* @since 1.5
*/
public InputStreamReader(InputStream in, CharsetDecoder decoder) {
this.in = in;
@@ -50,7 +50,6 @@ import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.TreeSet;
@@ -442,6 +442,11 @@ public class ObjectOutputStream extends OutputStream
realOutput.writeByte(flags);
ObjectStreamField[] fields = osc.fields;
if (fields == ObjectStreamClass.INVALID_FIELDS)
throw new InvalidClassException
(osc.getName(), "serialPersistentFields is invalid");
realOutput.writeShort(fields.length);
ObjectStreamField field;
@@ -63,6 +63,8 @@ import java.util.Vector;
public class ObjectStreamClass implements Serializable
{
static final ObjectStreamField[] INVALID_FIELDS = new ObjectStreamField[0];
/**
* Returns the <code>ObjectStreamClass</code> for <code>cl</code>.
* If <code>cl</code> is null, or is not <code>Serializable</code>,
@@ -71,6 +73,11 @@ public class ObjectStreamClass implements Serializable
* same <code>ObjectStreamClass</code> object and no recalculation
* will be done.
*
* Warning: If this class contains an invalid serialPersistentField arrays
* lookup will not throw anything. However {@link #getFields()} will return
* an empty array and {@link java.io.ObjectOutputStream#writeObject} will throw an
* {@link java.io.InvalidClassException}.
*
* @see java.io.Serializable
*/
public static ObjectStreamClass lookup(Class cl)
@@ -148,6 +155,8 @@ public class ObjectStreamClass implements Serializable
* Returns the serializable (non-static and non-transient) Fields
* of the class represented by this ObjectStreamClass. The Fields
* are sorted by name.
* If fields were obtained using serialPersistentFields and this array
* is faulty then the returned array of this method will be empty.
*
* @return the fields.
*/
@@ -608,6 +617,28 @@ outer:
fields = getSerialPersistentFields(cl);
if (fields != null)
{
ObjectStreamField[] fieldsName = new ObjectStreamField[fields.length];
System.arraycopy(fields, 0, fieldsName, 0, fields.length);
Arrays.sort (fieldsName, new Comparator() {
public int compare(Object o1, Object o2)
{
ObjectStreamField f1 = (ObjectStreamField)o1;
ObjectStreamField f2 = (ObjectStreamField)o2;
return f1.getName().compareTo(f2.getName());
}
});
for (int i=1; i < fields.length; i++)
{
if (fieldsName[i-1].getName().equals(fieldsName[i].getName()))
{
fields = INVALID_FIELDS;
return;
}
}
Arrays.sort (fields);
// Retrieve field reference.
for (int i=0; i < fields.length; i++)
@@ -213,6 +213,8 @@ public class OutputStreamWriter extends Writer
*
* @param out The <code>OutputStream</code> to write to
* @param cs The <code>Charset</code> of the encoding to use
*
* @since 1.5
*/
public OutputStreamWriter(OutputStream out, Charset cs)
{
@@ -230,6 +232,8 @@ public class OutputStreamWriter extends Writer
*
* @param out The <code>OutputStream</code> to write to
* @param enc The <code>CharsetEncoder</code> to encode the output with
*
* @since 1.5
*/
public OutputStreamWriter(OutputStream out, CharsetEncoder enc)
{
+6 -3
View File
@@ -1,5 +1,6 @@
/* PrintStream.java -- OutputStream for printing output
Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2001, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +39,8 @@ exception statement from your version. */
package java.io;
import gnu.classpath.SystemProperties;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
* Status: Believed complete and correct to 1.3
@@ -64,7 +67,7 @@ public class PrintStream extends FilterOutputStream
// Line separator string.
private static final char[] line_separator
= System.getProperty("line.separator").toCharArray();
= SystemProperties.getProperty("line.separator").toCharArray();
/**
* Encoding name
@@ -112,7 +115,7 @@ public class PrintStream extends FilterOutputStream
super (out);
try {
this.encoding = System.getProperty("file.encoding");
this.encoding = SystemProperties.getProperty("file.encoding");
} catch (SecurityException e){
this.encoding = "ISO8859_1";
} catch (IllegalArgumentException e){
@@ -124,7 +124,10 @@ public class RandomAccessFile implements DataOutput, DataInput
ch = FileChannelImpl.create(file, fdmode);
fd = new FileDescriptor(ch);
out = new DataOutputStream (new FileOutputStream (fd));
if ((fdmode & FileChannelImpl.WRITE) != 0)
out = new DataOutputStream (new FileOutputStream (fd));
else
out = null;
in = new DataInputStream (new FileInputStream (fd));
}
@@ -766,6 +769,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void write (int oneByte) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.write(oneByte);
}
@@ -777,6 +783,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void write (byte[] buffer) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.write(buffer);
}
@@ -792,6 +801,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public void write (byte[] buffer, int offset, int len) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.write (buffer, offset, len);
}
@@ -806,6 +818,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeBoolean (boolean val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeBoolean(val);
}
@@ -820,6 +835,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeByte (int val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeByte(val);
}
@@ -834,6 +852,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeShort (int val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeShort(val);
}
@@ -848,6 +869,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeChar (int val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeChar(val);
}
@@ -861,6 +885,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeInt (int val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeInt(val);
}
@@ -874,6 +901,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeLong (long val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeLong(val);
}
@@ -893,6 +923,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeFloat (float val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeFloat(val);
}
@@ -913,6 +946,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeDouble (double val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeDouble(val);
}
@@ -927,6 +963,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeBytes (String val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeBytes(val);
}
@@ -941,6 +980,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeChars (String val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeChars(val);
}
@@ -975,6 +1017,9 @@ public class RandomAccessFile implements DataOutput, DataInput
*/
public final void writeUTF (String val) throws IOException
{
if (out == null)
throw new IOException("Bad file descriptor");
out.writeUTF(val);
}
@@ -550,6 +550,12 @@ public class StreamTokenizer
/**
* This method sets the numeric attribute on the characters '0' - '9' and
* the characters '.' and '-'.
* When this method is used, the result of giving other attributes
* (whitespace, quote, or comment) to the numeric characters may
* vary depending on the implementation. For example, if
* parseNumbers() and then whitespaceChars('1', '1') are called,
* this implementation reads "121" as 2, while some other implementation
* will read it as 21.
*/
public void parseNumbers()
{
+6 -5
View File
@@ -2410,11 +2410,11 @@ public final class Character implements Serializable, Comparable
{
// Write second char first to cause IndexOutOfBoundsException
// immediately.
dst[dstIndex + 1] = (char) ((codePoint & 0x3ff)
+ (int) MIN_LOW_SURROGATE );
dst[dstIndex] = (char) ((codePoint >> 10) + (int) MIN_HIGH_SURROGATE);
final int cp2 = codePoint - 0x10000;
dst[dstIndex + 1] = (char) ((cp2 % 0x400) + (int) MIN_LOW_SURROGATE);
dst[dstIndex] = (char) ((cp2 / 0x400) + (int) MIN_HIGH_SURROGATE);
result = 2;
}
}
else
{
dst[dstIndex] = (char) codePoint;
@@ -2523,7 +2523,8 @@ public final class Character implements Serializable, Comparable
*/
public static int toCodePoint(char high, char low)
{
return ((high - MIN_HIGH_SURROGATE) << 10) + (low - MIN_LOW_SURROGATE);
return ((high - MIN_HIGH_SURROGATE) * 0x400) +
(low - MIN_LOW_SURROGATE) + 0x10000;
}
/**
+5 -3
View File
@@ -583,8 +583,7 @@ public final class Class implements Serializable
/**
* Returns the <code>Package</code> in which this class is defined
* Returns null when this information is not available from the
* classloader of this class or when the classloader of this class
* is null.
* classloader of this class.
*
* @return the package for this class, if it is available
* @since 1.2
@@ -837,7 +836,10 @@ public final class Class implements Serializable
*/
public int getModifiers()
{
return VMClass.getModifiers (this, false);
int mod = VMClass.getModifiers (this, false);
return (mod & (Modifier.PUBLIC | Modifier.PROTECTED | Modifier.PRIVATE |
Modifier.FINAL | Modifier.STATIC | Modifier.ABSTRACT |
Modifier.INTERFACE));
}
/**
+75
View File
@@ -172,6 +172,81 @@ public final class Double extends Number implements Comparable
return VMDouble.toString(d, false);
}
/**
* Convert a double value to a hexadecimal string. This converts as
* follows:
* <ul>
* <li> A NaN value is converted to the string "NaN".
* <li> Positive infinity is converted to the string "Infinity".
* <li> Negative infinity is converted to the string "-Infinity".
* <li> For all other values, the first character of the result is '-'
* if the value is negative. This is followed by '0x1.' if the
* value is normal, and '0x0.' if the value is denormal. This is
* then followed by a (lower-case) hexadecimal representation of the
* mantissa, with leading zeros as required for denormal values.
* The next character is a 'p', and this is followed by a decimal
* representation of the unbiased exponent.
* </ul>
* @param d the double value
* @return the hexadecimal string representation
* @since 1.5
*/
public static String toHexString(double d)
{
if (isNaN(d))
return "NaN";
if (isInfinite(d))
return d < 0 ? "-Infinity" : "Infinity";
long bits = doubleToLongBits(d);
StringBuilder result = new StringBuilder();
if (bits < 0)
result.append('-');
result.append("0x");
final int mantissaBits = 52;
final int exponentBits = 11;
long mantMask = (1L << mantissaBits) - 1;
long mantissa = bits & mantMask;
long expMask = (1L << exponentBits) - 1;
long exponent = (bits >>> mantissaBits) & expMask;
result.append(exponent == 0 ? '0' : '1');
result.append('.');
result.append(Long.toHexString(mantissa));
if (exponent == 0 && mantissa != 0)
{
// Treat denormal specially by inserting '0's to make
// the length come out right. The constants here are
// to account for things like the '0x'.
int offset = 4 + ((bits < 0) ? 1 : 0);
// The silly +3 is here to keep the code the same between
// the Float and Double cases. In Float the value is
// not a multiple of 4.
int desiredLength = offset + (mantissaBits + 3) / 4;
while (result.length() < desiredLength)
result.insert(offset, '0');
}
result.append('p');
if (exponent == 0 && mantissa == 0)
{
// Zero, so do nothing special.
}
else
{
// Apply bias.
boolean denormal = exponent == 0;
exponent -= (1 << (exponentBits - 1)) - 1;
// Handle denormal.
if (denormal)
++exponent;
}
result.append(Long.toString(exponent));
return result.toString();
}
/**
* Returns a <code>Double</code> object wrapping the value.
* In contrast to the <code>Double</code> constructor, this method
+77
View File
@@ -182,6 +182,83 @@ public final class Float extends Number implements Comparable
return VMDouble.toString(f, true);
}
/**
* Convert a float value to a hexadecimal string. This converts as
* follows:
* <ul>
* <li> A NaN value is converted to the string "NaN".
* <li> Positive infinity is converted to the string "Infinity".
* <li> Negative infinity is converted to the string "-Infinity".
* <li> For all other values, the first character of the result is '-'
* if the value is negative. This is followed by '0x1.' if the
* value is normal, and '0x0.' if the value is denormal. This is
* then followed by a (lower-case) hexadecimal representation of the
* mantissa, with leading zeros as required for denormal values.
* The next character is a 'p', and this is followed by a decimal
* representation of the unbiased exponent.
* </ul>
* @param f the float value
* @return the hexadecimal string representation
* @since 1.5
*/
public static String toHexString(float f)
{
if (isNaN(f))
return "NaN";
if (isInfinite(f))
return f < 0 ? "-Infinity" : "Infinity";
int bits = floatToIntBits(f);
StringBuilder result = new StringBuilder();
if (bits < 0)
result.append('-');
result.append("0x");
final int mantissaBits = 23;
final int exponentBits = 8;
int mantMask = (1 << mantissaBits) - 1;
int mantissa = bits & mantMask;
int expMask = (1 << exponentBits) - 1;
int exponent = (bits >>> mantissaBits) & expMask;
result.append(exponent == 0 ? '0' : '1');
result.append('.');
// For Float only, we have to adjust the mantissa.
mantissa <<= 1;
result.append(Integer.toHexString(mantissa));
if (exponent == 0 && mantissa != 0)
{
// Treat denormal specially by inserting '0's to make
// the length come out right. The constants here are
// to account for things like the '0x'.
int offset = 4 + ((bits < 0) ? 1 : 0);
// The silly +3 is here to keep the code the same between
// the Float and Double cases. In Float the value is
// not a multiple of 4.
int desiredLength = offset + (mantissaBits + 3) / 4;
while (result.length() < desiredLength)
result.insert(offset, '0');
}
result.append('p');
if (exponent == 0 && mantissa == 0)
{
// Zero, so do nothing special.
}
else
{
// Apply bias.
boolean denormal = exponent == 0;
exponent -= (1 << (exponentBits - 1)) - 1;
// Handle denormal.
if (denormal)
++exponent;
}
result.append(Integer.toString(exponent));
return result.toString();
}
/**
* Creates a new <code>Float</code> object using the <code>String</code>.
*
@@ -1,5 +1,5 @@
/* InheritableThreadLocal -- a ThreadLocal which inherits values across threads
Copyright (C) 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
Copyright (C) 2000, 2001, 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -37,8 +37,9 @@ exception statement from your version. */
package java.lang;
import gnu.java.util.WeakIdentityHashMap;
import java.util.Iterator;
import java.util.WeakHashMap;
/**
* A ThreadLocal whose value is inherited by child Threads. The value of the
@@ -98,15 +99,15 @@ public class InheritableThreadLocal extends ThreadLocal
Iterator keys = parentThread.locals.keySet().iterator();
while (keys.hasNext())
{
Key key = (Key)keys.next();
if (key.get() instanceof InheritableThreadLocal)
Object key = keys.next();
if (key instanceof InheritableThreadLocal)
{
InheritableThreadLocal local = (InheritableThreadLocal)key.get();
InheritableThreadLocal local = (InheritableThreadLocal)key;
Object parentValue = parentThread.locals.get(key);
Object childValue = local.childValue(parentValue == NULL
? null : parentValue);
if (childThread.locals == null)
childThread.locals = new WeakHashMap();
childThread.locals = new WeakIdentityHashMap();
childThread.locals.put(key, (childValue == null
? NULL : childValue));
}
@@ -41,9 +41,6 @@ package java.lang;
import gnu.classpath.VMStackWalker;
import java.awt.AWTPermission;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.Window;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -424,7 +421,7 @@ public class SecurityManager
public void checkAccess(Thread thread)
{
if (thread.getThreadGroup() != null
&& thread.getThreadGroup().getParent() != null)
&& thread.getThreadGroup().getParent() == null)
checkPermission(new RuntimePermission("modifyThread"));
}
@@ -457,7 +454,7 @@ public class SecurityManager
*/
public void checkAccess(ThreadGroup g)
{
if (g.getParent() != null)
if (g.getParent() == null)
checkPermission(new RuntimePermission("modifyThreadGroup"));
}
@@ -837,7 +834,7 @@ public class SecurityManager
* @param window the window to create
* @return true if there is permission to show the window without warning
* @throws NullPointerException if window is null
* @see Window#Window(Frame)
* @see java.awt.Window#Window(java.awt.Frame)
*/
public boolean checkTopLevelWindow(Object window)
{
@@ -862,7 +859,7 @@ public class SecurityManager
* an exception.
*
* @throws SecurityException if permission is denied
* @see Toolkit#getPrintJob(Frame, String, Properties)
* @see java.awt.Toolkit#getPrintJob(java.awt.Frame, String, Properties)
* @since 1.1
*/
public void checkPrintJobAccess()
@@ -878,7 +875,7 @@ public class SecurityManager
* rather than throwing an exception.
*
* @throws SecurityException if permission is denied
* @see Toolkit#getSystemClipboard()
* @see java.awt.Toolkit#getSystemClipboard()
* @since 1.1
*/
public void checkSystemClipboardAccess()
@@ -894,7 +891,7 @@ public class SecurityManager
* rather than throwing an exception.
*
* @throws SecurityException if permission is denied
* @see Toolkit#getSystemEventQueue()
* @see java.awt.Toolkit#getSystemEventQueue()
* @since 1.1
*/
public void checkAwtEventQueueAccess()
@@ -49,7 +49,7 @@ import java.io.Serializable;
* @author Mark Wielaard (mark@klomp.org)
* @author Eric Blake (ebb9@email.byu.edu)
* @since 1.4
* @status updated to 1.4
* @status updated to 1.5
*/
public final class StackTraceElement implements Serializable
{
@@ -111,6 +111,26 @@ public final class StackTraceElement implements Serializable
this.isNative = isNative;
}
/**
* Create a new StackTraceElement representing a given source location.
*
* @param className the fully qualified name of the class
* @param methodName the name of the method
* @param fileName the name of the file, null if unknown
* @param lineNumber the line in the file, negative if unknown, or -2
* if this method is native
*
* @since 1.5
*/
public StackTraceElement(String className, String methodName, String fileName,
int lineNumber)
{
this(fileName, lineNumber, className, methodName, lineNumber == -2);
// The public constructor doesn't allow certain values to be null.
if (className == null || methodName == null)
throw new NullPointerException("invalid argument to constructor");
}
/**
* Returns the name of the file, or null if unknown. This is usually
* obtained from the <code>SourceFile</code> attribute of the class file
+11 -5
View File
@@ -273,7 +273,8 @@ public final class String implements Serializable, Comparable, CharSequence
throw new StringIndexOutOfBoundsException("offset: " + offset);
if (count < 0)
throw new StringIndexOutOfBoundsException("count: " + count);
if (offset + count < 0 || offset + count > ascii.length)
// equivalent to: offset + count < 0 || offset + count > ascii.length
if (ascii.length - offset < count)
throw new StringIndexOutOfBoundsException("offset + count: "
+ (offset + count));
value = new char[count];
@@ -338,7 +339,8 @@ public final class String implements Serializable, Comparable, CharSequence
throw new StringIndexOutOfBoundsException("offset: " + offset);
if (count < 0)
throw new StringIndexOutOfBoundsException("count: " + count);
if (offset + count < 0 || offset + count > data.length)
// equivalent to: offset + count < 0 || offset + count > data.length
if (data.length - offset < count)
throw new StringIndexOutOfBoundsException("offset + count: "
+ (offset + count));
try
@@ -418,7 +420,8 @@ public final class String implements Serializable, Comparable, CharSequence
throw new StringIndexOutOfBoundsException("offset: " + offset);
if (count < 0)
throw new StringIndexOutOfBoundsException("count: " + count);
if (offset + count < 0 || offset + count > data.length)
// equivalent to: offset + count < 0 || offset + count > data.length
if (data.length - offset < count)
throw new StringIndexOutOfBoundsException("offset + count: "
+ (offset + count));
int o, c;
@@ -533,7 +536,8 @@ public final class String implements Serializable, Comparable, CharSequence
throw new StringIndexOutOfBoundsException("offset: " + offset);
if (count < 0)
throw new StringIndexOutOfBoundsException("count: " + count);
if (offset + count < 0 || offset + count > data.length)
// equivalent to: offset + count < 0 || offset + count > data.length
if (data.length - offset < count)
throw new StringIndexOutOfBoundsException("offset + count: "
+ (offset + count));
if (dont_copy)
@@ -1761,7 +1765,7 @@ public final class String implements Serializable, Comparable, CharSequence
/**
* Return the number of code points between two indices in the
* <code>StringBuffer</code>. An unpaired surrogate counts as a
* <code>String</code>. An unpaired surrogate counts as a
* code point for this purpose. Characters outside the indicated
* range are not examined, even if the range ends in the middle of a
* surrogate pair.
@@ -1879,6 +1883,8 @@ public final class String implements Serializable, Comparable, CharSequence
* described in s.
* @param s the CharSequence
* @return true iff this String contains s
*
* @since 1.5
*/
public boolean contains (CharSequence s)
{
+3 -3
View File
@@ -38,9 +38,9 @@ exception statement from your version. */
package java.lang;
import gnu.java.util.WeakIdentityHashMap;
import java.security.Permission;
import java.util.Map;
import java.util.WeakHashMap;
/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
* "The Java Language Specification", ISBN 0-201-63451-1
@@ -137,7 +137,7 @@ public class Thread implements Runnable
/** Thread local storage. Package accessible for use by
* InheritableThreadLocal.
*/
WeakHashMap locals;
WeakIdentityHashMap locals;
/**
* Allocates a new <code>Thread</code> object. This constructor has
@@ -996,7 +996,7 @@ public class Thread implements Runnable
Map locals = thread.locals;
if (locals == null)
{
locals = thread.locals = new WeakHashMap();
locals = thread.locals = new WeakIdentityHashMap();
}
return locals;
}
+4 -19
View File
@@ -1,5 +1,5 @@
/* ThreadLocal -- a variable with a unique value per thread
Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 2000, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -95,21 +95,6 @@ public class ThreadLocal
*/
static final Object NULL = new Object();
/**
* Serves as a key for the Thread.locals WeakHashMap.
* We can't use "this", because a subclass may override equals/hashCode
* and we need to use object identity for the map.
*/
final Key key = new Key();
class Key
{
ThreadLocal get()
{
return ThreadLocal.this;
}
}
/**
* Creates a ThreadLocal object without associating any value to it yet.
*/
@@ -143,11 +128,11 @@ public class ThreadLocal
Map map = Thread.getThreadLocals();
// Note that we don't have to synchronize, as only this thread will
// ever modify the map.
Object value = map.get(key);
Object value = map.get(this);
if (value == null)
{
value = initialValue();
map.put(key, value == null ? NULL : value);
map.put(this, value == null ? NULL : value);
}
return value == NULL ? null : value;
}
@@ -165,6 +150,6 @@ public class ThreadLocal
Map map = Thread.getThreadLocals();
// Note that we don't have to synchronize, as only this thread will
// ever modify the map.
map.put(key, value == null ? NULL : value);
map.put(this, value == null ? NULL : value);
}
}
@@ -176,7 +176,12 @@ public class DatagramSocket
{
String propVal = SystemProperties.getProperty("impl.prefix");
if (propVal == null || propVal.equals(""))
impl = new PlainDatagramSocketImpl();
{
if (factory != null)
impl = factory.createDatagramSocketImpl();
else
impl = new PlainDatagramSocketImpl();
}
else
try
{
+5 -134
View File
@@ -43,7 +43,6 @@ import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.StringTokenizer;
/**
@@ -65,22 +64,6 @@ public class InetAddress implements Serializable
{
private static final long serialVersionUID = 3286316764910316507L;
/**
* The default DNS hash table size,
* Use a prime number happy with hash table.
*/
private static final int DEFAULT_CACHE_SIZE = 89;
/**
* The default caching period in minutes.
*/
private static final int DEFAULT_CACHE_PERIOD = 4 * 60;
/**
* Percentage of cache entries to purge when the table gets full.
*/
private static final int DEFAULT_CACHE_PURGE_PCT = 30;
/**
* The special IP address INADDR_ANY.
*/
@@ -96,50 +79,8 @@ public class InetAddress implements Serializable
*/
static InetAddress LOCALHOST;
/**
* The size of the cache.
*/
private static int cache_size = 0;
/**
* The length of time we will continue to read the address from cache
* before forcing another lookup.
*/
private static int cache_period = 0;
/**
* What percentage of the cache we will purge if it gets full.
*/
private static int cache_purge_pct = 0;
/**
* HashMap to use as DNS lookup cache.
* Use HashMap because all accesses to cache are already synchronized.
*/
private static HashMap cache;
static
{
// Look for properties that override default caching behavior
cache_size =
Integer.getInteger("gnu.java.net.dns_cache_size", DEFAULT_CACHE_SIZE)
.intValue();
cache_period =
Integer.getInteger("gnu.java.net.dns_cache_period",
DEFAULT_CACHE_PERIOD * 60 * 1000).intValue();
cache_purge_pct =
Integer.getInteger("gnu.java.net.dns_cache_purge_pct",
DEFAULT_CACHE_PURGE_PCT).intValue();
// Fallback to defaults if necessary
if ((cache_purge_pct < 1) || (cache_purge_pct > 100))
cache_purge_pct = DEFAULT_CACHE_PURGE_PCT;
// Create the cache
if (cache_size != 0)
cache = new HashMap(cache_size);
// precompute the ANY_IF address
try
{
@@ -173,11 +114,6 @@ public class InetAddress implements Serializable
*/
String hostName;
/**
* The time this address was looked up.
*/
transient long lookup_time;
/**
* The field 'family' seems to be the AF_ value.
* FIXME: Much of the code in the other java.net classes does not make
@@ -200,8 +136,6 @@ public class InetAddress implements Serializable
addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
hostName = hostname;
lookup_time = System.currentTimeMillis();
family = 2; /* AF_INET */
}
@@ -649,20 +583,17 @@ public class InetAddress implements Serializable
InetAddress[] addresses;
if (hostname != null)
hostname = hostname.trim();
// Default to current host if necessary
if (hostname == null)
if (hostname == null || hostname.equals(""))
{
addresses = new InetAddress[1];
addresses[0] = LOCALHOST;
return addresses;
}
// Check the cache for this host before doing a lookup
addresses = checkCacheFor(hostname);
if (addresses != null)
return addresses;
// Not in cache, try the lookup
byte[][] iplist = VMInetAddress.getHostByName(hostname);
@@ -679,70 +610,9 @@ public class InetAddress implements Serializable
addresses[i] = new Inet4Address(iplist[i], hostname);
}
addToCache(hostname, addresses);
return addresses;
}
/**
* This method checks the DNS cache to see if we have looked this hostname
* up before. If so, we return the cached addresses unless it has been in the
* cache too long.
*
* @param hostname The hostname to check for
*
* @return The InetAddress for this hostname or null if not available
*/
private static synchronized InetAddress[] checkCacheFor(String hostname)
{
InetAddress[] addresses = null;
if (cache_size == 0)
return null;
Object obj = cache.get(hostname);
if (obj == null)
return null;
if (obj instanceof InetAddress[])
addresses = (InetAddress[]) obj;
if (addresses == null)
return null;
if (cache_period != -1)
if ((System.currentTimeMillis() - addresses[0].lookup_time) > cache_period)
{
cache.remove(hostname);
return null;
}
return addresses;
}
/**
* This method adds an InetAddress object to our DNS cache. Note that
* if the cache is full, then we run a purge to get rid of old entries.
* This will cause a performance hit, thus applications using lots of
* lookups should set the cache size to be very large.
*
* @param hostname The hostname to cache this address under
* @param obj The InetAddress or InetAddress array to store
*/
private static synchronized void addToCache(String hostname, Object obj)
{
if (cache_size == 0)
return;
// Check to see if hash table is full
if (cache_size != -1)
if (cache.size() == cache_size)
{
// FIXME Add code to purge later.
}
cache.put(hostname, obj);
}
/**
* Returns the special address INADDR_ANY used for binding to a local
* port on all IP addresses hosted by a the local host.
@@ -757,6 +627,7 @@ public class InetAddress implements Serializable
{
byte[] tmp = VMInetAddress.lookupInaddrAny();
inaddr_any = new Inet4Address(tmp, null);
inaddr_any.hostName = inaddr_any.getHostName();
}
return inaddr_any;
+5 -4
View File
@@ -1,5 +1,5 @@
/* URL.java -- Uniform Resource Locator Class
Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005
Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -38,6 +38,7 @@ exception statement from your version. */
package java.net;
import gnu.classpath.SystemProperties;
import gnu.java.net.URLParseError;
import java.io.IOException;
@@ -198,7 +199,7 @@ public final class URL implements Serializable
static
{
String s = System.getProperty("gnu.java.net.nocache_protocol_handlers");
String s = SystemProperties.getProperty("gnu.java.net.nocache_protocol_handlers");
if (s == null)
cache_handlers = true;
@@ -342,7 +343,7 @@ public final class URL implements Serializable
*/
public URL(URL context, String spec) throws MalformedURLException
{
this(context, spec, (URLStreamHandler) null);
this(context, spec, (context == null) ? (URLStreamHandler)null : context.ph);
}
/**
@@ -867,7 +868,7 @@ public final class URL implements Serializable
// Except in very unusual environments the JDK specified one shouldn't
// ever be needed (or available).
String ph_search_path =
System.getProperty("java.protocol.handler.pkgs");
SystemProperties.getProperty("java.protocol.handler.pkgs");
// Tack our default package on at the ends.
if (ph_search_path != null)
@@ -121,6 +121,8 @@ public abstract class Charset implements Comparable
*
* This may be set by the user or VM with the file.encoding
* property.
*
* @since 1.5
*/
public static Charset defaultCharset()
{
@@ -1,5 +1,5 @@
/* CharsetProvider.java -- charset service provider interface
Copyright (C) 2002 Free Software Foundation
Copyright (C) 2002, 2006 Free Software Foundation
This file is part of GNU Classpath.
@@ -67,8 +67,12 @@ public abstract class CharsetProvider
*/
protected CharsetProvider()
{
// We only do the security check for custom providers, not for the
// built in ones.
SecurityManager s = System.getSecurityManager();
if (s != null)
if (s != null &&
! (this instanceof gnu.java.nio.charset.Provider
|| this instanceof gnu.java.nio.charset.iconv.IconvProvider))
s.checkPermission(new RuntimePermission("charsetProvider"));
}
@@ -1,5 +1,5 @@
/* MessageDigest.java --- The message digest interface.
Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc.
Copyright (C) 1999, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -167,6 +167,9 @@ public abstract class MessageDigest extends MessageDigestSpi
public static MessageDigest getInstance(String algorithm, String provider)
throws NoSuchAlgorithmException, NoSuchProviderException
{
if (provider != null)
provider = provider.trim();
if (provider == null || provider.length() == 0)
throw new IllegalArgumentException("Illegal provider");
+21 -5
View File
@@ -1,5 +1,6 @@
/* Security.java --- Java base security class implementation
Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -41,6 +42,7 @@ package java.security;
import gnu.classpath.SystemProperties;
import gnu.classpath.Configuration;
import gnu.classpath.VMStackWalker;
import java.io.IOException;
import java.io.InputStream;
@@ -354,6 +356,14 @@ public final class Security
*/
public static Provider getProvider(String name)
{
if (name == null)
return null;
else
{
name = name.trim();
if (name.length() == 0)
return null;
}
Provider p;
int max = providers.size ();
for (int i = 0; i < max; i++)
@@ -383,8 +393,11 @@ public final class Security
*/
public static String getProperty(String key)
{
// XXX To prevent infinite recursion when the SecurityManager calls us,
// don't do a security check if the caller is trusted (by virtue of having
// been loaded by the bootstrap class loader).
SecurityManager sm = System.getSecurityManager();
if (sm != null)
if (sm != null && VMStackWalker.getCallingClassLoader() != null)
sm.checkSecurityAccess("getProperty." + key);
return secprops.getProperty(key);
@@ -399,20 +412,23 @@ public final class Security
* </p>
*
* @param key the name of the property to be set.
* @param datnum the value of the property to be set.
* @param datum the value of the property to be set.
* @throws SecurityException if a security manager exists and its
* {@link SecurityManager#checkPermission(Permission)} method denies access
* to set the specified security property value.
* @see #getProperty(String)
* @see SecurityPermission
*/
public static void setProperty(String key, String datnum)
public static void setProperty(String key, String datum)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkSecurityAccess("setProperty." + key);
secprops.put(key, datnum);
if (datum == null)
secprops.remove(key);
else
secprops.put(key, datum);
}
/**
+78
View File
@@ -0,0 +1,78 @@
/* Bidi.java -- Bidirectional Algorithm implementation
Copyright (C) 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.text;
/**
* Bidirectional Algorithm implementation.
*
* TODO/FIXME Only one method <code>requiresBidi</code> is implemented
* for now by using <code>Character</code>. The full algorithm is <a
* href="http://www.unicode.org/unicode/reports/tr9/">Unicode Standard
* Annex #9: The Bidirectional Algorithm</a>. A full implementation is
* <a href="http://fribidi.org/">GNU FriBidi</a>.
*/
public class Bidi
{
/**
* Returns false if all characters in the text between start and end
* are all left-to-right text. This implementation is just calls
* <code>Character.getDirectionality(char)</code> on all characters
* and makes sure all characters are either explicitly left-to-right
* or neutral in directionality (character types L, EN, ES, ET, AN,
* CS, S and WS).
*/
public static boolean requiresBidi(char[] text, int start, int end)
{
for (int i = start; i < end; i++)
{
byte dir = Character.getDirectionality(text[i]);
if (dir != Character.DIRECTIONALITY_LEFT_TO_RIGHT
&& dir != Character.DIRECTIONALITY_EUROPEAN_NUMBER
&& dir != Character.DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR
&& dir != Character.DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR
&& dir != Character.DIRECTIONALITY_ARABIC_NUMBER
&& dir != Character.DIRECTIONALITY_COMMON_NUMBER_SEPARATOR
&& dir != Character.DIRECTIONALITY_SEGMENT_SEPARATOR
&& dir != Character.DIRECTIONALITY_WHITESPACE)
return true;
}
return false;
}
}
@@ -182,7 +182,9 @@ public class DecimalFormat extends NumberFormat
{
groupingUsed = saw_group;
groupingSize = (byte) countSinceGroup;
minimumIntegerDigits = zeroCount;
// Checking "zeroCount > 0" avoids 0 being formatted into "" with "#".
if (zeroCount > 0)
minimumIntegerDigits = zeroCount;
}
// Early termination.
+2 -2
View File
@@ -594,13 +594,13 @@ public abstract class AbstractMap implements Map
*
* @param o1 the first object
* @param o2 the second object
* @return o1 == null ? o2 == null : o1.equals(o2)
* @return o1 == o2 || (o1 != null && o1.equals(o2))
*/
// Package visible for use throughout java.util.
// It may be inlined since it is final.
static final boolean equals(Object o1, Object o2)
{
return o1 == null ? o2 == null : o1.equals(o2);
return o1 == o2 || (o1 != null && o1.equals(o2));
}
/**
+1 -1
View File
@@ -92,7 +92,7 @@ public class ArrayList extends AbstractList
/**
* The default capacity for new ArrayLists.
*/
private static final int DEFAULT_CAPACITY = 16;
private static final int DEFAULT_CAPACITY = 10;
/**
* The number of elements in this list.
+4 -4
View File
@@ -670,10 +670,10 @@ public class Collections
for ( ; i != pos; i--, o = itr.previous());
forward = false;
}
final int d = compare(key, o, c);
final int d = compare(o, key, c);
if (d == 0)
return pos;
else if (d < 0)
else if (d > 0)
hi = pos - 1;
else
// This gets the insertion point right on the last loop
@@ -685,10 +685,10 @@ public class Collections
while (low <= hi)
{
pos = (low + hi) >> 1;
final int d = compare(key, l.get(pos), c);
final int d = compare(l.get(pos), key, c);
if (d == 0)
return pos;
else if (d < 0)
else if (d > 0)
hi = pos - 1;
else
// This gets the insertion point right on the last loop
+166 -66
View File
@@ -1,6 +1,7 @@
/* Hashtable.java -- a class providing a basic hashtable data structure,
mapping Object --> Object
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -110,12 +111,6 @@ public class Hashtable extends Dictionary
*/
private static final int DEFAULT_CAPACITY = 11;
/** An "enum" of iterator types. */
// Package visible for use by nested classes.
static final int KEYS = 0,
VALUES = 1,
ENTRIES = 2;
/**
* The default load factor; this is explicitly specified by the spec.
*/
@@ -302,7 +297,7 @@ public class Hashtable extends Dictionary
*/
public Enumeration keys()
{
return new Enumerator(KEYS);
return new KeyEnumerator();
}
/**
@@ -316,7 +311,7 @@ public class Hashtable extends Dictionary
*/
public Enumeration elements()
{
return new Enumerator(VALUES);
return new ValueEnumerator();
}
/**
@@ -333,20 +328,19 @@ public class Hashtable extends Dictionary
*/
public synchronized boolean contains(Object value)
{
if (value == null)
throw new NullPointerException();
for (int i = buckets.length - 1; i >= 0; i--)
{
HashEntry e = buckets[i];
while (e != null)
{
if (value.equals(e.value))
if (e.value.equals(value))
return true;
e = e.next;
}
}
// Must throw on null argument even if the table is empty
if (value == null)
throw new NullPointerException();
return false;
}
@@ -385,7 +379,7 @@ public class Hashtable extends Dictionary
HashEntry e = buckets[idx];
while (e != null)
{
if (key.equals(e.key))
if (e.key.equals(key))
return true;
e = e.next;
}
@@ -408,7 +402,7 @@ public class Hashtable extends Dictionary
HashEntry e = buckets[idx];
while (e != null)
{
if (key.equals(e.key))
if (e.key.equals(key))
return e.value;
e = e.next;
}
@@ -438,7 +432,7 @@ public class Hashtable extends Dictionary
while (e != null)
{
if (key.equals(e.key))
if (e.key.equals(key))
{
// Bypass e.setValue, since we already know value is non-null.
Object r = e.value;
@@ -484,7 +478,7 @@ public class Hashtable extends Dictionary
while (e != null)
{
if (key.equals(e.key))
if (e.key.equals(key))
{
modCount++;
if (last == null)
@@ -581,8 +575,8 @@ public class Hashtable extends Dictionary
{
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized HashIterator instead.
Iterator entries = new HashIterator(ENTRIES);
// unsynchronized EntryIterator instead.
Iterator entries = new EntryIterator();
StringBuffer r = new StringBuffer("{");
for (int pos = size; pos > 0; pos--)
{
@@ -624,7 +618,7 @@ public class Hashtable extends Dictionary
public Iterator iterator()
{
return new HashIterator(KEYS);
return new KeyIterator();
}
public void clear()
@@ -682,7 +676,7 @@ public class Hashtable extends Dictionary
public Iterator iterator()
{
return new HashIterator(VALUES);
return new ValueIterator();
}
public void clear()
@@ -734,7 +728,7 @@ public class Hashtable extends Dictionary
public Iterator iterator()
{
return new HashIterator(ENTRIES);
return new EntryIterator();
}
public void clear()
@@ -798,8 +792,8 @@ public class Hashtable extends Dictionary
{
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized HashIterator instead.
Iterator itr = new HashIterator(ENTRIES);
// unsynchronized EntryIterator instead.
Iterator itr = new EntryIterator();
int hashcode = 0;
for (int pos = size; pos > 0; pos--)
hashcode += itr.next().hashCode();
@@ -844,7 +838,7 @@ public class Hashtable extends Dictionary
HashEntry e = buckets[idx];
while (e != null)
{
if (o.equals(e))
if (e.equals(o))
return e;
e = e.next;
}
@@ -904,8 +898,12 @@ public class Hashtable extends Dictionary
if (dest != null)
{
while (dest.next != null)
dest = dest.next;
HashEntry next = dest.next;
while (next != null)
{
dest = next;
next = dest.next;
}
dest.next = e;
}
else
@@ -940,8 +938,8 @@ public class Hashtable extends Dictionary
s.writeInt(size);
// Since we are already synchronized, and entrySet().iterator()
// would repeatedly re-lock/release the monitor, we directly use the
// unsynchronized HashIterator instead.
Iterator it = new HashIterator(ENTRIES);
// unsynchronized EntryIterator instead.
Iterator it = new EntryIterator();
while (it.hasNext())
{
HashEntry entry = (HashEntry) it.next();
@@ -980,21 +978,17 @@ public class Hashtable extends Dictionary
/**
* A class which implements the Iterator interface and is used for
* iterating over Hashtables.
* This implementation is parameterized to give a sequential view of
* keys, values, or entries; it also allows the removal of elements,
* as per the Javasoft spec. Note that it is not synchronized; this is
* a performance enhancer since it is never exposed externally and is
* only used within synchronized blocks above.
* This implementation iterates entries. Subclasses are used to
* iterate key and values. It also allows the removal of elements,
* as per the Javasoft spec. Note that it is not synchronized; this
* is a performance enhancer since it is never exposed externally
* and is only used within synchronized blocks above.
*
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
private final class HashIterator implements Iterator
private class EntryIterator implements Iterator
{
/**
* The type of this Iterator: {@link #KEYS}, {@link #VALUES},
* or {@link #ENTRIES}.
*/
final int type;
/**
* The number of modifications to the backing Hashtable that we know about.
*/
@@ -1013,14 +1007,13 @@ public class Hashtable extends Dictionary
HashEntry next;
/**
* Construct a new HashIterator with the supplied type.
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES}
* Construct a new EtryIterator
*/
HashIterator(int type)
EntryIterator()
{
this.type = type;
}
/**
* Returns true if the Iterator has more elements.
* @return true if there are more elements
@@ -1049,14 +1042,13 @@ public class Hashtable extends Dictionary
HashEntry e = next;
while (e == null)
e = buckets[--idx];
if (idx <= 0)
return null;
else
e = buckets[--idx];
next = e.next;
last = e;
if (type == VALUES)
return e.value;
if (type == KEYS)
return e.key;
return e;
}
@@ -1077,29 +1069,70 @@ public class Hashtable extends Dictionary
last = null;
knownMod++;
}
} // class HashIterator
} // class EntryIterator
/**
* A class which implements the Iterator interface and is used for
* iterating over keys in Hashtables.
*
* @author Fridtjof Siebert
*/
private class KeyIterator extends EntryIterator
{
/**
* Returns the next element in the Iterator's sequential view.
*
* @return the next element
*
* @throws ConcurrentModificationException if the hashtable was modified
* @throws NoSuchElementException if there is none
*/
public Object next()
{
return ((HashEntry)super.next()).key;
}
} // class KeyIterator
/**
* Enumeration view of this Hashtable, providing sequential access to its
* elements; this implementation is parameterized to provide access either
* to the keys or to the values in the Hashtable.
* A class which implements the Iterator interface and is used for
* iterating over values in Hashtables.
*
* @author Fridtjof Siebert
*/
private class ValueIterator extends EntryIterator
{
/**
* Returns the next element in the Iterator's sequential view.
*
* @return the next element
*
* @throws ConcurrentModificationException if the hashtable was modified
* @throws NoSuchElementException if there is none
*/
public Object next()
{
return ((HashEntry)super.next()).value;
}
} // class ValueIterator
/**
* Enumeration view of the entries in this Hashtable, providing
* sequential access to its elements.
*
* <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
* as this could cause a rehash and we'd completely lose our place. Even
* without a rehash, it is undetermined if a new element added would
* appear in the enumeration. The spec says nothing about this, but
* the "Java Class Libraries" book infers that modifications to the
* the "Java Class Libraries" book implies that modifications to the
* hashtable during enumeration causes indeterminate results. Don't do it!
*
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
private final class Enumerator implements Enumeration
private class EntryEnumerator implements Enumeration
{
/**
* The type of this Iterator: {@link #KEYS} or {@link #VALUES}.
*/
final int type;
/** The number of elements remaining to be returned by next(). */
int count = size;
/** Current index in the physical hash table. */
@@ -1113,11 +1146,10 @@ public class Hashtable extends Dictionary
/**
* Construct the enumeration.
* @param type either {@link #KEYS} or {@link #VALUES}.
*/
Enumerator(int type)
EntryEnumerator()
{
this.type = type;
// Nothing to do here.
}
/**
@@ -1142,10 +1174,78 @@ public class Hashtable extends Dictionary
HashEntry e = next;
while (e == null)
e = buckets[--idx];
if (idx <= 0)
return null;
else
e = buckets[--idx];
next = e.next;
return type == VALUES ? e.value : e.key;
return e;
}
} // class Enumerator
} // class EntryEnumerator
/**
* Enumeration view of this Hashtable, providing sequential access to its
* elements.
*
* <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
* as this could cause a rehash and we'd completely lose our place. Even
* without a rehash, it is undetermined if a new element added would
* appear in the enumeration. The spec says nothing about this, but
* the "Java Class Libraries" book implies that modifications to the
* hashtable during enumeration causes indeterminate results. Don't do it!
*
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
private final class KeyEnumerator extends EntryEnumerator
{
/**
* Returns the next element.
* @return the next element
* @throws NoSuchElementException if there is none.
*/
public Object nextElement()
{
HashEntry entry = (HashEntry) super.nextElement();
Object retVal = null;
if (entry != null)
retVal = entry.key;
return retVal;
}
} // class KeyEnumerator
/**
* Enumeration view of this Hashtable, providing sequential access to its
* values.
*
* <b>NOTE</b>: Enumeration is not safe if new elements are put in the table
* as this could cause a rehash and we'd completely lose our place. Even
* without a rehash, it is undetermined if a new element added would
* appear in the enumeration. The spec says nothing about this, but
* the "Java Class Libraries" book implies that modifications to the
* hashtable during enumeration causes indeterminate results. Don't do it!
*
* @author Jon Zeppieri
* @author Fridjof Siebert
*/
private final class ValueEnumerator extends EntryEnumerator
{
/**
* Returns the next element.
* @return the next element
* @throws NoSuchElementException if there is none.
*/
public Object nextElement()
{
HashEntry entry = (HashEntry) super.nextElement();
Object retVal = null;
if (entry != null)
retVal = entry.value;
return retVal;
}
} // class ValueEnumerator
} // class Hashtable
+56 -170
View File
@@ -47,15 +47,10 @@ import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
@@ -743,173 +738,64 @@ label = Name:\\u0020</pre>
throw new NullPointerException("Null input stream supplied.");
try
{
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setValidating(false); /* Don't use the URI */
XMLReader parser = factory.newSAXParser().getXMLReader();
PropertiesHandler handler = new PropertiesHandler();
parser.setContentHandler(handler);
parser.setProperty("http://xml.org/sax/properties/lexical-handler",
handler);
parser.parse(new InputSource(in));
XMLInputFactory factory = XMLInputFactory.newInstance();
// Don't resolve external entity references
factory.setProperty("javax.xml.stream.isSupportingExternalEntities",
Boolean.FALSE);
XMLStreamReader reader = factory.createXMLStreamReader(in);
String name, key = null;
StringBuffer buf = null;
while (reader.hasNext())
{
switch (reader.next())
{
case XMLStreamConstants.START_ELEMENT:
name = reader.getLocalName();
if (buf == null && "entry".equals(name))
{
key = reader.getAttributeValue(null, "key");
if (key == null)
{
String msg = "missing 'key' attribute";
throw new InvalidPropertiesFormatException(msg);
}
buf = new StringBuffer();
}
else if (!"properties".equals(name) && !"comment".equals(name))
{
String msg = "unexpected element name '" + name + "'";
throw new InvalidPropertiesFormatException(msg);
}
break;
case XMLStreamConstants.END_ELEMENT:
name = reader.getLocalName();
if (buf != null && "entry".equals(name))
{
put(key, buf.toString());
buf = null;
}
else if (!"properties".equals(name) && !"comment".equals(name))
{
String msg = "unexpected element name '" + name + "'";
throw new InvalidPropertiesFormatException(msg);
}
break;
case XMLStreamConstants.CHARACTERS:
case XMLStreamConstants.SPACE:
case XMLStreamConstants.CDATA:
if (buf != null)
buf.append(reader.getText());
break;
}
}
reader.close();
}
catch (SAXException e)
catch (XMLStreamException e)
{
throw (InvalidPropertiesFormatException)
new InvalidPropertiesFormatException("Error in parsing XML.").
initCause(e);
}
catch (ParserConfigurationException e)
{
throw (IOException)
new IOException("An XML parser could not be found.").
initCause(e);
}
}
/**
* This class deals with the parsing of XML using
* <a href="http://java.sun.com/dtd/properties.dtd">
* http://java.sun.com/dtd/properties.dtd</a>.
*
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
*/
private class PropertiesHandler
extends DefaultHandler2
{
/**
* The current key.
*/
private String key;
/**
* The current value.
*/
private String value;
/**
* A flag to check whether a valid DTD declaration has been seen.
*/
private boolean dtdDeclSeen;
/**
* Constructs a new Properties handler.
*/
public PropertiesHandler()
{
key = null;
value = null;
dtdDeclSeen = false;
}
/**
* <p>
* Captures the start of the DTD declarations, if they exist.
* A valid properties file must declare the following doctype:
* </p>
* <p>
* <code>!DOCTYPE properties SYSTEM
* "http://java.sun.com/dtd/properties.dtd"</code>
* </p>
*
* @param name the name of the document type.
* @param publicId the public identifier that was declared, or
* null if there wasn't one.
* @param systemId the system identifier that was declared, or
* null if there wasn't one.
* @throws SAXException if some error occurs in parsing.
*/
public void startDTD(String name, String publicId, String systemId)
throws SAXException
{
if (name.equals("properties") &&
publicId == null &&
systemId.equals("http://java.sun.com/dtd/properties.dtd"))
{
dtdDeclSeen = true;
}
else
throw new SAXException("Invalid DTD declaration: " + name);
}
/**
* Captures the start of an XML element.
*
* @param uri the namespace URI.
* @param localName the local name of the element inside the namespace.
* @param qName the local name qualified with the namespace URI.
* @param attributes the attributes of this element.
* @throws SAXException if some error occurs in parsing.
*/
public void startElement(String uri, String localName,
String qName, Attributes attributes)
throws SAXException
{
if (qName.equals("entry"))
{
int index = attributes.getIndex("key");
if (index != -1)
key = attributes.getValue(index);
}
else if (qName.equals("comment") || qName.equals("properties"))
{
/* Ignore it */
}
else
throw new SAXException("Invalid tag: " + qName);
}
/**
* Captures characters within an XML element.
*
* @param ch the array of characters.
* @param start the start index of the characters to use.
* @param length the number of characters to use from the start index on.
* @throws SAXException if some error occurs in parsing.
*/
public void characters(char[] ch, int start, int length)
throws SAXException
{
if (key != null)
value = new String(ch,start,length);
}
/**
* Captures the end of an XML element.
*
* @param uri the namespace URI.
* @param localName the local name of the element inside the namespace.
* @param qName the local name qualified with the namespace URI.
* @throws SAXException if some error occurs in parsing.
*/
public void endElement(String uri, String localName,
String qName)
throws SAXException
{
if (qName.equals("entry"))
{
if (value == null)
value = "";
setProperty(key, value);
key = null;
value = null;
}
}
/**
* Captures the end of the XML document. If a DTD declaration has
* not been seen, the document is erroneous and an exception is thrown.
*
* @throws SAXException if the correct DTD declaration didn't appear.
*/
public void endDocument()
throws SAXException
{
if (!dtdDeclSeen)
throw new SAXException("No appropriate DTD declaration was seen.");
}
} // class PropertiesHandler
} // class Properties
@@ -132,8 +132,7 @@ public class StringTokenizer implements Enumeration
{
len = str.length();
this.str = str;
// The toString() hack causes the NullPointerException.
this.delim = delim.toString();
this.delim = delim;
this.retDelims = returnDelims;
this.pos = 0;
}
+3 -3
View File
@@ -475,7 +475,7 @@ public class WeakHashMap extends AbstractMap implements Map
if (o instanceof Map.Entry)
{
Map.Entry e = (Map.Entry) o;
return key.equals(e.getKey())
return WeakHashMap.equals(getKey(), e.getKey())
&& WeakHashMap.equals(value, e.getValue());
}
return false;
@@ -483,7 +483,7 @@ public class WeakHashMap extends AbstractMap implements Map
public String toString()
{
return key + "=" + value;
return getKey() + "=" + value;
}
}
@@ -657,7 +657,7 @@ public class WeakHashMap extends AbstractMap implements Map
while (bucket != null)
{
WeakBucket.WeakEntry entry = bucket.getEntry();
if (entry != null && key.equals(entry.key))
if (entry != null && equals(key, entry.key))
return entry;
bucket = bucket.next;
@@ -194,7 +194,7 @@ public class XMLFormatter
appendTag(buf, 1, "date", iso8601.format(new Date(millis)));
appendTag(buf, 1, "millis", record.getMillis());
appendTag(buf, 1, "millis", millis);
appendTag(buf, 1, "sequence", record.getSequenceNumber());
appendTag(buf, 1, "logger", record.getLoggerName());
@@ -103,8 +103,11 @@ public final class Pattern implements Serializable
}
catch (REException e)
{
throw new PatternSyntaxException(e.getMessage(),
PatternSyntaxException pse;
pse = new PatternSyntaxException(e.getMessage(),
regex, e.getPosition());
pse.initCause(e);
throw pse;
}
}