2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.appc.configuration;
29 import java.io.IOException;
30 import java.io.InputStream;
32 import java.security.CodeSource;
33 import java.security.ProtectionDomain;
34 import java.security.Provider;
35 import java.security.Provider.Service;
36 import java.security.Security;
37 import java.util.Map.Entry;
38 import java.util.Properties;
39 import java.util.jar.JarFile;
40 import java.util.jar.Manifest;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
44 import org.openecomp.appc.encryption.EncryptionTool;
45 import org.openecomp.appc.util.UnmodifiableProperties;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
50 * This class provides the implementation of the <code>Configuration</code> interface. It is created by the
51 * ConfigurationFactory and initialized with the configuration values for the process.
56 public final class DefaultConfiguration implements Configuration, Cloneable {
58 private static final Logger logger = LoggerFactory.getLogger(DefaultConfiguration.class);
61 * The framework configuration properties.
63 private Properties properties = new Properties();
66 * Construct the configuration object.
68 public DefaultConfiguration() {
72 * Clears all properties
79 * @see java.lang.Object#clone()
82 protected Object clone() throws CloneNotSupportedException {
83 DefaultConfiguration clone = (DefaultConfiguration) super.clone();
85 clone.properties = new Properties(this.properties);
86 clone.properties.putAll(this.properties);
92 * Decrypts an encrypted value, if it is encrypted, and returns the clear text. Performs no operation on the string
93 * if it is not encrypted.
96 * The value to (optionally) be decrypted
97 * @return The clear text
99 @SuppressWarnings("nls")
100 private static String decrypt(String value) {
102 if (value.startsWith(EncryptionTool.ENCRYPTED_VALUE_PREFIX)) {
104 return EncryptionTool.getInstance().decrypt(value);
105 } catch (Throwable e) {
107 for (Provider p : Security.getProviders()) {
108 for (Service s : p.getServices()) {
109 String algo = s.getAlgorithm();
111 String.format("\n==Found Algorithm [ %s ] in provider [ %s ] and service [ %s ]", algo,
112 p.getName(), s.getClassName());
116 logger.warn(String.format("Could not decrypt the configuration value [%s]", value), e);
124 * Decrypts all elements in the properties object
126 private void decryptAllProperties() {
127 if (properties != null) {
128 for (Entry<Object, Object> e : properties.entrySet()) {
129 if (e.getValue() != null) {
130 e.setValue(decrypt(e.getValue().toString()));
137 * @see java.lang.Object#equals(java.lang.Object)
140 public boolean equals(Object obj) {
141 DefaultConfiguration other = (DefaultConfiguration) obj;
143 if ((this.properties.size() == other.properties.size())
144 && (this.properties.entrySet().containsAll(other.properties.entrySet()))
145 && (other.properties.entrySet().containsAll(this.properties.entrySet()))) {
153 * This method will use the properties object to expand any variables that may be present in the template provided.
154 * Variables are represented by the string "${name}", where "name" is the name of a property defined in either the
155 * current configuration object, or system properties if undefined. If the value cannot be found, the variable is
156 * removed and an empty string is used to replace the variable.
159 * The template to be expanded
160 * @return The expanded template where each variable is replaced with its value
162 @SuppressWarnings("nls")
163 private String expandVariables(String template) {
164 if (template == null) {
168 // Decrypt the template if needed
169 // template = decrypt(template); DH: Do not assign values to parameters, bad form! Also, Sonar complains
172 StringBuffer buffer = new StringBuffer(decrypt(template));
173 Pattern pattern = Pattern.compile("\\$\\{([^\\}]+)\\}");
174 Matcher matcher = pattern.matcher(buffer);
175 while (matcher.find()) {
176 String variable = matcher.group(1);
177 String value = properties.getProperty(variable);
179 value = System.getProperty(variable);
184 buffer.replace(matcher.start(), matcher.end(), value);
188 return buffer.toString().trim();
192 * This method is called to obtain a property expressed as a boolean value (true or false). The standard rules for
193 * Boolean.parseBoolean() are used.
197 * @return The value of the property expressed as a boolean, or false if it does not exist.
199 @SuppressWarnings("nls")
201 public boolean getBooleanProperty(String key) {
202 return Boolean.valueOf(getProperty(key, "false")).booleanValue();
206 * This method is called to obtain a property expressed as a boolean value (true or false). The standard rules for
207 * Boolean.valueOf(String) are used.
211 * @param defaultValue
212 * The default value to be returned if the property does not exist
213 * @return The value of the property expressed as a boolean, or false if it does not exist.
214 * @see org.openecomp.appc.configuration.Configuration#getBooleanProperty(java.lang.String, boolean)
217 public boolean getBooleanProperty(String key, boolean defaultValue) {
218 if (isPropertyDefined(key)) {
219 return getBooleanProperty(key);
225 * Returns the indicated property value expressed as a floating point double-precision value (double).
228 * The property to retrieve
229 * @return The value of the property, or 0.0 if not found
230 * @see org.openecomp.appc.configuration.Configuration#getDoubleProperty(java.lang.String)
232 @SuppressWarnings("nls")
234 public double getDoubleProperty(String key) {
236 return Double.valueOf(getProperty(key, "0.0")).doubleValue();
237 } catch (NumberFormatException e) {
243 * This method is called to obtain a property as a string value
246 * The key of the property
247 * @param defaultValue
248 * The default value to be returned if the property does not exist
249 * @return The string value, or null if it does not exist.
250 * @see org.openecomp.appc.configuration.Configuration#getDoubleProperty(java.lang.String, double)
253 public double getDoubleProperty(String key, double defaultValue) {
254 if (isPropertyDefined(key)) {
255 return getDoubleProperty(key);
261 * Returns the property indicated expressed as an integer. The standard rules for
262 * {@link Integer#parseInt(String, int)} using a radix of 10 are used.
265 * The property name to retrieve.
266 * @returns The value of the property, or 0 if it does not exist or is invalid.
267 * @see org.openecomp.appc.configuration.Configuration#getIntegerProperty(java.lang.String)
269 @SuppressWarnings("nls")
271 public int getIntegerProperty(String key) {
273 return Integer.parseInt(getProperty(key, "0"), 10);
274 } catch (NumberFormatException e) {
280 * Returns the property indicated expressed as an integer. The standard rules for Integer.parseInt(String, int)
281 * using a radix of 10 are used.
284 * The property name to retrieve.
285 * @param defaultValue
286 * The default value to be returned if the property does not exist
287 * @return The value of the property, or 0 if it does not exist or is invalid.
288 * @see org.openecomp.appc.configuration.Configuration#getIntegerProperty(java.lang.String, int)
291 public int getIntegerProperty(String key, int defaultValue) {
292 if (isPropertyDefined(key)) {
293 return getIntegerProperty(key);
299 * Returns the specified property as a long integer value, if it exists, or zero if it does not.
302 * The key of the property desired.
303 * @return The value of the property expressed as an integer long value, or zero if the property does not exist or
304 * is not a valid integer long.
305 * @see org.openecomp.appc.configuration.Configuration#getLongProperty(java.lang.String)
307 @SuppressWarnings("nls")
309 public long getLongProperty(String key) {
311 return Long.parseLong(getProperty(key, "0"), 10);
312 } catch (NumberFormatException e) {
318 * Returns the specified property as a long integer value, if it exists, or the default value if it does not exist
322 * The key of the property desired.
323 * @param defaultValue
324 * the value to be returned if the property is not valid or does not exist.
325 * @return The value of the property expressed as an integer long value, or the default value if the property does
326 * not exist or is not a valid integer long.
327 * @see org.openecomp.appc.configuration.Configuration#getLongProperty(java.lang.String, long)
330 public long getLongProperty(String key, long defaultValue) {
331 if (isPropertyDefined(key)) {
332 return getLongProperty(key);
338 * This method can be called to retrieve a properties object that is immutable. Any attempt to modify the properties
339 * object returned will result in an exception. This allows a caller to view the current configuration as a set of
342 * @return An unmodifiable properties object.
343 * @see org.openecomp.appc.configuration.Configuration#getProperties()
346 public Properties getProperties() {
347 return new UnmodifiableProperties(properties);
351 * This method is called to obtain a property as a string value
354 * The key of the property
355 * @return The string value, or null if it does not exist.
358 public String getProperty(String key) {
359 String value = properties.getProperty(key);
363 return expandVariables(value.trim());
367 * This method is called to obtain a property as a string value
370 * The key of the property
371 * @param defaultValue
372 * The default value to be returned if the property does not exist
373 * @return The string value, or null if it does not exist.
374 * @see org.openecomp.appc.configuration.Configuration#getProperty(java.lang.String, java.lang.String)
377 public String getProperty(String key, String defaultValue) {
378 if (isPropertyDefined(key)) {
379 return getProperty(key);
382 if (defaultValue == null) {
386 return expandVariables(defaultValue.trim());
390 * @see java.lang.Object#hashCode()
393 public int hashCode() {
394 return (properties == null ? 0 : properties.hashCode());
398 * Returns true if the named property is defined, false otherwise.
401 * The key of the property we are interested in
402 * @return True if the property exists.
405 public boolean isPropertyDefined(String key) {
406 return properties.containsKey(key);
410 * Returns an indication of the validity of the boolean property. A boolean property is considered to be valid only
411 * if it has the value "true" or "false" (ignoring case).
414 * The property to be checked
415 * @returns True if the value is a boolean constant, or false if it does not exist or is not a correct string
416 * @see org.openecomp.appc.configuration.Configuration#isValidBoolean(java.lang.String)
418 @SuppressWarnings("nls")
420 public boolean isValidBoolean(String key) {
421 String value = getProperty(key);
423 value = value.toLowerCase();
424 return value.matches("true|false");
430 * Returns an indication if the indicated property represents a valid double-precision floating point number.
433 * The property to be examined
434 * @returns True if the property is a valid representation of a double, or false if it does not exist or contains
435 * illegal characters.
436 * @see org.openecomp.appc.configuration.Configuration#isValidDouble(java.lang.String)
439 public boolean isValidDouble(String key) {
440 String value = getProperty(key);
443 Double.valueOf(value);
445 } catch (NumberFormatException e) {
453 * Returns an indication if the property is a valid integer value or not.
456 * The key of the property to check
457 * @returns True if the value is a valid integer string, or false if it does not exist or contains illegal
459 * @see org.openecomp.appc.configuration.Configuration#isValidInteger(java.lang.String)
462 public boolean isValidInteger(String key) {
463 String value = getProperty(key);
466 Integer.parseInt(value.trim(), 10);
468 } catch (NumberFormatException e) {
476 * Determines is the specified property exists and is a valid representation of an integer long value.
479 * The property to be checked
480 * @return True if the property is a valid representation of an integer long value, and false if it either does not
481 * exist or is not valid.
482 * @see org.openecomp.appc.configuration.Configuration#isValidLong(java.lang.String)
485 public boolean isValidLong(String key) {
486 String value = getProperty(key);
489 Long.parseLong(value.trim(), 10);
491 } catch (NumberFormatException e) {
499 * This method allows an implementation to load configuration properties that may override default values.
502 * An input stream that contains the properties to be loaded
504 public void setProperties(InputStream is) {
507 } catch (IOException e) {
513 * This method allows an implementation to load configuration properties that may override default values.
516 * An optional Properties object to be merged into the configuration, replacing any same-named
518 * @see org.openecomp.appc.configuration.Configuration#setProperties(java.util.Properties)
521 public void setProperties(Properties props) {
522 properties.putAll(props);
523 decryptAllProperties();
527 * This method allows a caller to insert a new property definition into the configuration object. This allows the
528 * application to adjust or add to the current configuration. If the property already exists, it is replaced with
532 * The key of the property to be defined
534 * The value of the property to be defined
535 * @see org.openecomp.appc.configuration.Configuration#setProperty(java.lang.String, java.lang.String)
538 public void setProperty(String key, String value) {
539 properties.setProperty(key, decrypt(value));
543 * @see java.lang.Object#toString()
545 @SuppressWarnings("nls")
547 public String toString() {
548 return String.format("Configuration: %d properties, keys:[%s]", properties.size(), properties.keySet()
553 * This is a helper method to read the manifest of the jar file that this class was loaded from. Note that this will
554 * only work if the code is packaged in a jar file. If it is an open deployment, such as under eclipse, this will
555 * not work and there is code added to detect that case.
557 * @return The manifest object from the jar file, or null if the code is not packaged in a jar file.
562 private Manifest getManifest() {
563 ProtectionDomain domain = getClass().getProtectionDomain();
564 CodeSource source = domain.getCodeSource();
565 URL location = source.getLocation();
566 String path = location.getPath();
567 int index = path.indexOf('!');
569 path = path.substring(0, index);
571 if (path.endsWith(".jar")) {
572 try (JarFile jar = new JarFile(location.getFile())) {
573 return jar.getManifest();
574 } catch (IOException e) {
575 logger.error("getManifest", e);