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 }