View Javadoc

1   /*
2    * Copyright 2012-2013 smartics, Kronseder & Reiner GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package de.smartics.properties.api.config.app;
17  
18  import java.io.Serializable;
19  import java.util.Iterator;
20  import java.util.ServiceConfigurationError;
21  import java.util.ServiceLoader;
22  
23  import javax.annotation.concurrent.ThreadSafe;
24  
25  import org.apache.commons.lang.builder.ToStringBuilder;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  import de.smartics.properties.api.core.security.Base64PropertyValueSecurity;
30  import de.smartics.properties.api.core.security.PropertyValueSecurity;
31  
32  /**
33   * Provides properties to configure an instance of
34   * {@link de.smartics.properties.api.config.app.ConfigurationPropertiesFactory}.
35   */
36  @ThreadSafe
37  public final class FactoryConfiguration implements Serializable
38  {
39    // ********************************* Fields *********************************
40  
41    // --- constants ------------------------------------------------------------
42  
43    /**
44     * The class version identifier.
45     */
46    private static final long serialVersionUID = 1L;
47  
48    /**
49     * Reference to the logger for this class.
50     */
51    private static final Logger LOG = LoggerFactory
52        .getLogger(FactoryConfiguration.class);
53  
54    // --- members --------------------------------------------------------------
55  
56    /**
57     * The flag to tell whether (<code>true</code>) or not (<code>false</code>)
58     * the URLs of the context class loader should be added.
59     *
60     * @serial
61     */
62    private volatile boolean addDefaultRootLocations = true;
63  
64    /**
65     * The flag indicates that loading properties form the class path is to be
66     * skipped.
67     *
68     * @serial
69     */
70    private volatile boolean skipClassPathPropertyLoading;
71  
72    /**
73     * The flag indicates that a cache should be provided, if supported.
74     *
75     * @serial
76     */
77    private volatile boolean useCache = true;
78  
79    /**
80     * The helper to decrypt secured property values.
81     *
82     * @serial
83     */
84    private volatile PropertyValueSecurity decrypter = createDecrypter();
85  
86    // ****************************** Initializer *******************************
87  
88    // ****************************** Constructors ******************************
89  
90    /**
91     * Default constructor.
92     */
93    public FactoryConfiguration()
94    {
95    }
96  
97    // ****************************** Inner Classes *****************************
98  
99    // ********************************* Methods ********************************
100 
101   // --- init -----------------------------------------------------------------
102 
103   // --- get&set --------------------------------------------------------------
104 
105   /**
106    * Returns the flag to tell whether (<code>true</code>) or not (
107    * <code>false</code>) the URLs of the context class loader should be added.
108    *
109    * @return the flag to tell whether (<code>true</code>) or not (
110    *         <code>false</code>) the URLs of the context class loader should be
111    *         added.
112    */
113   public boolean isAddDefaultRootLocations()
114   {
115     return addDefaultRootLocations;
116   }
117 
118   /**
119    * Sets the flag to tell whether (<code>true</code>) or not (
120    * <code>false</code>) the URLs of the context class loader should be added.
121    *
122    * @param addDefaultRootLocations the flag to tell whether (<code>true</code>)
123    *          or not (<code>false</code>) the URLs of the context class loader
124    *          should be added.
125    */
126   public void setAddDefaultRootLocations(final boolean addDefaultRootLocations)
127   {
128     this.addDefaultRootLocations = addDefaultRootLocations;
129   }
130 
131   /**
132    * Returns the flag indicates that loading properties form the class path is
133    * to be skipped.
134    *
135    * @return the flag indicates that loading properties form the class path is
136    *         to be skipped.
137    */
138   public boolean isSkipClassPathPropertyLoading()
139   {
140     return skipClassPathPropertyLoading;
141   }
142 
143   /**
144    * Sets the flag indicates that loading properties from the class path is to
145    * be skipped.
146    *
147    * @param skipClassPathPropertyLoading the flag indicates that loading
148    *          properties from the class path is to be skipped.
149    */
150   public void setSkipClassPathPropertyLoading(
151       final boolean skipClassPathPropertyLoading)
152   {
153     this.skipClassPathPropertyLoading = skipClassPathPropertyLoading;
154   }
155 
156   /**
157    * Returns the flag indicates that a cache should be provided, if supported.
158    *
159    * @return the flag indicates that a cache should be provided, if supported.
160    */
161   public boolean isUseCache()
162   {
163     return useCache;
164   }
165 
166   /**
167    * Sets the flag indicates that a cache should be provided, if supported.
168    *
169    * @param useCache the flag indicates that a cache should be provided, if
170    *          supported.
171    */
172   public void setUseCache(final boolean useCache)
173   {
174     this.useCache = useCache;
175   }
176 
177   /**
178    * Returns the helper to decrypt secured property values.
179    *
180    * @return the helper to decrypt secured property values.
181    */
182   public PropertyValueSecurity getDecrypter()
183   {
184     return decrypter;
185   }
186 
187   /**
188    * Sets the helper to decrypt secured property values.
189    *
190    * @param decrypter the helper to decrypt secured property values.
191    */
192   public void setDecrypter(final PropertyValueSecurity decrypter)
193   {
194     this.decrypter = decrypter;
195   }
196 
197   // --- business -------------------------------------------------------------
198 
199   /**
200    * Creates an instance of {@link PropertyValueSecurity} as registered in
201    * <code>META-INF/services/de.smartics.properties.api.core.security.PropertyValueSecurity</code>
202    * .
203    * <p>
204    * Issues a warning if more than one implementation is found. If no
205    * implementation is configured, a non-secure instance is returned.
206    * </p>
207    *
208    * @return the instance of a decrypter. Never <code>null</code>.
209    */
210   private PropertyValueSecurity createDecrypter()
211   {
212     final Iterator<PropertyValueSecurity> iterator =
213         ServiceLoader.load(PropertyValueSecurity.class).iterator();
214 
215     final StringBuilder buffer = new StringBuilder(64);
216     PropertyValueSecurity security = null;
217     while (iterator.hasNext())
218     {
219       try
220       {
221         if (security != null)
222         {
223           final String implementation = iterator.next().getClass().getName();
224           buffer.append("\nDuplicated implementation rejected: "
225                         + implementation);
226           continue;
227         }
228 
229         security = iterator.next();
230       }
231       catch (final ServiceConfigurationError e)
232       {
233         buffer.append("\nError encountered: ").append(e.getMessage());
234       }
235     }
236 
237     if (buffer.length() > 0)
238     {
239       LOG.warn("Problems encountered while fetching implementations of '"
240                + PropertyValueSecurity.class.getName() + "':" + buffer);
241     }
242 
243     if (security == null)
244     {
245       return new Base64PropertyValueSecurity();
246     }
247 
248     return security;
249   }
250 
251   // --- object basics --------------------------------------------------------
252 
253   /**
254    * {@inheritDoc}
255    * <p>
256    * Provides the properties via reflection for displaying debug information.
257    * </p>
258    * <p>
259    * Please note that calling this method may not be thread-safe. The flag
260    * printed may not reflect an actual state or a state that ever existed.
261    * </p>
262    *
263    * @see java.lang.Object#toString()
264    */
265   @Override
266   public String toString()
267   {
268     return ToStringBuilder.reflectionToString(this);
269   }
270 }