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;
011    
012    import java.util.Map;
013    import java.util.Properties;
014    
015    /**
016     * Collection of immutable properties, holding behaviour characteristics.  See 
017     * <a href="http://www.picocontainer.org/behaviors.html">The PicoContainer Website</a> for details on the usage
018     * of Characteristics.
019     * 
020     * @author Paul Hammant
021     * @see org.picocontainer.ComponentAdapter
022     * @see org.picocontainer.Behavior
023     */
024    @SuppressWarnings("serial")
025    public final class Characteristics {
026    
027        private static final String _INJECTION = "injection";
028        private static final String _NONE = "none";
029        private static final String _CONSTRUCTOR = "constructor";
030        private static final String _METHOD = "method";
031        private static final String _SETTER = "setter";
032        private static final String _CACHE = "cache";
033        private static final String _SYNCHRONIZING = "synchronizing";
034        private static final String _LOCKING = "locking";
035        private static final String _HIDE_IMPL = "hide-impl";
036        private static final String _PROPERTY_APPLYING = "property-applying";
037        private static final String _AUTOMATIC = "automatic";
038        private static final String _USE_NAMES = "use-parameter-names";    
039        private static final String _ENABLE_CIRCULAR = "enable-circular";
040        private static final String _GUARD = "guard";
041        private static final String _EMJECTION = "emjection_enabled";
042    
043        /**
044         * Since properties use strings, we supply String constants for Boolean conditions.
045         */
046        public static final String FALSE = "false";
047    
048        /**
049         * Since properties use strings, we supply String constants for Boolean conditions.
050         */
051        public static final String TRUE = "true";
052    
053        /**
054         * Turns on constructor injection.
055         * @see org.picocontainer.injectors.ConstructorInjection
056         */
057        public static final Properties CDI = immutable(_INJECTION, _CONSTRUCTOR);
058    
059        /**
060         * Turns on Setter Injection.
061         * @see org.picocontainer.injectors.SetterInjection
062         */
063        public static final Properties SDI = immutable(_INJECTION, _SETTER);
064    
065        /**
066         * Turns on Method Injection.
067         */
068        public static final Properties METHOD_INJECTION = immutable(_INJECTION, _METHOD);
069    
070        /**
071         * Turns off Caching of component instances.  (Often referred to in other circles
072         * as singleton). 
073         * @see org.picocontainer.behaviors.Caching
074         */
075        public static final Properties NO_CACHE = immutable(_CACHE, FALSE);
076    
077        /**
078         * Turns on Caching of component instances.  (Often referred to in other circles
079         * as singleton)
080         * @see org.picocontainer.behaviors.Caching
081         */
082        public static final Properties CACHE = immutable(_CACHE, TRUE);
083    
084        /**
085         * Turns on synchronized access to the component instance.  (Under JDK 1.5 conditions,
086         * it will be better to use {@link #LOCK} instead.
087         * @see org.picocontainer.behaviors.Synchronizing
088         */
089        public static final Properties SYNCHRONIZE = immutable(_SYNCHRONIZING, TRUE);
090    
091        
092        /**
093         * Turns off synchronized access to the component instance.
094         * @see org.picocontainer.behaviors.Synchronizing
095         */
096        public static final Properties NO_SYNCHRONIZE = immutable(_SYNCHRONIZING, FALSE);
097        
098        /**
099         * Uses a java.util.concurrent.Lock to provide faster access than synchronized.
100         * @see org.picocontainer.behaviors.Locking
101         */
102        public static final Properties LOCK = immutable(_LOCKING, TRUE);
103    
104        /**
105         * Turns off locking synchronization.
106         * @see org.picocontainer.behaviors.Locking
107         */
108        public static final Properties NO_LOCK = immutable(_LOCKING, FALSE);
109        
110        /**
111         * Synonym for {@link #CACHE CACHE}.
112         * @see org.picocontainer.behaviors.Caching
113         */
114        public static final Properties SINGLE = CACHE;
115    
116        /**
117         * Synonym for {@link #NO_CACHE NO_CACHE}.
118         * @see org.picocontainer.behaviors.Caching
119         */
120        public static final Properties NO_SINGLE = NO_CACHE;
121        
122        /**
123         * Turns on implementation hiding.  You may use the JDK Proxy implementation included
124         * in this version, <strong>or</strong> the ASM-based implementation hiding method
125         * included in PicoContainer Gems.  However, you cannot use both in a single PicoContainer
126         * instance.
127         */
128        public static final Properties HIDE_IMPL = immutable(_HIDE_IMPL, TRUE);
129    
130        /**
131         * Turns off implementation hiding.
132         * @see #HIDE_IMPL for more information.
133         */
134        public static final Properties NO_HIDE_IMPL = immutable(_HIDE_IMPL, FALSE);
135    
136        public static final Properties ENABLE_CIRCULAR = immutable(_ENABLE_CIRCULAR, TRUE);
137        
138        public static final Properties NONE = immutable(_NONE, "");
139    
140        /**
141         * Turns on bean-setting property applications where certain simple properties are set
142         * after the object is created based.
143         */
144        public static final Properties PROPERTY_APPLYING = immutable(_PROPERTY_APPLYING, TRUE);
145        
146        /**
147         * Turns off bean-setting property applications.
148         * @see org.picocontainer.behaviors.PropertyApplying
149         */
150        public static final Properties NO_PROPERTY_APPLYING = immutable(_PROPERTY_APPLYING, FALSE);
151    
152        public static final Properties AUTOMATIC = immutable(_AUTOMATIC, TRUE);
153    
154        public static final Properties USE_NAMES = immutable(_USE_NAMES, TRUE);
155    
156        public static final Properties EMJECTION_ENABLED = immutable(_EMJECTION, TRUE);
157    
158        public static final Properties GUARD = immutable(_GUARD, "guard");
159    
160        public static final Properties GUARD(String with) {
161            return immutable(_GUARD, with);
162        };
163    
164        /**
165         * Transforms a single name value pair unto a <em>read only</em> {@linkplain java.util.Properties}
166         * instance.
167         * <p>Example Usage:</p>
168         * <pre>
169         *          Properties readOnly = immutable("oneKey","oneValue"};
170         *          assert readOnly.getProperty("oneKey") != null);
171         * </pre>
172         * @param name the property key.
173         * @param value the property value.
174         * @return Read Only properties instance.
175         */
176        public static Properties immutable(String name, String value) {
177            return new ImmutableProperties(name, value);
178        }
179        
180        /**
181         * Read only property set.  Once constructed, all methods that modify state will
182         * throw UnsupportedOperationException.
183         * @author Paul Hammant.
184         */
185        public static class ImmutableProperties extends Properties {
186            
187            private boolean sealed = false;
188    
189            public ImmutableProperties(String name, String value) {
190                super.setProperty(name, value);
191                sealed = true;
192            }
193            
194            /**
195             * Read Only Object:  will throw UnsupportedOperationException.
196             */
197            @Override
198            @SuppressWarnings("unused")
199            public Object remove( Object o) {
200                throw new UnsupportedOperationException("immutable properties are read only");
201            }
202    
203            /**
204             * Read Only Object:  will throw UnsupportedOperationException.
205             */
206            @Override
207            @SuppressWarnings("unused")
208            public synchronized Object setProperty(String string, String string1) {
209                throw new UnsupportedOperationException("immutable properties are read only");
210            }
211    
212            /**
213             * Read Only Object:  will throw UnsupportedOperationException.
214             */
215                    @Override
216                    public synchronized void clear() {
217                throw new UnsupportedOperationException("immutable properties are read only");
218                    }
219    
220                    /**
221                     * Once object is constructed, this will throw UnsupportedOperationException because
222                     * this class is a read only wrapper.
223                     */
224                    @Override
225                    public synchronized Object put(Object key, Object value) {
226                            if (!sealed) {
227                                    //setProperty calls put, so until the object is fully constructed, we 
228                                    //cannot seal it.
229                                    return super.put(key, value);
230                            }
231                            
232                throw new UnsupportedOperationException("immutable properties are read only");
233                    }
234    
235            /**
236             * Read Only Object:  will throw UnsupportedOperationException.
237             */
238                    @Override
239                    @SuppressWarnings("unused")
240                    public synchronized void putAll(Map<? extends Object, ? extends Object> t) {
241                throw new UnsupportedOperationException("immutable properties are read only");
242                    }
243            
244            
245        }
246    
247    }