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