View Javadoc

1   package com.sourceforge.jpatterns.core.configuration;
2   
3   import com.sourceforge.jpatterns.core.configuration.exceptions.JPInitializationException;
4   import com.sourceforge.jpatterns.utils.JPatternsPropsUtils;
5   import com.zmicer.utils.*;
6   import org.apache.log4j.Logger;
7   
8   import java.util.Enumeration;
9   import java.util.HashSet;
10  import java.util.ResourceBundle;
11  import java.util.Set;
12  
13  /**
14   * This class manages deals with the properties files JPatterns uses.
15   * <br/>
16   * Please do not put here any functionality which could be customizable later. Only the functionality fitting the approach:
17   * we have default and custom properties files which are taken from the classpath. In the case custom configuration contains the same
18   * keys - they would override the default configuration.
19   * <br/>
20   * Potentially the part of this PropertyManager could be used at the JInit.
21   * <br/>
22   * Please be noticed the very important method is the following:
23   * <code>com.sourceforge.jpatterns.core.configuration.PropertiesManagerImpl#getBundle(java.lang.String)</code>, and this method
24   * firstly checks the default configuration, and then checks the overriden, custom configuration.
25   * todo [zmicer]: think if this could be moved to the common functionality. Think over the PropertiesProvider class - why do we really need\
26   * two these classes? Please finish investigating.
27   *
28   * todo [zmicer]: introduce the opportunity to setup the necessary names from outside - it would allow us to use this approach as the common
29   * functionality.
30   * todo [zmicer]: please check in which way the is used here: 0001\src\testdata\jpatterns_custom.properties
31   *
32   * $Author:: zmicer             $<br/>
33   * $Rev:: 67                    $<br/> * $Date:: 2007-08-28 21:37:07 #$<br/>
34   * $Date:: 2007-08-28 21:37:07 #$<br/>
35   */
36  public class PropertiesManagerImpl implements IPropertiesManager
37  {
38      /**
39       * Logger instance.
40       */
41      final public static Logger LOG = Logger.getLogger(PropertiesManagerImpl.class);
42  
43      /**
44       * The default bundle to be used.
45       */
46      private ResourceBundle m_defaultBundle;
47  
48      /**
49       * The custom bundle to be used.
50       */
51      private ResourceBundle m_customBundle;
52  
53      /**
54       * This variable is used for indicating the functionality was already initialized.
55       */
56      private static boolean isInitialized;
57  
58      /**
59       * Please review the following Java Docs to understand the meaning of this props:
60       * {@link com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.USE_ONLY_CUSTOM_FRAMEWORK_PROPERTIES}
61       */
62      private static boolean useOnlyCustomPropsIfPresent;
63  
64      /**
65       * The reason this class has the constructor and implements "singleton" - we are worrying if we need interface for it later.
66       */
67      public PropertiesManagerImpl()
68      {
69          // 00: initial configuration
70          super();
71          initConfigs();
72      }
73  
74      /**
75       * Perform the check if the functionality was initialized. Throws <code>IllegalStateException</code> in the case the functionality
76       * was not intialized. Should be used for all the "state read/write" methods just to be sure all is ok.
77       */
78      protected void checkIsInitialized()
79      {
80          if (!isInitialized)
81          {
82              throw new IllegalStateException("Please be noticed the PropertiesManagerImpl is not initialized.");
83          }
84      }
85  
86      /**
87       * Init the resource bundles configuration (methods <code>getDefaultBundleFileName and getCustomBundleFileName</code> are used
88       * for the retrieving the actual nname of the properties to be obtained during the initialization process)
89       * <br/>
90       * Protected to allow to cover that with the unit tests
91       */
92      public void initConfigs()
93      {
94          isInitialized = false;
95          // todo [zmicer]: clarify for what it is ???
96          if (null == m_defaultBundle && null != JPatternsPropsUtils.getDefaultBundle())
97          {
98              m_defaultBundle = JPatternsPropsUtils.getDefaultBundle();
99              m_customBundle = JPatternsPropsUtils.getCustomBundle();
100             JPatternsPropsUtils.setDefaultBundle(null);
101             JPatternsPropsUtils.setCustomBundle(null);
102         }
103         else
104         {
105             final String defaultProps = JPatternsPropsUtils.getDefaultBundleName();
106             final String customProps = JPatternsPropsUtils.getCustomBundleName();
107             if (null == defaultProps)
108             {
109                 throw new IllegalStateException("The name of default configuration can not be null.");
110             }
111             m_defaultBundle = ResourceUtils.getResourceBundle(defaultProps);
112             m_customBundle = ResourceUtils.getResourceBundle(customProps);
113         }
114 
115         isInitialized = true;
116         // 01: initialize <code>useOnlyCustomPropsIfPresent</code>
117         initUseOnlyCustomConfigIfPresent();
118     }
119 
120 
121     /**
122      * @see IPropertiesManager#customConfigPresents()
123      */
124     public boolean customConfigPresents()
125     {
126         checkIsInitialized();
127         return (null != m_customBundle);
128     }
129 
130     /**
131      * @see IPropertiesManager#defaultConfigPresents()
132      */
133     public boolean defaultConfigPresents()
134     {
135         checkIsInitialized();
136         return (null != m_defaultBundle);
137     }
138 
139     /**
140      * @see com.sourceforge.jpatterns.core.configuration.IPropertiesManager#useOnlyCustomConfigIfPresent()
141      */
142     public boolean useOnlyCustomConfigIfPresent()
143     {
144         checkIsInitialized();
145         return useOnlyCustomPropsIfPresent;
146     }
147 
148     /**
149      * Initialize the useOnlyCustomPropsIfPresent field.
150      */
151     protected void initUseOnlyCustomConfigIfPresent()
152     {
153         checkIsInitialized();
154         final String defaultValue = getDefaultBundle(PropertiesProvider.JPProperties.USE_ONLY_CUSTOM_FRAMEWORK_PROPERTIES);
155         final String customValue = getCustomBundle(PropertiesProvider.JPProperties.USE_ONLY_CUSTOM_FRAMEWORK_PROPERTIES);
156         if (null == customValue || "".equals(customValue))
157         {
158             if (null == defaultValue || "".equals(defaultValue))
159             {
160                 // 00: the case when there are definitions with this settings at the both custom and default property files.
161                 useOnlyCustomPropsIfPresent = false;
162             }
163             else
164             {
165                 final Boolean boolObject = StringUtils.getBoolean(defaultValue);
166                 if (null == boolObject)
167                 {
168                     throw new IllegalStateException("The property defined at the properties file doesn't take boolean value");
169                 }
170                 useOnlyCustomPropsIfPresent = boolObject;
171             }
172         }
173         else
174         {
175             final Boolean boolObject = StringUtils.getBoolean(customValue);
176             if (null == boolObject)
177             {
178                 throw new IllegalStateException("The property defined at the properties file doesn't take boolean value");
179             }
180             useOnlyCustomPropsIfPresent = boolObject;
181         }
182     }
183 
184     /**
185      * @see IPropertiesManager#getBundle(java.lang.String)
186      */
187     public String getBundle(final String key)
188     {
189         checkIsInitialized();
190         InputArgumentUtils.checkStrings(true, key);
191         final String customValue = getCustomBundle(key);
192         if ((useOnlyCustomPropsIfPresent && customConfigPresents()) || null != customValue)
193         {
194             return customValue;
195         }
196         return getDefaultBundle(key);
197     }
198 
199     /**
200      * @see IPropertiesManager#getBundle(Class)
201      */
202     public String getBundle(final Class key)
203     {
204         checkIsInitialized();
205         if (null == key)
206         {
207             throw new IllegalArgumentException("The class for each we need to get the resource bundle can not be null");
208         }
209         final String nameKey = ReflexionUtils.getBaseName(key);
210         if (null == nameKey)
211         {
212             throw new IllegalStateException("Could not get the base name using the Class instance. Please check the sources.");
213         }
214         return getBundle(nameKey);
215     }
216 
217     /**
218      * @see com.sourceforge.jpatterns.core.configuration.IPropertiesManager#getBundledObject(Class)
219      */
220     public Object getBundledObject(final Class key)
221     {
222         final String bundledObjectClassName = getBundle(key);
223         if (null == bundledObjectClassName)
224         {
225             throw new JPInitializationException("Can not find the name of the class instance of which we should instantiate. Class name: " +
226                 key.getName());
227         }
228 
229         // the object we got using reflexion
230         try
231         {
232             final Object object= ReflexionUtils.reflectObject(bundledObjectClassName, true);
233             if (null == object)
234             {
235                 throw new JPInitializationException("Illegal, incorrect definition of the Class is defined at the properties file. " +
236                     "Class name :" + key.getName() + ", value for the key is : " + bundledObjectClassName);
237             }
238             return object;
239         }
240         catch(Exception ex)
241         {
242             LoggingUtils.logException(LOG, ex, null, this.getClass());
243             throw new JPInitializationException(ex);
244         }
245 
246     }
247 
248     /**
249      * @see com.sourceforge.jpatterns.core.configuration.IPropertiesManager#getBundledObject(String)
250      */
251     public Object getBundledObject(final String key)
252     {
253         final String bundledObjectClassName = getBundle(key);
254         if (null == bundledObjectClassName)
255         {
256             throw new JPInitializationException("Can not find the name of the class instance of which we should instantiate. Class name: " +
257                 key);
258         }
259         // the object we got using reflexion
260         final Object object = ReflexionUtils.reflectObject(bundledObjectClassName, false);
261         if (null == object)
262         {
263             throw new JPInitializationException("Illegal, incorrect definition of the Class is defined at the properties file. " +
264                 "Class name :" + key + ", value for the key is : " + bundledObjectClassName);
265         }
266         return object;
267     }
268 
269     /**
270      * @see IPropertiesManager#getDefaultBundle(java.lang.String)
271      */
272     public String getDefaultBundle(final String key)
273     {
274         checkIsInitialized();
275         InputArgumentUtils.checkStrings(true, key);
276         if (!defaultConfigPresents())
277         {
278             throw new JPInitializationException("The default configuration is not present. It is illegale state of the JPatterns " +
279                 "framework.");
280         }
281         String result = null;
282         try
283         {
284             result = m_defaultBundle.getString(key);
285             if (null != result && !"".equals(result))
286             {
287                 LOG.debug("The value for the key [" + key + "] was found using the default properties.");
288                 return result;
289             }
290         }
291         catch (Exception ex)
292         {
293             // just catching, and that is all
294         }
295         return result;
296     }
297 
298     /**
299      * @see IPropertiesManager#getCustomBundle(java.lang.String)
300      */
301     public String getCustomBundle(final String key)
302     {
303         checkIsInitialized();
304         InputArgumentUtils.checkStrings(true, key);
305         if (!customConfigPresents())
306         {
307             LOG.debug("Trying to obtain the bundle with the key " + key + " from the custom properties: the custom properties file " +
308                 "is absent");
309             return null;
310         }
311         String result = null;
312         try
313         {
314             result = m_customBundle.getString(key);
315             if (null != result && !"".equals(result))
316             {
317                 LOG.debug("The value for the key [" + key + "] was found using the custom properties.");
318                 return result;
319             }
320         }
321         catch (Exception ex)
322         {
323             // just catching, and that is all
324         }
325         return result;
326     }
327 
328     /**
329      * @return the Enumeration of the keys (merged one or the custom one or the default one - it depends on the following:
330      * a. if custom properties files is present or was specified at the JVM parameter b. study the
331      * <code>com.sourceforge.jpatterns.core.configuration.PropertiesProvider.JPProperties.USE_ONLY_CUSTOM_FRAMEWORK_PROPERTIES</code>)
332      * todo: [zmicer] think over the caching these values between the initialization periods - just to increase the performance of the
333      * framework initialization!
334      */
335     public Set<String> getMergedKeys()
336     {
337         checkIsInitialized();
338         Set<String> customSet = new HashSet<String>();
339         if (customConfigPresents())
340         {
341             final Enumeration<String> customEnum = m_customBundle.getKeys();
342             customSet = CollectionsUtils.toSet(customEnum);
343             if (useOnlyCustomPropsIfPresent && customConfigPresents())
344             {
345                 return customSet;
346             }
347         }
348         Set<String> defaultSet = new HashSet<String>();
349         if (defaultConfigPresents())
350         {
351             final Enumeration<String> defaultEnum = m_defaultBundle.getKeys();
352             defaultSet = CollectionsUtils.toSet(defaultEnum);
353             if (null != customSet && !customSet.isEmpty())
354             {
355                 defaultSet.addAll(customSet);
356             }
357         }
358         if (defaultSet.isEmpty())
359         {
360             return customSet;
361         }
362 
363         return defaultSet;
364     }
365 }