diff options
Diffstat (limited to 'utils/src/main/java/org/onap/policy')
4 files changed, 225 insertions, 247 deletions
diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java index 7253c746..e72ebaba 100644 --- a/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java +++ b/utils/src/main/java/org/onap/policy/common/utils/properties/PropertyConfiguration.java @@ -25,8 +25,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.onap.policy.common.utils.properties.exception.PropertyAccessException; import org.onap.policy.common.utils.properties.exception.PropertyException; import org.onap.policy.common.utils.properties.exception.PropertyInvalidException; @@ -35,7 +38,9 @@ import org.onap.policy.common.utils.properties.exception.PropertyMissingExceptio /** * Configuration whose fields are initialized by reading from a set of {@link Properties}, * as directed by the {@link Property} annotations that appear on fields within the - * subclass. + * subclass. The values of the fields are set via <i>setXxx()</i> methods. As a result, if + * a field is annotated and there is no corresponding <i>setXxx()</i> method, then an + * exception will be thrown. * <p> * It is possible that an invalid <i>defaultValue</i> is specified via the * {@link Property} annotation. This could remain undetected until an optional property is @@ -104,7 +109,10 @@ public class PropertyConfiguration { checkModifiable(field, prop); - if (setValue(field, props, prop)) { + Method setter = getSetter(field, prop); + checkSetter(setter, prop); + + if (setValue(setter, field, props, prop)) { return true; } @@ -112,15 +120,33 @@ public class PropertyConfiguration { } /** + * @param field field whose value is to be set + * @param prop property of interest + * @return the method to be used to set the field's value + * @throws PropertyAccessException if a "set" method cannot be identified + */ + private Method getSetter(Field field, Property prop) throws PropertyAccessException { + String nm = "set" + StringUtils.capitalize(field.getName()); + + try { + return this.getClass().getMethod(nm, field.getType()); + + } catch (NoSuchMethodException | SecurityException e) { + throw new PropertyAccessException(prop.name(), nm, e); + } + } + + /** * Sets a field's value from a particular property. * + * @param setter method to be used to set the field's value * @param field field whose value is to be set * @param props properties from which to get the value * @param prop property of interest * @return {@code true} if the property's value was set, {@code false} otherwise * @throws PropertyException if an error occurs */ - protected boolean setValue(Field field, Properties props, Property prop) throws PropertyException { + protected boolean setValue(Method setter, Field field, Properties props, Property prop) throws PropertyException { try { Object val = getValue(field, props, prop); @@ -128,23 +154,15 @@ public class PropertyConfiguration { return false; } else { - - /* - * According to java docs & blogs, "field" is our own copy, so we're free - * to change the flags without impacting the real permissions of the field - * within the real class. - */ - field.setAccessible(true); - - field.set(this, val); + setter.invoke(this, val); return true; } } catch (IllegalArgumentException e) { throw new PropertyInvalidException(prop.name(), field.getName(), e); - } catch (IllegalAccessException e) { - throw new PropertyAccessException(prop.name(), field.getName(), e); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new PropertyAccessException(prop.name(), setter.getName(), e); } } @@ -203,6 +221,21 @@ public class PropertyConfiguration { } /** + * Verifies that the setter method is not <i>static</i>. + * + * @param setter method to be checked + * @param prop property of interest + * @throws PropertyAccessException if the method is static + */ + private void checkSetter(Method setter, Property prop) throws PropertyAccessException { + int mod = setter.getModifiers(); + + if (Modifier.isStatic(mod)) { + throw new PropertyAccessException(prop.name(), setter.getName(), "method is 'static'"); + } + } + + /** * Gets a property value, coercing it to a String. * * @param fieldName field whose value is to be set diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java new file mode 100644 index 00000000..0f416c3a --- /dev/null +++ b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecProperties.java @@ -0,0 +1,117 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.properties; + +import java.util.Properties; + +/** + * Properties with an optional specialization (e.g., session name, controller name). + */ +public class SpecProperties extends Properties { + private static final long serialVersionUID = 1L; + + /** + * The property prefix, ending with ".". + */ + private final String prefix; + + /** + * The specialized property prefix, ending with ".". + */ + private final String specPrefix; + + /** + * + * @param prefix the property name prefix that appears before any specialization, may + * be "" + * @param specialization the property name specialization (e.g., session name) + */ + public SpecProperties(String prefix, String specialization) { + this.prefix = withTrailingDot(prefix); + this.specPrefix = withTrailingDot(this.prefix + specialization); + } + + /** + * + * @param prefix the property name prefix that appears before any specialization, may + * be "" + * @param specialization the property name specialization (e.g., session name) + * @param props the default properties + */ + public SpecProperties(String prefix, String specialization, Properties props) { + super(props); + + this.prefix = withTrailingDot(prefix); + this.specPrefix = withTrailingDot(this.prefix + specialization); + } + + /** + * Adds a trailing "." to a String, if it doesn't already have one. + * + * @param text text to which the "." should be added + * @return the text, with a trailing "." + */ + private static String withTrailingDot(String text) { + return text.isEmpty() || text.endsWith(".") ? text : text + "."; + } + + /** + * Gets the property whose value has the given key, looking first for the specialized + * property name, and then for the generalized property name. + * + * @param key property name, without the specialization + * @return the value from the property set, or {@code null} if the property set does + * not contain the value + */ + @Override + public String getProperty(String key) { + if (!key.startsWith(prefix)) { + return super.getProperty(key); + } + + String suffix = key.substring(prefix.length()); + + String val = super.getProperty(specPrefix + suffix); + if (val != null) { + return val; + } + + return super.getProperty(key); + } + + protected String getPrefix() { + return prefix; + } + + protected String getSpecPrefix() { + return specPrefix; + } + + @Override + public final int hashCode() { + throw new UnsupportedOperationException("SpecProperties cannot be hashed"); + } + + @Override + public final boolean equals(Object obj) { + throw new UnsupportedOperationException("cannot compare SpecProperties"); + } +} diff --git a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java b/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java deleted file mode 100644 index 9e3767c1..00000000 --- a/utils/src/main/java/org/onap/policy/common/utils/properties/SpecPropertyConfiguration.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * ONAP Policy Engine - Common Modules - * ================================================================================ - * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.policy.common.utils.properties; - -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.onap.policy.common.utils.properties.exception.PropertyException; - -/** - * PropertyConfiguration whose property names are specialized, using a specialization. A - * property name can take one of the following forms: - * <dl> - * <dt>aaa{$}Ddd</dt> - * <dd>if the specialization is "Xxx", then it looks for the value associated with the - * property named "aaaXxxDdd"</dd> - * <dt>aaa{Bbb?Ccc}Ddd</dt> - * <dd>if the specialization is "Xxx", then it looks for the value associated with the - * property named "aaaBbbXxxCccDdd". If the property does not exist, then it looks for the - * value associated with the property named "aaaDdd" (i.e., without the - * specialization)</dd> - * <dt>aaa</dt> - * <dd>simply looks for the value associated with the property named "aaa", without using - * the specialization</dd> - * </dl> - * <p> - * In the above examples, any of the components (e.g., "aaa") may be empty. - */ -public class SpecPropertyConfiguration extends PropertyConfiguration { - - /** - * Pattern to extract the specializer from a property name. Group 1 matches the form, - * "{$}", while groups 2 and 3 match the prefix and suffix, respectively, of the form, - * "{prefix?suffix}". - */ - private static final Pattern SPEC_PAT = Pattern.compile("" - // start of specialization info - + "\\{(?:" - // specialization type 1 - + "(\\$)" - // alternative - + "|" - // specialization type 2 - + "(?:" - // specialization type 2 prefix, may be empty - + "([^}?]*)" - // place-holder for the specialization, itself - + "\\?" - // specialization type 2 suffix, may be empty - + "([^}]*)" - // end of specialization type 2 - + ")" - // end of specialization info - + ")\\}"); - - /** - * The specialization to be used within property names. - */ - private final String specialization; - - /** - * Constructs a configuration, without populating any fields; fields should be - * populated later by invoking {@link #setAllFields(Properties)}. - * - * @param specialization specialization to be substituted within property names - */ - public SpecPropertyConfiguration(String specialization) { - super(); - - this.specialization = specialization; - } - - /** - * - * Initializes each "@Property" field with its value, as found in the properties. - * - * @param specialization specialization to be substituted within property names - * @param props properties from which to extract the values - * @throws PropertyException if an error occurs - */ - public SpecPropertyConfiguration(String specialization, Properties props) throws PropertyException { - super(); - - this.specialization = specialization; - - setAllFields(props); - } - - /** - * Gets a property's value, examining the property name for each of the types of - * specialization. - */ - @Override - protected String getRawPropertyValue(Properties props, String propnm) { - Matcher mat = SPEC_PAT.matcher(propnm); - - if (!mat.find()) { - // property name isn't specialized - use it as is - return super.getRawPropertyValue(props, propnm); - - } else if (mat.group(1) != null) { - // replace "{$}" with the specialization name - return super.getRawPropertyValue(props, specializeType1(propnm, specialization, mat)); - - } else { - // first try to get the property using the specialization info - String val = super.getRawPropertyValue(props, specializeType2(propnm, specialization, mat)); - if (val != null) { - return val; - } - - // wasn't found - try again, without any specialization info - return super.getRawPropertyValue(props, generalizeType2(propnm, mat)); - } - } - - /** - * Generalizes a property name by stripping any specialization info from it. This is - * typically used to construct property names for junit testing. - * - * @param propnm property name to be stripped of specialization info - * @return the generalized property name - * @throws IllegalArgumentException if the property name requires specialization - * (i.e., contains "{$}") - */ - public static String generalize(String propnm) { - Matcher mat = SPEC_PAT.matcher(propnm); - - if (!mat.find()) { - // property name has no specialization info - return propnm; - - } else if (mat.group(1) != null) { - // the "{$}" form requires specialization - throw new IllegalArgumentException("property requires specialization"); - - } else { - // property name has specialization info - strip it out - return generalizeType2(propnm, mat); - } - } - - /** - * - * Generalizes a property name of specialization type 2 (i.e., "{xxx?yyy}" form). - * - * @param propnm property name to be stripped of specialization info - * @param matcher the matcher that matched the "{xxx?yyy}" - * @return the generalized property name - */ - private static String generalizeType2(String propnm, Matcher mat) { - String prefix = propnm.substring(0, mat.start()); - String suffix = propnm.substring(mat.end()); - - return prefix + suffix; - } - - /** - * Specializes a property name by applying the specialization. This is typically used - * to construct property names for junit testing. - * - * @param propnm property name to be stripped of specialization info - * @param spec specialization to apply - * @return the specialized property name - */ - public static String specialize(String propnm, String spec) { - Matcher mat = SPEC_PAT.matcher(propnm); - - if (!mat.find()) { - // property name has no specialization info - leave it as is - return propnm; - - } else if (mat.group(1) != null) { - // the "{$}" form requires specialization - return specializeType1(propnm, spec, mat); - - } else { - // the "{xxx?yyy}" form requires specialization - return specializeType2(propnm, spec, mat); - } - } - - /** - * Specializes a property name of specialization type 1 (i.e., "{$}" form). - * - * @param propnm property name to be stripped of specialization info - * @param spec specialization to apply - * @param matcher the matcher that matched the "{$}" - * @return the specialized property name - */ - private static String specializeType1(String propnm, String spec, Matcher mat) { - String prefix = propnm.substring(0, mat.start()); - String suffix = propnm.substring(mat.end()); - - return prefix + spec + suffix; - } - - /** - * Specializes a property name of specialization type 2 (i.e., "{xxx?yyy}" form). - * - * @param propnm property name to be stripped of specialization info - * @param spec specialization to apply - * @param matcher the matcher that matched the "{xxx?yyy}" - * @return the specialized property name - */ - private static String specializeType2(String propnm, String spec, Matcher matcher) { - String prefix = propnm.substring(0, matcher.start()); - String suffix = propnm.substring(matcher.end()); - - String specPrefix = matcher.group(2); - String specSuffix = matcher.group(3); - - return (prefix + specPrefix + spec + specSuffix + suffix); - } -} diff --git a/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java b/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java new file mode 100644 index 00000000..cab469e5 --- /dev/null +++ b/utils/src/main/java/org/onap/policy/common/utils/time/CurrentTime.java @@ -0,0 +1,61 @@ +/* + * ============LICENSE_START======================================================= + * Common Utils + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.common.utils.time; + +import java.util.Date; + +/** + * Methods to access the current time. Classes can use objects of this type to get current + * time information, while allowing the objects to be overridden by junit tests. + */ +public class CurrentTime { + + /** + * + */ + public CurrentTime() { + super(); + } + + /** + * @return the current time, in milliseconds + */ + public long getMillis() { + return System.currentTimeMillis(); + } + + /** + * @return the current Date + */ + public Date getDate() { + return new Date(); + } + + /** + * Sleeps for a period of time. + * + * @param sleepMs amount of time to sleep, in milliseconds + * @throws InterruptedException + */ + public void sleep(long sleepMs) throws InterruptedException { + Thread.sleep(sleepMs); + } +} |