| /* gnu.java.beans.decoder.ObjectHandler |
| 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., 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.decoder; |
| |
| import java.beans.ExceptionListener; |
| |
| import org.xml.sax.Attributes; |
| |
| /** An ObjectHandler parses the <object> tag and thereby creates various |
| * Context implementations. |
| * |
| * @author Robert Schuster |
| * |
| */ |
| public class ObjectHandler extends AbstractElementHandler |
| { |
| /** |
| * XXX: Can all results be stored with an object id? |
| * |
| * |
| * @param PersistenceParser |
| */ |
| ObjectHandler(ElementHandler parent) |
| { |
| super(parent, true); |
| } |
| |
| protected Context startElement(Attributes attributes, ExceptionListener exceptionListener) |
| throws AssemblyException |
| { |
| String className = attributes.getValue("class"); |
| String methodName = attributes.getValue("method"); |
| String fieldName = attributes.getValue("field"); |
| String index = attributes.getValue("index"); |
| String propertyName = attributes.getValue("property"); |
| String id = attributes.getValue("id"); |
| String idRef = attributes.getValue("idref"); |
| |
| /* first check if we just want to access an existing object (idref present) |
| * |
| * note: <object idref="foo" method="bar"/> is not valid to call method "bar" |
| * on the object with id "foo". Instead this should return the object "foo" |
| * itself. The right way to this is: |
| * <object idref="foo"> |
| * <object method="bar"/> |
| * </object> |
| * |
| * This means that if idref is present class, method, field, index and |
| * property are obsolete. |
| */ |
| if (idRef != null) |
| // reactivates an existing object and giving it another name if id exists |
| return new ObjectContext(id, getObject(idRef)); |
| |
| // decides whether we are in a static (className present) or dynamic context |
| if (className != null) |
| { |
| try |
| { |
| Class klass = instantiateClass(className); |
| |
| // class name exists which means that we are in a static context. |
| // so we may want to ... |
| // access a static field if the fieldName exists |
| if (fieldName != null) |
| { |
| try |
| { |
| return new ObjectContext(id, |
| klass.getField(fieldName).get(null)); |
| } |
| catch (NoSuchFieldException nsfe) |
| { |
| throw new AssemblyException(nsfe); |
| } |
| catch (IllegalAccessException iae) |
| { |
| throw new AssemblyException(iae); |
| } |
| } |
| |
| // (falling through is important!) |
| // run a constructor if methodName is "new" or null |
| if (methodName == null || methodName.equals("new")) |
| return new ConstructorContext(id, klass); |
| |
| // (falling through is important!) |
| // run a static method on the given class (if methodName exists, which is implied already) |
| return new StaticMethodContext(id, klass, methodName); |
| // XXX: should fail if unexpected attributes are present? |
| } |
| catch (ClassNotFoundException cnfe) |
| { |
| throw new AssemblyException(cnfe); |
| } |
| } |
| else |
| { |
| // className does not exist which means we are in the context of |
| // some object and want to ... |
| // access the get(int index) method if index != null |
| if (index != null) |
| { |
| try |
| { |
| // Note: http://java.sun.com/products/jfc/tsc/articles/persistence3/ says |
| // that <void index="4"/> will make up a get()-call. But this is wrong because |
| // <void/> tags never return values (to the surrounding context) |
| return new IndexContext(id, Integer.parseInt(index)); |
| } |
| catch (NumberFormatException nfe) |
| { |
| throw new AssemblyException(nfe); |
| } |
| } |
| |
| // access a method if methodName exists |
| if (methodName != null) |
| return new MethodContext(id, methodName); |
| |
| // (falling through is important!) |
| // access a property if a propertyName exists |
| if (propertyName != null && propertyName.length() > 0) |
| // this is reported as an ordinary method access where the propertyName is |
| // converted into a 'getter'-method name: convert first character of property name |
| // to upper case and prepend 'get' |
| // Note: This will be a getter-method because the <object> tag implies that a return |
| // value is expected. |
| return new PropertyContext(id, propertyName); |
| } |
| |
| throw new AssemblyException(new IllegalArgumentException("Wrong or missing attributes for <object> tag.")); |
| } |
| } |