785d7591290406dec2ceaf8196bd61a43003611d
[policy/xacml-pdp.git] / main / src / main / java / org / onap / policy / pdpx / main / rest / XacmlPdpApplicationManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
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  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdpx.main.rest;
22
23 import java.io.IOException;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.ServiceLoader;
32 import java.util.stream.Collectors;
33 import org.onap.policy.models.decisions.concepts.DecisionRequest;
34 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
35 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier;
36 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyTypeIdentifier;
37 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationException;
38 import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 public class XacmlPdpApplicationManager {
43     private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpApplicationManager.class);
44
45     private static boolean needsInit = true;
46     private static ServiceLoader<XacmlApplicationServiceProvider> applicationLoader;
47     private static Map<String, XacmlApplicationServiceProvider> providerActionMap = new HashMap<>();
48     private static List<ToscaPolicyTypeIdentifier> toscaPolicyTypeIdents = new ArrayList<>();
49     private static List<ToscaPolicyIdentifier> toscaPolicyIdents = new ArrayList<>();
50     private static List<ToscaPolicy> toscaPolicies = new ArrayList<>();
51     private static Map<ToscaPolicy, XacmlApplicationServiceProvider> mapLoadedPolicies = new HashMap<>();
52
53
54     private XacmlPdpApplicationManager() {
55         super();
56     }
57
58     /**
59      * One time to initialize the applications upon startup.
60      */
61     public static void initializeApplications(Path applicationPath) {
62         //
63         // If we have already done this
64         //
65         if (! needsInit) {
66             LOGGER.error("Already initialized the applications");
67             return;
68         }
69         //
70         // Load service
71         //
72         applicationLoader = ServiceLoader.load(XacmlApplicationServiceProvider.class);
73         //
74         // Iterate through the applications for actions and supported policy types
75         //
76         for (XacmlApplicationServiceProvider application : applicationLoader) {
77             LOGGER.info("Application {} supports {}", application.applicationName(),
78                     application.supportedPolicyTypes());
79             //
80             // We are not going to make this available unless the application can
81             // install correctly.
82             //
83             boolean applicationInitialized = false;
84             //
85             // Have it initialize at a path
86             //
87             try {
88                 initializeApplicationPath(applicationPath, application);
89                 //
90                 // We are initialized
91                 //
92                 applicationInitialized = true;
93             } catch (XacmlApplicationException e) {
94                 LOGGER.error("Failed to initialize path for {}", application.applicationName(), e);
95             }
96             if (applicationInitialized) {
97                 //
98                 // Iterate through the actions and save in the providerActionMap
99                 //
100                 for (String action : application.actionDecisionsSupported()) {
101                     //
102                     // Save the actions that it supports
103                     //
104                     providerActionMap.put(action, application);
105                 }
106                 //
107                 // Add all the supported policy types
108                 //
109                 toscaPolicyTypeIdents.addAll(application.supportedPolicyTypes());
110             }
111         }
112         //
113         // we have initialized
114         //
115         needsInit = false;
116     }
117
118     public static XacmlApplicationServiceProvider findApplication(DecisionRequest request) {
119         return providerActionMap.get(request.getAction());
120     }
121
122     /**
123      * getToscaPolicies.
124      *
125      * @return the map containing ToscaPolicies
126      */
127     public static Map<ToscaPolicy, XacmlApplicationServiceProvider> getToscaPolicies() {
128         return mapLoadedPolicies;
129     }
130
131     /**
132      * getToscaPolicyIdentifiers.
133      *
134      * @return list of ToscaPolicyIdentifier
135      */
136     public static List<ToscaPolicyIdentifier> getToscaPolicyIdentifiers() {
137         //
138         // converting map to return List of ToscaPolicyIdentiers
139         //
140         return mapLoadedPolicies.keySet().stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList());
141     }
142
143     public static List<ToscaPolicyTypeIdentifier> getToscaPolicyTypeIdents() {
144         return toscaPolicyTypeIdents;
145     }
146
147     /**
148      * Finds the appropriate application and removes the policy.
149      *
150      * @param policy Incoming policy
151      */
152     public static void removeUndeployedPolicy(ToscaPolicy policy) {
153
154         for (XacmlApplicationServiceProvider application : applicationLoader) {
155             try {
156                 if (application.unloadPolicy(policy)) {
157                     LOGGER.info("Unloaded ToscaPolicy {} from application {}", policy.getMetadata(),
158                             application.applicationName());
159                     if (mapLoadedPolicies.remove(policy) == null) {
160                         LOGGER.error("Failed to remove unloaded policy {} from map size {}", policy.getMetadata(),
161                                 mapLoadedPolicies.size());
162                     }
163                 }
164             } catch (XacmlApplicationException e) {
165                 LOGGER.error("Failed to undeploy the Tosca Policy", e);
166             }
167         }
168     }
169
170     /**
171      * Finds the appropriate application and loads the policy.
172      *
173      * @param policy Incoming policy
174      */
175     public static void loadDeployedPolicy(ToscaPolicy policy) {
176
177         for (XacmlApplicationServiceProvider application : applicationLoader) {
178             try {
179                 //
180                 // There should be only one application per policytype. We can
181                 // put more logic surrounding enforcement of that later. For now,
182                 // just use the first one found.
183                 //
184                 if (application.canSupportPolicyType(policy.getTypeIdentifier())) {
185                     if (application.loadPolicy(policy)) {
186                         LOGGER.info("Loaded ToscaPolicy {} into application {}", policy.getMetadata(),
187                                 application.applicationName());
188                         mapLoadedPolicies.put(policy, application);
189                     }
190                     return;
191                 }
192             } catch (XacmlApplicationException e) {
193                 LOGGER.error("Failed to load the Tosca Policy", e);
194             }
195         }
196     }
197
198     /**
199      * Returns the current count of policy types supported. This could be misleading a bit
200      * as some applications can support wildcard of policy types. Eg. onap.Monitoring.* as
201      * well as individual types/versions. Nevertheless useful for debugging and testing.
202      *
203      * @return Total count added from all applications
204      */
205     public static long getPolicyTypeCount() {
206         long types = 0;
207         for (XacmlApplicationServiceProvider application : applicationLoader) {
208             types += application.supportedPolicyTypes().size();
209         }
210         return types;
211     }
212
213     private static void initializeApplicationPath(Path basePath, XacmlApplicationServiceProvider application)
214             throws XacmlApplicationException {
215         //
216         // Making an assumption that all application names are unique, and
217         // they can result in a valid directory being created.
218         //
219         Path path = Paths.get(basePath.toAbsolutePath().toString(), application.applicationName());
220         LOGGER.info("initializeApplicationPath {} at this path {}", application.applicationName(), path);
221         //
222         // Create that the directory if it does not exist. Ideally
223         // this is only for testing, but could be used for production
224         // Probably better to have the docker container and/or helm
225         // scripts setup the local directory.
226         //
227         if (! path.toFile().exists()) {
228             try {
229                 //
230                 // Try to create the directory
231                 //
232                 Files.createDirectory(path);
233             } catch (IOException e) {
234                 LOGGER.error("Failed to create application directory", e);
235             }
236         }
237         //
238         // Have the application initialize
239         //
240         application.initialize(path);
241     }
242
243 }