aboutsummaryrefslogtreecommitdiffstats
path: root/common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java
diff options
context:
space:
mode:
Diffstat (limited to 'common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java')
-rw-r--r--common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java395
1 files changed, 395 insertions, 0 deletions
diff --git a/common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java b/common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java
new file mode 100644
index 0000000000..77676314bc
--- /dev/null
+++ b/common/src/main/java/org/openecomp/mso/properties/MsoPropertiesFactory.java
@@ -0,0 +1,395 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * OPENECOMP - MSO
+ * ================================================================================
+ * 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.openecomp.mso.properties;
+
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.ejb.ConcurrencyManagement;
+import javax.ejb.ConcurrencyManagementType;
+import javax.ejb.LocalBean;
+import javax.ejb.Schedule;
+import javax.ejb.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+
+import org.openecomp.mso.logger.MessageEnum;
+import org.openecomp.mso.logger.MsoLogger;
+import org.openecomp.mso.utils.CryptoUtils;
+
+/**
+ * This EJB Singleton class returns an instance of the mso properties for a specified file.
+ * This class can handle many config at the same time and is thread safe.
+ * This instance is a copy of the one cached so it can be modified or reloaded without impacting the others class using
+ * it.
+ * The mso properties files loaded and cached here will be reloaded every X second (it's configurable with the init
+ * method)
+ * This class can be used as an EJB or can be instantiated directly as long as the EJB has been initialized for the current
+ * module. Locks are made manually and not using EJB locks to allow this.
+ *
+ *
+ */
+@Singleton(name = "MsoPropertiesFactory")
+@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
+@LocalBean
+@Path("/properties")
+public class MsoPropertiesFactory implements Serializable {
+
+ private static final long serialVersionUID = 4365495305496742113L;
+
+ protected static String prefixMsoPropertiesPath = System.getProperty ("mso.config.path");
+
+ private static MsoLogger LOGGER = MsoLogger.getMsoLogger (MsoLogger.Catalog.GENERAL);
+
+ // Keep a static copy of properties for global usage
+ private static final ConcurrentHashMap <String, MsoPropertiesParameters> msoPropertiesCache;
+
+ static {
+ if (prefixMsoPropertiesPath == null) {
+ // Hardcode if nothing is received
+ prefixMsoPropertiesPath = "";
+ }
+ msoPropertiesCache = new ConcurrentHashMap <String, MsoPropertiesParameters> ();
+ }
+
+ private static final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock ();
+
+ public MsoPropertiesFactory () {
+
+ }
+
+ private boolean isJsonFile(String propertiesFilePath) {
+ return propertiesFilePath.endsWith(".json");
+ }
+
+
+ private boolean isJavaPropertiesFile (String propertiesFilePath) {
+ return propertiesFilePath.endsWith(".properties");
+ }
+
+ private MsoPropertiesParameters createObjectType (MsoPropertiesParameters msoPropParams, String propertiesFilePath) throws MsoPropertiesException, IOException {
+
+ try {
+ if (this.isJavaPropertiesFile(propertiesFilePath)) {
+
+ msoPropParams.msoProperties = new MsoJavaProperties();
+ msoPropParams.msoPropertiesType = MsoPropertiesParameters.MsoPropertiesType.JAVA_PROP;
+ } else if (this.isJsonFile(propertiesFilePath)) {
+
+ msoPropParams.msoProperties = new MsoJsonProperties();
+ msoPropParams.msoPropertiesType = MsoPropertiesParameters.MsoPropertiesType.JSON_PROP;
+ } else {
+ throw new MsoPropertiesException("Unable to load the MSO properties file because format is not recognized (only .json or .properties): " + propertiesFilePath);
+ }
+
+ msoPropParams.msoProperties.loadPropertiesFile (propertiesFilePath);
+
+ return msoPropParams;
+ } finally {
+ if (msoPropParams.msoProperties!=null) {
+ msoPropParams.refreshCounter = msoPropParams.msoProperties.getAutomaticRefreshInMinutes();
+ }
+ }
+
+ }
+
+ /**
+ * This method is used to create a MsoProperties file cache and factory.
+ * The ID is kept in cache even if the config fails to be loaded.
+ * This is used to maintain the config ID until someone fixes the config file.
+ *
+ * @param msoPropertiesID A string representing the key of the config
+ * @param propertiesFilePath The mso properties file to load
+ *
+ * @throws MsoPropertiesException In case of issues with the mso properties loading
+ *
+ * @see MsoPropertiesFactory#getMsoJavaProperties()
+ * @see MsoPropertiesFactory#getMsoJsonProperties()
+ */
+ public void initializeMsoProperties (String msoPropertiesID,
+ String propertiesFilePath) throws MsoPropertiesException {
+
+ rwl.writeLock ().lock ();
+
+ String msoPropPath="none";
+ MsoPropertiesParameters msoPropertiesParams=new MsoPropertiesParameters();
+ try {
+ msoPropPath = prefixMsoPropertiesPath + propertiesFilePath;
+ if (msoPropertiesCache.get (msoPropertiesID) != null) {
+ throw new MsoPropertiesException ("The factory contains already an instance of this mso properties: "
+ + msoPropPath);
+ }
+ // Create the global MsoProperties object
+ msoPropertiesParams = createObjectType(msoPropertiesParams, msoPropPath);
+
+ } catch (FileNotFoundException e) {
+ throw new MsoPropertiesException ("Unable to load the MSO properties file because it has not been found:"
+ + msoPropPath, e);
+
+ } catch (IOException e) {
+ throw new MsoPropertiesException ("Unable to load the MSO properties file because IOException occurs: "
+ + msoPropPath, e);
+ } finally {
+ // put it in all cases, just to not forget about him and attempt a default reload
+ msoPropertiesCache.put (msoPropertiesID, msoPropertiesParams);
+ rwl.writeLock ().unlock ();
+ }
+ }
+
+ public void removeMsoProperties (String msoPropertiesID) throws MsoPropertiesException {
+
+ rwl.writeLock ().lock ();
+ try {
+ if (MsoPropertiesFactory.msoPropertiesCache.remove (msoPropertiesID) == null) {
+ throw new MsoPropertiesException ("Mso properties not found in cache:" + msoPropertiesID);
+ }
+ } finally {
+ rwl.writeLock ().unlock ();
+ }
+ }
+
+ /**
+ * This method clears all the configs in cache, the factory will then be free of any config.
+ *
+ * @see MsoPropertiesFactory#initializeMsoProperties(String, String)
+ */
+ public void removeAllMsoProperties () {
+
+ rwl.writeLock ().lock ();
+ try {
+ MsoPropertiesFactory.msoPropertiesCache.clear ();
+ } finally {
+ rwl.writeLock ().unlock ();
+ }
+ }
+
+ /**
+ * THis method can be used to change the file and timer fields of an existing MSO properties file.
+ *
+ * @param msoPropertiesID The MSO properties ID
+ * @param newMsoPropPath The new file Path
+ * @throws MsoPropertiesException In case of the MSO Properties is not found in cache
+ */
+ public void changeMsoPropertiesFilePath (String msoPropertiesID,
+ String newMsoPropPath) throws MsoPropertiesException {
+
+ rwl.writeLock ().lock ();
+ try {
+ MsoPropertiesParameters msoPropInCache = MsoPropertiesFactory.msoPropertiesCache.get (msoPropertiesID);
+
+ if (msoPropInCache != null) {
+ msoPropInCache.msoProperties.propertiesFileName = prefixMsoPropertiesPath + newMsoPropPath;
+
+ } else {
+ throw new MsoPropertiesException ("Mso properties not found in cache:" + msoPropertiesID);
+ }
+ } finally {
+ rwl.writeLock ().unlock ();
+ }
+ }
+
+ private AbstractMsoProperties getAndCloneProperties(String msoPropertiesID, MsoPropertiesParameters.MsoPropertiesType type) throws MsoPropertiesException {
+ rwl.readLock ().lock ();
+ try {
+ MsoPropertiesParameters msoPropInCache = MsoPropertiesFactory.msoPropertiesCache.get (msoPropertiesID);
+ if (msoPropInCache == null) {
+ throw new MsoPropertiesException ("Mso properties not found in cache:" + msoPropertiesID);
+ } else {
+ if (type.equals(msoPropInCache.msoPropertiesType)) {
+ return msoPropInCache.msoProperties.clone ();
+ } else {
+ throw new MsoPropertiesException ("Mso properties is not "+type.name()+" properties type:" + msoPropertiesID);
+ }
+
+ }
+ } finally {
+ rwl.readLock ().unlock ();
+ }
+ }
+
+ /**
+ * Get the MSO Properties (As Java Properties) as a copy of the mso properties cache.
+ * The object returned can therefore be modified.
+ *
+ * @return A copy of the mso properties, properties class can be empty if the file has not been read properly
+ * @throws MsoPropertiesException If the mso properties does not exist in the cache
+ */
+ public MsoJavaProperties getMsoJavaProperties (String msoPropertiesID) throws MsoPropertiesException {
+
+ return (MsoJavaProperties)getAndCloneProperties(msoPropertiesID,MsoPropertiesParameters.MsoPropertiesType.JAVA_PROP);
+ }
+
+ /**
+ * Get the MSO Properties (As JSON Properties) as a copy of the mso properties cache.
+ * The object returned can therefore be modified.
+ *
+ * @return A copy of the mso properties, properties class can be empty if the file has not been read properly
+ * @throws MsoPropertiesException If the mso properties does not exist in the cache
+ */
+ public MsoJsonProperties getMsoJsonProperties (String msoPropertiesID) throws MsoPropertiesException {
+
+ return (MsoJsonProperties)getAndCloneProperties(msoPropertiesID,MsoPropertiesParameters.MsoPropertiesType.JSON_PROP);
+ }
+
+ /**
+ * Get all MSO Properties as a copy of the mso properties cache.
+ * The objects returned can therefore be modified.
+ *
+ * @return A List of copies of the mso properties, can be empty
+ */
+ public List <AbstractMsoProperties> getAllMsoProperties () {
+
+ List <AbstractMsoProperties> resultList = new LinkedList <AbstractMsoProperties> ();
+ rwl.readLock ().lock ();
+ try {
+
+ for (MsoPropertiesParameters msoProp:MsoPropertiesFactory.msoPropertiesCache.values ()) {
+ resultList.add(msoProp.msoProperties.clone());
+ }
+ return resultList;
+
+ } finally {
+ rwl.readLock ().unlock ();
+ }
+
+ }
+
+ /**
+ * This method is not intended to be called, it's used to refresh the config automatically
+ *
+ * @return true if Properties have been reloaded, false otherwise
+ */
+ @Schedule(minute = "*/1", hour = "*", persistent = false)
+ public boolean reloadMsoProperties () {
+ AbstractMsoProperties msoPropInCache = null;
+ try {
+ if (!rwl.writeLock ().tryLock () && !rwl.writeLock ().tryLock (30L, TimeUnit.SECONDS)) {
+ LOGGER.debug ("Busy write lock on mso properties factory, skipping the reloading");
+ return false;
+ }
+ } catch (InterruptedException e1) {
+ LOGGER.debug ("Interrupted while trying to acquire write lock on mso properties factory, skipping the reloading");
+ Thread.currentThread ().interrupt ();
+ return false;
+ }
+ try {
+ for (Entry <String, MsoPropertiesParameters> entryMsoPropTimer : MsoPropertiesFactory.msoPropertiesCache.entrySet ()) {
+
+ if (entryMsoPropTimer.getValue ().refreshCounter <= 1) {
+ // It's time to reload the config
+ msoPropInCache = MsoPropertiesFactory.msoPropertiesCache.get (entryMsoPropTimer.getKey ()).msoProperties;
+ try {
+ AbstractMsoProperties oldProps = msoPropInCache.clone ();
+ msoPropInCache.reloadPropertiesFile ();
+ entryMsoPropTimer.getValue().refreshCounter=entryMsoPropTimer.getValue().msoProperties.getAutomaticRefreshInMinutes();
+
+ if (!msoPropInCache.equals (oldProps)) {
+ LOGGER.info (MessageEnum.LOAD_PROPERTIES_SUC, msoPropInCache.getPropertiesFileName (), "", "");
+ }
+ } catch (FileNotFoundException ef) {
+ LOGGER.error (MessageEnum.NO_PROPERTIES, msoPropInCache.propertiesFileName, "", "", MsoLogger.ErrorCode.PermissionError, "", ef);
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, msoPropInCache.propertiesFileName, "", "", MsoLogger.ErrorCode.BusinessProcesssError, "", e);
+ }
+
+ } else {
+ --entryMsoPropTimer.getValue().refreshCounter;
+ }
+ }
+ return true;
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.LOAD_PROPERTIES_FAIL, "Unknown. Global issue while reloading", "", "", MsoLogger.ErrorCode.BusinessProcesssError, "", e);
+ return false;
+ } finally {
+ rwl.writeLock ().unlock ();
+ }
+ }
+
+ /**
+ * This method can be used to known if the MSO properties instance hold is different from the one in cache
+ *
+ * @param msoPropertiesID The MSO properties ID
+ * @param oldMsoProperties The MSO Properties instance that must be compared to
+ * @return True if they are the same, false otherwise
+ * @throws MsoPropertiesException
+ */
+ public boolean propertiesHaveChanged (String msoPropertiesID, AbstractMsoProperties oldMsoProperties) throws MsoPropertiesException {
+ rwl.readLock ().lock ();
+ try {
+ if (MsoPropertiesFactory.msoPropertiesCache.get (msoPropertiesID) == null) {
+ throw new MsoPropertiesException ("Mso properties not found in cache:" + msoPropertiesID);
+ }
+
+ AbstractMsoProperties msoPropInCache = MsoPropertiesFactory.msoPropertiesCache.get (msoPropertiesID).msoProperties;
+ if (oldMsoProperties != null) {
+ return !oldMsoProperties.equals (msoPropInCache);
+ } else {
+ return msoPropInCache != null;
+ }
+ } finally {
+ rwl.readLock ().unlock ();
+ }
+ }
+
+ @GET
+ @Path("/show")
+ @Produces("text/plain")
+ public Response showProperties () {
+
+ List <AbstractMsoProperties> listMsoProp = this.getAllMsoProperties ();
+ StringBuffer response = new StringBuffer ();
+
+ if (listMsoProp.isEmpty ()) {
+ response.append ("No file defined");
+ }
+
+ for (AbstractMsoProperties properties : listMsoProp) {
+
+ response.append(properties.toString());
+ }
+
+ return Response.status (200).entity (response).build ();
+ }
+
+ @GET
+ @Path("/encrypt/{value}/{cryptKey}")
+ @Produces("text/plain")
+ public Response encryptProperty (@PathParam("value") String value, @PathParam("cryptKey") String cryptKey) {
+ try {
+ String encryptedValue = CryptoUtils.encrypt (value, cryptKey);
+ return Response.status (200).entity (encryptedValue).build ();
+ } catch (Exception e) {
+ LOGGER.error (MessageEnum.GENERAL_EXCEPTION_ARG, "Encryption error", "", "", MsoLogger.ErrorCode.BusinessProcesssError, "Error in encrypting property", e);
+ return Response.status (500).entity (e.getMessage ()).build ();
+ }
+ }
+}