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 }