2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2016-2018 Ericsson. All rights reserved.
4 * Modification Copyright (C) 2019-2020 Nordix Foundation.
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.apex.service.engine.main;
24 import java.util.Arrays;
25 import java.util.Base64;
26 import java.util.LinkedHashMap;
27 import java.util.List;
29 import java.util.Map.Entry;
30 import java.util.TreeMap;
33 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
34 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
35 import org.onap.policy.apex.model.basicmodel.service.ModelService;
36 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbum;
37 import org.onap.policy.apex.model.contextmodel.concepts.AxContextAlbums;
38 import org.onap.policy.apex.model.enginemodel.concepts.AxEngineModel;
39 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
40 import org.onap.policy.apex.service.parameters.ApexParameterHandler;
41 import org.onap.policy.apex.service.parameters.ApexParameters;
42 import org.onap.policy.apex.service.parameters.eventhandler.EventHandlerParameters;
43 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
44 import org.slf4j.ext.XLogger;
45 import org.slf4j.ext.XLoggerFactory;
48 * This class initiates Apex as a complete service from the command line.
50 * @author Liam Fallon (liam.fallon@ericsson.com)
52 public class ApexMain {
53 private static final String APEX_SERVICE_FAILED_MSG = "start of Apex service failed";
55 private static final XLogger LOGGER = XLoggerFactory.getXLogger(ApexMain.class);
57 // The Apex Activator that activates the Apex engine
58 private ApexActivator activator;
60 // The parameters read in from JSON for each policy
62 private Map<ToscaPolicyIdentifier, ApexParameters> apexParametersMap;
65 @Setter(lombok.AccessLevel.PRIVATE)
66 private volatile boolean alive = false;
69 * Instantiates the Apex service.
71 * @param args the command line arguments
73 public ApexMain(final String[] args) {
74 LOGGER.entry("Starting Apex service with parameters " + Arrays.toString(args) + " . . .");
75 apexParametersMap = new LinkedHashMap<>();
77 apexParametersMap.put(new ToscaPolicyIdentifier(), populateApexParameters(args));
78 } catch (ApexException e) {
79 LOGGER.error(APEX_SERVICE_FAILED_MSG, e);
83 // Now, create the activator for the Apex service
84 activator = new ApexActivator(apexParametersMap);
86 // Start the activator
88 activator.initialize();
90 } catch (final ApexActivatorException e) {
91 LOGGER.error("start of Apex service failed, used parameters are " + Arrays.toString(args), e);
95 // Add a shutdown hook to shut everything down in an orderly manner
96 Runtime.getRuntime().addShutdownHook(new ApexMainShutdownHookClass());
97 LOGGER.exit("Started Apex");
101 * Instantiates the Apex service for multiple policies.
103 * @param policyArgumentsMap the map with command line arguments as value and policy-id as key
104 * @throws ApexException on errors
106 public ApexMain(Map<ToscaPolicyIdentifier, String[]> policyArgumentsMap) throws ApexException {
107 apexParametersMap = new LinkedHashMap<>();
108 for (Entry<ToscaPolicyIdentifier, String[]> policyArgsEntry: policyArgumentsMap.entrySet()) {
110 apexParametersMap.put(policyArgsEntry.getKey(), populateApexParameters(policyArgsEntry.getValue()));
111 } catch (ApexException e) {
112 LOGGER.error("Invalid arguments specified for policy - " + policyArgsEntry.getKey().getName() + ":"
113 + policyArgsEntry.getKey().getVersion(), e);
116 if (apexParametersMap.isEmpty()) {
117 LOGGER.error(APEX_SERVICE_FAILED_MSG);
120 // Now, create the activator for the Apex service
121 activator = new ApexActivator(apexParametersMap);
123 // Start the activator
125 activator.initialize();
126 apexParametersMap = activator.getApexParametersMap();
128 } catch (final ApexActivatorException e) {
129 LOGGER.error(APEX_SERVICE_FAILED_MSG, e);
130 activator.terminate();
134 // Add a shutdown hook to shut everything down in an orderly manner
135 Runtime.getRuntime().addShutdownHook(new ApexMainShutdownHookClass());
136 LOGGER.exit("Started Apex");
140 * Updates the APEX Engine with the model created from new Policies.
142 * @param policyArgsMap the map with command line arguments as value and policy-id as key
143 * @throws ApexException on errors
145 public void updateModel(Map<ToscaPolicyIdentifier, String[]> policyArgsMap) throws ApexException {
146 apexParametersMap.clear();
147 AxContextAlbums albums = ModelService.getModel(AxContextAlbums.class);
148 Map<AxArtifactKey, AxContextAlbum> albumsMap = new TreeMap<>();
149 for (Entry<ToscaPolicyIdentifier, String[]> policyArgsEntry : policyArgsMap.entrySet()) {
150 findAlbumsToHold(albumsMap, policyArgsEntry.getKey());
152 apexParametersMap.put(policyArgsEntry.getKey(), populateApexParameters(policyArgsEntry.getValue()));
153 } catch (ApexException e) {
154 LOGGER.error("Invalid arguments specified for policy - {}:{}", policyArgsEntry.getKey().getName(),
155 policyArgsEntry.getKey().getVersion(), e);
159 if (albumsMap.isEmpty()) {
160 // clear context since none of the policies' context albums has to be retained
161 // this could be because all policies have a major version change,
162 // or a full set of new policies are received in the update message
163 activator.terminate();
164 // ParameterService is cleared when activator is terminated. Register the engine parameters in this case
165 new ApexParameterHandler().registerParameters(apexParametersMap.values().iterator().next());
166 activator = new ApexActivator(apexParametersMap);
167 activator.initialize();
170 albums.setAlbumsMap(albumsMap);
171 activator.setApexParametersMap(apexParametersMap);
172 activator.updateModel(apexParametersMap);
174 } catch (final ApexException e) {
175 LOGGER.error(APEX_SERVICE_FAILED_MSG, e);
176 activator.terminate();
177 throw new ApexException(e.getMessage());
182 * Find the context albums which should be retained when updating the policies.
184 * @param albumsMap the albums which should be kept during model update
185 * @param policyId the policy id of current policy
187 private void findAlbumsToHold(Map<AxArtifactKey, AxContextAlbum> albumsMap, ToscaPolicyIdentifier policyId) {
188 for (Entry<ToscaPolicyIdentifier, AxPolicyModel> policyModelsEntry : activator.getPolicyModelsMap()
190 // If a policy with the same major version is received in PDP_UPDATE,
191 // context for that policy has to be retained. For this, take such policies' albums
192 if (policyModelsEntry.getKey().getName().equals(policyId.getName())
193 && policyModelsEntry.getKey().getVersion().split("\\.")[0]
194 .equals(policyId.getVersion().split("\\.")[0])) {
195 albumsMap.putAll(policyModelsEntry.getValue().getAlbums().getAlbumsMap());
200 private ApexParameters populateApexParameters(String[] args) throws ApexException {
201 // Check the arguments
202 final ApexCommandLineArguments arguments = new ApexCommandLineArguments();
204 // The arguments return a string if there is a message to print and we should exit
205 final String argumentMessage = arguments.parse(args);
206 if (argumentMessage != null) {
207 LOGGER.info(argumentMessage);
208 throw new ApexException(argumentMessage);
211 // Validate that the arguments are sane
212 arguments.validate();
213 } catch (final ApexException e) {
214 LOGGER.error("Arguments validation failed.", e);
215 throw new ApexException("Arguments validation failed.", e);
218 ApexParameters axParameters;
219 // Read the parameters
221 ApexParameterHandler apexParameterHandler = new ApexParameterHandler();
222 // In case of multiple policies received from PAP, do not clear ParameterService if parameters of one policy
223 // already registered
224 apexParameterHandler.setKeepParameterServiceFlag(null != apexParametersMap && !apexParametersMap.isEmpty());
225 axParameters = apexParameterHandler.getParameters(arguments);
226 } catch (final Exception e) {
227 LOGGER.error("Cannot create APEX Parameters from the arguments provided.", e);
228 throw new ApexException("Cannot create APEX Parameters from the arguments provided.", e);
231 // Set incoming Java properties
232 setJavaProperties(axParameters);
234 // Set the name of the event handler parameters for producers and consumers
235 for (final Entry<String, EventHandlerParameters> ehParameterEntry : axParameters.getEventOutputParameters()
237 if (!ehParameterEntry.getValue().checkSetName()) {
238 ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
241 for (final Entry<String, EventHandlerParameters> ehParameterEntry : axParameters.getEventInputParameters()
243 if (!ehParameterEntry.getValue().checkSetName()) {
244 ehParameterEntry.getValue().setName(ehParameterEntry.getKey());
251 * Shut down Execution.
253 * @throws ApexException on shutdown errors
255 public void shutdown() throws ApexException {
256 if (activator != null) {
257 activator.terminate();
263 * Get the Engine Stats.
265 public List<AxEngineModel> getEngineStats() {
266 List<AxEngineModel> engineStats = null;
267 if (activator != null) {
268 engineStats = activator.getEngineStats();
274 * The Class ApexMainShutdownHookClass terminates the Apex engine for the Apex service when its run
277 private class ApexMainShutdownHookClass extends Thread {
284 // Shutdown the Apex engine and wait for everything to stop
285 activator.terminate();
287 } catch (final ApexException e) {
288 LOGGER.warn("error occured during shut down of the Apex service", e);
294 * Set the Java properties specified in the parameters.
296 * @param parameters The incoming parameters
298 private void setJavaProperties(final ApexParameters parameters) {
299 if (!parameters.checkJavaPropertiesSet()) {
303 // Set each Java property
304 for (String[] javaProperty : parameters.getJavaProperties()) {
305 String javaPropertyName = javaProperty[0];
306 String javaPropertyValue = javaProperty[1];
308 // Passwords are encoded using base64, better than sending passwords in the clear
309 if (javaPropertyName.toLowerCase().contains("password")) {
310 javaPropertyValue = new String(Base64.getDecoder().decode(javaPropertyValue.getBytes()));
313 // Set the Java property
314 System.setProperty(javaPropertyName, javaPropertyValue);
321 * @param args the arguments
323 public static void main(final String[] args) {