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 *****************************************************************************/
010package org.picocontainer;
011
012import java.util.Map;
013import 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")
025public 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}