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.PropertyApplyingBehavior;
030    import org.picocontainer.behaviors.PropertyApplyingBehaviorFactory;
031    import org.picocontainer.injectors.AdaptiveInjectionFactory;
032    import org.picocontainer.behaviors.AbstractBehavior;
033    import org.picocontainer.ComponentFactory;
034    import org.picocontainer.tck.AbstractComponentFactoryTestCase;
035    import org.picocontainer.testmodel.SimpleTouchable;
036    import org.picocontainer.testmodel.Touchable;
037    
038    /**
039     * @author Aslak Hellesøy
040     * @author Mirko Novakovic
041     * @version $Revision: 3677 $
042     */
043    public class PropertyApplyingBehaviorFactoryTestCase 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 PropertyApplyingBehaviorFactory().forThis(new AdaptiveInjectionFactory());
157        }
158    
159        public void testPropertiesSetAfterAdapterCreationShouldBeTakenIntoAccount() {
160            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
161    
162            PropertyApplyingBehavior adapter =
163                (PropertyApplyingBehavior)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    
181        public void testDelegateIsAccessible() {
182            AbstractBehavior componentAdapter =
183                (AbstractBehavior)createComponentFactory().createComponentAdapter(new NullComponentMonitor(),
184                                                                                  new NullLifecycleStrategy(),
185                                                                                  new Properties(Characteristics
186                                                                                      .CDI),
187                                                                                  Touchable.class,
188                                                                                  SimpleTouchable.class,
189                                                                                  (Parameter[])null);
190    
191            assertNotNull(componentAdapter.getDelegate());
192        }
193    
194        private ComponentAdapter createAdapterCallingSetMessage(Class impl) {
195            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
196    
197            Map properties = new HashMap();
198            properties.put("message", "hello");
199    
200            PropertyApplyingBehavior adapter =
201                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
202                                                                         new NullLifecycleStrategy(),
203                                                                         new Properties(Characteristics
204                                                                             .CDI),
205                                                                         impl,
206                                                                         impl,
207                                                                         (Parameter[])null);
208            adapter.setProperties(properties);
209            return adapter;
210        }
211    
212        public void testAllJavaPrimitiveAttributesShouldBeSetByTheAdapter() throws MalformedURLException {
213            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
214            Map properties = new HashMap();
215            properties.put("byte_", "1");
216            properties.put("short_", "2");
217            properties.put("int_", "3");
218            properties.put("long_", "4");
219            properties.put("float_", "5.0");
220            properties.put("double_", "6.0");
221            properties.put("char_", "a");
222            properties.put("boolean_", "true");
223            properties.put("file_", "/foo/bar");
224            properties.put("url_", "http://www.picocontainer.org/");
225            properties.put("string_", "g string");
226            properties.put("class_", "javax.swing.JLabel");
227            PropertyApplyingBehavior adapter =
228                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
229                                                                         new NullLifecycleStrategy(),
230                                                                         new Properties(Characteristics
231                                                                             .CDI),
232                                                                         Primitives.class,
233                                                                         Primitives.class,
234                                                                         (Parameter[])null);
235            adapter.setProperties(properties);
236            Primitives primitives = (Primitives)adapter.getComponentInstance(null);
237    
238            assertNotNull(primitives);
239            assertEquals(1, primitives.byte_);
240            assertEquals(2, primitives.short_);
241            assertEquals(3, primitives.int_);
242            assertEquals(4, primitives.long_);
243            assertEquals(5.0, primitives.float_, 0.1);
244            assertEquals(6.0, primitives.double_, 0.1);
245            assertEquals('a', primitives.char_);
246            assertEquals(true, primitives.boolean_);
247            assertEquals(new File("/foo/bar"), primitives.file_);
248            assertEquals(new URL("http://www.picocontainer.org/"), primitives.url_);
249            assertEquals("g string", primitives.string_);
250            assertEquals(JLabel.class, primitives.class_);
251        }
252    
253        public void testSetDependenComponentWillBeSetByTheAdapter() {
254            picoContainer.addComponent("b", B.class);
255            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
256            Map properties = new HashMap();
257    
258            // the second b is the key of the B implementation
259            properties.put("b", "b");
260            PropertyApplyingBehavior adapter =
261                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
262                                                                         new NullLifecycleStrategy(),
263                                                                         new Properties(Characteristics
264                                                                             .CDI),
265                                                                         A.class,
266                                                                         A.class,
267                                                                         (Parameter[])null);
268            adapter.setProperties(properties);
269            picoContainer.addAdapter(adapter);
270            A a = picoContainer.getComponent(A.class);
271    
272            assertNotNull(a);
273            assertNotNull(a.b);
274        }
275    
276        public void testSetBeanPropertiesWithValueObjects() {
277            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
278    
279            Map properties = new HashMap();
280            properties.put("lenient", Boolean.FALSE);
281            properties.put("2DigitYearStart", new Date(0));
282    
283            PropertyApplyingBehavior adapter =
284                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
285                                                                         new NullLifecycleStrategy(),
286                                                                         new Properties(Characteristics
287                                                                             .CDI),
288                                                                         SimpleDateFormat.class,
289                                                                         SimpleDateFormat.class,
290                                                                         (Parameter[])null);
291            adapter.setProperties(properties);
292            picoContainer.addAdapter(adapter);
293    
294    
295            SimpleDateFormat dateFormat = picoContainer.getComponent(SimpleDateFormat.class);
296            assertNotNull(dateFormat);
297            assertEquals(false, dateFormat.isLenient());
298            assertEquals(new Date(0), dateFormat.get2DigitYearStart());
299        }
300    
301    
302        /** todo Is this test duplicated elsewhere?  --MR */
303        public void testSetBeanPropertiesWithWrongNumberOfParametersThrowsPicoInitializationException() {
304            Object testBean = new Object() {
305                public void setMultiValues(String val1, String Val2) {
306                    throw new IllegalStateException("Setter should never have been called");
307                }
308    
309                public void setSomeString(String val1) {
310                    throw new IllegalStateException("Setter should never have been called");
311                }
312            };
313    
314            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
315    
316    
317            PropertyApplyingBehavior adapter =
318                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
319                                                                         new NullLifecycleStrategy(),
320                                                                         new Properties(Characteristics
321                                                                             .CDI),
322                                                                         "TestBean",
323                                                                         testBean.getClass(),
324                                                                         (Parameter[])null);
325    
326            Map properties = new HashMap();
327            properties.put("multiValues", "abcdefg");
328            adapter.setProperties(properties);
329    
330            picoContainer.addAdapter(adapter);
331    
332            try {
333                Object testResult = picoContainer.getComponent("TestBean");
334                fail(
335                    "Getting a bad test result through PropertyApplyingBehavior should have thrown exception.  Instead got:" +
336                    testResult);
337            } catch (PicoCompositionException ex) {
338                //A-ok
339            }
340    
341        }
342    
343    
344        public void testSetBeanPropertiesWithInvalidValueTypes() {
345            PropertyApplyingBehaviorFactory factory = (PropertyApplyingBehaviorFactory)createComponentFactory();
346    
347    
348            Map properties = new HashMap();
349    
350            // Set two digit year to a boolean (should throw error)
351            properties.put("2DigitYearStart", Boolean.FALSE);
352            PropertyApplyingBehavior adapter =
353                (PropertyApplyingBehavior)factory.createComponentAdapter(new NullComponentMonitor(),
354                                                                         new NullLifecycleStrategy(),
355                                                                         new Properties(Characteristics
356                                                                             .CDI),
357                                                                         SimpleDateFormat.class,
358                                                                         SimpleDateFormat.class,
359                                                                         (Parameter[])null);
360            adapter.setProperties(properties);
361            picoContainer.addAdapter(adapter);
362    
363    
364            try {
365                SimpleDateFormat dateFormat = picoContainer.getComponent(SimpleDateFormat.class);
366                fail(
367                    "Getting a bad test result through PropertyApplyingBehavior should have thrown exception.  Instead got:" +
368                    dateFormat);
369            } catch (ClassCastException ex) {
370                //A-ok
371            }
372    
373        }
374    }