| /* $Id$ |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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.apache.commons.digester3.xmlrules; |
| |
| import static org.apache.commons.digester3.binder.DigesterLoader.newLoader; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.InputStream; |
| import java.io.StringReader; |
| import java.net.URL; |
| import java.util.ArrayList; |
| |
| import org.apache.commons.digester3.Address; |
| import org.apache.commons.digester3.Digester; |
| import org.apache.commons.digester3.ObjectCreationFactoryTestImpl; |
| import org.apache.commons.digester3.binder.RulesModule; |
| import org.junit.Test; |
| import org.xml.sax.InputSource; |
| |
| /** |
| * Tests loading Digester rules from an XML file. |
| */ |
| |
| public class FromXmlRuleSetTest |
| { |
| |
| private final RulesModule createRules( final URL xmlRules ) |
| { |
| return new FromXmlRulesModule() |
| { |
| |
| @Override |
| protected void loadRules() |
| { |
| loadXMLRules( xmlRules ); |
| } |
| |
| }; |
| } |
| |
| private final RulesModule createRules( final String xmlText ) |
| { |
| return new FromXmlRulesModule() |
| { |
| |
| @Override |
| protected void loadRules() |
| { |
| loadXMLRulesFromText( xmlText ); |
| } |
| |
| }; |
| } |
| |
| /** |
| * Tests the DigesterLoader.createDigester(), with multiple |
| * included rule sources: testrules.xml includes another rules xml |
| * file, and also includes programmatically created rules. |
| */ |
| @Test |
| public void testCreateDigester() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "testrules.xml" ); |
| final URL input = getClass().getResource( "test.xml" ); |
| |
| final Digester digester = newLoader( createRules( rules ) ).newDigester(); |
| digester.push( new ArrayList<Object>() ); |
| final Object root = digester.parse( input.openStream() ); |
| assertEquals( "[foo1 baz1 foo2, foo3 foo4]", root.toString() ); |
| } |
| |
| /** |
| * Tests the DigesterLoader.load(), with multiple included rule |
| * sources: testrules.xml includes another rules xml file, and |
| * also includes programmatically created rules. |
| */ |
| @Test |
| public void testLoad1() |
| throws Exception |
| { |
| final ClassLoader classLoader = getClass().getClassLoader(); |
| final URL rules = getClass().getResource( "testrules.xml" ); |
| final URL input = getClass().getResource( "test.xml" ); |
| |
| final Digester digester = newLoader( createRules( rules ) ).setClassLoader( classLoader ).newDigester(); |
| digester.push( new ArrayList<Object>() ); |
| |
| final Object root = digester.parse( input ); |
| if ( !( root instanceof ArrayList<?> ) ) |
| { |
| fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " |
| + root.getClass().getName() ); |
| } |
| assertEquals( "[foo1 baz1 foo2, foo3 foo4]", root.toString() ); |
| |
| @SuppressWarnings( "unchecked" ) |
| final |
| // root is an ArrayList |
| ArrayList<Object> al = (ArrayList<Object>) root; |
| final Object obj = al.get( 0 ); |
| if ( !( obj instanceof ObjectTestImpl ) ) |
| { |
| fail( "Unexpected object returned from DigesterLoader. Expected TestObject; got " |
| + obj.getClass().getName() ); |
| } |
| final ObjectTestImpl to = (ObjectTestImpl) obj; |
| assertEquals( new Long( 555 ), to.getLongValue() ); |
| assertEquals( "foo", to.getMapValue( "test1" ) ); |
| assertEquals( "bar", to.getMapValue( "test2" ) ); |
| } |
| |
| /** |
| * The same as testLoad1, exception the input file is passed to |
| * DigesterLoader as an InputStream instead of a URL. |
| */ |
| @Test |
| public void testLoad2() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "testrules.xml" ); |
| final InputStream input = getClass().getResourceAsStream( "test.xml" ); |
| final Digester digester = |
| newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); |
| digester.push( new ArrayList<Object>() ); |
| |
| final ArrayList<Object> list = digester.parse( input ); |
| |
| assertEquals( list.toString(), "[foo1 baz1 foo2, foo3 foo4]" ); |
| assertEquals( "Wrong number of classes created", 2, list.size() ); |
| assertEquals( "Pushed first", true, ( (ObjectTestImpl) list.get( 0 ) ).isPushed() ); |
| assertEquals( "Didn't push second", false, ( (ObjectTestImpl) list.get( 1 ) ).isPushed() ); |
| assertTrue( "Property was set properly", |
| ( (ObjectTestImpl) list.get( 0 ) ).getProperty().equals( "I am a property!" ) ); |
| } |
| |
| /** |
| */ |
| @Test |
| public void testSetCustomProperties() |
| throws Exception |
| { |
| final URL rules = this.getClass().getResource( "testPropertyAliasRules.xml" ); |
| final InputStream input = |
| getClass().getClassLoader().getResource( "org/apache/commons/digester3/Test7.xml" ).openStream(); |
| |
| final Digester digester = |
| newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); |
| digester.push( new ArrayList<Object>() ); |
| |
| final Object obj = digester.parse( input ); |
| |
| if ( !( obj instanceof ArrayList<?> ) ) |
| { |
| fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " + obj.getClass().getName() ); |
| } |
| |
| @SuppressWarnings("unchecked") // root is an ArrayList of Address |
| final |
| ArrayList<Address> root = (ArrayList<Address>) obj; |
| |
| assertEquals( "Wrong array size", 4, root.size() ); |
| |
| // note that the array is in popped order (rather than pushed) |
| |
| Address add = root.get( 0 ); |
| final Address addressOne = add; |
| assertEquals( "(1) Street attribute", "New Street", addressOne.getStreet() ); |
| assertEquals( "(1) City attribute", "Las Vegas", addressOne.getCity() ); |
| assertEquals( "(1) State attribute", "Nevada", addressOne.getState() ); |
| |
| add = root.get( 1 ); |
| final Address addressTwo = add; |
| assertEquals( "(2) Street attribute", "Old Street", addressTwo.getStreet() ); |
| assertEquals( "(2) City attribute", "Portland", addressTwo.getCity() ); |
| assertEquals( "(2) State attribute", "Oregon", addressTwo.getState() ); |
| |
| add = root.get( 2 ); |
| final Address addressThree = add; |
| assertEquals( "(3) Street attribute", "4th Street", addressThree.getStreet() ); |
| assertEquals( "(3) City attribute", "Dayton", addressThree.getCity() ); |
| assertEquals( "(3) State attribute", "US", addressThree.getState() ); |
| |
| add = root.get( 3 ); |
| final Address addressFour = add; |
| assertEquals( "(4) Street attribute", "6th Street", addressFour.getStreet() ); |
| assertEquals( "(4) City attribute", "Cleveland", addressFour.getCity() ); |
| assertEquals( "(4) State attribute", "Ohio", addressFour.getState() ); |
| } |
| |
| @Test |
| public void testFactoryCreateRule() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "testfactory.xml" ); |
| final String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; |
| |
| final Digester digester = |
| newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); |
| digester.push( new ArrayList<ObjectCreationFactoryTestImpl>() ); |
| |
| final Object obj = digester.parse( new StringReader( xml ) ); |
| if ( !( obj instanceof ArrayList<?> ) ) |
| { |
| fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " + obj.getClass().getName() ); |
| } |
| |
| @SuppressWarnings("unchecked") // root is an ArrayList of TestObjectCreationFactory |
| final |
| ArrayList<ObjectCreationFactoryTestImpl> list = (ArrayList<ObjectCreationFactoryTestImpl>) obj; |
| |
| assertEquals( "List should contain only the factory object", list.size(), 1 ); |
| final ObjectCreationFactoryTestImpl factory = list.get( 0 ); |
| assertEquals( "Object create not called(1)", factory.called, true ); |
| assertEquals( "Attribute not passed (1)", factory.attributes.getValue( "one" ), "good" ); |
| assertEquals( "Attribute not passed (2)", factory.attributes.getValue( "two" ), "bad" ); |
| assertEquals( "Attribute not passed (3)", factory.attributes.getValue( "three" ), "ugly" ); |
| } |
| |
| @Test |
| public void testFactoryIgnoreCreateRule() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "testfactoryignore.xml" ); |
| |
| final String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; |
| try { |
| newLoader(createRules(rules)).newDigester().parse(new StringReader(xml)); |
| } catch (final Exception e) { |
| fail("This exception should have been ignored: " + e.getClass().getName()); |
| } |
| } |
| |
| @Test |
| public void testFactoryNotIgnoreCreateRule() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "testfactorynoignore.xml" ); |
| |
| final String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; |
| try |
| { |
| newLoader( createRules( rules ) ).newDigester().parse( new StringReader( xml ) ); |
| fail( "Exception should have been propagated from create method." ); |
| } |
| catch ( final Exception e ) |
| { |
| /* What we expected */ |
| assertEquals( org.xml.sax.SAXParseException.class, e.getClass() ); |
| } |
| } |
| |
| @Test |
| public void testCallParamRule() |
| throws Exception |
| { |
| final URL rules = getClass().getResource( "test-call-param-rules.xml" ); |
| |
| final String xml = "<?xml version='1.0' ?>" |
| + "<root><foo attr='long'><bar>short</bar><foobar><ping>tosh</ping></foobar></foo></root>"; |
| |
| final CallParamTestObject testObject = new CallParamTestObject(); |
| |
| final Digester digester = |
| newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); |
| digester.push( testObject ); |
| digester.parse( new StringReader( xml ) ); |
| |
| assertEquals( "Incorrect left value", "long", testObject.getLeft() ); |
| assertEquals( "Incorrect middle value", "short", testObject.getMiddle() ); |
| assertEquals( "Incorrect right value", "", testObject.getRight() ); |
| } |
| |
| @Test |
| public void testInputSourceLoader() throws Exception { |
| final String rulesXml = "<?xml version='1.0'?>" |
| + "<digester-rules>" |
| + " <pattern value='root'>" |
| + " <pattern value='foo'>" |
| + " <call-method-rule methodname='triple' paramcount='3'" |
| + " paramtypes='java.lang.String,java.lang.String,java.lang.String'/>" |
| + " <call-param-rule paramnumber='0' attrname='attr'/>" |
| + " <pattern value='bar'>" |
| + " <call-param-rule paramnumber='1' from-stack='false'/>" |
| + " </pattern>" |
| + " <pattern value='foobar'>" |
| + " <object-create-rule classname='java.lang.String'/>" |
| + " <pattern value='ping'>" |
| + " <call-param-rule paramnumber='2' from-stack='true'/>" |
| + " </pattern>" |
| + " </pattern>" |
| + " </pattern>" |
| + " </pattern>" |
| + "</digester-rules>"; |
| |
| final String xml = "<?xml version='1.0' ?>" |
| + "<root><foo attr='long'><bar>short</bar><foobar><ping>tosh</ping></foobar></foo></root>"; |
| |
| final CallParamTestObject testObject = new CallParamTestObject(); |
| |
| final Digester digester = newLoader( createRules( rulesXml ) ).newDigester(); |
| digester.push( testObject ); |
| digester.parse( new StringReader( xml ) ); |
| |
| assertEquals( "Incorrect left value", "long", testObject.getLeft() ); |
| assertEquals( "Incorrect middle value", "short", testObject.getMiddle() ); |
| assertEquals( "Incorrect right value", "", testObject.getRight() ); |
| } |
| |
| /** |
| * Test the FromXmlRules.addRuleInstances(digester, path) method, ie |
| * test loading rules at a base position other than the root. |
| */ |
| @Test |
| public void testBasePath() |
| throws Exception |
| { |
| final String xmlRules = |
| "<?xml version='1.0'?>" |
| + "<digester-rules>" |
| + " <pattern value='root/foo'>" |
| + " <call-method-rule methodname='setProperty' usingElementBodyAsArgument='true' />" |
| + " </pattern>" |
| + "</digester-rules>"; |
| |
| final String xml = |
| "<?xml version='1.0'?>" |
| + "<root>" |
| + " <foo>success</foo>" |
| + "</root>"; |
| |
| final ObjectTestImpl testObject = new ObjectTestImpl(); |
| final Digester digester = newLoader( createRules( xmlRules ) ).newDigester(); |
| |
| digester.push( testObject ); |
| digester.parse( new InputSource( new StringReader( xml ) ) ); |
| |
| assertEquals( "success", testObject.getProperty() ); |
| } |
| } |