From 21788cc75a85a6e7b2097c5549957a38178a9197 Mon Sep 17 00:00:00 2001 From: Ryan Goulding Date: Wed, 6 Sep 2017 11:47:00 -0400 Subject: Fix service registration for SDNC sliPluginUtils was using a BundleActivator for Service Instantiation, which is prone to heisenbugs due to indeterminate service instantiation logic. This removes the BundleActivator and instantiates services using blueprint. Since dme2.properties are parsed using Properties instead of using a ManagedService, the decision was to just keep them immutable. Future work may involve making instance variables private in DME2, since currently Dme2Test performs direct member access on DME2 instance variables which is considered bad practices (violates encapsulation). Issue-Id: SDNC-54 Change-Id: Ib1155565e04e9a95d222bc4028a0845d9d81bd82 Signed-off-by: Ryan Goulding --- sliPluginUtils/provider/pom.xml | 1 - .../onap/ccsdk/sli/core/slipluginutils/DME2.java | 49 ++++- .../slipluginutils/Dme2PropertiesProvider.java | 223 +++++++++++++++++++++ .../sli/core/slipluginutils/SliPluginUtils.java | 2 - .../slipluginutils/SliPluginUtilsActivator.java | 95 --------- .../blueprint/slipluginutils-blueprint.xml | 19 ++ .../ccsdk/sli/core/slipluginutils/Dme2Test.java | 10 +- 7 files changed, 290 insertions(+), 109 deletions(-) create mode 100644 sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2PropertiesProvider.java delete mode 100644 sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtilsActivator.java create mode 100644 sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml (limited to 'sliPluginUtils') diff --git a/sliPluginUtils/provider/pom.xml b/sliPluginUtils/provider/pom.xml index 1af88e829..430221fcb 100755 --- a/sliPluginUtils/provider/pom.xml +++ b/sliPluginUtils/provider/pom.xml @@ -70,7 +70,6 @@ org.onap.ccsdk.sli.core.slipluginutils - org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtilsActivator org.onap.ccsdk.sli.core.slipluginutils org.onap.ccsdk.sli.core.*,org.osgi.framework.*,org.slf4j.*,java.net.* *;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|mysql-connector-java|slf4j-api|jcl-over-slf4j diff --git a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/DME2.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/DME2.java index 105ae9545..326490d9d 100644 --- a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/DME2.java +++ b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/DME2.java @@ -23,6 +23,7 @@ package org.onap.ccsdk.sli.core.slipluginutils; import java.util.Map; +import java.util.Optional; import org.onap.ccsdk.sli.core.sli.SvcLogicContext; import org.onap.ccsdk.sli.core.sli.SvcLogicException; import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin; @@ -35,16 +36,19 @@ import org.slf4j.LoggerFactory; * A SvcLogicJavaPlugin that generates DME2 proxy urls using parameters from context memory. */ public class DME2 implements SvcLogicJavaPlugin { - String aafUserName; - String aafPassword; - String envContext; - String routeOffer; - String[] proxyUrls; + + private static final Logger LOG = LoggerFactory.getLogger(DME2.class); + + final String aafUserName; + final String aafPassword; + final String envContext; + final String routeOffer; + final String[] proxyUrls; + final String commonServiceVersion; + Integer index; - String commonServiceVersion; String partner; - private static final Logger LOG = LoggerFactory.getLogger(DME2.class); public void setPartner(String partner) { if (partner != null && partner.length() > 0) { @@ -62,6 +66,37 @@ public class DME2 implements SvcLogicJavaPlugin { this.commonServiceVersion = commonServiceVersion; } + public DME2(final Dme2PropertiesProvider provider) { + this.aafUserName = useProperty(provider.getAafUsername(), Dme2PropertiesProvider.AAF_USERNAME_KEY); + this.aafPassword = useProperty(provider.getAafPassword(), Dme2PropertiesProvider.AAF_PASSWORD_KEY); + this.envContext = useProperty(provider.getEnvContext(), Dme2PropertiesProvider.ENV_CONTEXT_KEY); + this.routeOffer = useProperty(provider.getRouteOffer(), Dme2PropertiesProvider.ROUTE_OFFER_KEY); + this.index = 0; + this.commonServiceVersion = useProperty(provider.getCommonServiceVersion(), + Dme2PropertiesProvider.COMMON_SERVICE_VERSION_KEY); + + final Optional maybeProxyUrls = provider.getProxyUrls(); + if (maybeProxyUrls.isPresent()) { + this.proxyUrls = maybeProxyUrls.get(); + } else { + warnOfMissingProperty(Dme2PropertiesProvider.PROXY_URL_KEY); + this.proxyUrls = null; + } + this.setPartner(useProperty(provider.getPartner(), Dme2PropertiesProvider.PARTNER_KEY)); + } + + private String useProperty(final Optional propertyOptional, final String propertyKey) { + if (propertyOptional.isPresent()) { + return propertyOptional.get(); + } + warnOfMissingProperty(propertyKey); + return null; + } + + private void warnOfMissingProperty(final String propertyName) { + LOG.warn("Utilizing null for {} since it was left unassigned in the properties file"); + } + // constructs a URL to contact the proxy which contacts a DME2 service public String constructUrl(String service, String version, String subContext) { StringBuilder sb = new StringBuilder(); diff --git a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2PropertiesProvider.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2PropertiesProvider.java new file mode 100644 index 000000000..519614916 --- /dev/null +++ b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2PropertiesProvider.java @@ -0,0 +1,223 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP : CCSDK + * ================================================================================ + * Copyright (C) 2017 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.ccsdk.sli.core.slipluginutils; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Strings; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.Properties; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Immutable properties container for dme2 properties. Since the initial design decision was made to + * utilize Properties instead of an OSGi ManagedService, it was decided + * to make these properties immutable. + */ +public final class Dme2PropertiesProvider { + + private static final Logger LOG = LoggerFactory.getLogger(Dme2PropertiesProvider.class); + + /** + * The name of the environment variable to specify the configuration directory. + */ + private static final String SDNC_ROOT_DIR_ENV_VAR_KEY = "SDNC_CONFIG_DIR"; + + /** + * the dme2 properties file name. + */ + private static final String DME2_PROPERTIES_FILE_NAME = "dme2.properties"; + + /** + * the key for proxyUrl, which represents a CSV list of urls + */ + static final String PROXY_URL_KEY = "proxyUrl"; + + /** + * indicates that proxy urls are separated by commas + */ + private static final String PROXY_URLS_VALUE_SEPARATOR = ","; + + /** + * the key for aafUsername + */ + static final String AAF_USERNAME_KEY = "aafUsername"; + + /** + * the key for aafPassword + */ + static final String AAF_PASSWORD_KEY = "aafPassword"; + + /** + * the key for envContext + */ + static final String ENV_CONTEXT_KEY = "envContext"; + + /** + * the key for routeOffer + */ + static final String ROUTE_OFFER_KEY = "routeOffer"; + + /** + * the key for commonServiceVersion + */ + static final String COMMON_SERVICE_VERSION_KEY = "commonServiceVersion"; + + /** + * the key for partner + */ + static final String PARTNER_KEY = "partner"; + + private Optional proxyUrls = Optional.empty(); + + private Optional aafUsername = Optional.empty(); + + private Optional aafPassword = Optional.empty(); + + private Optional envContext = Optional.empty(); + + private Optional routeOffer = Optional.empty(); + + private Optional commonServiceVersion = Optional.empty(); + + private Optional partner = Optional.empty(); + + + /** + * Instantiates the properties provider, which involves loading the appropriate properties for dme2. + */ + public Dme2PropertiesProvider() { + this(getDme2Path(SDNC_ROOT_DIR_ENV_VAR_KEY, DME2_PROPERTIES_FILE_NAME).toString()); + } + + /** + * Instantiates the properties provider, which involves loading the appropriate properties for dme2. + * + * @param dme2Path location of the dme2.properties file + */ + @VisibleForTesting + Dme2PropertiesProvider(final String dme2Path) { + final Properties properties; + try { + properties = getProperties(dme2Path); + this.proxyUrls = getProxyUrls(properties); + this.aafUsername = getAafUsername(properties); + this.aafPassword = getAafPassword(properties); + this.envContext = getEnvContext(properties); + this.routeOffer = getRouteOffer(properties); + this.commonServiceVersion = getCommonServiceVersion(properties); + this.partner = getPartner(properties); + } catch (final FileNotFoundException e) { + LOG.error("dme2.properties file could not be found at path: {}", dme2Path, e); + } catch (final IOException e) { + LOG.error("fatal error reading dme2.properties at path: {}", dme2Path, e); + } + } + + private static Path getDme2Path(final String sdncRootDirectory, final String dme2Filename) { + return Paths.get(sdncRootDirectory, dme2Filename); + } + + private static Properties getProperties(final String dme2Path) throws IOException { + final File dme2File = new File(dme2Path); + final Properties properties = new Properties(); + properties.load(new FileReader(dme2File)); + return properties; + } + + private String getProxyUrl(final Properties properties) { + return properties.getProperty(PROXY_URL_KEY); + } + + private Optional getProxyUrls(final Properties properties) { + final String proxyUrlsValue = getProxyUrl(properties); + if (!Strings.isNullOrEmpty(proxyUrlsValue)) { + return Optional.ofNullable(proxyUrlsValue.split(PROXY_URLS_VALUE_SEPARATOR)); + } + return Optional.empty(); + } + + public Optional getProxyUrls() { + return this.proxyUrls; + } + + private Optional getAafUsername(final Properties properties) { + final String aafUsernameValue = properties.getProperty(AAF_USERNAME_KEY); + return Optional.ofNullable(aafUsernameValue); + } + + Optional getAafUsername() { + return this.aafUsername; + } + + private Optional getAafPassword(final Properties properties) { + final String aafPassword = properties.getProperty(AAF_PASSWORD_KEY); + return Optional.ofNullable(aafPassword); + } + + Optional getAafPassword() { + return this.aafPassword; + } + + private Optional getEnvContext(final Properties properties) { + final String envContext = properties.getProperty(ENV_CONTEXT_KEY); + return Optional.ofNullable(envContext); + } + + Optional getEnvContext() { + return this.envContext; + } + + private Optional getRouteOffer(final Properties properties) { + final String routeOffer = properties.getProperty(ROUTE_OFFER_KEY); + return Optional.ofNullable(routeOffer); + } + + Optional getRouteOffer() { + return this.routeOffer; + } + + private Optional getCommonServiceVersion(final Properties properties) { + final String commonServiceVersion = properties.getProperty(COMMON_SERVICE_VERSION_KEY); + return Optional.ofNullable(commonServiceVersion); + } + + Optional getCommonServiceVersion() { + return this.commonServiceVersion; + } + + private Optional getPartner(final Properties properties) { + final String partner = properties.getProperty(PARTNER_KEY); + return Optional.ofNullable(partner); + } + + Optional getPartner() { + return this.partner; + } +} diff --git a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java index 8a2aa6d69..e6811e789 100644 --- a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java +++ b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java @@ -60,8 +60,6 @@ public class SliPluginUtils implements SvcLogicJavaPlugin { public SliPluginUtils() {} - public SliPluginUtils( Properties props ) {} - // ========== CONTEXT MEMORY FUNCTIONS ========== diff --git a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtilsActivator.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtilsActivator.java deleted file mode 100644 index 89eb4f23b..000000000 --- a/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtilsActivator.java +++ /dev/null @@ -1,95 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP : CCSDK - * ================================================================================ - * Copyright (C) 2017 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.ccsdk.sli.core.slipluginutils; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.Properties; - -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SliPluginUtilsActivator implements BundleActivator { - @SuppressWarnings("rawtypes") private List registrations = new LinkedList(); - - private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtilsActivator.class); - private static final String SDNC_ROOT_DIR = "SDNC_CONFIG_DIR"; - private static final String DME2_PROPERTIES_FILE_NAME = "dme2.properties"; - - @Override - public void start(BundleContext ctx) throws Exception { - SliPluginUtils plugin = new SliPluginUtils(new Properties()); - LOG.info("Registering service " + plugin.getClass().getName()); - registrations.add(ctx.registerService(plugin.getClass().getName(), plugin, null)); - - SliStringUtils sliStringUtils_Plugin = new SliStringUtils(); - LOG.info("Registering service " + sliStringUtils_Plugin.getClass().getName()); - registrations.add(ctx.registerService(sliStringUtils_Plugin.getClass().getName(), sliStringUtils_Plugin, null)); - - try { - String path = System.getenv(SDNC_ROOT_DIR) + File.separator + DME2_PROPERTIES_FILE_NAME; - DME2 dmePlugin = initDme2(path); - if (dmePlugin != null) { - LOG.info("Registering service " + dmePlugin.getClass().getName()); - registrations.add(ctx.registerService(dmePlugin.getClass().getName(), dmePlugin, null)); - } - } catch (Exception e) { - LOG.error("DME2 plugin could not be started", e); - } - } - - public DME2 initDme2(String pathToDmeProperties) { - Properties dme2properties = new Properties(); - String loadPropertiesErrorMessage = "Couldn't load DME2 properties at path " + pathToDmeProperties; - File dme2propertiesFile = new File(pathToDmeProperties); - - try { - dme2properties.load(new FileReader(dme2propertiesFile)); - String proxyUrlProperty = dme2properties.getProperty("proxyUrl"); - String[] proxyUrls = proxyUrlProperty.split(","); - DME2 dmePlugin = new DME2(dme2properties.getProperty("aafUserName"), dme2properties.getProperty("aafPassword"), dme2properties.getProperty("envContext"), dme2properties.getProperty("routeOffer"), proxyUrls, dme2properties.getProperty("commonServiceVersion")); - dmePlugin.setPartner(dme2properties.getProperty("partner")); - return dmePlugin; - } catch (FileNotFoundException e) { - LOG.error(loadPropertiesErrorMessage); - } catch (IOException e) { - LOG.error(loadPropertiesErrorMessage); - } - LOG.error("Couldn't create DME2 plugin"); - return null; - } - - @Override - public void stop(BundleContext ctx) throws Exception { - for (@SuppressWarnings("rawtypes") ServiceRegistration registration : registrations) { - registration.unregister(); - registration = null; - } - } -} diff --git a/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml b/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml new file mode 100644 index 000000000..c0952d2a2 --- /dev/null +++ b/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2Test.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2Test.java index 48c32f452..ab681ad25 100644 --- a/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2Test.java +++ b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/Dme2Test.java @@ -72,8 +72,9 @@ public class Dme2Test { @Test public void createDme2EndtoEnd() { - SliPluginUtilsActivator activator = new SliPluginUtilsActivator(); - DME2 dme2 = activator.initDme2("src/test/resources/dme2.e2e.properties"); + Dme2PropertiesProvider provider = + new Dme2PropertiesProvider("src/test/resources/dme2.e2e.properties"); + DME2 dme2 = new DME2(provider); assertEquals("user@sample.com", dme2.aafUserName); assertEquals("fake", dme2.aafPassword); assertEquals("UAT", dme2.envContext); @@ -89,8 +90,9 @@ public class Dme2Test { @Test public void createDme2Prod() { - SliPluginUtilsActivator activator = new SliPluginUtilsActivator(); - DME2 dme2 = activator.initDme2("src/test/resources/dme2.prod.properties"); + Dme2PropertiesProvider provider = + new Dme2PropertiesProvider("src/test/resources/dme2.prod.properties"); + DME2 dme2 = new DME2(provider); assertEquals("user@sample.com", dme2.aafUserName); assertEquals("fake", dme2.aafPassword); assertEquals("PROD", dme2.envContext); -- cgit 1.2.3-korg