001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 * * 008 * Original code by * 009 *****************************************************************************/ 010 package org.picocontainer.behaviors; 011 012 013 import static org.junit.Assert.assertEquals; 014 import static org.junit.Assert.assertNotNull; 015 import static org.junit.Assert.fail; 016 017 import java.io.File; 018 import java.net.MalformedURLException; 019 import java.net.URL; 020 import java.text.SimpleDateFormat; 021 import java.util.Date; 022 import java.util.HashMap; 023 import java.util.Map; 024 import java.util.Properties; 025 026 import javax.swing.JLabel; 027 028 import org.junit.Test; 029 import org.picocontainer.Characteristics; 030 import org.picocontainer.ComponentAdapter; 031 import org.picocontainer.ComponentFactory; 032 import org.picocontainer.DefaultPicoContainer; 033 import org.picocontainer.Parameter; 034 import org.picocontainer.PicoCompositionException; 035 import org.picocontainer.injectors.AdaptingInjection; 036 import org.picocontainer.lifecycle.NullLifecycleStrategy; 037 import org.picocontainer.monitors.NullComponentMonitor; 038 import org.picocontainer.tck.AbstractComponentFactoryTest; 039 import org.picocontainer.testmodel.SimpleTouchable; 040 import org.picocontainer.testmodel.Touchable; 041 042 043 /** 044 * @author Aslak Hellesøy 045 * @author Mirko Novakovic 046 */ 047 public class PropertyApplyingTestCase extends AbstractComponentFactoryTest { 048 049 public static class Foo { 050 public String message; 051 052 public void setMessage(String message) { 053 this.message = message; 054 } 055 } 056 057 public static class Failing { 058 public void setMessage(String message) { 059 throw new ArrayIndexOutOfBoundsException(); 060 } 061 } 062 063 /** 064 * Class that contains all types of Java primitives, to test if they are 065 * set correctly. 066 * 067 * @author Mirko Novakovic 068 */ 069 public static class Primitives { 070 public byte byte_; 071 public short short_; 072 public int int_; 073 public long long_; 074 public float float_; 075 public double double_; 076 public boolean boolean_; 077 public char char_; 078 public File file_; 079 public URL url_; 080 public Class class_; 081 public String string_; 082 083 public void setClass_(Class class_) { 084 this.class_ = class_; 085 } 086 087 public void setString_(String string_) { 088 this.string_ = string_; 089 } 090 091 public void setBoolean_(boolean boolean_) { 092 this.boolean_ = boolean_; 093 } 094 095 public void setByte_(byte byte_) { 096 this.byte_ = byte_; 097 } 098 099 public void setChar_(char char_) { 100 this.char_ = char_; 101 } 102 103 public void setDouble_(double double_) { 104 this.double_ = double_; 105 } 106 107 public void setFloat_(float float_) { 108 this.float_ = float_; 109 } 110 111 public void setInt_(int int_) { 112 this.int_ = int_; 113 } 114 115 public void setLong_(long long_) { 116 this.long_ = long_; 117 } 118 119 public void setShort_(short short_) { 120 this.short_ = short_; 121 } 122 123 public void setFile_(File file_) { 124 this.file_ = file_; 125 } 126 127 public void setUrl_(URL url_) { 128 this.url_ = url_; 129 } 130 } 131 132 public static class A { 133 private B b; 134 135 public void setB(B b) { 136 this.b = b; 137 } 138 } 139 140 public static class B { 141 } 142 143 @Test public void testSetProperties() { 144 ComponentAdapter adapter = createAdapterCallingSetMessage(Foo.class); 145 Foo foo = (Foo)adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 146 assertNotNull(foo); 147 assertEquals("hello", foo.message); 148 } 149 150 @Test public void testFailingSetter() { 151 ComponentAdapter adapter = createAdapterCallingSetMessage(Failing.class); 152 try { 153 adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 154 fail(); 155 } catch (PicoCompositionException e) { 156 } 157 } 158 159 protected ComponentFactory createComponentFactory() { 160 return new PropertyApplying().wrap(new AdaptingInjection()); 161 } 162 163 @Test public void testPropertiesSetAfterAdapterCreationShouldBeTakenIntoAccount() { 164 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 165 166 PropertyApplicator adapter = 167 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 168 new NullLifecycleStrategy(), 169 new Properties(Characteristics 170 .CDI), 171 "foo", 172 Foo.class, 173 (Parameter[])null); 174 175 Map properties = new HashMap(); 176 properties.put("message", "hello"); 177 adapter.setProperties(properties); 178 179 Foo foo = (Foo)adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 180 181 assertEquals("hello", foo.message); 182 } 183 184 @Test public void testPropertySetAfterAdapterCreationShouldBeTakenIntoAccount() { 185 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 186 187 PropertyApplicator adapter = 188 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 189 new NullLifecycleStrategy(), 190 new Properties(Characteristics 191 .CDI), 192 "foo", 193 Foo.class, 194 (Parameter[])null); 195 adapter.setProperty("message", "hello"); 196 197 Foo foo = (Foo)adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 198 199 assertEquals("hello", foo.message); 200 } 201 202 203 @Test public void testPropertiesTidiedUpAfterPicoUsage() { 204 DefaultPicoContainer pico = new DefaultPicoContainer(createComponentFactory()); 205 pico.as(Characteristics.PROPERTY_APPLYING).addComponent("foo", Foo.class); 206 Foo foo = (Foo) pico.getComponent("foo"); 207 } 208 209 210 @Test public void testDelegateIsAccessible() { 211 AbstractBehavior componentAdapter = 212 (AbstractBehavior)createComponentFactory().createComponentAdapter(new NullComponentMonitor(), 213 new NullLifecycleStrategy(), 214 new Properties(Characteristics 215 .CDI), 216 Touchable.class, 217 SimpleTouchable.class, 218 (Parameter[])null); 219 220 assertNotNull(componentAdapter.getDelegate()); 221 } 222 223 private ComponentAdapter createAdapterCallingSetMessage(Class impl) { 224 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 225 226 Map properties = new HashMap(); 227 properties.put("message", "hello"); 228 229 PropertyApplicator adapter = 230 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 231 new NullLifecycleStrategy(), 232 new Properties(Characteristics 233 .CDI), 234 impl, 235 impl, 236 (Parameter[])null); 237 adapter.setProperties(properties); 238 return adapter; 239 } 240 241 @Test public void testAllJavaPrimitiveAttributesShouldBeSetByTheAdapter() throws MalformedURLException { 242 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 243 Map properties = new HashMap(); 244 properties.put("byte_", "1"); 245 properties.put("short_", "2"); 246 properties.put("int_", "3"); 247 properties.put("long_", "4"); 248 properties.put("float_", "5.0"); 249 properties.put("double_", "6.0"); 250 properties.put("char_", "a"); 251 properties.put("boolean_", "true"); 252 properties.put("file_", "/foo/bar"); 253 properties.put("url_", "http://www.picocontainer.org/"); 254 properties.put("string_", "g string"); 255 properties.put("class_", "javax.swing.JLabel"); 256 PropertyApplicator adapter = 257 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 258 new NullLifecycleStrategy(), 259 new Properties(Characteristics 260 .CDI), 261 Primitives.class, 262 Primitives.class, 263 (Parameter[])null); 264 adapter.setProperties(properties); 265 Primitives primitives = (Primitives)adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 266 267 assertNotNull(primitives); 268 assertEquals(1, primitives.byte_); 269 assertEquals(2, primitives.short_); 270 assertEquals(3, primitives.int_); 271 assertEquals(4, primitives.long_); 272 assertEquals(5.0, primitives.float_, 0.1); 273 assertEquals(6.0, primitives.double_, 0.1); 274 assertEquals('a', primitives.char_); 275 assertEquals(true, primitives.boolean_); 276 assertEquals(new File("/foo/bar"), primitives.file_); 277 assertEquals(new URL("http://www.picocontainer.org/"), primitives.url_); 278 assertEquals("g string", primitives.string_); 279 assertEquals(JLabel.class, primitives.class_); 280 } 281 282 @Test public void testSetDependenComponentWillBeSetByTheAdapter() { 283 picoContainer.addComponent("b", B.class); 284 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 285 Map properties = new HashMap(); 286 287 // the second b is the key of the B implementation 288 properties.put("b", "b"); 289 PropertyApplicator adapter = 290 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 291 new NullLifecycleStrategy(), 292 new Properties(Characteristics 293 .CDI), 294 A.class, 295 A.class, 296 (Parameter[])null); 297 adapter.setProperties(properties); 298 picoContainer.addAdapter(adapter); 299 A a = picoContainer.getComponent(A.class); 300 301 assertNotNull(a); 302 assertNotNull(a.b); 303 } 304 305 @Test public void testPropertySetAfterWrappedAdapterCreationShouldBeTakenIntoAccount() { 306 Caching factory = (Caching) new Caching().wrap(createComponentFactory()); 307 308 ComponentAdapter<?> adapter = 309 factory.createComponentAdapter(new NullComponentMonitor(), 310 new NullLifecycleStrategy(), 311 new Properties(Characteristics 312 .CDI), 313 "foo", 314 Foo.class, 315 (Parameter[])null); 316 317 318 PropertyApplicator pa = adapter.findAdapterOfType(PropertyApplicator.class); 319 320 pa.setProperty("message", "hello"); 321 322 Foo foo = (Foo)adapter.getComponentInstance(null, ComponentAdapter.NOTHING.class); 323 324 assertEquals("hello", foo.message); 325 } 326 327 @Test public void testSetBeanPropertiesWithValueObjects() { 328 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 329 330 Map properties = new HashMap(); 331 properties.put("lenient", Boolean.FALSE); 332 properties.put("2DigitYearStart", new Date(0)); 333 334 PropertyApplicator adapter = 335 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 336 new NullLifecycleStrategy(), 337 new Properties(Characteristics 338 .CDI), 339 SimpleDateFormat.class, 340 SimpleDateFormat.class, 341 (Parameter[])null); 342 adapter.setProperties(properties); 343 picoContainer.addAdapter(adapter); 344 345 346 SimpleDateFormat dateFormat = picoContainer.getComponent(SimpleDateFormat.class); 347 assertNotNull(dateFormat); 348 assertEquals(false, dateFormat.isLenient()); 349 assertEquals(new Date(0), dateFormat.get2DigitYearStart()); 350 } 351 352 353 /** todo Is this test duplicated elsewhere? --MR */ 354 @Test public void testSetBeanPropertiesWithWrongNumberOfParametersThrowsPicoInitializationException() { 355 Object testBean = new Object() { 356 public void setMultiValues(String val1, String Val2) { 357 throw new IllegalStateException("Setter should never have been called"); 358 } 359 360 public void setSomeString(String val1) { 361 throw new IllegalStateException("Setter should never have been called"); 362 } 363 }; 364 365 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 366 367 368 PropertyApplicator adapter = 369 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 370 new NullLifecycleStrategy(), 371 new Properties(Characteristics 372 .CDI), 373 "TestBean", 374 testBean.getClass(), 375 (Parameter[])null); 376 377 Map properties = new HashMap(); 378 properties.put("multiValues", "abcdefg"); 379 adapter.setProperties(properties); 380 381 picoContainer.addAdapter(adapter); 382 383 try { 384 Object testResult = picoContainer.getComponent("TestBean"); 385 fail( 386 "Getting a bad test result through PropertyApplicator should have thrown exception. Instead got:" + 387 testResult); 388 } catch (PicoCompositionException ex) { 389 //A-ok 390 } 391 392 } 393 394 395 @Test public void testSetBeanPropertiesWithInvalidValueTypes() { 396 PropertyApplying factory = (PropertyApplying)createComponentFactory(); 397 398 399 Map properties = new HashMap(); 400 401 // Set two digit year to a boolean (should throw error) 402 properties.put("2DigitYearStart", Boolean.FALSE); 403 PropertyApplicator adapter = 404 (PropertyApplicator)factory.createComponentAdapter(new NullComponentMonitor(), 405 new NullLifecycleStrategy(), 406 new Properties(Characteristics 407 .CDI), 408 SimpleDateFormat.class, 409 SimpleDateFormat.class, 410 (Parameter[])null); 411 adapter.setProperties(properties); 412 picoContainer.addAdapter(adapter); 413 414 415 try { 416 SimpleDateFormat dateFormat = picoContainer.getComponent(SimpleDateFormat.class); 417 fail( 418 "Getting a bad test result through PropertyApplicator should have thrown exception. Instead got:" + 419 dateFormat); 420 } catch (ClassCastException ex) { 421 //A-ok 422 } 423 424 } 425 }