ec2d93f35b4f2572e47fa083be2c16c48f34ae50
[sdc.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2019 Nordix Foundation
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.openecomp.core.factory.impl;
21
22 import com.amdocs.zusammen.utils.facade.impl.FactoryConfig;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25 import org.apache.commons.lang3.StringUtils;
26 import org.openecomp.core.utilities.CommonMethods;
27 import org.openecomp.sdc.common.errors.CoreException;
28 import org.openecomp.sdc.common.errors.ErrorCategory;
29 import org.openecomp.sdc.common.errors.ErrorCode;
30
31 public class FactoryManager {
32
33     private static final FactoryManager instance = new FactoryManager();
34     private static final String ERROR_CODE_E0001 = "E0001";
35     /**
36      * Temporary registry of default implementations. The map keeps class names rather then class
37      * types to allow unloading of those classes from memory by garbage collector if factory is not
38      * actually used.
39      */
40     private final Map<String, String> factoryRegistry = new ConcurrentHashMap<>();
41     /**
42      * Cached factory instances.
43      */
44     private final Map<String, AbstractFactoryBase> factoryInstanceMap = new ConcurrentHashMap<>();
45
46
47     private FactoryManager() {
48         initializeFactoryRegistry();
49     }
50
51     public static synchronized FactoryManager getInstance() {
52         return instance;
53     }
54
55     private void initializeFactoryRegistry() {
56         final Map<String, String> factoryMap = FactoryConfig.getFactoriesMap();
57
58         for (final Map.Entry<String, String> entry : factoryMap.entrySet()) {
59             final String abstractClassName = entry.getKey();
60             final String concreteTypeName = entry.getValue();
61
62             if (StringUtils.isEmpty(concreteTypeName)) {
63                 throw new CoreException(
64                     new ErrorCode.ErrorCodeBuilder().withId("E0003")
65                         .withMessage("Missing configuration value:" + concreteTypeName + ".")
66                         .withCategory(ErrorCategory.SYSTEM).build());
67
68             }
69             registerFactory(abstractClassName, concreteTypeName);
70         }
71     }
72
73     /**
74      * Instantiates the configured implementation of an abstract factory.
75      *
76      * @param <F>         Type specific abstract factory for concrete Java interface
77      * @param factoryType Java class of type specific abstract factory
78      * @return Instance of implementation class
79      */
80     @SuppressWarnings("unchecked")
81     public <F extends AbstractFactoryBase> F getFactoryInstance(Class<F> factoryType) {
82         if (factoryType == null) {
83             throw new CoreException(
84                 new ErrorCode.ErrorCodeBuilder().withId(ERROR_CODE_E0001)
85                     .withMessage("Mandatory input factory type.").withCategory(ErrorCategory.SYSTEM)
86                     .build());
87
88         }
89         final String factoryTypeName = factoryType.getName();
90         // Check if the factory is already cached
91         if (factoryInstanceMap.get(factoryTypeName) == null) {
92             //if not, create a new one and cache it
93             // Get the implementation class name
94             final String implName = factoryRegistry.get(factoryTypeName);
95
96             if (StringUtils.isEmpty(implName)) {
97                 throw new CoreException(
98                     new ErrorCode.ErrorCodeBuilder().withId(ERROR_CODE_E0001)
99                         .withMessage("Mandatory input factory implementation.")
100                         .withCategory(ErrorCategory.SYSTEM).build());
101             }
102
103             F factory = CommonMethods.newInstance(implName, factoryType);
104             factory.init();
105             // Cache the instantiated singleton
106             factoryInstanceMap.putIfAbsent(factoryTypeName, factory);
107         }
108
109         return (F) factoryInstanceMap.get(factoryTypeName);
110     }
111
112     public void registerFactory(final String factoryName, final String implName) {
113         factoryRegistry.put(factoryName, implName);
114     }
115
116     /**
117      * Unregister factory and removes the cached instance if any.
118      * @param factoryName the factory name to unregister
119      */
120     public void unregisterFactory(final String factoryName) {
121         final String factoryClass = factoryRegistry.get(factoryName);
122         if (StringUtils.isNotEmpty(factoryClass)) {
123             factoryInstanceMap.remove(factoryClass);
124             factoryRegistry.remove(factoryName);
125         }
126     }
127
128     /**
129      * Removes the cached factory instance if any.
130      *
131      * @param <F>     the type parameter
132      * @param factory the factory
133      */
134     public <F extends AbstractFactoryBase> void removeFactoryInstance(Class<F> factory) {
135         if (factory == null) {
136             throw new CoreException(
137                 new ErrorCode.ErrorCodeBuilder().withId(ERROR_CODE_E0001).withMessage("Mandatory input factory.")
138                     .withCategory(ErrorCategory.SYSTEM).build());
139         }
140
141         factoryInstanceMap.remove(factory.getName());
142     }
143
144     /**
145      * Stop all.
146      */
147     public void stopAll() {
148         factoryInstanceMap.values().forEach(AbstractFactoryBase::stop);
149     }
150 }