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