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.defaults;
011    
012    import org.picocontainer.ComponentAdapter;
013    import org.picocontainer.PicoInitializationException;
014    import org.picocontainer.tck.AbstractComponentAdapterFactoryTestCase;
015    import org.picocontainer.testmodel.SimpleTouchable;
016    import org.picocontainer.testmodel.Touchable;
017    
018    import java.io.File;
019    import java.net.MalformedURLException;
020    import java.net.URL;
021    import java.text.SimpleDateFormat;
022    import java.util.Date;
023    import java.util.HashMap;
024    import java.util.Map;
025    import javax.swing.*;
026    
027    /**
028     * @author Aslak Hellesøy
029     * @author Mirko Novakovic
030     * @version $Revision: 2316 $
031     */
032    public class BeanPropertyComponentAdapterFactoryTestCase extends AbstractComponentAdapterFactoryTestCase {
033    
034        public static class Foo {
035            public String message;
036    
037            public void setMessage(String message) {
038                this.message = message;
039            }
040        }
041    
042        public static class Failing {
043            public void setMessage(String message) {
044                throw new ArrayIndexOutOfBoundsException();
045            }
046        }
047    
048        /**
049         * Class that contains all types of Java primitives, to test if they are
050         * set correctly.
051         *
052         * @author Mirko Novakovic
053         */
054        public static class Primitives {
055            public byte byte_;
056            public short short_;
057            public int int_;
058            public long long_;
059            public float float_;
060            public double double_;
061            public boolean boolean_;
062            public char char_;
063            public File file_;
064            public URL url_;
065            public Class class_;
066            public String string_;
067    
068            public void setClass_(Class class_) {
069                this.class_ = class_;
070            }
071    
072            public void setString_(String string_) {
073                this.string_ = string_;
074            }
075    
076            public void setBoolean_(boolean boolean_) {
077                this.boolean_ = boolean_;
078            }
079    
080            public void setByte_(byte byte_) {
081                this.byte_ = byte_;
082            }
083    
084            public void setChar_(char char_) {
085                this.char_ = char_;
086            }
087    
088            public void setDouble_(double double_) {
089                this.double_ = double_;
090            }
091    
092            public void setFloat_(float float_) {
093                this.float_ = float_;
094            }
095    
096            public void setInt_(int int_) {
097                this.int_ = int_;
098            }
099    
100            public void setLong_(long long_) {
101                this.long_ = long_;
102            }
103    
104            public void setShort_(short short_) {
105                this.short_ = short_;
106            }
107    
108            public void setFile_(File file_) {
109                this.file_ = file_;
110            }
111    
112            public void setUrl_(URL url_) {
113                this.url_ = url_;
114            }
115        }
116    
117        public static class A {
118            private B b;
119    
120            public void setB(B b) {
121                this.b = b;
122            }
123        }
124    
125        public static class B {
126        }
127    
128        public void testSetProperties() {
129            ComponentAdapter adapter = createAdapterCallingSetMessage(Foo.class);
130            Foo foo = (Foo) adapter.getComponentInstance(null);
131            assertNotNull(foo);
132            assertEquals("hello", foo.message);
133        }
134    
135        public void testFailingSetter() {
136            ComponentAdapter adapter = createAdapterCallingSetMessage(Failing.class);
137            try {
138                adapter.getComponentInstance(null);
139                fail();
140            } catch (PicoInitializationException e) {
141            }
142        }
143    
144        protected ComponentAdapterFactory createComponentAdapterFactory() {
145            return new BeanPropertyComponentAdapterFactory(new DefaultComponentAdapterFactory());
146        }
147    
148        public void testPropertiesSetAfterAdapterCreationShouldBeTakenIntoAccount() {
149            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
150    
151            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter) factory.createComponentAdapter("foo", Foo.class, null);
152    
153            Map properties = new HashMap();
154            properties.put("message", "hello");
155            adapter.setProperties(properties);
156    
157            Foo foo = (Foo) adapter.getComponentInstance(null);
158    
159            assertEquals("hello", foo.message);
160        }
161    
162    
163        public void testDelegateIsAccessible() {
164            DecoratingComponentAdapter componentAdapter =
165                    (DecoratingComponentAdapter) createComponentAdapterFactory().createComponentAdapter(Touchable.class, SimpleTouchable.class, null);
166    
167            assertNotNull(componentAdapter.getDelegate());
168        }
169    
170        private ComponentAdapter createAdapterCallingSetMessage(Class impl) {
171            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
172    
173            Map properties = new HashMap();
174            properties.put("message", "hello");
175    
176            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter) factory.createComponentAdapter(impl, impl, null);
177            adapter.setProperties(properties);
178            return adapter;
179        }
180    
181        public void testAllJavaPrimitiveAttributesShouldBeSetByTheAdapter() throws MalformedURLException {
182            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
183            Map properties = new HashMap();
184            properties.put("byte_", "1");
185            properties.put("short_", "2");
186            properties.put("int_", "3");
187            properties.put("long_", "4");
188            properties.put("float_", "5.0");
189            properties.put("double_", "6.0");
190            properties.put("char_", "a");
191            properties.put("boolean_", "true");
192            properties.put("file_", "/foo/bar");
193            properties.put("url_", "http://www.picocontainer.org/");
194            properties.put("string_", "g string");
195            properties.put("class_", "javax.swing.JLabel");
196            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter) factory.createComponentAdapter(Primitives.class, Primitives.class, null);
197            adapter.setProperties(properties);
198            Primitives primitives = (Primitives) adapter.getComponentInstance(null);
199    
200            assertNotNull(primitives);
201            assertEquals(1, primitives.byte_);
202            assertEquals(2, primitives.short_);
203            assertEquals(3, primitives.int_);
204            assertEquals(4, primitives.long_);
205            assertEquals(5.0, primitives.float_, 0.1);
206            assertEquals(6.0, primitives.double_, 0.1);
207            assertEquals('a', primitives.char_);
208            assertEquals(true, primitives.boolean_);
209            assertEquals(new File("/foo/bar"), primitives.file_);
210            assertEquals(new URL("http://www.picocontainer.org/"), primitives.url_);
211            assertEquals("g string", primitives.string_);
212            assertEquals(JLabel.class, primitives.class_);
213        }
214    
215        public void testSetDependenComponentWillBeSetByTheAdapter() {
216            picoContainer.registerComponentImplementation("b", B.class);
217            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
218            Map properties = new HashMap();
219    
220            // the second b is the key of the B implementation
221            properties.put("b", "b");
222            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter) factory.createComponentAdapter(A.class, A.class, null);
223            adapter.setProperties(properties);
224            picoContainer.registerComponent(adapter);
225            A a = (A) picoContainer.getComponentInstance(A.class);
226    
227            assertNotNull(a);
228            assertNotNull(a.b);
229        }
230    
231        public void testSetBeanPropertiesWithValueObjects() {
232          BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
233    
234          Map properties = new HashMap();
235          properties.put("lenient", Boolean.FALSE);
236          properties.put("2DigitYearStart", new Date(0));
237    
238          BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter)factory.createComponentAdapter(SimpleDateFormat.class,SimpleDateFormat.class,null);
239          adapter.setProperties(properties);
240          picoContainer.registerComponent(adapter);
241    
242    
243          SimpleDateFormat dateFormat = (SimpleDateFormat)picoContainer.getComponentInstance(SimpleDateFormat.class);
244          assertNotNull(dateFormat);
245          assertEquals(false, dateFormat.isLenient());
246          assertEquals(new Date(0), dateFormat.get2DigitYearStart());
247        }
248    
249    
250        /**
251         * todo Is this test duplicated elsewhere?  --MR
252         */
253        public void testSetBeanPropertiesWithWrongNumberOfParametersThrowsPicoInitializationException() {
254            Object testBean = new Object() {
255                public void setMultiValues(String val1, String Val2) {
256                    throw new IllegalStateException("Setter should never have been called");
257                }
258    
259                public void setSomeString(String val1) {
260                    throw new IllegalStateException("Setter should never have been called");
261                }
262            };
263    
264            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
265    
266    
267            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter)factory.createComponentAdapter("TestBean",testBean.getClass(),null);
268    
269            Map properties = new HashMap();
270            properties.put("multiValues","abcdefg");
271            adapter.setProperties(properties);
272    
273            picoContainer.registerComponent(adapter);
274    
275            try {
276                Object testResult = picoContainer.getComponentInstance("TestBean");
277                fail("Getting a bad test result through BeanPropertyComponentAdapter should have thrown exception.  Instead got:" + testResult);
278            } catch (PicoInitializationException ex) {
279                //A-ok
280            }
281    
282        }
283    
284    
285        public void testSetBeanPropertiesWithInvalidValueTypes() {
286            BeanPropertyComponentAdapterFactory factory = (BeanPropertyComponentAdapterFactory) createComponentAdapterFactory();
287    
288    
289            Map properties = new HashMap();
290    
291            // Set two digit year to a boolean (should throw error)
292            properties.put("2DigitYearStart", Boolean.FALSE);
293            BeanPropertyComponentAdapter adapter = (BeanPropertyComponentAdapter)factory.createComponentAdapter(SimpleDateFormat.class,SimpleDateFormat.class,null);
294            adapter.setProperties(properties);
295            picoContainer.registerComponent(adapter);
296    
297    
298            try {
299                SimpleDateFormat dateFormat = (SimpleDateFormat) picoContainer.getComponentInstance(SimpleDateFormat.class);
300                fail("Getting a bad test result through BeanPropertyComponentAdapter should have thrown exception.  Instead got:" + dateFormat);
301            } catch (ClassCastException ex) {
302                //A-ok
303            }
304    
305        }
306    }