diff options
author | Ryan Goulding <ryandgoulding@gmail.com> | 2017-09-06 11:47:00 -0400 |
---|---|---|
committer | Ryan Goulding <ryandgoulding@gmail.com> | 2017-09-06 11:50:20 -0400 |
commit | 21788cc75a85a6e7b2097c5549957a38178a9197 (patch) | |
tree | 2f1cc40eeaa5190f75a5022e9178178e997855a6 /sliPluginUtils | |
parent | b6ad62d01b1045ff03c03aa05ee1beeaabc633c7 (diff) |
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 <ryandgoulding@gmail.com>
Diffstat (limited to 'sliPluginUtils')
7 files changed, 290 insertions, 109 deletions
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 @@ <configuration> <instructions> <Bundle-SymbolicName>org.onap.ccsdk.sli.core.slipluginutils</Bundle-SymbolicName> - <Bundle-Activator>org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtilsActivator</Bundle-Activator> <Export-Package>org.onap.ccsdk.sli.core.slipluginutils</Export-Package> <Import-Package>org.onap.ccsdk.sli.core.*,org.osgi.framework.*,org.slf4j.*,java.net.*</Import-Package> <Embed-Dependency>*;scope=compile|runtime;artifactId=!sli-common|org.eclipse.osgi|mysql-connector-java|slf4j-api|jcl-over-slf4j</Embed-Dependency> 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<String []> 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<String> 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 <code>Properties</code> instead of an OSGi <code>ManagedService</code>, 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 <code>proxyUrl</code>, 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 <code>aafUsername</code> + */ + static final String AAF_USERNAME_KEY = "aafUsername"; + + /** + * the key for <code>aafPassword</code> + */ + static final String AAF_PASSWORD_KEY = "aafPassword"; + + /** + * the key for <code>envContext</code> + */ + static final String ENV_CONTEXT_KEY = "envContext"; + + /** + * the key for <code>routeOffer</code> + */ + static final String ROUTE_OFFER_KEY = "routeOffer"; + + /** + * the key for <code>commonServiceVersion</code> + */ + static final String COMMON_SERVICE_VERSION_KEY = "commonServiceVersion"; + + /** + * the key for <code>partner</code> + */ + static final String PARTNER_KEY = "partner"; + + private Optional<String []> proxyUrls = Optional.empty(); + + private Optional<String> aafUsername = Optional.empty(); + + private Optional<String> aafPassword = Optional.empty(); + + private Optional<String> envContext = Optional.empty(); + + private Optional<String> routeOffer = Optional.empty(); + + private Optional<String> commonServiceVersion = Optional.empty(); + + private Optional<String> 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<String []> 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<String []> getProxyUrls() { + return this.proxyUrls; + } + + private Optional<String> getAafUsername(final Properties properties) { + final String aafUsernameValue = properties.getProperty(AAF_USERNAME_KEY); + return Optional.ofNullable(aafUsernameValue); + } + + Optional<String> getAafUsername() { + return this.aafUsername; + } + + private Optional<String> getAafPassword(final Properties properties) { + final String aafPassword = properties.getProperty(AAF_PASSWORD_KEY); + return Optional.ofNullable(aafPassword); + } + + Optional<String> getAafPassword() { + return this.aafPassword; + } + + private Optional<String> getEnvContext(final Properties properties) { + final String envContext = properties.getProperty(ENV_CONTEXT_KEY); + return Optional.ofNullable(envContext); + } + + Optional<String> getEnvContext() { + return this.envContext; + } + + private Optional<String> getRouteOffer(final Properties properties) { + final String routeOffer = properties.getProperty(ROUTE_OFFER_KEY); + return Optional.ofNullable(routeOffer); + } + + Optional<String> getRouteOffer() { + return this.routeOffer; + } + + private Optional<String> getCommonServiceVersion(final Properties properties) { + final String commonServiceVersion = properties.getProperty(COMMON_SERVICE_VERSION_KEY); + return Optional.ofNullable(commonServiceVersion); + } + + Optional<String> getCommonServiceVersion() { + return this.commonServiceVersion; + } + + private Optional<String> getPartner(final Properties properties) { + final String partner = properties.getProperty(PARTNER_KEY); + return Optional.ofNullable(partner); + } + + Optional<String> 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<ServiceRegistration> registrations = new LinkedList<ServiceRegistration>(); - - 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" + xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0" + odl:use-default-for-reference-types="true"> + + + <bean id="sliPluginUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" /> + <service ref="sliPluginUtils" interface="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" /> + + <bean id="sliStringUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" /> + <service ref="sliStringUtils" interface="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" /> + + <bean id="dme2Properties" class="org.onap.ccsdk.sli.core.slipluginutils.Dme2PropertiesProvider" /> + <bean id="dme2" class="org.onap.ccsdk.sli.core.slipluginutils.DME2"> + <argument ref="dme2Properties" /> + </bean> + <service ref="dme2" interface="org.onap.ccsdk.sli.core.slipluginutils.DME2" /> + +</blueprint>
\ 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); |