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