diff options
Diffstat (limited to 'libjava/classpath/gnu/java')
43 files changed, 5207 insertions, 219 deletions
diff --git a/libjava/classpath/gnu/java/awt/image/ImageDecoder.java b/libjava/classpath/gnu/java/awt/image/ImageDecoder.java index 141c854..8e8eecb 100644 --- a/libjava/classpath/gnu/java/awt/image/ImageDecoder.java +++ b/libjava/classpath/gnu/java/awt/image/ImageDecoder.java @@ -40,6 +40,8 @@ package gnu.java.awt.image; import java.awt.image.ImageConsumer; import java.awt.image.ImageProducer; import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.EOFException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; @@ -55,6 +57,7 @@ public abstract class ImageDecoder implements ImageProducer int offset; int length; InputStream input; + DataInput datainput; static { @@ -79,6 +82,11 @@ public abstract class ImageDecoder implements ImageProducer this.input = is; } + public ImageDecoder (DataInput datainput) + { + this.datainput = datainput; + } + public ImageDecoder (byte[] imagedata, int imageoffset, int imagelength) { data = imagedata; @@ -119,6 +127,8 @@ public abstract class ImageDecoder implements ImageProducer { if (url != null) input = url.openStream(); + else if (datainput != null) + input = new DataInputStreamWrapper(datainput); else { if (filename != null) @@ -153,4 +163,26 @@ public abstract class ImageDecoder implements ImageProducer } public abstract void produce (Vector v, InputStream is) throws IOException; + + private static class DataInputStreamWrapper extends InputStream + { + private final DataInput datainput; + + DataInputStreamWrapper(DataInput datainput) + { + this.datainput = datainput; + } + + public int read() throws IOException + { + try + { + return datainput.readByte() & 0xFF; + } + catch (EOFException eofe) + { + return -1; + } + } + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java index d80306c..d7217aa 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics.java @@ -48,7 +48,6 @@ import java.awt.Graphics; import java.awt.Image; import java.awt.Rectangle; import java.awt.Shape; -import java.awt.SystemColor; import java.awt.image.ImageObserver; import java.text.AttributedCharacterIterator; @@ -81,18 +80,23 @@ public class GdkGraphics extends Graphics native void initStateUnlocked (GtkComponentPeer component); native void initState (int width, int height); native void initFromImage (GtkImage image); - native void copyState (GdkGraphics g); + native void nativeCopyState (GdkGraphics g); + + /** + * A cached instance that is used by {@link #create} in order to avoid + * massive allocation of graphics contexts. + */ + GdkGraphics cached = null; + + /** + * A link to the parent context. This is used in {@link #dispose} to put + * this graphics context into the cache. + */ + GdkGraphics parent = null; GdkGraphics (GdkGraphics g) { - color = g.color; - xorColor = g.xorColor; - font = g.font; - if (font == null) - font = new Font ("Dialog", Font.PLAIN, 12); - clip = new Rectangle (g.clip); - component = g.component; - + parent = g; copyState (g); } @@ -162,12 +166,54 @@ public class GdkGraphics extends Graphics public native void copyArea(int x, int y, int width, int height, int dx, int dy); - public Graphics create () + /** + * Creates a copy of this GdkGraphics instance. This implementation can + * reuse a cached instance to avoid massive instantiation of Graphics objects + * during painting. + * + * @return a copy of this graphics context + */ + public Graphics create() + { + GdkGraphics copy = cached; + if (copy == null) + copy = new GdkGraphics(this); + else + { + copy.copyState(this); + cached = null; + } + return copy; + } + + public native void nativeDispose(); + + /** + * Disposes this graphics object. This puts this graphics context into the + * cache of its parent graphics if there is one. + */ + public void dispose() { - return new GdkGraphics (this); + if (parent != null) + { + parent.cached = this; + parent = null; + } + else + nativeDispose(); } - public native void dispose(); + /** + * This is called when this object gets finalized by the garbage collector. + * In addition to {@link Graphics#finalize()} this calls nativeDispose() to + * make sure the native resources are freed before the graphics context is + * thrown away. + */ + public void finalize() + { + super.finalize(); + nativeDispose(); + } public boolean drawImage (Image img, int x, int y, Color bgcolor, ImageObserver observer) @@ -248,9 +294,8 @@ public class GdkGraphics extends Graphics public void drawString (String str, int x, int y) { drawString(getFontPeer(), str, x, y); - } + } - public void drawString (AttributedCharacterIterator ci, int x, int y) { throw new Error ("not implemented"); @@ -419,4 +464,23 @@ public class GdkGraphics extends Graphics translateNative (x, y); } + + /** + * Copies over the state of another GdkGraphics to this instance. This is + * used by the {@link #GdkGraphics(GdkGraphics)} constructor and the + * {@link #create()} method. + * + * @param g the GdkGraphics object to copy the state from + */ + private void copyState(GdkGraphics g) + { + color = g.color; + xorColor = g.xorColor; + font = g.font; + if (font == null) + font = new Font ("Dialog", Font.PLAIN, 12); + clip = new Rectangle (g.clip); + component = g.component; + nativeCopyState(g); + } } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java index c9ed301..195304d 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkGraphics2D.java @@ -180,11 +180,14 @@ public class GdkGraphics2D extends Graphics2D else fg = new Color(g.fg.getRGB()); - if (g.bg.getAlpha() != -1) - bg = new Color(g.bg.getRed(), g.bg.getGreen(), g.bg.getBlue(), - g.bg.getAlpha()); - else - bg = new Color(g.bg.getRGB()); + if (g.bg != null) + { + if (g.bg.getAlpha() != -1) + bg = new Color(g.bg.getRed(), g.bg.getGreen(), g.bg.getBlue(), + g.bg.getAlpha()); + else + bg = new Color(g.bg.getRGB()); + } if (g.clip == null) clip = null; @@ -1088,6 +1091,8 @@ public class GdkGraphics2D extends Graphics2D public void setBackground(Color c) { + if (c == null) + c = Color.WHITE; bg = c; } diff --git a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java index 85cb1e4..054ebaa 100644 --- a/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java +++ b/libjava/classpath/gnu/java/awt/peer/gtk/GdkPixbufDecoder.java @@ -47,6 +47,7 @@ import java.awt.image.ImageConsumer; import java.awt.image.ImageProducer; import java.awt.image.Raster; import java.awt.image.RenderedImage; +import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.io.InputStream; @@ -102,6 +103,11 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder 0x00ff0000, 0x0000ff00, 0x000000ff); + public GdkPixbufDecoder (DataInput datainput) + { + super (datainput); + } + public GdkPixbufDecoder (InputStream in) { super (in); @@ -630,7 +636,14 @@ public class GdkPixbufDecoder extends gnu.java.awt.image.ImageDecoder boolean ignoreMetadata) { super.setInput(input, seekForwardOnly, ignoreMetadata); - dec = new GdkPixbufDecoder((InputStream) getInput()); + Object get = getInput(); + if (get instanceof InputStream) + dec = new GdkPixbufDecoder((InputStream) get); + else if (get instanceof DataInput) + dec = new GdkPixbufDecoder((DataInput) get); + else + throw new IllegalArgumentException("input object not supported: " + + get); } public BufferedImage read(int imageIndex, ImageReadParam param) diff --git a/libjava/classpath/gnu/java/beans/encoder/ArrayPersistenceDelegate.java b/libjava/classpath/gnu/java/beans/encoder/ArrayPersistenceDelegate.java new file mode 100644 index 0000000..12d757e --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ArrayPersistenceDelegate.java @@ -0,0 +1,153 @@ +/* ArrayPersistenceDelegate.java - A PersistenceDelegate that handles arrays. + 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 gnu.java.beans.encoder; + +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; +import java.beans.Statement; + +import java.lang.reflect.Array; +import java.util.HashMap; + +public class ArrayPersistenceDelegate extends PersistenceDelegate +{ + private static final HashMap NULL_VALUES = new HashMap(); + + static + { + NULL_VALUES.put(Boolean.TYPE, Boolean.FALSE); + NULL_VALUES.put(Byte.TYPE, Byte.valueOf((byte) 0)); + NULL_VALUES.put(Short.TYPE, Short.valueOf((short) 0)); + NULL_VALUES.put(Integer.TYPE, Integer.valueOf(0)); + NULL_VALUES.put(Long.TYPE, Long.valueOf(0)); + NULL_VALUES.put(Float.TYPE, Float.valueOf(0.0f)); + NULL_VALUES.put(Double.TYPE, Double.valueOf(0.0)); + } + + protected Expression instantiate(Object oldInstance, Encoder out) + { + Class type = oldInstance.getClass().getComponentType(); + + // oldInstance is expected to be an array, then + // getClass().getComponentType() should lead + // to its component type. + assert (type != null); + + // Not handling primitive types in a special way here + // causes that Class.forName("int") is built as an Expression + // later which would cause an exception if executed. A special + // handling to avoid the execution for primitive types can be + // java.beans.Encoder.writeExpression() . + return new Expression( + oldInstance, + Array.class, + "newInstance", + new Object[] { + type, + new Integer(Array.getLength(oldInstance)) }); + } + + protected void initialize(Class type, Object oldInstance, Object newInstance, + Encoder out) + { + int length = Array.getLength(oldInstance); + + // Compares the array value against a prototypical + // null value of the array's component type in order to skip + // writing the default values of an array. + + // Note: I have no idea why the persistence delegate for arrays writes + // an Expression that reads the value and then writes a Statement that sets + // the value. However it turned out that object arrays work better with the + // get-Expression and primitive array work fine with the set-Statement. + + type = type.getComponentType(); + if (type.isPrimitive()) + { + Object nullValue = NULL_VALUES.get(type); + + for (int i = 0; i < length; i++) + { + Object oldValue = Array.get(oldInstance, i); + + if (!oldValue.equals(nullValue)) + { + out.writeExpression(new Expression(Array.class, "get", + new Object[] { oldInstance, + Integer.valueOf(i), + })); + + out.writeStatement(new Statement(Array.class, "set", + new Object[] { + oldInstance, + Integer.valueOf(i), + oldValue + })); + } + } + + } + else + { + + for (int i = 0; i < length; i++) + { + Object oldValue = Array.get(oldInstance, i); + + if (oldValue != null) + { + out.writeExpression(new Expression(Array.class, "get", + new Object[] { oldInstance, + Integer.valueOf(i), + })); + + out.writeStatement(new Statement(Array.class, "set", + new Object[] { + oldInstance, + Integer.valueOf(i), + oldValue + })); + } + } + } + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/ClassPersistenceDelegate.java b/libjava/classpath/gnu/java/beans/encoder/ClassPersistenceDelegate.java new file mode 100644 index 0000000..7b0656a --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ClassPersistenceDelegate.java @@ -0,0 +1,80 @@ +/* ClassPersistenceDelegate.java - A PersistenceDelegate for the Class type. + 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 gnu.java.beans.encoder; + +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; + +/** <p>The <code>ClassPersistenceDelegate</code> creates + * <code>Expression</code> instances which denote class resolutions.</p> + * + * <p>The class resolution is always the last step when serializing a tree + * of objects. Due to the recursive nature of the algorithm we need a way + * to end the recursion. This is achieved by the implementation of this + * {@link instantiate} method. Arbitrary classes are described with a call + * to <code>Class.forName</code>. However for the <code>Class</code> class + * we call <code>getClass()</code> on a <code>String.class</code> instance. + * This in turn lead to the resolution of the String class which is always + * encoded as <code>"".getClass()</code>. Finally the <code>Encoder</code> + * treats strings in a special way so that the recursion ends here. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class ClassPersistenceDelegate extends PersistenceDelegate +{ + + protected Expression instantiate(Object oldInstance, Encoder out) + { + Class oldClass = (Class) oldInstance; + + // Due to the special handling of String instances in the Encoder + // this Expression does not lead to further class resolutions. + if (oldClass == String.class) + return new Expression(oldClass, "", "getClass", null); + + // This Expression will lead to the class resolution of String.class. + if (oldClass == Class.class) + return new Expression(oldClass, String.class, "getClass", null); + + // This Expression will lead to the class resolution of Class.class. + return new Expression(oldClass, Class.class, "forName", + new Object[] { oldClass.getName() }); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/CollectionPersistenceDelegate.java b/libjava/classpath/gnu/java/beans/encoder/CollectionPersistenceDelegate.java new file mode 100644 index 0000000..f1375d2 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/CollectionPersistenceDelegate.java @@ -0,0 +1,84 @@ +/* CollectionPersistenceDelegate.java - A PersistenceDelegate for Collection subclasses. + 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 gnu.java.beans.encoder; + +import java.util.Collection; +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; +import java.beans.Statement; + +import java.util.Iterator; + +/** <p>A <code>PersistenceDelegate</code> implementation that calls + * the no-argument constructor to create the Collection instance and + * uses an iterator to add all the objects it reaches through it.</p> + * + * <p>It is used for <code>Set</code> and <code>List</code> + * implementations.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class CollectionPersistenceDelegate extends PersistenceDelegate +{ + + protected Expression instantiate(Object oldInstance, Encoder out) + { + return new Expression( + oldInstance, + oldInstance.getClass(), + "new", + null); + } + + protected void initialize(Class type, Object oldInstance, Object newInstance, + Encoder out) + { + Iterator ite = ((Collection) oldInstance).iterator(); + + while (ite.hasNext()) + { + out.writeStatement(new Statement(oldInstance, "add", + new Object[] { ite.next() })); + + } + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/Context.java b/libjava/classpath/gnu/java/beans/encoder/Context.java new file mode 100644 index 0000000..9126d49 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/Context.java @@ -0,0 +1,88 @@ +/* Context.java -- Provides calling context information to ScannerStates. + 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 gnu.java.beans.encoder; + +/** A <code>Contect</code> object describes the current state + * and the call number while processing the original object + * tree in the {@link ScanEngine}. + * + * <p>The class allows to distinguish the different calling states + * and is neccessary for the child element skipping feature of + * the {@link GenericScannerState}.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class Context +{ + private String state; + + private int call; + + Context(String newState, int newCall) + { + state = newState; + call = newCall; + } + + public int hashCode() + { + int hc = 7; + hc = 31 * hc + state.hashCode(); + hc = 31 * hc + call; + + return hc; + } + + public boolean equals(Object o) + { + if (!(o instanceof Context)) + return false; + + Context that = (Context) o; + + return state.equals(that.state) + && call == that.call; + } + + public String toString() + { + return "Context [state=" + state + ", call=" + call + "]"; + } +} diff --git a/libjava/classpath/gnu/java/beans/encoder/GenericScannerState.java b/libjava/classpath/gnu/java/beans/encoder/GenericScannerState.java new file mode 100644 index 0000000..3c3f8a3 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/GenericScannerState.java @@ -0,0 +1,257 @@ +/* GenericScannerState.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 gnu.java.beans.encoder; + +import java.util.HashMap; + +import gnu.java.beans.encoder.elements.ArrayInstantiation; +import gnu.java.beans.encoder.elements.Array_Get; +import gnu.java.beans.encoder.elements.Array_Set; +import gnu.java.beans.encoder.elements.ClassResolution; +import gnu.java.beans.encoder.elements.Element; +import gnu.java.beans.encoder.elements.List_Get; +import gnu.java.beans.encoder.elements.List_Set; +import gnu.java.beans.encoder.elements.MethodInvocation; +import gnu.java.beans.encoder.elements.NullObject; +import gnu.java.beans.encoder.elements.ObjectInstantiation; +import gnu.java.beans.encoder.elements.ObjectReference; +import gnu.java.beans.encoder.elements.PrimitiveInstantiation; +import gnu.java.beans.encoder.elements.StaticFieldAccess; +import gnu.java.beans.encoder.elements.StaticMethodInvocation; +import gnu.java.beans.encoder.elements.StringReference; + +/** + * This class is a {@link ScannerState} implementation that creates + * suitable {@link gnu.java.beans.encoder.elements.Element} instances + * for each transition variant. + * + * <p>Furthermore it can optionally skip a certain number of child + * elements. The algorithm can cope with the fact that one + * <code>GenericScannerState</code> instance may be called at + * different levels of recursions.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +class GenericScannerState extends ScannerState +{ + private int skipElements, initialSkipElements; + + final Root root; + + HashMap skipValues; + + GenericScannerState(Root newRoot) + { + root = newRoot; + } + + GenericScannerState(Root root, int skipElements) + { + this(root); + this.skipElements = initialSkipElements = skipElements; + + if (skipElements > 0) + skipValues = new HashMap(); + } + + protected void enterImpl(Context ctx) + { + if (skipValues != null) + { + Integer skip = (Integer) skipValues.get(ctx); + + if (skip == null) + { + skip = Integer.valueOf(initialSkipElements); + skipValues.put(ctx, skip); + } + + skipElements = skip.intValue(); + } + } + + void methodInvocation(String methodName) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new MethodInvocation(methodName)); + } + + void staticMethodInvocation(String className, String methodName) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new StaticMethodInvocation(className, methodName)); + } + + void staticFieldAccess(String className, String fieldName) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new StaticFieldAccess(className, fieldName)); + } + + void classResolution(String className) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new ClassResolution(className)); + } + + void objectInstantiation(String className, ObjectId objectId) + { + if (skipValues != null && skipElements > 0) + return; + + Element elem = new ObjectInstantiation(className); + elem.initId(objectId); + + root.addChild(elem); + } + + void primitiveInstantiation(String primitiveName, String valueAsString) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new PrimitiveInstantiation(primitiveName, valueAsString)); + } + + void objectArrayInstantiation(String arrayClassName, String lengthAsString, + ObjectId objectId) + { + if (skipValues != null && skipElements > 0) + return; + + Element elem = new ArrayInstantiation(arrayClassName, lengthAsString); + elem.initId(objectId); + + root.addChild(elem); + } + + void primitiveArrayInstantiation(String arrayClassName, String lengthAsString, + ObjectId objectId) + { + objectArrayInstantiation(arrayClassName, lengthAsString, objectId); + } + + void arraySet(String indexAsString) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new Array_Set(indexAsString)); + } + + void arrayGet(String indexAsString) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new Array_Get(indexAsString)); + } + + void listGet() + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new List_Get()); + } + + void listSet() + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new List_Set()); + } + + void nullObject() + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new NullObject()); + } + + void stringReference(String string) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new StringReference(string)); + } + + void objectReference(ObjectId id) + { + if (skipValues != null && skipElements > 0) + return; + + root.addChild(new ObjectReference(id)); + } + + void end() + { + if (skipValues != null) + { + if (skipElements > 0) + skipElements--; + else + { + // Finishes the Element we are constructing. + root.end(); + } + skipValues.put(context(), Integer.valueOf(skipElements)); + } + else + root.end(); + + } + + void enter() + { + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/IgnoringScannerState.java b/libjava/classpath/gnu/java/beans/encoder/IgnoringScannerState.java new file mode 100644 index 0000000..054f1f0 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/IgnoringScannerState.java @@ -0,0 +1,133 @@ +/* IgnoringScannerState.java -- A ScannerState that does nothing. + 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 gnu.java.beans.encoder; + +/** A special {@link ScannerState} implementation that ignores all child + * elements. + * + * <p>Consider the call hierarchy: + * <code> + * methodInvocation + * objectInstantiation + * classResolution* + * objectInstantiation + * classResolution + * </code> + * </p> + * + * <p>When the ignoring state is active one can filter the elements of + * one level. One has to set up the state machine that a transition + * via "class resolution" from a state that was reached via "object + * instantation" reaches an <code>IgnoringScannerState</code>.</p> + * + * <p>Setting the default successor of a <code>IgnoringScannerState</code> + * to itself causes all elements of the call hierarchy to be skipped + * until another state is reached by going back.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +class IgnoringScannerState extends ScannerState +{ + + void methodInvocation(String methodName) + { + } + + void staticMethodInvocation(String className, String methodName) + { + } + + void staticFieldAccess(String className, String fieldName) + { + } + + void classResolution(String className) + { + } + + void objectInstantiation(String className, ObjectId objectId) + { + } + + void primitiveInstantiation(String primitiveName, String valueAsString) + { + } + + void objectArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId) + { + } + + void primitiveArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId) + { + } + + void arraySet(String indexAsString) + { + } + + void arrayGet(String indexAsString) + { + } + + void listGet() + { + } + + void listSet() + { + } + + void nullObject() + { + } + + void stringReference(String string) + { + } + + void objectReference(ObjectId id) + { + } + + void end() + { + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/MapPersistenceDelegate.java b/libjava/classpath/gnu/java/beans/encoder/MapPersistenceDelegate.java new file mode 100644 index 0000000..84cdce9 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/MapPersistenceDelegate.java @@ -0,0 +1,81 @@ +/* MapPersistenceDelegate.java -- A PersistenceDelegate for Map subclasses. + + 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 gnu.java.beans.encoder; + +import java.util.Map; +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; +import java.beans.Statement; + +import java.util.Iterator; + +/** + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class MapPersistenceDelegate extends PersistenceDelegate +{ + + protected Expression instantiate(Object oldInstance, Encoder out) + { + return new Expression( + oldInstance, + oldInstance.getClass(), + "new", + null); + } + + protected void initialize(Class type, Object oldInstance, Object newInstance, + Encoder out) + { + Map map = (Map) oldInstance; + Iterator ite = map.keySet().iterator(); + + while (ite.hasNext()) + { + Object key = ite.next(); + out.writeStatement(new Statement(oldInstance, "put", + new Object[] { key, map.get(key) })); + + } + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/ObjectId.java b/libjava/classpath/gnu/java/beans/encoder/ObjectId.java new file mode 100644 index 0000000..eca5c3d --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ObjectId.java @@ -0,0 +1,132 @@ +/* ObjectId.java -- Simple object identification mechanism for XML encoding. + 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 gnu.java.beans.encoder; + +import java.util.HashMap; + +/** + * <p> + * ObjectId provides an object identification mechanism which gives each object + * a name in the form <code><class><Nameindex></code>. + * </p> + * + * <p> + * Each id can be in an unused state which means that only one instance of the + * object is in use and a special id is not needed. Certain {@link + * gnu.java.beans.encoder.elements.Element} subclasses use this feature to find + * out whether they write the "id" attribute or not. + * </p> + * <p> + * An <code>ObjectId</code> instance is typically given to multiple objects. + * The second user should then invoke the {@link #init} method to generate the + * identification string and bring the id in the 'used' state. + * </p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class ObjectId +{ + /** + * Stores the index an object of a specific type should be given. + */ + private static HashMap nameIndices = new HashMap(); + + private String id; + + private Class klass; + + ObjectId(Class klass) + { + this.klass = klass; + } + + public boolean isUnused() + { + return id == null; + } + + public String toString() + { + return (id != null) ? id : "<unused id>"; + } + + /** + * <p> + * Generates a simple Id by concatenating a class name with a self-increasing + * number. + * </p> + */ + public void init() + { + assert (klass != null); + + if (id != null) + return; + + Integer count = (Integer) nameIndices.get(klass); + if (count == null) + { + count = Integer.valueOf(0); + } + + if (klass.isArray()) + { + Class ct = klass.getComponentType(); + if (ct == Boolean.TYPE) + id = "booleanArray" + count.intValue(); + else if (ct == Byte.TYPE) + id = "byteArray" + count.intValue(); + else if (ct == Short.TYPE) + id = "shortArray" + count.intValue(); + else if (ct == Integer.TYPE) + id = "intArray" + count.intValue(); + else if (ct == Long.TYPE) + id = "longArray" + count.intValue(); + else if (ct == Float.TYPE) + id = "floatArray" + count.intValue(); + else if (ct == Double.TYPE) + id = "doubleArray" + count.intValue(); + } + else + id = klass.getName() + count.intValue(); + + nameIndices.put(klass, Integer.valueOf(count.intValue() + 1)); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/PrimitivePersistenceDelegate.java b/libjava/classpath/gnu/java/beans/encoder/PrimitivePersistenceDelegate.java new file mode 100644 index 0000000..8cb3705 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/PrimitivePersistenceDelegate.java @@ -0,0 +1,74 @@ +/* PrimitivePersistenceDelegate.java + -- A PersistenceDelegate for primitive data types. + 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 gnu.java.beans.encoder; + +import java.beans.Encoder; +import java.beans.Expression; +import java.beans.PersistenceDelegate; + +/** + * A shared PersistenceDelegate implementation for all primitive types. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class PrimitivePersistenceDelegate extends PersistenceDelegate +{ + + protected Expression instantiate(Object oldInstance, Encoder out) + { + // The implementation relies on the fact that every primitive + // wrapper class has a constructor accepting a String argument. + // By using these constructors creating a primitive instance + // depends on the String class only. + return new Expression(oldInstance, oldInstance.getClass(), "new", + new Object[] { oldInstance.toString() }); + } + + protected void initialize(Class type, Object oldInstance, Object newInstance, Encoder out) + { + // This is a hack to make serializing primitive arrays work correctly. + // Instead of modifying an existing primitive instance to make it equal + // with another instance (which is not possible because primitives are + // immutable) we create a new instance. This is against the specification + // of the initialize method but make things work fine. + out.writeExpression(new Expression(oldInstance, oldInstance.getClass(), "new", + new Object[] { oldInstance.toString() })); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/ReportingScannerState.java b/libjava/classpath/gnu/java/beans/encoder/ReportingScannerState.java new file mode 100644 index 0000000..fb6e061 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ReportingScannerState.java @@ -0,0 +1,131 @@ +/* ReportingScannerState.java -- A state for debugging purposes. + 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 gnu.java.beans.encoder; + +/** + * A <code>ScannerState</code> implementation that prints useful details + * about its arguments. Use it when the XML encoding does not work correctly + * and you want to find out how things relate to each other. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +class ReportingScannerState extends ScannerState +{ + + void methodInvocation(String methodName) + { + System.out.println("methodInvocation: " + methodName + "()"); + } + + void staticMethodInvocation(String className, String methodName) + { + System.out.println("staticMethodInvocation: " + className + "." + methodName + "()"); + } + + void staticFieldAccess(String className, String fieldName) + { + System.out.println("staticFieldAccess: " + className + "." + fieldName); + } + + void classResolution(String className) + { + System.out.println("classResolution: " + className); + } + + void objectInstantiation(String className, ObjectId objectId) + { + System.out.println("objectInstantiation: " + className); + } + + void primitiveInstantiation(String primitiveName, String valueAsString) + { + System.out.println("primitiveInstantiation: (" + primitiveName + ") " + valueAsString); + } + + void objectArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId) + { + System.out.println("objectArrayInstantiation: new " + arrayClassName + "[" + lengthAsString + "]"); + } + + void primitiveArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId) + { + System.out.println("primitiveArrayInstantiation: new " + arrayClassName + "[" + lengthAsString + "]"); + } + + void arraySet(String indexAsString) + { + System.out.println("arraySet: " + indexAsString); + } + + void arrayGet(String indexAsString) + { + System.out.println("arrayGet: " + indexAsString); + } + + void listGet() + { + System.out.println("listGet"); + } + + void listSet() + { + System.out.println("listSet"); + } + + void nullObject() + { + System.out.println("nullObject"); + } + + void stringReference(String string) + { + System.out.println("stringReference: " + string); + } + + void objectReference(ObjectId id) + { + System.out.println("objectReference: " + id); + } + + void end() + { + System.out.println("-close"); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/Root.java b/libjava/classpath/gnu/java/beans/encoder/Root.java new file mode 100644 index 0000000..f4eade1 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/Root.java @@ -0,0 +1,198 @@ +/* Root.java -- The root of an object tree. + 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 gnu.java.beans.encoder; + +import java.beans.XMLEncoder; +import java.util.Iterator; +import java.util.Stack; + +import gnu.java.beans.encoder.elements.Element; + +/** <p><code>Root</code> provides a simple interface to a tree of + * objects.</p> + * + * <p>Using an instance of this class a logical representation of + * the real object tree that is serialized can be built. When the + * actual data should be written as XML <code>Root</code> and + * {@link gnu.java.beans.encoder.elements.Element} class can provide + * context information which is used to write the best fitting + * XML representation.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class Root +{ + private Stack parents = new Stack(); + + private Element rootElement, current; + + private boolean started; + + public Root() + { + rootElement = current = new RootElement(); + } + + /** <p>Adds another child element to the tree.</p> + * + * <p>The new element automatically becomes the current + * element.</p> + * + * @param elem The new child element. + */ + public void addChild(Element elem) + { + current.addChild(elem); + + parents.push(current); + current = elem; + } + + /** + * <p>Marks that the end of the current element + * is reached and that no more childs are added to + * it.</p> + * + * <p>The behavior is to return to the nearest parent + * element.</p> + */ + public void end() + { + current = (Element) parents.pop(); + } + + /** + * <p>Goes back to the nearest parent element but + * deletes the just created child.</p> + * + * <p>This is used if something went wrong while + * processing the child element's {@link java.beans.Expression} + * or {@link java.beans.Statement}.</p> + * + */ + public void deleteLast() + { + current = (Element) parents.pop(); + + current.removeLast(); + } + + /** + * <p>Traverses the elements in the object tree + * and creates their XML representation in the output + * stream of the given {@link Writer}.</p> + * + * <p>Finally the <code>Writer</code> is flushed.</p> + * + * @param writer The Writer instance that generates the XML representation. + */ + public void traverse(Writer writer) + { + if (!started) + { + writer.writePreamble(); + rootElement.writeStart(writer); + } + started = true; + + traverse(writer, rootElement.iterator()); + + rootElement.clear(); + + writer.flush(); + } + + /** Writes the closing element and closes the {@link Writer} + * + * @param writer The Writer instance that generates the XML representation. + */ + public void close(Writer writer) + { + rootElement.writeEnd(writer); + writer.close(); + } + + /** Recursively traverses the object tree. + * + * @param writer The Writer instance that generates the XML representation. + * @param ite An Iterator returning Element instances. + */ + private void traverse(Writer writer, Iterator ite) + { + while (ite.hasNext()) + { + Element e = (Element) ite.next(); + e.writeStart(writer); + + traverse(writer, e.iterator()); + + e.writeEnd(writer); + + e.clear(); + } + } + + /** <p>A special Element implementation that represents the + * encoder's context.</p> + * + * <p>This element is written only once per Writer.</p> + * + * <p>It is assumed that this element is never empty to simplify + * the implementation.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org); + * + */ + static class RootElement extends Element + { + public void writeStart(Writer writer) + { + writer.write("java", new String[] { "version", "class" }, + new String[] { System.getProperty("java.version"), + XMLEncoder.class.getName() }, false); + } + + public void writeEnd(Writer writer) + { + writer.writeEnd(false); + } + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/ScanEngine.java b/libjava/classpath/gnu/java/beans/encoder/ScanEngine.java new file mode 100644 index 0000000..edf07d7 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ScanEngine.java @@ -0,0 +1,860 @@ +/* ScanEngine.java + -- Scans the input and generates an object tree that can be written as XML. + 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 gnu.java.beans.encoder; + +import java.beans.Expression; +import java.beans.Statement; +import java.io.OutputStream; +import java.lang.reflect.Array; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Stack; + +/** <p>The <code>ScanEngine</code> is the main class of the backend of the + * XML persistence algorithm. It scans {@link java.beans.Expression} and + * {@link java.beans.Statement} instances and some raw objects via the + * {@link #writeObject} method and feeds it to a state machine. The + * state machine then constructs and object tree which is finally + * written as XML by a {@link Writer} implementation.</p> + * + * <p>How does it work?</p> + * <p>The <code>ScanEngine</code> sits below the {@link java.beans.XMLEncoder} + * class and is called by it exclusively. The <code>XMLEncoder</code> sends + * interpretive data by invoking {@link #writeExpression}, {@link #writeStatement} + * and {@link #writeObject}. The invocations of <code>writeExpression</code> and + * <code>writeStatement</code> are usually nested into each other and provide + * more information then necessary to generate the XML representation. + * Furthermore the meaning of certain <code>Expressions</code> differs + * depending on the enclosing elements or the inner elements have to be + * simply discarded.</p> + * + * <p>To cope with this state dependant nature the <code>ScanEngine</code> + * contains a state machine which is programmed statically (no adjustments are + * needed, all <code>ScanEngine</code> engines use the same setup). The + * <code>ScanEngine</code>'s job is to decode the <code>Expression</code>s, + * <code>Statement</code>s and certain objects (namely <code>String</code>, + * <code>null</code> objects and instances which are repeatedly provided to + * the encoder) into 13 low-level (event) methods, which denote the meaning of the + * argument. For example an <code>Expression</code> can be an array + * instantiation which provokes a call to {@link arrayInstantiation} or + * it can be a class resolution leading to a call to {@link #classResolution}. + * For the state machione the 13 methods are the distinct way to transit + * from one state to another. Whenever the <code>ScanEngine</code> calls + * one of the event methods the current's state successor for that event + * is fetched from the state machine configuration, the successpr becomes + * the current state and then the event method is called in the new current + * state. The last step allows the state instance to do something meaningful + * to the object tree.</p> + * + * <p>The state machine knows the concept of returning to the previous + * state. This is done using a stack of states which is popped every + * time a call to <code>writeStatement</code>, <code>writeExpression</code> + * in the <code>XMLEncoder</code> ends by calling the {@link #end} method. + * Note that due to the inheritance relationship of <code>Encoder</code> + * and <code>XMLEncoder</code> it is impossible for the + * <code>ScanEngine</code> itself to decide when an expression or statement + * ended. This can only be done in case of {@link #writeObject} calls because + * they are not nested.</p> + * + * <p>When the XML persistence mechanism reaches an object twice (and more) + * it should generate an XML element using the "idref" attribute and add + * an "id" attribute to its first instantiation. This complicates things a bit + * because the first instantiation will always be part of the object tree + * as some {@link gnu.java.beans.encoder.elements.Element} subclass instance when the + * second and further objects accesses are written. Therefore the {@link ObjectId} + * class was introduced which is shared between all the object tree elements + * and has the notion of an "unused" state meaning that no identification + * is needed. The relationship between an object and its <code>ObjectId</code> + * instance is stored in the <code>ScanEngine</code> and gets cleared whenever + * the {@link #flush} method is called. This method also writes the currently + * built object tree and generates the XML representation.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class ScanEngine +{ + + /** Change this to true to let the ScanEngine print state transition + * information. + */ + boolean DEBUG = false; + + /** + * Stores the scanner engine states as values and their names as keys. + */ + HashMap states = new HashMap(); + + /** + * Stores former scanner state and makes it possible to come back to them. + */ + Stack parents = new Stack(); + + /** + * The currently active scanner state. + */ + ScannerState current; + + /** + * The root of an object tree that is later written to XML. + */ + Root root; + + /** + * The Writer used to generate the XML output. + */ + Writer writer; + + /** Stores the relationship between objects and their {@link ObjectId} instance. + */ + IdentityHashMap objects = new IdentityHashMap(); + + public ScanEngine(OutputStream os) + { + // TODO: Provide another Writer implementation (e.g. one that does not use + // the XML APIs at all). + writer = new StAXWriter(os); + root = new Root(); + + final ScannerState start = current = new GenericScannerState(root);; + ScannerState conf; + + // Use the ReportingScannerState to debug serialization issues. + register(ScannerState.DEFAULT_STATE_NAME, new IgnoringScannerState()); + + register("start", start); + + // Special dead-end state where all transitions are ignored. + register("ignoreAll", new IgnoringScannerState()) + .setDefaultSuccessor("ignoreAll"); + + // Object reference, string reference, null object + start.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple"); + start.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple"); + start.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple"); + register("simple", new GenericScannerState(root)) + .setDefaultSuccessor("ignoreAll"); + + // Class resolution. + start.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0"); + register("classRes0", + new GenericScannerState(root)).setDefaultSuccessor("ignoreAll"); + + // Object instantiation. + start.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, + "newObj0"); + conf = register("newObj0", new GenericScannerState(root)); + conf.setDefaultSuccessor("ignoreAll"); + + // Simply use the start state to encode method invocations inside of + // objects. + conf.putSuccessor(ScannerState.TRANSITION_METHOD_INVOCATION, "start"); + + // Primitive instantiations. + start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "newPrimitive0"); + register("newPrimitive0", + new GenericScannerState(root)).setDefaultSuccessor("ignoreAll"); + + // Object arrays use the ARRAY_GET transition to create setting the + // array values. + start.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION, + "newObjectArray"); + conf = register("newObjectArray", new GenericScannerState(root)); + conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "newOArrayGet"); + conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "ignoreAll"); + + // Get here when a value is set in the array. + register("newOArrayGet", + conf = new GenericScannerState(root)); + + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "newOArrayGet_ignoreFirstInteger"); + + // "newArrayGet_ignoreFirstInteger" is set up mostly identical like the "start" + // state. Otherwise things would not behave the same when done inside + // arrays. + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple"); + conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple"); + conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple"); + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "newObj0"); + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION, + "newPrimitiveArray"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION, + "newObjectArray"); + + conf = register("newOArrayGet_ignoreFirstInteger", + new GenericScannerState(root, 1)); + + // In non-int primitive arrays class resolutions can happen + // but they should be ignored. + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll"); + + // Spurious object and string references occur when setting array + // elements. This suppresses them. + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll"); + + conf.setDefaultSuccessor("start"); + + // Primitive arrays use the ARRAY_SET transition to create setting the + // array values. This turned out to be the only working solution. + // When primitive arrays were handled by ARRAY_GET the values in boolean + // arrays were always skipped. + start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION, + "newPrimitiveArray"); + conf = register("newPrimitiveArray", new GenericScannerState(root)); + conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "newPArraySet"); + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "ignoreAll"); + + conf = register("newPArraySet", new GenericScannerState(root)); + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "newPArraySet_ignoreFirstInteger"); + + // Primitive arrays ignore all kinds of non-primitive object information. + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, + "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ingoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION, + "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION, + "ignoreAll"); + + conf = register("newPArraySet_ignoreFirstInteger", + new GenericScannerState(root, 1)); + + // In non-int primitive arrays class resolutions can happen + // but they should be ignored. + conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll"); + + // Spurious object and string references occur when setting array + // elements. This suppresses them. + conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION, + "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll"); + conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll"); + conf.setDefaultSuccessor("start"); + + } + + /** Registers a <code>ScannerState</code> under a certain name. + * + * @param name Name of the state + * @param state The <code>ScannerState</code> instance. + * @return The second argument. + */ + private ScannerState register(String name, ScannerState state) + { + state.init(name); + + states.put(name, state); + + return state; + } + + /** Generates or returns an id for the given object which can be activated + * later if the object is suitable. + * + * <p>Objects are unsuitable if they are an instance of a primitive wrapper + * or String.</p> + * + * @param value The object to retrieve an id for. + * @return The id for the object or <code>null</code>. + */ + private ObjectId retrieveId(Object value) + { + Class valueClass = value.getClass(); + ObjectId id = null; + + // Although multiple accesses to Class objects are not handled + // through ids we generate one for them, too. This allows us to detect + // second time references to such objects in the writeObject method + // and handle them in a special way. + if (valueClass != String.class + && valueClass.getSuperclass() != Number.class + && valueClass != Boolean.class) + { + if ((id = (ObjectId) objects.get(value)) == null) + { + id = new ObjectId(valueClass); + objects.put(value, id); + } + } + + return id; + } + + /** Scans the argument and calls one of event methods. See + * the introduction of this class for details. + * + * @param expr The expression to serialize. + */ + public void writeExpression(Expression expr) + { + String methodName = expr.getMethodName(); + Object[] args = expr.getArguments(); + Object target = expr.getTarget(); + Object value = null; + + try + { + value = expr.getValue(); + } + catch (Exception e) + { + throw (InternalError) + new InternalError( + "The Expression's value should be available at this point.") + .initCause(e); + } + + // TODO: What if the value is null? + ObjectId id; + Class valueClass = value.getClass(); + + if (target == Array.class) + { + if (methodName.equals("newInstance")) + { + id = retrieveId(value); + + Class ct = (Class) args[0]; + + if (ct.isPrimitive() || ct == Boolean.class || ct == Byte.class + || ct == Short.class || ct == Integer.class || ct == Long.class + || ct == Float.class || ct == Double.class) + primitiveArrayInstantiation(ct.getName(), + args[1].toString(), + id); + else + objectArrayInstantiation(ct.getName(), + args[1].toString(), + id); + + return; + } + else if (methodName.equals("get")) + { + arrayGet(args[1].toString()); + + // The encoder does not call the ScanEngine + // when an object is serialized that we already know. + // We test for this situation and insert the object reference + // manually. + // Since there is already a workaround for the Class class + // in writeObject we have to except it from this behavior. + id = (ObjectId) objects.get(value); + if (id != null && valueClass != Class.class) + { + objectReference(id); + end(); + } + + return; + } + else if (methodName.equals("set")) + { + arraySet(args[1].toString()); + return; + } + } + + id = retrieveId(value); + + if (target instanceof Class) + { + if (methodName.equals("new")) + { + Class targetClass = (Class) target; + + // All primitive types have short-hand forms for their + // constructors. + if (valueClass == Boolean.class) + primitiveInstantiation("boolean", args[0].toString()); + else if (valueClass == Byte.class) + primitiveInstantiation("byte", args[0].toString()); + else if (valueClass == Short.class) + primitiveInstantiation("short", args[0].toString()); + else if (valueClass == Integer.class) + primitiveInstantiation("int", args[0].toString()); + else if (valueClass == Long.class) + primitiveInstantiation("long", args[0].toString()); + else if (valueClass == Float.class) + primitiveInstantiation("float", args[0].toString()); + else if (valueClass == Double.class) + primitiveInstantiation("double", args[0].toString()); + else + objectInstantiation(targetClass.getName(), id); + + return; + } + else if (value instanceof Class) + { + String className = ((Class) value).getName(); + + // At this point we know that some *static* method will be called. + + if (methodName.equals("forName")) + { + // However "Class.forName" represents class resolution and has a + // special syntax. + classResolution(className); + return; + } + else if (methodName.equals("getField")) + { + // The same goes for "Class.getField". + // Note: The name of the wanted field is given in + // the argument array. + staticFieldAccess(className, args[0].toString()); + return; + } + else + { + // If nothing fits it is just a static method + // invocation which we decode as such. + staticMethodInvocation(className, methodName); + return; + } + } + } + else if (target instanceof List) + { + // Special behavior for indexed get and set method for list-style + // classes. + // The arguments are in the args array but we need them as subelements. + if (methodName.equals("get")) + { + listGet(); + return; + } + else if (methodName.equals("set")) + { + listSet(); + return; + } + } + + // If nothing else could be used then this is a normal + // method invocation. + methodInvocation(methodName); + } + + /** + * Ends the current state and returns to the last one. + */ + public void end() + { + current.end(); + + if (DEBUG) System.err.print("back from " + current.getName()); + + ScannerState oldCurrent = current; + current = (ScannerState) parents.pop(); + + if (DEBUG) System.err.println(" to " + current.getName()); + } + + /** + * Returns to the last state and deletes the last element in the object tree. + */ + public void revoke() + { + ScannerState oldCurrent = current; + current = (ScannerState) parents.pop(); + + root.deleteLast(); + } + + /** Scans the argument and calls one of event methods. See + * the introduction of this class for details. + * + * @param stmt The statement to serialize. + */ + public void writeStatement(Statement stmt) + { + // This is a simplified version of writeExpression. Everything + // that would not create something that is embedded in a <void> tag + // is left out (instantiation, getters, ...). + // TODO: Is this the right thing to do? + + String methodName = stmt.getMethodName(); + Object target = stmt.getTarget(); + Object[] args = stmt.getArguments(); + + if (target == Array.class && methodName.equals("set")) + { + arraySet(args[1].toString()); + return; + } + + if (target instanceof List) + { + if (methodName.equals("set")) + { + listSet(); + return; + } + } + + // If nothing else could be used then this is a normal + // method invocation. + methodInvocation(methodName); + } + + /** Scans the argument and calls one of event methods. See + * the introduction of this class for details. + * + * @param o The object to serialize. + */ + public boolean writeObject(Object o) + { + ObjectId id = null; + + if (o == null) + { + // Handle null objects which have a special syntax. + nullObject(); + end(); + } + else if (o.getClass() == String.class) + { + // Handle strings which are treated extremely special + // in the encoder (they are never converted into a + // Expression). + stringReference((String) o); + end(); + } + else if ((id = (ObjectId) objects.get(o)) != null) + { + // Multiple references to a Class object do not generate + // an object reference but we use the id to detect that + // situation. + if (o.getClass() == Class.class) + { + classResolution(((Class) o).getName()); + end(); + return false; + } + + // If our object has a corresponding ObjectId instance + // then generate an objectReference. This will + // initialize the id (= brings it in the "used" state) + // when this is the first referal. + objectReference(id); + end(); + return false; + } + + return true; + } + + /** + * Writes the currently constructed object tree out as + * XML and clears the object to {@link ObjectId} relations. + */ + public void flush() + { + // Make all references unreachable. That means we have to generate + // new object ids. + objects.clear(); + + root.traverse(writer); + } + + /** Writes the final bits if the object tree and closes the stream + * afterwards. + */ + public void close() + { + flush(); + root.close(writer); + } + + /** + * Does a transition from one state to another using the given event. + * + * <p>This involves saving the current state, retrieving it's + * successor and setting it as the current state.</p> + * + * @param transition One of {@link ScannerStates]'s transition constants. + */ + private void transition(int transition) + { + parents.push(current); + + String stateName = current.getSuccessor(transition); + + if (DEBUG) + { + System.err.println("from state: " + current.getName() + "\n\troute: " + + ScannerState.transitionNames[transition] + + "\n\t\tto state: " + + stateName); + } + + ScannerState newState = (ScannerState) states.get(stateName); + + newState.enter(new Context(current.getName(), current.getCalls())); + + assert (newState != null) : "State '" + stateName + "' was not defined."; + + current = newState; + } + + /** Event method that denotes a (non-static) method invocation. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param methodName The name of the method which is called. + */ + void methodInvocation(String methodName) + { + transition(ScannerState.TRANSITION_METHOD_INVOCATION); + + current.methodInvocation(methodName); + } + + /** Event method that denotes a static method invocation. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param methodName The name of the method which is called. + * @param className The name of the class in which the method is called. + */ + void staticMethodInvocation(String className, String methodName) + { + transition(ScannerState.TRANSITION_STATIC_METHOD_INVOCATION); + + current.staticMethodInvocation(className, methodName); + } + + /** Event method that denotes the retrieval of a static field's value. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param fieldName The name of the field whose value is retrieved. + * @param className The name of the class in which the method is called. + */ + void staticFieldAccess(String className, String fieldName) + { + transition(ScannerState.TRANSITION_STATIC_FIELD_ACCESS); + + current.staticFieldAccess(className, fieldName); + } + + /** Event method that denotes the resolution of a class. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param className The name of the class in which the method is called. + */ + void classResolution(String className) + { + transition(ScannerState.TRANSITION_CLASS_RESOLUTION); + + current.classResolution(className); + } + + /** Event method that denotes the instantiation of an object. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param className The name of the class in which the method is called. + * @param objectId An ObjectId instance which can be activated later. + */ + void objectInstantiation(String className, ObjectId objectId) + { + transition(ScannerState.TRANSITION_OBJECT_INSTANTIATION); + + current.objectInstantiation(className, objectId); + } + + /** Event method that denotes the instantiation of a primitive. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param primitiveName One of "boolean, "byte", "short", "int", "long" + * , "float" or "double" + * @param valueAsString The value of the primitive as a String. + */ + void primitiveInstantiation(String primitiveName, String valueAsString) + { + transition(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION); + + current.primitiveInstantiation(primitiveName, valueAsString); + } + + /** Event method that denotes the instantiation of an object array. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param arrayClassName The array's class name. + * @param objectId An ObjectId instance which can be activated later. + * @param lengthAsString The array's length as String. + */ + void objectArrayInstantiation(String arrayClassName, String lengthAsString, + ObjectId objectId) + { + transition(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION); + + current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId); + } + + /** Event method that denotes the instantiation of a primitive array. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param arrayClassName The array's class name. + * @param objectId An ObjectId instance which can be activated later. + * @param lengthAsString The array's length as String. + */ + void primitiveArrayInstantiation(String arrayClassName, String lengthAsString, + ObjectId objectId) + { + transition(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION); + + current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId); + } + + /** Event method that denotes the setting of a value in an array. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param indexAsString The index to as a String. + */ + void arraySet(String indexAsString) + { + transition(ScannerState.TRANSITION_ARRAY_SET); + + current.arraySet(indexAsString); + } + + /** Event method that denotes the retrieval of a value in an array. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + * + * @param indexAsString The index to as a String. + */ + void arrayGet(String indexAsString) + { + transition(ScannerState.TRANSITION_ARRAY_GET); + + current.arrayGet(indexAsString); + } + + /** Event method that denotes the setting of a value in a list. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + */ + void listSet() + { + transition(ScannerState.TRANSITION_LIST_SET); + + current.listSet(); + } + + /** Event method that denotes the retrieval of a value in a list. + * + * <p>More details about this method can be found in this + * class' introduction.</p> + */ + void listGet() + { + transition(ScannerState.TRANSITION_LIST_GET); + + current.listGet(); + } + + /** Event method that denotes the null value. + */ + void nullObject() + { + transition(ScannerState.TRANSITION_NULL_OBJECT); + + current.nullObject(); + } + + /** Event method that denotes a string. + * + * @param string The string that should be written. + */ + void stringReference(String string) + { + transition(ScannerState.TRANSITION_STRING_REFERENCE); + + current.stringReference(string); + } + + /** Event method that denotes a reference to an existing object. + * + * @param id The ObjectId to be used. + */ + void objectReference(ObjectId id) + { + transition(ScannerState.TRANSITION_OBJECT_REFERENCE); + + current.objectReference(id); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/ScannerState.java b/libjava/classpath/gnu/java/beans/encoder/ScannerState.java new file mode 100644 index 0000000..888478a --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/ScannerState.java @@ -0,0 +1,236 @@ +/* ScannerState.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 gnu.java.beans.encoder; + +import java.util.HashMap; + +/** <p>Provides the infrastructure for the state machine and the transition + * mechanism.</p> + * + * <p>Each states knows a set of successor. There can be one successor for + * every transition variant. Furthermore a state knows about a default + * successor which is taken when there is no special setup for a + * transition.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public abstract class ScannerState +{ + + static final int TRANSITION_METHOD_INVOCATION = 0; + + static final int TRANSITION_STATIC_METHOD_INVOCATION = 1; + + static final int TRANSITION_STATIC_FIELD_ACCESS = 2; + + static final int TRANSITION_CLASS_RESOLUTION = 3; + + static final int TRANSITION_OBJECT_INSTANTIATION = 4; + + static final int TRANSITION_PRIMITIVE_INSTANTIATION = 5; + + static final int TRANSITION_OBJECT_ARRAY_INSTANTIATION = 6; + + static final int TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION = 7; + + static final int TRANSITION_ARRAY_SET = 8; + + static final int TRANSITION_ARRAY_GET = 9; + + static final int TRANSITION_LIST_SET = 10; + + static final int TRANSITION_LIST_GET = 11; + + static final int TRANSITION_NULL_OBJECT = 12; + + static final int TRANSITION_STRING_REFERENCE = 13; + + static final int TRANSITION_OBJECT_REFERENCE = 14; + + static final int TRANSITION_FIRST = 0; + + static final int TRANSITION_LAST = 14; + + static final String DEFAULT_STATE_NAME = "default"; + + String defaultSuccessor = DEFAULT_STATE_NAME; + + static String[] transitionNames = { "METHOD_INVOCATION", "STATIC_METHOD_INVOCATION", + "STATIC_FIELD_ACCESS", "CLASS_RESOLUTION", + "OBJECT_INSTANTIATION", + "PRIMITIVE_INSTANTIATION", "OBJECT_ARRAY_INSTANTIATION", + "PRIMITIVE_ARRAY_INSTANTIATION", + "ARRAY_SET", "ARRAY_GET", "LIST_SET", "LIST_GET", + "NULL_OBJECT", "STRING_REFERENCE", "OBJECT_REFERENCE" }; + + /** + * Stores the transition setup as the relation + * transition->successor's state name. + */ + HashMap transitions = new HashMap(); + + int calls; + + Context context; + + String name; + + final void init(String newName) + { + assert (name == null); + + name = newName; + } + + final String getName() + { + return name; + } + + final void enter(Context ctx) + { + calls++; + context = ctx; + + enterImpl(ctx); + } + + protected void enterImpl(Context ctx) + { + } + + final Context context() + { + return context; + } + + final int getCalls() + { + return calls; + } + + /** + * <p>Stores a successor's state name for a certain transition.</p> + * + * <p>This method is only used at the configuration time of the state + * machine.</p> + * + * @param transition One of the transition constants. + * @param stateName The state name of the successor. + */ + final void putSuccessor(int transition, String stateName) + { + assert (transition >= TRANSITION_FIRST && transition <= TRANSITION_LAST) : + "Transition identifier '" + transition + "' is unknown."; + + transitions.put(new Integer(transition), stateName); + } + + /** <p>Retrieves a the state name of a successor for the given transition + * constant.</p> + * + * <p>Returns the default successor's state name if no special setup was + * prepared.</p> + * + * @param transition One of the transition constants. + * @return The state name of the successor. + */ + final String getSuccessor(int transition) + { + String state = (String) transitions.get(new Integer(transition)); + + return (state == null) ? defaultSuccessor : state; + } + + /** + * Sets the name for the default successor state. + * + * @param newDefaultSuccessor The default successor's state name. + */ + final void setDefaultSuccessor(String newDefaultSuccessor) + { + defaultSuccessor = newDefaultSuccessor; + } + + abstract void methodInvocation(String methodName); + + abstract void staticMethodInvocation(String className, String methodName); + + abstract void staticFieldAccess(String className, String fieldName); + + abstract void classResolution(String className); + + abstract void objectInstantiation(String className, ObjectId objectId); + + abstract void primitiveInstantiation(String primitiveName, + String valueAsString); + + abstract void objectArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId); + + abstract void primitiveArrayInstantiation(String arrayClassName, String lengthAsString, ObjectId objectId); + + abstract void arraySet(String indexAsString); + + abstract void arrayGet(String indexAsString); + + abstract void listGet(); + + abstract void listSet(); + + abstract void nullObject(); + + abstract void stringReference(String string); + + abstract void objectReference(ObjectId id); + + /** + * <p>A special event that does not provoke a direct transition.</p> + * + * <p>Instead the transition is done by the <code>ScanEngine</code>: It goes + * back to the previous state and just uses this method to inform the state + * about this happening.</p> + */ + abstract void end(); + + void enter() + { + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/StAXWriter.java b/libjava/classpath/gnu/java/beans/encoder/StAXWriter.java new file mode 100644 index 0000000..fdb5f7d4 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/StAXWriter.java @@ -0,0 +1,233 @@ +/* StAXWriter.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 gnu.java.beans.encoder; + +import java.io.OutputStream; + +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +/** A {@link Writer} implementation based on the StAX API. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class StAXWriter implements Writer +{ + XMLStreamWriter writer; + + int indent = 0; + + public StAXWriter(OutputStream os) + { + try + { + XMLOutputFactory factory = XMLOutputFactory.newInstance(); + writer = factory.createXMLStreamWriter(os); + } + catch (XMLStreamException se) + { + throw (InternalError) + new InternalError( + "Could not instantiate a streaming XML writer.") + .initCause(se); + } + + } + + public void flush() + { + if (writer != null) + { + try + { + writer.flush(); + } + catch (XMLStreamException xse) + { + // TODO: find out + } + } + + } + + public void close() + { + if (writer != null) + { + try + { + writer.close(); + } + catch (XMLStreamException xse) + { + // TODO: find out + } + writer = null; + } + + } + + public void writePreamble() + { + try + { + writer.writeStartDocument("UTF-8", "1.0"); + } + catch (XMLStreamException xmlse) + { + + } + } + + public void writeEnd(boolean wasEmpty) + { + try + { + indent -= 2; + + if (wasEmpty) + return; + + for (int i = 0; i < indent; i++) + writer.writeCharacters(" "); + + writer.writeEndElement(); + + writer.writeCharacters("\n"); + } + catch (XMLStreamException xmlse) + { + + } + } + + public void writeEndNoChildren() + { + try + { + writer.writeEndElement(); + writer.writeCharacters("\n"); + } + catch (XMLStreamException xmlse) + { + + } + } + + public void write(String tagName, boolean empty) + { + write(tagName, null, null, null, empty); + } + + public void write(String tagName, String value) + { + write(tagName, value, null, null, value == null); + } + + public void writeNoChildren(String tagName, String value) + { + try + { + for (int i = 0; i < indent; i++) + writer.writeCharacters(" "); + + writer.writeStartElement(tagName); + + writer.writeCharacters(value); + } + catch (XMLStreamException xmlse) + { + + } + } + + public void write(String tagName, String attributeName, + String attributeValue, boolean empty) + { + write(tagName, null, new String[] { attributeName }, + new String[] { attributeValue }, empty); + } + + public void write(String tagName, String value, String[] attributeNames, + String[] attributeValues, boolean empty) + { + try + { + for (int i = 0; i < indent; i++) + + writer.writeCharacters(" "); + + if (empty) + writer.writeEmptyElement(tagName); + else + writer.writeStartElement(tagName); + + if (attributeNames != null) + for (int i = 0; i < attributeNames.length; i++) + writer.writeAttribute(attributeNames[i], attributeValues[i]); + + writer.writeCharacters("\n"); + + indent += 2; + + if (value != null) + { + for (int i = 0; i < indent; i++) + writer.writeCharacters(" "); + + writer.writeCharacters(value); + + writer.writeCharacters("\n"); + } + } + catch (XMLStreamException xmlse) + { + + } + } + + public void write(String tagName, String[] attributeNames, + String[] attributeValues, boolean empty) + { + write(tagName, null, attributeNames, attributeValues, empty); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/Writer.java b/libjava/classpath/gnu/java/beans/encoder/Writer.java new file mode 100644 index 0000000..57203d2 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/Writer.java @@ -0,0 +1,174 @@ +/* Writer.java -- Writing interface for XML persistence. + 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 gnu.java.beans.encoder; + +/** A <code>Writer</code> represents a simplified interface to an XML + * writer that is used for the XML persistence mechanism. + * + * <p>Its sole purpose is to allow multiple backends which may remove + * the need to have certain APIs in the classpath. Eg. it is possible + * to write a stripped down XML Writer that does not rely on SAX, StAX + * or DOM APIs.</p> + * + * <p>The caller may assume that every action is done immediately. However + * it is possible that the underlying implementation uses buffering streams. + * To make sure the data is written call the {@link flush} method.</p> + * + * <p>The <code>Writer</code> implementation should care about the formatting + * of the XML stream making it possible to generate three types of formats using + * a special method invocation chain.</p> + * + * <p>Write + * <code> + * <element/> + * </code> + * by issuing <code>write("element", true)</code> (or any of the other + * write-variants that allows specifying the <code>isEmpty</code> argument) + * and <code>writeEnd(true)</code>.</p> + * + * <p>Write + * <code> + * <element>body</element> + * </code> + * by issuing <code>writeNoChildren("element", "body")</code> and <code>writeNoChildrenEnd()</code>.</p> + * + * <p> + * Write + * <code> + * <element> + * <child1/> + * <child2/> + * ... + * <element/> + * </code> + * by issuing <code>write("element", false)</code> (or any of the other + * write-variants that allows specifying the <code>isEmpty</code> argument) + * and <code>writeEnd(false)</code>.</p> + * + * <p>Note: It is important that the values of <code>isEmpty</code> and + * <code>wasEmpty</code> match. Otherwise strange things might happen to + * the layout.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public interface Writer +{ + // TODO: This interface's design is not the best. Feel free to + // improve it as you like. + + /** Writes the XML preamble. */ + void writePreamble(); + + /** Writes the end of an XML tag. + * + * <p>If your tag has not generated any body text or child + * elements provide <code>true</code> as the argument to generate + * more space efficient variant of the tag.>/p> + * + * @param wasEmpty Whether the tag was empty or not. + */ + void writeEnd(boolean wasEmpty); + + /** Writes an XML tag without any attributes. + * + * @param tagName The name of the tag to write. + * @param empty Whether the element has child elements. + */ + void write(String tagName, boolean empty); + + /** Writes an XML tag with one attribute name and value. + * + * @param tagName The name of the tag to write. + * @param attributeName The name of attribute. + * @param attributeValue The attribute's value. + * @param empty Whether the element has child elements. + */ + void write(String tagName, String attributeName, String attributeValue, boolean empty); + + /** Writes an XML tag with multiple attributes and a body text. + * + * @param tagName The name of the tag to write. + * @param value The element's body content. + * @param attributeNames A set of attribute names. + * @param attributeValues A set of attribute values. + * @param empty Whether the element has child elements. + */ + void write(String tagName, String value, String[] attributeNames, + String[] attributeValues, boolean empty); + + /** Writes an XML tag with multiple attributes without a body text. + * + * @param tagName The name of the tag to write. + * @param attributeNames A set of attribute names. + * @param attributeValues A set of attribute values. + * @param empty Whether the element has child elements. + */ + void write(String tagName, String[] attributeNames, String[] attributeValues, boolean empty); + + /** Writes an XML tag with no attributes but with a body text + * that may have child elements. + * + * @param tagName The name of the tag to write. + * @param value The element's body content. + */ + void write(String tagName, String value); + + /** Writes an XML tag with no attributes but with a body text + * that does not have child elements. + * + * @param tagName The name of the tag to write. + * @param value The element's body content. + */ + void writeNoChildren(String tagName, String value); + + /** Writes the end of an XML tag that has no child elements. + * + * <p>Must be used in combination with {@link writeNoChildren} only.</p> + */ + void writeEndNoChildren(); + + /** Forces the implementation to write some data. + */ + void flush(); + + /** Closes the writer. + */ + void close(); +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/ArrayInstantiation.java b/libjava/classpath/gnu/java/beans/encoder/elements/ArrayInstantiation.java new file mode 100644 index 0000000..a9aef89 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/ArrayInstantiation.java @@ -0,0 +1,74 @@ +/* ArrayInstantiation.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.ObjectId; +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the instantiation of an array. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class ArrayInstantiation extends Element +{ + final String className; + + final String lengthAsString; + + public ArrayInstantiation(String newClassName, String newLengthAsString) + { + className = newClassName; + lengthAsString = newLengthAsString; + } + + public void writeStart(Writer writer) + { + ObjectId objectId = getId(); + if (objectId.isUnused()) + writer.write("array", new String[] { "class", "length" }, + new String[] { className, lengthAsString }, isEmpty()); + else + writer.write("array", new String[] { "id", "class", "length" }, + new String[] { objectId.toString(), className, + lengthAsString }, isEmpty()); + + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/Array_Get.java b/libjava/classpath/gnu/java/beans/encoder/elements/Array_Get.java new file mode 100644 index 0000000..ca2ce0f --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/Array_Get.java @@ -0,0 +1,62 @@ +/* Array_Get.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** + * Generates an XML element denoting the retrieval of an array value. + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public class Array_Get extends Element +{ + final String indexAsString; + + public Array_Get(String newIndexAsString) + { + indexAsString = newIndexAsString; + } + + public void writeStart(Writer writer) + { + writer.write("void", "index", indexAsString, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/Array_Set.java b/libjava/classpath/gnu/java/beans/encoder/elements/Array_Set.java new file mode 100644 index 0000000..0962320 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/Array_Set.java @@ -0,0 +1,57 @@ +/* Array_Set.java -- FIXME: briefly describe file purpose + 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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +public class Array_Set extends Element +{ + final String indexAsString; + + public Array_Set(String newIndexAsString) + { + indexAsString = newIndexAsString; + } + + public void writeStart(Writer writer) + { + writer.write("void", "index", indexAsString, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/ClassResolution.java b/libjava/classpath/gnu/java/beans/encoder/elements/ClassResolution.java new file mode 100644 index 0000000..8e640d1 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/ClassResolution.java @@ -0,0 +1,67 @@ +/* ClassResolution.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the resolution of a class. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class ClassResolution extends Element +{ + final String className; + + public ClassResolution(String newClassName) + { + className = newClassName; + } + + public void writeStart(Writer writer) + { + writer.writeNoChildren("class", className); + } + + public void writeEnd(Writer writer) + { + writer.writeEndNoChildren(); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/Element.java b/libjava/classpath/gnu/java/beans/encoder/elements/Element.java new file mode 100644 index 0000000..5681d2b --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/Element.java @@ -0,0 +1,157 @@ +/* Element.java -- Base class for object tree elements. + 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 gnu.java.beans.encoder.elements; + +import java.util.Iterator; +import java.util.LinkedList; + +import gnu.java.beans.encoder.ObjectId; +import gnu.java.beans.encoder.Writer; + +/** <code>Element</code> is the base class for the object tree elements. + * + * <p>It provides the neccessary infrastructure every element subclass + * needs in order to interact with the {@link gnu.java.beans.encoder.Root} + * class.</p> + * + * @author Robert Schuster (robertschuster@fsfe.org) + */ +public abstract class Element +{ + /** + * Stores the child elements. + */ + private LinkedList children = new LinkedList(); + + /** + * An optional ObjectId instance which is needed for certain subclasses + * only. + */ + private ObjectId objectId; + + /** Sets an {@link gnu.java.beans.encoder.ObjectId} instance in this + * <code>Element</code>. + * + * <p>This can only be done once.</p> + * + * @param objectId An ObjectId instance. + */ + public final void initId(ObjectId objectId) + { + assert (this.objectId == null); + assert (objectId != null); + + this.objectId = objectId; + } + + /** Adds a child element to this <code>Element</code>. + * + * @param elem The new child. + */ + public final void addChild(Element elem) + { + children.add(elem); + } + + /** Removes the child element added last. + */ + public final void removeLast() + { + children.removeLast(); + } + + /** Provides access to the child elements via an iterator. + * + * @return An iterator for the child elements. + */ + public final Iterator iterator(){ + return children.iterator(); + } + + /** Clears all the stored child elements. + * + */ + public final void clear() + { + children.clear(); + } + + /** Returns whether this element contains child elements. + * + * <p>This method is useful to decide which formatting variant + * for the XML element can be chosen.</p> + * + * @return Whether the element has child elements. + */ + public final boolean isEmpty() + { + return children.isEmpty(); + } + + /** Retrieves the element's {@link gnu.java.beans.encoder.ObjectId} instance + * if it has one. + * + * @return The ObjectId instance or <code>null</code>. + */ + public final ObjectId getId() + { + return objectId; + } + + /** Writes the opening XML tag. + * + * @param writer The writer to be used for XML writing. + */ + public abstract void writeStart(Writer writer); + + /** Writes the closing XML tag. + * + * <p>By default this does <code>writer.writeEnd(children.isEmpty())</code>. + * Override if neccessary, for example when using the + * {@link gnu.java.beans.encoder.Writer#writeNoChildren}</code> method + * variants. + * + * @param writer The writer to be used for XML writing. + */ + public void writeEnd(Writer writer) + { + writer.writeEnd(children.isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/List_Get.java b/libjava/classpath/gnu/java/beans/encoder/elements/List_Get.java new file mode 100644 index 0000000..e73afa8 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/List_Get.java @@ -0,0 +1,56 @@ +/* List_Get.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the retrieval of a list's element. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class List_Get extends Element +{ + + public void writeStart(Writer writer) + { + writer.write("object", "get"); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/List_Set.java b/libjava/classpath/gnu/java/beans/encoder/elements/List_Set.java new file mode 100644 index 0000000..03c73fd --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/List_Set.java @@ -0,0 +1,56 @@ +/* List_Set.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the setting of a list's element. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class List_Set extends Element +{ + + public void writeStart(Writer writer) + { + writer.write("object", "set"); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/MethodInvocation.java b/libjava/classpath/gnu/java/beans/encoder/elements/MethodInvocation.java new file mode 100644 index 0000000..d5b3174 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/MethodInvocation.java @@ -0,0 +1,62 @@ +/* MethodCall.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting a non-static method call. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class MethodInvocation extends Element +{ + final String methodName; + + public MethodInvocation(String newMethodName) + { + methodName = newMethodName; + } + + public void writeStart(Writer writer) + { + writer.write("void", "method", methodName, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/NullObject.java b/libjava/classpath/gnu/java/beans/encoder/elements/NullObject.java new file mode 100644 index 0000000..599c4d8 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/NullObject.java @@ -0,0 +1,61 @@ +/* NullObject.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the <code>null</code> value. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class NullObject extends Element +{ + + public void writeStart(Writer writer) + { + writer.write("null", true); + } + + public void writeEnd(Writer writer) + { + writer.writeEnd(true); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/ObjectInstantiation.java b/libjava/classpath/gnu/java/beans/encoder/elements/ObjectInstantiation.java new file mode 100644 index 0000000..692227d --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/ObjectInstantiation.java @@ -0,0 +1,68 @@ +/* ObjectInstantiation.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.ObjectId; +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting the instantiation of an object. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class ObjectInstantiation extends Element +{ + final String className; + + public ObjectInstantiation(String newClassName) + { + className = newClassName; + } + + public void writeStart(Writer writer) + { + ObjectId objectId = getId(); + if (objectId.isUnused()) + writer.write("object", "class", className, isEmpty()); + else + writer.write("object", new String[] { "id", "class" }, + new String[] { objectId.toString(), className }, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/ObjectReference.java b/libjava/classpath/gnu/java/beans/encoder/elements/ObjectReference.java new file mode 100644 index 0000000..a44c2ee --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/ObjectReference.java @@ -0,0 +1,68 @@ +/* StringInstantiation.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.ObjectId; +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting referencing an existing object. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class ObjectReference extends Element +{ + final ObjectId id; + + public ObjectReference(ObjectId newId) + { + id = newId; + + // Initializing the Id here is making sure it gets + // actually used. This step modifies the Id instance + // in other elements. + id.init(); + } + + public void writeStart(Writer writer) + { + writer.write("object", "idref", id.toString(), isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/PrimitiveInstantiation.java b/libjava/classpath/gnu/java/beans/encoder/elements/PrimitiveInstantiation.java new file mode 100644 index 0000000..db08edb --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/PrimitiveInstantiation.java @@ -0,0 +1,69 @@ +/* PrimitiveInstantiation.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting a primitive data value. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class PrimitiveInstantiation extends Element +{ + final String primitiveName; + + final String valueAsString; + + public PrimitiveInstantiation(String newPrimitiveName, String newValueAsString) + { + primitiveName = newPrimitiveName; + valueAsString = newValueAsString; + } + + public void writeStart(Writer writer) + { + writer.writeNoChildren(primitiveName, valueAsString); + } + + public void writeEnd(Writer writer) + { + writer.writeEndNoChildren(); + } +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/StaticFieldAccess.java b/libjava/classpath/gnu/java/beans/encoder/elements/StaticFieldAccess.java new file mode 100644 index 0000000..7ed935d --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/StaticFieldAccess.java @@ -0,0 +1,66 @@ +/* StaticFieldAccess.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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** Generates an XML element denoting a static method call. + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class StaticFieldAccess extends Element +{ + final String className; + + final String fieldName; + + public StaticFieldAccess(String newClassName, String newFieldName) + { + className = newClassName; + fieldName = newFieldName; + } + + public void writeStart(Writer writer) + { + writer.write("object", new String[] { "class", "field" }, + new String[] { className, fieldName }, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/StaticMethodInvocation.java b/libjava/classpath/gnu/java/beans/encoder/elements/StaticMethodInvocation.java new file mode 100644 index 0000000..40c46a5 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/StaticMethodInvocation.java @@ -0,0 +1,67 @@ +/* StaticMethodCall.java + -- A class denoting an XML element which makes up a static method call. + 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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +/** + * + * @author Robert Schuster (robertschuster@fsfe.org) + * + */ +public class StaticMethodInvocation extends Element +{ + final String className; + + final String methodName; + + public StaticMethodInvocation(String newClassName, String newMethodName) + { + className = newClassName; + methodName = newMethodName; + } + + public void writeStart(Writer writer) + { + writer.write("void", new String[] { "class", "method" }, + new String[] { className, methodName }, isEmpty()); + } + +} diff --git a/libjava/classpath/gnu/java/beans/encoder/elements/StringReference.java b/libjava/classpath/gnu/java/beans/encoder/elements/StringReference.java new file mode 100644 index 0000000..c368e65 --- /dev/null +++ b/libjava/classpath/gnu/java/beans/encoder/elements/StringReference.java @@ -0,0 +1,63 @@ +/* StringInstantiation.java + -- A class denoting an XML element which retrieves an array element. + 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 gnu.java.beans.encoder.elements; + +import gnu.java.beans.encoder.Writer; + +public class StringReference extends Element +{ + final String string; + + public StringReference(String newString) + { + string = newString; + } + + public void writeStart(Writer writer) + { + writer.writeNoChildren("string", string); + } + + public void writeEnd(Writer writer) + { + writer.writeEndNoChildren(); + } + +} diff --git a/libjava/classpath/gnu/java/net/CRLFInputStream.java b/libjava/classpath/gnu/java/net/CRLFInputStream.java index d0f9e8c..91fd840 100644 --- a/libjava/classpath/gnu/java/net/CRLFInputStream.java +++ b/libjava/classpath/gnu/java/net/CRLFInputStream.java @@ -128,7 +128,7 @@ public class CRLFInputStream in.reset(); if (i != -1) { - l = in.read(b, off, i + 1); // read to CR + l = in.read(b, off, (i + 1) - off); // read to CR in.read(); // skip LF b[i] = LF; // fix CR as LF } diff --git a/libjava/classpath/gnu/java/net/PlainDatagramSocketImpl.java b/libjava/classpath/gnu/java/net/PlainDatagramSocketImpl.java index 339b556..0fcd780 100644 --- a/libjava/classpath/gnu/java/net/PlainDatagramSocketImpl.java +++ b/libjava/classpath/gnu/java/net/PlainDatagramSocketImpl.java @@ -38,8 +38,6 @@ exception statement from your version. */ package gnu.java.net; -import gnu.classpath.Configuration; - import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocketImpl; @@ -64,20 +62,7 @@ import java.net.SocketException; */ public final class PlainDatagramSocketImpl extends DatagramSocketImpl { - // Static initializer to load native library - static - { - if (Configuration.INIT_LOAD_LIBRARY) - { - System.loadLibrary("javanet"); - } - } - - /** - * Option id for the IP_TTL (time to live) value. - */ - private static final int IP_TTL = 0x1E61; // 7777 - + /** * This is the actual underlying file descriptor */ @@ -98,6 +83,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl */ public PlainDatagramSocketImpl() { + // Nothing to do here. } protected void finalize() throws Throwable @@ -123,15 +109,48 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl * * @exception SocketException If an error occurs */ - protected synchronized native void bind(int port, InetAddress addr) - throws SocketException; + protected synchronized void bind(int port, InetAddress addr) + throws SocketException + { + VMPlainDatagramSocketImpl.bind(this, port, addr); + } /** * Creates a new datagram socket * * @exception SocketException If an error occurs */ - protected synchronized native void create() throws SocketException; + protected synchronized void create() throws SocketException + { + VMPlainDatagramSocketImpl.create(this); + } + + /** + * Connects to the remote address and port specified as arguments. + * + * @param addr The remote address to connect to + * @param port The remote port to connect to + * + * @exception SocketException If an error occurs + */ + protected void connect(InetAddress addr, int port) throws SocketException + { + VMPlainDatagramSocketImpl.connect(this, addr, port); + } + + /** + * Disconnects the socket. + * + * @since 1.4 + */ + protected void disconnect() + { + synchronized (this) + { + if (native_fd != -1) + close(); + } + } /** * Sets the Time to Live value for the socket @@ -142,7 +161,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl */ protected synchronized void setTimeToLive(int ttl) throws IOException { - setOption(IP_TTL, new Integer(ttl)); + setOption(VMPlainDatagramSocketImpl.IP_TTL, new Integer(ttl)); } /** @@ -154,7 +173,7 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl */ protected synchronized int getTimeToLive() throws IOException { - Object obj = getOption(IP_TTL); + Object obj = getOption(VMPlainDatagramSocketImpl.IP_TTL); if (! (obj instanceof Integer)) throw new IOException("Internal Error"); @@ -162,20 +181,6 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl return ((Integer) obj).intValue(); } - /** - * Sends a packet of data to a remote host - * - * @param addr The address to send to - * @param port The port to send to - * @param buf The buffer to send - * @param offset The offset of the data in the buffer to send - * @param len The length of the data to send - * - * @exception IOException If an error occurs - */ - private native void sendto (InetAddress addr, int port, - byte[] buf, int offset, int len) - throws IOException; /** * Sends a packet of data to a remote host @@ -186,12 +191,13 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl */ protected void send(DatagramPacket packet) throws IOException { - synchronized(SEND_LOCK) + if (native_fd != -1) { - sendto(packet.getAddress(), packet.getPort(), packet.getData(), - packet.getOffset(), packet.getLength()); - } - + synchronized(SEND_LOCK) + { + VMPlainDatagramSocketImpl.send(this, packet); + } + } } /** @@ -206,18 +212,10 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl { synchronized(RECEIVE_LOCK) { - receive0(packet); + VMPlainDatagramSocketImpl.receive(this, packet); } } - /** - * Native call to receive a UDP packet from the network - * - * @param packet The packet to fill in with the data received - * - * @exception IOException IOException If an error occurs - */ - private native void receive0(DatagramPacket packet) throws IOException; /** * Sets the value of an option on the socket @@ -227,8 +225,11 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl * * @exception SocketException If an error occurs */ - public synchronized native void setOption(int option_id, Object val) - throws SocketException; + public synchronized void setOption(int option_id, Object val) + throws SocketException + { + VMPlainDatagramSocketImpl.setOption(this, option_id, val); + } /** * Retrieves the value of an option on the socket @@ -239,13 +240,19 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl * * @exception SocketException If an error occurs */ - public synchronized native Object getOption(int option_id) - throws SocketException; + public synchronized Object getOption(int option_id) + throws SocketException + { + return VMPlainDatagramSocketImpl.getOption(this, option_id); + } /** * Closes the socket */ - protected synchronized native void close(); + protected synchronized void close() + { + VMPlainDatagramSocketImpl.close(this); + } /** * Gets the Time to Live value for the socket @@ -282,7 +289,10 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl * * @exception IOException If an error occurs */ - protected synchronized native void join(InetAddress addr) throws IOException; + protected synchronized void join(InetAddress addr) throws IOException + { + VMPlainDatagramSocketImpl.join(this,addr); + } /** * Leaves a multicast group @@ -291,7 +301,10 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl * * @exception IOException If an error occurs */ - protected synchronized native void leave(InetAddress addr) throws IOException; + protected synchronized void leave(InetAddress addr) throws IOException + { + VMPlainDatagramSocketImpl.leave(this, addr); + } /** * What does this method really do? @@ -308,14 +321,14 @@ public final class PlainDatagramSocketImpl extends DatagramSocketImpl } public void joinGroup(SocketAddress address, NetworkInterface netIf) + throws IOException { - throw new InternalError - ("PlainDatagramSocketImpl::joinGroup is not implemented"); + VMPlainDatagramSocketImpl.joinGroup(this, address, netIf); } public void leaveGroup(SocketAddress address, NetworkInterface netIf) + throws IOException { - throw new InternalError - ("PlainDatagramSocketImpl::leaveGroup is not implemented"); + VMPlainDatagramSocketImpl.leaveGroup(this, address, netIf); } } diff --git a/libjava/classpath/gnu/java/net/PlainSocketImpl.java b/libjava/classpath/gnu/java/net/PlainSocketImpl.java index 05221ff..47d05aa 100644 --- a/libjava/classpath/gnu/java/net/PlainSocketImpl.java +++ b/libjava/classpath/gnu/java/net/PlainSocketImpl.java @@ -39,17 +39,13 @@ exception statement from your version. */ package gnu.java.net; -import gnu.classpath.Configuration; - -import java.io.IOException; import java.io.InputStream; +import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.SocketException; import java.net.SocketImpl; -import java.net.SocketOptions; /** * Written using on-line Java Platform 1.2 API Specification, as well @@ -69,14 +65,6 @@ import java.net.SocketOptions; */ public final class PlainSocketImpl extends SocketImpl { - // Static initializer to load native library. - static - { - if (Configuration.INIT_LOAD_LIBRARY) - { - System.loadLibrary("javanet"); - } - } /** * The OS file handle representing the socket. @@ -125,10 +113,11 @@ public final class PlainSocketImpl extends SocketImpl } /** - * Default do nothing constructor + * Default do nothing constructor. */ public PlainSocketImpl() { + // Nothing to do here. } protected void finalize() throws Throwable @@ -142,6 +131,7 @@ public final class PlainSocketImpl extends SocketImpl } catch (IOException ex) { + // Nothing we can do about it. } } super.finalize(); @@ -158,121 +148,111 @@ public final class PlainSocketImpl extends SocketImpl * Integer. The option_id parameter is one of the defined constants in * this interface. * - * @param option_id The identifier of the option - * @param val The value to set the option to + * @param optionId The identifier of the option + * @param value The value to set the option to * - * @exception SocketException If an error occurs + * @throws SocketException if an error occurs */ - public native void setOption(int optID, Object value) throws SocketException; + public void setOption(int optionId, Object value) throws SocketException + { + VMPlainSocketImpl.setOption(this, optionId, value); + } /** * Returns the current setting of the specified option. The Object returned * will be an Integer for options that have integer values. The option_id * is one of the defined constants in this interface. * - * @param option_id The option identifier + * @param optionId the option identifier * - * @return The current value of the option + * @return the current value of the option * - * @exception SocketException If an error occurs + * @throws SocketException if an error occurs */ - public native Object getOption(int optID) throws SocketException; + public Object getOption(int optionId) throws SocketException + { + return VMPlainSocketImpl.getOption(this, optionId); + } - /** - * Flushes the input stream and closes it. If you read from the input stream - * after calling this method a <code>IOException</code> will be thrown. - * - * @throws IOException if an error occurs - */ - public native void shutdownInput() throws IOException; + public void shutdownInput() throws IOException + { + VMPlainSocketImpl.shutdownInput(this); + } - /** - * Flushes the output stream and closes it. If you write to the output stream - * after calling this method a <code>IOException</code> will be thrown. - * - * @throws IOException if an error occurs - */ - public native void shutdownOutput() throws IOException; + public void shutdownOutput() throws IOException + { + VMPlainSocketImpl.shutdownOutput(this); + } /** * Creates a new socket that is not bound to any local address/port and - * is not connected to any remote address/port. This will be created as - * a stream socket if the stream parameter is true, or a datagram socket - * if the stream parameter is false. + * is not connected to any remote address/port. The stream parameter will be + * ignored since PlainSocketImpl always is a stream socket. Datagram sockets + * are handled by PlainDatagramSocketImpl. * - * @param stream true for a stream socket, false for a datagram socket + * @param stream <code>true</code> for stream sockets, <code>false</code> for + * datagram sockets */ - protected synchronized native void create(boolean stream) throws IOException; + protected synchronized void create(boolean stream) throws IOException + { + VMPlainSocketImpl.create(this); + } /** * Connects to the remote hostname and port specified as arguments. * - * @param hostname The remote hostname to connect to - * @param port The remote port to connect to + * @param hostname the remote hostname to connect to + * @param port the remote port to connect to * - * @exception IOException If an error occurs + * @throws IOException If an error occurs */ - protected synchronized void connect(String host, int port) throws IOException + protected synchronized void connect(String hostname, int port) + throws IOException { - connect(InetAddress.getByName(host), port); + connect(InetAddress.getByName(hostname), port); } /** * Connects to the remote address and port specified as arguments. * - * @param addr The remote address to connect to - * @param port The remote port to connect to + * @param addr the remote address to connect to + * @param port the remote port to connect to * - * @exception IOException If an error occurs + * @throws IOException If an error occurs */ - protected native void connect(InetAddress addr, int port) throws IOException; + protected void connect(InetAddress addr, int port) throws IOException + { + VMPlainSocketImpl.connect(this, addr, port); + } /** * Connects to the remote socket address with a specified timeout. * - * @param timeout The timeout to use for this connect, 0 means infinite. + * @param address the remote address to connect to + * @param timeout the timeout to use for this connect, 0 means infinite. * - * @exception IOException If an error occurs + * @throws IOException If an error occurs */ - protected synchronized void connect(SocketAddress address, int timeout) throws IOException + protected synchronized void connect(SocketAddress address, int timeout) + throws IOException { - InetSocketAddress sockAddr = (InetSocketAddress) address; - InetAddress addr = sockAddr.getAddress(); - - if (addr == null) - throw new IllegalArgumentException("address is unresolved: " + sockAddr); - - int port = sockAddr.getPort(); - - if (timeout < 0) - throw new IllegalArgumentException("negative timeout"); - - Object oldTimeoutObj = null; - - try - { - oldTimeoutObj = this.getOption (SocketOptions.SO_TIMEOUT); - this.setOption (SocketOptions.SO_TIMEOUT, new Integer (timeout)); - connect (addr, port); - } - finally - { - if (oldTimeoutObj != null) - this.setOption (SocketOptions.SO_TIMEOUT, oldTimeoutObj); - } + VMPlainSocketImpl.connect(this, address, timeout); } /** * Binds to the specified port on the specified addr. Note that this addr * must represent a local IP address. **** How bind to INADDR_ANY? **** * - * @param addr The address to bind to - * @param port The port number to bind to + * @param addr the address to bind to + * @param port the port number to bind to * - * @exception IOException If an error occurs + * @throws IOException if an error occurs */ - protected synchronized native void bind(InetAddress addr, int port) - throws IOException; + protected synchronized void bind(InetAddress addr, int port) + throws IOException + { + VMPlainSocketImpl.bind(this, addr, port); + } /** * Starts listening for connections on a socket. The queuelen parameter @@ -282,10 +262,13 @@ public final class PlainSocketImpl extends SocketImpl * * @param queuelen The length of the pending connection queue * - * @exception IOException If an error occurs + * @throws IOException If an error occurs */ - protected synchronized native void listen(int queuelen) - throws IOException; + protected synchronized void listen(int queuelen) + throws IOException + { + VMPlainSocketImpl.listen(this, queuelen); + } /** * Accepts a new connection on this socket and returns in in the @@ -293,33 +276,44 @@ public final class PlainSocketImpl extends SocketImpl * * @param impl The SocketImpl object to accept this connection. */ - protected synchronized native void accept(SocketImpl impl) - throws IOException; + protected synchronized void accept(SocketImpl impl) + throws IOException + { + VMPlainSocketImpl.accept(this, impl); + } /** * Returns the number of bytes that the caller can read from this socket * without blocking. * - * @return The number of readable bytes before blocking + * @return the number of readable bytes before blocking * - * @exception IOException If an error occurs + * @throws IOException if an error occurs */ - protected native int available() throws IOException; + protected int available() throws IOException + { + return VMPlainSocketImpl.available(this); + } /** * Closes the socket. This will cause any InputStream or OutputStream * objects for this Socket to be closed as well. + * * <p> * Note that if the SO_LINGER option is set on this socket, then the * operation could block. + * </p> * - * @exception IOException If an error occurs + * @throws IOException if an error occurs */ - protected native void close() throws IOException; + protected void close() throws IOException + { + VMPlainSocketImpl.close(this); + } public void sendUrgentData(int data) { - throw new InternalError ("PlainSocketImpl::sendUrgentData not implemented"); + VMPlainSocketImpl.sendUrgendData(this, data); } /** @@ -327,22 +321,53 @@ public final class PlainSocketImpl extends SocketImpl * the connection. Reads up to len bytes of data into the buffer * buf starting at offset bytes into the buffer. * - * @return The actual number of bytes read or -1 if end of stream. + * @return the actual number of bytes read or -1 if end of stream. * - * @exception IOException If an error occurs + * @throws IOException if an error occurs + */ + protected int read(byte[] buf, int offset, int len) + throws IOException + { + return VMPlainSocketImpl.read(this, buf, offset, len); + } + + /** + * Internal method used by SocketInputStream for reading data from + * the connection. Reads and returns one byte of data. + * + * @return the read byte + * + * @throws IOException if an error occurs */ - protected native int read(byte[] buf, int offset, int len) - throws IOException; + protected int read() + throws IOException + { + return VMPlainSocketImpl.read(this); + } /** * Internal method used by SocketOuputStream for writing data to * the connection. Writes up to len bytes of data from the buffer * buf starting at offset bytes into the buffer. * - * @exception IOException If an error occurs + * @throws IOException If an error occurs + */ + protected void write(byte[] buf, int offset, int len) + throws IOException + { + VMPlainSocketImpl.write(this, buf, offset, len); + } + + /** + * Internal method used by SocketOuputStream for writing data to + * the connection. Writes up one byte to the socket. + * + * @throws IOException If an error occurs */ - protected native void write(byte[] buf, int offset, int len) - throws IOException; + protected void write(int data) throws IOException + { + VMPlainSocketImpl.write(this, data); + } /** * Returns an InputStream object for reading from this socket. This will @@ -356,7 +381,7 @@ public final class PlainSocketImpl extends SocketImpl { if (in == null) in = new SocketInputStream(); - + return in; } @@ -372,7 +397,7 @@ public final class PlainSocketImpl extends SocketImpl { if (out == null) out = new SocketOutputStream(); - + return out; } @@ -380,7 +405,7 @@ public final class PlainSocketImpl extends SocketImpl * This class contains an implementation of <code>InputStream</code> for * sockets. It in an internal only class used by <code>PlainSocketImpl</code>. * - * @author Nic Ferrier (nferrier@tapsellferrier.co.uk) + * @author Nic Ferrier <nferrier@tapsellferrier.co.uk> */ final class SocketInputStream extends InputStream @@ -412,13 +437,7 @@ public final class PlainSocketImpl extends SocketImpl */ public int read() throws IOException { - byte buf[] = new byte [1]; - int bytes_read = read(buf, 0, 1); - - if (bytes_read == -1) - return -1; - - return buf[0] & 0xFF; + return PlainSocketImpl.this.read(); } /** @@ -450,7 +469,7 @@ public final class PlainSocketImpl extends SocketImpl * <code>getOutputStream method</code>. It expects only to be used in that * context. * - * @author Nic Ferrier (nferrier@tapsellferrier.co.uk) + * @author Nic Ferrier <nferrier@tapsellferrier.co.uk> */ final class SocketOutputStream extends OutputStream @@ -476,8 +495,7 @@ public final class PlainSocketImpl extends SocketImpl */ public void write(int b) throws IOException { - byte buf[] = { (byte) b }; - write(buf, 0, 1); + PlainSocketImpl.this.write(b); } /** diff --git a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java index 466f3dd..a557c7d 100644 --- a/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java +++ b/libjava/classpath/gnu/java/nio/channels/FileChannelImpl.java @@ -1,5 +1,5 @@ /* FileChannelImpl.java -- - Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -301,8 +301,10 @@ public final class FileChannelImpl extends FileChannel else if (mode == MapMode.READ_WRITE || mode == MapMode.PRIVATE) { nmode = mode == MapMode.READ_WRITE ? '+' : 'c'; - if ((this.mode & (READ|WRITE)) != (READ|WRITE)) + if ((this.mode & WRITE) != WRITE) throw new NonWritableChannelException(); + if ((this.mode & READ) != READ) + throw new NonReadableChannelException(); } else throw new IllegalArgumentException ("mode: " + mode); diff --git a/libjava/classpath/gnu/java/nio/charset/Provider.java b/libjava/classpath/gnu/java/nio/charset/Provider.java index 3f25c59..01c2650 100644 --- a/libjava/classpath/gnu/java/nio/charset/Provider.java +++ b/libjava/classpath/gnu/java/nio/charset/Provider.java @@ -1,5 +1,5 @@ /* Provider.java -- - Copyright (C) 2002, 2005 Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,6 +39,8 @@ package gnu.java.nio.charset; import java.nio.charset.Charset; import java.nio.charset.spi.CharsetProvider; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -47,6 +49,11 @@ import java.util.Iterator; * Charset provider for the required charsets. Used by * {@link Charset#charsetForName} and * {@link Charset#availableCharsets}. * + * Note: This class is a privileged class, because it can be instantiated without + * requiring the RuntimePermission("charsetProvider"). There is a check in + * java.nio.charset.spi.CharsetProvider to skip the security check if the provider + * is an instance of this class. + * * @author Jesse Rosenstock * @author Robert Schuster (thebohemian@gmx.net) * @see Charset @@ -55,14 +62,6 @@ public final class Provider extends CharsetProvider { private static Provider singleton; - static - { - synchronized (Provider.class) - { - singleton = null; - } - } - /** * Map from charset name to charset canonical name. The strings * are all lower-case to allow case-insensitive retrieval of @@ -232,8 +231,16 @@ public final class Provider extends CharsetProvider public static synchronized Provider provider () { + // The default provider is safe to instantiate. if (singleton == null) - singleton = new Provider (); + singleton = (Provider) AccessController.doPrivileged + (new PrivilegedAction() + { + public Object run() + { + return new Provider(); + } + }); return singleton; } } diff --git a/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java b/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java index 873e9ec..6fd8b74 100644 --- a/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java +++ b/libjava/classpath/gnu/java/nio/charset/iconv/IconvProvider.java @@ -1,5 +1,5 @@ /* IconvProvider.java -- - Copyright (C) 2005 Free Software Foundation, Inc. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -48,20 +48,17 @@ import java.util.Vector; /** * Charset provider wrapping iconv. * + * Note: This class is a privileged class, because it can be instantiated without + * requiring the RuntimePermission("charsetProvider"). There is a check in + * java.nio.charset.spi.CharsetProvider to skip the security check if the provider + * is an instance of this class. + * * @author Sven de Marothy */ public final class IconvProvider extends CharsetProvider { private static IconvProvider singleton; - static - { - synchronized (IconvProvider.class) - { - singleton = null; - } - } - // Declaring the construtor public may violate the use of singleton. // But it must be public so that an instance of this class can be // created by Class.newInstance(), which is the case when this provider is diff --git a/libjava/classpath/gnu/java/rmi/server/UnicastRef.java b/libjava/classpath/gnu/java/rmi/server/UnicastRef.java index c1b871f..8097a04 100644 --- a/libjava/classpath/gnu/java/rmi/server/UnicastRef.java +++ b/libjava/classpath/gnu/java/rmi/server/UnicastRef.java @@ -47,6 +47,7 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.rmi.ConnectException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.server.ObjID; @@ -195,7 +196,7 @@ public RemoteCall newCall(RemoteObject obj, Operation[] op, int opnum, long hash conn = manager.getConnection(); } catch (IOException e1) { - throw new RemoteException("connection failed to host: " + manager.serverName, e1); + throw new ConnectException("connection failed to host: " + manager.serverName, e1); } //obj: useless? diff --git a/libjava/classpath/gnu/java/security/Engine.java b/libjava/classpath/gnu/java/security/Engine.java index b75de5c..4b6bd10 100644 --- a/libjava/classpath/gnu/java/security/Engine.java +++ b/libjava/classpath/gnu/java/security/Engine.java @@ -1,5 +1,5 @@ /* Engine -- generic getInstance method. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -130,7 +130,14 @@ public final class Engine Provider provider, Object[] initArgs) throws InvocationTargetException, NoSuchAlgorithmException { - if (service == null || algorithm == null + if (service != null) + service = service.trim(); + + if (algorithm != null) + algorithm = algorithm.trim(); + + if (service == null || service.length() == 0 + || algorithm == null || algorithm.length() == 0 || provider == null || initArgs == null) throw new IllegalArgumentException(); diff --git a/libjava/classpath/gnu/java/util/WeakIdentityHashMap.java b/libjava/classpath/gnu/java/util/WeakIdentityHashMap.java new file mode 100644 index 0000000..210a3d8 --- /dev/null +++ b/libjava/classpath/gnu/java/util/WeakIdentityHashMap.java @@ -0,0 +1,862 @@ +/* WeakIdentityHashMap -- an identity hashtable that keeps only weak references + to its keys, allowing the virtual machine to reclaim them + Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.util; + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A weak hash map has only weak references to the key. This means that it + * allows the key to be garbage collected if it is not used otherwise. If + * this happens, the entry will eventually disappear from the map, + * asynchronously. + * + * <p>Other strange behaviors to be aware of: The size of this map may + * spontaneously shrink (even if you use a synchronized map and synchronize + * it); it behaves as if another thread removes entries from this table + * without synchronization. The entry set returned by <code>entrySet</code> + * has similar phenomenons: The size may spontaneously shrink, or an + * entry, that was in the set before, suddenly disappears. + * + * <p>A weak hash map is not meant for caches; use a normal map, with + * soft references as values instead, or try {@link LinkedHashMap}. + * + * <p>The weak hash map supports null values and null keys. The null key + * is never deleted from the map (except explictly of course). The + * performance of the methods are similar to that of a hash map. + * + * <p>The value objects are strongly referenced by this table. So if a + * value object maintains a strong reference to the key (either direct + * or indirect) the key will never be removed from this map. According + * to Sun, this problem may be fixed in a future release. It is not + * possible to do it with the jdk 1.2 reference model, though. + * + * @author Jochen Hoenicke + * @author Eric Blake (ebb9@email.byu.edu) + * @author Jeroen Frijters + * + * @see HashMap + * @see WeakReference + * @see WeakHashMap + * @see IdentityHashMap + * @see LinkedHashMap + */ +public class WeakIdentityHashMap extends AbstractMap implements Map +{ + /** + * The default capacity for an instance of HashMap. + * Sun's documentation mildly suggests that this (11) is the correct + * value. + */ + private static final int DEFAULT_CAPACITY = 11; + + /** + * The default load factor of a HashMap. + */ + private static final float DEFAULT_LOAD_FACTOR = 0.75F; + + /** + * This is used instead of the key value <i>null</i>. It is needed + * to distinguish between an null key and a removed key. + */ + // Package visible for use by nested classes. + static final Object NULL_KEY = new Object(); + + /** + * The reference queue where our buckets (which are WeakReferences) are + * registered to. + */ + private final ReferenceQueue queue; + + /** + * The number of entries in this hash map. + */ + // Package visible for use by nested classes. + int size; + + /** + * The load factor of this WeakIdentityHashMap. This is the maximum ratio of + * size versus number of buckets. If size grows the number of buckets + * must grow, too. + */ + private float loadFactor; + + /** + * The rounded product of the capacity (i.e. number of buckets) and + * the load factor. When the number of elements exceeds the + * threshold, the HashMap calls <code>rehash()</code>. + */ + private int threshold; + + /** + * The number of structural modifications. This is used by + * iterators, to see if they should fail. This doesn't count + * the silent key removals, when a weak reference is cleared + * by the garbage collection. Instead the iterators must make + * sure to have strong references to the entries they rely on. + */ + // Package visible for use by nested classes. + int modCount; + + /** + * The entry set. There is only one instance per hashmap, namely + * theEntrySet. Note that the entry set may silently shrink, just + * like the WeakIdentityHashMap. + */ + private final class WeakEntrySet extends AbstractSet + { + /** + * Non-private constructor to reduce bytecode emitted. + */ + WeakEntrySet() + { + } + + /** + * Returns the size of this set. + * + * @return the set size + */ + public int size() + { + return size; + } + + /** + * Returns an iterator for all entries. + * + * @return an Entry iterator + */ + public Iterator iterator() + { + return new Iterator() + { + /** + * The entry that was returned by the last + * <code>next()</code> call. This is also the entry whose + * bucket should be removed by the <code>remove</code> call. <br> + * + * It is null, if the <code>next</code> method wasn't + * called yet, or if the entry was already removed. <br> + * + * Remembering this entry here will also prevent it from + * being removed under us, since the entry strongly refers + * to the key. + */ + WeakBucket.WeakEntry lastEntry; + + /** + * The entry that will be returned by the next + * <code>next()</code> call. It is <code>null</code> if there + * is no further entry. <br> + * + * Remembering this entry here will also prevent it from + * being removed under us, since the entry strongly refers + * to the key. + */ + WeakBucket.WeakEntry nextEntry = findNext(null); + + /** + * The known number of modification to the list, if it differs + * from the real number, we throw an exception. + */ + int knownMod = modCount; + + /** + * Check the known number of modification to the number of + * modifications of the table. If it differs from the real + * number, we throw an exception. + * @throws ConcurrentModificationException if the number + * of modifications doesn't match. + */ + private void checkMod() + { + // This method will get inlined. + cleanQueue(); + if (knownMod != modCount) + throw new ConcurrentModificationException(knownMod + " != " + + modCount); + } + + /** + * Get a strong reference to the next entry after + * lastBucket. + * @param lastEntry the previous bucket, or null if we should + * get the first entry. + * @return the next entry. + */ + private WeakBucket.WeakEntry findNext(WeakBucket.WeakEntry lastEntry) + { + int slot; + WeakBucket nextBucket; + if (lastEntry != null) + { + nextBucket = lastEntry.getBucket().next; + slot = lastEntry.getBucket().slot; + } + else + { + nextBucket = buckets[0]; + slot = 0; + } + + while (true) + { + while (nextBucket != null) + { + WeakBucket.WeakEntry entry = nextBucket.getEntry(); + if (entry != null) + // This is the next entry. + return entry; + + // Entry was cleared, try next. + nextBucket = nextBucket.next; + } + + slot++; + if (slot == buckets.length) + // No more buckets, we are through. + return null; + + nextBucket = buckets[slot]; + } + } + + /** + * Checks if there are more entries. + * @return true, iff there are more elements. + * @throws ConcurrentModificationException if the hash map was + * modified. + */ + public boolean hasNext() + { + checkMod(); + return nextEntry != null; + } + + /** + * Returns the next entry. + * @return the next entry. + * @throws ConcurrentModificationException if the hash map was + * modified. + * @throws NoSuchElementException if there is no entry. + */ + public Object next() + { + checkMod(); + if (nextEntry == null) + throw new NoSuchElementException(); + lastEntry = nextEntry; + nextEntry = findNext(lastEntry); + return lastEntry; + } + + /** + * Removes the last returned entry from this set. This will + * also remove the bucket of the underlying weak hash map. + * @throws ConcurrentModificationException if the hash map was + * modified. + * @throws IllegalStateException if <code>next()</code> was + * never called or the element was already removed. + */ + public void remove() + { + checkMod(); + if (lastEntry == null) + throw new IllegalStateException(); + modCount++; + internalRemove(lastEntry.getBucket()); + lastEntry = null; + knownMod++; + } + }; + } + } + + /** + * A bucket is a weak reference to the key, that contains a strong + * reference to the value, a pointer to the next bucket and its slot + * number. <br> + * + * It would be cleaner to have a WeakReference as field, instead of + * extending it, but if a weak reference gets cleared, we only get + * the weak reference (by queue.poll) and wouldn't know where to + * look for this reference in the hashtable, to remove that entry. + * + * @author Jochen Hoenicke + */ + private static class WeakBucket extends WeakReference + { + /** + * The value of this entry. The key is stored in the weak + * reference that we extend. + */ + Object value; + + /** + * The next bucket describing another entry that uses the same + * slot. + */ + WeakBucket next; + + /** + * The slot of this entry. This should be + * <code>Math.abs(key.hashCode() % buckets.length)</code>. + * + * But since the key may be silently removed we have to remember + * the slot number. + * + * If this bucket was removed the slot is -1. This marker will + * prevent the bucket from being removed twice. + */ + int slot; + + /** + * Creates a new bucket for the given key/value pair and the specified + * slot. + * @param key the key + * @param queue the queue the weak reference belongs to + * @param value the value + * @param slot the slot. This must match the slot where this bucket + * will be enqueued. + */ + public WeakBucket(Object key, ReferenceQueue queue, Object value, + int slot) + { + super(key, queue); + this.value = value; + this.slot = slot; + } + + /** + * This class gives the <code>Entry</code> representation of the + * current bucket. It also keeps a strong reference to the + * key; bad things may happen otherwise. + */ + class WeakEntry implements Map.Entry + { + /** + * The strong ref to the key. + */ + Object key; + + /** + * Creates a new entry for the key. + * @param key the key + */ + public WeakEntry(Object key) + { + this.key = key; + } + + /** + * Returns the underlying bucket. + * @return the owning bucket + */ + public WeakBucket getBucket() + { + return WeakBucket.this; + } + + /** + * Returns the key. + * @return the key + */ + public Object getKey() + { + return key == NULL_KEY ? null : key; + } + + /** + * Returns the value. + * @return the value + */ + public Object getValue() + { + return value; + } + + /** + * This changes the value. This change takes place in + * the underlying hash map. + * @param newVal the new value + * @return the old value + */ + public Object setValue(Object newVal) + { + Object oldVal = value; + value = newVal; + return oldVal; + } + + /** + * The hashCode as specified in the Entry interface. + * @return the hash code + */ + public int hashCode() + { + return System.identityHashCode(key) + ^ (value == null ? 0 : value.hashCode()); + } + + /** + * The equals method as specified in the Entry interface. + * @param o the object to compare to + * @return true iff o represents the same key/value pair + */ + public boolean equals(Object o) + { + if (o instanceof Map.Entry) + { + Map.Entry e = (Map.Entry) o; + return getKey() == e.getKey() + && (value == null ? e.getValue() == null + : value.equals(e.getValue())); + } + return false; + } + + public String toString() + { + return getKey() + "=" + value; + } + } + + /** + * This returns the entry stored in this bucket, or null, if the + * bucket got cleared in the mean time. + * @return the Entry for this bucket, if it exists + */ + WeakEntry getEntry() + { + final Object key = this.get(); + if (key == null) + return null; + return new WeakEntry(key); + } + } + + /** + * The entry set returned by <code>entrySet()</code>. + */ + private final WeakEntrySet theEntrySet; + + /** + * The hash buckets. These are linked lists. Package visible for use in + * nested classes. + */ + WeakBucket[] buckets; + + /** + * Creates a new weak hash map with default load factor and default + * capacity. + */ + public WeakIdentityHashMap() + { + this(DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR); + } + + /** + * Creates a new weak hash map with default load factor and the given + * capacity. + * @param initialCapacity the initial capacity + * @throws IllegalArgumentException if initialCapacity is negative + */ + public WeakIdentityHashMap(int initialCapacity) + { + this(initialCapacity, DEFAULT_LOAD_FACTOR); + } + + /** + * Creates a new weak hash map with the given initial capacity and + * load factor. + * @param initialCapacity the initial capacity. + * @param loadFactor the load factor (see class description of HashMap). + * @throws IllegalArgumentException if initialCapacity is negative, or + * loadFactor is non-positive + */ + public WeakIdentityHashMap(int initialCapacity, float loadFactor) + { + // Check loadFactor for NaN as well. + if (initialCapacity < 0 || ! (loadFactor > 0)) + throw new IllegalArgumentException(); + if (initialCapacity == 0) + initialCapacity = 1; + this.loadFactor = loadFactor; + threshold = (int) (initialCapacity * loadFactor); + theEntrySet = new WeakEntrySet(); + queue = new ReferenceQueue(); + buckets = new WeakBucket[initialCapacity]; + } + + /** + * Construct a new WeakIdentityHashMap with the same mappings as the given map. + * The WeakIdentityHashMap has a default load factor of 0.75. + * + * @param m the map to copy + * @throws NullPointerException if m is null + * @since 1.3 + */ + public WeakIdentityHashMap(Map m) + { + this(m.size(), DEFAULT_LOAD_FACTOR); + putAll(m); + } + + /** + * Simply hashes a non-null Object to its array index. + * @param key the key to hash + * @return its slot number + */ + private int hash(Object key) + { + return Math.abs(System.identityHashCode(key) % buckets.length); + } + + /** + * Cleans the reference queue. This will poll all references (which + * are WeakBuckets) from the queue and remove them from this map. + * This will not change modCount, even if it modifies the map. The + * iterators have to make sure that nothing bad happens. <br> + * + * Currently the iterator maintains a strong reference to the key, so + * that is no problem. + */ + // Package visible for use by nested classes. + void cleanQueue() + { + Object bucket = queue.poll(); + while (bucket != null) + { + internalRemove((WeakBucket) bucket); + bucket = queue.poll(); + } + } + + /** + * Rehashes this hashtable. This will be called by the + * <code>add()</code> method if the size grows beyond the threshold. + * It will grow the bucket size at least by factor two and allocates + * new buckets. + */ + private void rehash() + { + WeakBucket[] oldBuckets = buckets; + int newsize = buckets.length * 2 + 1; // XXX should be prime. + threshold = (int) (newsize * loadFactor); + buckets = new WeakBucket[newsize]; + + // Now we have to insert the buckets again. + for (int i = 0; i < oldBuckets.length; i++) + { + WeakBucket bucket = oldBuckets[i]; + WeakBucket nextBucket; + while (bucket != null) + { + nextBucket = bucket.next; + + Object key = bucket.get(); + if (key == null) + { + // This bucket should be removed; it is probably + // already on the reference queue. We don't insert it + // at all, and mark it as cleared. + bucket.slot = -1; + size--; + } + else + { + // Add this bucket to its new slot. + int slot = hash(key); + bucket.slot = slot; + bucket.next = buckets[slot]; + buckets[slot] = bucket; + } + bucket = nextBucket; + } + } + } + + /** + * Finds the entry corresponding to key. Since it returns an Entry + * it will also prevent the key from being removed under us. + * @param key the key, may be null + * @return The WeakBucket.WeakEntry or null, if the key wasn't found. + */ + private WeakBucket.WeakEntry internalGet(Object key) + { + if (key == null) + key = NULL_KEY; + int slot = hash(key); + WeakBucket bucket = buckets[slot]; + while (bucket != null) + { + WeakBucket.WeakEntry entry = bucket.getEntry(); + if (entry != null && key == entry.key) + return entry; + + bucket = bucket.next; + } + return null; + } + + /** + * Adds a new key/value pair to the hash map. + * @param key the key. This mustn't exists in the map. It may be null. + * @param value the value. + */ + private void internalAdd(Object key, Object value) + { + if (key == null) + key = NULL_KEY; + int slot = hash(key); + WeakBucket bucket = new WeakBucket(key, queue, value, slot); + bucket.next = buckets[slot]; + buckets[slot] = bucket; + size++; + } + + /** + * Removes a bucket from this hash map, if it wasn't removed before + * (e.g. one time through rehashing and one time through reference queue). + * Package visible for use in nested classes. + * + * @param bucket the bucket to remove. + */ + void internalRemove(WeakBucket bucket) + { + int slot = bucket.slot; + if (slot == -1) + // This bucket was already removed. + return; + + // Mark the bucket as removed. This is necessary, since the + // bucket may be enqueued later by the garbage collection, and + // internalRemove will be called a second time. + bucket.slot = -1; + + WeakBucket prev = null; + WeakBucket next = buckets[slot]; + while (next != bucket) + { + if (next == null) + throw new InternalError("WeakIdentityHashMap in inconsistent state"); + prev = next; + next = prev.next; + } + if (prev == null) + buckets[slot] = bucket.next; + else + prev.next = bucket.next; + + size--; + } + + /** + * Returns the size of this hash map. Note that the size() may shrink + * spontaneously, if the some of the keys were only weakly reachable. + * @return the number of entries in this hash map. + */ + public int size() + { + cleanQueue(); + return size; + } + + /** + * Tells if the map is empty. Note that the result may change + * spontanously, if all of the keys were only weakly reachable. + * @return true, iff the map is empty. + */ + public boolean isEmpty() + { + cleanQueue(); + return size == 0; + } + + /** + * Tells if the map contains the given key. Note that the result + * may change spontanously, if the key was only weakly + * reachable. + * @param key the key to look for + * @return true, iff the map contains an entry for the given key. + */ + public boolean containsKey(Object key) + { + cleanQueue(); + return internalGet(key) != null; + } + + /** + * Gets the value the key is mapped to. + * @return the value the key was mapped to. It returns null if + * the key wasn't in this map, or if the mapped value was + * explicitly set to null. + */ + public Object get(Object key) + { + cleanQueue(); + WeakBucket.WeakEntry entry = internalGet(key); + return entry == null ? null : entry.getValue(); + } + + /** + * Adds a new key/value mapping to this map. + * @param key the key, may be null + * @param value the value, may be null + * @return the value the key was mapped to previously. It returns + * null if the key wasn't in this map, or if the mapped value + * was explicitly set to null. + */ + public Object put(Object key, Object value) + { + cleanQueue(); + WeakBucket.WeakEntry entry = internalGet(key); + if (entry != null) + return entry.setValue(value); + + modCount++; + if (size >= threshold) + rehash(); + + internalAdd(key, value); + return null; + } + + /** + * Removes the key and the corresponding value from this map. + * @param key the key. This may be null. + * @return the value the key was mapped to previously. It returns + * null if the key wasn't in this map, or if the mapped value was + * explicitly set to null. + */ + public Object remove(Object key) + { + cleanQueue(); + WeakBucket.WeakEntry entry = internalGet(key); + if (entry == null) + return null; + + modCount++; + internalRemove(entry.getBucket()); + return entry.getValue(); + } + + /** + * Returns a set representation of the entries in this map. This + * set will not have strong references to the keys, so they can be + * silently removed. The returned set has therefore the same + * strange behaviour (shrinking size(), disappearing entries) as + * this weak hash map. + * @return a set representation of the entries. + */ + public Set entrySet() + { + cleanQueue(); + return theEntrySet; + } + + /** + * Clears all entries from this map. + */ + public void clear() + { + super.clear(); + } + + /** + * Returns true if the map contains at least one key which points to + * the specified object as a value. Note that the result + * may change spontanously, if its key was only weakly reachable. + * @param value the value to search for + * @return true if it is found in the set. + */ + public boolean containsValue(Object value) + { + cleanQueue(); + return super.containsValue(value); + } + + /** + * Returns a set representation of the keys in this map. This + * set will not have strong references to the keys, so they can be + * silently removed. The returned set has therefore the same + * strange behaviour (shrinking size(), disappearing entries) as + * this weak hash map. + * @return a set representation of the keys. + */ + public Set keySet() + { + cleanQueue(); + return super.keySet(); + } + + /** + * Puts all of the mappings from the given map into this one. If the + * key already exists in this map, its value is replaced. + * @param m the map to copy in + */ + public void putAll(Map m) + { + super.putAll(m); + } + + /** + * Returns a collection representation of the values in this map. This + * collection will not have strong references to the keys, so mappings + * can be silently removed. The returned collection has therefore the same + * strange behaviour (shrinking size(), disappearing entries) as + * this weak hash map. + * @return a collection representation of the values. + */ + public Collection values() + { + cleanQueue(); + return super.values(); + } +} // class WeakIdentityHashMap |