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