    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&oslash;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    }