001/* $Id: FromXmlRuleSetTest.java 1127922 2011-05-26 14:03:41Z simonetripodi $ 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.commons.digester3.xmlrules; 020 021import static org.apache.commons.digester3.binder.DigesterLoader.newLoader; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertTrue; 024import static org.junit.Assert.fail; 025 026import java.io.InputStream; 027import java.io.StringReader; 028import java.net.URL; 029import java.util.ArrayList; 030 031import org.apache.commons.digester3.Address; 032import org.apache.commons.digester3.Digester; 033import org.apache.commons.digester3.ObjectCreationFactoryTestImpl; 034import org.apache.commons.digester3.binder.RulesModule; 035import org.junit.Test; 036import org.xml.sax.InputSource; 037 038/** 039 * Tests loading Digester rules from an XML file. 040 */ 041 042public class FromXmlRuleSetTest 043{ 044 045 private final RulesModule createRules( final URL xmlRules ) 046 { 047 return new FromXmlRulesModule() 048 { 049 050 @Override 051 protected void loadRules() 052 { 053 loadXMLRules( xmlRules ); 054 } 055 056 }; 057 } 058 059 private final RulesModule createRules( final String xmlText ) 060 { 061 return new FromXmlRulesModule() 062 { 063 064 @Override 065 protected void loadRules() 066 { 067 loadXMLRulesFromText( xmlText ); 068 } 069 070 }; 071 } 072 073 /** 074 * Tests the DigesterLoader.createDigester(), with multiple 075 * included rule sources: testrules.xml includes another rules xml 076 * file, and also includes programmatically created rules. 077 */ 078 @Test 079 public void testCreateDigester() 080 throws Exception 081 { 082 URL rules = getClass().getResource( "testrules.xml" ); 083 URL input = getClass().getResource( "test.xml" ); 084 085 Digester digester = newLoader( createRules( rules ) ).newDigester(); 086 digester.push( new ArrayList<Object>() ); 087 Object root = digester.parse( input.openStream() ); 088 assertEquals( "[foo1 baz1 foo2, foo3 foo4]", root.toString() ); 089 } 090 091 /** 092 * Tests the DigesterLoader.load(), with multiple included rule 093 * sources: testrules.xml includes another rules xml file, and 094 * also includes programmatically created rules. 095 */ 096 @Test 097 public void testLoad1() 098 throws Exception 099 { 100 ClassLoader classLoader = getClass().getClassLoader(); 101 URL rules = getClass().getResource( "testrules.xml" ); 102 URL input = getClass().getResource( "test.xml" ); 103 104 Digester digester = newLoader( createRules( rules ) ).setClassLoader( classLoader ).newDigester(); 105 digester.push( new ArrayList<Object>() ); 106 107 Object root = digester.parse( input ); 108 if ( !( root instanceof ArrayList<?> ) ) 109 { 110 fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " 111 + root.getClass().getName() ); 112 } 113 assertEquals( "[foo1 baz1 foo2, foo3 foo4]", root.toString() ); 114 115 @SuppressWarnings( "unchecked" ) 116 // root is an ArrayList 117 ArrayList<Object> al = (ArrayList<Object>) root; 118 Object obj = al.get( 0 ); 119 if ( !( obj instanceof ObjectTestImpl ) ) 120 { 121 fail( "Unexpected object returned from DigesterLoader. Expected TestObject; got " 122 + obj.getClass().getName() ); 123 } 124 ObjectTestImpl to = (ObjectTestImpl) obj; 125 assertEquals( new Long( 555 ), to.getLongValue() ); 126 assertEquals( "foo", to.getMapValue( "test1" ) ); 127 assertEquals( "bar", to.getMapValue( "test2" ) ); 128 } 129 130 /** 131 * The same as testLoad1, exception the input file is passed to 132 * DigesterLoader as an InputStream instead of a URL. 133 */ 134 @Test 135 public void testLoad2() 136 throws Exception 137 { 138 URL rules = getClass().getResource( "testrules.xml" ); 139 InputStream input = getClass().getResourceAsStream( "test.xml" ); 140 Digester digester = 141 newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); 142 digester.push( new ArrayList<Object>() ); 143 144 ArrayList<Object> list = digester.parse( input ); 145 146 assertEquals( list.toString(), "[foo1 baz1 foo2, foo3 foo4]" ); 147 assertEquals( "Wrong number of classes created", 2, list.size() ); 148 assertEquals( "Pushed first", true, ( (ObjectTestImpl) list.get( 0 ) ).isPushed() ); 149 assertEquals( "Didn't push second", false, ( (ObjectTestImpl) list.get( 1 ) ).isPushed() ); 150 assertTrue( "Property was set properly", 151 ( (ObjectTestImpl) list.get( 0 ) ).getProperty().equals( "I am a property!" ) ); 152 } 153 154 /** 155 */ 156 @Test 157 public void testSetCustomProperties() 158 throws Exception 159 { 160 URL rules = this.getClass().getResource( "testPropertyAliasRules.xml" ); 161 InputStream input = 162 getClass().getClassLoader().getResource( "org/apache/commons/digester3/Test7.xml" ).openStream(); 163 164 Digester digester = 165 newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); 166 digester.push( new ArrayList<Object>() ); 167 168 Object obj = digester.parse( input ); 169 170 if ( !( obj instanceof ArrayList<?> ) ) 171 { 172 fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " + obj.getClass().getName() ); 173 } 174 175 @SuppressWarnings("unchecked") // root is an ArrayList of Address 176 ArrayList<Address> root = (ArrayList<Address>) obj; 177 178 assertEquals( "Wrong array size", 4, root.size() ); 179 180 // note that the array is in popped order (rather than pushed) 181 182 Address add = root.get( 0 ); 183 Address addressOne = add; 184 assertEquals( "(1) Street attribute", "New Street", addressOne.getStreet() ); 185 assertEquals( "(1) City attribute", "Las Vegas", addressOne.getCity() ); 186 assertEquals( "(1) State attribute", "Nevada", addressOne.getState() ); 187 188 add = root.get( 1 ); 189 Address addressTwo = add; 190 assertEquals( "(2) Street attribute", "Old Street", addressTwo.getStreet() ); 191 assertEquals( "(2) City attribute", "Portland", addressTwo.getCity() ); 192 assertEquals( "(2) State attribute", "Oregon", addressTwo.getState() ); 193 194 add = root.get( 2 ); 195 Address addressThree = add; 196 assertEquals( "(3) Street attribute", "4th Street", addressThree.getStreet() ); 197 assertEquals( "(3) City attribute", "Dayton", addressThree.getCity() ); 198 assertEquals( "(3) State attribute", "US", addressThree.getState() ); 199 200 add = root.get( 3 ); 201 Address addressFour = add; 202 assertEquals( "(4) Street attribute", "6th Street", addressFour.getStreet() ); 203 assertEquals( "(4) City attribute", "Cleveland", addressFour.getCity() ); 204 assertEquals( "(4) State attribute", "Ohio", addressFour.getState() ); 205 } 206 207 @Test 208 public void testFactoryCreateRule() 209 throws Exception 210 { 211 URL rules = getClass().getResource( "testfactory.xml" ); 212 String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; 213 214 Digester digester = 215 newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); 216 digester.push( new ArrayList<ObjectCreationFactoryTestImpl>() ); 217 218 Object obj = digester.parse( new StringReader( xml ) ); 219 if ( !( obj instanceof ArrayList<?> ) ) 220 { 221 fail( "Unexpected object returned from DigesterLoader. Expected ArrayList; got " + obj.getClass().getName() ); 222 } 223 224 @SuppressWarnings("unchecked") // root is an ArrayList of TestObjectCreationFactory 225 ArrayList<ObjectCreationFactoryTestImpl> list = (ArrayList<ObjectCreationFactoryTestImpl>) obj; 226 227 assertEquals( "List should contain only the factory object", list.size(), 1 ); 228 ObjectCreationFactoryTestImpl factory = list.get( 0 ); 229 assertEquals( "Object create not called(1)", factory.called, true ); 230 assertEquals( "Attribute not passed (1)", factory.attributes.getValue( "one" ), "good" ); 231 assertEquals( "Attribute not passed (2)", factory.attributes.getValue( "two" ), "bad" ); 232 assertEquals( "Attribute not passed (3)", factory.attributes.getValue( "three" ), "ugly" ); 233 } 234 235 @Test 236 public void testFactoryIgnoreCreateRule() 237 throws Exception 238 { 239 URL rules = getClass().getResource( "testfactoryignore.xml" ); 240 241 String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; 242 try { 243 newLoader(createRules(rules)).newDigester().parse(new StringReader(xml)); 244 } catch (Exception e) { 245 fail("This exception should have been ignored: " + e.getClass().getName()); 246 } 247 } 248 249 @Test 250 public void testFactoryNotIgnoreCreateRule() 251 throws Exception 252 { 253 URL rules = getClass().getResource( "testfactorynoignore.xml" ); 254 255 String xml = "<?xml version='1.0' ?><root one='good' two='bad' three='ugly'><foo/></root>"; 256 try 257 { 258 newLoader( createRules( rules ) ).newDigester().parse( new StringReader( xml ) ); 259 fail( "Exception should have been propagated from create method." ); 260 } 261 catch ( Exception e ) 262 { 263 /* What we expected */ 264 assertEquals( org.xml.sax.SAXParseException.class, e.getClass() ); 265 } 266 } 267 268 @Test 269 public void testCallParamRule() 270 throws Exception 271 { 272 URL rules = getClass().getResource( "test-call-param-rules.xml" ); 273 274 String xml = "<?xml version='1.0' ?>" 275 + "<root><foo attr='long'><bar>short</bar><foobar><ping>tosh</ping></foobar></foo></root>"; 276 277 CallParamTestObject testObject = new CallParamTestObject(); 278 279 Digester digester = 280 newLoader( createRules( rules ) ).setClassLoader( this.getClass().getClassLoader() ).newDigester(); 281 digester.push( testObject ); 282 digester.parse( new StringReader( xml ) ); 283 284 assertEquals( "Incorrect left value", "long", testObject.getLeft() ); 285 assertEquals( "Incorrect middle value", "short", testObject.getMiddle() ); 286 assertEquals( "Incorrect right value", "", testObject.getRight() ); 287 } 288 289 @Test 290 public void testInputSourceLoader() throws Exception { 291 String rulesXml = "<?xml version='1.0'?>" 292 + "<digester-rules>" 293 + " <pattern value='root'>" 294 + " <pattern value='foo'>" 295 + " <call-method-rule methodname='triple' paramcount='3'" 296 + " paramtypes='java.lang.String,java.lang.String,java.lang.String'/>" 297 + " <call-param-rule paramnumber='0' attrname='attr'/>" 298 + " <pattern value='bar'>" 299 + " <call-param-rule paramnumber='1' from-stack='false'/>" 300 + " </pattern>" 301 + " <pattern value='foobar'>" 302 + " <object-create-rule classname='java.lang.String'/>" 303 + " <pattern value='ping'>" 304 + " <call-param-rule paramnumber='2' from-stack='true'/>" 305 + " </pattern>" 306 + " </pattern>" 307 + " </pattern>" 308 + " </pattern>" 309 + "</digester-rules>"; 310 311 String xml = "<?xml version='1.0' ?>" 312 + "<root><foo attr='long'><bar>short</bar><foobar><ping>tosh</ping></foobar></foo></root>"; 313 314 CallParamTestObject testObject = new CallParamTestObject(); 315 316 Digester digester = newLoader( createRules( rulesXml ) ).newDigester(); 317 digester.push( testObject ); 318 digester.parse( new StringReader( xml ) ); 319 320 assertEquals( "Incorrect left value", "long", testObject.getLeft() ); 321 assertEquals( "Incorrect middle value", "short", testObject.getMiddle() ); 322 assertEquals( "Incorrect right value", "", testObject.getRight() ); 323 } 324 325 /** 326 * Test the FromXmlRules.addRuleInstances(digester, path) method, ie 327 * test loading rules at a base position other than the root. 328 */ 329 @Test 330 public void testBasePath() 331 throws Exception 332 { 333 String xmlRules = 334 "<?xml version='1.0'?>" 335 + "<digester-rules>" 336 + " <pattern value='root/foo'>" 337 + " <call-method-rule methodname='setProperty' usingElementBodyAsArgument='true' />" 338 + " </pattern>" 339 + "</digester-rules>"; 340 341 String xml = 342 "<?xml version='1.0'?>" 343 + "<root>" 344 + " <foo>success</foo>" 345 + "</root>"; 346 347 ObjectTestImpl testObject = new ObjectTestImpl(); 348 Digester digester = newLoader( createRules( xmlRules ) ).newDigester(); 349 350 digester.push( testObject ); 351 digester.parse( new InputSource( new StringReader( xml ) ) ); 352 353 assertEquals( "success", testObject.getProperty() ); 354 } 355}