Index: xml/src/main/java/org/exolab/castor/xml/MarshalFramework.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/MarshalFramework.java (revision 8042) +++ xml/src/main/java/org/exolab/castor/xml/MarshalFramework.java (working copy) @@ -183,10 +183,19 @@ //-----------------------------/ /** - * We need some stuff initialized here. + * We need some stuff initialized here. MarshalFramework requires internally + * an {@link InternalContext}, so either one is given or {@link BackwardCompatibilityContext} + * is instantiated! Mind that instantiating {@link BackwardCompatibilityContext} + * means to (re-)read configuration files. + * @param internalContext either an {@link InternalContext} comes from outside + * or {@link BackwardCompatibilityContext} is instantiated */ - public MarshalFramework() { - _internalContext = new BackwardCompatibilityContext(); + public MarshalFramework(final InternalContext internalContext) { + if (internalContext == null) { + _internalContext = new BackwardCompatibilityContext(); + } else { + _internalContext = internalContext; + } } /** Index: xml/src/main/java/org/exolab/castor/xml/Unmarshaller.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/Unmarshaller.java (revision 8042) +++ xml/src/main/java/org/exolab/castor/xml/Unmarshaller.java (working copy) @@ -343,7 +343,7 @@ **/ public UnmarshalHandler createHandler() { - UnmarshalHandler handler = new UnmarshalHandler(_class); + UnmarshalHandler handler = new UnmarshalHandler(_internalContext, _class); handler.setClearCollections(_clearCollections); handler.setReuseObjects(_reuseObjects); Index: xml/src/main/java/org/exolab/castor/xml/UnmarshalHandler.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/UnmarshalHandler.java (revision 8042) +++ xml/src/main/java/org/exolab/castor/xml/UnmarshalHandler.java (working copy) @@ -67,6 +67,7 @@ import org.apache.commons.logging.LogFactory; import org.castor.core.util.Base64Decoder; import org.castor.core.util.HexDecoder; +import org.castor.xml.InternalContext; import org.castor.xml.UnmarshalListenerAdapter; import org.castor.xml.XMLProperties; import org.exolab.castor.mapping.ClassDescriptor; @@ -287,22 +288,31 @@ **/ protected UnmarshalHandler() { this(null); - } //-- UnmarshalHandler + } /** * Creates a new UnmarshalHandler. * - * @param _class the Class to create the UnmarshalHandler for + * @param topClass the Class to create the UnmarshalHandler for */ - protected UnmarshalHandler(final Class _class) { - super(); + protected UnmarshalHandler(final Class topClass) { + this(null, topClass); + } + + /** + * Creates a new UnmarshalHandler. + * @param internalContext the {@link InternalContext} to use + * @param topClass the Class to work for + */ + protected UnmarshalHandler(final InternalContext internalContext, final Class topClass) { + super(internalContext); _stateInfo = new Stack(); _idResolver = new IDResolverImpl(); _javaPackages = new HashMap(); - _topClass = _class; + _topClass = topClass; _namespaces = new Namespaces(); _namespaceToPackage = new HashMap(); - } //-- UnmarshalHandler(Class) + } /** * Adds a mapping from the given namespace URI to the given Index: xml/src/main/java/org/exolab/castor/xml/Marshaller.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/Marshaller.java (revision 8042) +++ xml/src/main/java/org/exolab/castor/xml/Marshaller.java (working copy) @@ -287,6 +287,7 @@ * **/ public Marshaller(final DocumentHandler handler) { + super(null); if (handler == null) { throw new IllegalArgumentException("The given 'org.sax.DocumentHandler' " + "instance is null."); @@ -295,7 +296,7 @@ setContentHandler(new DocumentHandlerAdapter(handler)); // call internal initializer - initialize(); + initialize(null); } /** @@ -326,6 +327,7 @@ * **/ public Marshaller(final ContentHandler contentHandler) { + super(null); if (contentHandler == null) { throw new IllegalArgumentException("The given 'org.sax.ContentHandler' is null."); } @@ -333,7 +335,19 @@ setContentHandler(contentHandler); // call internal initializer - initialize(); + initialize(null); + } + + /** + * The one {@link Marshaller} constructor that is used by {@link XMLContext} which + * sets an {@link InternalContext} that comes from outside. Writer or {@link ContentHandler} + * have to be set in a second step. + * @param internalContext the {@link InternalContext} to initialize the {@link Marshaller} + * instance with + */ + public Marshaller(final InternalContext internalContext) { + super(internalContext); + initialize(internalContext); } /** @@ -341,7 +355,8 @@ * separately. */ public Marshaller () { - initialize(); + super(null); + initialize(null); } /** @@ -357,7 +372,8 @@ * **/ public Marshaller(final Writer out) throws IOException { - initialize(); + super(null); + initialize(null); setWriter(out); } @@ -413,13 +429,14 @@ * **/ public Marshaller(final Node node) { + super(null); if (node == null) { throw new IllegalArgumentException("The given org.w3c.dom.Node instance is null."); } setContentHandler(new DocumentHandlerAdapter(new SAX2DOMHandler(node))); // call internal initializer - initialize(); + initialize(null); } /** @@ -435,11 +452,16 @@ } /** - * Initializes this Marshaller. This is common code shared among the - * Constructors + * Either sets the internalContext as provided - or if null was provided it is + * set to a new instance of {@link BackwardCompatibilityContext}. + * @param internalContext the {@link InternalContext} to set */ - private void initialize() { - setInternalContext(new BackwardCompatibilityContext()); + private void initialize(final InternalContext internalContext) { + if (internalContext == null) { + setInternalContext(new BackwardCompatibilityContext()); + } else { + setInternalContext(internalContext); + } } /** Index: xml/src/main/java/org/exolab/castor/xml/XMLContext.java =================================================================== --- xml/src/main/java/org/exolab/castor/xml/XMLContext.java (revision 8042) +++ xml/src/main/java/org/exolab/castor/xml/XMLContext.java (working copy) @@ -163,8 +163,7 @@ if (LOG.isDebugEnabled()) { LOG.debug("Creating new Marshaller instance."); } - Marshaller marshaller = new Marshaller(); - marshaller.setInternalContext(_internalContext); + Marshaller marshaller = new Marshaller(_internalContext); return marshaller; } Index: xml/src/main/java/org/castor/xml/AbstractInternalContext.java =================================================================== --- xml/src/main/java/org/castor/xml/AbstractInternalContext.java (revision 8042) +++ xml/src/main/java/org/castor/xml/AbstractInternalContext.java (working copy) @@ -168,9 +168,41 @@ } /** + * {@inheritDoc} * @see org.castor.xml.InternalContext#setProperty(java.lang.String, java.lang.Object) */ public void setProperty(final String propertyName, final Object value) { + // resetting all values that are only reinitialized if null + if (propertyName == null) { + IllegalArgumentException iae = new IllegalArgumentException("setProperty must not be called with a propertyName == null"); + LOG.warn(iae.getMessage()); + throw iae; + } + if (propertyName.equals(XMLProperties.XML_NAMING)) { + if (value instanceof String) { + setXMLNaming((String)value); + } else if (value instanceof XMLNaming) { + setXMLNaming((XMLNaming) value); + } else { + IllegalArgumentException iae = new IllegalArgumentException("XML Naming can only be set to a String or an implementation of XMLNaming"); + LOG.warn(iae.getMessage()); + throw iae; + } + } + if (propertyName.equals(XMLProperties.JAVA_NAMING)) { + if (value instanceof String) { + setJavaNaming((String)value); + } else if (value instanceof JavaNaming) { + setJavaNaming((JavaNaming) value); + } else { + IllegalArgumentException iae = new IllegalArgumentException("Java Naming can only be set to a String or an implementation of JavaNaming"); + LOG.warn(iae.getMessage()); + throw iae; + } + } + _primitiveNodeType = null; + _regExpEvaluator = null; + // now writing the new property _properties.put(propertyName, value); } @@ -182,42 +214,26 @@ } /** + * {@inheritDoc} * @see org.castor.xml.InternalContext#getXMLNaming() */ public XMLNaming getXMLNaming() { - return getXMLNaming(null); + if (_xmlNaming != null) { + return _xmlNaming; + } + + String prop = _properties.getString(XMLProperties.XML_NAMING, null); + setXMLNaming(prop); + return _xmlNaming; } /** + * {@inheritDoc} * @see org.castor.xml.InternalContext#getXMLNaming(java.lang.ClassLoader) + * @deprecated Makes no sence! */ public XMLNaming getXMLNaming(final ClassLoader classLoader) { - - if (_xmlNaming != null) { - return _xmlNaming; - } - - String prop = _properties.getString(XMLProperties.XML_NAMING, null); - if ((prop == null) || (prop.equalsIgnoreCase("lower"))) { - _xmlNaming = new DefaultNaming(); - } else if (prop.equalsIgnoreCase("mixed")) { - DefaultNaming dn = new DefaultNaming(); - dn.setStyle(DefaultNaming.MIXED_CASE_STYLE); - _xmlNaming = dn; - } else { - try { - Class cls = null; - if (classLoader != null) { - cls = classLoader.loadClass(prop); - } else { - cls = Class.forName(prop); - } - _xmlNaming = (XMLNaming) cls.newInstance(); - } catch (Exception e) { - throw new RuntimeException("Failed to load XMLNaming: " + e); - } - } - return _xmlNaming; + return getXMLNaming(); } //-- getXMLNaming /** @@ -446,11 +462,62 @@ _javaNaming = javaNaming; } + public void setJavaNaming(final String javaNamingProperty) { + if (javaNamingProperty == null || javaNamingProperty.length() == 0) { + _javaNaming = new JavaNamingImpl(); + } else { + try { + Class cls = (Class) Class.forName(javaNamingProperty); + _javaNaming = cls.newInstance(); + } catch (Exception e) { + IllegalArgumentException iae = new IllegalArgumentException( + "Failed to load JavaNaming: " + e); + LOG.warn(iae.getMessage()); + throw iae; + } + } + } + /** * @see org.castor.xml.InternalContext#setXMLNaming(org.castor.xml.XMLNaming) */ public void setXMLNaming(final XMLNaming xmlNaming) { _xmlNaming = xmlNaming; + // propagate to e.g. Introspector also!! + if (_introspector != null) { + _introspector.setNaming(_xmlNaming); + } + } + + /** + * This XMLNaming setter is meant to be used when working in property style + * instead of setting an XMLNaming implementation. + * @param xmlNamingProperty to set the XMLNaming property as read from configuration + */ + public void setXMLNaming(final String xmlNamingProperty) { + if ((xmlNamingProperty == null) || (xmlNamingProperty.equalsIgnoreCase("lower"))) { + setXMLNaming(new DefaultNaming()); + } else if (xmlNamingProperty.equalsIgnoreCase("mixed")) { + DefaultNaming dn = new DefaultNaming(); + dn.setStyle(DefaultNaming.MIXED_CASE_STYLE); + setXMLNaming(dn); + } else { + try { + Class cls = (Class) Class.forName(xmlNamingProperty); + setXMLNaming(cls.newInstance()); + } catch (Exception e) { + IllegalArgumentException iae = new IllegalArgumentException( + "Failed to load XMLNaming: " + e); + LOG.warn(iae.getMessage()); + throw iae; + } + } + if (_xmlNaming == null) { + IllegalArgumentException iae = new IllegalArgumentException( + "Failed to correctly set XMLNaming; property was: " + xmlNamingProperty); + LOG.warn(iae.getMessage()); + throw iae; + } } /** Index: xml/src/test/java/org/exolab/castor/xml/SetPropertyXmlNamingTest.java =================================================================== --- xml/src/test/java/org/exolab/castor/xml/SetPropertyXmlNamingTest.java (revision 0) +++ xml/src/test/java/org/exolab/castor/xml/SetPropertyXmlNamingTest.java (revision 0) @@ -0,0 +1,93 @@ +/* + * Copyright 2009 Joachim Grueneis + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.exolab.castor.xml; + +import java.io.StringReader; +import java.io.StringWriter; + +import org.xml.sax.InputSource; + +import junit.framework.Assert; +import junit.framework.TestCase; + +/** + * @author joachim + * + */ +public class SetPropertyXmlNamingTest extends TestCase { + + private static final String RESULT2 = + "\n" + + ""; + + private static final String RESULT = + "\n" + + ""; + + public void testSetXmlContextToMixed() throws Exception { + XMLContext xmlContext = new XMLContext(); + xmlContext.setProperty("org.exolab.castor.xml.naming", "mixed"); + xmlContext.addClass(Foo.class); + + StringWriter writer = new StringWriter(); + Marshaller marshaller = xmlContext.createMarshaller(); + marshaller.setWriter(writer); + marshaller.marshal(new Foo()); + + assertEquals(RESULT, writer.toString()); + } + + public void testSetXmlContextToMixedWithUnmarshaller() throws Exception { + XMLContext xmlContext = new XMLContext(); + xmlContext.setProperty("org.exolab.castor.xml.naming", "mixed"); + xmlContext.addClass(Foo.class); + Unmarshaller unmarshaller = xmlContext.createUnmarshaller(); + unmarshaller.setClass(Foo.class); + + StringReader sr = new StringReader(RESULT2); + Foo f = (Foo) unmarshaller.unmarshal(new InputSource(sr)); + Assert.assertNotNull(f); + Assert.assertEquals(0, f.barBar); + } + + public void testSetMarshallerToMixed() throws Exception { + XMLContext xmlContext = new XMLContext(); + xmlContext.addClass(Foo.class); + + StringWriter writer = new StringWriter(); + Marshaller marshaller = xmlContext.createMarshaller(); + marshaller.setWriter(writer); + marshaller.setProperty("org.exolab.castor.xml.naming", "mixed"); + marshaller.marshal(new Foo()); + + assertEquals(RESULT, writer.toString()); + } + + public void testSetNewMarshallerToMixed() throws Exception { + StringWriter writer = new StringWriter(); + Marshaller marshaller = new Marshaller(); + marshaller.setWriter(writer); + marshaller.setProperty("org.exolab.castor.xml.naming", "mixed"); + marshaller.marshal(new Foo()); + + assertEquals(RESULT, writer.toString()); + } + + public static class Foo { + public int barBar; + } + +}