2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.openecomp.appc.configuration;
26 import java.io.IOException;
27 import java.io.InputStream;
29 import java.security.CodeSource;
30 import java.security.ProtectionDomain;
31 import java.security.Provider;
32 import java.security.Provider.Service;
33 import java.security.Security;
34 import java.util.Map.Entry;
35 import java.util.Properties;
36 import java.util.jar.JarFile;
37 import java.util.jar.Manifest;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
41 import org.openecomp.appc.encryption.EncryptionTool;
42 import org.openecomp.appc.util.UnmodifiableProperties;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
47 * This class provides the implementation of the <code>Configuration</code> interface. It is created by the
48 * ConfigurationFactory and initialized with the configuration values for the process.
53 public final class DefaultConfiguration implements Configuration, Cloneable {
55 private static final Logger logger = LoggerFactory.getLogger(DefaultConfiguration.class);
58 * The framework configuration properties.
60 private Properties properties = new Properties();
63 * Construct the configuration object.
65 public DefaultConfiguration() {
69 * Clears all properties
76 * @see java.lang.Object#clone()
79 protected Object clone() throws CloneNotSupportedException {
80 DefaultConfiguration clone = (DefaultConfiguration) super.clone();
82 clone.properties = new Properties(this.properties);
83 clone.properties.putAll(this.properties);
89 * Decrypts an encrypted value, if it is encrypted, and returns the clear text. Performs no operation on the string
90 * if it is not encrypted.
93 * The value to (optionally) be decrypted
94 * @return The clear text
96 @SuppressWarnings("nls")
97 private static String decrypt(String value) {
99 if (value.startsWith(EncryptionTool.ENCRYPTED_VALUE_PREFIX)) {
101 return EncryptionTool.getInstance().decrypt(value);
102 } catch (Throwable e) {
104 for (Provider p : Security.getProviders()) {
105 for (Service s : p.getServices()) {
106 String algo = s.getAlgorithm();
108 String.format("\n==Found Algorithm [ %s ] in provider [ %s ] and service [ %s ]", algo,
109 p.getName(), s.getClassName());
113 logger.warn(String.format("Could not decrypt the configuration value [%s]", value), e);
121 * Decrypts all elements in the properties object
123 private void decryptAllProperties() {
124 if (properties != null) {
125 for (Entry<Object, Object> e : properties.entrySet()) {
126 if (e.getValue() != null) {
127 e.setValue(decrypt(e.getValue().toString()));
134 * @see java.lang.Object#equals(java.lang.Object)
137 public boolean equals(Object obj) {
138 DefaultConfiguration other = (DefaultConfiguration) obj;
140 if ((this.properties.size() == other.properties.size())
141 && (this.properties.entrySet().containsAll(other.properties.entrySet()))
142 && (other.properties.entrySet().containsAll(this.properties.entrySet()))) {
150 * This method will use the properties object to expand any variables that may be present in the template provided.
151 * Variables are represented by the string "${name}", where "name" is the name of a property defined in either the
152 * current configuration object, or system properties if undefined. If the value cannot be found, the variable is
153 * removed and an empty string is used to replace the variable.
156 * The template to be expanded
157 * @return The expanded template where each variable is replaced with its value
159 @SuppressWarnings("nls")
160 private String expandVariables(String template) {
161 if (template == null) {
165 // Decrypt the template if needed
166 // template = decrypt(template); DH: Do not assign values to parameters, bad form! Also, Sonar complains
169 StringBuffer buffer = new StringBuffer(decrypt(template));
170 Pattern pattern = Pattern.compile("\\$\\{([^\\}]+)\\}");
171 Matcher matcher = pattern.matcher(buffer);
172 while (matcher.find()) {
173 String variable = matcher.group(1);
174 String value = properties.getProperty(variable);
176 value = System.getProperty(variable);
181 buffer.replace(matcher.start(), matcher.end(), value);
185 return buffer.toString().trim();
189 * This method is called to obtain a property expressed as a boolean value (true or false). The standard rules for
190 * Boolean.parseBoolean() are used.
194 * @return The value of the property expressed as a boolean, or false if it does not exist.
196 @SuppressWarnings("nls")
198 public boolean getBooleanProperty(String key) {
199 return Boolean.valueOf(getProperty(key, "false")).booleanValue();
203 * This method is called to obtain a property expressed as a boolean value (true or false). The standard rules for
204 * Boolean.valueOf(String) are used.
208 * @param defaultValue
209 * The default value to be returned if the property does not exist
210 * @return The value of the property expressed as a boolean, or false if it does not exist.
211 * @see org.openecomp.appc.configuration.Configuration#getBooleanProperty(java.lang.String, boolean)
214 public boolean getBooleanProperty(String key, boolean defaultValue) {
215 if (isPropertyDefined(key)) {
216 return getBooleanProperty(key);
222 * Returns the indicated property value expressed as a floating point double-precision value (double).
225 * The property to retrieve
226 * @return The value of the property, or 0.0 if not found
227 * @see org.openecomp.appc.configuration.Configuration#getDoubleProperty(java.lang.String)
229 @SuppressWarnings("nls")
231 public double getDoubleProperty(String key) {
233 return Double.valueOf(getProperty(key, "0.0")).doubleValue();
234 } catch (NumberFormatException e) {
240 * This method is called to obtain a property as a string value
243 * The key of the property
244 * @param defaultValue
245 * The default value to be returned if the property does not exist
246 * @return The string value, or null if it does not exist.
247 * @see org.openecomp.appc.configuration.Configuration#getDoubleProperty(java.lang.String, double)
250 public double getDoubleProperty(String key, double defaultValue) {
251 if (isPropertyDefined(key)) {
252 return getDoubleProperty(key);
258 * Returns the property indicated expressed as an integer. The standard rules for
259 * {@link Integer#parseInt(String, int)} using a radix of 10 are used.
262 * The property name to retrieve.
263 * @returns The value of the property, or 0 if it does not exist or is invalid.
264 * @see org.openecomp.appc.configuration.Configuration#getIntegerProperty(java.lang.String)
266 @SuppressWarnings("nls")
268 public int getIntegerProperty(String key) {
270 return Integer.parseInt(getProperty(key, "0"), 10);
271 } catch (NumberFormatException e) {
277 * Returns the property indicated expressed as an integer. The standard rules for Integer.parseInt(String, int)
278 * using a radix of 10 are used.
281 * The property name to retrieve.
282 * @param defaultValue
283 * The default value to be returned if the property does not exist
284 * @return The value of the property, or 0 if it does not exist or is invalid.
285 * @see org.openecomp.appc.configuration.Configuration#getIntegerProperty(java.lang.String, int)
288 public int getIntegerProperty(String key, int defaultValue) {
289 if (isPropertyDefined(key)) {
290 return getIntegerProperty(key);
296 * Returns the specified property as a long integer value, if it exists, or zero if it does not.
299 * The key of the property desired.
300 * @return The value of the property expressed as an integer long value, or zero if the property does not exist or
301 * is not a valid integer long.
302 * @see org.openecomp.appc.configuration.Configuration#getLongProperty(java.lang.String)
304 @SuppressWarnings("nls")
306 public long getLongProperty(String key) {
308 return Long.parseLong(getProperty(key, "0"), 10);
309 } catch (NumberFormatException e) {
315 * Returns the specified property as a long integer value, if it exists, or the default value if it does not exist
319 * The key of the property desired.
320 * @param defaultValue
321 * the value to be returned if the property is not valid or does not exist.
322 * @return The value of the property expressed as an integer long value, or the default value if the property does
323 * not exist or is not a valid integer long.
324 * @see org.openecomp.appc.configuration.Configuration#getLongProperty(java.lang.String, long)
327 public long getLongProperty(String key, long defaultValue) {
328 if (isPropertyDefined(key)) {
329 return getLongProperty(key);
335 * This method can be called to retrieve a properties object that is immutable. Any attempt to modify the properties
336 * object returned will result in an exception. This allows a caller to view the current configuration as a set of
339 * @return An unmodifiable properties object.
340 * @see org.openecomp.appc.configuration.Configuration#getProperties()
343 public Properties getProperties() {
344 return new UnmodifiableProperties(properties);
348 * This method is called to obtain a property as a string value
351 * The key of the property
352 * @return The string value, or null if it does not exist.
355 public String getProperty(String key) {
356 String value = properties.getProperty(key);
360 return expandVariables(value.trim());
364 * This method is called to obtain a property as a string value
367 * The key of the property
368 * @param defaultValue
369 * The default value to be returned if the property does not exist
370 * @return The string value, or null if it does not exist.
371 * @see org.openecomp.appc.configuration.Configuration#getProperty(java.lang.String, java.lang.String)
374 public String getProperty(String key, String defaultValue) {
375 if (isPropertyDefined(key)) {
376 return getProperty(key);
379 if (defaultValue == null) {
383 return expandVariables(defaultValue.trim());
387 * @see java.lang.Object#hashCode()
390 public int hashCode() {
391 return (properties == null ? 0 : properties.hashCode());
395 * Returns true if the named property is defined, false otherwise.
398 * The key of the property we are interested in
399 * @return True if the property exists.
402 public boolean isPropertyDefined(String key) {
403 return properties.containsKey(key);
407 * Returns an indication of the validity of the boolean property. A boolean property is considered to be valid only
408 * if it has the value "true" or "false" (ignoring case).
411 * The property to be checked
412 * @returns True if the value is a boolean constant, or false if it does not exist or is not a correct string
413 * @see org.openecomp.appc.configuration.Configuration#isValidBoolean(java.lang.String)
415 @SuppressWarnings("nls")
417 public boolean isValidBoolean(String key) {
418 String value = getProperty(key);
420 value = value.toLowerCase();
421 return value.matches("true|false");
427 * Returns an indication if the indicated property represents a valid double-precision floating point number.
430 * The property to be examined
431 * @returns True if the property is a valid representation of a double, or false if it does not exist or contains
432 * illegal characters.
433 * @see org.openecomp.appc.configuration.Configuration#isValidDouble(java.lang.String)
436 public boolean isValidDouble(String key) {
437 String value = getProperty(key);
440 Double.valueOf(value);
442 } catch (NumberFormatException e) {
450 * Returns an indication if the property is a valid integer value or not.
453 * The key of the property to check
454 * @returns True if the value is a valid integer string, or false if it does not exist or contains illegal
456 * @see org.openecomp.appc.configuration.Configuration#isValidInteger(java.lang.String)
459 public boolean isValidInteger(String key) {
460 String value = getProperty(key);
463 Integer.parseInt(value.trim(), 10);
465 } catch (NumberFormatException e) {
473 * Determines is the specified property exists and is a valid representation of an integer long value.
476 * The property to be checked
477 * @return True if the property is a valid representation of an integer long value, and false if it either does not
478 * exist or is not valid.
479 * @see org.openecomp.appc.configuration.Configuration#isValidLong(java.lang.String)
482 public boolean isValidLong(String key) {
483 String value = getProperty(key);
486 Long.parseLong(value.trim(), 10);
488 } catch (NumberFormatException e) {
496 * This method allows an implementation to load configuration properties that may override default values.
499 * An input stream that contains the properties to be loaded
501 public void setProperties(InputStream is) {
504 } catch (IOException e) {
510 * This method allows an implementation to load configuration properties that may override default values.
513 * An optional Properties object to be merged into the configuration, replacing any same-named
515 * @see org.openecomp.appc.configuration.Configuration#setProperties(java.util.Properties)
518 public void setProperties(Properties props) {
519 properties.putAll(props);
520 decryptAllProperties();
524 * This method allows a caller to insert a new property definition into the configuration object. This allows the
525 * application to adjust or add to the current configuration. If the property already exists, it is replaced with
529 * The key of the property to be defined
531 * The value of the property to be defined
532 * @see org.openecomp.appc.configuration.Configuration#setProperty(java.lang.String, java.lang.String)
535 public void setProperty(String key, String value) {
536 properties.setProperty(key, decrypt(value));
540 * @see java.lang.Object#toString()
542 @SuppressWarnings("nls")
544 public String toString() {
545 return String.format("Configuration: %d properties, keys:[%s]", properties.size(), properties.keySet()
550 * This is a helper method to read the manifest of the jar file that this class was loaded from. Note that this will
551 * only work if the code is packaged in a jar file. If it is an open deployment, such as under eclipse, this will
552 * not work and there is code added to detect that case.
554 * @return The manifest object from the jar file, or null if the code is not packaged in a jar file.
559 private Manifest getManifest() {
560 ProtectionDomain domain = getClass().getProtectionDomain();
561 CodeSource source = domain.getCodeSource();
562 URL location = source.getLocation();
563 String path = location.getPath();
564 int index = path.indexOf('!');
566 path = path.substring(0, index);
568 if (path.endsWith(".jar")) {
569 try (JarFile jar = new JarFile(location.getFile())) {
570 return jar.getManifest();
571 } catch (IOException e) {
572 logger.error("getManifest", e);