diff options
author | Michael Koch <mkoch@gcc.gnu.org> | 2005-02-19 18:47:29 +0000 |
---|---|---|
committer | Michael Koch <mkoch@gcc.gnu.org> | 2005-02-19 18:47:29 +0000 |
commit | 6ca84a804a7378e79bbb1d5a6d646ead7e6cfa46 (patch) | |
tree | 55ebacd491a20d362082021ef37660e30d015575 /libjava/gnu/java/beans/decoder/PersistenceParser.java | |
parent | 2cdc207340d10fdbf643ae6b83cb289af1ba32d6 (diff) | |
download | gcc-6ca84a804a7378e79bbb1d5a6d646ead7e6cfa46.zip gcc-6ca84a804a7378e79bbb1d5a6d646ead7e6cfa46.tar.gz gcc-6ca84a804a7378e79bbb1d5a6d646ead7e6cfa46.tar.bz2 |
[multiple changes]
2005-02-19 Michael Koch <konqueror@gmx.de>
* Makefile.am: Added new files in gnu/java/beans and
java/beans/XMLDecoder.java.
* Makefile.in: Regenerated.
2005-02-19 Robert Schuster <thebohemian@gmx.net>
* gnu/java/beans/decoder/GrowableArrayContext.java: Fixed
assignment behavior by using java.lang.reflect.Array.set()
directly.
2005-02-19 Dalibor Topic <robilad@kaffe.org>
* gnu/java/beans/EmptyBeanInfo.java,
gnu/java/beans/info/ComponentBeanInfo.java:
Removed unused files.
2005-02-19 Robert Schuster <thebohemian@gmx.net>
* gnu/java/beans/DummyAppletStub.java: Add dummy implementation
of AppletStub for java.beans.Beans.instantiate.
* gnu/java/beans/DummyAppletContext.java: Add dummy implementation
of AppletContext.
* java/beans/Beans: Added 1.4 functionality, fixed user documentation
to be conformant with Javadoc guidelines.
(instantiate): Added two more overloaded variants, reworked user
documentation, fixed exception behavior, fixed behavior when
deserializing null.
2005-02-19 Mark Wielaard <mark@klomp.org>
* gnu/java/beans/decoder/DummyHandler.java: Add return statements for
failing methods.
* gnu/java/beans/decoder/DummyContext.java: Likewise.
2005-02-19 Robert Schuster <theBohemian@gmx.net>
* gnu/java/beans/decoder/AbstractContext.java,
gnu/java/beans/decoder/AbstractCreatableContext.java,
gnu/java/beans/decoder/AbstractElementHandler.java,
gnu/java/beans/decoder/AbstractObjectContext.java,
gnu/java/beans/decoder/ArrayContext.java,
gnu/java/beans/decoder/ArrayHandler.java,
gnu/java/beans/decoder/AssemblyException.java,
gnu/java/beans/decoder/BooleanHandler.java,
gnu/java/beans/decoder/ByteHandler.java,
gnu/java/beans/decoder/CharHandler.java,
gnu/java/beans/decoder/ClassHandler.java,
gnu/java/beans/decoder/ConstructorContext.java,
gnu/java/beans/decoder/Context.java,
gnu/java/beans/decoder/DecoderContext.java,
gnu/java/beans/decoder/DefaultExceptionListener.java,
gnu/java/beans/decoder/DoubleHandler.java,
gnu/java/beans/decoder/DummyContext.java,
gnu/java/beans/decoder/DummyHandler.java,
gnu/java/beans/decoder/ElementHandler.java,
gnu/java/beans/decoder/FloatHandler.java,
gnu/java/beans/decoder/GrowableArrayContext.java,
gnu/java/beans/decoder/IndexContext.java,
gnu/java/beans/decoder/IntHandler.java,
gnu/java/beans/decoder/JavaHandler.java,
gnu/java/beans/decoder/LongHandler.java,
gnu/java/beans/decoder/MethodContext.java,
gnu/java/beans/decoder/MethodFinder.java,
gnu/java/beans/decoder/NullHandler.java,
gnu/java/beans/decoder/ObjectContext.java,
gnu/java/beans/decoder/ObjectHandler.java,
gnu/java/beans/decoder/PersistenceParser.java,
gnu/java/beans/decoder/PropertyContext.java,
gnu/java/beans/decoder/ShortHandler.java,
gnu/java/beans/decoder/SimpleHandler.java,
gnu/java/beans/decoder/StaticMethodContext.java,
gnu/java/beans/decoder/StringHandler.java,
gnu/java/beans/decoder/VoidHandler.java: New class
implementing java.beans.XMLDecoder decoding functionality.
* java/beans/XMLDecoder.java: New class.
From-SVN: r95287
Diffstat (limited to 'libjava/gnu/java/beans/decoder/PersistenceParser.java')
-rw-r--r-- | libjava/gnu/java/beans/decoder/PersistenceParser.java | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/libjava/gnu/java/beans/decoder/PersistenceParser.java b/libjava/gnu/java/beans/decoder/PersistenceParser.java new file mode 100644 index 0000000..3315478 --- /dev/null +++ b/libjava/gnu/java/beans/decoder/PersistenceParser.java @@ -0,0 +1,484 @@ +/* gnu.java.beans.PersistenceParser + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +02111-1307 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.decoder; + +import java.beans.ExceptionListener; +import java.beans.XMLDecoder; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** The PersistenceParser parses an XML data stream and delegates actions to ElementHandler + * instances. The parser catches and recovers from all exception which reside from wrong usage + * of attributes and tags. + * + * @author Robert Schuster + */ +public class PersistenceParser extends DefaultHandler implements Context +{ + /** The ExceptionListener instance which is informed of non-critical parsing exceptions. + */ + private ExceptionListener exceptionListener; + + /** When an element was not usable all elements inside it should be skipped. + * This is done by skipping startElement() and endElement() invocations whenever + * this value is above 0. + */ + private int skipElement; + + /** Stores the Creator instances which can instantiate the appropriate handler implementation + * for a given element. + */ + private HashMap handlerCreators = new HashMap(); + + /** Denotes the current ElementHandler. To avoid checking for null-values it is pre-assigned + * with a DummyHandler instance which must not be used but acts as a root element. + */ + private ElementHandler currentHandler; + + /** The real root element that stores all objects created during parsing. + */ + private JavaHandler javaHandler; + + /** Stores the decoded objects. */ + private List objects = new LinkedList(); + + /** The XMLDecoder instance that started this PersistenceParser */ + private XMLDecoder decoder; + + /** Creates a PersistenceParser which reads XML data from the given InputStream, reports + * exceptions to ExceptionListener instance, stores resulting object in the DecoderContext + * and uses the given ClassLoader to resolve classes. + * + * @param inputStream + * @param exceptionListener + * @param decoderContext + * @param cl + */ + public PersistenceParser( + InputStream inputStream, + ExceptionListener exceptionListener, + ClassLoader cl, + XMLDecoder decoder) + { + + this.exceptionListener = exceptionListener; + this.decoder = decoder; + + DummyHandler dummyHandler = new DummyHandler(); + currentHandler = dummyHandler; + javaHandler = new JavaHandler(dummyHandler, this, cl); + + SAXParserFactory factory = SAXParserFactory.newInstance(); + + SAXParser parser; + try + { + parser = factory.newSAXParser(); + } + catch (ParserConfigurationException pce) + { + // should not happen when a parser is available because we did + // not request any requirements on the XML parser + throw (InternalError) new InternalError( + "No SAX Parser available.").initCause( + pce); + } + catch (SAXException saxe) + { + // should not happen when a parser is available because we did + // not request any requirements on the XML parser + throw (InternalError) new InternalError( + "No SAX Parser available.").initCause( + saxe); + } + + // prepares a map of Creator instances which can instantiate a handler which is + // appropriate for the tag that is used as a key for the Creator + handlerCreators.put("java", new JavaHandlerCreator()); + + // calls methods (properties), constructors, access fields + handlerCreators.put("object", new ObjectHandlerCreator()); + handlerCreators.put("void", new VoidHandlerCreator()); + + handlerCreators.put("array", new ArrayHandlerCreator()); + + // these handler directly create an Object (or null) + handlerCreators.put("class", new ClassHandlerCreator()); + handlerCreators.put("null", new NullHandlerCreator()); + + handlerCreators.put("char", new CharHandlerCreator()); + handlerCreators.put("string", new StringHandlerCreator()); + handlerCreators.put("boolean", new BooleanHandlerCreator()); + handlerCreators.put("byte", new ByteHandlerCreator()); + handlerCreators.put("short", new ShortHandlerCreator()); + handlerCreators.put("int", new IntHandlerCreator()); + handlerCreators.put("long", new LongHandlerCreator()); + handlerCreators.put("float", new FloatHandlerCreator()); + handlerCreators.put("double", new DoubleHandlerCreator()); + + // parses the data and sends all exceptions to the ExceptionListener + try + { + parser.parse(inputStream, this); + } + catch (SAXException saxe) + { + exceptionListener.exceptionThrown( + new IllegalArgumentException("XML data not well-formed.")); + } + catch (IOException ioe) + { + exceptionListener.exceptionThrown(ioe); + } + } + + public void startElement( + String uri, + String localName, + String qName, + Attributes attributes) + throws SAXException + { + /* The element is skipped if + * a) the current handler has already failed or a previous error occured + * which makes all children obsolete + */ + if (currentHandler.hasFailed() || skipElement > 0) + { + exceptionListener.exceptionThrown( + new IllegalArgumentException( + "Element unusable due to previous error: " + qName)); + + skipElement++; + + return; + } + + /* b) Subelements are not allowed within the current ElementHandler. + */ + if (!currentHandler.isSubelementAllowed(qName)) + { + exceptionListener.exceptionThrown( + new IllegalArgumentException( + "Element is not allowed here: " + qName)); + + skipElement++; + + return; + } + + /* c) The tag name is not a key in the map of Creator instances. This means that + * either the XML data is of a newer version or simply contains a miss-spelled element. + */ + if (!handlerCreators.containsKey(qName)) + { + exceptionListener.exceptionThrown( + new IllegalArgumentException( + "Element unusable because tag is unknown: " + qName)); + + skipElement++; + + return; + } + + // creates a new handler for the new element + AbstractElementHandler handler = + ((Creator) handlerCreators.get(qName)).createHandler( + currentHandler); + + // makes it the current handler to receive character data + currentHandler = handler; + + // starts the handler + currentHandler.start(attributes, exceptionListener); + } + + public void endElement(String uri, String localName, String qName) + throws SAXException + { + // skips processing the current handler if we are parsing an element + // which was marked invalid (in startElement() ) + if (skipElement > 0) + { + skipElement--; + return; + } + + // invokes the handler's finishing method + currentHandler.end(exceptionListener); + + // removes the current handler and reactivates its parent + currentHandler = currentHandler.getParent(); + } + + /** Transfers character data to the current handler + */ + public void characters(char[] ch, int start, int length) + throws SAXException + { + // prevents sending character data of invalid elements + if (skipElement > 0) + return; + + currentHandler.characters(ch, start, length); + } + + /** Creator interface provided a mechanism to instantiate ElementHandler instances + * for the appropriate tag. + * + * @author Robert Schuster + */ + interface Creator + { + /** Creates an ElementHandler instance using the given ElementHandler as its parent. + * + * @param parent The parent ElementHandler of the result. + * @return A new ElementHandler instance. + */ + AbstractElementHandler createHandler(ElementHandler parent); + } + + class BooleanHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new BooleanHandler(parent); + } + } + + class ByteHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new ByteHandler(parent); + } + } + + class ShortHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new ShortHandler(parent); + } + } + + class IntHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new IntHandler(parent); + } + } + + class LongHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new LongHandler(parent); + } + } + + class FloatHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new FloatHandler(parent); + } + } + + class DoubleHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new DoubleHandler(parent); + } + } + + class CharHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new CharHandler(parent); + } + } + + class StringHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new StringHandler(parent); + } + } + + class JavaHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return javaHandler; + } + } + + class ObjectHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new ObjectHandler(parent); + } + } + + class VoidHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new VoidHandler(parent); + } + } + + class ClassHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new ClassHandler(parent); + } + } + + class NullHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new NullHandler(parent); + } + } + + class ArrayHandlerCreator implements Creator + { + public AbstractElementHandler createHandler(ElementHandler parent) + { + return new ArrayHandler(parent); + } + } + + /** Adds a decoded object to the Context. */ + public void addParameterObject(Object o) throws AssemblyException + { + objects.add(o); + } + + public void notifyStatement(Context outerContext) throws AssemblyException + { + // can be ignored because theis Context does not react to statement and expressions + // differently + } + + public Object endContext(Context outerContext) throws AssemblyException + { + return null; + } + + public boolean subContextFailed() + { + // failing of subcontexts is no problem for the mother of all contexts + return false; + } + + public void set(int index, Object o) throws AssemblyException + { + // not supported + throw new AssemblyException( + new IllegalArgumentException("Set method is not allowed in decoder context.")); + } + + public Object get(int index) throws AssemblyException + { + // not supported + throw new AssemblyException( + new IllegalArgumentException("Get method is not allowed in decoder context.")); + } + + public Object getResult() + { + // returns the XMLDecoder instance which is requested by child contexts this way. + // That is needed to invoke methods on the decoder. + return decoder; + } + + public void setId(String id) + { + exceptionListener.exceptionThrown(new IllegalArgumentException("id attribute is not allowed for <java> tag.")); + } + + public String getId() + { + // appears to have no id + return null; + } + + public boolean isStatement() + { + // this context is a statement by definition because it never returns anything to a parent because + // there is no such parent (DummyContext does not count!) + return true; + } + + public void setStatement(boolean b) + { + // ignores that because this Context is always a statement + } + + /** Returns an Iterator instance which returns the decoded objects. + * + * This method is used by the XMLDecoder directly. + */ + public Iterator iterator() + { + return objects.iterator(); + } + +} |